diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index a823829419..4e7a8d7618 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,9 +1,8 @@ FROM mcr.microsoft.com/vscode/devcontainers/rust:1-bullseye -# Install cmake and protobuf-compiler +# Install cmake RUN apt-get update \ && apt-get install -y cmake \ - && apt-get install -y protobuf-compiler \ && rm -rf /var/lib/apt/lists/* # Install Deno diff --git a/.dlint.json b/.dlint.json index d25defffb1..f84d2b233c 100644 --- a/.dlint.json +++ b/.dlint.json @@ -4,6 +4,7 @@ "include": [ "ban-untagged-todo", "camelcase", + "no-console", "guard-for-in" ], "exclude": [ diff --git a/.dprint.json b/.dprint.json index 6ee255d536..7877f17647 100644 --- a/.dprint.json +++ b/.dprint.json @@ -39,10 +39,14 @@ "tests/node_compat/runner/TODO.md", "tests/node_compat/test", "tests/registry/", + "tests/specs/bench/default_ts", "tests/specs/fmt", "tests/specs/lint/bom", + "tests/specs/lint/default_ts", "tests/specs/lint/syntax_error_reporting", "tests/specs/publish/no_check_surfaces_syntax_error", + "tests/specs/run/default_ts", + "tests/specs/test/default_ts", "tests/testdata/byte_order_mark.ts", "tests/testdata/encoding", "tests/testdata/file_extensions/ts_with_js_extension.js", @@ -56,7 +60,6 @@ "tests/testdata/run/byte_order_mark.ts", "tests/testdata/run/error_syntax_empty_trailing_line.mjs", "tests/testdata/run/inline_js_source_map*", - "tests/testdata/test/glob/", "tests/testdata/test/markdown_windows.md", "tests/util/std", "tests/wpt/runner/expectation.json", @@ -65,11 +68,11 @@ "third_party" ], "plugins": [ - "https://plugins.dprint.dev/typescript-0.91.6.wasm", - "https://plugins.dprint.dev/json-0.19.3.wasm", - "https://plugins.dprint.dev/markdown-0.17.5.wasm", - "https://plugins.dprint.dev/toml-0.6.2.wasm", + "https://plugins.dprint.dev/typescript-0.93.0.wasm", + "https://plugins.dprint.dev/json-0.19.4.wasm", + "https://plugins.dprint.dev/markdown-0.17.8.wasm", + "https://plugins.dprint.dev/toml-0.6.3.wasm", "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0", - "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.4.0.wasm" + "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm" ] } diff --git a/.github/workflows/cargo_publish.yml b/.github/workflows/cargo_publish.yml index 45f075b579..f285b78919 100644 --- a/.github/workflows/cargo_publish.yml +++ b/.github/workflows/cargo_publish.yml @@ -2,6 +2,11 @@ name: cargo_publish on: workflow_dispatch +# Ensures only one publish is running at a time +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + jobs: build: name: cargo publish @@ -28,16 +33,10 @@ jobs: - uses: dsherret/rust-toolchain-file@v1 - name: Install deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: v1.x - - name: Install protoc - uses: arduino/setup-protoc@v3 - with: - version: '21.12' - repo-token: '${{ secrets.GITHUB_TOKEN }}' - - name: Publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/ci.generate.ts b/.github/workflows/ci.generate.ts index 7e66d9997d..3e2b079643 100755 --- a/.github/workflows/ci.generate.ts +++ b/.github/workflows/ci.generate.ts @@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify"; // Bump this number when you want to purge the cache. // Note: the tools/release/01_bump_crate_versions.ts script will update this version // automatically via regex, so ensure that this line maintains this format. -const cacheVersion = 11; +const cacheVersion = 22; const ubuntuX86Runner = "ubuntu-22.04"; const ubuntuX86XlRunner = "ubuntu-22.04-xl"; @@ -191,14 +191,9 @@ const installNodeStep = { uses: "actions/setup-node@v4", with: { "node-version": 18 }, }; -const installProtocStep = { - name: "Install protoc", - uses: "arduino/setup-protoc@v3", - with: { "version": "21.12", "repo-token": "${{ secrets.GITHUB_TOKEN }}" }, -}; const installDenoStep = { name: "Install Deno", - uses: "denoland/setup-deno@v1", + uses: "denoland/setup-deno@v2", with: { "deno-version": "v1.x" }, }; @@ -354,7 +349,7 @@ const ci = { needs: ["pre_build"], if: "${{ needs.pre_build.outputs.skip_build != 'true' }}", "runs-on": "${{ matrix.runner }}", - "timeout-minutes": 150, + "timeout-minutes": 180, defaults: { run: { // GH actions does not fail fast by default on @@ -494,7 +489,6 @@ const ci = { if: "matrix.job == 'bench' || matrix.job == 'test'", ...installNodeStep, }, - installProtocStep, { if: [ "matrix.profile == 'release' &&", @@ -649,7 +643,7 @@ const ci = { name: "test_format.js", if: "matrix.job == 'lint' && matrix.os == 'linux'", run: - "deno run --unstable --allow-write --allow-read --allow-run --allow-net ./tools/format.js --check", + "deno run --allow-write --allow-read --allow-run --allow-net ./tools/format.js --check", }, { name: "Lint PR title", @@ -664,7 +658,7 @@ const ci = { name: "lint.js", if: "matrix.job == 'lint'", run: - "deno run --unstable --allow-write --allow-read --allow-run --allow-net ./tools/lint.js", + "deno run --allow-write --allow-read --allow-run --allow-net ./tools/lint.js", }, { name: "jsdoc_checker.js", @@ -758,8 +752,10 @@ const ci = { run: [ "cd target/release", "zip -r deno-${{ matrix.arch }}-unknown-linux-gnu.zip deno", + "shasum -a 256 deno-${{ matrix.arch }}-unknown-linux-gnu.zip > deno-${{ matrix.arch }}-unknown-linux-gnu.zip.sha256sum", "strip denort", "zip -r denort-${{ matrix.arch }}-unknown-linux-gnu.zip denort", + "shasum -a 256 denort-${{ matrix.arch }}-unknown-linux-gnu.zip > denort-${{ matrix.arch }}-unknown-linux-gnu.zip.sha256sum", "./deno types > lib.deno.d.ts", ].join("\n"), }, @@ -784,8 +780,10 @@ const ci = { "--entitlements-xml-file=cli/entitlements.plist", "cd target/release", "zip -r deno-${{ matrix.arch }}-apple-darwin.zip deno", + "shasum -a 256 deno-${{ matrix.arch }}-apple-darwin.zip > deno-${{ matrix.arch }}-apple-darwin.zip.sha256sum", "strip denort", "zip -r denort-${{ matrix.arch }}-apple-darwin.zip denort", + "shasum -a 256 denort-${{ matrix.arch }}-apple-darwin.zip > denort-${{ matrix.arch }}-apple-darwin.zip.sha256sum", ] .join("\n"), }, @@ -800,7 +798,9 @@ const ci = { shell: "pwsh", run: [ "Compress-Archive -CompressionLevel Optimal -Force -Path target/release/deno.exe -DestinationPath target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip", + "Get-FileHash target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip -Algorithm SHA256 | Format-List > target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip.sha256sum", "Compress-Archive -CompressionLevel Optimal -Force -Path target/release/denort.exe -DestinationPath target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip", + "Get-FileHash target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip -Algorithm SHA256 | Format-List > target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip.sha256sum", ].join("\n"), }, { @@ -813,6 +813,7 @@ const ci = { ].join("\n"), run: [ 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/canary/$(git rev-parse HEAD)/', + 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/canary/$(git rev-parse HEAD)/', "echo ${{ github.sha }} > canary-latest.txt", 'gsutil -h "Cache-Control: no-cache" cp canary-latest.txt gs://dl.deno.land/canary-$(rustc -vV | sed -n "s|host: ||p")-latest.txt', ].join("\n"), @@ -826,7 +827,7 @@ const ci = { "!startsWith(github.ref, 'refs/tags/')", ].join("\n"), run: - "target/release/deno run -A --unstable --config tests/config/deno.json ext/websocket/autobahn/fuzzingclient.js", + "target/release/deno run -A --config tests/config/deno.json ext/websocket/autobahn/fuzzingclient.js", }, { name: "Test (full, debug)", @@ -879,9 +880,9 @@ const ci = { DENO_BIN: "./target/debug/deno", }, run: [ - "deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\\", + "deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\\", " ./tests/wpt/wpt.ts setup", - "deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\\", + "deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\\", ' ./tests/wpt/wpt.ts run --quiet --binary="$DENO_BIN"', ].join("\n"), }, @@ -892,9 +893,9 @@ const ci = { DENO_BIN: "./target/release/deno", }, run: [ - "deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\\", + "deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\\", " ./tests/wpt/wpt.ts setup", - "deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\\", + "deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\\", " ./tests/wpt/wpt.ts run --quiet --release \\", ' --binary="$DENO_BIN" \\', " --json=wpt.json \\", @@ -958,8 +959,7 @@ const ci = { "git clone --depth 1 --branch gh-pages \\", " https://${DENOBOT_PAT}@github.com/denoland/benchmark_data.git \\", " gh-pages", - "./target/release/deno run --allow-all --unstable \\", - " ./tools/build_benchmark_jsons.js --release", + "./target/release/deno run --allow-all ./tools/build_benchmark_jsons.js --release", "cd gh-pages", 'git config user.email "propelml@gmail.com"', 'git config user.name "denobot"', @@ -995,8 +995,10 @@ const ci = { "github.repository == 'denoland/deno' &&", "startsWith(github.ref, 'refs/tags/')", ].join("\n"), - run: + run: [ 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/', + 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/', + ].join("\n"), }, { name: "Upload release to dl.deno.land (windows)", @@ -1010,8 +1012,10 @@ const ci = { env: { CLOUDSDK_PYTHON: "${{env.pythonLocation}}\\python.exe", }, - run: + run: [ 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/', + 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/', + ].join("\n"), }, { name: "Create release notes", @@ -1041,15 +1045,25 @@ const ci = { with: { files: [ "target/release/deno-x86_64-pc-windows-msvc.zip", + "target/release/deno-x86_64-pc-windows-msvc.zip.sha256sum", "target/release/denort-x86_64-pc-windows-msvc.zip", + "target/release/denort-x86_64-pc-windows-msvc.zip.sha256sum", "target/release/deno-x86_64-unknown-linux-gnu.zip", + "target/release/deno-x86_64-unknown-linux-gnu.zip.sha256sum", "target/release/denort-x86_64-unknown-linux-gnu.zip", + "target/release/denort-x86_64-unknown-linux-gnu.zip.sha256sum", "target/release/deno-x86_64-apple-darwin.zip", + "target/release/deno-x86_64-apple-darwin.zip.sha256sum", "target/release/denort-x86_64-apple-darwin.zip", + "target/release/denort-x86_64-apple-darwin.zip.sha256sum", "target/release/deno-aarch64-unknown-linux-gnu.zip", + "target/release/deno-aarch64-unknown-linux-gnu.zip.sha256sum", "target/release/denort-aarch64-unknown-linux-gnu.zip", + "target/release/denort-aarch64-unknown-linux-gnu.zip.sha256sum", "target/release/deno-aarch64-apple-darwin.zip", + "target/release/deno-aarch64-apple-darwin.zip.sha256sum", "target/release/denort-aarch64-apple-darwin.zip", + "target/release/denort-aarch64-apple-darwin.zip.sha256sum", "target/release/deno_src.tar.gz", "target/release/lib.deno.d.ts", ].join("\n"), @@ -1068,6 +1082,7 @@ const ci = { "./target", "!./target/*/gn_out", "!./target/*/*.zip", + "!./target/*/*.sha256sum", "!./target/*/*.tar.gz", ].join("\n"), key: prCacheKeyPrefix + "${{ github.sha }}", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4774a9040..5739537bb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: - pre_build if: '${{ needs.pre_build.outputs.skip_build != ''true'' }}' runs-on: '${{ matrix.runner }}' - timeout-minutes: 150 + timeout-minutes: 180 defaults: run: shell: bash @@ -178,7 +178,7 @@ jobs: if: '!(matrix.skip)' - if: '!(matrix.skip) && (matrix.job == ''lint'' || matrix.job == ''test'' || matrix.job == ''bench'')' name: Install Deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: v1.x - name: Install Python @@ -199,12 +199,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: 18 - - name: Install protoc - uses: arduino/setup-protoc@v3 - with: - version: '21.12' - repo-token: '${{ secrets.GITHUB_TOKEN }}' - if: '!(matrix.skip)' - if: |- !(matrix.skip) && (matrix.profile == 'release' && matrix.job == 'test' && @@ -367,8 +361,8 @@ jobs: path: |- ~/.cargo/registry/index ~/.cargo/registry/cache - key: '11-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}' - restore-keys: '11-cargo-home-${{ matrix.os }}-${{ matrix.arch }}' + key: '22-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}' + restore-keys: '22-cargo-home-${{ matrix.os }}-${{ matrix.arch }}' if: '!(matrix.skip)' - name: Restore cache build output (PR) uses: actions/cache/restore@v4 @@ -381,7 +375,7 @@ jobs: !./target/*/*.zip !./target/*/*.tar.gz key: never_saved - restore-keys: '11-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-' + restore-keys: '22-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-' - name: Apply and update mtime cache if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))' uses: ./.github/mtime_cache @@ -389,7 +383,7 @@ jobs: cache-path: ./target - name: test_format.js if: '!(matrix.skip) && (matrix.job == ''lint'' && matrix.os == ''linux'')' - run: deno run --unstable --allow-write --allow-read --allow-run --allow-net ./tools/format.js --check + run: deno run --allow-write --allow-read --allow-run --allow-net ./tools/format.js --check - name: Lint PR title if: '!(matrix.skip) && (matrix.job == ''lint'' && github.event_name == ''pull_request'' && matrix.os == ''linux'')' env: @@ -397,7 +391,7 @@ jobs: run: deno run ./tools/verify_pr_title.js "$PR_TITLE" - name: lint.js if: '!(matrix.skip) && (matrix.job == ''lint'')' - run: deno run --unstable --allow-write --allow-read --allow-run --allow-net ./tools/lint.js + run: deno run --allow-write --allow-read --allow-run --allow-net ./tools/lint.js - name: jsdoc_checker.js if: '!(matrix.skip) && (matrix.job == ''lint'')' run: deno run --allow-read --allow-env --allow-sys ./tools/jsdoc_checker.js @@ -449,8 +443,10 @@ jobs: run: |- cd target/release zip -r deno-${{ matrix.arch }}-unknown-linux-gnu.zip deno + shasum -a 256 deno-${{ matrix.arch }}-unknown-linux-gnu.zip > deno-${{ matrix.arch }}-unknown-linux-gnu.zip.sha256sum strip denort zip -r denort-${{ matrix.arch }}-unknown-linux-gnu.zip denort + shasum -a 256 denort-${{ matrix.arch }}-unknown-linux-gnu.zip > denort-${{ matrix.arch }}-unknown-linux-gnu.zip.sha256sum ./deno types > lib.deno.d.ts - name: Pre-release (mac) if: |- @@ -466,8 +462,10 @@ jobs: rcodesign sign target/release/deno --code-signature-flags=runtime --p12-password="$APPLE_CODESIGN_PASSWORD" --p12-file=<(echo $APPLE_CODESIGN_KEY | base64 -d) --entitlements-xml-file=cli/entitlements.plist cd target/release zip -r deno-${{ matrix.arch }}-apple-darwin.zip deno + shasum -a 256 deno-${{ matrix.arch }}-apple-darwin.zip > deno-${{ matrix.arch }}-apple-darwin.zip.sha256sum strip denort zip -r denort-${{ matrix.arch }}-apple-darwin.zip denort + shasum -a 256 denort-${{ matrix.arch }}-apple-darwin.zip > denort-${{ matrix.arch }}-apple-darwin.zip.sha256sum - name: Pre-release (windows) if: |- !(matrix.skip) && (matrix.os == 'windows' && @@ -477,7 +475,9 @@ jobs: shell: pwsh run: |- Compress-Archive -CompressionLevel Optimal -Force -Path target/release/deno.exe -DestinationPath target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip + Get-FileHash target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip -Algorithm SHA256 | Format-List > target/release/deno-${{ matrix.arch }}-pc-windows-msvc.zip.sha256sum Compress-Archive -CompressionLevel Optimal -Force -Path target/release/denort.exe -DestinationPath target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip + Get-FileHash target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip -Algorithm SHA256 | Format-List > target/release/denort-${{ matrix.arch }}-pc-windows-msvc.zip.sha256sum - name: Upload canary to dl.deno.land if: |- !(matrix.skip) && (matrix.job == 'test' && @@ -486,6 +486,7 @@ jobs: github.ref == 'refs/heads/main') run: |- gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/canary/$(git rev-parse HEAD)/ + gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/canary/$(git rev-parse HEAD)/ echo ${{ github.sha }} > canary-latest.txt gsutil -h "Cache-Control: no-cache" cp canary-latest.txt gs://dl.deno.land/canary-$(rustc -vV | sed -n "s|host: ||p")-latest.txt - name: Autobahn testsuite @@ -494,7 +495,7 @@ jobs: matrix.job == 'test' && matrix.profile == 'release' && !startsWith(github.ref, 'refs/tags/')) - run: target/release/deno run -A --unstable --config tests/config/deno.json ext/websocket/autobahn/fuzzingclient.js + run: target/release/deno run -A --config tests/config/deno.json ext/websocket/autobahn/fuzzingclient.js - name: 'Test (full, debug)' if: |- !(matrix.skip) && (matrix.job == 'test' && @@ -531,18 +532,18 @@ jobs: env: DENO_BIN: ./target/debug/deno run: |- - deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\ + deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\ ./tests/wpt/wpt.ts setup - deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\ + deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\ ./tests/wpt/wpt.ts run --quiet --binary="$DENO_BIN" - name: Run web platform tests (release) if: '!(matrix.skip) && (matrix.wpt && matrix.profile == ''release'')' env: DENO_BIN: ./target/release/deno run: |- - deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\ + deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\ ./tests/wpt/wpt.ts setup - deno run -A --unstable --lock=tools/deno.lock.json --config tests/config/deno.json\ + deno run -A --lock=tools/deno.lock.json --config tests/config/deno.json\ ./tests/wpt/wpt.ts run --quiet --release \ --binary="$DENO_BIN" \ --json=wpt.json \ @@ -590,8 +591,7 @@ jobs: git clone --depth 1 --branch gh-pages \ https://${DENOBOT_PAT}@github.com/denoland/benchmark_data.git \ gh-pages - ./target/release/deno run --allow-all --unstable \ - ./tools/build_benchmark_jsons.js --release + ./target/release/deno run --allow-all ./tools/build_benchmark_jsons.js --release cd gh-pages git config user.email "propelml@gmail.com" git config user.name "denobot" @@ -616,7 +616,9 @@ jobs: matrix.profile == 'release' && github.repository == 'denoland/deno' && startsWith(github.ref, 'refs/tags/')) - run: 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/' + run: |- + gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/ + gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/ - name: Upload release to dl.deno.land (windows) if: |- !(matrix.skip) && (matrix.os == 'windows' && @@ -626,7 +628,9 @@ jobs: startsWith(github.ref, 'refs/tags/')) env: CLOUDSDK_PYTHON: '${{env.pythonLocation}}\python.exe' - run: 'gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/' + run: |- + gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.zip gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/ + gsutil -h "Cache-Control: public, max-age=3600" cp ./target/release/*.sha256sum gs://dl.deno.land/release/${GITHUB_REF#refs/*/}/ - name: Create release notes if: |- !(matrix.skip) && (matrix.job == 'test' && @@ -648,15 +652,25 @@ jobs: with: files: |- target/release/deno-x86_64-pc-windows-msvc.zip + target/release/deno-x86_64-pc-windows-msvc.zip.sha256sum target/release/denort-x86_64-pc-windows-msvc.zip + target/release/denort-x86_64-pc-windows-msvc.zip.sha256sum target/release/deno-x86_64-unknown-linux-gnu.zip + target/release/deno-x86_64-unknown-linux-gnu.zip.sha256sum target/release/denort-x86_64-unknown-linux-gnu.zip + target/release/denort-x86_64-unknown-linux-gnu.zip.sha256sum target/release/deno-x86_64-apple-darwin.zip + target/release/deno-x86_64-apple-darwin.zip.sha256sum target/release/denort-x86_64-apple-darwin.zip + target/release/denort-x86_64-apple-darwin.zip.sha256sum target/release/deno-aarch64-unknown-linux-gnu.zip + target/release/deno-aarch64-unknown-linux-gnu.zip.sha256sum target/release/denort-aarch64-unknown-linux-gnu.zip + target/release/denort-aarch64-unknown-linux-gnu.zip.sha256sum target/release/deno-aarch64-apple-darwin.zip + target/release/deno-aarch64-apple-darwin.zip.sha256sum target/release/denort-aarch64-apple-darwin.zip + target/release/denort-aarch64-apple-darwin.zip.sha256sum target/release/deno_src.tar.gz target/release/lib.deno.d.ts body_path: target/release/release-notes.md @@ -669,8 +683,9 @@ jobs: ./target !./target/*/gn_out !./target/*/*.zip + !./target/*/*.sha256sum !./target/*/*.tar.gz - key: '11-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' + key: '22-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' publish-canary: name: publish canary runs-on: ubuntu-22.04 diff --git a/.github/workflows/promote_to_rc.yml b/.github/workflows/promote_to_release.yml similarity index 62% rename from .github/workflows/promote_to_rc.yml rename to .github/workflows/promote_to_release.yml index a875743464..79fefa6d6c 100644 --- a/.github/workflows/promote_to_rc.yml +++ b/.github/workflows/promote_to_release.yml @@ -1,15 +1,22 @@ -name: promote_to_rc +name: promote_to_release on: workflow_dispatch: inputs: + releaseKind: + description: 'Kind of release' + type: choice + options: + - rc + - lts + required: true commitHash: - description: Commit to promote to the Release Candidate + description: Commit to promote to release required: true jobs: - promote-to-rc: - name: Promote to Release Candidate + promote-to-release: + name: Promote to Release runs-on: macOS-latest if: github.repository == 'denoland/deno' steps: @@ -33,7 +40,7 @@ jobs: project_id: denoland - name: Install deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: v1.x @@ -42,14 +49,14 @@ jobs: ./tools/install_prebuilt.js rcodesign echo $GITHUB_WORKSPACE/third_party/prebuilt/mac >> $GITHUB_PATH - - name: Promote to RC + - name: Promote to Release env: APPLE_CODESIGN_KEY: '${{ secrets.APPLE_CODESIGN_KEY }}' APPLE_CODESIGN_PASSWORD: '${{ secrets.APPLE_CODESIGN_PASSWORD }}' run: | - deno run -A ./tools/release/promote_to_rc.ts ${{github.event.inputs.commitHash}} + deno run -A ./tools/release/promote_to_release.ts ${{github.event.inputs.releaseKind}} ${{github.event.inputs.commitHash}} - name: Upload archives to dl.deno.land run: | - gsutil -h "Cache-Control: public, max-age=3600" cp ./*.zip gs://dl.deno.land/release/$(cat release-rc-latest.txt)/ - gsutil -h "Cache-Control: no-cache" cp release-rc-latest.txt gs://dl.deno.land/release-rc-latest.txt + gsutil -h "Cache-Control: public, max-age=3600" cp ./*.zip gs://dl.deno.land/release/$(cat release-${{github.event.inputs.releaseKind}}-latest.txt)/ + gsutil -h "Cache-Control: no-cache" cp release-${{github.event.inputs.releaseKind}}-latest.txt gs://dl.deno.land/release-${{github.event.inputs.releaseKind}}-latest.txt diff --git a/.github/workflows/start_release.yml b/.github/workflows/start_release.yml index 392551afbe..7c2f149e11 100644 --- a/.github/workflows/start_release.yml +++ b/.github/workflows/start_release.yml @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@v4 - name: Install deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: v1.x diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 733abbb024..fd082bca3e 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -39,7 +39,7 @@ jobs: - uses: dsherret/rust-toolchain-file@v1 - name: Install deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: v1.x diff --git a/.github/workflows/wpt_epoch.yml b/.github/workflows/wpt_epoch.yml index 166b51c6e7..d679498b83 100644 --- a/.github/workflows/wpt_epoch.yml +++ b/.github/workflows/wpt_epoch.yml @@ -30,7 +30,7 @@ jobs: persist-credentials: false - name: Setup Deno - uses: denoland/setup-deno@v1 + uses: denoland/setup-deno@v2 with: deno-version: ${{ matrix.deno-version }} @@ -66,9 +66,9 @@ jobs: - name: Run web platform tests shell: bash run: | - deno run --unstable -A --lock=tools/deno.lock.json --config=tests/config/deno.json \ + deno run -A --lock=tools/deno.lock.json --config=tests/config/deno.json \ ./tests/wpt/wpt.ts setup - deno run --unstable -A --lock=tools/deno.lock.json --config=tests/config/deno.json \ + deno run -A --lock=tools/deno.lock.json --config=tests/config/deno.json \ ./tests/wpt/wpt.ts run \ \ --binary=$(which deno) --quiet --release --no-ignore --json=wpt.json --wptreport=wptreport.json --exit-zero diff --git a/Cargo.lock b/Cargo.lock index debd091e87..623d028ce6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "aead-gcm-stream" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a09ecb526d53de2842cc876ee5c9b51161ee60399edeca4cf74892a01b48177" +checksum = "4947a169074c7e038fa43051d1c4e073f4488b0e4b0a30658f1e1a1b06449ce8" dependencies = [ "aead", "aes", @@ -128,19 +128,6 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" -[[package]] -name = "ammonia" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170" -dependencies = [ - "html5ever", - "maplit", - "once_cell", - "tendril", - "url", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -152,23 +139,24 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" @@ -453,7 +441,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.10.5", @@ -464,12 +452,32 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn 2.0.72", "which 4.4.2", ] +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease 0.2.17", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.72", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -493,9 +501,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -630,12 +638,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.10" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "066fce287b1d4eafef758e89e09d724a24808a9196fe9756b8ca90e86d0719a2" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -687,23 +696,23 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.3", + "libloading 0.8.5", ] [[package]] name = "clap" -version = "4.5.13" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -714,9 +723,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.12" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8670053e87c316345e384ca1f3eba3006fc6355ed8b8a1140d104e109e3df34" +checksum = "6d7db6eca8c205649e8d3ccd05aa5042b1800a784e56bc7c43524fde8abbfa9b" dependencies = [ "clap", ] @@ -749,8 +758,10 @@ dependencies = [ "deno_core", "deno_fetch", "deno_lockfile", + "deno_semver", "deno_terminal 0.2.0", "deno_tls", + "deno_tower_lsp", "fastwebsockets", "file_test_runner", "flaky_test", @@ -758,7 +769,7 @@ dependencies = [ "http-body-util", "hyper 1.4.1", "hyper-util", - "nix 0.26.2", + "nix", "once_cell", "os_pipe", "pretty_assertions", @@ -767,7 +778,6 @@ dependencies = [ "serde", "test_server", "tokio", - "tower-lsp", "trust-dns-client", "trust-dns-server", "url", @@ -838,9 +848,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comrak" -version = "0.26.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ab67843c57df5a4ee29d610740828dbc928cc64ecf0f2a1d5cd0e98e107a9" +checksum = "c93ab3577cca16b4a1d80a88c2e0cd8b6e969e51696f0bbb0d1dcb0157109832" dependencies = [ "caseless", "derive_builder", @@ -1038,7 +1048,7 @@ dependencies = [ "cpufeatures", "curve25519-dalek-derive", "digest", - "fiat-crypto", + "fiat-crypto 0.2.7", "rustc_version 0.4.0", "subtle", "zeroize", @@ -1061,8 +1071,8 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" dependencies = [ - "bitflags 2.5.0", - "libloading 0.8.3", + "bitflags 2.6.0", + "libloading 0.8.5", "winapi", ] @@ -1111,7 +1121,7 @@ dependencies = [ "hashbrown", "lock_api", "once_cell", - "parking_lot_core 0.9.9", + "parking_lot_core", ] [[package]] @@ -1144,10 +1154,10 @@ dependencies = [ [[package]] name = "deno" -version = "1.46.0-rc.2" +version = "2.0.3" dependencies = [ + "anstream", "async-trait", - "base32", "base64 0.21.7", "bincode", "bytes", @@ -1166,16 +1176,19 @@ dependencies = [ "deno_config", "deno_core", "deno_doc", - "deno_emit", "deno_graph", "deno_lint", "deno_lockfile", "deno_npm", "deno_package_json", + "deno_path_util", + "deno_resolver", "deno_runtime", "deno_semver", "deno_task_shell", "deno_terminal 0.2.0", + "deno_tower_lsp", + "dhat", "dissimilar", "dotenvy", "dprint-plugin-json", @@ -1183,7 +1196,6 @@ dependencies = [ "dprint-plugin-markdown", "dprint-plugin-typescript", "env_logger", - "eszip", "fancy-regex", "faster-hex", "flate2", @@ -1208,8 +1220,7 @@ dependencies = [ "markup_fmt", "memmem", "monch", - "napi_sym", - "nix 0.26.2", + "nix", "node_resolver", "notify", "once_cell", @@ -1217,7 +1228,7 @@ dependencies = [ "p256", "pathdiff", "percent-encoding", - "phf 0.11.2", + "phf", "pretty_assertions", "pretty_yaml", "quick-junit", @@ -1242,7 +1253,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "tower-lsp", + "tracing", "twox-hash", "typed-arena", "uuid", @@ -1256,12 +1267,22 @@ dependencies = [ ] [[package]] -name = "deno_ast" -version = "0.41.2" +name = "deno-tower-lsp-macros" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8207814a257d99164dbf780a73b9dee17af4db983f4b23ffbf20c7340d52f5" +checksum = "05d59a1cfd445fd86f63616127a434aabca000e03d963b01b03ce813520565b9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "deno_ast" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b9d03b1bbeeecdac54367f075d572131736d06c5be3bc49037855bc5ab1bbb" dependencies = [ - "anyhow", "base64 0.21.7", "deno_media_type", "deno_terminal 0.1.1", @@ -1269,6 +1290,7 @@ dependencies = [ "once_cell", "percent-encoding", "serde", + "sourcemap 9.0.0", "swc_atoms", "swc_bundler", "swc_common", @@ -1301,7 +1323,7 @@ dependencies = [ [[package]] name = "deno_bench_util" -version = "0.158.0" +version = "0.168.0" dependencies = [ "bencher", "deno_core", @@ -1310,37 +1332,41 @@ dependencies = [ [[package]] name = "deno_broadcast_channel" -version = "0.158.0" +version = "0.168.0" dependencies = [ "async-trait", "deno_core", + "thiserror", "tokio", "uuid", ] [[package]] name = "deno_cache" -version = "0.96.0" +version = "0.106.0" dependencies = [ "async-trait", "deno_core", "rusqlite", "serde", "sha2", + "thiserror", "tokio", ] [[package]] name = "deno_cache_dir" -version = "0.10.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fa4989e4c6b0409438e2a68a91e4e02858b0d8ba6e5bc6860af6b0d0f385e8" +checksum = "186a102b13b4512841f5f40784cd25822042d22954afe3b5b070d406d15eb4f2" dependencies = [ + "base32", "deno_media_type", + "deno_path_util", "indexmap", "log", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "serde", "serde_json", "sha2", @@ -1350,22 +1376,24 @@ dependencies = [ [[package]] name = "deno_canvas" -version = "0.33.0" +version = "0.43.0" dependencies = [ "deno_core", "deno_webgpu", "image", "serde", + "thiserror", ] [[package]] name = "deno_config" -version = "0.30.0" +version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e287a8ab3552cf3ef8fc41b2bd7cc041c5e8e1a76de3aeb26e804b570bab37d7" +checksum = "5900bfb37538d83b19ba0b157cdc785770e38422ee4632411e3bd3d90ac0f537" dependencies = [ "anyhow", "deno_package_json", + "deno_path_util", "deno_semver", "glob", "ignore", @@ -1374,6 +1402,7 @@ dependencies = [ "jsonc-parser", "log", "percent-encoding", + "phf", "serde", "serde_json", "thiserror", @@ -1382,16 +1411,16 @@ dependencies = [ [[package]] name = "deno_console" -version = "0.164.0" +version = "0.174.0" dependencies = [ "deno_core", ] [[package]] name = "deno_core" -version = "0.304.0" +version = "0.314.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb02f25a743fe58a117ed5cfd47c4e640761926e294a1f4ba964a0e2c68b4dc" +checksum = "83138917579676069b423c3eb9be3c1e579f60dc022d85f6ded4c792456255ff" dependencies = [ "anyhow", "bincode", @@ -1404,15 +1433,15 @@ dependencies = [ "deno_unsync", "futures", "libc", - "memoffset 0.9.1", - "parking_lot 0.12.3", + "memoffset", + "parking_lot", "percent-encoding", "pin-project", "serde", "serde_json", "serde_v8", "smallvec", - "sourcemap", + "sourcemap 8.0.1", "static_assertions", "tokio", "url", @@ -1427,19 +1456,20 @@ checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1" [[package]] name = "deno_cron" -version = "0.44.0" +version = "0.54.0" dependencies = [ "anyhow", "async-trait", "chrono", "deno_core", "saffron", + "thiserror", "tokio", ] [[package]] name = "deno_crypto" -version = "0.178.0" +version = "0.188.0" dependencies = [ "aes", "aes-gcm", @@ -1451,6 +1481,7 @@ dependencies = [ "curve25519-dalek", "deno_core", "deno_web", + "ed448-goldilocks", "elliptic-curve", "num-traits", "once_cell", @@ -1460,23 +1491,25 @@ dependencies = [ "rand", "ring", "rsa", + "sec1", "serde", "serde_bytes", "sha1", "sha2", "signature", "spki", + "thiserror", + "tokio", "uuid", "x25519-dalek", ] [[package]] name = "deno_doc" -version = "0.146.0" +version = "0.154.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48063b68a1646ef64811171b683eb2993e08260b33b2bd987649679945099370" +checksum = "17e204e45b0d79750880114e37b34abe19ad0710d8435a8da8f23a528fe98de4" dependencies = [ - "ammonia", "anyhow", "cfg-if", "comrak", @@ -1496,26 +1529,9 @@ dependencies = [ "termcolor", ] -[[package]] -name = "deno_emit" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a22b37181789a1b04ef823c168a194e821f8f3145d9d9d6b4da4207eba807d" -dependencies = [ - "anyhow", - "base64 0.21.7", - "deno_ast", - "deno_graph", - "escape8259", - "futures", - "import_map", - "parking_lot 0.11.2", - "url", -] - [[package]] name = "deno_fetch" -version = "0.188.0" +version = "0.198.0" dependencies = [ "base64 0.21.7", "bytes", @@ -1536,6 +1552,7 @@ dependencies = [ "rustls-webpki", "serde", "serde_json", + "thiserror", "tokio", "tokio-rustls", "tokio-socks", @@ -1547,7 +1564,7 @@ dependencies = [ [[package]] name = "deno_ffi" -version = "0.151.0" +version = "0.161.0" dependencies = [ "deno_core", "deno_permissions", @@ -1556,37 +1573,42 @@ dependencies = [ "libffi", "libffi-sys", "log", + "num-bigint", "serde", "serde-value", "serde_json", + "thiserror", + "tokio", "winapi", ] [[package]] name = "deno_fs" -version = "0.74.0" +version = "0.84.0" dependencies = [ "async-trait", "base32", "deno_core", "deno_io", + "deno_path_util", "deno_permissions", "filetime", "junction", "libc", - "nix 0.26.2", + "nix", "rand", "rayon", "serde", + "thiserror", "winapi", "windows-sys 0.52.0", ] [[package]] name = "deno_graph" -version = "0.81.2" +version = "0.83.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beccc9d4007be8b85299f696a412f38912fc304cf9519092b47531319ef8a92f" +checksum = "5bd20bc0780071989c622cbfd5d4fb2e4fd05a247ccd7f791f13c8d2c3792228" dependencies = [ "anyhow", "async-trait", @@ -1601,7 +1623,7 @@ dependencies = [ "log", "monch", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "regex", "serde", "serde_json", @@ -1613,7 +1635,7 @@ dependencies = [ [[package]] name = "deno_http" -version = "0.162.0" +version = "0.172.0" dependencies = [ "async-compression", "async-trait", @@ -1638,7 +1660,7 @@ dependencies = [ "mime", "once_cell", "percent-encoding", - "phf 0.11.2", + "phf", "pin-project", "rand", "ring", @@ -1652,7 +1674,7 @@ dependencies = [ [[package]] name = "deno_io" -version = "0.74.0" +version = "0.84.0" dependencies = [ "async-trait", "deno_core", @@ -1662,7 +1684,7 @@ dependencies = [ "log", "once_cell", "os_pipe", - "parking_lot 0.12.3", + "parking_lot", "pin-project", "rand", "tokio", @@ -1673,7 +1695,7 @@ dependencies = [ [[package]] name = "deno_kv" -version = "0.72.0" +version = "0.82.0" dependencies = [ "anyhow", "async-trait", @@ -1682,7 +1704,7 @@ dependencies = [ "chrono", "deno_core", "deno_fetch", - "deno_node", + "deno_path_util", "deno_permissions", "deno_tls", "denokv_proto", @@ -1698,14 +1720,15 @@ dependencies = [ "rand", "rusqlite", "serde", + "thiserror", "url", ] [[package]] name = "deno_lint" -version = "0.63.1" +version = "0.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e6cc8fcb4819dd5e12d640d6fc455217c66bda00e30fd6d46d2844e3e1bdcf" +checksum = "871b60e32bfb6c110cbb9b0688dbf048f81e5d347fe4ce5a42239263de9dd938" dependencies = [ "anyhow", "deno_ast", @@ -1713,7 +1736,7 @@ dependencies = [ "if_chain", "log", "once_cell", - "phf 0.11.2", + "phf", "regex", "serde", "serde_json", @@ -1721,10 +1744,11 @@ dependencies = [ [[package]] name = "deno_lockfile" -version = "0.21.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01138860cdf20cfca4c9e6bcda2bbe577f0c784f6f6938205d522ee2b6327ed" +checksum = "579117d5815aa9bae0212637d6f4d5f45f9649bb2c8988dca434077545535039" dependencies = [ + "deno_semver", "serde", "serde_json", "thiserror", @@ -1743,11 +1767,17 @@ dependencies = [ [[package]] name = "deno_napi" -version = "0.95.0" +version = "0.105.0" dependencies = [ "deno_core", "deno_permissions", + "libc", "libloading 0.7.4", + "libuv-sys-lite", + "log", + "napi_sym", + "thiserror", + "windows-sys 0.52.0", ] [[package]] @@ -1765,7 +1795,7 @@ dependencies = [ [[package]] name = "deno_net" -version = "0.156.0" +version = "0.166.0" dependencies = [ "deno_core", "deno_permissions", @@ -1774,6 +1804,7 @@ dependencies = [ "rustls-tokio-stream", "serde", "socket2", + "thiserror", "tokio", "trust-dns-proto", "trust-dns-resolver", @@ -1781,7 +1812,7 @@ dependencies = [ [[package]] name = "deno_node" -version = "0.101.0" +version = "0.111.0" dependencies = [ "aead-gcm-stream", "aes", @@ -1800,6 +1831,7 @@ dependencies = [ "deno_media_type", "deno_net", "deno_package_json", + "deno_path_util", "deno_permissions", "deno_whoami", "der", @@ -1860,6 +1892,7 @@ dependencies = [ "thiserror", "tokio", "url", + "webpki-root-certs", "winapi", "windows-sys 0.52.0", "x25519-dalek", @@ -1869,9 +1902,9 @@ dependencies = [ [[package]] name = "deno_npm" -version = "0.23.0" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceef28152643a021fc3487a3ec93ae83996972c087547d97f425c83e15dca932" +checksum = "e6b4dc4a9f1cff63d5638e7d93042f24f46300d1cc77b86f3caaa699a7ddccf7" dependencies = [ "anyhow", "async-trait", @@ -1888,9 +1921,9 @@ dependencies = [ [[package]] name = "deno_ops" -version = "0.180.0" +version = "0.190.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbba184551dfe009836a42c0268fea6b4ad036b5154aec5a7625e7a7ce4e315" +checksum = "26f46d4e4f52f26c882b74a9b58810ea75252b807cf0966166ec333077cdfd85" dependencies = [ "proc-macro-rules", "proc-macro2", @@ -1903,9 +1936,9 @@ dependencies = [ [[package]] name = "deno_package_json" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf6ea5cc98ea7ad58b0e84593773bea03fc0431071a296017bed4151e3dc1d" +checksum = "6cbc4c4d3eb0960b58e8f43f9fc2d3f620fcac9a03cd85203e08db5b04e83c1f" dependencies = [ "deno_semver", "indexmap", @@ -1915,25 +1948,55 @@ dependencies = [ "url", ] +[[package]] +name = "deno_path_util" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff25f6e08e7a0214bbacdd6f7195c7f1ebcd850c87a624e4ff06326b68b42d99" +dependencies = [ + "percent-encoding", + "thiserror", + "url", +] + [[package]] name = "deno_permissions" -version = "0.24.0" +version = "0.34.0" dependencies = [ "deno_core", + "deno_path_util", "deno_terminal 0.2.0", "fqdn", "libc", "log", "once_cell", + "percent-encoding", "serde", "which 4.4.2", "winapi", ] [[package]] -name = "deno_runtime" -version = "0.173.0" +name = "deno_resolver" +version = "0.6.0" dependencies = [ + "anyhow", + "base32", + "deno_media_type", + "deno_package_json", + "deno_path_util", + "deno_semver", + "node_resolver", + "test_server", + "thiserror", + "url", +] + +[[package]] +name = "deno_runtime" +version = "0.183.0" +dependencies = [ + "color-print", "deno_ast", "deno_broadcast_channel", "deno_cache", @@ -1951,6 +2014,7 @@ dependencies = [ "deno_napi", "deno_net", "deno_node", + "deno_path_util", "deno_permissions", "deno_terminal 0.2.0", "deno_tls", @@ -1972,7 +2036,7 @@ dependencies = [ "libc", "log", "netif", - "nix 0.26.2", + "nix", "node_resolver", "notify", "ntapi", @@ -1980,10 +2044,13 @@ dependencies = [ "percent-encoding", "regex", "rustyline", + "same-file", "serde", "signal-hook", "signal-hook-registry", + "tempfile", "test_server", + "thiserror", "tokio", "tokio-metrics", "twox-hash", @@ -1995,9 +2062,9 @@ dependencies = [ [[package]] name = "deno_semver" -version = "0.5.10" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56feaf035e29320d11adf89eafa14f5447d3089deb1ce7de61ba7969195f5ff1" +checksum = "c957c6a57c38b7dde2315df0da0ec228911e56a74f185b108a488d0401841a67" dependencies = [ "monch", "once_cell", @@ -2008,9 +2075,9 @@ dependencies = [ [[package]] name = "deno_task_shell" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6413ffc1654cad015edb5c4ab574069acdc929a6efafed23bc947901bcff1a" +checksum = "4f444918f7102c1a5a143e9d57809e499fb4d365070519bf2e8bdb16d586af2a" dependencies = [ "anyhow", "futures", @@ -2045,7 +2112,7 @@ dependencies = [ [[package]] name = "deno_tls" -version = "0.151.0" +version = "0.161.0" dependencies = [ "deno_core", "deno_native_certs", @@ -2054,34 +2121,59 @@ dependencies = [ "rustls-tokio-stream", "rustls-webpki", "serde", + "thiserror", "tokio", "webpki-roots", ] +[[package]] +name = "deno_tower_lsp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afb4d257c084fd889e8cf1ba3ad58db0002428c819cc7717815f996f97777a" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap", + "deno-tower-lsp-macros", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tracing", +] + [[package]] name = "deno_unsync" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f36b4ef61a04ce201b925a5dffa90f88437d37fee4836c758470dd15ba7f05e" dependencies = [ - "parking_lot 0.12.3", + "parking_lot", "tokio", ] [[package]] name = "deno_url" -version = "0.164.0" +version = "0.174.0" dependencies = [ "deno_bench_util", "deno_console", "deno_core", "deno_webidl", + "thiserror", "urlpattern", ] [[package]] name = "deno_web" -version = "0.195.0" +version = "0.205.0" dependencies = [ "async-trait", "base64-simd 0.8.0", @@ -2096,17 +2188,19 @@ dependencies = [ "flate2", "futures", "serde", + "thiserror", "tokio", "uuid", ] [[package]] name = "deno_webgpu" -version = "0.131.0" +version = "0.141.0" dependencies = [ "deno_core", "raw-window-handle", "serde", + "thiserror", "tokio", "wgpu-core", "wgpu-types", @@ -2114,7 +2208,7 @@ dependencies = [ [[package]] name = "deno_webidl" -version = "0.164.0" +version = "0.174.0" dependencies = [ "deno_bench_util", "deno_core", @@ -2122,7 +2216,7 @@ dependencies = [ [[package]] name = "deno_websocket" -version = "0.169.0" +version = "0.179.0" dependencies = [ "bytes", "deno_core", @@ -2138,16 +2232,18 @@ dependencies = [ "once_cell", "rustls-tokio-stream", "serde", + "thiserror", "tokio", ] [[package]] name = "deno_webstorage" -version = "0.159.0" +version = "0.169.0" dependencies = [ "deno_core", "deno_web", "rusqlite", + "thiserror", ] [[package]] @@ -2162,9 +2258,9 @@ dependencies = [ [[package]] name = "denokv_proto" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114538d2cacd2b219f05faa753d80950f95416e47c77904c7452d5f41e157059" +checksum = "f629c77d2bf59e2e2a07fd7b14bfffae352a3813fbdcb801e72205741fb7625c" dependencies = [ "anyhow", "async-trait", @@ -2203,9 +2299,9 @@ dependencies = [ [[package]] name = "denokv_sqlite" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "188b792af19082cbfc7b666e71979775300482877d8b80601f4a5a86a80098a3" +checksum = "3c4f5719e2bf698ec4f39fe29d91b62ff06a4b4a37ee481ffb8658d140fed986" dependencies = [ "anyhow", "async-stream", @@ -2333,6 +2429,22 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" +[[package]] +name = "dhat" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cd11d84628e233de0ce467de10b8633f4ddaecafadefc86e13b84b8739b827" +dependencies = [ + "backtrace", + "lazy_static", + "mintex", + "parking_lot", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "thousands", +] + [[package]] name = "diff" version = "0.1.13" @@ -2437,7 +2549,7 @@ dependencies = [ "bumpalo", "hashbrown", "indexmap", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "unicode-width", ] @@ -2454,9 +2566,9 @@ dependencies = [ [[package]] name = "dprint-plugin-json" -version = "0.19.3" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19f4a9f2f548b2098b8ec597d7bb40af133b6e9a3187c1d3c4caa101b8c93c3" +checksum = "57f91e594559b450b7c5d6a0ba9f3f9fe951c1ea371168f7c95973da3fdbd85a" dependencies = [ "anyhow", "dprint-core", @@ -2468,9 +2580,9 @@ dependencies = [ [[package]] name = "dprint-plugin-jupyter" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c67b0e54b552a4775c221b44ed33be918c400bd8041d1f044f947fbb01025cc0" +checksum = "d0d20684e37b3824e2bc917cfcb14e2cdf88398eef507335d839cbd78172bfee" dependencies = [ "anyhow", "dprint-core", @@ -2481,9 +2593,9 @@ dependencies = [ [[package]] name = "dprint-plugin-markdown" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f1d74e1b3481450e956c35a68e0a5e795796adb13e100d19b6971b9cb531824" +checksum = "934a8e33f6f373b2fb66c288a468e3dae9a56a6c66bfecd5504fe566131afd3f" dependencies = [ "anyhow", "dprint-core", @@ -2496,29 +2608,29 @@ dependencies = [ [[package]] name = "dprint-plugin-typescript" -version = "0.91.6" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390da1b0ba3761f824518a3e4f06ca273837ba16fac73560efd201342b980561" +checksum = "e9308d98b923b7c0335c2ee1560199e3f2321b1be82803107b4ba4ed5dac46cc" dependencies = [ "anyhow", "deno_ast", "dprint-core", "dprint-core-macros", "percent-encoding", - "rustc-hash", + "rustc-hash 1.1.0", "serde", ] [[package]] name = "dprint-swc-ext" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f385cdad3065151fae39262ad43003099234689856a0dc476e8804c5ba8f475b" +checksum = "0ba28c12892aadb751c2ba7001d8460faee4748a04b4edc51c7121cc67ee03db" dependencies = [ "allocator-api2", "bumpalo", "num-bigint", - "rustc-hash", + "rustc-hash 1.1.0", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -2632,6 +2744,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed448-goldilocks" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06924531e9e90130842b012e447f85bdaf9161bc8a0f8092be8cb70b01ebe092" +dependencies = [ + "fiat-crypto 0.1.20", + "hex", + "subtle", + "zeroize", +] + [[package]] name = "editpe" version = "0.1.0" @@ -2658,6 +2782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", + "base64ct", "crypto-bigint", "digest", "ff", @@ -2668,6 +2793,8 @@ dependencies = [ "pkcs8", "rand_core", "sec1", + "serde_json", + "serdect", "subtle", "zeroize", ] @@ -2767,43 +2894,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31ae425815400e5ed474178a7a22e275a9687086a12ca63ec793ff292d8fdae8" -[[package]] -name = "escape8259" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" -dependencies = [ - "rustversion", -] - -[[package]] -name = "eszip" -version = "0.75.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ab3253e0e6a99b79ffc6d7a6243ad541f54543768cecd2198b64476a5971f8" -dependencies = [ - "anyhow", - "async-trait", - "base64 0.21.7", - "deno_ast", - "deno_graph", - "deno_npm", - "deno_semver", - "futures", - "hashlink", - "indexmap", - "serde", - "serde_json", - "sha2", - "thiserror", - "url", -] - [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fallible-streaming-iterator" @@ -2900,6 +2995,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + [[package]] name = "fiat-crypto" version = "0.2.7" @@ -2915,7 +3016,7 @@ dependencies = [ "anyhow", "crossbeam-channel", "deno_terminal 0.1.1", - "parking_lot 0.12.3", + "parking_lot", "regex", "thiserror", ] @@ -2928,7 +3029,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "windows-sys 0.52.0", ] @@ -2979,6 +3080,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -3074,16 +3184,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - [[package]] name = "futures" version = "0.3.30" @@ -3279,7 +3379,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "gpu-alloc-types", ] @@ -3289,7 +3389,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -3298,7 +3398,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "gpu-descriptor-types", "hashbrown", ] @@ -3309,7 +3409,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -3382,9 +3482,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "5.1.2" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "ce25b617d1375ef96eeb920ae717e3da34a02fc979fe632c75128350f9e1f74a" dependencies = [ "heck 0.5.0", "log", @@ -3407,9 +3507,9 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ "hashbrown", ] @@ -3491,8 +3591,8 @@ dependencies = [ "hashbrown", "new_debug_unreachable", "once_cell", - "phf 0.11.2", - "rustc-hash", + "phf", + "rustc-hash 1.1.0", "triomphe", ] @@ -3505,20 +3605,6 @@ dependencies = [ "utf8-width", ] -[[package]] -name = "html5ever" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "http" version = "0.2.12" @@ -3740,15 +3826,16 @@ dependencies = [ [[package]] name = "import_map" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b8288ad259df0d1314e3e8b2fff0e5e63f22e01bc54ecd2c3c7ad77b9200c" +checksum = "351a787decc56f38d65d16d32687265045d6d6a4531b4a0e1b649def3590354e" dependencies = [ "indexmap", "log", "percent-encoding", "serde", "serde_json", + "thiserror", "url", ] @@ -3793,15 +3880,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -3871,6 +3949,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -3921,9 +4005,9 @@ dependencies = [ [[package]] name = "jsonc-parser" -version = "0.23.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7725c320caac8c21d8228c1d055af27a995d371f78cc763073d3e068323641b5" +checksum = "b558af6b49fd918e970471374e7a798b2c9bbcda624a210ffa3901ee5614bc8e" dependencies = [ "serde_json", ] @@ -3968,7 +4052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.3", + "libloading 0.8.5", "pkg-config", ] @@ -4036,70 +4120,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.153" @@ -4137,9 +4157,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", "windows-targets 0.52.4", @@ -4157,15 +4177,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] [[package]] name = "libsqlite3-sys" -version = "0.26.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +checksum = "6b694a822684ddb75df4d657029161431bcb4a85c1856952f845b76912bc6fec" dependencies = [ "cc", "pkg-config", @@ -4174,9 +4194,9 @@ dependencies = [ [[package]] name = "libsui" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0f34a58599483cd44a31ff3622dbcca0c50679af60f98b705069dc729e70cf" +checksum = "205eca4e7beaad637dcd38fe41292065894ee7f498077cf3c135d5f7252b9f27" dependencies = [ "editpe", "libc", @@ -4186,10 +4206,20 @@ dependencies = [ ] [[package]] -name = "libz-sys" -version = "1.1.16" +name = "libuv-sys-lite" +version = "1.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "ca8dfd1a173826d193e3b955e07c22765829890f62c677a59c4a410cb4f47c01" +dependencies = [ + "bindgen 0.70.1", + "libloading 0.8.5", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "cmake", @@ -4246,23 +4276,17 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.1" +version = "0.97.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +checksum = "53353550a17c04ac46c585feb189c2db82154fc84b79c7a66c96c2c644f66071" dependencies = [ "bitflags 1.3.2", + "fluent-uri", "serde", "serde_json", "serde_repr", - "url", ] -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - [[package]] name = "malloc_buf" version = "0.0.6" @@ -4274,9 +4298,9 @@ dependencies = [ [[package]] name = "malva" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e9f16e424a6672f6726daf965333952dece79ef3d17aac712b92b3b72d0a8" +checksum = "1c67b97ed99f56b86fa3c010843441f1fcdb71884bab96b8551bb3d1e7c6d529" dependencies = [ "aho-corasick", "itertools 0.13.0", @@ -4285,31 +4309,11 @@ dependencies = [ "tiny_pretty", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "markup5ever" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" -dependencies = [ - "log", - "phf 0.10.1", - "phf_codegen", - "string_cache", - "string_cache_codegen", - "tendril", -] - [[package]] name = "markup_fmt" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33edf0c364d53d5518cf663824e7d5d5339c844daa54bb0208bee5202dde88f1" +checksum = "3f15d7b24ae4ea9b87279bc0696462a4fb6c2168847f2cc162a2da05fe1a0f61" dependencies = [ "aho-corasick", "css_dataset", @@ -4364,15 +4368,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.9.1" @@ -4388,7 +4383,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block", "core-graphics-types", "foreign-types", @@ -4419,6 +4414,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mintex" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07" + [[package]] name = "mio" version = "0.8.11" @@ -4451,13 +4452,13 @@ checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.5.0", + "bitflags 2.6.0", "codespan-reporting", "hexf-parse", "indexmap", "log", "num-traits", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "spirv", "termcolor", @@ -4482,7 +4483,7 @@ dependencies = [ [[package]] name = "napi_sym" -version = "0.94.0" +version = "0.104.0" dependencies = [ "quote", "serde", @@ -4524,39 +4525,26 @@ dependencies = [ "smallvec", ] -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", - "pin-utils", - "static_assertions", -] - [[package]] name = "nix" version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", ] [[package]] name = "node_resolver" -version = "0.3.0" +version = "0.13.0" dependencies = [ "anyhow", "async-trait", "deno_media_type", "deno_package_json", + "deno_path_util", "futures", "lazy-regex", "once_cell", @@ -4594,7 +4582,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -4858,17 +4846,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -4876,21 +4853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -4901,7 +4864,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -5024,15 +4987,6 @@ dependencies = [ "indexmap", ] -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - [[package]] name = "phf" version = "0.11.2" @@ -5040,27 +4994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand", + "phf_shared", ] [[package]] @@ -5069,7 +5003,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared 0.11.2", + "phf_shared", "rand", ] @@ -5079,22 +5013,13 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", + "phf_generator", + "phf_shared", "proc-macro2", "quote", "syn 2.0.72", ] -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - [[package]] name = "phf_shared" version = "0.11.2" @@ -5217,12 +5142,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "pretty_assertions" version = "1.4.0" @@ -5235,9 +5154,9 @@ dependencies = [ [[package]] name = "pretty_yaml" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ba50511591c8e1d84125f7e2e6d17ccb06865c484b812f5ee3af61f42a66be" +checksum = "dda9a64ee7296e82d1e0f4389383e6a7d8e6e2487d8391f7d028c131395fd376" dependencies = [ "rowan", "tiny_pretty", @@ -5424,7 +5343,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb4e75767fbc9d92b90e4d0c011f61358cde9513b31ef07ea3631b15ffc3b4fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -5468,7 +5387,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 1.1.0", "rustls", "thiserror", "tokio", @@ -5477,14 +5396,14 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand", "ring", - "rustc-hash", + "rustc-hash 2.0.0", "rustls", "slab", "thiserror", @@ -5619,15 +5538,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -5801,7 +5711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags 2.5.0", + "bitflags 2.6.0", "serde", "serde_derive", ] @@ -5814,8 +5724,8 @@ checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" dependencies = [ "countme", "hashbrown", - "memoffset 0.9.1", - "rustc-hash", + "memoffset", + "rustc-hash 1.1.0", "text-size", ] @@ -5865,11 +5775,11 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.29.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +checksum = "1cdbe9230a57259b37f7257d0aff38b8c9dbda3513edba2105e59b130189d82f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -5889,6 +5799,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc_version" version = "0.2.3" @@ -5922,7 +5838,7 @@ version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno 0.3.8", "libc", "linux-raw-sys", @@ -5969,9 +5885,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-tokio-stream" @@ -6008,7 +5924,7 @@ version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "clipboard-win", "fd-lock", @@ -6016,7 +5932,7 @@ dependencies = [ "libc", "log", "memchr", - "nix 0.27.1", + "nix", "radix_trie", "unicode-segmentation", "unicode-width", @@ -6118,6 +6034,7 @@ dependencies = [ "der", "generic-array", "pkcs8", + "serdect", "subtle", "zeroize", ] @@ -6252,9 +6169,9 @@ dependencies = [ [[package]] name = "serde_v8" -version = "0.213.0" +version = "0.223.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1831a65bad8086cfc993eaead4cbcb00579c085e43b4952a90024e1243f23b4e" +checksum = "9cf3d859dda87ee96423c01244f10af864fa6d6a9fcdc2b77e0595078ea0ea11" dependencies = [ "num-bigint", "serde", @@ -6263,6 +6180,16 @@ dependencies = [ "v8", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -6368,13 +6295,12 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simd-json" -version = "0.13.9" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b84c23a1066e1d650ebc99aa8fb9f8ed0ab96fd36e2e836173c92fc9fb29bc" +checksum = "05f0b376aada35f30a0012f5790e50aed62f91804a0682669aefdbe81c7fcb91" dependencies = [ "getrandom", "halfbrown", - "lexical-core", "ref-cast", "serde", "serde_json", @@ -6469,7 +6395,26 @@ dependencies = [ "data-encoding", "debugid", "if_chain", - "rustc-hash", + "rustc-hash 1.1.0", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + +[[package]] +name = "sourcemap" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab08a862c70980b8e23698b507e272317ae52a608a164a844111f5372374f1f" +dependencies = [ + "base64-simd 0.7.0", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash 1.1.0", "rustc_version 0.2.3", "serde", "serde_json", @@ -6489,7 +6434,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -6527,32 +6472,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.3", - "phf_shared 0.10.0", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro2", - "quote", -] - [[package]] name = "string_enum" version = "0.4.4" @@ -6617,7 +6536,7 @@ dependencies = [ "bumpalo", "hashbrown", "ptr_meta", - "rustc-hash", + "rustc-hash 1.1.0", "triomphe", ] @@ -6629,22 +6548,22 @@ checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" dependencies = [ "hstr", "once_cell", - "rustc-hash", + "rustc-hash 1.1.0", "serde", ] [[package]] name = "swc_bundler" -version = "0.233.3" +version = "0.237.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e0a88398e80a77bd6e1b523698a0f1ab3b12fbddd03c8a69a73963c02d3bbc" +checksum = "c77c112c218a09635d99a45802a81b4f341d6c28c81076aa2c29ba3bcd9151a9" dependencies = [ "anyhow", "crc", "indexmap", "is-macro", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "petgraph", "radix_fmt", "relative-path", @@ -6679,9 +6598,9 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.36.2" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1802b1642488aec58597dc55ea88992c165660d6e44e9838d4d93f7b78ab95f3" +checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" dependencies = [ "ast_node", "better_scoped_tls", @@ -6691,10 +6610,10 @@ dependencies = [ "new_debug_unreachable", "num-bigint", "once_cell", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "siphasher", - "sourcemap", + "sourcemap 9.0.0", "swc_allocator", "swc_atoms", "swc_eq_ignore_macros", @@ -6706,9 +6625,9 @@ dependencies = [ [[package]] name = "swc_config" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b67e115ab136fe0eb03558bb0508ca7782eeb446a96d165508c48617e3fd94" +checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" dependencies = [ "anyhow", "indexmap", @@ -6732,14 +6651,14 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "0.117.4" +version = "0.118.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5da2f0310e8cd84b8c803095e75b2cbca872c71fc7f7404d4c9c8117d894960" +checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "is-macro", "num-bigint", - "phf 0.11.2", + "phf", "scoped-tls", "serde", "string_enum", @@ -6750,15 +6669,15 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "0.154.4" +version = "0.155.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7badcda2c45056495ed94b957884099cb000470ae7901ba68db2e7fd48414a4b" +checksum = "cc7641608ef117cfbef9581a99d02059b522fcca75e5244fa0cbbd8606689c6f" dependencies = [ "memchr", "num-bigint", "once_cell", "serde", - "sourcemap", + "sourcemap 9.0.0", "swc_allocator", "swc_atoms", "swc_common", @@ -6781,9 +6700,9 @@ dependencies = [ [[package]] name = "swc_ecma_loader" -version = "0.48.1" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a201c65ccbaa0c80fbcfd5c90dcc0bfc7ae62ac596f2233651ac715caf5d2c12" +checksum = "55fa3d55045b97894bfb04d38aff6d6302ac8a6a38e3bb3dfb0d20475c4974a9" dependencies = [ "anyhow", "pathdiff", @@ -6795,15 +6714,15 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "0.148.1" +version = "0.149.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8204235f635274dba4adc30c47ac896fd126ddfc53b27210676722423cbb2e7" +checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" dependencies = [ "either", "new_debug_unreachable", "num-bigint", "num-traits", - "phf 0.11.2", + "phf", "serde", "smallvec", "smartstring", @@ -6817,16 +6736,16 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "0.143.3" +version = "0.145.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df81c1cbb920d9c47abe6fb105363b0f78df2c8f6b0910c4fdd2ad7cbdfb23d" +checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" dependencies = [ "better_scoped_tls", - "bitflags 2.5.0", + "bitflags 2.6.0", "indexmap", "once_cell", - "phf 0.11.2", - "rustc-hash", + "phf", + "rustc-hash 1.1.0", "serde", "smallvec", "swc_atoms", @@ -6840,9 +6759,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_classes" -version = "0.132.1" +version = "0.134.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53291bcdfca4bd4c2546c3170d7f0ea1d4f22f6fce2a531265ead010a9a2ebdf" +checksum = "3c3d884594385bea9405a2e1721151470d9a14d3ceec5dd773c0ca6894791601" dependencies = [ "swc_atoms", "swc_common", @@ -6866,15 +6785,15 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "0.204.2" +version = "0.208.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7f9a903d6774d3f9005775badc25817296791ffed560f1b7e38aab62ca37ff" +checksum = "98d8447ea20ef76958a8240feef95743702485a84331e6df5bdbe7e383c87838" dependencies = [ "dashmap", "indexmap", "once_cell", "petgraph", - "rustc-hash", + "rustc-hash 1.1.0", "serde_json", "swc_atoms", "swc_common", @@ -6890,12 +6809,12 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_proposal" -version = "0.177.1" +version = "0.179.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d84d062b05ae89982a76ff47881a5e15bbd02e9b3c68dc14a3f5eacf48abca" +checksum = "79938ff510fc647febd8c6c3ef4143d099fdad87a223680e632623d056dae2dd" dependencies = [ "either", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "smallvec", "swc_atoms", @@ -6910,9 +6829,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "0.189.2" +version = "0.191.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d411add563dd86d50b3db6e74e38def06587fa2fd370b430f71226688bfa6ded" +checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" dependencies = [ "base64 0.21.7", "dashmap", @@ -6935,9 +6854,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "0.194.3" +version = "0.198.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f73c4ae3eb15adc5865dc729c4e111040529cec5a349d56ed0b4a0de1a86242" +checksum = "15455da4768f97186c40523e83600495210c11825d3a44db43383fd81eace88d" dependencies = [ "ryu-js", "serde", @@ -6952,14 +6871,14 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "0.133.4" +version = "0.134.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6148af60d25da893aef037621e4869e9b580eb280e12f5a8d4f87fa5e4cd5da" +checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" dependencies = [ "indexmap", "num_cpus", "once_cell", - "rustc-hash", + "rustc-hash 1.1.0", "ryu-js", "swc_atoms", "swc_common", @@ -6971,9 +6890,9 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "0.103.3" +version = "0.104.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed8026e4d9abcb75d511bf7623d49e8e135f02f4f9a6bb7c115df8239cfe3d4f" +checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" dependencies = [ "new_debug_unreachable", "num-bigint", @@ -6997,21 +6916,21 @@ dependencies = [ [[package]] name = "swc_fast_graph" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f854cf8efc290aa927d31dab98b42011ff2341fecb2b27fdc817ef7b30ef3b" +checksum = "357e2c97bb51431d65080f25b436bc4e2fc1a7f64a643bc21a8353e478dc799f" dependencies = [ "indexmap", "petgraph", - "rustc-hash", + "rustc-hash 1.1.0", "swc_common", ] [[package]] name = "swc_graph_analyzer" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97d4b3b186f842f6def323db73f1bc90d7086bd5fa1fb4cca527e20c70f856e" +checksum = "f84e1d24a0d6e4066b42cfc00ab9b3109e314465aa199dd3e16849ed9566dce7" dependencies = [ "auto_impl", "petgraph", @@ -7033,11 +6952,12 @@ dependencies = [ [[package]] name = "swc_visit" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e194d14f94121fd08b823d3379eedb3ce455785d9e0c3d2742c59377e283207" +checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" dependencies = [ "either", + "new_debug_unreachable", ] [[package]] @@ -7153,17 +7073,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -7195,6 +7104,7 @@ dependencies = [ name = "test_napi" version = "0.1.0" dependencies = [ + "libuv-sys-lite", "napi-build", "napi-sys", "test_server", @@ -7225,10 +7135,10 @@ dependencies = [ "libc", "lsp-types", "monch", - "nix 0.26.2", + "nix", "once_cell", "os_pipe", - "parking_lot 0.12.3", + "parking_lot", "pretty_assertions", "prost", "prost-build", @@ -7266,24 +7176,30 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", "syn 2.0.72", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "thread_local" version = "1.1.8" @@ -7360,7 +7276,7 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot 0.12.3", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -7503,12 +7419,12 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" dependencies = [ "async-compression", - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "http 1.1.0", @@ -7523,43 +7439,9 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-lsp" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" -dependencies = [ - "async-trait", - "auto_impl", - "bytes", - "dashmap", - "futures", - "httparse", - "lsp-types", - "memchr", - "serde", - "serde_json", - "tokio", - "tokio-util", - "tower", - "tower-lsp-macros", - "tracing", -] - -[[package]] -name = "tower-lsp-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" @@ -7573,6 +7455,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -7664,7 +7547,7 @@ dependencies = [ "ipconfig", "lru-cache", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "rand", "resolv-conf", "serde", @@ -7910,12 +7793,12 @@ dependencies = [ [[package]] name = "v8" -version = "0.103.0" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d72310e5b559c0a8165a5d6bdf4c975ba77c61461039ccf615ce3bbe489ca5" +checksum = "a381badc47c6f15acb5fe0b5b40234162349ed9d4e4fd7c83a7f5547c0fc69c5" dependencies = [ - "bindgen", - "bitflags 2.5.0", + "bindgen 0.69.4", + "bitflags 2.6.0", "fslock", "gzip-header", "home", @@ -7931,7 +7814,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97599c400fc79925922b58303e98fcb8fa88f573379a08ddb652e72cbd2e70f6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "encoding_rs", "indexmap", "num-bigint", @@ -7942,9 +7825,9 @@ dependencies = [ [[package]] name = "value-trait" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad8db98c1e677797df21ba03fca7d3bf9bec3ca38db930954e4fe6e1ea27eb4" +checksum = "bcaa56177466248ba59d693a048c0959ddb67f1151b963f904306312548cf392" dependencies = [ "float-cmp", "halfbrown", @@ -8112,6 +7995,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c6dfa3ac045bc517de14c7b1384298de1dbd229d38e08e169d9ae8c170937c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.26.1" @@ -8129,7 +8021,7 @@ checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" dependencies = [ "arrayvec", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg_aliases", "codespan-reporting", "document-features", @@ -8137,11 +8029,11 @@ dependencies = [ "log", "naga", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "profiling", "raw-window-handle", "ron", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "smallvec", "thiserror", @@ -8160,7 +8052,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.5.0", + "bitflags 2.6.0", "block", "cfg_aliases", "core-graphics-types", @@ -8172,18 +8064,18 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.3", + "libloading 0.8.5", "log", "metal", "naga", "ndk-sys", "objc", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "profiling", "range-alloc", "raw-window-handle", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "thiserror", "wasm-bindgen", @@ -8198,7 +8090,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "js-sys", "serde", "web-sys", @@ -8234,7 +8126,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall", "wasite", "web-sys", ] @@ -8671,7 +8563,7 @@ dependencies = [ "log", "num-traits", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "rand", "regex", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 1176656e20..37fed81681 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ resolver = "2" members = [ "bench_util", "cli", - "cli/napi/sym", "ext/broadcast_channel", "ext/cache", "ext/canvas", @@ -19,15 +18,17 @@ members = [ "ext/io", "ext/kv", "ext/napi", + "ext/napi/sym", "ext/net", "ext/node", - "ext/node_resolver", "ext/url", "ext/web", "ext/webgpu", "ext/webidl", "ext/websocket", "ext/webstorage", + "resolvers/deno", + "resolvers/node", "runtime", "runtime/permissions", "tests", @@ -44,47 +45,53 @@ license = "MIT" repository = "https://github.com/denoland/deno" [workspace.dependencies] -deno_ast = { version = "=0.41.2", features = ["transpiling"] } -deno_core = { version = "0.304.0" } +deno_ast = { version = "=0.42.2", features = ["transpiling"] } +deno_core = { version = "0.314.2" } -deno_bench_util = { version = "0.158.0", path = "./bench_util" } -deno_lockfile = "0.21.1" +deno_bench_util = { version = "0.168.0", path = "./bench_util" } +deno_lockfile = "=0.23.1" deno_media_type = { version = "0.1.4", features = ["module_specifier"] } -deno_permissions = { version = "0.24.0", path = "./runtime/permissions" } -deno_runtime = { version = "0.173.0", path = "./runtime" } +deno_npm = "=0.25.4" +deno_path_util = "=0.2.1" +deno_permissions = { version = "0.34.0", path = "./runtime/permissions" } +deno_runtime = { version = "0.183.0", path = "./runtime" } +deno_semver = "=0.5.16" deno_terminal = "0.2.0" -napi_sym = { version = "0.94.0", path = "./cli/napi/sym" } +napi_sym = { version = "0.104.0", path = "./ext/napi/sym" } test_util = { package = "test_server", path = "./tests/util/server" } denokv_proto = "0.8.1" denokv_remote = "0.8.1" # denokv_sqlite brings in bundled sqlite if we don't disable the default features -denokv_sqlite = { default-features = false, version = "0.8.1" } +denokv_sqlite = { default-features = false, version = "0.8.2" } # exts -deno_broadcast_channel = { version = "0.158.0", path = "./ext/broadcast_channel" } -deno_cache = { version = "0.96.0", path = "./ext/cache" } -deno_canvas = { version = "0.33.0", path = "./ext/canvas" } -deno_console = { version = "0.164.0", path = "./ext/console" } -deno_cron = { version = "0.44.0", path = "./ext/cron" } -deno_crypto = { version = "0.178.0", path = "./ext/crypto" } -deno_fetch = { version = "0.188.0", path = "./ext/fetch" } -deno_ffi = { version = "0.151.0", path = "./ext/ffi" } -deno_fs = { version = "0.74.0", path = "./ext/fs" } -deno_http = { version = "0.162.0", path = "./ext/http" } -deno_io = { version = "0.74.0", path = "./ext/io" } -deno_kv = { version = "0.72.0", path = "./ext/kv" } -deno_napi = { version = "0.95.0", path = "./ext/napi" } -deno_net = { version = "0.156.0", path = "./ext/net" } -deno_node = { version = "0.101.0", path = "./ext/node" } -deno_tls = { version = "0.151.0", path = "./ext/tls" } -deno_url = { version = "0.164.0", path = "./ext/url" } -deno_web = { version = "0.195.0", path = "./ext/web" } -deno_webgpu = { version = "0.131.0", path = "./ext/webgpu" } -deno_webidl = { version = "0.164.0", path = "./ext/webidl" } -deno_websocket = { version = "0.169.0", path = "./ext/websocket" } -deno_webstorage = { version = "0.159.0", path = "./ext/webstorage" } -node_resolver = { version = "0.3.0", path = "./ext/node_resolver" } +deno_broadcast_channel = { version = "0.168.0", path = "./ext/broadcast_channel" } +deno_cache = { version = "0.106.0", path = "./ext/cache" } +deno_canvas = { version = "0.43.0", path = "./ext/canvas" } +deno_console = { version = "0.174.0", path = "./ext/console" } +deno_cron = { version = "0.54.0", path = "./ext/cron" } +deno_crypto = { version = "0.188.0", path = "./ext/crypto" } +deno_fetch = { version = "0.198.0", path = "./ext/fetch" } +deno_ffi = { version = "0.161.0", path = "./ext/ffi" } +deno_fs = { version = "0.84.0", path = "./ext/fs" } +deno_http = { version = "0.172.0", path = "./ext/http" } +deno_io = { version = "0.84.0", path = "./ext/io" } +deno_kv = { version = "0.82.0", path = "./ext/kv" } +deno_napi = { version = "0.105.0", path = "./ext/napi" } +deno_net = { version = "0.166.0", path = "./ext/net" } +deno_node = { version = "0.111.0", path = "./ext/node" } +deno_tls = { version = "0.161.0", path = "./ext/tls" } +deno_url = { version = "0.174.0", path = "./ext/url" } +deno_web = { version = "0.205.0", path = "./ext/web" } +deno_webgpu = { version = "0.141.0", path = "./ext/webgpu" } +deno_webidl = { version = "0.174.0", path = "./ext/webidl" } +deno_websocket = { version = "0.179.0", path = "./ext/websocket" } +deno_webstorage = { version = "0.169.0", path = "./ext/webstorage" } + +# resolvers +deno_resolver = { version = "0.6.0", path = "./resolvers/deno" } +node_resolver = { version = "0.13.0", path = "./resolvers/node" } aes = "=0.8.3" anyhow = "1.0.57" @@ -99,14 +106,16 @@ cbc = { version = "=0.1.2", features = ["alloc"] } # Note: Do not use the "clock" feature of chrono, as it links us to CoreFoundation on macOS. # Instead use util::time::utc_now() chrono = { version = "0.4", default-features = false, features = ["std", "serde"] } +color-print = "0.3.5" console_static_text = "=0.8.1" +dashmap = "5.5.3" data-encoding = "2.3.3" data-url = "=0.3.0" -deno_cache_dir = "=0.10.2" -deno_package_json = { version = "=0.1.1", default-features = false } +deno_cache_dir = "=0.13.0" +deno_package_json = { version = "0.1.2", default-features = false } dlopen2 = "0.6.1" ecb = "=0.1.2" -elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem"] } +elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem", "jwk"] } encoding_rs = "=0.8.33" fast-socks5 = "0.9.6" faster-hex = "0.9" @@ -128,12 +137,12 @@ hyper-util = { version = "=0.1.7", features = ["tokio", "client", "client-legacy hyper_v014 = { package = "hyper", version = "0.14.26", features = ["runtime", "http1"] } indexmap = { version = "2", features = ["serde"] } ipnet = "2.3" -jsonc-parser = { version = "=0.23.0", features = ["serde"] } +jsonc-parser = { version = "=0.26.2", features = ["serde"] } lazy-regex = "3" libc = "0.2.126" -libz-sys = { version = "1.1", default-features = false } +libz-sys = { version = "1.1.20", default-features = false } log = "0.4.20" -lsp-types = "=0.94.1" # used by tower-lsp and "proposed" feature is unstable in patch releases +lsp-types = "=0.97.0" # used by tower-lsp and "proposed" feature is unstable in patch releases memmem = "0.1.1" monch = "=0.5.0" notify = "=6.1.1" @@ -141,8 +150,8 @@ num-bigint = { version = "0.4", features = ["rand"] } once_cell = "1.17.1" os_pipe = { version = "=1.1.5", features = ["io_safety"] } p224 = { version = "0.13.0", features = ["ecdh"] } -p256 = { version = "0.13.2", features = ["ecdh"] } -p384 = { version = "0.13.0", features = ["ecdh"] } +p256 = { version = "0.13.2", features = ["ecdh", "jwk"] } +p384 = { version = "0.13.0", features = ["ecdh", "jwk"] } parking_lot = "0.12.0" percent-encoding = "2.3.0" phf = { version = "0.11", features = ["macros"] } @@ -154,7 +163,7 @@ rand = "=0.8.5" regex = "^1.7.0" reqwest = { version = "=0.12.5", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli", "socks", "json", "http2"] } # pinned because of https://github.com/seanmonstar/reqwest/pull/1955 ring = "^0.17.0" -rusqlite = { version = "=0.29.0", features = ["unlock_notify", "bundled"] } +rusqlite = { version = "0.32.0", features = ["unlock_notify", "bundled"] } rustls = { version = "0.23.11", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-pemfile = "2" rustls-tokio-stream = "=0.3.0" @@ -162,6 +171,7 @@ rustls-webpki = "0.102" rustyline = "=13.0.0" saffron = "=0.1.0" scopeguard = "1.2.0" +sec1 = "0.7" serde = { version = "1.0.149", features = ["derive"] } serde_bytes = "0.11" serde_json = "1.0.85" @@ -177,21 +187,23 @@ tar = "=0.4.40" tempfile = "3.4.0" termcolor = "1.1.3" thiserror = "1.0.61" -tokio = { version = "=1.36.0", features = ["full"] } +tokio = { version = "1.36.0", features = ["full"] } tokio-metrics = { version = "0.3.0", features = ["rt"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring", "tls12"] } tokio-socks = "0.5.1" tokio-util = "0.7.4" tower = { version = "0.4.13", default-features = false, features = ["util"] } -tower-http = { version = "0.5.2", features = ["decompression-br", "decompression-gzip"] } -tower-lsp = { version = "=0.20.0", features = ["proposed"] } +tower-http = { version = "0.6.1", features = ["decompression-br", "decompression-gzip"] } +tower-lsp = { package = "deno_tower_lsp", version = "0.1.0", features = ["proposed"] } tower-service = "0.3.2" twox-hash = "=1.6.3" # Upgrading past 2.4.1 may cause WPT failures url = { version = "< 2.5.0", features = ["serde", "expose_internals"] } uuid = { version = "1.3.0", features = ["v4"] } +webpki-root-certs = "0.26.5" webpki-roots = "0.26" which = "4.2.5" +yoke = { version = "0.7.4", features = ["derive"] } zeromq = { version = "=0.4.0", default-features = false, features = ["tcp-transport", "tokio-runtime"] } zstd = "=0.12.4" @@ -209,15 +221,14 @@ quote = "1" syn = { version = "2", features = ["full", "extra-traits"] } # unix -nix = "=0.26.2" +nix = "=0.27.1" # windows deps junction = "=0.2.0" winapi = "=0.3.9" -windows-sys = { version = "0.52.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_WindowsProgramming", "Wdk", "Wdk_System", "Wdk_System_SystemInformation", "Win32_System_Pipes", "Wdk_Storage_FileSystem", "Win32_System_Registry"] } +windows-sys = { version = "0.52.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_WindowsProgramming", "Wdk", "Wdk_System", "Wdk_System_SystemInformation", "Win32_Security", "Win32_System_Pipes", "Wdk_Storage_FileSystem", "Win32_System_Registry", "Win32_System_Kernel"] } winres = "=0.1.12" -# NB: the `bench` and `release` profiles must remain EXACTLY the same. [profile.release] codegen-units = 1 incremental = true @@ -235,13 +246,6 @@ inherits = "release" codegen-units = 128 lto = "thin" -# NB: the `bench` and `release` profiles must remain EXACTLY the same. -[profile.bench] -codegen-units = 1 -incremental = true -lto = true -opt-level = 'z' # Optimize for size - # Key generation is too slow on `debug` [profile.dev.package.num-bigint-dig] opt-level = 3 @@ -250,80 +254,6 @@ opt-level = 3 [profile.dev.package.v8] opt-level = 1 -# Optimize these packages for performance. -# NB: the `bench` and `release` profiles must remain EXACTLY the same. -[profile.bench.package.async-compression] -opt-level = 3 -[profile.bench.package.base64-simd] -opt-level = 3 -[profile.bench.package.brotli] -opt-level = 3 -[profile.bench.package.brotli-decompressor] -opt-level = 3 -[profile.bench.package.bytes] -opt-level = 3 -[profile.bench.package.deno_bench_util] -opt-level = 3 -[profile.bench.package.deno_broadcast_channel] -opt-level = 3 -[profile.bench.package.deno_core] -opt-level = 3 -[profile.bench.package.deno_crypto] -opt-level = 3 -[profile.bench.package.deno_fetch] -opt-level = 3 -[profile.bench.package.deno_ffi] -opt-level = 3 -[profile.bench.package.deno_http] -opt-level = 3 -[profile.bench.package.deno_napi] -opt-level = 3 -[profile.bench.package.deno_net] -opt-level = 3 -[profile.bench.package.deno_node] -opt-level = 3 -[profile.bench.package.deno_runtime] -opt-level = 3 -[profile.bench.package.deno_tls] -opt-level = 3 -[profile.bench.package.deno_url] -opt-level = 3 -[profile.bench.package.deno_web] -opt-level = 3 -[profile.bench.package.deno_websocket] -opt-level = 3 -[profile.bench.package.fastwebsockets] -opt-level = 3 -[profile.bench.package.flate2] -opt-level = 3 -[profile.bench.package.futures-util] -opt-level = 3 -[profile.bench.package.hyper] -opt-level = 3 -[profile.bench.package.miniz_oxide] -opt-level = 3 -[profile.bench.package.num-bigint-dig] -opt-level = 3 -[profile.bench.package.rand] -opt-level = 3 -[profile.bench.package.serde] -opt-level = 3 -[profile.bench.package.serde_v8] -opt-level = 3 -[profile.bench.package.test_napi] -opt-level = 3 -[profile.bench.package.tokio] -opt-level = 3 -[profile.bench.package.url] -opt-level = 3 -[profile.bench.package.v8] -opt-level = 3 -[profile.bench.package.zstd] -opt-level = 3 -[profile.bench.package.zstd-sys] -opt-level = 3 - -# NB: the `bench` and `release` profiles must remain EXACTLY the same. [profile.release.package.async-compression] opt-level = 3 [profile.release.package.base64-simd] @@ -382,6 +312,8 @@ opt-level = 3 opt-level = 3 [profile.release.package.serde_v8] opt-level = 3 +[profile.release.package.libsui] +opt-level = 3 [profile.release.package.test_napi] opt-level = 3 [profile.release.package.tokio] diff --git a/Releases.md b/Releases.md index 802dc1ca20..5576d4bd8c 100644 --- a/Releases.md +++ b/Releases.md @@ -6,6 +6,778 @@ https://github.com/denoland/deno/releases We also have one-line install commands at: https://github.com/denoland/deno_install +### 2.0.3 / 2024.10.25 + +- feat(lsp): interactive inlay hints (#26382) +- fix: support node-api in denort (#26389) +- fix(check): support `--frozen` on deno check (#26479) +- fix(cli): increase size of blocking task threadpool on windows (#26465) +- fix(config): schemas for lint rule and tag autocompletion (#26515) +- fix(ext/console): ignore casing for named colors in css parsing (#26466) +- fix(ext/ffi): return u64/i64 as bigints from nonblocking ffi calls (#26486) +- fix(ext/node): cancel pending ipc writes on channel close (#26504) +- fix(ext/node): map `ERROR_INVALID_NAME` to `ENOENT` on windows (#26475) +- fix(ext/node): only set our end of child process pipe to nonblocking mode + (#26495) +- fix(ext/node): properly map reparse point error in readlink (#26375) +- fix(ext/node): refactor http.ServerResponse into function class (#26210) +- fix(ext/node): stub HTTPParser internal binding (#26401) +- fix(ext/node): use primordials in `ext/node/polyfills/https.ts` (#26323) +- fix(fmt): --ext flag requires to pass files (#26525) +- fix(fmt): upgrade formatters (#26469) +- fix(help): missing package specifier (#26380) +- fix(info): resolve workspace member mappings (#26350) +- fix(install): better json editing (#26450) +- fix(install): cache all exports of JSR packages listed in `deno.json` (#26501) +- fix(install): cache type only module deps in `deno install` (#26497) +- fix(install): don't cache json exports of JSR packages (for now) (#26530) +- fix(install): update lockfile when using package.json (#26458) +- fix(lsp): import-map-remap quickfix for type imports (#26454) +- fix(node/util): support array formats in `styleText` (#26507) +- fix(node:tls): set TLSSocket.alpnProtocol for client connections (#26476) +- fix(npm): ensure scoped package name is encoded in URLs (#26390) +- fix(npm): support version ranges with && or comma (#26453) +- fix: `.npmrc` settings not being passed to install/add command (#26473) +- fix: add 'fmt-component' to unstable features in schema file (#26526) +- fix: share inotify fd across watchers (#26200) +- fix: unpin tokio version (#26457) +- perf(compile): pass module source data from binary directly to v8 (#26494) +- perf: avoid multiple calls to runMicrotask (#26378) + +### 2.0.2 / 2024.10.17 + +- fix(cli): set napi object property properly (#26344) +- fix(ext/node): add null check for kStreamBaseField (#26368) +- fix(install): don't attempt to cache specifiers that point to directories + (#26369) +- fix(jupyter): fix panics for overslow subtraction (#26371) +- fix(jupyter): update to the new logo (#26353) +- fix(net): don't try to set nodelay on upgrade streams (#26342) +- fix(node/fs): copyFile with `COPYFILE_EXCL` should not throw if the + destination doesn't exist (#26360) +- fix(node/http): normalize header names in `ServerResponse` (#26339) +- fix(runtime): send ws ping frames from inspector server (#26352) +- fix: don't warn on ignored signals on windows (#26332) + +### 2.0.1 / 2024.10.16 + +- feat(lsp): "deno/didRefreshDenoConfigurationTree" notifications (#26215) +- feat(unstable): `--unstable-detect-cjs` for respecting explicit + `"type": "commonjs"` (#26149) +- fix(add): create deno.json when running `deno add jsr:` (#26275) +- fix(add): exact version should not have range `^` specifier (#26302) +- fix(child_process): map node `--no-warnings` flag to `--quiet` (#26288) +- fix(cli): add prefix to install commands in help (#26318) +- fix(cli): consolidate pkg parser for install & remove (#26298) +- fix(cli): named export takes precedence over default export in doc testing + (#26112) +- fix(cli): improve deno info output for npm packages (#25906) +- fix(console/ext/repl): support using parseFloat() (#25900) +- fix(ext/console): apply coloring for console.table (#26280) +- fix(ext/napi): pass user context to napi_threadsafe_fn finalizers (#26229) +- fix(ext/node): allow writing to tty columns (#26201) +- fix(ext/node): compute pem length (upper bound) for key exports (#26231) +- fix(ext/node): fix dns.lookup result ordering (#26264) +- fix(ext/node): handle http2 server ending stream (#26235) +- fix(ext/node): implement TCP.setNoDelay (#26263) +- fix(ext/node): timingSafeEqual account for AB byteOffset (#26292) +- fix(ext/node): use primordials in `ext/node/polyfills/internal/buffer.mjs` + (#24993) +- fix(ext/webgpu): allow GL backend on Windows (#26206) +- fix(install): duplicate dependencies in `package.json` (#26128) +- fix(install): handle pkg with dep on self when pkg part of peer dep resolution + (#26277) +- fix(install): retry downloads of registry info / tarballs (#26278) +- fix(install): support installing npm package with alias (#26246) +- fix(jupyter): copy kernels icons to the kernel directory (#26084) +- fix(jupyter): keep running event loop when waiting for messages (#26049) +- fix(lsp): relative completions for bare import-mapped specifiers (#26137) +- fix(node): make `process.stdout.isTTY` writable (#26130) +- fix(node/util): export `styleText` from `node:util` (#26194) +- fix(npm): support `--allow-scripts` on `deno run` (and `deno add`, + `deno test`, etc) (#26075) +- fix(repl): importing json files (#26053) +- fix(repl): remove check flags (#26140) +- fix(unstable/worker): ensure import permissions are passed (#26101) +- fix: add hint for missing `document` global in terminal error (#26218) +- fix: do not panic on wsl share file paths on windows (#26081) +- fix: do not panic running remote cjs module (#26259) +- fix: do not panic when using methods on classes and interfaces in deno doc + html output (#26100) +- fix: improve suggestions and hints when using CommonJS modules (#26287) +- fix: node-api function call should use preamble (#26297) +- fix: panic in `prepare_stack_trace_callback` when global interceptor throws + (#26241) +- fix: use syntect for deno doc html generation (#26322) +- perf(http): avoid clone getting request method and url (#26250) +- perf(http): cache webidl.converters lookups in ext/fetch/23_response.js + (#26256) +- perf(http): make heap allocation for path conditional (#26289) +- perf: use fast calls for microtask ops (#26236) + +### 2.0.0 / 2024.10.09 + +Read announcement blog post at: https://deno.com/blog/v2 + +- BREAKING: `DENO_FUTURE=1` by default, or welcome to Deno 2.0 (#25213) +- BREAKING: disallow `new Deno.FsFile()` (#25478) +- BREAKING: drop support for Deno.run.{clearEnv,gid,uid} (#25371) +- BREAKING: improve types for `Deno.serve` (#25369) +- BREAKING: improved error code accuracy (#25383) +- BREAKING: make supported compilerOptions an allow list (#25432) +- BREAKING: move `width` and `height` options to `UnsafeWindowSurface` + constructor (#24200) +- BREAKING: remove --allow-hrtime (#25367) +- BREAKING: remove "emit" and "map" from deno info output (#25468) +- BREAKING: remove `--allow-none` flag (#25337) +- BREAKING: remove `--jobs` flag (#25336) +- BREAKING: remove `--trace-ops` (#25344) +- BREAKING: remove `--ts` flag (#25338) +- BREAKING: remove `--unstable` flag (#25522) +- BREAKING: remove `deno bundle` (#25339) +- BREAKING: remove `deno vendor` (#25343) +- BREAKING: remove `Deno.[Tls]Listener.prototype.rid` (#25556) +- BREAKING: remove `Deno.{Conn,TlsConn,TcpConn,UnixConn}.prototype.rid` (#25446) +- BREAKING: remove `Deno.{Reader,Writer}[Sync]` and `Deno.Closer` (#25524) +- BREAKING: remove `Deno.Buffer` (#25441) +- BREAKING: remove `Deno.close()` (#25347) +- BREAKING: remove `Deno.ConnectTlsOptions.{certChain,certFile,privateKey}` and + `Deno.ListenTlsOptions.certChain,certFile,keyFile}` (#25525) +- BREAKING: remove `Deno.copy()` (#25345) +- BREAKING: remove `Deno.customInspect` (#25348) +- BREAKING: remove `Deno.fdatasync[Sync]()` (#25520) +- BREAKING: remove `Deno.File` (#25447) +- BREAKING: remove `Deno.flock[Sync]()` (#25350) +- BREAKING: remove `Deno.FsFile.prototype.rid` (#25499) +- BREAKING: remove `Deno.fstat[Sync]()` (#25351) +- BREAKING: remove `Deno.FsWatcher.prototype.rid` (#25444) +- BREAKING: remove `Deno.fsync[Sync]()` (#25448) +- BREAKING: remove `Deno.ftruncate[Sync]()` (#25412) +- BREAKING: remove `Deno.funlock[Sync]()` (#25442) +- BREAKING: remove `Deno.futime[Sync]()` (#25252) +- BREAKING: remove `Deno.iter[Sync]()` (#25346) +- BREAKING: remove `Deno.read[Sync]()` (#25409) +- BREAKING: remove `Deno.readAll[Sync]()` (#25386) +- BREAKING: remove `Deno.seek[Sync]()` (#25449) +- BREAKING: remove `Deno.Seeker[Sync]` (#25551) +- BREAKING: remove `Deno.shutdown()` (#25253) +- BREAKING: remove `Deno.write[Sync]()` (#25408) +- BREAKING: remove `Deno.writeAll[Sync]()` (#25407) +- BREAKING: remove deprecated `UnsafeFnPointer` constructor type with untyped + `Deno.PointerObject` parameter (#25577) +- BREAKING: remove deprecated files config (#25535) +- BREAKING: Remove obsoleted Temporal APIs part 2 (#25505) +- BREAKING: remove remaining web types for compatibility (#25334) +- BREAKING: remove support for remote import maps in deno.json (#25836) +- BREAKING: rename "deps" remote cache folder to "remote" (#25969) +- BREAKING: soft-remove `Deno.isatty()` (#25410) +- BREAKING: soft-remove `Deno.run()` (#25403) +- BREAKING: soft-remove `Deno.serveHttp()` (#25451) +- BREAKING: undeprecate `Deno.FsWatcher.prototype.return()` (#25623) +- feat: add `--allow-import` flag (#25469) +- feat: Add a hint on error about 'Relative import path ... not prefixed with + ...' (#25430) +- feat: Add better error messages for unstable APIs (#25519) +- feat: Add suggestion for packages using Node-API addons (#25975) +- feat: Allow importing .cjs files (#25426) +- feat: default to TS for file extension and support ext flag in more scenarios + (#25472) +- feat: deprecate import assertions (#25281) +- feat: Don't warn about --allow-script when using esbuild (#25894) +- feat: hide several --unstable-* flags (#25378) +- feat: improve lockfile v4 to store normalized version constraints and be more + terse (#25247) +- feat: improve warnings for deprecations and lifecycle script for npm packages + (#25694) +- feat: include version number in all --json based outputs (#25335) +- feat: lockfile v4 by default (#25165) +- feat: make 'globalThis.location' a configurable property (#25812) +- feat: print `Listening on` messages on stderr instead of stdout (#25491) +- feat: remove `--lock-write` flag (#25214) +- feat: require jsr prefix for `deno install` and `deno add` (#25698) +- feat: require(esm) (#25501) +- feat: Show hints when using `window` global (#25805) +- feat: stabilize `Deno.createHttpClient()` (#25569) +- feat: suggest `deno install --entrypoint` instead of `deno cache` (#25228) +- feat: support DENO_LOG env var instead of RUST_LOG (#25356) +- feat: TypeScript 5.6 and `npm:@types/node@22` (#25614) +- feat: Update no-window lint rule (#25486) +- feat: update warning message for --allow-run with no list (#25693) +- feat: warn when using `--allow-run` with no allow list (#25215) +- feat(add): Add npm packages to package.json if present (#25477) +- feat(add): strip package subpath when adding a package (#25419) +- feat(add/install): Flag to add dev dependency to package.json (#25495) +- feat(byonm): support `deno run npm:` when package is not in + package.json (#25981) +- feat(check): turn on noImplicitOverride (#25695) +- feat(check): turn on useUnknownInCatchVariables (#25465) +- feat(cli): evaluate code snippets in JSDoc and markdown (#25220) +- feat(cli): give access to `process` global everywhere (#25291) +- feat(cli): use NotCapable error for permission errors (#25431) +- feat(config): Node modules option for 2.0 (#25299) +- feat(ext/crypto): import and export p521 keys (#25789) +- feat(ext/crypto): X448 support (#26043) +- feat(ext/kv): configurable limit params (#25174) +- feat(ext/node): add abort helpers, process & streams fix (#25262) +- feat(ext/node): add rootCertificates to node:tls (#25707) +- feat(ext/node): buffer.transcode() (#25972) +- feat(ext/node): export 'promises' symbol from 'node:timers' (#25589) +- feat(ext/node): export missing constants from 'zlib' module (#25584) +- feat(ext/node): export missing symbols from domain, puncode, repl, tls + (#25585) +- feat(ext/node): export more symbols from streams and timers/promises (#25582) +- feat(ext/node): expose ES modules for _ modules (#25588) +- feat(flags): allow double commas to escape values in path based flags (#25453) +- feat(flags): support user provided args in repl subcommand (#25605) +- feat(fmt): better error on malfored HTML files (#25853) +- feat(fmt): stabilize CSS, HTML and YAML formatters (#25753) +- feat(fmt): support vto and njk extensions (#25831) +- feat(fmt): upgrade markup_fmt (#25768) +- feat(install): deno install with entrypoint (#25411) +- feat(install): warn repeatedly about not-run lifecycle scripts on explicit + installs (#25878) +- feat(lint): add `no-process-global` lint rule (#25709) +- feat(lsp): add a message when someone runs 'deno lsp' manually (#26051) +- feat(lsp): auto-import types with 'import type' (#25662) +- feat(lsp): html/css/yaml file formatting (#25353) +- feat(lsp): quick fix for @deno-types="npm:@types/*" (#25954) +- feat(lsp): turn on useUnknownInCatchVariables (#25474) +- feat(lsp): unstable setting as list (#25552) +- feat(permissions): `Deno.mainModule` doesn't require permissions (#25667) +- feat(permissions): allow importing from cdn.jsdelivr.net by default (#26013) +- feat(serve): Support second parameter in deno serve (#25606) +- feat(tools/doc): display subitems in symbol overviews where applicable + (#25885) +- feat(uninstall): alias to 'deno remove' if -g flag missing (#25461) +- feat(upgrade): better error message on failure (#25503) +- feat(upgrade): print info links for Deno 2 RC releases (#25225) +- feat(upgrade): support LTS release channel (#25123) +- fix: add link to env var docs (#25557) +- fix: add suggestion how to fix importing CJS module (#21764) +- fix: add test ensuring als works across dynamic import (#25593) +- fix: better error for Deno.UnsafeWindowSurface, correct HttpClient name, + cleanup unused code (#25833) +- fix: cjs resolution cases (#25739) +- fix: consistent with deno_config and treat `"experimentalDecorators"` as + deprecated (#25735) +- fix: delete old Deno 1.x headers file when loading cache (#25283) +- fix: do not panic running invalid file specifier (#25530) +- fix: don't include extensionless files in file collection for lint & fmt by + default (#25721) +- fix: don't prompt when using `Deno.permissions.request` with `--no-prompt` + (#25811) +- fix: eagerly error for specifier with empty version constraint (#25944) +- fix: enable `Win32_Security` feature in `windows-sys` (#26007) +- fix: error on unsupported compiler options (#25714) +- fix: error out if a valid flag is passed before a subcommand (#25830) +- fix: fix jupyter display function type (#25326) +- fix: Float16Array type (#25506) +- fix: handle showing warnings while the progress bar is shown (#25187) +- fix: Hide 'deno cache' from help output (#25960) +- fix: invalid ipv6 hostname on `deno serve` (#25482) +- fix: linux canonicalization checks (#24641) +- fix: lock down allow-run permissions more (#25370) +- fix: make some warnings more standard (#25324) +- fix: no cmd prefix in help output go links (#25459) +- fix: only enable byonm if workspace root has pkg json (#25379) +- fix: panic when require(esm) (#25769) +- fix: precompile preserve SVG camelCase attributes (#25945) +- fix: reland async context (#25140) +- fix: remove --allow-run warning when using deno without args or subcommand + (#25684) +- fix: remove entrypoint hack for Deno 2.0 (#25332) +- fix: remove recently added deno.json node_modules aliasing (#25542) +- fix: remove the typo in the help message (#25962) +- fix: removed unstable-htttp from deno help (#25216) +- fix: replace `npm install` hint with `deno install` hint (#25244) +- fix: trim space around DENO_AUTH_TOKENS (#25147) +- fix: update deno_doc (#25290) +- fix: Update deno_npm to fix `deno install` with crossws (#25837) +- fix: update hint for `deno add ` (#25455) +- fix: update malva in deno to support astro css comments (#25553) +- fix: update nodeModulesDir config JSON schema (#25653) +- fix: update patchver to 0.2 (#25952) +- fix: update sui to 0.4 (#25942) +- fix: upgrade deno_ast 0.42 (#25313) +- fix: upgrade deno_core to 0.307.0 (#25287) +- fix(add/install): default to "latest" tag for npm packages in + `deno add npm:pkg` (#25858) +- fix(bench): Fix table column alignments and NO_COLOR=1 (#25190) +- fix(BREAKING): make dns record types have consistent naming (#25357) +- fix(byonm): resolve npm deps of jsr deps (#25399) +- fix(check): ignore noImplicitOverrides in remote modules (#25854) +- fix(check): move is cjs check from resolving to loading (#25597) +- fix(check): properly surface dependency errors in types file of js file + (#25860) +- fix(cli): `deno task` exit with status 0 (#25637) +- fix(cli): Default to auto with --node-modules-dir flag (#25772) +- fix(cli): handle edge cases around `export`s in doc tests and default export + (#25720) +- fix(cli): Map error kind to `PermissionDenied` when symlinking fails due to + permissions (#25398) +- fix(cli): Only set allow net flag for deno serve if not already allowed all + (#25743) +- fix(cli): Warn on not-run lifecycle scripts with global cache (#25786) +- fix(cli/tools): correct `deno init --serve` template behavior (#25318) +- fix(compile): support 'deno compile' in RC and LTS releases (#25875) +- fix(config): validate export names (#25436) +- fix(coverage): ignore urls from doc testing (#25736) +- fix(doc): surface graph errors as warnings (#25888) +- fix(dts): stabilize `fetch` declaration for use with `Deno.HttpClient` + (#25683) +- fix(ext/console): more precision in console.time (#25723) +- fix(ext/console): prevent duplicate error printing when the cause is assigned + (#25327) +- fix(ext/crypto): ensure EC public keys are exported uncompressed (#25766) +- fix(ext/crypto): fix identity test for x25519 derive bits (#26011) +- fix(ext/crypto): reject empty usages in SubtleCrypto#importKey (#25759) +- fix(ext/crypto): support md4 digest algorithm (#25656) +- fix(ext/crypto): throw DataError for invalid EC key import (#25181) +- fix(ext/fetch): fix lowercase http_proxy classified as https (#25686) +- fix(ext/fetch): percent decode userinfo when parsing proxies (#25229) +- fix(ext/http): do not set localhost to hostname unnecessarily (#24777) +- fix(ext/http): gracefully handle Response.error responses (#25712) +- fix(ext/node): add `FileHandle#writeFile` (#25555) +- fix(ext/node): add `vm.constants` (#25630) +- fix(ext/node): Add missing `node:path` exports (#25567) +- fix(ext/node): Add missing node:fs and node:constants exports (#25568) +- fix(ext/node): add stubs for `node:trace_events` (#25628) +- fix(ext/node): attach console stream properties (#25617) +- fix(ext/node): avoid showing `UNKNOWN` error from TCP handle (#25550) +- fix(ext/node): close upgraded socket when the underlying http connection is + closed (#25387) +- fix(ext/node): delay accept() call 2 ticks in net.Server#listen (#25481) +- fix(ext/node): don't throw error for unsupported signal binding on windows + (#25699) +- fix(ext/node): emit `online` event after worker thread is initialized (#25243) +- fix(ext/node): export `process.allowedNodeEnvironmentFlags` (#25629) +- fix(ext/node): export JWK public key (#25239) +- fix(ext/node): export request and response clases from `http2` module (#25592) +- fix(ext/node): fix `Cipheriv#update(string, undefined)` (#25571) +- fix(ext/node): fix Decipheriv when autoPadding disabled (#25598) +- fix(ext/node): fix process.stdin.pause() (#25864) +- fix(ext/node): Fix vm sandbox object panic (#24985) +- fix(ext/node): http2session ready state (#25143) +- fix(ext/node): Implement detached option in `child_process` (#25218) +- fix(ext/node): import EC JWK keys (#25266) +- fix(ext/node): import JWK octet key pairs (#25180) +- fix(ext/node): import RSA JWK keys (#25267) +- fix(ext/node): register `node:wasi` built-in (#25134) +- fix(ext/node): remove unimplemented promiseHook stubs (#25979) +- fix(ext/node): report freemem() on Linux in bytes (#25511) +- fix(ext/node): Rewrite `node:v8` serialize/deserialize (#25439) +- fix(ext/node): session close during stream setup (#25170) +- fix(ext/node): Stream should be instance of EventEmitter (#25527) +- fix(ext/node): stub `inspector/promises` (#25635) +- fix(ext/node): stub `process.cpuUsage()` (#25462) +- fix(ext/node): stub cpu_info() for OpenBSD (#25807) +- fix(ext/node): support x509 certificates in `createPublicKey` (#25731) +- fix(ext/node): throw when loading `cpu-features` module (#25257) +- fix(ext/node): update aead-gcm-stream to 0.3 (#25261) +- fix(ext/node): use primordials in `ext/node/polyfills/console.ts` (#25572) +- fix(ext/node): use primordials in ext/node/polyfills/wasi.ts (#25608) +- fix(ext/node): validate input lengths in `Cipheriv` and `Decipheriv` (#25570) +- fix(ext/web): don't ignore capture in EventTarget.removeEventListener (#25788) +- fix(ext/webgpu): allow to build on unsupported platforms (#25202) +- fix(ext/webgpu): sync category comment (#25580) +- fix(ext/webstorage): make `getOwnPropertyDescriptor` with symbol return + `undefined` (#13348) +- fix(flags): --allow-all should conflict with lower permissions (#25909) +- fix(flags): don't treat empty run command as task subcommand (#25708) +- fix(flags): move some content from docs.deno.com into help output (#25951) +- fix(flags): properly error out for urls (#25770) +- fix(flags): require global flag for permission flags in install subcommand + (#25391) +- fix(fmt): --check was broken for CSS, YAML and HTML (#25848) +- fix(fmt): fix incorrect quotes in components (#25249) +- fix(fmt): fix tabs in YAML (#25536) +- fix(fmt/markdown): fix regression with multi-line footnotes and inline math + (#25222) +- fix(info): error instead of panic for npm specifiers when using byonm (#25947) +- fix(info): move "version" field to top of json output (#25890) +- fix(inspector): Fix panic when re-entering runtime ops (#25537) +- fix(install): compare versions directly to decide whether to create a child + node_modules dir for a workspace member (#26001) +- fix(install): Make sure target node_modules exists when symlinking (#25494) +- fix(install): recommend using `deno install -g` when using a single http url + (#25388) +- fix(install): store tags associated with package in node_modules dir (#26000) +- fix(install): surface package.json dependency errors (#26023) +- fix(install): Use relative symlinks in deno install (#25164) +- fix(installl): make bin entries executable even if not put in + `node_modules/.bin` (#25873) +- fix(jupyter): allow unstable flags (#25483) +- fix(lint): correctly handle old jsx in linter (#25902) +- fix(lint): support linting jsr pkg without version field (#25230) +- fix(lockfile): use loose deserialization for version constraints (#25660) +- fix(lsp): encode url parts before parsing as uri (#25509) +- fix(lsp): exclude missing import quick fixes with bad resolutions (#26025) +- fix(lsp): panic on url_to_uri() (#25238) +- fix(lsp): properly resolve jsxImportSource for caching (#25688) +- fix(lsp): update diagnostics on npm install (#25352) +- fix(napi): Don't run microtasks in napi_resolve_deferred (#25246) +- fix(napi): Fix worker threads importing already-loaded NAPI addon (#25245) +- fix(no-slow-types): better `override` handling (#25989) +- fix(node): Don't error out if we fail to statically analyze CJS re-export + (#25748) +- fix(node): fix worker_threads issues blocking Angular support (#26024) +- fix(node): implement libuv APIs needed to support `npm:sqlite3` (#25893) +- fix(node): Include "node" condition during CJS re-export analysis (#25785) +- fix(node): Pass NPM_PROCESS_STATE to subprocesses via temp file instead of env + var (#25896) +- fix(node/byonm): do not accidentally resolve bare node built-ins (#25543) +- fix(node/cluster): improve stubs to make log4js work (#25146) +- fix(npm): better error handling for remote npm deps (#25670) +- fix(npm): root package has peer dependency on itself (#26022) +- fix(permissions): disallow any `LD_` or `DYLD_` prefixed env var without full + --allow-run permissions (#25271) +- fix(permissions): disallow launching subprocess with LD_PRELOAD env var + without full run permissions (#25221) +- fix(publish): ensure provenance is spec compliant (#25200) +- fix(regression): do not expose resolved path in Deno.Command permission denied + error (#25434) +- fix(runtime): don't error `child.output()` on consumed stream (#25657) +- fix(runtime): use more null proto objects again (#25040) +- fix(runtime/web_worker): populate `SnapshotOptions` for `WebWorker` when + instantiated without snapshot (#25280) +- fix(task): correct name for scoped npm package binaries (#25390) +- fix(task): support tasks with colons in name in `deno run` (#25233) +- fix(task): use current executable for deno even when not named deno (#26019) +- fix(types): simplify mtls related types (#25658) +- fix(upgrade): more informative information on invalid version (#25319) +- fix(windows): Deno.Command - align binary resolution with linux and mac + (#25429) +- fix(workspace): handle when config has members when specified via --config + (#25988) +- perf: fast path for cached dyn imports (#25636) +- perf: Use -O3 for sui in release builds (#26010) +- perf(cache): single cache file for remote modules (#24983) +- perf(cache): single cache file for typescript emit (#24994) +- perf(ext/fetch): improve decompression throughput by upgrading `tower_http` + (#25806) +- perf(ext/node): reduce some allocations in require (#25197) +- perf(ext/web): optimize performance.measure() (#25774) + +### 1.46.3 / 2024.09.04 + +- feat(upgrade): print info links for Deno 2 RC releases (#25225) +- fix(cli): Map error kind to `PermissionDenied` when symlinking fails due to + permissions (#25398) +- fix(cli/tools): correct `deno init --serve` template behavior (#25318) +- fix(ext/node): session close during stream setup (#25170) +- fix(publish): ensure provenance is spec compliant (#25200) +- fix(upgrade): more informative information on invalid version (#25319) +- fix: fix jupyter display function type (#25326) + +### 1.46.2 / 2024.08.29 + +- Revert "feat(fetch): accept async iterables for body" (#25207) +- fix(bench): Fix table column alignments and NO_COLOR=1 (#25190) +- fix(ext/crypto): throw DataError for invalid EC key import (#25181) +- fix(ext/fetch): percent decode userinfo when parsing proxies (#25229) +- fix(ext/node): emit `online` event after worker thread is initialized (#25243) +- fix(ext/node): export JWK public key (#25239) +- fix(ext/node): import EC JWK keys (#25266) +- fix(ext/node): import JWK octet key pairs (#25180) +- fix(ext/node): import RSA JWK keys (#25267) +- fix(ext/node): throw when loading `cpu-features` module (#25257) +- fix(ext/node): update aead-gcm-stream to 0.3 (#25261) +- fix(ext/webgpu): allow to build on unsupported platforms (#25202) +- fix(fmt): fix incorrect quotes in components (#25249) +- fix(fmt/markdown): fix regression with multi-line footnotes and inline math + (#25222) +- fix(install): Use relative symlinks in deno install (#25164) +- fix(lsp): panic on url_to_uri() (#25238) +- fix(napi): Don't run microtasks in napi_resolve_deferred (#25246) +- fix(napi): Fix worker threads importing already-loaded NAPI addon (#25245) +- fix(node/cluster): improve stubs to make log4js work (#25146) +- fix(runtime/web_worker): populate `SnapshotOptions` for `WebWorker` when + instantiated without snapshot (#25280) +- fix(task): support tasks with colons in name in `deno run` (#25233) +- fix: handle showing warnings while the progress bar is shown (#25187) +- fix: reland async context (#25140) +- fix: removed unstable-htttp from deno help (#25216) +- fix: replace `npm install` hint with `deno install` hint (#25244) +- fix: update deno_doc (#25290) +- fix: upgrade deno_core to 0.307.0 (#25287) +- perf(ext/node): reduce some allocations in require (#25197) + +### 1.46.1 / 2024.08.22 + +- fix(ext/node): http2session ready state (#25143) +- fix(ext/node): register `node:wasi` built-in (#25134) +- fix(urlpattern): fallback to empty string for undefined group values (#25151) +- fix: trim space around DENO_AUTH_TOKENS (#25147) + +### 1.46.0 / 2024.08.22 + +- BREAKING(temporal/unstable): Remove obsoleted Temporal APIs (#24836) +- BREAKING(webgpu/unstable): Replace async .requestAdapterInfo() with sync .info + (#24783) +- feat: `deno compile --icon ` (#25039) +- feat: `deno init --serve` (#24897) +- feat: `deno upgrade --rc` (#24905) +- feat: Add Deno.ServeDefaultExport type (#24879) +- feat: async context (#24402) +- feat: better help output (#24958) +- feat: codesign for deno compile binaries (#24604) +- feat: deno clean (#24950) +- feat: deno remove (#24952) +- feat: deno run (#24891) +- feat: Deprecate "import assertions" with a warning (#24743) +- feat: glob and directory support for `deno check` and `deno cache` cli arg + paths (#25001) +- feat: Print deprecation message for npm packages (#24992) +- feat: refresh "Download" progress bar with a spinner (#24913) +- feat: Rename --unstable-hmr to --watch-hmr (#24975) +- feat: support short flags for permissions (#24883) +- feat: treat bare deno command with run arguments as deno run (#24887) +- feat: upgrade deno_core (#24886) +- feat: upgrade deno_core (#25042) +- feat: upgrade V8 to 12.8 (#24693) +- feat: Upgrade V8 to 12.9 (#25138) +- feat: vm rewrite (#24596) +- feat(clean): add progress bar (#25026) +- feat(cli): Add --env-file as alternative to --env (#24555) +- feat(cli/tools): add a subcommand `--hide-stacktraces` for test (#24095) +- feat(config): Support frozen lockfile config option in deno.json (#25100) +- feat(config/jsr): add license field (#25056) +- feat(coverage): add breadcrumbs to deno coverage `--html` report (#24860) +- feat(ext/node): rewrite crypto keys (#24463) +- feat(ext/node): support http2session.socket (#24786) +- feat(fetch): accept async iterables for body (#24623) +- feat(flags): improve help output and make `deno run` list tasks (#25108) +- feat(fmt): support CSS, SCSS, Sass and Less (#24870) +- feat(fmt): support HTML, Svelte, Vue, Astro and Angular (#25019) +- feat(fmt): support YAML (#24717) +- feat(FUTURE): terse lockfile (v4) (#25059) +- feat(install): change 'Add ...' message (#24949) +- feat(lint): Add lint for usage of node globals (with autofix) (#25048) +- feat(lsp): node specifier completions (#24904) +- feat(lsp): registry completions for import-mapped specifiers (#24792) +- feat(node): support `username` and `_password` in `.npmrc` file (#24793) +- feat(permissions): link to docs in permission prompt (#24948) +- feat(publish): error on missing license file (#25011) +- feat(publish): suggest importing `jsr:@std/` for `deno.land/std` urls (#25046) +- feat(serve): Opt-in parallelism for `deno serve` (#24920) +- feat(test): rename --allow-none to --permit-no-files (#24809) +- feat(unstable): ability to use a local copy of jsr packages (#25068) +- feat(unstable/fmt): move yaml formatting behind unstable flag (#24848) +- feat(upgrade): refresh output (#24911) +- feat(upgrade): support `deno upgrade 1.46.0` (#25096) +- feat(urlpattern): add ignoreCase option & hasRegExpGroups property, and fix + spec discrepancies (#24741) +- feat(watch): add watch paths to test subcommand (#24771) +- fix: `node:inspector` not being registered (#25007) +- fix: `rename` watch event missing (#24893) +- fix: actually add missing `node:readline/promises` module (#24772) +- fix: adapt to new jupyter runtime API and include session IDs (#24762) +- fix: add permission name when accessing a special file errors (#25085) +- fix: adjust suggestion for lockfile regeneration (#25107) +- fix: cache bust jsr meta file when version not found in dynamic branches + (#24928) +- fix: CFunctionInfo and CTypeInfo leaks (#24634) +- fix: clean up flag help output (#24686) +- fix: correct JSON config schema to show vendor option as stable (#25090) +- fix: dd-trace http message compat (#25021) +- fix: deserialize lockfile v3 straight (#25121) +- fix: Don't panic if fail to handle JS stack frame (#25122) +- fix: Don't panic if failed to add system certificate (#24823) +- fix: Don't shell out to `unzip` in deno upgrade/compile (#24926) +- fix: enable the reporting of parsing related problems when running deno lint + (#24332) +- fix: errors with CallSite methods (#24907) +- fix: include already seen deps in lockfile dep tracking (#24556) +- fix: log current version when using deno upgrade (#25079) +- fix: make `deno add` output more deterministic (#25083) +- fix: make vendor cache manifest more deterministic (#24658) +- fix: missing `emitWarning` import (#24587) +- fix: regressions around Error.prepareStackTrace (#24839) +- fix: stub `node:module.register()` (#24965) +- fix: support `npm:bindings` and `npm:callsites` packages (#24727) +- fix: unblock fsevents native module (#24542) +- fix: update deno_doc (#24972) +- fix: update dry run success message (#24885) +- fix: update lsp error message of 'relative import path' to 'use deno add' for + npm/jsr packages (#24524) +- fix: upgrade deno_core to 0.298.0 (#24709) +- fix: warn about import assertions when using typescript (#25135) +- fix(add): better error message providing scoped pkg missing leading `@` symbol + (#24961) +- fix(add): Better error message when missing npm specifier (#24970) +- fix(add): error when config file contains importMap field (#25115) +- fix(add): Handle packages without root exports (#25102) +- fix(add): Support dist tags in deno add (#24960) +- fix(cli): add NAPI support in standalone mode (#24642) +- fix(cli): Create child node_modules for conflicting dependency versions, + respect aliases in package.json (#24609) +- fix(cli): Respect implied BYONM from DENO_FUTURE in `deno task` (#24652) +- fix(cli): shorten examples in help text (#24374) +- fix(cli): support --watch when running cjs npm packages (#25038) +- fix(cli): Unhide publish subcommand help string (#24787) +- fix(cli): update permission prompt message for compiled binaries (#24081) +- fix(cli/init): broken link in deno init sample template (#24545) +- fix(compile): adhoc codesign mach-o by default (#24824) +- fix(compile): make output more deterministic (#25092) +- fix(compile): support workspace members importing other members (#24909) +- fix(compile/windows): handle cjs re-export of relative path with parent + component (#24795) +- fix(config): regression - should not discover npm workspace for nested + deno.json not in workspace (#24559) +- fix(cron): improve error message for invalid cron names (#24644) +- fix(docs): fix some deno.land/manual broken urls (#24557) +- fix(ext/console): Error Cause Not Inspect-Formatted when printed (#24526) +- fix(ext/console): render properties of Intl.Locale (#24827) +- fix(ext/crypto): respect offsets when writing into ab views in randomFillSync + (#24816) +- fix(ext/fetch): include TCP src/dst socket info in error messages (#24939) +- fix(ext/fetch): include URL and error details on fetch failures (#24910) +- fix(ext/fetch): respect authority from URL (#24705) +- fix(ext/fetch): use correct ALPN to proxies (#24696) +- fix(ext/fetch): use correct ALPN to socks5 proxies (#24817) +- fix(ext/http): correctly consume response body in `Deno.serve` (#24811) +- fix(ext/net): validate port in Deno.{connect,serve,listen} (#24399) +- fix(ext/node): add `CipherIv.setAutoPadding()` (#24940) +- fix(ext/node): add crypto.diffieHellman (#24938) +- fix(ext/node): client closing streaming request shouldn't terminate http + server (#24946) +- fix(ext/node): createBrotliCompress params (#24984) +- fix(ext/node): do not expose `self` global in node (#24637) +- fix(ext/node): don't concat set-cookie in ServerResponse.appendHeader (#25000) +- fix(ext/node): don't throw when calling PerformanceObserver.observe (#25036) +- fix(ext/node): ed25519 signing and cipheriv autopadding fixes (#24957) +- fix(ext/node): fix prismjs compatibiliy in Web Worker (#25062) +- fix(ext/node): handle node child_process with --v8-options flag (#24804) +- fix(ext/node): handle prefix mapping for IPv4-mapped IPv6 addresses (#24546) +- fix(ext/node): http request uploads of subarray of buffer should work (#24603) +- fix(ext/node): improve shelljs compat with managed npm execution (#24912) +- fix(ext/node): node:zlib coerces quality 10 to 9.5 (#24850) +- fix(ext/node): pass content-disposition header as string instead of bytes + (#25128) +- fix(ext/node): prevent panic in http2.connect with uppercase header names + (#24780) +- fix(ext/node): read correct CPU usage stats on Linux (#24732) +- fix(ext/node): rewrite X509Certificate resource and add `publicKey()` (#24988) +- fix(ext/node): stat.mode on windows (#24434) +- fix(ext/node): support ieee-p1363 ECDSA signatures and pss salt len (#24981) +- fix(ext/node): use pem private keys in createPublicKey (#24969) +- fix(ext/node/net): emit `error` before `close` when connection is refused + (#24656) +- fix(ext/web): make CompressionResource garbage collectable (#24884) +- fix(ext/web): make TextDecoderResource use cppgc (#24888) +- fix(ext/webgpu): assign missing `constants` property of shader about + `GPUDevice.createRenderPipeline[Async]` (#24803) +- fix(ext/webgpu): don't crash while constructing GPUOutOfMemoryError (#24807) +- fix(ext/webgpu): GPUDevice.createRenderPipelineAsync should return a Promise + (#24349) +- fix(ext/websocket): unhandled close rejection in WebsocketStream (#25125) +- fix(fmt): handle using stmt in for of stmt (#24834) +- fix(fmt): regression with pipe in code blocks in tables (#25098) +- fix(fmt): upgrade to dprint-plugin-markdown 0.17.4 (#25075) +- fix(fmt): was sometimes putting comments in front of commas in parameter lists + (#24650) +- fix(future): Emit `deno install` warning less often, suggest `deno install` in + error message (#24706) +- fix(http): Adjust hostname display for Windows when using 0.0.0.0 (#24698) +- fix(init): use bare specifier for `jsr:@std/assert` (#24581) +- fix(install): Properly handle dist tags when setting up node_modules (#24968) +- fix(lint): support linting tsx/jsx from stdin (#24955) +- fix(lsp): directly use file referrer when loading document (#24997) +- fix(lsp): don't always use byonm resolver when DENO_FUTURE=1 (#24865) +- fix(lsp): hang when caching failed (#24651) +- fix(lsp): import map lookup for jsr subpath auto import (#25025) +- fix(lsp): include scoped import map keys in completions (#25047) +- fix(lsp): resolve jsx import source with types mode (#25064) +- fix(lsp): rewrite import for 'infer return type' action (#24685) +- fix(lsp): scope attribution for asset documents (#24663) +- fix(lsp): support npm workspaces and fix some resolution issues (#24627) +- fix(node): better detection for when to surface node resolution errors + (#24653) +- fix(node): cjs pkg dynamically importing esm-only pkg fails (#24730) +- fix(node): Create additional pipes for child processes (#25016) +- fix(node): Fix `--allow-scripts` with no `deno.json` (#24533) +- fix(node): Fix node IPC serialization for objects with undefined values + (#24894) +- fix(node): revert invalid package target change (#24539) +- fix(node): Rework node:child_process IPC (#24763) +- fix(node): Run node compat tests listed in the `ignore` field (and fix the + ones that fail) (#24631) +- fix(node): support `tty.hasColors()` and `tty.getColorDepth()` (#24619) +- fix(node): support wildcards in package.json imports (#24794) +- fix(node/crypto): Assign publicKey and privateKey with let instead of const + (#24943) +- fix(node/fs): node:fs.read and write should accept typed arrays other than + Uint8Array (#25030) +- fix(node/fs): Use correct offset and length in node:fs.read and write (#25049) +- fix(node/fs/promises): watch should be async iterable (#24805) +- fix(node/http): wrong `req.url` value (#25081) +- fix(node/inspector): Session constructor should not throw (#25041) +- fix(node/timers/promises): add scheduler APIs (#24802) +- fix(node/tty): fix `tty.WriteStream.hasColor` with different args (#25094) +- fix(node/util): add missing `debug` alias of `debuglog` (#24944) +- fix(node/worker_threads): support `port.once()` (#24725) +- fix(npm): handle packages with only pre-released 0.0.0 versions (#24563) +- fix(npm): use start directory deno.json as "root deno.json config" in npm + workspace (#24538) +- fix(npmrc): skip loading .npmrc in home dir on permission error (#24758) +- fix(publish): show dirty files on dirty check failure (#24541) +- fix(publish): surface syntax errors when using --no-check (#24620) +- fix(publish): warn about missing license file (#24677) +- fix(publish): workspace included license file had incorrect path (#24747) +- fix(repl): Prevent panic on broken pipe (#21945) +- fix(runtime/windows): fix calculation of console size (#23873) +- fix(std/http2): release window capacity back to remote stream (#24576) +- fix(tls): print a warning if a system certificate can't be loaded (#25023) +- fix(types): Conform lib.deno_web.d.ts to lib.dom.d.ts and lib.webworker.d.ts + (#24599) +- fix(types): fix streams types (#24770) +- fix(unstable): move sloppy-import warnings to lint rule (#24710) +- fix(unstable): panic when running deno install with DENO_FUTURE=1 (#24866) +- fix(unstable/compile): handle byonm import in sub dir (#24755) +- fix(upgrade): better error message when check_exe fails (#25133) +- fix(upgrade): correctly compute latest version based on current release + channel (#25087) +- fix(upgrade): do not error if config in cwd invalid (#24689) +- fix(upgrade): fallback to Content-Length header for progress bar (#24923) +- fix(upgrade): return no RC versions if fetching fails (#25013) +- fix(upgrade): support RC release with --version flag (#25091) +- fix(upgrade): use proper version display (#25029) +- fix(urlpattern): correct typings for added APIs (#24881) +- fix(webgpu): Fix `GPUAdapter#isFallbackAdapter` and `GPUAdapter#info` + properties (#24914) +- fix(workspace): do not resolve to self for npm pkg depending on matching req + (#24591) +- fix(workspace): support resolving bare specifiers to npm pkgs within a + workspace (#24611) +- fix(workspaces/publish): include the license file from the workspace root if + not in pkg (#24714) +- perf: skip saving to emit cache after first failure (#24896) +- perf: update deno_ast to 0.41 (#24819) +- perf: update deno_doc (#24700) +- perf(ext/crypto): make randomUUID() 5x faster (#24510) +- perf(ext/fetch): speed up `resp.clone()` (#24812) +- perf(ext/http): Reduce size of `ResponseBytesInner` (#24840) +- perf(ext/node): improve `Buffer` from string performance (#24567) +- perf(ext/node): optimize fs.exists[Sync] (#24613) +- perf(lsp): remove fallback config scopes for workspace folders (#24868) +- refactor: `version` module exports a single const struct (#25014) +- refactor: decouple node resolution from deno_core (#24724) +- refactor: move importMap with imports/scopes diagnostic to deno_config + (#24553) +- refactor: remove version::is_canary(), use ReleaseChannel instead (#25053) +- refactor: show release channel in `deno --version` (#25061) +- refactor: update to deno_config 0.25 (#24645) +- refactor: update to use deno_package_json (#24688) +- refactor(ext/node): create separate ops for node:http module (#24788) +- refactor(fetch): reimplement fetch with hyper instead of reqwest (#24237) +- refactor(lint): move reporters to separate module (#24757) +- refactor(node): internally add `.code()` to node resolution errors (#24610) +- refactor(upgrade): cleanup pass (#24954) +- refactor(upgrade): make fetching latest version async (#24919) +- Reland "fix: CFunctionInfo and CTypeInfo leaks (#24634)" (#24692) +- Reland "refactor(fetch): reimplement fetch with hyper instead of reqwest" + (#24593) + ### 1.45.5 / 2024.07.31 - fix(cli): Unhide publish subcommand help string (#24787) diff --git a/bench_util/Cargo.toml b/bench_util/Cargo.toml index 7f2d87eac8..eea9c69a3c 100644 --- a/bench_util/Cargo.toml +++ b/bench_util/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_bench_util" -version = "0.158.0" +version = "0.168.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 920f0d795d..0065a2cbd0 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno" -version = "1.46.0-rc.2" +version = "2.0.3" authors.workspace = true default-run = "deno" edition.workspace = true @@ -38,6 +38,11 @@ path = "./bench/lsp_bench_standalone.rs" [features] default = ["upgrade", "__vendored_zlib_ng"] +# A feature that enables heap profiling with dhat on Linux. +# 1. Compile with `cargo build --profile=release-with-debug --features=dhat-heap` +# 2. Run the executable. It will output a dhat-heap.json file. +# 3. Open the json file in https://nnethercote.github.io/dh_view/dh_view.html +dhat-heap = ["dhat"] # A feature that enables the upgrade subcommand and the background check for # available updates (of deno binary). This is typically disabled for (Linux) # distribution packages. @@ -65,44 +70,44 @@ winres.workspace = true [dependencies] deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] } deno_cache_dir = { workspace = true } -deno_config = { version = "=0.30.0", features = ["workspace", "sync"] } +deno_config = { version = "=0.37.2", features = ["workspace", "sync"] } deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } -deno_doc = { version = "0.146.0", features = ["html", "syntect"] } -deno_emit = "=0.44.0" -deno_graph = { version = "=0.81.2" } -deno_lint = { version = "=0.63.1", features = ["docs"] } +deno_doc = { version = "0.154.0", default-features = false, features = ["rust", "html", "syntect"] } +deno_graph = { version = "=0.83.4" } +deno_lint = { version = "=0.67.0", features = ["docs"] } deno_lockfile.workspace = true -deno_npm = "=0.23.0" +deno_npm.workspace = true deno_package_json.workspace = true +deno_path_util.workspace = true +deno_resolver.workspace = true deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] } -deno_semver = "=0.5.10" -deno_task_shell = "=0.17.0" +deno_semver.workspace = true +deno_task_shell = "=0.18.1" deno_terminal.workspace = true -eszip = "=0.75.0" -libsui = "0.3.0" -napi_sym.workspace = true +libsui = "0.4.0" node_resolver.workspace = true +anstream = "0.6.14" async-trait.workspace = true -base32.workspace = true base64.workspace = true bincode = "=1.3.3" bytes.workspace = true cache_control.workspace = true chrono = { workspace = true, features = ["now"] } -clap = { version = "=4.5.13", features = ["env", "string", "wrap_help"] } -clap_complete = "=4.5.12" +clap = { version = "=4.5.16", features = ["env", "string", "wrap_help", "error-context"] } +clap_complete = "=4.5.24" clap_complete_fig = "=4.5.2" -color-print = "0.3.5" +color-print.workspace = true console_static_text.workspace = true -dashmap = "5.5.3" +dashmap.workspace = true data-encoding.workspace = true +dhat = { version = "0.3.3", optional = true } dissimilar = "=1.0.4" dotenvy = "0.15.7" -dprint-plugin-json = "=0.19.3" -dprint-plugin-jupyter = "=0.1.3" -dprint-plugin-markdown = "=0.17.5" -dprint-plugin-typescript = "=0.91.6" +dprint-plugin-json = "=0.19.4" +dprint-plugin-jupyter = "=0.1.5" +dprint-plugin-markdown = "=0.17.8" +dprint-plugin-typescript = "=0.93.0" env_logger = "=0.10.0" fancy-regex = "=0.10.0" faster-hex.workspace = true @@ -114,17 +119,17 @@ http.workspace = true http-body.workspace = true http-body-util.workspace = true hyper-util.workspace = true -import_map = { version = "=0.20.0", features = ["ext"] } +import_map = { version = "=0.20.1", features = ["ext"] } indexmap.workspace = true -jsonc-parser.workspace = true +jsonc-parser = { workspace = true, features = ["cst", "serde"] } jupyter_runtime = { package = "runtimelib", version = "=0.14.0" } lazy-regex.workspace = true libc.workspace = true libz-sys.workspace = true log = { workspace = true, features = ["serde"] } lsp-types.workspace = true -malva = "=0.9.0" -markup_fmt = "=0.12.0" +malva = "=0.11.0" +markup_fmt = "=0.14.0" memmem.workspace = true monch.workspace = true notify.workspace = true @@ -134,7 +139,7 @@ p256.workspace = true pathdiff = "0.2.1" percent-encoding.workspace = true phf.workspace = true -pretty_yaml = "=0.4.0" +pretty_yaml = "=0.5.0" quick-junit = "^0.3.5" rand = { workspace = true, features = ["small_rng"] } regex.workspace = true @@ -155,6 +160,7 @@ thiserror.workspace = true tokio.workspace = true tokio-util.workspace = true tower-lsp.workspace = true +tracing = { version = "0.1", features = ["log", "default"] } twox-hash.workspace = true typed-arena = "=2.0.2" uuid = { workspace = true, features = ["serde"] } diff --git a/cli/args/deno_json.rs b/cli/args/deno_json.rs index cbc33aa0b2..e9ab0189f5 100644 --- a/cli/args/deno_json.rs +++ b/cli/args/deno_json.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; +use deno_config::deno_json::TsConfigForEmit; use deno_core::serde_json; use deno_semver::jsr::JsrDepPackageReq; use deno_semver::jsr::JsrPackageReqReference; @@ -105,3 +106,18 @@ fn values_to_set<'a>( } entries } + +pub fn check_warn_tsconfig(ts_config: &TsConfigForEmit) { + if let Some(ignored_options) = &ts_config.maybe_ignored_options { + log::warn!("{}", ignored_options); + } + let serde_json::Value::Object(obj) = &ts_config.ts_config.0 else { + return; + }; + if obj.get("experimentalDecorators") == Some(&serde_json::Value::Bool(true)) { + log::warn!( + "{} experimentalDecorators compiler option is deprecated and may be removed at any time", + deno_runtime::colors::yellow("Warning"), + ); + } +} diff --git a/cli/args/flags.rs b/cli/args/flags.rs index a273d8b370..235dd53a42 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1,29 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use clap::builder::styling::AnsiColor; -use clap::builder::FalseyValueParser; -use clap::value_parser; -use clap::Arg; -use clap::ArgAction; -use clap::ArgMatches; -use clap::ColorChoice; -use clap::Command; -use clap::ValueHint; -use deno_config::glob::FilePatterns; -use deno_config::glob::PathOrPatternSet; -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::AnyError; -use deno_core::normalize_path; -use deno_core::resolve_url_or_path; -use deno_core::url::Url; -use deno_graph::GraphKind; -use deno_runtime::deno_permissions::parse_sys_kind; -use deno_runtime::deno_permissions::PermissionsOptions; -use log::debug; -use log::Level; -use serde::Deserialize; -use serde::Serialize; +use std::borrow::Cow; use std::collections::HashSet; use std::env; use std::ffi::OsString; @@ -35,11 +12,40 @@ use std::path::Path; use std::path::PathBuf; use std::str::FromStr; +use clap::builder::styling::AnsiColor; +use clap::builder::FalseyValueParser; +use clap::error::ErrorKind; +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::ColorChoice; +use clap::Command; +use clap::ValueHint; +use color_print::cstr; +use deno_config::deno_json::NodeModulesDirMode; +use deno_config::glob::FilePatterns; +use deno_config::glob::PathOrPatternSet; +use deno_core::anyhow::bail; +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_core::resolve_url_or_path; +use deno_core::url::Url; +use deno_graph::GraphKind; +use deno_path_util::normalize_path; +use deno_path_util::url_to_file_path; +use deno_runtime::deno_permissions::PermissionsOptions; +use deno_runtime::deno_permissions::SysDescriptor; +use log::debug; +use log::Level; +use serde::Deserialize; +use serde::Serialize; + use crate::args::resolve_no_prompt; use crate::util::fs::canonicalize_path; use super::flags_net; -use super::DENO_FUTURE; +use super::jsr_url; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub enum ConfigFlag { @@ -81,6 +87,7 @@ impl FileFlags { #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct AddFlags { pub packages: Vec, + pub dev: bool, } #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -97,13 +104,6 @@ pub struct BenchFlags { pub watch: Option, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct BundleFlags { - pub source_file: String, - pub out_file: Option, - pub watch: Option, -} - #[derive(Clone, Debug, Eq, PartialEq)] pub struct CacheFlags { pub files: Vec, @@ -112,6 +112,8 @@ pub struct CacheFlags { #[derive(Clone, Debug, Eq, PartialEq)] pub struct CheckFlags { pub files: Vec, + pub doc: bool, + pub doc_only: bool, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -206,10 +208,7 @@ pub struct FmtFlags { pub prose_wrap: Option, pub no_semicolons: Option, pub watch: Option, - pub unstable_css: bool, - pub unstable_html: bool, pub unstable_component: bool, - pub unstable_yaml: bool, } impl FmtFlags { @@ -243,14 +242,19 @@ pub struct InstallFlagsGlobal { #[derive(Clone, Debug, Eq, PartialEq)] pub enum InstallKind { - #[allow(unused)] - Local(Option), + Local(InstallFlagsLocal), Global(InstallFlagsGlobal), } +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum InstallFlagsLocal { + Add(AddFlags), + TopLevel, + Entrypoints(Vec), +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct InstallFlags { - pub global: bool, pub kind: InstallKind, } @@ -274,14 +278,12 @@ pub struct UninstallFlagsGlobal { #[derive(Clone, Debug, Eq, PartialEq)] pub enum UninstallKind { - #[allow(unused)] - Local, + Local(RemoveFlags), Global(UninstallFlagsGlobal), } #[derive(Clone, Debug, Eq, PartialEq)] pub struct UninstallFlags { - pub global: bool, pub kind: UninstallKind, } @@ -296,7 +298,6 @@ pub struct LintFlags { pub json: bool, pub compact: bool, pub watch: Option, - pub ext: Option, } impl LintFlags { @@ -376,6 +377,7 @@ pub struct WatchFlagsWithPaths { pub struct TaskFlags { pub cwd: Option, pub task: Option, + pub is_run: bool, } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] @@ -395,7 +397,7 @@ pub struct TestFlags { pub clean: bool, pub fail_fast: Option, pub files: FileFlags, - pub allow_none: bool, + pub permit_no_files: bool, pub filter: Option, pub shuffle: Option, pub concurrent_jobs: Option, @@ -417,13 +419,6 @@ pub struct UpgradeFlags { pub version_or_hash_or_channel: Option, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct VendorFlags { - pub specifiers: Vec, - pub output_path: Option, - pub force: bool, -} - #[derive(Clone, Debug, Eq, PartialEq)] pub struct PublishFlags { pub token: Option, @@ -443,7 +438,7 @@ pub enum DenoSubcommand { Add(AddFlags), Remove(RemoveFlags), Bench(BenchFlags), - Bundle(BundleFlags), + Bundle, Cache(CacheFlags), Check(CheckFlags), Clean, @@ -468,7 +463,7 @@ pub enum DenoSubcommand { Test(TestFlags), Types, Upgrade(UpgradeFlags), - Vendor(VendorFlags), + Vendor, Publish(PublishFlags), Help(HelpFlags), } @@ -551,7 +546,10 @@ pub enum CaData { #[derive(Clone, Debug, Eq, PartialEq, Default)] pub struct LifecycleScriptsConfig { pub allowed: PackagesAllowedScripts, - pub initial_cwd: Option, + pub initial_cwd: PathBuf, + pub root_dir: PathBuf, + /// Part of an explicit `deno install` + pub explicit_install: bool, } #[derive(Debug, Clone, Eq, PartialEq, Default)] @@ -575,13 +573,23 @@ fn parse_packages_allowed_scripts(s: &str) -> Result { Clone, Default, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, )] pub struct UnstableConfig { + // TODO(bartlomieju): remove in Deno 2.5 pub legacy_flag_enabled: bool, // --unstable - pub bare_node_builtins: bool, // --unstable-bare-node-builts - pub byonm: bool, + pub bare_node_builtins: bool, + pub detect_cjs: bool, pub sloppy_imports: bool, pub features: Vec, // --unstabe-kv --unstable-cron } +#[derive(Clone, Debug, Eq, PartialEq, Default)] +pub struct InternalFlags { + /// Used when the language server is configured with an + /// explicit cache option. + pub cache_path: Option, + /// Only reads to the lockfile instead of writing to it. + pub lockfile_skip_write: bool, +} + #[derive(Clone, Debug, Eq, PartialEq, Default)] pub struct Flags { /// Vector of CLI arguments - these are user script arguments, all Deno @@ -593,17 +601,16 @@ pub struct Flags { pub ca_stores: Option>, pub ca_data: Option, pub cache_blocklist: Vec, - /// This is not exposed as an option in the CLI, it is used internally when - /// the language server is configured with an explicit cache option. - pub cache_path: Option, pub cached_only: bool, pub type_check_mode: TypeCheckMode, pub config_flag: ConfigFlag, - pub node_modules_dir: Option, + pub node_modules_dir: Option, pub vendor: Option, pub enable_op_summary_metrics: bool, pub enable_testing_features: bool, pub ext: Option, + /// Flags that aren't exposed in the CLI, but are used internally. + pub internal: InternalFlags, pub ignore: Vec, pub import_map_path: Option, pub env_file: Option, @@ -611,8 +618,6 @@ pub struct Flags { pub inspect_wait: Option, pub inspect: Option, pub location: Option, - // TODO(bartlomieju): deprecated, to be removed in Deno 2. - pub lock_write: bool, pub lock: Option, pub log_level: Option, pub no_remote: bool, @@ -634,8 +639,6 @@ pub struct PermissionFlags { pub allow_all: bool, pub allow_env: Option>, pub deny_env: Option>, - pub allow_hrtime: bool, - pub deny_hrtime: bool, pub allow_ffi: Option>, pub deny_ffi: Option>, pub allow_net: Option>, @@ -649,6 +652,7 @@ pub struct PermissionFlags { pub allow_write: Option>, pub deny_write: Option>, pub no_prompt: bool, + pub allow_import: Option>, } impl PermissionFlags { @@ -656,8 +660,6 @@ impl PermissionFlags { self.allow_all || self.allow_env.is_some() || self.deny_env.is_some() - || self.allow_hrtime - || self.deny_hrtime || self.allow_ffi.is_some() || self.deny_ffi.is_some() || self.allow_net.is_some() @@ -670,66 +672,98 @@ impl PermissionFlags { || self.deny_sys.is_some() || self.allow_write.is_some() || self.deny_write.is_some() + || self.allow_import.is_some() } - pub fn to_options( - &self, - // will be None when `deno compile` can't resolve the cwd - initial_cwd: Option<&Path>, - ) -> Result { - fn convert_option_str_to_path_buf( - flag: &Option>, - initial_cwd: Option<&Path>, - ) -> Result>, AnyError> { - let Some(paths) = &flag else { - return Ok(None); - }; - - let mut new_paths = Vec::with_capacity(paths.len()); - for path in paths { - if let Some(initial_cwd) = initial_cwd { - new_paths.push(initial_cwd.join(path)) - } else { - let path = PathBuf::from(path); - if path.is_absolute() { - new_paths.push(path); - } else { - bail!("Could not resolve relative permission path '{}' when current working directory could not be resolved.", path.display()) - } - } + pub fn to_options(&self, cli_arg_urls: &[Cow]) -> PermissionsOptions { + fn handle_allow( + allow_all: bool, + value: Option, + ) -> Option { + if allow_all { + assert!(value.is_none()); + Some(T::default()) + } else { + value } - Ok(Some(new_paths)) } - Ok(PermissionsOptions { + fn handle_imports( + cli_arg_urls: &[Cow], + imports: Option>, + ) -> Option> { + if imports.is_some() { + return imports; + } + + let builtin_allowed_import_hosts = [ + "jsr.io:443", + "deno.land:443", + "esm.sh:443", + "cdn.jsdelivr.net:443", + "raw.githubusercontent.com:443", + "gist.githubusercontent.com:443", + ]; + + let mut imports = + Vec::with_capacity(builtin_allowed_import_hosts.len() + 1); + imports + .extend(builtin_allowed_import_hosts.iter().map(|s| s.to_string())); + + // also add the JSR_URL env var + if let Some(jsr_host) = allow_import_host_from_url(jsr_url()) { + imports.push(jsr_host); + } + // include the cli arg urls + for url in cli_arg_urls { + if let Some(host) = allow_import_host_from_url(url) { + imports.push(host); + } + } + + Some(imports) + } + + PermissionsOptions { allow_all: self.allow_all, - allow_env: self.allow_env.clone(), + allow_env: handle_allow(self.allow_all, self.allow_env.clone()), deny_env: self.deny_env.clone(), - allow_hrtime: self.allow_hrtime, - deny_hrtime: self.deny_hrtime, - allow_net: self.allow_net.clone(), + allow_net: handle_allow(self.allow_all, self.allow_net.clone()), deny_net: self.deny_net.clone(), - allow_ffi: convert_option_str_to_path_buf(&self.allow_ffi, initial_cwd)?, - deny_ffi: convert_option_str_to_path_buf(&self.deny_ffi, initial_cwd)?, - allow_read: convert_option_str_to_path_buf( - &self.allow_read, - initial_cwd, - )?, - deny_read: convert_option_str_to_path_buf(&self.deny_read, initial_cwd)?, - allow_run: self.allow_run.clone(), + allow_ffi: handle_allow(self.allow_all, self.allow_ffi.clone()), + deny_ffi: self.deny_ffi.clone(), + allow_read: handle_allow(self.allow_all, self.allow_read.clone()), + deny_read: self.deny_read.clone(), + allow_run: handle_allow(self.allow_all, self.allow_run.clone()), deny_run: self.deny_run.clone(), - allow_sys: self.allow_sys.clone(), + allow_sys: handle_allow(self.allow_all, self.allow_sys.clone()), deny_sys: self.deny_sys.clone(), - allow_write: convert_option_str_to_path_buf( - &self.allow_write, - initial_cwd, - )?, - deny_write: convert_option_str_to_path_buf( - &self.deny_write, - initial_cwd, - )?, + allow_write: handle_allow(self.allow_all, self.allow_write.clone()), + deny_write: self.deny_write.clone(), + allow_import: handle_imports( + cli_arg_urls, + handle_allow(self.allow_all, self.allow_import.clone()), + ), prompt: !resolve_no_prompt(self), - }) + } + } +} + +/// Gets the --allow-import host from the provided url +fn allow_import_host_from_url(url: &Url) -> Option { + let host = url.host()?; + if let Some(port) = url.port() { + Some(format!("{}:{}", host, port)) + } else { + use deno_core::url::Host::*; + match host { + Domain(domain) if domain == "jsr.io" && url.scheme() == "https" => None, + _ => match url.scheme() { + "https" => Some(format!("{}:443", host)), + "http" => Some(format!("{}:80", host)), + _ => None, + }, + } } } @@ -920,12 +954,15 @@ impl Flags { _ => {} } - if self.permissions.allow_hrtime { - args.push("--allow-hrtime".to_string()); - } - - if self.permissions.deny_hrtime { - args.push("--deny-hrtime".to_string()); + match &self.permissions.allow_import { + Some(allowlist) if allowlist.is_empty() => { + args.push("--allow-import".to_string()); + } + Some(allowlist) => { + let s = format!("--allow-import={}", allowlist.join(",")); + args.push(s); + } + _ => {} } args @@ -975,7 +1012,7 @@ impl Flags { if module_specifier.scheme() == "file" || module_specifier.scheme() == "npm" { - if let Ok(p) = module_specifier.to_file_path() { + if let Ok(p) = url_to_file_path(&module_specifier) { Some(vec![p.parent().unwrap().to_path_buf()]) } else { Some(vec![current_dir.to_path_buf()]) @@ -1011,8 +1048,6 @@ impl Flags { pub fn has_permission_in_argv(&self) -> bool { self.argv.iter().any(|arg| { arg == "--allow-all" - || arg == "--allow-hrtime" - || arg == "--deny-hrtime" || arg.starts_with("--allow-env") || arg.starts_with("--deny-env") || arg.starts_with("--allow-ffi") @@ -1033,14 +1068,14 @@ impl Flags { #[inline(always)] fn allow_all(&mut self) { self.permissions.allow_all = true; - self.permissions.allow_read = Some(vec![]); - self.permissions.allow_env = Some(vec![]); - self.permissions.allow_net = Some(vec![]); - self.permissions.allow_run = Some(vec![]); - self.permissions.allow_write = Some(vec![]); - self.permissions.allow_sys = Some(vec![]); - self.permissions.allow_ffi = Some(vec![]); - self.permissions.allow_hrtime = true; + self.permissions.allow_read = None; + self.permissions.allow_env = None; + self.permissions.allow_net = None; + self.permissions.allow_run = None; + self.permissions.allow_write = None; + self.permissions.allow_sys = None; + self.permissions.allow_ffi = None; + self.permissions.allow_import = None; } pub fn resolve_watch_exclude_set( @@ -1054,14 +1089,6 @@ impl Flags { }), .. }) - | DenoSubcommand::Bundle(BundleFlags { - watch: - Some(WatchFlags { - exclude: excluded_paths, - .. - }), - .. - }) | DenoSubcommand::Bench(BenchFlags { watch: Some(WatchFlags { @@ -1107,12 +1134,13 @@ impl Flags { } } -static ENV_VARIABLES_HELP: &str = color_print::cstr!( +static ENV_VARIABLES_HELP: &str = cstr!( r#"Environment variables: +Docs: https://docs.deno.com/go/env-vars + DENO_AUTH_TOKENS A semi-colon separated list of bearer tokens and hostnames to use when fetching remote modules from private repositories (e.g. "abcde12345@deno.land;54321edcba@github.com") - DENO_FUTURE Set to "1" to enable APIs that will take effect in Deno 2 DENO_CERT Load certificate authorities from PEM encoded file DENO_DIR Set the cache directory DENO_INSTALL_ROOT Set deno install's output directory @@ -1132,7 +1160,7 @@ static ENV_VARIABLES_HELP: &str = color_print::cstr!( NPM_CONFIG_REGISTRY URL to use for the npm registry."# ); -static DENO_HELP: &str = color_print::cstr!( +static DENO_HELP: &str = cstr!( "Deno: A modern JavaScript and TypeScript runtime Usage: {usage} @@ -1150,7 +1178,7 @@ static DENO_HELP: &str = color_print::cstr!( Dependency management: add Add dependencies - deno add @std/assert | deno add npm:express + deno add jsr:@std/assert | deno add npm:express install Install script as an executable uninstall Uninstall a script previously installed with deno install remove Remove dependencies from the configuration file @@ -1158,8 +1186,8 @@ static DENO_HELP: &str = color_print::cstr!( Tooling: bench Run benchmarks deno bench bench.ts - cache Cache the dependencies check Type-check the dependencies + clean Remove the cache directory compile Compile the script into a self contained executable deno compile main.ts | deno compile --target=x86_64-unknown-linux-gnu coverage Print coverage reports @@ -1175,7 +1203,7 @@ static DENO_HELP: &str = color_print::cstr!( deno test | deno test test.ts publish Publish the current working directory's package or workspace upgrade Upgrade deno executable to given version - deno upgrade | deno upgrade --version=1.45.0 | deno upgrade --canary + deno upgrade | deno upgrade 1.45.0 | deno upgrade canary {after-help} Docs: https://docs.deno.com @@ -1187,7 +1215,32 @@ static DENO_HELP: &str = color_print::cstr!( /// Main entry point for parsing deno's command line flags. pub fn flags_from_vec(args: Vec) -> clap::error::Result { let mut app = clap_root(); - let mut matches = app.try_get_matches_from_mut(&args)?; + let mut matches = + app + .try_get_matches_from_mut(&args) + .map_err(|mut e| match e.kind() { + ErrorKind::MissingRequiredArgument => { + if let Some(clap::error::ContextValue::Strings(s)) = + e.get(clap::error::ContextKind::InvalidArg) + { + if s.len() == 1 + && s[0] == "--global" + && args.iter().any(|arg| arg == "install") + { + e.insert( + clap::error::ContextKind::Usage, + clap::error::ContextValue::StyledStr( + "Note: Permission flags can only be used in a global setting" + .into(), + ), + ); + } + } + + e + } + _ => e, + })?; let mut flags = Flags::default(); @@ -1214,28 +1267,7 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { .get_arguments() .any(|arg| arg.get_id().as_str() == "unstable") { - subcommand = subcommand - .mut_arg("unstable", |arg| { - let new_help = arg - .get_help() - .unwrap() - .to_string() - .split_once("\n") - .unwrap() - .0 - .to_string(); - arg.help_heading(UNSTABLE_HEADING).help(new_help) - }) - .mut_args(|arg| { - // long_help here is being used as a metadata, see unstable args definition - if arg.get_help_heading() == Some(UNSTABLE_HEADING) - && arg.get_long_help().is_some() - { - arg.hide(false) - } else { - arg - } - }); + subcommand = enable_unstable(subcommand); } help_parse(&mut flags, subcommand); @@ -1247,51 +1279,100 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { app }; + help_parse(&mut flags, subcommand); + return Ok(flags); + } else if let Some(help_subcommand_matches) = + matches.subcommand_matches("help") + { + app.build(); + let subcommand = + if let Some(sub) = help_subcommand_matches.subcommand_name() { + app.find_subcommand(sub).unwrap().clone() + } else { + app + }; + help_parse(&mut flags, subcommand); return Ok(flags); } if let Some((subcommand, mut m)) = matches.remove_subcommand() { + let pre_subcommand_arg = app + .get_arguments() + .filter(|arg| !arg.is_global_set()) + .find(|arg| { + matches + .value_source(arg.get_id().as_str()) + .is_some_and(|value| value == clap::parser::ValueSource::CommandLine) + }) + .map(|arg| { + format!( + "--{}", + arg.get_long().unwrap_or_else(|| arg.get_id().as_str()) + ) + }); + + if let Some(arg) = pre_subcommand_arg { + let usage = app.find_subcommand_mut(&subcommand).unwrap().render_usage(); + + let mut err = + clap::error::Error::new(ErrorKind::UnknownArgument).with_cmd(&app); + err.insert( + clap::error::ContextKind::InvalidArg, + clap::error::ContextValue::String(arg.clone()), + ); + + let valid = app.get_styles().get_valid(); + + let styled_suggestion = clap::builder::StyledStr::from(format!( + "'{}{subcommand} {arg}{}' exists", + valid.render(), + valid.render_reset() + )); + + err.insert( + clap::error::ContextKind::Suggested, + clap::error::ContextValue::StyledStrs(vec![styled_suggestion]), + ); + err.insert( + clap::error::ContextKind::Usage, + clap::error::ContextValue::StyledStr(usage), + ); + + return Err(err); + } + match subcommand.as_str() { - "add" => add_parse(&mut flags, &mut m), + "add" => add_parse(&mut flags, &mut m)?, "remove" => remove_parse(&mut flags, &mut m), - "bench" => bench_parse(&mut flags, &mut m), + "bench" => bench_parse(&mut flags, &mut m)?, "bundle" => bundle_parse(&mut flags, &mut m), - "cache" => cache_parse(&mut flags, &mut m), - "check" => check_parse(&mut flags, &mut m), + "cache" => cache_parse(&mut flags, &mut m)?, + "check" => check_parse(&mut flags, &mut m)?, "clean" => clean_parse(&mut flags, &mut m), - "compile" => compile_parse(&mut flags, &mut m), + "compile" => compile_parse(&mut flags, &mut m)?, "completions" => completions_parse(&mut flags, &mut m, app), - "coverage" => coverage_parse(&mut flags, &mut m), - "doc" => doc_parse(&mut flags, &mut m), - "eval" => eval_parse(&mut flags, &mut m), - "fmt" => fmt_parse(&mut flags, &mut m), + "coverage" => coverage_parse(&mut flags, &mut m)?, + "doc" => doc_parse(&mut flags, &mut m)?, + "eval" => eval_parse(&mut flags, &mut m)?, + "fmt" => fmt_parse(&mut flags, &mut m)?, "init" => init_parse(&mut flags, &mut m), - "info" => info_parse(&mut flags, &mut m), - "install" => install_parse(&mut flags, &mut m), + "info" => info_parse(&mut flags, &mut m)?, + "install" => install_parse(&mut flags, &mut m)?, "json_reference" => json_reference_parse(&mut flags, &mut m, app), "jupyter" => jupyter_parse(&mut flags, &mut m), - "lint" => lint_parse(&mut flags, &mut m), + "lint" => lint_parse(&mut flags, &mut m)?, "lsp" => lsp_parse(&mut flags, &mut m), - "repl" => repl_parse(&mut flags, &mut m), + "repl" => repl_parse(&mut flags, &mut m)?, "run" => run_parse(&mut flags, &mut m, app, false)?, "serve" => serve_parse(&mut flags, &mut m, app)?, "task" => task_parse(&mut flags, &mut m), - "test" => test_parse(&mut flags, &mut m), + "test" => test_parse(&mut flags, &mut m)?, "types" => types_parse(&mut flags, &mut m), "uninstall" => uninstall_parse(&mut flags, &mut m), "upgrade" => upgrade_parse(&mut flags, &mut m), "vendor" => vendor_parse(&mut flags, &mut m), "publish" => publish_parse(&mut flags, &mut m), - "help" => { - let subcommand = if let Some((sub, _)) = matches.remove_subcommand() { - app.find_subcommand(sub).unwrap().clone() - } else { - app - }; - - help_parse(&mut flags, subcommand) - } _ => unreachable!(), } } else { @@ -1321,6 +1402,31 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { Ok(flags) } +fn enable_unstable(command: Command) -> Command { + command + .mut_arg("unstable", |arg| { + let new_help = arg + .get_help() + .unwrap() + .to_string() + .split_once("\n") + .unwrap() + .0 + .to_string(); + arg.help_heading(UNSTABLE_HEADING).help(new_help) + }) + .mut_args(|arg| { + // long_help here is being used as a metadata, see unstable args definition + if arg.get_help_heading() == Some(UNSTABLE_HEADING) + && arg.get_long_help().is_some() + { + arg.hide(false) + } else { + arg + } + }) +} + macro_rules! heading { ($($name:ident = $title:expr),+; $total:literal) => { $(const $name: &str = $title;)+ @@ -1373,12 +1479,7 @@ fn help_parse(flags: &mut Flags, mut subcommand: Command) { for (mut i, (arg, heading)) in args.into_iter().enumerate() { if let Some(heading) = heading { let heading_i = HEADING_ORDER.iter().position(|h| h == &heading).unwrap(); - i += (if heading == UNSTABLE_HEADING { - // ensures the unstable section is always last - 50 - } else { - heading_i - }) * 100; + i += heading_i * 100; } subcommand = subcommand.mut_arg(arg, |arg| arg.display_order(i)); @@ -1411,14 +1512,7 @@ where fn handle_repl_flags(flags: &mut Flags, repl_flags: ReplFlags) { // If user runs just `deno` binary we enter REPL and allow all permissions. if repl_flags.is_default_command { - flags.permissions.allow_net = Some(vec![]); - flags.permissions.allow_env = Some(vec![]); - flags.permissions.allow_run = Some(vec![]); - flags.permissions.allow_read = Some(vec![]); - flags.permissions.allow_sys = Some(vec![]); - flags.permissions.allow_write = Some(vec![]); - flags.permissions.allow_ffi = Some(vec![]); - flags.permissions.allow_hrtime = true; + flags.allow_all(); } flags.subcommand = DenoSubcommand::Repl(repl_flags); } @@ -1435,7 +1529,7 @@ pub fn clap_root() -> Command { ); run_args(Command::new("deno"), true) - .args(unstable_args(UnstableArgsConfig::ResolutionAndRuntime)) + .with_unstable_args(UnstableArgsConfig::ResolutionAndRuntime) .next_line_help(false) .bin_name("deno") .styles( @@ -1507,11 +1601,7 @@ pub fn clap_root() -> Command { .subcommand(fmt_subcommand()) .subcommand(init_subcommand()) .subcommand(info_subcommand()) - .subcommand(if *DENO_FUTURE { - future_install_subcommand() - } else { - install_subcommand() - }) + .subcommand(install_subcommand()) .subcommand(json_reference_subcommand()) .subcommand(jupyter_subcommand()) .subcommand(uninstall_subcommand()) @@ -1541,54 +1631,66 @@ fn command( ) -> Command { Command::new(name) .about(about) - .args(unstable_args(unstable_args_config)) + .with_unstable_args(unstable_args_config) } fn help_subcommand(app: &Command) -> Command { command("help", None, UnstableArgsConfig::None) - .hide(true) + .disable_version_flag(true) .disable_help_subcommand(true) .subcommands(app.get_subcommands().map(|command| { Command::new(command.get_name().to_owned()) - .hide(true) .disable_help_flag(true) .disable_version_flag(true) })) } +fn add_dev_arg() -> Arg { + Arg::new("dev") + .long("dev") + .short('D') + .help("Add as a dev dependency") + .long_help("Add the package as a dev dependency. Note: This only applies when adding to a `package.json` file.") + .action(ArgAction::SetTrue) +} + fn add_subcommand() -> Command { command( "add", - "Add dependencies to the configuration file. - - deno add @std/path + cstr!( + "Add dependencies to your configuration file. + deno add jsr:@std/path You can add multiple dependencies at once: - deno add @std/path @std/assert -", + deno add jsr:@std/path jsr:@std/assert" + ), UnstableArgsConfig::None, ) .defer(|cmd| { - cmd.arg( - Arg::new("packages") - .help("List of packages to add") - .required_unless_present("help") - .num_args(1..) - .action(ArgAction::Append), - ) + cmd + .arg( + Arg::new("packages") + .help("List of packages to add") + .required_unless_present("help") + .num_args(1..) + .action(ArgAction::Append), + ) + .arg(add_dev_arg()) + .arg(allow_scripts_arg()) }) } fn remove_subcommand() -> Command { command( "remove", - "Remove dependencies from the configuration file. - - deno remove @std/path + cstr!( + "Remove dependencies from the configuration file. + deno remove @std/path You can remove multiple dependencies at once: deno remove @std/path @std/assert -", +" + ), UnstableArgsConfig::None, ) .defer(|cmd| { @@ -1605,19 +1707,19 @@ You can remove multiple dependencies at once: fn bench_subcommand() -> Command { command( "bench", - "Run benchmarks using Deno's built-in bench tool. + cstr!("Run benchmarks using Deno's built-in bench tool. -Evaluate the given modules, run all benches declared with 'Deno.bench()' -and report results to standard output: - deno bench src/fetch_bench.ts src/signal_bench.ts +Evaluate the given files, run all benches declared with 'Deno.bench()' and report results to standard output: + deno bench src/fetch_bench.ts src/signal_bench.ts -Directory arguments are expanded to all contained files matching the -glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}: - deno bench src/", +If you specify a directory instead of a file, the path is expanded to all contained files matching the glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}: + deno bench src/ + +Read more: https://docs.deno.com/go/bench"), UnstableArgsConfig::ResolutionAndRuntime, ) .defer(|cmd| { - runtime_args(cmd, true, false) + runtime_args(cmd, true, false, true) .arg(check_arg(true)) .arg( Arg::new("json") @@ -1629,7 +1731,7 @@ glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}: Arg::new("ignore") .long("ignore") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help("Ignore files"), ) @@ -1637,7 +1739,9 @@ glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}: Arg::new("filter") .long("filter") .allow_hyphen_values(true) - .help("Run benchmarks with this string or pattern in the bench name"), + .help( + "Run benchmarks with this string or regexp pattern in the bench name", + ), ) .arg( Arg::new("files") @@ -1656,49 +1760,31 @@ glob {*_,*.,}bench.{js,mjs,ts,mts,jsx,tsx}: .arg(no_clear_screen_arg()) .arg(script_arg().last(true)) .arg(env_file_arg()) + .arg(executable_ext_arg()) }) } fn bundle_subcommand() -> Command { - command("bundle", "⚠️ Warning: `deno bundle` is deprecated and will be removed in Deno 2.0. -Use an alternative bundler like \"deno_emit\", \"esbuild\" or \"rollup\" instead. + command("bundle", "⚠️ `deno bundle` was removed in Deno 2. -Output a single JavaScript file with all dependencies. - deno bundle jsr:@std/http/file-server file_server.bundle.js - -If no output file is given, the output is written to standard output: - deno bundle jsr:@std/http/file-server", UnstableArgsConfig::ResolutionOnly) +See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations", UnstableArgsConfig::ResolutionOnly) .hide(true) - .defer(|cmd| { - compile_args(cmd) - .hide(true) - .arg(check_arg(true)) - .arg( - Arg::new("source_file") - .required_unless_present("help") - .value_hint(ValueHint::FilePath), - ) - .arg(Arg::new("out_file").value_hint(ValueHint::FilePath)) - .arg(watch_arg(false)) - .arg(watch_exclude_arg()) - .arg(no_clear_screen_arg()) - .arg(executable_ext_arg()) - }) } fn cache_subcommand() -> Command { command( "cache", - "Cache and compile remote dependencies recursively. + cstr!("Cache and compile remote dependencies. -Download and compile a module with all of its static dependencies and save -them in the local cache, without running any code: - deno cache jsr:@std/http/file-server +Download and compile a module with all of its static dependencies and save them in the local cache, without running any code: + deno cache jsr:@std/http/file-server -Future runs of this module will trigger no downloads or compilation unless ---reload is specified.", +Future runs of this module will trigger no downloads or compilation unless --reload is specified + +Read more: https://docs.deno.com/go/cache"), UnstableArgsConfig::ResolutionOnly, - ) +) + .hide(true) .defer(|cmd| { compile_args(cmd) .arg(check_arg(false)) @@ -1710,24 +1796,27 @@ Future runs of this module will trigger no downloads or compilation unless ) .arg(frozen_lockfile_arg()) .arg(allow_scripts_arg()) + .arg(allow_import_arg()) }) } fn clean_subcommand() -> Command { command( "clean", - "Remove the cache directory ($DENO_DIR)", + cstr!("Remove the cache directory ($DENO_DIR)"), UnstableArgsConfig::None, ) } fn check_subcommand() -> Command { command("check", - "Download and type-check without execution. + cstr!("Download and type-check without execution. - deno check jsr:@std/http/file-server + deno check jsr:@std/http/file-server -Unless --reload is specified, this command will not re-download already cached dependencies.", +Unless --reload is specified, this command will not re-download already cached dependencies + +Read more: https://docs.deno.com/go/check"), UnstableArgsConfig::ResolutionAndRuntime ) .defer(|cmd| { @@ -1743,17 +1832,32 @@ Unless --reload is specified, this command will not re-download already cached d // past alias for --all Arg::new("remote") .long("remote") - .help("Type-check all modules, including remote") + .help("Type-check all modules, including remote ones") .action(ArgAction::SetTrue) .conflicts_with("no-remote") .hide(true) ) + .arg( + Arg::new("doc") + .long("doc") + .help("Type-check code blocks in JSDoc as well as actual code") + .action(ArgAction::SetTrue) + ) + .arg( + Arg::new("doc-only") + .long("doc-only") + .help("Type-check code blocks in JSDoc and Markdown only") + .action(ArgAction::SetTrue) + .conflicts_with("doc") + ) .arg( Arg::new("file") .num_args(1..) .required_unless_present("help") .value_hint(ValueHint::FilePath), ) + .arg(frozen_lockfile_arg()) + .arg(allow_import_arg()) } ) } @@ -1761,40 +1865,36 @@ Unless --reload is specified, this command will not re-download already cached d fn compile_subcommand() -> Command { command( "compile", - "Compiles the given script into a self contained executable. + cstr!("Compiles the given script into a self contained executable. - deno compile -A jsr:@std/http/file-server - deno compile --output file_server jsr:@std/http/file-server + deno compile --allow-read --allow-net jsr:@std/http/file-server + deno compile --output file_server jsr:@std/http/file-server -Any flags passed which affect runtime behavior, such as '--unstable', -'--allow-*', '--v8-flags', etc. are encoded into the output executable and -used at runtime as if they were passed to a similar 'deno run' command. +Any flags specified which affect runtime behavior will be applied to the resulting binary. -The executable name is inferred by default: Attempt to take the file stem of -the URL path. The above example would become 'file_server'. If the file stem -is something generic like 'main', 'mod', 'index' or 'cli', and the path has no -parent, take the file name of the parent path. Otherwise settle with the -generic name. If the resulting name has an '@...' suffix, strip it. +This allows distribution of a Deno application to systems that do not have Deno installed. +Under the hood, it bundles a slimmed down version of the Deno runtime along with your +JavaScript or TypeScript code. -Cross-compiling to different target architectures is supported using the -`--target` flag. On the first invocation with deno will download proper -binary and cache it in $DENO_DIR. The aarch64-apple-darwin target is not -supported in canary. -", +Cross-compiling to different target architectures is supported using the --target flag. +On the first invocation with deno will download the proper binary and cache it in $DENO_DIR. + +Read more: https://docs.deno.com/go/compile +"), UnstableArgsConfig::ResolutionAndRuntime, ) .defer(|cmd| { - runtime_args(cmd, true, false) + runtime_args(cmd, true, false, true) .arg(check_arg(true)) .arg( Arg::new("include") .long("include") .help( - "Includes an additional module in the compiled executable's module - graph. Use this flag if a dynamically imported module or a web worker main - module fails to load in the executable. This flag can be passed multiple - times, to include multiple additional modules.", - ) + cstr!("Includes an additional module in the compiled executable's module graph. + Use this flag if a dynamically imported module or a web worker main module + fails to load in the executable. This flag can be passed multiple times, + to include multiple additional modules.", + )) .action(ArgAction::Append) .value_hint(ValueHint::FilePath) .help_heading(COMPILE_HEADING), @@ -1804,7 +1904,7 @@ supported in canary. .long("output") .short('o') .value_parser(value_parser!(String)) - .help("Output file (defaults to $PWD/)") + .help(cstr!("Output file (defaults to $PWD/<>)")) .value_hint(ValueHint::FilePath) .help_heading(COMPILE_HEADING), ) @@ -1848,10 +1948,12 @@ supported in canary. fn completions_subcommand() -> Command { command( "completions", - "Output shell completion script to standard output. + cstr!( + "Output shell completion script to standard output. - deno completions bash > /usr/local/etc/bash_completion.d/deno.bash - source /usr/local/etc/bash_completion.d/deno.bash", + deno completions bash > /usr/local/etc/bash_completion.d/deno.bash + source /usr/local/etc/bash_completion.d/deno.bash" + ), UnstableArgsConfig::None, ) .defer(|cmd| { @@ -1866,31 +1968,25 @@ fn completions_subcommand() -> Command { fn coverage_subcommand() -> Command { command( "coverage", - "Print coverage reports from coverage profiles. + cstr!("Print coverage reports from coverage profiles. Collect a coverage profile with deno test: - deno test --coverage=cov_profile + deno test --coverage=cov_profile Print a report to stdout: - deno coverage cov_profile + deno coverage cov_profile -Include urls that start with the file schema: - deno coverage --include=\"^file:\" cov_profile - -Exclude urls ending with test.ts and test.js: - deno coverage --exclude=\"test\\.(ts|js)\" cov_profile - -Include urls that start with the file schema and exclude files ending with -test.ts and test.js, for an url to match it must match the include pattern and -not match the exclude pattern: - deno coverage --include=\"^file:\" --exclude=\"test\\.(ts|js)\" cov_profile +Include urls that start with the file schema and exclude files ending with test.ts and test.js, +for an url to match it must match the include pattern and not match the exclude pattern: + deno coverage --include=\"^file:\" --exclude=\"test\\.(ts|js)\" cov_profile Write a report using the lcov format: - deno coverage --lcov --output=cov.lcov cov_profile/ + deno coverage --lcov --output=cov.lcov cov_profile/ Generate html reports from lcov: - genhtml -o html_cov cov.lcov -", + genhtml -o html_cov cov.lcov + +Read more: https://docs.deno.com/go/coverage"), UnstableArgsConfig::None, ) .defer(|cmd| { @@ -1899,7 +1995,7 @@ Generate html reports from lcov: Arg::new("ignore") .long("ignore") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help("Ignore coverage files") .value_hint(ValueHint::AnyPath), @@ -1936,10 +2032,9 @@ Generate html reports from lcov: .long("output") .value_parser(value_parser!(String)) .help( - "Exports the coverage report in lcov format to the given file. - Filename should be passed along with '=' For example '--output=foo.lcov' - If no --output arg is specified then the report is written to stdout.", - ) + cstr!("Exports the coverage report in lcov format to the given file. + If no --output arg is specified then the report is written to stdout.", + )) .require_equals(true) .value_hint(ValueHint::FilePath), ) @@ -1952,7 +2047,7 @@ Generate html reports from lcov: .arg( Arg::new("detailed") .long("detailed") - .help("Output coverage report in detailed format in the terminal.") + .help("Output coverage report in detailed format in the terminal") .action(ArgAction::SetTrue), ) .arg( @@ -1966,31 +2061,25 @@ Generate html reports from lcov: fn doc_subcommand() -> Command { command("doc", - "Show documentation for a module. + cstr!("Show documentation for a module. Output documentation to standard output: - deno doc ./path/to/module.ts + deno doc ./path/to/module.ts Output documentation in HTML format: - deno doc --html --name=\"My library\" ./path/to/module.ts - deno doc --html --name=\"My library\" ./main.ts ./dev.ts - deno doc --html --name=\"My library\" --output=./documentation/ ./path/to/module.ts - -Output private documentation to standard output: - deno doc --private ./path/to/module.ts - -Output documentation in JSON format: - deno doc --json ./path/to/module.ts + deno doc --html --name=\"My library\" ./path/to/module.ts Lint a module for documentation diagnostics: - deno doc --lint ./path/to/module.ts + deno doc --lint ./path/to/module.ts Target a specific symbol: - deno doc ./path/to/module.ts MyClass.someField + deno doc ./path/to/module.ts MyClass.someField Show documentation for runtime built-ins: - deno doc - deno doc --filter Deno.Listener", + deno doc + deno doc --filter Deno.Listener + +Read more: https://docs.deno.com/go/doc"), UnstableArgsConfig::ResolutionOnly ) .defer(|cmd| { @@ -2001,6 +2090,7 @@ Show documentation for runtime built-ins: .arg(no_lock_arg()) .arg(no_npm_arg()) .arg(no_remote_arg()) + .arg(allow_import_arg()) .arg( Arg::new("json") .long("json") @@ -2019,7 +2109,7 @@ Show documentation for runtime built-ins: .arg( Arg::new("name") .long("name") - .help("The name that will be displayed in the docs") + .help("The name that will be used in the docs (ie for breadcrumbs)") .action(ArgAction::Set) .require_equals(true).help_heading(DOC_HEADING) ) @@ -2042,14 +2132,14 @@ Show documentation for runtime built-ins: .arg( Arg::new("strip-trailing-html") .long("strip-trailing-html") - .help("Remove trailing .html from various links. Will still generate files with a .html extension.") + .help("Remove trailing .html from various links. Will still generate files with a .html extension") .requires("html") .action(ArgAction::SetTrue).help_heading(DOC_HEADING) ) .arg( Arg::new("default-symbol-map") .long("default-symbol-map") - .help("Uses the provided mapping of default name to wanted name for usage blocks.") + .help("Uses the provided mapping of default name to wanted name for usage blocks") .requires("html") .action(ArgAction::Set) .require_equals(true).help_heading(DOC_HEADING) @@ -2099,67 +2189,69 @@ Show documentation for runtime built-ins: } fn eval_subcommand() -> Command { - command("eval", + command( + "eval", + cstr!( "Evaluate JavaScript from the command line. - - deno eval \"console.log('hello world')\" + deno eval \"console.log('hello world')\" To evaluate as TypeScript: - deno eval --ext=ts \"const v: string = 'hello'; console.log(v)\" + deno eval --ext=ts \"const v: string = 'hello'; console.log(v)\" -This command has implicit access to all permissions (--allow-all).", - UnstableArgsConfig::ResolutionAndRuntime, - ) - .defer(|cmd| { - runtime_args(cmd, false, true) - .arg(check_arg(false)) - .arg( - // TODO(@satyarohith): remove this argument in 2.0. - Arg::new("ts") - .conflicts_with("ext") - .long("ts") - .short('T') - .help("deprecated: Use `--ext=ts` instead. The `--ts` and `-T` flags are deprecated and will be removed in Deno 2.0.") - .action(ArgAction::SetTrue) - .hide(true), - ) - .arg(executable_ext_arg()) - .arg( - Arg::new("print") - .long("print") - .short('p') - .help("print result to stdout") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("code_arg") - .num_args(1..) - .action(ArgAction::Append) - .help("Code arg") - .value_name("CODE_ARG") - .required_unless_present("help"), - ) - .arg(env_file_arg()) - }) +This command has implicit access to all permissions. + +Read more: https://docs.deno.com/go/eval" + ), + UnstableArgsConfig::ResolutionAndRuntime, + ) + .defer(|cmd| { + runtime_args(cmd, false, true, true) + .arg(check_arg(false)) + .arg(executable_ext_arg()) + .arg( + Arg::new("print") + .long("print") + .short('p') + .help("print result to stdout") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("code_arg") + .num_args(1..) + .action(ArgAction::Append) + .help("Code to evaluate") + .value_name("CODE_ARG") + .required_unless_present("help"), + ) + .arg(env_file_arg()) + }) } fn fmt_subcommand() -> Command { command( "fmt", - "Auto-format JavaScript, TypeScript, Markdown, and JSON files. + cstr!("Auto-format various file types. + deno fmt myfile1.ts myfile2.ts - deno fmt - deno fmt myfile1.ts myfile2.ts - deno fmt --check +Supported file types are: + JavaScript, TypeScript, Markdown, JSON(C) and Jupyter Notebooks + +Supported file types which are behind corresponding unstable flags (see formatting options): + HTML, CSS, SCSS, SASS, LESS, YAML, Svelte, Vue, Astro and Angular Format stdin and write to stdout: - cat file.ts | deno fmt - + cat file.ts | deno fmt - + +Check if the files are formatted: + deno fmt --check Ignore formatting code by preceding it with an ignore comment: - // deno-fmt-ignore + // deno-fmt-ignore Ignore formatting a file by adding an ignore comment at the top of the file: - // deno-fmt-ignore-file", + // deno-fmt-ignore-file + +Read more: https://docs.deno.com/go/fmt"), UnstableArgsConfig::None, ) .defer(|cmd| { @@ -2167,7 +2259,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .arg(config_arg()) .arg(no_config_arg()) .arg( - Arg::new("check") + Arg::new("check") .long("check") .help("Check if the source files are formatted") .num_args(0) @@ -2177,20 +2269,18 @@ Ignore formatting a file by adding an ignore comment at the top of the file: Arg::new("ext") .long("ext") .help("Set content type of the supplied file") - // prefer using ts for formatting instead of js because ts works in more scenarios - .default_value("ts") .value_parser([ "ts", "tsx", "js", "jsx", "md", "json", "jsonc", "css", "scss", "sass", "less", "html", "svelte", "vue", "astro", "yml", "yaml", "ipynb", ]) - .help_heading(FMT_HEADING), + .help_heading(FMT_HEADING).requires("files"), ) .arg( Arg::new("ignore") .long("ignore") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help("Ignore formatting particular source files") .value_hint(ValueHint::AnyPath) @@ -2214,7 +2304,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .default_missing_value("true") .require_equals(true) .help( - "Use tabs instead of spaces for indentation. Defaults to false.", + cstr!( "Use tabs instead of spaces for indentation [default: false]"), ) .help_heading(FMT_HEADING), ) @@ -2222,7 +2312,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: Arg::new("line-width") .long("line-width") .alias("options-line-width") - .help("Define maximum line width. Defaults to 80.") + .help(cstr!("Define maximum line width [default: 80]")) .value_parser(value_parser!(NonZeroU32)) .help_heading(FMT_HEADING), ) @@ -2230,7 +2320,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: Arg::new("indent-width") .long("indent-width") .alias("options-indent-width") - .help("Define indentation width. Defaults to 2.") + .help(cstr!("Define indentation width [default: 2]")) .value_parser(value_parser!(NonZeroU8)) .help_heading(FMT_HEADING), ) @@ -2242,7 +2332,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .value_parser(value_parser!(bool)) .default_missing_value("true") .require_equals(true) - .help("Use single quotes. Defaults to false.") + .help(cstr!("Use single quotes [default: false]")) .help_heading(FMT_HEADING), ) .arg( @@ -2250,7 +2340,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .long("prose-wrap") .alias("options-prose-wrap") .value_parser(["always", "never", "preserve"]) - .help("Define how prose should be wrapped. Defaults to always.") + .help(cstr!("Define how prose should be wrapped [default: always]")) .help_heading(FMT_HEADING), ) .arg( @@ -2262,49 +2352,59 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .default_missing_value("true") .require_equals(true) .help( - "Don't use semicolons except where necessary. Defaults to false.", + cstr!("Don't use semicolons except where necessary [default: false]"), ) .help_heading(FMT_HEADING), ) .arg( Arg::new("unstable-css") .long("unstable-css") - .help("Enable formatting CSS, SCSS, Sass and Less files.") + .help("Enable formatting CSS, SCSS, Sass and Less files") .value_parser(FalseyValueParser::new()) .action(ArgAction::SetTrue) - .help_heading(FMT_HEADING), + .help_heading(FMT_HEADING) + .hide(true), ) .arg( Arg::new("unstable-html") .long("unstable-html") - .help("Enable formatting HTML files.") + .help("Enable formatting HTML files") .value_parser(FalseyValueParser::new()) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .help_heading(FMT_HEADING) + .hide(true), ) .arg( Arg::new("unstable-component") .long("unstable-component") - .help("Enable formatting Svelte, Vue, Astro and Angular files.") + .help("Enable formatting Svelte, Vue, Astro and Angular files") .value_parser(FalseyValueParser::new()) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .help_heading(FMT_HEADING), ) .arg( Arg::new("unstable-yaml") .long("unstable-yaml") - .help("Enable formatting YAML files.") + .help("Enable formatting YAML files") .value_parser(FalseyValueParser::new()) .action(ArgAction::SetTrue) - .help_heading(FMT_HEADING), + .help_heading(FMT_HEADING) + .hide(true), ) }) } fn init_subcommand() -> Command { - command("init", "Initialize a new project", UnstableArgsConfig::None).defer( + command("init", "scaffolds a basic Deno project with a script, test, and configuration file", UnstableArgsConfig::None).defer( |cmd| { cmd .arg(Arg::new("dir").value_hint(ValueHint::DirPath)) - .arg(Arg::new("lib").long("lib").action(ArgAction::SetTrue)) + .arg( + Arg::new("lib") + .long("lib") + .help("Generate an example library project") + .action(ArgAction::SetTrue), + ) .arg( Arg::new("serve") .long("serve") @@ -2318,23 +2418,18 @@ fn init_subcommand() -> Command { fn info_subcommand() -> Command { command("info", - "Information about a module or the cache directories. + cstr!("Show information about a module or the cache directories. Get information about a module: - deno info jsr:@std/http/file-server + deno info jsr:@std/http/file-server The following information is shown: + local: Local path of the file + type: JavaScript, TypeScript, or JSON + emit: Local path of compiled source code (TypeScript only) + dependencies: Dependency tree of the source file -local: Local path of the file. -type: JavaScript, TypeScript, or JSON. -emit: Local path of compiled source code. (TypeScript only.) -dependencies: Dependency tree of the source file. - -Without any additional arguments, 'deno info' shows: - -DENO_DIR: Directory containing Deno-managed files. -Remote modules cache: Subdirectory containing downloaded remote modules. -TypeScript compiler cache: Subdirectory containing TS compiler output.", +Read more: https://docs.deno.com/go/info"), UnstableArgsConfig::ResolutionOnly ) .defer(|cmd| cmd @@ -2345,14 +2440,13 @@ TypeScript compiler cache: Subdirectory containing TS compiler output.", .arg( location_arg() .conflicts_with("file") - .help("Show files used for origin bound APIs like the Web Storage API when running a script with '--location='") + .help(cstr!("Show files used for origin bound APIs like the Web Storage API when running a script with --location=<>")) ) .arg(no_check_arg().hide(true)) // TODO(lucacasonato): remove for 2.0 .arg(no_config_arg()) .arg(no_remote_arg()) .arg(no_npm_arg()) .arg(lock_arg()) - .arg(lock_write_arg()) .arg(no_lock_arg()) .arg(config_arg()) .arg(import_map_arg()) @@ -2364,133 +2458,101 @@ TypeScript compiler cache: Subdirectory containing TS compiler output.", .help("UNSTABLE: Outputs the information in JSON format") .action(ArgAction::SetTrue), )) -} - -fn install_args(cmd: Command, deno_future: bool) -> Command { - let cmd = if deno_future { - cmd.arg( - Arg::new("cmd") - .required_if_eq("global", "true") - .num_args(1..) - .value_hint(ValueHint::FilePath), - ) - } else { - cmd.arg( - Arg::new("cmd") - .required_unless_present("help") - .num_args(1..) - .value_hint(ValueHint::FilePath), - ) - }; - cmd - .arg( - Arg::new("name") - .long("name") - .short('n') - .help("Executable file name"), - ) - .arg( - Arg::new("root") - .long("root") - .help("Installation root") - .value_hint(ValueHint::DirPath), - ) - .arg( - Arg::new("force") - .long("force") - .short('f') - .help("Forcefully overwrite existing installation") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("global") - .long("global") - .short('g') - .help("Install a package or script as a globally available executable") - .action(ArgAction::SetTrue), - ) - .arg(env_file_arg()) -} - -fn future_install_subcommand() -> Command { - command("install", "Installs dependencies either in the local project or globally to a bin directory. - -Local installation -------------------- -If the --global flag is not set, adds dependencies to the local project's configuration -(package.json / deno.json) and installs them in the package cache. If no dependency -is specified, installs all dependencies listed in package.json. - - deno install - deno install @std/bytes - deno install npm:chalk - -Global installation -------------------- -If the --global flag is set, installs a script as an executable in the installation root's bin directory. - - deno install --global --allow-net --allow-read jsr:@std/http/file-server - deno install -g https://examples.deno.land/color-logging.ts - -To change the executable name, use -n/--name: - - deno install -g --allow-net --allow-read -n serve jsr:@std/http/file-server - -The executable name is inferred by default: - - Attempt to take the file stem of the URL path. The above example would - become 'file_server'. - - If the file stem is something generic like 'main', 'mod', 'index' or 'cli', - and the path has no parent, take the file name of the parent path. Otherwise - settle with the generic name. - - If the resulting name has an '@...' suffix, strip it. - -To change the installation root, use --root: - - deno install -g --allow-net --allow-read --root /usr/local jsr:@std/http/file-server - -The installation root is determined, in order of precedence: - - --root option - - DENO_INSTALL_ROOT environment variable - - $HOME/.deno - -These must be added to the path manually if required.", UnstableArgsConfig::ResolutionAndRuntime) - .visible_alias("i") - .defer(|cmd| { - let cmd = runtime_args(cmd, true, true).arg(check_arg(true)).arg(allow_scripts_arg()); - install_args(cmd, true) - }) + .arg(allow_import_arg()) } fn install_subcommand() -> Command { - command("install", - "Installs a script as an executable in the installation root's bin directory. + command("install", cstr!("Installs dependencies either in the local project or globally to a bin directory. - deno install --global --allow-net --allow-read jsr:@std/http/file-server - deno install -g https://examples.deno.land/color-logging.ts +Local installation -To change the executable name, use -n/--name: - deno install -g --allow-net --allow-read -n serve jsr:@std/http/file-server +Add dependencies to the local project's configuration (deno.json / package.json) and installs them +in the package cache. If no dependency is specified, installs all dependencies listed in the config file. +If the --entrypoint flag is passed, installs the dependencies of the specified entrypoint(s). + + deno install + deno install jsr:@std/bytes + deno install npm:chalk + deno install --entrypoint entry1.ts entry2.ts + +Global installation + +If the --global flag is set, installs a script as an executable in the installation root's bin directory. + + deno install --global --allow-net --allow-read jsr:@std/http/file-server + deno install -g https://examples.deno.land/color-logging.ts + +To change the executable name, use -n/--name: + deno install -g --allow-net --allow-read -n serve jsr:@std/http/file-server The executable name is inferred by default: - Attempt to take the file stem of the URL path. The above example would - become 'file_server'. - - If the file stem is something generic like 'main', 'mod', 'index' or 'cli', + become file_server. + - If the file stem is something generic like main, mod, index or cli, and the path has no parent, take the file name of the parent path. Otherwise settle with the generic name. - - If the resulting name has an '@...' suffix, strip it. + - If the resulting name has an @... suffix, strip it. -To change the installation root, use --root: - deno install -g --allow-net --allow-read --root /usr/local jsr:@std/http/file-server +To change the installation root, use --root: + deno install -g --allow-net --allow-read --root /usr/local jsr:@std/http/file-server The installation root is determined, in order of precedence: - - --root option - - DENO_INSTALL_ROOT environment variable - - $HOME/.deno + - --root option + - DENO_INSTALL_ROOT environment variable + - $HOME/.deno -These must be added to the path manually if required.", UnstableArgsConfig::ResolutionAndRuntime) +These must be added to the path manually if required."), UnstableArgsConfig::ResolutionAndRuntime) + .visible_alias("i") .defer(|cmd| { - let cmd = runtime_args(cmd, true, true).arg(check_arg(true)); - install_args(cmd, false) + permission_args(runtime_args(cmd, false, true, false), Some("global")) + .arg(check_arg(true)) + .arg(allow_scripts_arg()) + .arg( + Arg::new("cmd") + .required_if_eq("global", "true") + .required_if_eq("entrypoint", "true") + .num_args(1..) + .value_hint(ValueHint::FilePath), + ) + .arg( + Arg::new("name") + .long("name") + .short('n') + .requires("global") + .help("Executable file name"), + ) + .arg( + Arg::new("root") + .long("root") + .requires("global") + .help("Installation root") + .value_hint(ValueHint::DirPath), + ) + .arg( + Arg::new("force") + .long("force") + .requires("global") + .short('f') + .help("Forcefully overwrite existing installation") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("global") + .long("global") + .short('g') + .help("Install a package or script as a globally available executable") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("entrypoint") + .long("entrypoint") + .short('e') + .conflicts_with("global") + .action(ArgAction::SetTrue) + .help("Install dependents of the specified entrypoint(s)"), + ) + .arg(env_file_arg()) + .arg(add_dev_arg().conflicts_with("entrypoint").conflicts_with("global")) }) } @@ -2499,7 +2561,7 @@ fn json_reference_subcommand() -> Command { } fn jupyter_subcommand() -> Command { - Command::new("jupyter") + command("jupyter", "Deno kernel for Jupyter notebooks", UnstableArgsConfig::ResolutionAndRuntime) .arg( Arg::new("install") .long("install") @@ -2522,32 +2584,32 @@ fn jupyter_subcommand() -> Command { .value_parser(value_parser!(String)) .value_hint(ValueHint::FilePath) .conflicts_with("install")) - .about("Deno kernel for Jupyter notebooks") } fn uninstall_subcommand() -> Command { command( "uninstall", - "Uninstalls an executable script in the installation root's bin directory. + cstr!("Uninstalls a dependency or an executable script in the installation root's bin directory. + deno uninstall @std/dotenv chalk + deno uninstall --global file_server - deno uninstall serve - -To change the installation root, use --root: - deno uninstall --root /usr/local serve +To change the installation root, use --root flag: + deno uninstall --global --root /usr/local serve The installation root is determined, in order of precedence: - - --root option - - DENO_INSTALL_ROOT environment variable - - $HOME/.deno", + - --root option + - DENO_INSTALL_ROOT environment variable + - $HOME/.deno"), UnstableArgsConfig::None, ) .defer(|cmd| { cmd - .arg(Arg::new("name").required_unless_present("help")) + .arg(Arg::new("name-or-package").required_unless_present("help")) .arg( Arg::new("root") .long("root") .help("Installation root") + .requires("global") .value_hint(ValueHint::DirPath), ) .arg( @@ -2557,49 +2619,53 @@ The installation root is determined, in order of precedence: .help("Remove globally installed package or module") .action(ArgAction::SetTrue), ) + .arg( + Arg::new("additional-packages") + .help("List of additional packages to remove") + .conflicts_with("global") + .num_args(1..) + .action(ArgAction::Append) + ) }) } fn lsp_subcommand() -> Command { Command::new("lsp").about( - "The 'deno lsp' subcommand provides a way for code editors and IDEs to -interact with Deno using the Language Server Protocol. Usually humans do not -use this subcommand directly. For example, 'deno lsp' can provide IDEs with -go-to-definition support and automatic code formatting. + "The 'deno lsp' subcommand provides a way for code editors and IDEs to interact with Deno +using the Language Server Protocol. Usually humans do not use this subcommand directly. +For example, 'deno lsp' can provide IDEs with go-to-definition support and automatic code formatting. -How to connect various editors and IDEs to 'deno lsp': -https://docs.deno.com/go/lsp", +How to connect various editors and IDEs to 'deno lsp': https://docs.deno.com/go/lsp", ) } fn lint_subcommand() -> Command { command( "lint", - "Lint JavaScript/TypeScript source code. + cstr!("Lint JavaScript/TypeScript source code. - deno lint - deno lint myfile1.ts myfile2.js + deno lint + deno lint myfile1.ts myfile2.js Print result as JSON: - deno lint --json + deno lint --json Read from stdin: - cat file.ts | deno lint - - cat file.ts | deno lint --json - + cat file.ts | deno lint - + cat file.ts | deno lint --json - List available rules: - deno lint --rules + deno lint --rules -Ignore diagnostics on the next line by preceding it with an ignore comment and -rule name: - // deno-lint-ignore no-explicit-any - // deno-lint-ignore require-await no-empty +To ignore specific diagnostics, you can write an ignore comment on the preceding line with a rule name (or multiple): + // deno-lint-ignore no-explicit-any + // deno-lint-ignore require-await no-empty -Names of rules to ignore must be specified after ignore comment. +To ignore linting on an entire file, you can add an ignore comment at the top of the file: + // deno-lint-ignore-file -Ignore linting a file by adding an ignore comment at the top of the file: - // deno-lint-ignore-file -", +Read more: https://docs.deno.com/go/lint +"), UnstableArgsConfig::ResolutionOnly, ) .defer(|cmd| { @@ -2664,7 +2730,7 @@ Ignore linting a file by adding an ignore comment at the top of the file: Arg::new("ignore") .long("ignore") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help("Ignore linting particular source files") .value_hint(ValueHint::AnyPath) @@ -2698,33 +2764,50 @@ Ignore linting a file by adding an ignore comment at the top of the file: } fn repl_subcommand() -> Command { - command("repl", "Read Eval Print Loop", UnstableArgsConfig::ResolutionAndRuntime) - .defer(|cmd| runtime_args(cmd, true, true) - .arg(check_arg(false)) + command("repl", cstr!( + "Starts a read-eval-print-loop, which lets you interactively build up program state in the global context. +It is especially useful for quick prototyping and checking snippets of code. + +TypeScript is supported, however it is not type-checked, only transpiled." + ), UnstableArgsConfig::ResolutionAndRuntime) + .defer(|cmd| { + let cmd = compile_args_without_check_args(cmd); + let cmd = inspect_args(cmd); + let cmd = permission_args(cmd, None); + let cmd = runtime_misc_args(cmd); + + cmd .arg( Arg::new("eval-file") .long("eval-file") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) - .help("Evaluates the provided file(s) as scripts when the REPL starts. Accepts file paths and URLs.") + .help("Evaluates the provided file(s) as scripts when the REPL starts. Accepts file paths and URLs") .value_hint(ValueHint::AnyPath), ) .arg( Arg::new("eval") .long("eval") - .help("Evaluates the provided code when the REPL starts.") + .help("Evaluates the provided code when the REPL starts") .value_name("code"), ) - .after_help(color_print::cstr!("Environment variables: + .after_help(cstr!("Environment variables: DENO_REPL_HISTORY Set REPL history file path. History file is disabled when the value is empty. - (defaults to $DENO_DIR/deno_history.txt)")) - ) + [default: $DENO_DIR/deno_history.txt]")) + }) .arg(env_file_arg()) + .arg( + Arg::new("args") + .num_args(0..) + .action(ArgAction::Append) + .value_name("ARGS") + .last(true) + ) } fn run_args(command: Command, top_level: bool) -> Command { - runtime_args(command, true, true) + runtime_args(command, true, true, true) .arg(check_arg(false)) .arg(watch_arg(true)) .arg(hmr_arg(true)) @@ -2734,16 +2817,14 @@ fn run_args(command: Command, top_level: bool) -> Command { .arg(if top_level { script_arg().trailing_var_arg(true).hide(true) } else { - script_arg() - .required_unless_present_any(["help", "v8-flags"]) - .trailing_var_arg(true) + script_arg().trailing_var_arg(true) }) .arg(env_file_arg()) .arg(no_code_cache_arg()) } fn run_subcommand() -> Command { - run_args(command("run", color_print::cstr!("Run a JavaScript or TypeScript program, or a task or script. + run_args(command("run", cstr!("Run a JavaScript or TypeScript program, or a task or script. By default all programs are run in sandbox without access to disk, network or ability to spawn subprocesses. deno run https://examples.deno.land/hello-world.ts @@ -2758,7 +2839,9 @@ Grant all permissions: deno run -A jsr:@std/http/file-server Specifying the filename '-' to read the file from stdin. - curl https://examples.deno.land/hello-world.ts | deno run -"), UnstableArgsConfig::ResolutionAndRuntime), false) + curl https://examples.deno.land/hello-world.ts | deno run - + +Read more: https://docs.deno.com/go/run"), UnstableArgsConfig::ResolutionAndRuntime), false) } fn serve_host_validator(host: &str) -> Result { @@ -2770,21 +2853,31 @@ fn serve_host_validator(host: &str) -> Result { } fn serve_subcommand() -> Command { - runtime_args(command("serve", None, UnstableArgsConfig::ResolutionAndRuntime), true, true) + runtime_args(command("serve", cstr!("Run a server defined in a main module + +The serve command uses the default exports of the main module to determine which servers to start. + +Start a server defined in server.ts: + deno serve server.ts + +Start a server defined in server.ts, watching for changes and running on port 5050: + deno serve --watch --port 5050 server.ts + +Read more: https://docs.deno.com/go/serve"), UnstableArgsConfig::ResolutionAndRuntime), true, true, true) .arg( Arg::new("port") .long("port") - .help("The TCP port to serve on, defaulting to 8000. Pass 0 to pick a random free port.") + .help(cstr!("The TCP port to serve on. Pass 0 to pick a random free port [default: 8000]")) .value_parser(value_parser!(u16)), ) .arg( Arg::new("host") .long("host") - .help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces).") + .help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces)") .value_parser(serve_host_validator), ) .arg( - parallel_arg("multiple server workers", false) + parallel_arg("multiple server workers") ) .arg(check_arg(false)) .arg(watch_arg(true)) @@ -2799,29 +2892,18 @@ fn serve_subcommand() -> Command { ) .arg(env_file_arg()) .arg(no_code_cache_arg()) - .about("Run a server defined in a main module - -The serve command uses the default exports of the main module to determine which -servers to start. - -See https://docs.deno.com/runtime/manual/tools/serve for -more detailed information. - -Start a server defined in server.ts: - - deno serve server.ts - -Start a server defined in server.ts, watching for changes and running on port 5050: - - deno serve --watch --port 5050 server.ts") } fn task_subcommand() -> Command { command( "task", - "Run a task defined in the configuration file + cstr!( + "Run a task defined in the configuration file. + deno task build - deno task build", +List all available tasks: + deno task" + ), UnstableArgsConfig::ResolutionAndRuntime, ) .defer(|cmd| { @@ -2836,30 +2918,32 @@ fn task_subcommand() -> Command { .help("Specify the directory to run the task in") .value_hint(ValueHint::DirPath), ) + .arg(node_modules_dir_arg()) }) } fn test_subcommand() -> Command { command("test", - "Run tests using Deno's built-in test runner. + cstr!("Run tests using Deno's built-in test runner. -Evaluate the given modules, run all tests declared with 'Deno.test()' and -report results to standard output: - deno test src/fetch_test.ts src/signal_test.ts +Evaluate the given modules, run all tests declared with Deno.test() and report results to standard output: + deno test src/fetch_test.ts src/signal_test.ts -Directory arguments are expanded to all contained files matching the glob -{*_,*.,}test.{js,mjs,ts,mts,jsx,tsx} or **/__tests__/**: - deno test src/", +Directory arguments are expanded to all contained files matching the glob {*_,*.,}test.{js,mjs,ts,mts,jsx,tsx} +or **/__tests__/**: + deno test src/ + +Read more: https://docs.deno.com/go/test"), UnstableArgsConfig::ResolutionAndRuntime ) .defer(|cmd| - runtime_args(cmd, true, true) + runtime_args(cmd, true, true, true) .arg(check_arg(true)) .arg( Arg::new("ignore") .long("ignore") .num_args(1..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help("Ignore files") .value_hint(ValueHint::AnyPath), @@ -2871,25 +2955,17 @@ Directory arguments are expanded to all contained files matching the glob .action(ArgAction::SetTrue) .help_heading(TEST_HEADING), ) - .arg( - Arg::new("trace-ops") - .long("trace-ops") - .help("Deprecated alias for --trace-leaks.") - .hide(true) - .action(ArgAction::SetTrue) - .help_heading(TEST_HEADING), - ) .arg( Arg::new("trace-leaks") .long("trace-leaks") - .help("Enable tracing of leaks. Useful when debugging leaking ops in test, but impacts test execution time.") + .help("Enable tracing of leaks. Useful when debugging leaking ops in test, but impacts test execution time") .action(ArgAction::SetTrue) .help_heading(TEST_HEADING), ) .arg( Arg::new("doc") .long("doc") - .help("Type-check code blocks in JSDoc and Markdown") + .help("Evaluate code blocks in JSDoc and Markdown") .action(ArgAction::SetTrue) .help_heading(TEST_HEADING), ) @@ -2897,25 +2973,16 @@ Directory arguments are expanded to all contained files matching the glob Arg::new("fail-fast") .long("fail-fast") .alias("failfast") - .help("Stop after N errors. Defaults to stopping after first failure.") + .help("Stop after N errors. Defaults to stopping after first failure") .num_args(0..=1) .require_equals(true) .value_name("N") .value_parser(value_parser!(NonZeroUsize)) .help_heading(TEST_HEADING)) - // TODO(@lucacasonato): remove for Deno 2.0 - .arg( - Arg::new("allow-none") - .long("allow-none") - .help("Don't return error code if no test files are found") - .hide(true) - .action(ArgAction::SetTrue), - ) .arg( Arg::new("permit-no-files") .long("permit-no-files") .help("Don't return an error code if no test files were found") - .conflicts_with("allow-none") .action(ArgAction::SetTrue) .help_heading(TEST_HEADING), ) @@ -2923,7 +2990,7 @@ Directory arguments are expanded to all contained files matching the glob Arg::new("filter") .allow_hyphen_values(true) .long("filter") - .help("Run tests with this string or pattern in the test name") + .help("Run tests with this string or regexp pattern in the test name") .help_heading(TEST_HEADING), ) .arg( @@ -2946,29 +3013,19 @@ Directory arguments are expanded to all contained files matching the glob .conflicts_with("inspect") .conflicts_with("inspect-wait") .conflicts_with("inspect-brk") - .help("Collect coverage profile data into DIR. If DIR is not specified, it uses 'coverage/'.") + .help("Collect coverage profile data into DIR. If DIR is not specified, it uses 'coverage/'") .help_heading(TEST_HEADING), ) .arg( Arg::new("clean") .long("clean") - .help("Empty the temporary coverage profile data directory before running tests. - Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.") + .help(cstr!("Empty the temporary coverage profile data directory before running tests. + Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.")) .action(ArgAction::SetTrue) .help_heading(TEST_HEADING), ) .arg( - parallel_arg("test modules", true) - ) - .arg( - Arg::new("jobs") - .short('j') - .long("jobs") - .help("deprecated: The `--jobs` flag is deprecated and will be removed in Deno 2.0. Use the `--parallel` flag with possibly the `DENO_JOBS` environment variable instead.") - .hide(true) - .num_args(0..=1) - .value_parser(value_parser!(NonZeroUsize)) - .help_heading(TEST_HEADING), + parallel_arg("test modules") ) .arg( Arg::new("files") @@ -2990,13 +3047,13 @@ Directory arguments are expanded to all contained files matching the glob .long("junit-path") .value_name("PATH") .value_hint(ValueHint::FilePath) - .help("Write a JUnit XML test report to PATH. Use '-' to write to stdout which is the default when PATH is not provided.") + .help("Write a JUnit XML test report to PATH. Use '-' to write to stdout which is the default when PATH is not provided") .help_heading(TEST_HEADING) ) .arg( Arg::new("reporter") .long("reporter") - .help("Select reporter to use. Default to 'pretty'.") + .help("Select reporter to use. Default to 'pretty'") .value_parser(["pretty", "dot", "junit", "tap"]) .help_heading(TEST_HEADING) ) @@ -3007,61 +3064,60 @@ Directory arguments are expanded to all contained files matching the glob .action(ArgAction::SetTrue) ) .arg(env_file_arg()) + .arg(executable_ext_arg()) ) } -fn parallel_arg(descr: &str, jobs_fallback: bool) -> Arg { - let arg = Arg::new("parallel") +fn parallel_arg(descr: &str) -> Arg { + Arg::new("parallel") .long("parallel") - .help(format!("Run {descr} in parallel. Parallelism defaults to the number of available CPUs or the value of the DENO_JOBS environment variable.")) - .action(ArgAction::SetTrue); - if jobs_fallback { - arg.conflicts_with("jobs") - } else { - arg - } + .help(format!("Run {descr} in parallel. Parallelism defaults to the number of available CPUs or the value of the DENO_JOBS environment variable")) + .action(ArgAction::SetTrue) } fn types_subcommand() -> Command { command( "types", - "Print runtime TypeScript declarations. + cstr!( + "Print runtime TypeScript declarations. - deno types > lib.deno.d.ts + deno types > lib.deno.d.ts -The declaration file could be saved and used for typing information.", +The declaration file could be saved and used for typing information." + ), UnstableArgsConfig::None, ) } +pub static UPGRADE_USAGE: &str = cstr!( + "Latest + deno upgrade + +Specific version + deno upgrade 1.45.0 + deno upgrade 1.46.0-rc.1 + deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 + +Channel + deno upgrade stable + deno upgrade rc + deno upgrade canary" +); + fn upgrade_subcommand() -> Command { command( "upgrade", - color_print::cstr!("Upgrade deno executable to the given version. + color_print::cformat!("Upgrade deno executable to the given version. -Latest +{} - deno upgrade +The version is downloaded from https://dl.deno.land and is used to replace the current executable. -Specific version +If you want to not replace the current Deno executable but instead download an update to a +different location, use the --output flag: + deno upgrade --output $HOME/my_deno - deno upgrade 1.45.0 - deno upgrade 1.46.0-rc.1 - deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 - -Channel - - deno upgrade stable - deno upgrade rc - deno upgrade canary - -The version is downloaded from -https://github.com/denoland/deno/releases -and is used to replace the current executable. - -If you want to not replace the current Deno executable but instead download an -update to a different location, use the --output flag: - deno upgrade --output $HOME/my_deno"), +Read more: https://docs.deno.com/go/upgrade", UPGRADE_USAGE), UnstableArgsConfig::None, ) .hide(cfg!(not(feature = "upgrade"))) @@ -3117,7 +3173,7 @@ update to a different location, use the --output flag: ) .arg( Arg::new("version-or-hash-or-channel") - .help(color_print::cstr!("Version (v1.46.0), channel (rc, canary) or commit hash (9bc2dd29ad6ba334fd57a20114e367d3c04763d4)")) + .help(cstr!("Version (v1.46.0), channel (rc, canary) or commit hash (9bc2dd29ad6ba334fd57a20114e367d3c04763d4)")) .value_name("VERSION") .action(ArgAction::Append) .trailing_var_arg(true), @@ -3127,62 +3183,18 @@ update to a different location, use the --output flag: }) } -// TODO(bartlomieju): this subcommand is now deprecated, remove it in Deno 2. fn vendor_subcommand() -> Command { command("vendor", - "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0. -Add `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead. + "⚠️ `deno vendor` was removed in Deno 2. -Vendor remote modules into a local directory. - -Analyzes the provided modules along with their dependencies, downloads -remote modules to the output directory, and produces an import map that -maps remote specifiers to the downloaded files. - deno vendor main.ts - deno run --import-map vendor/import_map.json main.ts - -Remote modules and multiple modules may also be specified: - deno vendor main.ts test.deps.ts jsr:@std/path", +See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations", UnstableArgsConfig::ResolutionOnly ) .hide(true) - .defer(|cmd| cmd - .arg( - Arg::new("specifiers") - .num_args(1..) - .action(ArgAction::Append) - .required_unless_present("help"), - ) - .arg( - Arg::new("output") - .long("output") - .help("The directory to output the vendored modules to") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::DirPath), - ) - .arg( - Arg::new("force") - .long("force") - .short('f') - .help( - "Forcefully overwrite conflicting files in existing output directory", - ) - .action(ArgAction::SetTrue), - ) - .arg(no_config_arg()) - .arg(config_arg()) - .arg(import_map_arg()) - .arg(lock_arg()) - .arg(node_modules_dir_arg()) - .arg(vendor_arg()) - .arg(reload_arg()) - .arg(ca_file_arg()) - .arg(unsafely_ignore_certificate_errors_arg()) - ) } fn publish_subcommand() -> Command { - command("publish", "Publish the current working directory's package or workspace", UnstableArgsConfig::ResolutionOnly) + command("publish", "Publish the current working directory's package or workspace to JSR", UnstableArgsConfig::ResolutionOnly) .defer(|cmd| { cmd .arg( @@ -3216,7 +3228,8 @@ fn publish_subcommand() -> Command { ).arg( Arg::new("no-provenance") .long("no-provenance") - .help("Disable provenance attestation. Enabled by default on Github actions, publicly links the package to where it was built and published from.") + .help(cstr!("Disable provenance attestation. + Enabled by default on Github actions, publicly links the package to where it was built and published from.")) .action(ArgAction::SetTrue) .help_heading(PUBLISH_HEADING) ) @@ -3240,257 +3253,408 @@ fn compile_args_without_check_args(app: Command) -> Command { .arg(no_config_arg()) .arg(reload_arg()) .arg(lock_arg()) - .arg(lock_write_arg()) .arg(no_lock_arg()) .arg(ca_file_arg()) .arg(unsafely_ignore_certificate_errors_arg()) } -fn permission_args(app: Command) -> Command { +fn permission_args(app: Command, requires: Option<&'static str>) -> Command { app - .after_help(color_print::cstr!(r#"Permission options: -Docs: https://docs.deno.com/go/permissions + .after_help(cstr!(r#"Permission options: +Docs: https://docs.deno.com/go/permissions - -A, --allow-all Allow all permissions. - -R, --{allow,deny}-read[=<...] Allow / deny file system read access. Optionally specify allowed / denied paths. - --allow-read | --allow-read="/etc,/var/log.txt" | --deny-read="/etc/hosts" - -W, --{allow,write}-read[=<...] Allow / deny file system write access. Optionally specify allowed / denied paths. - --allow-write | --allow-write="/etc,/var/log.txt" | --deny-write="/etc/hosts" - -N, --{allow,deny}-net[=<...] Allow / deny network access. Optionally specify allowed IP addresses and host names, with ports as necessary. - --allow-net | --allow-net="localhost:8080,deno.land" | --deny-net="deno.com" - -E --{allow,deny}-env[=<...] Allow / deny access to environment variables. Optionally specify accessible / inacessible environment variables. - --allow-env | --allow-env="PORT,HOME,PATH" | --deny-env="ACCESS_TOKEN" - -S --{allow,deny}-sys[=<...] Allow / deny access to OS information. Optionally allow / deny specific APIs by function name. - --allow-sys | --allow-sys="systemMemoryInfo,osRelease" | --deny-sys="hostname" - --{allow,deny}-run[=<...] Allow / deny running subprocesses. Optionally specify allowed / denied runnable program names. - --allow-run | --allow-run="whoami,ps" | --deny-run="cat" - --{allow,deny}-ffi[=<...] (Unstable) Allow / deny loading dynamic libraries. Optionally specify allowed / denied directories or files. - --allow-ffi | --allow-ffi="./libfoo.so" | --deny-ffi="./libfoo.so" - --{allow,deny}-hrtime Allow / deny high-resolution time measurement. Note: this can enable timing attacks and fingerprinting. - --no-prompt Always throw if required permission wasn't passed. Can also be set via the DENO_NO_PROMPT environment variable. + -A, --allow-all Allow all permissions. + --no-prompt Always throw if required permission wasn't passed. + Can also be set via the DENO_NO_PROMPT environment variable. + -R, --allow-read[=<...] Allow file system read access. Optionally specify allowed paths. + --allow-read | --allow-read="/etc,/var/log.txt" + -W, --allow-write[=<...] Allow file system write access. Optionally specify allowed paths. + --allow-write | --allow-write="/etc,/var/log.txt" + -I, --allow-import[=<...] Allow importing from remote hosts. Optionally specify allowed IP addresses and host names, with ports as necessary. + Default value: deno.land:443,jsr.io:443,esm.sh:443,cdn.jsdelivr.net:443,raw.githubusercontent.com:443,user.githubusercontent.com:443 + --allow-import | --allow-import="example.com,github.com" + -N, --allow-net[=<...] Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary. + --allow-net | --allow-net="localhost:8080,deno.land" + -E, --allow-env[=<...] Allow access to environment variables. Optionally specify accessible environment variables. + --allow-env | --allow-env="PORT,HOME,PATH" + -S, --allow-sys[=<...] Allow access to OS information. Optionally allow specific APIs by function name. + --allow-sys | --allow-sys="systemMemoryInfo,osRelease" + --allow-run[=<...] Allow running subprocesses. Optionally specify allowed runnable program names. + --allow-run | --allow-run="whoami,ps" + --allow-ffi[=<...] (Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files. + --allow-ffi | --allow-ffi="./libfoo.so" + --deny-read[=<...] Deny file system read access. Optionally specify denied paths. + --deny-read | --deny-read="/etc,/var/log.txt" + --deny-write[=<...] Deny file system write access. Optionally specify denied paths. + --deny-write | --deny-write="/etc,/var/log.txt" + --deny-net[=<...] Deny network access. Optionally specify defined IP addresses and host names, with ports as necessary. + --deny-net | --deny-net="localhost:8080,deno.land" + --deny-env[=<...] Deny access to environment variables. Optionally specify inacessible environment variables. + --deny-env | --deny-env="PORT,HOME,PATH" + --deny-sys[=<...] Deny access to OS information. Optionally deny specific APIs by function name. + --deny-sys | --deny-sys="systemMemoryInfo,osRelease" + --deny-run[=<...] Deny running subprocesses. Optionally specify denied runnable program names. + --deny-run | --deny-run="whoami,ps" + --deny-ffi[=<...] (Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files. + --deny-ffi | --deny-ffi="./libfoo.so" "#)) .arg( - Arg::new("allow-all") - .short('A') - .long("allow-all") - .action(ArgAction::SetTrue) - .help("Allow all permissions.") - .hide(true), + { + let mut arg = allow_all_arg().hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-read") - .long("allow-read") - .short('R') - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("Allow file system read access. Optionally specify allowed paths.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("allow-read") + .long("allow-read") + .short('R') + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("Allow file system read access. Optionally specify allowed paths") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-read") - .long("deny-read") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("Deny file system read access. Optionally specify denied paths.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("deny-read") + .long("deny-read") + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("Deny file system read access. Optionally specify denied paths") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-write") - .long("allow-write") - .short('W') - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("Allow file system write access. Optionally specify allowed paths.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("allow-write") + .long("allow-write") + .short('W') + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("Allow file system write access. Optionally specify allowed paths") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-write") - .long("deny-write") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("Deny file system write access. Optionally specify denied paths.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("deny-write") + .long("deny-write") + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("Deny file system write access. Optionally specify denied paths") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-net") - .long("allow-net") - .short('N') - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("IP_OR_HOSTNAME") - .help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary.") - .value_parser(flags_net::validator) - .hide(true), + { + let mut arg = Arg::new("allow-net") + .long("allow-net") + .short('N') + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("IP_OR_HOSTNAME") + .help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary") + .value_parser(flags_net::validator) + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-net") - .long("deny-net") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("IP_OR_HOSTNAME") - .help("Deny network access. Optionally specify denied IP addresses and host names, with ports as necessary.") - .value_parser(flags_net::validator) - .hide(true), + { + let mut arg = Arg::new("deny-net") + .long("deny-net") + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("IP_OR_HOSTNAME") + .help("Deny network access. Optionally specify denied IP addresses and host names, with ports as necessary") + .value_parser(flags_net::validator) + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-env") - .long("allow-env") - .short('E') - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("VARIABLE_NAME") - .help("Allow access to system environment information. Optionally specify accessible environment variables.") - .value_parser(|key: &str| { - if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { - return Err(format!("invalid key \"{key}\"")); - } + { + let mut arg = Arg::new("allow-env") + .long("allow-env") + .short('E') + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("VARIABLE_NAME") + .help("Allow access to system environment information. Optionally specify accessible environment variables") + .value_parser(|key: &str| { + if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { + return Err(format!("invalid key \"{key}\"")); + } - Ok(if cfg!(windows) { - key.to_uppercase() - } else { - key.to_string() + Ok(if cfg!(windows) { + key.to_uppercase() + } else { + key.to_string() + }) }) - }) - .hide(true), + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-env") - .long("deny-env") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("VARIABLE_NAME") - .help("Deny access to system environment information. Optionally specify accessible environment variables.") - .value_parser(|key: &str| { - if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { - return Err(format!("invalid key \"{key}\"")); - } + { + let mut arg = Arg::new("deny-env") + .long("deny-env") + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("VARIABLE_NAME") + .help("Deny access to system environment information. Optionally specify accessible environment variables") + .value_parser(|key: &str| { + if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { + return Err(format!("invalid key \"{key}\"")); + } - Ok(if cfg!(windows) { - key.to_uppercase() - } else { - key.to_string() + Ok(if cfg!(windows) { + key.to_uppercase() + } else { + key.to_string() + }) }) - }) - .hide(true), + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-sys") - .long("allow-sys") - .short('S') - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("API_NAME") - .help("Allow access to OS information. Optionally allow specific APIs by function name.") - .value_parser(|key: &str| parse_sys_kind(key).map(ToString::to_string)) - .hide(true), + { + let mut arg = Arg::new("allow-sys") + .long("allow-sys") + .short('S') + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("API_NAME") + .help("Allow access to OS information. Optionally allow specific APIs by function name") + .value_parser(|key: &str| SysDescriptor::parse(key.to_string()).map(|s| s.into_string())) + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-sys") - .long("deny-sys") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("API_NAME") - .help("Deny access to OS information. Optionally deny specific APIs by function name.") - .value_parser(|key: &str| parse_sys_kind(key).map(ToString::to_string)) - .hide(true), + { + let mut arg = Arg::new("deny-sys") + .long("deny-sys") + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("API_NAME") + .help("Deny access to OS information. Optionally deny specific APIs by function name") + .value_parser(|key: &str| SysDescriptor::parse(key.to_string()).map(|s| s.into_string())) + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-run") - .long("allow-run") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PROGRAM_NAME") - .help("Allow running subprocesses. Optionally specify allowed runnable program names.") - .hide(true), + { + let mut arg = Arg::new("allow-run") + .long("allow-run") + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("PROGRAM_NAME") + .help("Allow running subprocesses. Optionally specify allowed runnable program names") + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-run") - .long("deny-run") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PROGRAM_NAME") - .help("Deny running subprocesses. Optionally specify denied runnable program names.") - .hide(true), + { + let mut arg = Arg::new("deny-run") + .long("deny-run") + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("PROGRAM_NAME") + .help("Deny running subprocesses. Optionally specify denied runnable program names") + .hide(true) + ; + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + + } ) .arg( - Arg::new("allow-ffi") - .long("allow-ffi") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("(Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("allow-ffi") + .long("allow-ffi") + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("(Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-ffi") - .long("deny-ffi") - .num_args(0..) - .use_value_delimiter(true) - .require_equals(true) - .value_name("PATH") - .help("(Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files.") - .value_parser(value_parser!(String)) - .value_hint(ValueHint::AnyPath) - .hide(true), + { + let mut arg = Arg::new("deny-ffi") + .long("deny-ffi") + .num_args(0..) + .action(ArgAction::Append) + .require_equals(true) + .value_name("PATH") + .help("(Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files") + .value_hint(ValueHint::AnyPath) + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("allow-hrtime") - .long("allow-hrtime") - .action(ArgAction::SetTrue) - .help("Allow high-resolution time measurement. Note: this can enable timing attacks and fingerprinting.") - .hide(true), + { + let mut arg = Arg::new("allow-hrtime") + .long("allow-hrtime") + .action(ArgAction::SetTrue) + .help("REMOVED in Deno 2.0") + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("deny-hrtime") - .long("deny-hrtime") - .action(ArgAction::SetTrue) - .help("Deny high-resolution time measurement. Note: this can prevent timing attacks and fingerprinting.") - .hide(true), + { + let mut arg = Arg::new("deny-hrtime") + .long("deny-hrtime") + .action(ArgAction::SetTrue) + .help("REMOVED in Deno 2.0") + .hide(true); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) .arg( - Arg::new("no-prompt") - .long("no-prompt") - .action(ArgAction::SetTrue) - .hide(true) - .help("Always throw if required permission wasn't passed"), + { + let mut arg = Arg::new("no-prompt") + .long("no-prompt") + .action(ArgAction::SetTrue) + .hide(true) + .help("Always throw if required permission wasn't passed"); + if let Some(requires) = requires { + arg = arg.requires(requires) + } + arg + } ) + .arg( + { + let mut arg = allow_import_arg().hide(true); + if let Some(requires) = requires { + // allow this for install --global + if requires != "global" { + arg = arg.requires(requires) + } + } + arg + } + ) +} + +fn allow_all_arg() -> Arg { + Arg::new("allow-all") + .short('A') + .long("allow-all") + .conflicts_with("allow-read") + .conflicts_with("allow-write") + .conflicts_with("allow-net") + .conflicts_with("allow-env") + .conflicts_with("allow-run") + .conflicts_with("allow-sys") + .conflicts_with("allow-ffi") + .conflicts_with("allow-import") + .action(ArgAction::SetTrue) + .help("Allow all permissions") } fn runtime_args( app: Command, include_perms: bool, include_inspector: bool, + include_allow_scripts: bool, ) -> Command { let app = compile_args(app); let app = if include_perms { - permission_args(app) + permission_args(app, None) } else { app }; @@ -3499,6 +3663,15 @@ fn runtime_args( } else { app }; + let app = if include_allow_scripts { + app.arg(allow_scripts_arg()) + } else { + app + }; + runtime_misc_args(app) +} + +fn runtime_misc_args(app: Command) -> Command { app .arg(frozen_lockfile_arg()) .arg(cached_only_arg()) @@ -3509,13 +3682,28 @@ fn runtime_args( .arg(strace_ops_arg()) } +fn allow_import_arg() -> Arg { + Arg::new("allow-import") + .long("allow-import") + .short('I') + .num_args(0..) + .use_value_delimiter(true) + .require_equals(true) + .value_name("IP_OR_HOSTNAME") + .help(cstr!( + "Allow importing from remote hosts. Optionally specify allowed IP addresses and host names, with ports as necessary. Default value: deno.land:443,jsr.io:443,esm.sh:443,cdn.jsdelivr.net:443,raw.githubusercontent.com:443,user.githubusercontent.com:443" + )) + .value_parser(flags_net::validator) +} + fn inspect_args(app: Command) -> Command { app .arg( Arg::new("inspect") .long("inspect") .value_name("HOST_AND_PORT") - .help("Activate inspector on host:port (default: 127.0.0.1:9229)") + .default_missing_value("127.0.0.1:9229") + .help(cstr!("Activate inspector on host:port [default: 127.0.0.1:9229]")) .num_args(0..=1) .require_equals(true) .value_parser(value_parser!(SocketAddr)) @@ -3525,6 +3713,7 @@ fn inspect_args(app: Command) -> Command { Arg::new("inspect-brk") .long("inspect-brk") .value_name("HOST_AND_PORT") + .default_missing_value("127.0.0.1:9229") .help( "Activate inspector on host:port, wait for debugger to connect and break at the start of user script", ) @@ -3537,6 +3726,7 @@ fn inspect_args(app: Command) -> Command { Arg::new("inspect-wait") .long("inspect-wait") .value_name("HOST_AND_PORT") + .default_missing_value("127.0.0.1:9229") .help( "Activate inspector on host:port and wait for debugger to connect before running user code", ) @@ -3552,10 +3742,10 @@ fn import_map_arg() -> Arg { .long("import-map") .alias("importmap") .value_name("FILE") - .help( - "Load import map file from local file or remote URL. - Docs: https://docs.deno.com/runtime/manual/basics/import_maps", - ) + .help(cstr!( + "Load import map file from local file or remote URL + Docs: https://docs.deno.com/runtime/manual/basics/import_maps", + )) .value_hint(ValueHint::FilePath) .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } @@ -3565,11 +3755,11 @@ fn env_file_arg() -> Arg { .long("env-file") .alias("env") .value_name("FILE") - .help( - "Load environment variables from local file. - Only the first environment variable with a given key is used. - Existing process environment variables are not overwritten.", - ) + .help(cstr!( + "Load environment variables from local file + Only the first environment variable with a given key is used. + Existing process environment variables are not overwritten." + )) .value_hint(ValueHint::FilePath) .default_missing_value(".env") .require_equals(true) @@ -3580,19 +3770,18 @@ fn reload_arg() -> Arg { Arg::new("reload") .short('r') .num_args(0..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .long("reload") .value_name("CACHE_BLOCKLIST") .help( - color_print::cstr!("Reload source code cache (recompile TypeScript) + cstr!("Reload source code cache (recompile TypeScript) no value Reload everything jsr:@std/http/file-server,jsr:@std/assert/assert-equals Reloads specific modules npm: Reload all npm modules npm:chalk Reload specific npm module", )) .value_hint(ValueHint::FilePath) - .value_parser(reload_arg_validate) .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } @@ -3653,7 +3842,9 @@ fn location_arg() -> Arg { url.set_password(None).unwrap(); Ok(url) }) - .help("Value of 'globalThis.location' used by some web APIs") + .help(cstr!( + "Value of globalThis.location used by some web APIs" + )) .value_hint(ValueHint::Url) } @@ -3683,9 +3874,9 @@ fn v8_flags_arg() -> Arg { .use_value_delimiter(true) .require_equals(true) .value_name("V8_FLAGS") - .help("To see a list of all available flags use --v8-flags=--help. - Flags can also be set via the DENO_V8_FLAGS environment variable. - Any flags set with this flag are appended after the DENO_V8_FLAGS environment variable") + .help( cstr!("To see a list of all available flags use --v8-flags=--help + Flags can also be set via the DENO_V8_FLAGS environment variable. + Any flags set with this flag are appended after the DENO_V8_FLAGS environment variable")) } fn seed_arg() -> Arg { @@ -3709,18 +3900,17 @@ fn hmr_arg(takes_files: bool) -> Arg { arg .value_name("FILES") .num_args(0..) - .value_parser(value_parser!(String)) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help( - color_print::cstr!( + cstr!( "Watch for file changes and restart process automatically. Local files from entry point module graph are watched by default. Additional paths might be watched by passing them as arguments to this flag."), ) .value_hint(ValueHint::AnyPath) } else { - arg.action(ArgAction::SetTrue).help(color_print::cstr!( + arg.action(ArgAction::SetTrue).help(cstr!( "Watch for file changes and restart process automatically. Only local files from entry point module graph are watched." )) @@ -3736,18 +3926,17 @@ fn watch_arg(takes_files: bool) -> Arg { arg .value_name("FILES") .num_args(0..) - .value_parser(value_parser!(String)) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .help( - color_print::cstr!( + cstr!( "Watch for file changes and restart process automatically. Local files from entry point module graph are watched by default. Additional paths might be watched by passing them as arguments to this flag."), ) .value_hint(ValueHint::AnyPath) } else { - arg.action(ArgAction::SetTrue).help(color_print::cstr!( + arg.action(ArgAction::SetTrue).help(cstr!( "Watch for file changes and restart process automatically. Only local files from entry point module graph are watched." )) @@ -3776,8 +3965,7 @@ fn watch_exclude_arg() -> Arg { .help("Exclude provided files/patterns from watch mode") .value_name("FILES") .num_args(0..) - .value_parser(value_parser!(String)) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .value_hint(ValueHint::AnyPath) .help_heading(FILE_WATCHING_HEADING) @@ -3789,10 +3977,7 @@ fn no_check_arg() -> Arg { .require_equals(true) .value_name("NO_CHECK_TYPE") .long("no-check") - .help( - "Skip type-checking. If the value of '--no-check=remote' is supplied, - diagnostic errors from remote modules will be ignored.", - ) + .help("Skip type-checking. If the value of \"remote\" is supplied, diagnostic errors from remote modules will be ignored") .help_heading(TYPE_CHECKING_HEADING) } @@ -3807,17 +3992,16 @@ fn check_arg(checks_local_by_default: bool) -> Arg { if checks_local_by_default { arg.help( - "Set type-checking behavior. This subcommand type-checks local modules by - default, so adding --check is redundant. - If the value of \"all\" is supplied, remote modules will be included. - Alternatively, the 'deno check' subcommand can be used.", - ) + cstr!("Set type-checking behavior. This subcommand type-checks local modules by default, so adding --check is redundant + If the value of \"all\" is supplied, remote modules will be included. + Alternatively, the 'deno check' subcommand can be used", + )) } else { - arg.help( - "Enable type-checking. This subcommand does not type-check by default. - If the value of \"all\" is supplied, remote modules will be included. - Alternatively, the 'deno check' subcommand can be used.", - ) + arg.help(cstr!( + "Enable type-checking. This subcommand does not type-check by default + If the value of \"all\" is supplied, remote modules will be included. + Alternatively, the 'deno check' subcommand can be used" + )) } } @@ -3849,16 +4033,6 @@ fn lock_arg() -> Arg { .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } -// TODO(bartlomieju): deprecated, to be removed in Deno 2. -fn lock_write_arg() -> Arg { - Arg::new("lock-write") - .action(ArgAction::SetTrue) - .long("lock-write") - .help("Force overwriting the lock file.") - .conflicts_with("no-lock") - .hide(true) -} - fn no_lock_arg() -> Arg { Arg::new("no-lock") .long("no-lock") @@ -3873,10 +4047,10 @@ fn config_arg() -> Arg { .short('c') .long("config") .value_name("FILE") - .help("Configure different aspects of deno including TypeScript, linting, and code formatting. - Typically the configuration file will be called `deno.json` or `deno.jsonc` and + .help(cstr!("Configure different aspects of deno including TypeScript, linting, and code formatting + Typically the configuration file will be called `deno.json` or `deno.jsonc` and automatically detected; in that case this flag is not necessary. - Docs: https://docs.deno.com/go/config") + Docs: https://docs.deno.com/go/config")) .value_hint(ValueHint::FilePath) } @@ -3884,7 +4058,7 @@ fn no_config_arg() -> Arg { Arg::new("no-config") .long("no-config") .action(ArgAction::SetTrue) - .help("Disable automatic loading of the configuration file.") + .help("Disable automatic loading of the configuration file") .conflicts_with("config") } @@ -3904,15 +4078,36 @@ fn no_npm_arg() -> Arg { .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } +fn node_modules_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { + let value = matches.remove_one::("node-modules-dir"); + if let Some(mode) = value { + flags.node_modules_dir = Some(mode); + } +} + fn node_modules_dir_arg() -> Arg { + fn parse_node_modules_dir_mode( + s: &str, + ) -> Result { + match s { + "auto" | "true" => Ok(NodeModulesDirMode::Auto), + "manual" => Ok(NodeModulesDirMode::Manual), + "none" | "false" => Ok(NodeModulesDirMode::None), + _ => Err(format!( + "Invalid value '{}': expected \"auto\", \"manual\" or \"none\"", + s + )), + } + } + Arg::new("node-modules-dir") .long("node-modules-dir") .num_args(0..=1) - .value_parser(value_parser!(bool)) - .value_name("DIRECTORY") - .default_missing_value("true") + .default_missing_value("auto") + .value_parser(clap::builder::ValueParser::new(parse_node_modules_dir_mode)) + .value_name("MODE") .require_equals(true) - .help("Enables or disables the use of a local node_modules folder for npm packages") + .help("Sets the node modules management mode for npm packages") .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } @@ -3923,10 +4118,7 @@ fn vendor_arg() -> Arg { .value_parser(value_parser!(bool)) .default_missing_value("true") .require_equals(true) - .help( - "Enables or disables the use of a local vendor folder - for remote modules and node_modules folder for npm packages", - ) + .help("Toggles local vendor folder usage for remote modules and a node_modules folder for npm packages") .help_heading(DEPENDENCY_MANAGEMENT_HEADING) } @@ -3946,11 +4138,12 @@ fn allow_scripts_arg() -> Arg { Arg::new("allow-scripts") .long("allow-scripts") .num_args(0..) - .use_value_delimiter(true) + .action(ArgAction::Append) .require_equals(true) .value_name("PACKAGE") .value_parser(parse_packages_allowed_scripts) - .help("Allow running npm lifecycle scripts for the given packages. Note: Scripts will only be executed when using a node_modules directory (`--node-modules-dir`)") + .help(cstr!("Allow running npm lifecycle scripts for the given packages + Note: Scripts will only be executed when using a node_modules directory (`--node-modules-dir`)")) } enum UnstableArgsConfig { @@ -3960,22 +4153,29 @@ enum UnstableArgsConfig { ResolutionAndRuntime, } -struct UnstableArgsIter { - idx: usize, - cfg: UnstableArgsConfig, +trait CommandExt { + fn with_unstable_args(self, cfg: UnstableArgsConfig) -> Self; } -impl Iterator for UnstableArgsIter { - type Item = Arg; +impl CommandExt for Command { + fn with_unstable_args(self, cfg: UnstableArgsConfig) -> Self { + let mut next_display_order = { + let mut value = 1000; + move || { + value += 1; + value + } + }; - fn next(&mut self) -> Option { - let arg = if self.idx == 0 { + let mut cmd = self.arg( Arg::new("unstable") - .long("unstable") - .help("Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features.\n To view the list of individual unstable feature flags, run this command again with --help=unstable.") - .action(ArgAction::SetTrue) - .hide(matches!(self.cfg, UnstableArgsConfig::None)) - } else if self.idx == 1 { + .long("unstable") + .help(cstr!("Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features + To view the list of individual unstable feature flags, run this command again with --help=unstable")) + .action(ArgAction::SetTrue) + .hide(matches!(cfg, UnstableArgsConfig::None)) + .display_order(next_display_order()) + ).arg( Arg::new("unstable-bare-node-builtins") .long("unstable-bare-node-builtins") .help("Enable unstable bare node builtins feature") @@ -3983,80 +4183,104 @@ impl Iterator for UnstableArgsIter { .value_parser(FalseyValueParser::new()) .action(ArgAction::SetTrue) .hide(true) - .long_help(match self.cfg { + .long_help(match cfg { UnstableArgsConfig::None => None, UnstableArgsConfig::ResolutionOnly | UnstableArgsConfig::ResolutionAndRuntime => Some("true"), }) .help_heading(UNSTABLE_HEADING) - } else if self.idx == 2 { - Arg::new("unstable-byonm") - .long("unstable-byonm") - .help("Enable unstable 'bring your own node_modules' feature") - .env("DENO_UNSTABLE_BYONM") + .display_order(next_display_order()), + ).arg( + Arg::new("unstable-detect-cjs") + .long("unstable-detect-cjs") + .help("Reads the package.json type field in a project to treat .js files as .cjs") .value_parser(FalseyValueParser::new()) .action(ArgAction::SetTrue) .hide(true) - .long_help(match self.cfg { + .long_help(match cfg { UnstableArgsConfig::None => None, UnstableArgsConfig::ResolutionOnly | UnstableArgsConfig::ResolutionAndRuntime => Some("true"), }) .help_heading(UNSTABLE_HEADING) - } else if self.idx == 3 { + .display_order(next_display_order()) + ).arg( + Arg::new("unstable-byonm") + .long("unstable-byonm") + .value_parser(FalseyValueParser::new()) + .action(ArgAction::SetTrue) + .hide(true) + .help_heading(UNSTABLE_HEADING) + .display_order(next_display_order()), + ).arg( Arg::new("unstable-sloppy-imports") .long("unstable-sloppy-imports") - .help( - "Enable unstable resolving of specifiers by extension probing, .js to .ts, and directory probing.", - ) + .help("Enable unstable resolving of specifiers by extension probing, .js to .ts, and directory probing") .env("DENO_UNSTABLE_SLOPPY_IMPORTS") .value_parser(FalseyValueParser::new()) .action(ArgAction::SetTrue) .hide(true) - .long_help(match self.cfg { + .long_help(match cfg { UnstableArgsConfig::None => None, UnstableArgsConfig::ResolutionOnly | UnstableArgsConfig::ResolutionAndRuntime => Some("true") }) .help_heading(UNSTABLE_HEADING) - } else if self.idx > 3 { - let (flag_name, help, _) = - crate::UNSTABLE_GRANULAR_FLAGS.get(self.idx - 4)?; - Arg::new(format!("unstable-{}", flag_name)) - .long(format!("unstable-{}", flag_name)) - .help(help) - .action(ArgAction::SetTrue) - .hide(true) - .help_heading(UNSTABLE_HEADING) - // we don't render long help, so using it here as a sort of metadata - .long_help(match self.cfg { - UnstableArgsConfig::None | UnstableArgsConfig::ResolutionOnly => None, - UnstableArgsConfig::ResolutionAndRuntime => Some("true"), - }) - } else { - return None; - }; - self.idx += 1; - Some(arg.display_order(self.idx + 1000)) + .display_order(next_display_order()) + ); + + for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS.iter() { + cmd = cmd.arg( + Arg::new(format!("unstable-{}", granular_flag.name)) + .long(format!("unstable-{}", granular_flag.name)) + .help(granular_flag.help_text) + .action(ArgAction::SetTrue) + .hide(true) + .help_heading(UNSTABLE_HEADING) + // we don't render long help, so using it here as a sort of metadata + .long_help(if granular_flag.show_in_help { + match cfg { + UnstableArgsConfig::None | UnstableArgsConfig::ResolutionOnly => { + None + } + UnstableArgsConfig::ResolutionAndRuntime => Some("true"), + } + } else { + None + }) + .display_order(next_display_order()), + ); + } + + cmd } } -fn unstable_args(cfg: UnstableArgsConfig) -> impl IntoIterator { - UnstableArgsIter { idx: 0, cfg } -} - -fn allow_scripts_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn allow_scripts_arg_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { let Some(parts) = matches.remove_many::("allow-scripts") else { - return; + return Ok(()); }; if parts.len() == 0 { flags.allow_scripts = PackagesAllowedScripts::All; } else { - flags.allow_scripts = PackagesAllowedScripts::Some(parts.collect()); + flags.allow_scripts = PackagesAllowedScripts::Some( + parts + .flat_map(flat_escape_split_commas) + .collect::>()?, + ); } + Ok(()) } -fn add_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn add_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + allow_scripts_arg_parse(flags, matches)?; flags.subcommand = DenoSubcommand::Add(add_parse_inner(matches, None)); + Ok(()) } fn add_parse_inner( @@ -4066,7 +4290,8 @@ fn add_parse_inner( let packages = packages .unwrap_or_else(|| matches.remove_many::("packages").unwrap()) .collect(); - AddFlags { packages } + let dev = matches.get_flag("dev"); + AddFlags { packages, dev } } fn remove_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -4075,10 +4300,14 @@ fn remove_parse(flags: &mut Flags, matches: &mut ArgMatches) { }); } -fn bench_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn bench_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { flags.type_check_mode = TypeCheckMode::Local; - runtime_args_parse(flags, matches, true, false); + runtime_args_parse(flags, matches, true, false, true)?; + ext_arg_parse(flags, matches); // NOTE: `deno bench` always uses `--no-prompt`, tests shouldn't ever do // interactive prompts, unless done by user code @@ -4087,7 +4316,9 @@ fn bench_parse(flags: &mut Flags, matches: &mut ArgMatches) { let json = matches.get_flag("json"); let ignore = match matches.remove_many::("ignore") { - Some(f) => f.collect(), + Some(f) => f + .flat_map(flat_escape_split_commas) + .collect::>()?, None => vec![], }; @@ -4112,62 +4343,61 @@ fn bench_parse(flags: &mut Flags, matches: &mut ArgMatches) { filter, json, no_run, - watch: watch_arg_parse(matches), + watch: watch_arg_parse(matches)?, }); + + Ok(()) } -fn bundle_parse(flags: &mut Flags, matches: &mut ArgMatches) { - flags.type_check_mode = TypeCheckMode::Local; - - compile_args_parse(flags, matches); - unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); - - let source_file = matches.remove_one::("source_file").unwrap(); - - let out_file = - if let Some(out_file) = matches.remove_one::("out_file") { - flags.permissions.allow_write = Some(vec![]); - Some(out_file) - } else { - None - }; - - ext_arg_parse(flags, matches); - - flags.subcommand = DenoSubcommand::Bundle(BundleFlags { - source_file, - out_file, - watch: watch_arg_parse(matches), - }); +fn bundle_parse(flags: &mut Flags, _matches: &mut ArgMatches) { + flags.subcommand = DenoSubcommand::Bundle; } -fn cache_parse(flags: &mut Flags, matches: &mut ArgMatches) { - compile_args_parse(flags, matches); +fn cache_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + compile_args_parse(flags, matches)?; unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); frozen_lockfile_arg_parse(flags, matches); - allow_scripts_arg_parse(flags, matches); + allow_scripts_arg_parse(flags, matches)?; + allow_import_parse(flags, matches); let files = matches.remove_many::("file").unwrap().collect(); flags.subcommand = DenoSubcommand::Cache(CacheFlags { files }); + Ok(()) } -fn check_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn check_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { flags.type_check_mode = TypeCheckMode::Local; - compile_args_without_check_parse(flags, matches); + compile_args_without_check_parse(flags, matches)?; unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); + frozen_lockfile_arg_parse(flags, matches); let files = matches.remove_many::("file").unwrap().collect(); if matches.get_flag("all") || matches.get_flag("remote") { flags.type_check_mode = TypeCheckMode::All; } - flags.subcommand = DenoSubcommand::Check(CheckFlags { files }); + flags.subcommand = DenoSubcommand::Check(CheckFlags { + files, + doc: matches.get_flag("doc"), + doc_only: matches.get_flag("doc-only"), + }); + allow_import_parse(flags, matches); + Ok(()) } fn clean_parse(flags: &mut Flags, _matches: &mut ArgMatches) { flags.subcommand = DenoSubcommand::Clean; } -fn compile_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn compile_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { flags.type_check_mode = TypeCheckMode::Local; - runtime_args_parse(flags, matches, true, false); + runtime_args_parse(flags, matches, true, false, true)?; let mut script = matches.remove_many::("script_arg").unwrap(); let source_file = script.next().unwrap(); @@ -4191,6 +4421,8 @@ fn compile_parse(flags: &mut Flags, matches: &mut ArgMatches) { icon, include, }); + + Ok(()) } fn completions_parse( @@ -4222,13 +4454,18 @@ fn completions_parse( }); } -fn coverage_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn coverage_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { let files = match matches.remove_many::("files") { Some(f) => f.collect(), None => vec!["coverage".to_string()], // default }; let ignore = match matches.remove_many::("ignore") { - Some(f) => f.collect(), + Some(f) => f + .flat_map(flat_escape_split_commas) + .collect::, _>>()?, None => vec![], }; let include = match matches.remove_many::("include") { @@ -4259,16 +4496,21 @@ fn coverage_parse(flags: &mut Flags, matches: &mut ArgMatches) { exclude, r#type, }); + Ok(()) } -fn doc_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn doc_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); import_map_arg_parse(flags, matches); - reload_arg_parse(flags, matches); + reload_arg_parse(flags, matches)?; lock_arg_parse(flags, matches); no_lock_arg_parse(flags, matches); no_npm_arg_parse(flags, matches); no_remote_arg_parse(flags, matches); + allow_import_parse(flags, matches); let source_files_val = matches.remove_many::("source_file"); let source_files = if let Some(val) = source_files_val { @@ -4323,39 +4565,32 @@ fn doc_parse(flags: &mut Flags, matches: &mut ArgMatches) { filter, private, }); + Ok(()) } -fn eval_parse(flags: &mut Flags, matches: &mut ArgMatches) { - runtime_args_parse(flags, matches, false, true); +fn eval_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + runtime_args_parse(flags, matches, false, true, false)?; unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); flags.allow_all(); ext_arg_parse(flags, matches); - // TODO(@satyarohith): remove this flag in 2.0. - let as_typescript = matches.get_flag("ts"); - - #[allow(clippy::print_stderr)] - if as_typescript { - eprintln!( - "⚠️ {}", - crate::colors::yellow( - "Use `--ext=ts` instead. The `--ts` and `-T` flags are deprecated and will be removed in Deno 2.0." - ), - ); - - flags.ext = Some("ts".to_string()); - } - let print = matches.get_flag("print"); let mut code_args = matches.remove_many::("code_arg").unwrap(); let code = code_args.next().unwrap(); flags.argv.extend(code_args); flags.subcommand = DenoSubcommand::Eval(EvalFlags { print, code }); + Ok(()) } -fn fmt_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn fmt_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { config_args_parse(flags, matches); ext_arg_parse(flags, matches); @@ -4364,7 +4599,9 @@ fn fmt_parse(flags: &mut Flags, matches: &mut ArgMatches) { None => vec![], }; let ignore = match matches.remove_many::("ignore") { - Some(f) => f.collect(), + Some(f) => f + .flat_map(flat_escape_split_commas) + .collect::, _>>()?, None => vec![], }; @@ -4374,10 +4611,7 @@ fn fmt_parse(flags: &mut Flags, matches: &mut ArgMatches) { let single_quote = matches.remove_one::("single-quote"); let prose_wrap = matches.remove_one::("prose-wrap"); let no_semicolons = matches.remove_one::("no-semicolons"); - let unstable_css = matches.get_flag("unstable-css"); - let unstable_html = matches.get_flag("unstable-html"); let unstable_component = matches.get_flag("unstable-component"); - let unstable_yaml = matches.get_flag("unstable-yaml"); flags.subcommand = DenoSubcommand::Fmt(FmtFlags { check: matches.get_flag("check"), @@ -4388,12 +4622,10 @@ fn fmt_parse(flags: &mut Flags, matches: &mut ArgMatches) { single_quote, prose_wrap, no_semicolons, - watch: watch_arg_parse(matches), - unstable_css, - unstable_html, + watch: watch_arg_parse(matches)?, unstable_component, - unstable_yaml, }); + Ok(()) } fn init_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -4404,9 +4636,12 @@ fn init_parse(flags: &mut Flags, matches: &mut ArgMatches) { }); } -fn info_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn info_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); - reload_arg_parse(flags, matches); + reload_arg_parse(flags, matches)?; config_args_parse(flags, matches); import_map_arg_parse(flags, matches); location_arg_parse(flags, matches); @@ -4416,18 +4651,24 @@ fn info_parse(flags: &mut Flags, matches: &mut ArgMatches) { lock_args_parse(flags, matches); no_remote_arg_parse(flags, matches); no_npm_arg_parse(flags, matches); + allow_import_parse(flags, matches); let json = matches.get_flag("json"); flags.subcommand = DenoSubcommand::Info(InfoFlags { file: matches.remove_one::("file"), json, }); + + Ok(()) } -fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) { - runtime_args_parse(flags, matches, true, true); +fn install_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + runtime_args_parse(flags, matches, true, true, false)?; let global = matches.get_flag("global"); - if global || !*DENO_FUTURE { + if global { let root = matches.remove_one::("root"); let force = matches.get_flag("force"); let name = matches.remove_one::("name"); @@ -4438,8 +4679,6 @@ fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) { let args = cmd_values.collect(); flags.subcommand = DenoSubcommand::Install(InstallFlags { - // TODO(bartlomieju): remove for 2.0 - global, kind: InstallKind::Global(InstallFlagsGlobal { name, module_url, @@ -4448,16 +4687,32 @@ fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) { force, }), }); - } else { - let local_flags = matches - .remove_many("cmd") - .map(|packages| add_parse_inner(matches, Some(packages))); - allow_scripts_arg_parse(flags, matches); - flags.subcommand = DenoSubcommand::Install(InstallFlags { - global, - kind: InstallKind::Local(local_flags), - }) + + return Ok(()); } + + // allow scripts only applies to local install + allow_scripts_arg_parse(flags, matches)?; + if matches.get_flag("entrypoint") { + let entrypoints = matches.remove_many::("cmd").unwrap_or_default(); + flags.subcommand = DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(InstallFlagsLocal::Entrypoints( + entrypoints.collect(), + )), + }); + } else if let Some(add_files) = matches + .remove_many("cmd") + .map(|packages| add_parse_inner(matches, Some(packages))) + { + flags.subcommand = DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(InstallFlagsLocal::Add(add_files)), + }) + } else { + flags.subcommand = DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(InstallFlagsLocal::TopLevel), + }); + } + Ok(()) } fn json_reference_parse( @@ -4470,7 +4725,7 @@ fn json_reference_parse( app.build(); fn serialize_command( - command: &mut Command, + mut command: Command, top_level: bool, ) -> deno_core::serde_json::Value { let args = command @@ -4478,7 +4733,7 @@ fn json_reference_parse( .filter(|arg| { !arg.is_hide_set() && if top_level { - true + arg.is_global_set() } else { !arg.is_global_set() } @@ -4487,40 +4742,49 @@ fn json_reference_parse( let name = arg.get_id().as_str(); let short = arg.get_short(); let long = arg.get_long(); - let aliases = arg.get_visible_aliases(); let required = arg.is_required_set(); - let help = arg.get_help().map(|help| help.to_string()); + let help = arg.get_help().map(|help| help.ansi().to_string()); + let help_heading = arg + .get_help_heading() + .map(|help_heading| help_heading.to_string()); let usage = arg.to_string(); json!({ "name": name, "short": short, "long": long, - "aliases": aliases, "required": required, "help": help, + "help_heading": help_heading, "usage": usage, }) }) .collect::>(); let name = command.get_name().to_string(); - let about = command.get_about().map(|about| about.to_string()); - let visible_aliases = command - .get_visible_aliases() - .map(|s| s.to_string()) - .collect::>(); - let usage = command.render_usage().to_string(); + let about = command.get_about().map(|about| about.ansi().to_string()); + let usage = command.render_usage().ansi().to_string(); let subcommands = command - .get_subcommands_mut() - .map(|command| serialize_command(command, false)) + .get_subcommands() + .map(|command| { + serialize_command( + if command + .get_arguments() + .any(|arg| arg.get_id().as_str() == "unstable") + { + enable_unstable(command.clone()) + } else { + command.clone() + }, + false, + ) + }) .collect::>(); json!({ "name": name, "about": about, - "visible_aliases": visible_aliases, "args": args, "subcommands": subcommands, "usage": usage, @@ -4528,11 +4792,13 @@ fn json_reference_parse( } flags.subcommand = DenoSubcommand::JSONReference(JSONReferenceFlags { - json: serialize_command(&mut app, true), + json: serialize_command(app, true), }) } fn jupyter_parse(flags: &mut Flags, matches: &mut ArgMatches) { + unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); + let conn_file = matches.remove_one::("conn"); let kernel = matches.get_flag("kernel"); let install = matches.get_flag("install"); @@ -4545,31 +4811,46 @@ fn jupyter_parse(flags: &mut Flags, matches: &mut ArgMatches) { } fn uninstall_parse(flags: &mut Flags, matches: &mut ArgMatches) { - let root = matches.remove_one::("root"); - let global = matches.get_flag("global"); - let name = matches.remove_one::("name").unwrap(); - flags.subcommand = DenoSubcommand::Uninstall(UninstallFlags { - // TODO(bartlomieju): remove once `deno uninstall` supports both local and - // global installs - global, - kind: UninstallKind::Global(UninstallFlagsGlobal { name, root }), - }); + let name = matches.remove_one::("name-or-package").unwrap(); + + let kind = if matches.get_flag("global") { + let root = matches.remove_one::("root"); + UninstallKind::Global(UninstallFlagsGlobal { name, root }) + } else { + let packages: Vec<_> = vec![name] + .into_iter() + .chain( + matches + .remove_many::("additional-packages") + .unwrap_or_default(), + ) + .collect(); + UninstallKind::Local(RemoveFlags { packages }) + }; + + flags.subcommand = DenoSubcommand::Uninstall(UninstallFlags { kind }); } fn lsp_parse(flags: &mut Flags, _matches: &mut ArgMatches) { flags.subcommand = DenoSubcommand::Lsp; } -fn lint_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn lint_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); - + ext_arg_parse(flags, matches); config_args_parse(flags, matches); + let files = match matches.remove_many::("files") { Some(f) => f.collect(), None => vec![], }; let ignore = match matches.remove_many::("ignore") { - Some(f) => f.collect(), + Some(f) => f + .flat_map(flat_escape_split_commas) + .collect::, _>>()?, None => vec![], }; let fix = matches.get_flag("fix"); @@ -4588,7 +4869,6 @@ fn lint_parse(flags: &mut Flags, matches: &mut ArgMatches) { let json = matches.get_flag("json"); let compact = matches.get_flag("compact"); - let ext = matches.remove_one::("ext"); flags.subcommand = DenoSubcommand::Lint(LintFlags { files: FileFlags { @@ -4602,18 +4882,40 @@ fn lint_parse(flags: &mut Flags, matches: &mut ArgMatches) { maybe_rules_exclude, json, compact, - watch: watch_arg_parse(matches), - ext, + watch: watch_arg_parse(matches)?, }); + Ok(()) } -fn repl_parse(flags: &mut Flags, matches: &mut ArgMatches) { - runtime_args_parse(flags, matches, true, true); - unsafely_ignore_certificate_errors_parse(flags, matches); +fn repl_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); + compile_args_without_check_parse(flags, matches)?; + cached_only_arg_parse(flags, matches); + frozen_lockfile_arg_parse(flags, matches); + permission_args_parse(flags, matches)?; + inspect_arg_parse(flags, matches); + location_arg_parse(flags, matches); + v8_flags_arg_parse(flags, matches); + seed_arg_parse(flags, matches); + enable_testing_features_arg_parse(flags, matches); + env_file_arg_parse(flags, matches); + strace_ops_parse(flags, matches); let eval_files = matches .remove_many::("eval-file") - .map(|values| values.collect()); + .map(|values| { + values + .flat_map(flat_escape_split_commas) + .collect::, _>>() + }) + .transpose()?; + + if let Some(args) = matches.remove_many::("args") { + flags.argv.extend(args); + } handle_repl_flags( flags, @@ -4623,6 +4925,7 @@ fn repl_parse(flags: &mut Flags, matches: &mut ArgMatches) { is_default_command: false, }, ); + Ok(()) } fn run_parse( @@ -4631,83 +4934,30 @@ fn run_parse( mut app: Command, bare: bool, ) -> clap::error::Result<()> { - // todo(dsherret): remove this in Deno 2.0 - // This is a hack to make https://github.com/netlify/build/pull/5767 work - // for old versions of @netlify/edge-bundler with new versions of Deno - // where Deno has gotten smarter at resolving config files. - // - // It's an unfortunate scenario, but Netlify has the version at least - // pinned to 1.x in old versions so we can remove this in Deno 2.0 in - // a few months. - fn temp_netlify_deno_1_hack(flags: &mut Flags, script_arg: &str) { - fn is_netlify_edge_bundler_entrypoint( - flags: &Flags, - script_arg: &str, - ) -> bool { - // based on diff here: https://github.com/netlify/edge-bundler/blame/f1d33b74ca7aeec19a7c2149316d4547a94e43fb/node/config.ts#L85 - if flags.permissions.allow_read.is_none() - || flags.permissions.allow_write.is_none() - || flags.config_flag != ConfigFlag::Discover - { - return false; - } - if !script_arg.contains("@netlify") { - return false; - } - let path = PathBuf::from(script_arg); - if !path.ends_with("deno/config.ts") { - return false; - } - let mut found_node_modules = false; - for component in path.components().filter_map(|c| c.as_os_str().to_str()) - { - if !found_node_modules { - found_node_modules = component == "node_modules"; - } else { - // make this work with pnpm and other package managers - if component.contains("@netlify") { - return true; - } - } - } - false - } - - if is_netlify_edge_bundler_entrypoint(flags, script_arg) { - flags.config_flag = ConfigFlag::Disabled; - } - } - - runtime_args_parse(flags, matches, true, true); + runtime_args_parse(flags, matches, true, true, true)?; + ext_arg_parse(flags, matches); flags.code_cache_enabled = !matches.get_flag("no-code-cache"); - let mut script_arg = - matches.remove_many::("script_arg").ok_or_else(|| { - if bare { - app.override_usage("deno [OPTIONS] [COMMAND] [SCRIPT_ARG]...").error( - clap::error::ErrorKind::MissingRequiredArgument, - "[SCRIPT_ARG] may only be omitted with --v8-flags=--help, else to use the repl with arguments, please use the `deno repl` subcommand", - ) - } else { - app.find_subcommand_mut("run").unwrap().error( - clap::error::ErrorKind::MissingRequiredArgument, - "[SCRIPT_ARG] may only be omitted with --v8-flags=--help", - ) - } - })?; - - let script = script_arg.next().unwrap(); - flags.argv.extend(script_arg); - - ext_arg_parse(flags, matches); - temp_netlify_deno_1_hack(flags, &script); - - flags.subcommand = DenoSubcommand::Run(RunFlags { - script, - watch: watch_arg_parse_with_paths(matches), - bare, - }); + if let Some(mut script_arg) = matches.remove_many::("script_arg") { + let script = script_arg.next().unwrap(); + flags.argv.extend(script_arg); + flags.subcommand = DenoSubcommand::Run(RunFlags { + script, + watch: watch_arg_parse_with_paths(matches)?, + bare, + }); + } else if bare { + return Err(app.override_usage("deno [OPTIONS] [COMMAND] [SCRIPT_ARG]...").error( + clap::error::ErrorKind::MissingRequiredArgument, + "[SCRIPT_ARG] may only be omitted with --v8-flags=--help, else to use the repl with arguments, please use the `deno repl` subcommand", + )); + } else { + return Err(app.find_subcommand_mut("run").unwrap().error( + clap::error::ErrorKind::MissingRequiredArgument, + "[SCRIPT_ARG] may only be omitted with --v8-flags=--help", + )); + } Ok(()) } @@ -4723,9 +4973,9 @@ fn serve_parse( .remove_one::("host") .unwrap_or_else(|| "0.0.0.0".to_owned()); - let worker_count = parallel_arg_parse(matches, false).map(|v| v.get()); + let worker_count = parallel_arg_parse(matches).map(|v| v.get()); - runtime_args_parse(flags, matches, true, true); + runtime_args_parse(flags, matches, true, true, true)?; // If the user didn't pass --allow-net, add this port to the network // allowlist. If the host is 0.0.0.0, we add :{port} and allow the same network perms // as if it was passed to --allow-net directly. @@ -4735,7 +4985,10 @@ fn serve_parse( format!("{host}:{port}") }])?; match &mut flags.permissions.allow_net { - None => flags.permissions.allow_net = Some(allowed), + None if !flags.permissions.allow_all => { + flags.permissions.allow_net = Some(allowed) + } + None => {} Some(v) => { if !v.is_empty() { v.extend(allowed); @@ -4761,7 +5014,7 @@ fn serve_parse( flags.subcommand = DenoSubcommand::Serve(ServeFlags { script, - watch: watch_arg_parse_with_paths(matches), + watch: watch_arg_parse_with_paths(matches)?, port, host, worker_count, @@ -4777,10 +5030,12 @@ fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) { .unwrap_or(ConfigFlag::Discover); unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); + node_modules_arg_parse(flags, matches); let mut task_flags = TaskFlags { cwd: matches.remove_one::("cwd"), task: None, + is_run: false, }; if let Some((task, mut matches)) = matches.remove_subcommand() { @@ -4798,81 +5053,42 @@ fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) { flags.subcommand = DenoSubcommand::Task(task_flags); } -fn parallel_arg_parse( - matches: &mut ArgMatches, - fallback_to_jobs: bool, -) -> Option { +fn parallel_arg_parse(matches: &mut ArgMatches) -> Option { if matches.get_flag("parallel") { if let Ok(value) = env::var("DENO_JOBS") { value.parse::().ok() } else { std::thread::available_parallelism().ok() } - } else if fallback_to_jobs && matches.contains_id("jobs") { - // We can't change this to use the log crate because its not configured - // yet at this point since the flags haven't been parsed. This flag is - // deprecated though so it's not worth changing the code to use the log - // crate here and this is only done for testing anyway. - #[allow(clippy::print_stderr)] - { - eprintln!( - "⚠️ {}", - crate::colors::yellow(concat!( - "The `--jobs` flag is deprecated and will be removed in Deno 2.0.\n", - "Use the `--parallel` flag with possibly the `DENO_JOBS` environment variable instead.\n", - "Learn more at: https://docs.deno.com/runtime/manual/basics/env_variables" - )), - ); - } - if let Some(value) = matches.remove_one::("jobs") { - Some(value) - } else { - std::thread::available_parallelism().ok() - } } else { None } } -fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn test_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { flags.type_check_mode = TypeCheckMode::Local; - runtime_args_parse(flags, matches, true, true); + runtime_args_parse(flags, matches, true, true, true)?; + ext_arg_parse(flags, matches); + // NOTE: `deno test` always uses `--no-prompt`, tests shouldn't ever do // interactive prompts, unless done by user code flags.permissions.no_prompt = true; let ignore = match matches.remove_many::("ignore") { - Some(f) => f.collect(), + Some(f) => f + .flat_map(flat_escape_split_commas) + .collect::>()?, None => vec![], }; let no_run = matches.get_flag("no-run"); - let trace_leaks = - matches.get_flag("trace-ops") || matches.get_flag("trace-leaks"); - - #[allow(clippy::print_stderr)] - if trace_leaks && matches.get_flag("trace-ops") { - // We can't change this to use the log crate because its not configured - // yet at this point since the flags haven't been parsed. This flag is - // deprecated though so it's not worth changing the code to use the log - // crate here and this is only done for testing anyway. - eprintln!( - "⚠️ {}", - crate::colors::yellow("The `--trace-ops` flag is deprecated and will be removed in Deno 2.0.\nUse the `--trace-leaks` flag instead."), - ); - } + let trace_leaks = matches.get_flag("trace-leaks"); let doc = matches.get_flag("doc"); #[allow(clippy::print_stderr)] - let allow_none = matches.get_flag("permit-no-files") - || if matches.get_flag("allow-none") { - eprintln!( - "⚠️ {}", - crate::colors::yellow("The `--allow-none` flag is deprecated and will be removed in Deno 2.0.\nUse the `--permit-no-files` flag instead."), - ); - true - } else { - false - }; + let permit_no_files = matches.get_flag("permit-no-files"); let filter = matches.remove_one::("filter"); let clean = matches.get_flag("clean"); @@ -4900,7 +5116,7 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { flags.argv.extend(script_arg); } - let concurrent_jobs = parallel_arg_parse(matches, true); + let concurrent_jobs = parallel_arg_parse(matches); let include = if let Some(files) = matches.remove_many::("files") { files.collect() @@ -4938,14 +5154,15 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { files: FileFlags { include, ignore }, filter, shuffle, - allow_none, + permit_no_files, concurrent_jobs, trace_leaks, - watch: watch_arg_parse_with_paths(matches), + watch: watch_arg_parse_with_paths(matches)?, reporter, junit_path, hide_stacktraces, }); + Ok(()) } fn types_parse(flags: &mut Flags, _matches: &mut ArgMatches) { @@ -4975,24 +5192,8 @@ fn upgrade_parse(flags: &mut Flags, matches: &mut ArgMatches) { }); } -fn vendor_parse(flags: &mut Flags, matches: &mut ArgMatches) { - unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); - ca_file_arg_parse(flags, matches); - unsafely_ignore_certificate_errors_parse(flags, matches); - config_args_parse(flags, matches); - import_map_arg_parse(flags, matches); - lock_arg_parse(flags, matches); - node_modules_and_vendor_dir_arg_parse(flags, matches); - reload_arg_parse(flags, matches); - - flags.subcommand = DenoSubcommand::Vendor(VendorFlags { - specifiers: matches - .remove_many::("specifiers") - .map(|p| p.collect()) - .unwrap_or_default(), - output_path: matches.remove_one::("output"), - force: matches.get_flag("force"), - }); +fn vendor_parse(flags: &mut Flags, _matches: &mut ArgMatches) { + flags.subcommand = DenoSubcommand::Vendor } fn publish_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -5011,51 +5212,132 @@ fn publish_parse(flags: &mut Flags, matches: &mut ArgMatches) { }); } -fn compile_args_parse(flags: &mut Flags, matches: &mut ArgMatches) { - compile_args_without_check_parse(flags, matches); +fn compile_args_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { + compile_args_without_check_parse(flags, matches)?; no_check_arg_parse(flags, matches); check_arg_parse(flags, matches); + Ok(()) } fn compile_args_without_check_parse( flags: &mut Flags, matches: &mut ArgMatches, -) { +) -> clap::error::Result<()> { import_map_arg_parse(flags, matches); no_remote_arg_parse(flags, matches); no_npm_arg_parse(flags, matches); node_modules_and_vendor_dir_arg_parse(flags, matches); config_args_parse(flags, matches); - reload_arg_parse(flags, matches); + reload_arg_parse(flags, matches)?; lock_args_parse(flags, matches); ca_file_arg_parse(flags, matches); unsafely_ignore_certificate_errors_parse(flags, matches); + Ok(()) } -fn permission_args_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn escape_and_split_commas(s: String) -> Result, clap::Error> { + let mut result = vec![]; + let mut current = String::new(); + let mut chars = s.chars(); + + while let Some(c) = chars.next() { + if c == ',' { + if let Some(next) = chars.next() { + if next == ',' { + current.push(','); + } else { + if current.is_empty() { + return Err( + std::io::Error::new( + std::io::ErrorKind::Other, + String::from("Empty values are not allowed"), + ) + .into(), + ); + } + + result.push(current.clone()); + current.clear(); + current.push(next); + } + } else { + return Err( + std::io::Error::new( + std::io::ErrorKind::Other, + String::from("Empty values are not allowed"), + ) + .into(), + ); + } + } else { + current.push(c); + } + } + + if current.is_empty() { + return Err( + std::io::Error::new( + std::io::ErrorKind::Other, + String::from("Empty values are not allowed"), + ) + .into(), + ); + } + + result.push(current); + + Ok(result) +} + +fn flat_escape_split_commas(str: String) -> Vec> { + match escape_and_split_commas(str) { + Ok(vec) => vec.into_iter().map(Ok).collect::>(), + Err(e) => vec![Err(e)], + } +} + +fn permission_args_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { if let Some(read_wl) = matches.remove_many::("allow-read") { - flags.permissions.allow_read = Some(read_wl.collect()); + let read_wl = read_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.allow_read = Some(read_wl); } if let Some(read_wl) = matches.remove_many::("deny-read") { - flags.permissions.deny_read = Some(read_wl.collect()); + let read_wl = read_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.deny_read = Some(read_wl); } if let Some(write_wl) = matches.remove_many::("allow-write") { - flags.permissions.allow_write = Some(write_wl.collect()); + let write_wl = write_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.allow_write = Some(write_wl); } if let Some(write_wl) = matches.remove_many::("deny-write") { - flags.permissions.deny_write = Some(write_wl.collect()); + let write_wl = write_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.deny_write = Some(write_wl); } if let Some(net_wl) = matches.remove_many::("allow-net") { - let net_allowlist = flags_net::parse(net_wl.collect()).unwrap(); + let net_allowlist = flags_net::parse(net_wl.collect())?; flags.permissions.allow_net = Some(net_allowlist); } if let Some(net_wl) = matches.remove_many::("deny-net") { - let net_denylist = flags_net::parse(net_wl.collect()).unwrap(); + let net_denylist = flags_net::parse(net_wl.collect())?; flags.permissions.deny_net = Some(net_denylist); } @@ -5090,30 +5372,50 @@ fn permission_args_parse(flags: &mut Flags, matches: &mut ArgMatches) { } if let Some(ffi_wl) = matches.remove_many::("allow-ffi") { - flags.permissions.allow_ffi = Some(ffi_wl.collect()); + let ffi_wl = ffi_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.allow_ffi = Some(ffi_wl); debug!("ffi allowlist: {:#?}", &flags.permissions.allow_ffi); } if let Some(ffi_wl) = matches.remove_many::("deny-ffi") { - flags.permissions.deny_ffi = Some(ffi_wl.collect()); + let ffi_wl = ffi_wl + .flat_map(flat_escape_split_commas) + .collect::, _>>()?; + flags.permissions.deny_ffi = Some(ffi_wl); debug!("ffi denylist: {:#?}", &flags.permissions.deny_ffi); } - if matches.get_flag("allow-hrtime") { - flags.permissions.allow_hrtime = true; - } - - if matches.get_flag("deny-hrtime") { - flags.permissions.deny_hrtime = true; + if matches.get_flag("allow-hrtime") || matches.get_flag("deny-hrtime") { + // use eprintln instead of log::warn because logging hasn't been initialized yet + #[allow(clippy::print_stderr)] + { + eprintln!( + "{} `allow-hrtime` and `deny-hrtime` have been removed in Deno 2, as high resolution time is now always allowed", + deno_runtime::colors::yellow("Warning") + ); + } } if matches.get_flag("allow-all") { flags.allow_all(); } + allow_import_parse(flags, matches); + if matches.get_flag("no-prompt") { flags.permissions.no_prompt = true; } + + Ok(()) +} + +fn allow_import_parse(flags: &mut Flags, matches: &mut ArgMatches) { + if let Some(imports_wl) = matches.remove_many::("allow-import") { + let imports_allowlist = flags_net::parse(imports_wl.collect()).unwrap(); + flags.permissions.allow_import = Some(imports_allowlist); + } } fn unsafely_ignore_certificate_errors_parse( @@ -5133,54 +5435,34 @@ fn runtime_args_parse( matches: &mut ArgMatches, include_perms: bool, include_inspector: bool, -) { + include_allow_scripts: bool, +) -> clap::error::Result<()> { unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionAndRuntime); - compile_args_parse(flags, matches); + compile_args_parse(flags, matches)?; cached_only_arg_parse(flags, matches); frozen_lockfile_arg_parse(flags, matches); if include_perms { - permission_args_parse(flags, matches); + permission_args_parse(flags, matches)?; } if include_inspector { inspect_arg_parse(flags, matches); } + if include_allow_scripts { + allow_scripts_arg_parse(flags, matches)?; + } location_arg_parse(flags, matches); v8_flags_arg_parse(flags, matches); seed_arg_parse(flags, matches); enable_testing_features_arg_parse(flags, matches); env_file_arg_parse(flags, matches); strace_ops_parse(flags, matches); + Ok(()) } fn inspect_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { - let default = || "127.0.0.1:9229".parse::().unwrap(); - flags.inspect = if matches.contains_id("inspect") { - Some( - matches - .remove_one::("inspect") - .unwrap_or_else(default), - ) - } else { - None - }; - flags.inspect_brk = if matches.contains_id("inspect-brk") { - Some( - matches - .remove_one::("inspect-brk") - .unwrap_or_else(default), - ) - } else { - None - }; - flags.inspect_wait = if matches.contains_id("inspect-wait") { - Some( - matches - .remove_one::("inspect-wait") - .unwrap_or_else(default), - ) - } else { - None - }; + flags.inspect = matches.remove_one::("inspect"); + flags.inspect_brk = matches.remove_one::("inspect-brk"); + flags.inspect_wait = matches.remove_one::("inspect-wait"); } fn import_map_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -5191,9 +5473,15 @@ fn env_file_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { flags.env_file = matches.remove_one::("env-file"); } -fn reload_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn reload_arg_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { if let Some(cache_bl) = matches.remove_many::("reload") { - let raw_cache_blocklist: Vec = cache_bl.collect(); + let raw_cache_blocklist: Vec = cache_bl + .flat_map(flat_escape_split_commas) + .map(|s| s.and_then(reload_arg_validate)) + .collect::, _>>()?; if raw_cache_blocklist.is_empty() { flags.reload = true; } else { @@ -5202,6 +5490,8 @@ fn reload_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { flags.reload = false; } } + + Ok(()) } fn ca_file_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -5288,10 +5578,6 @@ fn check_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { fn lock_args_parse(flags: &mut Flags, matches: &mut ArgMatches) { lock_arg_parse(flags, matches); no_lock_arg_parse(flags, matches); - // TODO(bartlomieju): deprecated, to be removed in Deno 2. - if matches.get_flag("lock-write") { - flags.lock_write = true; - } } fn lock_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { @@ -5333,65 +5619,94 @@ fn node_modules_and_vendor_dir_arg_parse( flags: &mut Flags, matches: &mut ArgMatches, ) { - flags.node_modules_dir = matches.remove_one::("node-modules-dir"); + node_modules_arg_parse(flags, matches); flags.vendor = matches.remove_one::("vendor"); } -fn reload_arg_validate(urlstr: &str) -> Result { +fn reload_arg_validate(urlstr: String) -> Result { if urlstr.is_empty() { - return Err(String::from("Missing url. Check for extra commas.")); + return Err( + std::io::Error::new( + std::io::ErrorKind::Other, + String::from("Missing url. Check for extra commas."), + ) + .into(), + ); } - match Url::from_str(urlstr) { - Ok(_) => Ok(urlstr.to_string()), - Err(e) => Err(e.to_string()), + match Url::from_str(&urlstr) { + Ok(_) => Ok(urlstr), + Err(e) => { + Err(std::io::Error::new(std::io::ErrorKind::Other, e.to_string()).into()) + } } } -fn watch_arg_parse(matches: &mut ArgMatches) -> Option { +fn watch_arg_parse( + matches: &mut ArgMatches, +) -> clap::error::Result> { if matches.get_flag("watch") { - Some(WatchFlags { + Ok(Some(WatchFlags { hmr: false, no_clear_screen: matches.get_flag("no-clear-screen"), exclude: matches .remove_many::("watch-exclude") - .map(|f| f.collect::>()) + .map(|f| { + f.flat_map(flat_escape_split_commas) + .collect::>() + }) + .transpose()? .unwrap_or_default(), - }) + })) } else { - None + Ok(None) } } fn watch_arg_parse_with_paths( matches: &mut ArgMatches, -) -> Option { +) -> clap::error::Result> { if let Some(paths) = matches.remove_many::("watch") { - return Some(WatchFlagsWithPaths { - paths: paths.collect(), + return Ok(Some(WatchFlagsWithPaths { + paths: paths + .flat_map(flat_escape_split_commas) + .collect::, _>>()?, hmr: false, no_clear_screen: matches.get_flag("no-clear-screen"), exclude: matches .remove_many::("watch-exclude") - .map(|f| f.collect::>()) + .map(|f| { + f.flat_map(flat_escape_split_commas) + .collect::, _>>() + }) + .transpose()? .unwrap_or_default(), - }); + })); } if matches.try_contains_id("hmr").is_ok() { - return matches.remove_many::("hmr").map(|paths| { - WatchFlagsWithPaths { - paths: paths.collect(), - hmr: true, - no_clear_screen: matches.get_flag("no-clear-screen"), - exclude: matches - .remove_many::("watch-exclude") - .map(|f| f.collect::>()) - .unwrap_or_default(), - } - }); + return matches + .remove_many::("hmr") + .map(|paths| { + Ok(WatchFlagsWithPaths { + paths: paths + .flat_map(flat_escape_split_commas) + .collect::, _>>()?, + hmr: true, + no_clear_screen: matches.get_flag("no-clear-screen"), + exclude: matches + .remove_many::("watch-exclude") + .map(|f| { + f.flat_map(flat_escape_split_commas) + .collect::, _>>() + }) + .transpose()? + .unwrap_or_default(), + }) + }) + .transpose(); } - None + Ok(None) } fn unstable_args_parse( @@ -5399,20 +5714,24 @@ fn unstable_args_parse( matches: &mut ArgMatches, cfg: UnstableArgsConfig, ) { + // TODO(bartlomieju): remove in Deno 2.5 if matches.get_flag("unstable") { flags.unstable_config.legacy_flag_enabled = true; } flags.unstable_config.bare_node_builtins = matches.get_flag("unstable-bare-node-builtins"); - flags.unstable_config.byonm = matches.get_flag("unstable-byonm"); + flags.unstable_config.detect_cjs = matches.get_flag("unstable-detect-cjs"); flags.unstable_config.sloppy_imports = matches.get_flag("unstable-sloppy-imports"); if matches!(cfg, UnstableArgsConfig::ResolutionAndRuntime) { - for (name, _, _) in crate::UNSTABLE_GRANULAR_FLAGS { - if matches.get_flag(&format!("unstable-{}", name)) { - flags.unstable_config.features.push(name.to_string()); + for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS { + if matches.get_flag(&format!("unstable-{}", granular_flag.name)) { + flags + .unstable_config + .features + .push(granular_flag.name.to_string()); } } } @@ -5886,10 +6205,7 @@ mod tests { ); let r = flags_from_vec(svec!["deno", "run", "--v8-flags=--expose-gc"]); - assert!(r - .unwrap_err() - .to_string() - .contains("[SCRIPT_ARG] may only be omitted with --v8-flags=--help")); + assert!(r.is_err()); } #[test] @@ -6104,14 +6420,6 @@ mod tests { )), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, code_cache_enabled: true, @@ -6141,7 +6449,7 @@ mod tests { #[test] fn short_permission_flags() { - let r = flags_from_vec(svec!["deno", "run", "-RNESW", "gist.ts"]); + let r = flags_from_vec(svec!["deno", "run", "-RNESWI", "gist.ts"]); assert_eq!( r.unwrap(), Flags { @@ -6152,6 +6460,7 @@ mod tests { allow_read: Some(vec![]), allow_write: Some(vec![]), allow_env: Some(vec![]), + allow_import: Some(vec![]), allow_net: Some(vec![]), allow_sys: Some(vec![]), ..Default::default() @@ -6183,44 +6492,6 @@ mod tests { ); } - #[test] - fn allow_hrtime() { - let r = flags_from_vec(svec!["deno", "run", "--allow-hrtime", "gist.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "gist.ts".to_string(), - )), - permissions: PermissionFlags { - allow_hrtime: true, - ..Default::default() - }, - code_cache_enabled: true, - ..Flags::default() - } - ); - } - - #[test] - fn deny_hrtime() { - let r = flags_from_vec(svec!["deno", "run", "--deny-hrtime", "gist.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "gist.ts".to_string(), - )), - permissions: PermissionFlags { - deny_hrtime: true, - ..Default::default() - }, - code_cache_enabled: true, - ..Flags::default() - } - ); - } - #[test] fn double_hyphen() { // notice that flags passed after double dash will not @@ -6270,13 +6541,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6297,13 +6564,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6324,13 +6587,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6351,13 +6610,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Some(Default::default()), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6387,17 +6642,13 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: true, - unstable_html: true, unstable_component: true, - unstable_yaml: true, watch: Some(WatchFlags { hmr: false, no_clear_screen: true, exclude: vec![], }) }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6425,13 +6676,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Some(Default::default()), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6452,13 +6699,9 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() } @@ -6487,14 +6730,10 @@ mod tests { single_quote: None, prose_wrap: None, no_semicolons: None, - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Some(Default::default()), }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6527,13 +6766,9 @@ mod tests { single_quote: Some(true), prose_wrap: Some("never".to_string()), no_semicolons: Some(true), - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), ..Flags::default() } ); @@ -6561,13 +6796,35 @@ mod tests { single_quote: Some(false), prose_wrap: None, no_semicolons: Some(false), - unstable_css: false, - unstable_html: false, unstable_component: false, - unstable_yaml: false, watch: Default::default(), }), - ext: Some("ts".to_string()), + ..Flags::default() + } + ); + + let r = flags_from_vec(svec!["deno", "fmt", "--ext", "html"]); + assert!(r.is_err()); + let r = flags_from_vec(svec!["deno", "fmt", "--ext", "html", "./**"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Fmt(FmtFlags { + check: false, + files: FileFlags { + include: vec!["./**".to_string()], + ignore: vec![], + }, + use_tabs: None, + line_width: None, + indent_width: None, + single_quote: None, + prose_wrap: None, + no_semicolons: None, + unstable_component: false, + watch: Default::default(), + }), + ext: Some("html".to_string()), ..Flags::default() } ); @@ -6592,7 +6849,6 @@ mod tests { json: false, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6621,7 +6877,6 @@ mod tests { json: false, compact: false, watch: Some(Default::default()), - ext: None, }), ..Flags::default() } @@ -6655,7 +6910,6 @@ mod tests { no_clear_screen: true, exclude: vec![], }), - ext: None, }), ..Flags::default() } @@ -6683,7 +6937,6 @@ mod tests { json: false, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6706,7 +6959,6 @@ mod tests { json: false, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6734,7 +6986,6 @@ mod tests { json: false, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6763,7 +7014,6 @@ mod tests { json: false, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6786,7 +7036,6 @@ mod tests { json: true, compact: false, watch: Default::default(), - ext: None, }), ..Flags::default() } @@ -6816,7 +7065,6 @@ mod tests { json: true, compact: false, watch: Default::default(), - ext: None, }), config_flag: ConfigFlag::Path("Deno.jsonc".to_string()), ..Flags::default() @@ -6847,7 +7095,6 @@ mod tests { json: false, compact: true, watch: Default::default(), - ext: None, }), config_flag: ConfigFlag::Path("Deno.jsonc".to_string()), ..Flags::default() @@ -6889,12 +7136,55 @@ mod tests { Flags { subcommand: DenoSubcommand::Check(CheckFlags { files: svec!["script.ts"], + doc: false, + doc_only: false, }), type_check_mode: TypeCheckMode::Local, ..Flags::default() } ); + let r = flags_from_vec(svec!["deno", "check", "--doc", "script.ts"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Check(CheckFlags { + files: svec!["script.ts"], + doc: true, + doc_only: false, + }), + type_check_mode: TypeCheckMode::Local, + ..Flags::default() + } + ); + + let r = flags_from_vec(svec!["deno", "check", "--doc-only", "markdown.md"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Check(CheckFlags { + files: svec!["markdown.md"], + doc: false, + doc_only: true, + }), + type_check_mode: TypeCheckMode::Local, + ..Flags::default() + } + ); + + // `--doc` and `--doc-only` are mutually exclusive + let r = flags_from_vec(svec![ + "deno", + "check", + "--doc", + "--doc-only", + "script.ts" + ]); + assert_eq!( + r.unwrap_err().kind(), + clap::error::ErrorKind::ArgumentConflict + ); + for all_flag in ["--remote", "--all"] { let r = flags_from_vec(svec!["deno", "check", all_flag, "script.ts"]); assert_eq!( @@ -6902,6 +7192,8 @@ mod tests { Flags { subcommand: DenoSubcommand::Check(CheckFlags { files: svec!["script.ts"], + doc: false, + doc_only: false, }), type_check_mode: TypeCheckMode::All, ..Flags::default() @@ -7037,14 +7329,6 @@ mod tests { }), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, ..Flags::default() @@ -7064,14 +7348,6 @@ mod tests { }), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, ..Flags::default() @@ -7081,8 +7357,12 @@ mod tests { #[test] fn eval_typescript() { - let r = - flags_from_vec(svec!["deno", "eval", "-T", "'console.log(\"hello\")'"]); + let r = flags_from_vec(svec![ + "deno", + "eval", + "--ext=ts", + "'console.log(\"hello\")'" + ]); assert_eq!( r.unwrap(), Flags { @@ -7092,14 +7372,6 @@ mod tests { }), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, ext: Some("ts".to_string()), @@ -7111,7 +7383,7 @@ mod tests { #[test] fn eval_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "eval", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--env=.example.env", "42"]); + let r = flags_from_vec(svec!["deno", "eval", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--env=.example.env", "42"]); assert_eq!( r.unwrap(), Flags { @@ -7125,7 +7397,6 @@ mod tests { type_check_mode: TypeCheckMode::None, reload: true, lock: Some(String::from("lock.json")), - lock_write: true, ca_data: Some(CaData::File("example.crt".to_string())), cached_only: true, location: Some(Url::parse("https://foo/").unwrap()), @@ -7134,14 +7405,6 @@ mod tests { inspect: Some("127.0.0.1:9229".parse().unwrap()), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, env_file: Some(".example.env".to_owned()), @@ -7169,14 +7432,6 @@ mod tests { argv: svec!["arg1", "arg2"], permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, ..Flags::default() @@ -7197,20 +7452,7 @@ mod tests { }), unsafely_ignore_certificate_errors: None, permissions: PermissionFlags { - allow_net: Some(vec![]), - allow_env: Some(vec![]), - deny_env: None, - allow_run: Some(vec![]), - deny_run: None, - allow_read: Some(vec![]), - deny_read: None, - allow_sys: Some(vec![]), - deny_sys: None, - allow_write: Some(vec![]), - deny_write: None, - allow_ffi: Some(vec![]), - deny_ffi: None, - allow_hrtime: true, + allow_all: true, ..Default::default() }, ..Flags::default() @@ -7234,7 +7476,7 @@ mod tests { #[test] fn repl_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors", "--env=.example.env"]); + let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--reload", "--lock", "lock.json", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors", "--env=.example.env"]); assert_eq!( r.unwrap(), Flags { @@ -7249,7 +7491,6 @@ mod tests { type_check_mode: TypeCheckMode::None, reload: true, lock: Some(String::from("lock.json")), - lock_write: true, ca_data: Some(CaData::File("example.crt".to_string())), cached_only: true, location: Some(Url::parse("https://foo/").unwrap()), @@ -7258,14 +7499,6 @@ mod tests { inspect: Some("127.0.0.1:9229".parse().unwrap()), permissions: PermissionFlags { allow_all: true, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, ..Default::default() }, env_file: Some(".example.env".to_owned()), @@ -7291,7 +7524,6 @@ mod tests { allow_write: Some(vec![]), ..Default::default() }, - type_check_mode: TypeCheckMode::None, ..Flags::default() } ); @@ -7313,7 +7545,6 @@ mod tests { eval: None, is_default_command: false, }), - type_check_mode: TypeCheckMode::None, ..Flags::default() } ); @@ -7820,188 +8051,6 @@ mod tests { "script.ts" ]); assert!(r.is_err(), "Should reject a trailing comma"); - - let r = flags_from_vec(svec![ - "deno", - "run", - "--reload=http://deno.land/a,,http://deno.land/b", - "script.ts" - ]); - assert!(r.is_err(), "Should reject adjacent commas"); - } - - #[test] - fn bundle() { - let r = flags_from_vec(svec!["deno", "bundle", "source.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::Local, - ..Flags::default() - } - ); - } - - #[test] - fn bundle_with_config() { - let r = flags_from_vec(svec![ - "deno", - "bundle", - "--no-remote", - "--config", - "tsconfig.json", - "source.ts", - "bundle.js" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: Some("bundle.js".to_string()), - watch: Default::default(), - }), - permissions: PermissionFlags { - allow_write: Some(vec![]), - ..Default::default() - }, - no_remote: true, - type_check_mode: TypeCheckMode::Local, - config_flag: ConfigFlag::Path("tsconfig.json".to_owned()), - ..Flags::default() - } - ); - } - - #[test] - fn bundle_with_output() { - let r = flags_from_vec(svec!["deno", "bundle", "source.ts", "bundle.js"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: Some("bundle.js".to_string()), - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::Local, - permissions: PermissionFlags { - allow_write: Some(vec![]), - ..Default::default() - }, - ..Flags::default() - } - ); - } - - #[test] - fn bundle_with_lock() { - let r = flags_from_vec(svec![ - "deno", - "bundle", - "--lock-write", - "--lock=lock.json", - "source.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::Local, - lock_write: true, - lock: Some(String::from("lock.json")), - ..Flags::default() - } - ); - } - - #[test] - fn bundle_with_reload() { - let r = flags_from_vec(svec!["deno", "bundle", "--reload", "source.ts"]); - assert_eq!( - r.unwrap(), - Flags { - reload: true, - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::Local, - ..Flags::default() - } - ); - } - - #[test] - fn bundle_nocheck() { - let r = flags_from_vec(svec!["deno", "bundle", "--no-check", "script.ts"]) - .unwrap(); - assert_eq!( - r, - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "script.ts".to_string(), - out_file: None, - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::None, - ..Flags::default() - } - ); - } - - #[test] - fn bundle_watch() { - let r = flags_from_vec(svec!["deno", "bundle", "--watch", "source.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Some(Default::default()), - }), - type_check_mode: TypeCheckMode::Local, - ..Flags::default() - } - ) - } - - #[test] - fn bundle_watch_with_no_clear_screen() { - let r = flags_from_vec(svec![ - "deno", - "bundle", - "--watch", - "--no-clear-screen", - "source.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Some(WatchFlags { - hmr: false, - no_clear_screen: true, - exclude: vec![], - }), - }), - type_check_mode: TypeCheckMode::Local, - ..Flags::default() - } - ) } #[test] @@ -8235,8 +8284,12 @@ mod tests { #[test] fn install() { - let r = - flags_from_vec(svec!["deno", "install", "jsr:@std/http/file-server"]); + let r = flags_from_vec(svec![ + "deno", + "install", + "-g", + "jsr:@std/http/file-server" + ]); assert_eq!( r.unwrap(), Flags { @@ -8248,7 +8301,6 @@ mod tests { root: None, force: false, }), - global: false, }), ..Flags::default() } @@ -8271,7 +8323,6 @@ mod tests { root: None, force: false, }), - global: true, }), ..Flags::default() } @@ -8281,7 +8332,7 @@ mod tests { #[test] fn install_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "install", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "--env=.example.env", "jsr:@std/http/file-server", "foo", "bar"]); + let r = flags_from_vec(svec!["deno", "install", "--global", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "--env=.example.env", "jsr:@std/http/file-server", "foo", "bar"]); assert_eq!( r.unwrap(), Flags { @@ -8293,7 +8344,6 @@ mod tests { root: Some("/foo".to_string()), force: true, }), - global: false, }), import_map_path: Some("import_map.json".to_string()), no_remote: true, @@ -8301,7 +8351,6 @@ mod tests { type_check_mode: TypeCheckMode::None, reload: true, lock: Some(String::from("lock.json")), - lock_write: true, ca_data: Some(CaData::File("example.crt".to_string())), cached_only: true, v8_flags: svec!["--help", "--random-seed=1"], @@ -8321,16 +8370,31 @@ mod tests { #[test] fn uninstall() { - let r = flags_from_vec(svec!["deno", "uninstall", "file_server"]); + let r = flags_from_vec(svec!["deno", "uninstall"]); + assert!(r.is_err(),); + + let r = flags_from_vec(svec!["deno", "uninstall", "@std/load"]); assert_eq!( r.unwrap(), Flags { subcommand: DenoSubcommand::Uninstall(UninstallFlags { - kind: UninstallKind::Global(UninstallFlagsGlobal { - name: "file_server".to_string(), - root: None, + kind: UninstallKind::Local(RemoveFlags { + packages: vec!["@std/load".to_string()], + }), + }), + ..Flags::default() + } + ); + + let r = + flags_from_vec(svec!["deno", "uninstall", "file_server", "@std/load"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Uninstall(UninstallFlags { + kind: UninstallKind::Local(RemoveFlags { + packages: vec!["file_server".to_string(), "@std/load".to_string()], }), - global: false, }), ..Flags::default() } @@ -8345,7 +8409,27 @@ mod tests { name: "file_server".to_string(), root: None, }), - global: true, + }), + ..Flags::default() + } + ); + + let r = flags_from_vec(svec![ + "deno", + "uninstall", + "-g", + "--root", + "/user/foo/bar", + "file_server" + ]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Uninstall(UninstallFlags { + kind: UninstallKind::Global(UninstallFlagsGlobal { + name: "file_server".to_string(), + root: Some("/user/foo/bar".to_string()), + }), }), ..Flags::default() } @@ -8674,25 +8758,7 @@ mod tests { watch: None, bare: true, }), - node_modules_dir: Some(true), - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec![ - "deno", - "run", - "--node-modules-dir=false", - "script.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "script.ts".to_string(), - )), - node_modules_dir: Some(false), + node_modules_dir: Some(NodeModulesDirMode::Auto), code_cache_enabled: true, ..Flags::default() } @@ -8878,115 +8944,14 @@ mod tests { ); } - #[test] - fn lock_write() { - let r = flags_from_vec(svec![ - "deno", - "run", - "--lock-write", - "--lock=lock.json", - "script.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "script.ts".to_string(), - )), - lock_write: true, - lock: Some(String::from("lock.json")), - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec!["deno", "--no-lock", "script.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags { - script: "script.ts".to_string(), - watch: None, - bare: true, - }), - no_lock: true, - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec![ - "deno", - "run", - "--lock", - "--lock-write", - "script.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "script.ts".to_string(), - )), - lock_write: true, - lock: Some(String::from("./deno.lock")), - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec![ - "deno", - "run", - "--lock-write", - "--lock", - "lock.json", - "script.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "script.ts".to_string(), - )), - lock_write: true, - lock: Some(String::from("lock.json")), - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec!["deno", "run", "--lock-write", "script.ts"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Run(RunFlags::new_default( - "script.ts".to_string(), - )), - lock_write: true, - code_cache_enabled: true, - ..Flags::default() - } - ); - - let r = - flags_from_vec(svec!["deno", "run", "--lock", "--no-lock", "script.ts"]); - assert!(r.is_err(),); - - let r = flags_from_vec(svec![ - "deno", - "run", - "--lock-write", - "--no-lock", - "script.ts" - ]); - assert!(r.is_err(),); - } - #[test] fn test_no_colon_in_value_name() { - let app = - runtime_args(Command::new("test_inspect_completion_value"), true, true); + let app = runtime_args( + Command::new("test_inspect_completion_value"), + true, + true, + false, + ); let inspect_args = app .get_arguments() .filter(|arg| arg.get_id() == "inspect") @@ -9003,7 +8968,7 @@ mod tests { #[test] fn test_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "test", "--unstable", "--no-npm", "--no-remote", "--trace-leaks", "--no-run", "--filter", "- foo", "--coverage=cov", "--clean", "--location", "https:foo", "--allow-net", "--permit-no-files", "dir1/", "dir2/", "--", "arg1", "arg2"]); + let r = flags_from_vec(svec!["deno", "test", "--no-npm", "--no-remote", "--trace-leaks", "--no-run", "--filter", "- foo", "--coverage=cov", "--clean", "--location", "https:foo", "--allow-net", "--permit-no-files", "dir1/", "dir2/", "--", "arg1", "arg2"]); assert_eq!( r.unwrap(), Flags { @@ -9012,7 +8977,7 @@ mod tests { doc: false, fail_fast: None, filter: Some("- foo".to_string()), - allow_none: true, + permit_no_files: true, files: FileFlags { include: vec!["dir1/".to_string(), "dir2/".to_string()], ignore: vec![], @@ -9027,10 +8992,6 @@ mod tests { junit_path: None, hide_stacktraces: false, }), - unstable_config: UnstableConfig { - legacy_flag_enabled: true, - ..Default::default() - }, no_npm: true, no_remote: true, location: Some(Url::parse("https://foo/").unwrap()), @@ -9089,45 +9050,6 @@ mod tests { ); } - #[test] - fn test_with_concurrent_jobs() { - let r = flags_from_vec(svec!["deno", "test", "--jobs=4"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Test(TestFlags { - no_run: false, - reporter: Default::default(), - doc: false, - fail_fast: None, - filter: None, - allow_none: false, - shuffle: None, - files: FileFlags { - include: vec![], - ignore: vec![], - }, - concurrent_jobs: Some(NonZeroUsize::new(4).unwrap()), - trace_leaks: false, - coverage_dir: None, - clean: false, - watch: Default::default(), - junit_path: None, - hide_stacktraces: false, - }), - type_check_mode: TypeCheckMode::Local, - permissions: PermissionFlags { - no_prompt: true, - ..Default::default() - }, - ..Flags::default() - } - ); - - let r = flags_from_vec(svec!["deno", "test", "--jobs=0"]); - assert!(r.is_err()); - } - #[test] fn test_with_fail_fast() { let r = flags_from_vec(svec!["deno", "test", "--fail-fast=3"]); @@ -9139,7 +9061,7 @@ mod tests { doc: false, fail_fast: Some(NonZeroUsize::new(3).unwrap()), filter: None, - allow_none: false, + permit_no_files: false, shuffle: None, files: FileFlags { include: vec![], @@ -9182,7 +9104,7 @@ mod tests { doc: false, fail_fast: None, filter: None, - allow_none: false, + permit_no_files: false, shuffle: None, files: FileFlags { include: vec![], @@ -9319,7 +9241,7 @@ mod tests { doc: false, fail_fast: None, filter: None, - allow_none: false, + permit_no_files: false, shuffle: Some(1), files: FileFlags { include: vec![], @@ -9355,7 +9277,7 @@ mod tests { doc: false, fail_fast: None, filter: None, - allow_none: false, + permit_no_files: false, shuffle: None, files: FileFlags { include: vec![], @@ -9390,7 +9312,7 @@ mod tests { doc: false, fail_fast: None, filter: None, - allow_none: false, + permit_no_files: false, shuffle: None, files: FileFlags { include: vec!["./".to_string()], @@ -9427,7 +9349,7 @@ mod tests { doc: false, fail_fast: None, filter: None, - allow_none: false, + permit_no_files: false, shuffle: None, files: FileFlags { include: vec![], @@ -9662,30 +9584,6 @@ mod tests { ); } - #[test] - fn bundle_with_cafile() { - let r = flags_from_vec(svec![ - "deno", - "bundle", - "--cert", - "example.crt", - "source.ts" - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Bundle(BundleFlags { - source_file: "source.ts".to_string(), - out_file: None, - watch: Default::default(), - }), - type_check_mode: TypeCheckMode::Local, - ca_data: Some(CaData::File("example.crt".to_owned())), - ..Flags::default() - } - ); - } - #[test] fn upgrade_with_ca_file() { let r = flags_from_vec(svec!["deno", "upgrade", "--cert", "example.crt"]); @@ -10108,7 +10006,7 @@ mod tests { #[test] fn compile_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "compile", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--no-terminal", "--icon", "favicon.ico", "--output", "colors", "--env=.example.env", "https://examples.deno.land/color-logging.ts", "foo", "bar", "-p", "8080"]); + let r = flags_from_vec(svec!["deno", "compile", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-ignore-certificate-errors", "--reload", "--lock", "lock.json", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--no-terminal", "--icon", "favicon.ico", "--output", "colors", "--env=.example.env", "https://examples.deno.land/color-logging.ts", "foo", "bar", "-p", "8080"]); assert_eq!( r.unwrap(), Flags { @@ -10128,7 +10026,6 @@ mod tests { type_check_mode: TypeCheckMode::None, reload: true, lock: Some(String::from("lock.json")), - lock_write: true, ca_data: Some(CaData::File("example.crt".to_string())), cached_only: true, location: Some(Url::parse("https://foo/").unwrap()), @@ -10281,57 +10178,6 @@ mod tests { assert!(&error_message.contains("--watch[=...]")); } - #[test] - fn vendor_minimal() { - let r = flags_from_vec(svec!["deno", "vendor", "mod.ts",]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Vendor(VendorFlags { - specifiers: svec!["mod.ts"], - force: false, - output_path: None, - }), - ..Flags::default() - } - ); - } - - #[test] - fn vendor_all() { - let r = flags_from_vec(svec![ - "deno", - "vendor", - "--config", - "deno.json", - "--import-map", - "import_map.json", - "--lock", - "lock.json", - "--force", - "--output", - "out_dir", - "--reload", - "mod.ts", - "deps.test.ts", - ]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Vendor(VendorFlags { - specifiers: svec!["mod.ts", "deps.test.ts"], - force: true, - output_path: Some(String::from("out_dir")), - }), - config_flag: ConfigFlag::Path("deno.json".to_owned()), - import_map_path: Some("import_map.json".to_string()), - lock: Some(String::from("lock.json")), - reload: true, - ..Flags::default() - } - ); - } - #[test] fn task_subcommand() { let r = flags_from_vec(svec!["deno", "task", "build", "hello", "world",]); @@ -10341,6 +10187,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), argv: svec!["hello", "world"], ..Flags::default() @@ -10354,6 +10201,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), ..Flags::default() } @@ -10366,6 +10214,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: Some("foo".to_string()), task: Some("build".to_string()), + is_run: false, }), ..Flags::default() } @@ -10390,6 +10239,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), argv: svec!["--", "hello", "world"], config_flag: ConfigFlag::Path("deno.json".to_owned()), @@ -10406,6 +10256,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: Some("foo".to_string()), task: Some("build".to_string()), + is_run: false, }), argv: svec!["--", "hello", "world"], ..Flags::default() @@ -10423,6 +10274,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), argv: svec!["--"], ..Flags::default() @@ -10439,6 +10291,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), argv: svec!["-1", "--test"], ..Flags::default() @@ -10455,6 +10308,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), argv: svec!["--test"], ..Flags::default() @@ -10472,6 +10326,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: Some("build".to_string()), + is_run: false, }), log_level: Some(log::Level::Error), ..Flags::default() @@ -10488,6 +10343,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: None, + is_run: false, }), ..Flags::default() } @@ -10503,6 +10359,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: None, + is_run: false, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() @@ -10519,6 +10376,7 @@ mod tests { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, task: None, + is_run: false, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() @@ -10541,7 +10399,6 @@ mod tests { "deno", "bench", "--json", - "--unstable", "--no-npm", "--no-remote", "--no-run", @@ -10569,10 +10426,6 @@ mod tests { }, watch: Default::default(), }), - unstable_config: UnstableConfig { - legacy_flag_enabled: true, - ..Default::default() - }, no_npm: true, no_remote: true, type_check_mode: TypeCheckMode::Local, @@ -10864,31 +10717,53 @@ mod tests { } #[test] - fn add_subcommand() { + fn add_or_install_subcommand() { let r = flags_from_vec(svec!["deno", "add"]); r.unwrap_err(); + for cmd in ["add", "install"] { + let mk_flags = |flags: AddFlags| -> Flags { + match cmd { + "add" => Flags { + subcommand: DenoSubcommand::Add(flags), + ..Flags::default() + }, + "install" => Flags { + subcommand: DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(InstallFlagsLocal::Add(flags)), + }), + ..Flags::default() + }, + _ => unreachable!(), + } + }; - let r = flags_from_vec(svec!["deno", "add", "@david/which"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Add(AddFlags { + let r = flags_from_vec(svec!["deno", cmd, "@david/which"]); + assert_eq!( + r.unwrap(), + mk_flags(AddFlags { packages: svec!["@david/which"], - }), - ..Flags::default() - } - ); + dev: false, + }) // default is false + ); - let r = flags_from_vec(svec!["deno", "add", "@david/which", "@luca/hello"]); - assert_eq!( - r.unwrap(), - Flags { - subcommand: DenoSubcommand::Add(AddFlags { + let r = flags_from_vec(svec!["deno", cmd, "@david/which", "@luca/hello"]); + assert_eq!( + r.unwrap(), + mk_flags(AddFlags { packages: svec!["@david/which", "@luca/hello"], + dev: false, + }) + ); + + let r = flags_from_vec(svec!["deno", cmd, "--dev", "npm:chalk"]); + assert_eq!( + r.unwrap(), + mk_flags(AddFlags { + packages: svec!["npm:chalk"], + dev: true, }), - ..Flags::default() - } - ); + ); + } } #[test] @@ -11026,15 +10901,7 @@ mod tests { }), log_level: Some(Level::Debug), permissions: PermissionFlags { - allow_all: false, - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, + allow_all: true, ..Default::default() }, ..Flags::default() @@ -11042,6 +10909,25 @@ mod tests { ); } + #[test] + fn repl_user_args() { + let r = flags_from_vec(svec!["deno", "repl", "foo"]); + assert!(r.is_err()); + let r = flags_from_vec(svec!["deno", "repl", "--", "foo"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Repl(ReplFlags { + eval_files: None, + eval: None, + is_default_command: false, + }), + argv: svec!["foo"], + ..Flags::default() + } + ); + } + #[test] fn bare_with_flag_no_file() { let r = flags_from_vec(svec!["deno", "--no-config"]); @@ -11052,4 +10938,223 @@ mod tests { .to_string() .contains("Usage: deno [OPTIONS] [COMMAND] [SCRIPT_ARG]...")); } + + #[test] + fn equal_help_output() { + for command in clap_root().get_subcommands() { + if command.get_name() == "help" { + continue; + } + + let long_flag = if let DenoSubcommand::Help(help) = + flags_from_vec(svec!["deno", command.get_name(), "--help"]) + .unwrap() + .subcommand + { + help.help.to_string() + } else { + unreachable!() + }; + let short_flag = if let DenoSubcommand::Help(help) = + flags_from_vec(svec!["deno", command.get_name(), "-h"]) + .unwrap() + .subcommand + { + help.help.to_string() + } else { + unreachable!() + }; + let subcommand = if let DenoSubcommand::Help(help) = + flags_from_vec(svec!["deno", "help", command.get_name()]) + .unwrap() + .subcommand + { + help.help.to_string() + } else { + unreachable!() + }; + assert_eq!(long_flag, short_flag, "{} subcommand", command.get_name()); + assert_eq!(long_flag, subcommand, "{} subcommand", command.get_name()); + } + } + + #[test] + fn install_permissions_non_global() { + let r = + flags_from_vec(svec!["deno", "install", "--allow-net", "jsr:@std/fs"]); + + assert!(r + .unwrap_err() + .to_string() + .contains("Note: Permission flags can only be used in a global setting")); + } + + #[test] + fn jupyter_unstable_flags() { + let r = flags_from_vec(svec![ + "deno", + "jupyter", + "--unstable-ffi", + "--unstable-bare-node-builtins", + "--unstable-worker-options" + ]); + + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Jupyter(JupyterFlags { + install: false, + kernel: false, + conn_file: None, + }), + unstable_config: UnstableConfig { + bare_node_builtins: true, + sloppy_imports: false, + features: svec!["ffi", "worker-options"], + ..Default::default() + }, + ..Flags::default() + } + ); + } + + #[test] + fn serve_with_allow_all() { + let r = flags_from_vec(svec!["deno", "serve", "--allow-all", "./main.ts"]); + let flags = r.unwrap(); + assert_eq!( + &flags, + &Flags { + subcommand: DenoSubcommand::Serve(ServeFlags::new_default( + "./main.ts".into(), + 8000, + "0.0.0.0" + )), + permissions: PermissionFlags { + allow_all: true, + allow_net: None, + ..Default::default() + }, + code_cache_enabled: true, + ..Default::default() + } + ); + // just make sure this doesn't panic + let _ = flags.permissions.to_options(&[]); + } + + #[test] + fn escape_and_split_commas_test() { + assert_eq!(escape_and_split_commas("foo".to_string()).unwrap(), ["foo"]); + assert!(escape_and_split_commas("foo,".to_string()).is_err()); + assert_eq!( + escape_and_split_commas("foo,,".to_string()).unwrap(), + ["foo,"] + ); + assert!(escape_and_split_commas("foo,,,".to_string()).is_err()); + assert_eq!( + escape_and_split_commas("foo,,,,".to_string()).unwrap(), + ["foo,,"] + ); + assert_eq!( + escape_and_split_commas("foo,bar".to_string()).unwrap(), + ["foo", "bar"] + ); + assert_eq!( + escape_and_split_commas("foo,,bar".to_string()).unwrap(), + ["foo,bar"] + ); + assert_eq!( + escape_and_split_commas("foo,,,bar".to_string()).unwrap(), + ["foo,", "bar"] + ); + } + + #[test] + fn net_flag_with_url() { + let r = flags_from_vec(svec![ + "deno", + "run", + "--allow-net=https://example.com", + "script.ts" + ]); + assert_eq!( + r.unwrap_err().to_string(), + "error: invalid value 'https://example.com': URLs are not supported, only domains and ips" + ); + } + + #[test] + fn node_modules_dir_default() { + let r = + flags_from_vec(svec!["deno", "run", "--node-modules-dir", "./foo.ts"]); + let flags = r.unwrap(); + assert_eq!( + flags, + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "./foo.ts".into(), + ..Default::default() + }), + node_modules_dir: Some(NodeModulesDirMode::Auto), + code_cache_enabled: true, + ..Default::default() + } + ) + } + + #[test] + fn flag_before_subcommand() { + let r = flags_from_vec(svec!["deno", "--allow-net", "repl"]); + assert_eq!( + r.unwrap_err().to_string(), + "error: unexpected argument '--allow-net' found + + tip: 'repl --allow-net' exists + +Usage: deno repl [OPTIONS] [-- [ARGS]...]\n" + ) + } + + #[test] + fn test_allow_import_host_from_url() { + fn parse(text: &str) -> Option { + allow_import_host_from_url(&Url::parse(text).unwrap()) + } + + assert_eq!(parse("https://jsr.io"), None); + assert_eq!( + parse("http://127.0.0.1:4250"), + Some("127.0.0.1:4250".to_string()) + ); + assert_eq!(parse("http://jsr.io"), Some("jsr.io:80".to_string())); + assert_eq!( + parse("https://example.com"), + Some("example.com:443".to_string()) + ); + assert_eq!( + parse("http://example.com"), + Some("example.com:80".to_string()) + ); + assert_eq!(parse("file:///example.com"), None); + } + + #[test] + fn allow_all_conflicts_allow_perms() { + let flags = [ + "--allow-read", + "--allow-write", + "--allow-net", + "--allow-env", + "--allow-run", + "--allow-sys", + "--allow-ffi", + "--allow-import", + ]; + for flag in flags { + let r = + flags_from_vec(svec!["deno", "run", "--allow-all", flag, "foo.ts"]); + assert!(r.is_err()); + } + } } diff --git a/cli/args/flags_net.rs b/cli/args/flags_net.rs index 57cf8d527c..88ffcf0e46 100644 --- a/cli/args/flags_net.rs +++ b/cli/args/flags_net.rs @@ -50,7 +50,7 @@ pub fn parse(paths: Vec) -> clap::error::Result> { out.push(format!("{}:{}", host, port.0)); } } else { - host_and_port.parse::().map_err(|e| { + NetDescriptor::parse(&host_and_port).map_err(|e| { clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}")) })?; out.push(host_and_port) diff --git a/cli/args/import_map.rs b/cli/args/import_map.rs index 7a16ab2156..ff2f158715 100644 --- a/cli/args/import_map.rs +++ b/cli/args/import_map.rs @@ -3,7 +3,6 @@ use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url::Url; -use deno_runtime::deno_permissions::PermissionsContainer; use crate::file_fetcher::FileFetcher; @@ -17,7 +16,7 @@ pub async fn resolve_import_map_value_from_specifier( Ok(serde_json::from_str(&data_url_text)?) } else { let file = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(specifier) .await? .into_text_decoded()?; Ok(serde_json::from_str(&file.source)?) diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 00d1f929d8..1805d26426 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use std::collections::BTreeSet; +use std::collections::HashSet; use std::path::PathBuf; use deno_config::deno_json::ConfigFile; @@ -12,6 +12,7 @@ use deno_core::parking_lot::MutexGuard; use deno_lockfile::WorkspaceMemberConfig; use deno_package_json::PackageJsonDepValue; use deno_runtime::deno_node::PackageJson; +use deno_semver::jsr::JsrDepPackageReq; use crate::cache; use crate::util::fs::atomic_write_file_with_retries; @@ -23,11 +24,20 @@ use crate::args::InstallKind; use deno_lockfile::Lockfile; +#[derive(Debug)] +pub struct CliLockfileReadFromPathOptions { + pub file_path: PathBuf, + pub frozen: bool, + /// Causes the lockfile to only be read from, but not written to. + pub skip_write: bool, +} + #[derive(Debug)] pub struct CliLockfile { lockfile: Mutex, pub filename: PathBuf, - pub frozen: bool, + frozen: bool, + skip_write: bool, } pub struct Guard<'a, T> { @@ -49,15 +59,6 @@ impl<'a, T> std::ops::DerefMut for Guard<'a, T> { } impl CliLockfile { - pub fn new(lockfile: Lockfile, frozen: bool) -> Self { - let filename = lockfile.filename.clone(); - Self { - lockfile: Mutex::new(lockfile), - filename, - frozen, - } - } - /// Get the inner deno_lockfile::Lockfile. pub fn lock(&self) -> Guard { Guard { @@ -77,6 +78,10 @@ impl CliLockfile { } pub fn write_if_changed(&self) -> Result<(), AnyError> { + if self.skip_write { + return Ok(()); + } + self.error_if_changed()?; let mut lockfile = self.lockfile.lock(); let Some(bytes) = lockfile.resolve_write_bytes() else { @@ -98,7 +103,9 @@ impl CliLockfile { flags: &Flags, workspace: &Workspace, ) -> Result, AnyError> { - fn pkg_json_deps(maybe_pkg_json: Option<&PackageJson>) -> BTreeSet { + fn pkg_json_deps( + maybe_pkg_json: Option<&PackageJson>, + ) -> HashSet { let Some(pkg_json) = maybe_pkg_json else { return Default::default(); }; @@ -107,21 +114,21 @@ impl CliLockfile { .values() .filter_map(|dep| dep.as_ref().ok()) .filter_map(|dep| match dep { - PackageJsonDepValue::Req(req) => Some(req), + PackageJsonDepValue::Req(req) => { + Some(JsrDepPackageReq::npm(req.clone())) + } PackageJsonDepValue::Workspace(_) => None, }) - .map(|r| format!("npm:{}", r)) .collect() } fn deno_json_deps( maybe_deno_json: Option<&ConfigFile>, - ) -> BTreeSet { + ) -> HashSet { maybe_deno_json .map(|c| { crate::args::deno_json::deno_json_deps(c) .into_iter() - .map(|req| req.to_string()) .collect() }) .unwrap_or_default() @@ -139,7 +146,7 @@ impl CliLockfile { return Ok(None); } - let filename = match flags.lock { + let file_path = match flags.lock { Some(ref lock) => PathBuf::from(lock), None => match workspace.resolve_lockfile_path()? { Some(path) => path, @@ -157,15 +164,11 @@ impl CliLockfile { .unwrap_or(false) }); - let lockfile = if flags.lock_write { - log::warn!( - "{} \"--lock-write\" flag is deprecated and will be removed in Deno 2.", - crate::colors::yellow("Warning") - ); - CliLockfile::new(Lockfile::new_empty(filename, true), frozen) - } else { - Self::read_from_path(filename, frozen)? - }; + let lockfile = Self::read_from_path(CliLockfileReadFromPathOptions { + file_path, + frozen, + skip_write: flags.internal.lockfile_skip_write, + })?; // initialize the lockfile with the workspace's configuration let root_url = workspace.root_dir(); @@ -215,40 +218,31 @@ impl CliLockfile { Ok(Some(lockfile)) } + pub fn read_from_path( - file_path: PathBuf, - frozen: bool, + opts: CliLockfileReadFromPathOptions, ) -> Result { - match std::fs::read_to_string(&file_path) { - Ok(text) => Ok(CliLockfile::new( - Lockfile::new(deno_lockfile::NewLockfileOptions { - file_path, - content: &text, - overwrite: false, - is_deno_future: *super::DENO_FUTURE, - })?, - frozen, - )), + let lockfile = match std::fs::read_to_string(&opts.file_path) { + Ok(text) => Lockfile::new(deno_lockfile::NewLockfileOptions { + file_path: opts.file_path, + content: &text, + overwrite: false, + })?, Err(err) if err.kind() == std::io::ErrorKind::NotFound => { - Ok(CliLockfile::new( - if *super::DENO_FUTURE { - // force version 4 for deno future - Lockfile::new(deno_lockfile::NewLockfileOptions { - file_path, - content: r#"{"version":"4"}"#, - overwrite: false, - is_deno_future: true, - })? - } else { - Lockfile::new_empty(file_path, false) - }, - frozen, - )) + Lockfile::new_empty(opts.file_path, false) } - Err(err) => Err(err).with_context(|| { - format!("Failed reading lockfile '{}'", file_path.display()) - }), - } + Err(err) => { + return Err(err).with_context(|| { + format!("Failed reading lockfile '{}'", opts.file_path.display()) + }); + } + }; + Ok(CliLockfile { + filename: lockfile.filename.clone(), + lockfile: Mutex::new(lockfile), + frozen: opts.frozen, + skip_write: opts.skip_write, + }) } pub fn error_if_changed(&self) -> Result<(), AnyError> { @@ -257,12 +251,6 @@ impl CliLockfile { } let lockfile = self.lockfile.lock(); if lockfile.has_content_changed { - let suggested = if *super::DENO_FUTURE { - "`deno cache --frozen=false`, `deno install --frozen=false`," - } else { - "`deno cache --frozen=false`" - }; - let contents = std::fs::read_to_string(&lockfile.filename).unwrap_or_default(); let new_contents = lockfile.as_json_string(); @@ -270,7 +258,7 @@ impl CliLockfile { // has an extra newline at the end let diff = diff.trim_end(); Err(deno_core::anyhow::anyhow!( - "The lockfile is out of date. Run {suggested} or rerun with `--frozen=false` to update it.\nchanges:\n{diff}" + "The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it.\nchanges:\n{diff}" )) } else { Ok(()) diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 056dcb2af5..927f43e85a 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -8,7 +8,9 @@ mod lockfile; mod package_json; use deno_ast::SourceMapOption; +use deno_config::deno_json::NodeModulesDirMode; use deno_config::workspace::CreateResolverOptions; +use deno_config::workspace::FolderConfigs; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::VendorEnablement; use deno_config::workspace::Workspace; @@ -18,14 +20,13 @@ use deno_config::workspace::WorkspaceDiscoverOptions; use deno_config::workspace::WorkspaceDiscoverStart; use deno_config::workspace::WorkspaceLintConfig; use deno_config::workspace::WorkspaceResolver; -use deno_core::normalize_path; use deno_core::resolve_url_or_path; use deno_graph::GraphKind; use deno_npm::npm_rc::NpmRc; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::NpmSystemInfo; -use deno_runtime::deno_permissions::PermissionsContainer; +use deno_path_util::normalize_path; use deno_semver::npm::NpmPackageReqReference; use import_map::resolve_import_map_value_from_specifier; @@ -40,9 +41,11 @@ pub use deno_config::deno_json::TsConfigForEmit; pub use deno_config::deno_json::TsConfigType; pub use deno_config::deno_json::TsTypeLib; pub use deno_config::glob::FilePatterns; +pub use deno_json::check_warn_tsconfig; pub use flags::*; pub use lockfile::CliLockfile; -pub use package_json::PackageJsonInstallDepsProvider; +pub use lockfile::CliLockfileReadFromPathOptions; +pub use package_json::NpmInstallDepsProvider; use deno_ast::ModuleSpecifier; use deno_core::anyhow::bail; @@ -50,7 +53,6 @@ use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url::Url; -use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_permissions::PermissionsOptions; use deno_runtime::deno_tls::deno_native_certs::load_native_certs; use deno_runtime::deno_tls::rustls; @@ -63,10 +65,13 @@ use dotenvy::from_filename; use once_cell::sync::Lazy; use serde::Deserialize; use serde::Serialize; +use std::borrow::Cow; use std::collections::HashMap; use std::env; use std::io::BufReader; use std::io::Cursor; +use std::io::Read; +use std::io::Seek; use std::net::SocketAddr; use std::num::NonZeroUsize; use std::path::Path; @@ -116,9 +121,6 @@ pub static DENO_DISABLE_PEDANTIC_NODE_WARNINGS: Lazy = Lazy::new(|| { .is_some() }); -pub static DENO_FUTURE: Lazy = - Lazy::new(|| std::env::var("DENO_FUTURE").ok().is_some()); - pub fn jsr_url() -> &'static Url { static JSR_URL: Lazy = Lazy::new(|| { let env_var_name = "JSR_URL"; @@ -282,10 +284,7 @@ impl BenchOptions { #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct UnstableFmtOptions { - pub css: bool, - pub html: bool, pub component: bool, - pub yaml: bool, } #[derive(Clone, Debug)] @@ -318,10 +317,7 @@ impl FmtOptions { Self { options: resolve_fmt_options(fmt_flags, fmt_config.options), unstable: UnstableFmtOptions { - css: unstable.css || fmt_flags.unstable_css, - html: unstable.html || fmt_flags.unstable_html, component: unstable.component || fmt_flags.unstable_component, - yaml: unstable.yaml || fmt_flags.unstable_yaml, }, files: fmt_config.files, } @@ -370,7 +366,7 @@ pub struct WorkspaceTestOptions { pub doc: bool, pub no_run: bool, pub fail_fast: Option, - pub allow_none: bool, + pub permit_no_files: bool, pub filter: Option, pub shuffle: Option, pub concurrent_jobs: NonZeroUsize, @@ -383,7 +379,7 @@ pub struct WorkspaceTestOptions { impl WorkspaceTestOptions { pub fn resolve(test_flags: &TestFlags) -> Self { Self { - allow_none: test_flags.allow_none, + permit_no_files: test_flags.permit_no_files, concurrent_jobs: test_flags .concurrent_jobs .unwrap_or_else(|| NonZeroUsize::new(1).unwrap()), @@ -582,6 +578,7 @@ fn discover_npmrc( let resolved = npmrc .as_resolved(npm_registry_url()) .context("Failed to resolve .npmrc options")?; + log::debug!(".npmrc found at: '{}'", path.display()); Ok(Arc::new(resolved)) } @@ -749,15 +746,33 @@ pub enum NpmProcessStateKind { Byonm, } -pub(crate) const NPM_RESOLUTION_STATE_ENV_VAR_NAME: &str = - "DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE"; - static NPM_PROCESS_STATE: Lazy> = Lazy::new(|| { - let state = std::env::var(NPM_RESOLUTION_STATE_ENV_VAR_NAME).ok()?; - let state: NpmProcessState = serde_json::from_str(&state).ok()?; - // remove the environment variable so that sub processes - // that are spawned do not also use this. - std::env::remove_var(NPM_RESOLUTION_STATE_ENV_VAR_NAME); + use deno_runtime::ops::process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME; + let fd = std::env::var(NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME).ok()?; + std::env::remove_var(NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME); + let fd = fd.parse::().ok()?; + let mut file = { + use deno_runtime::deno_io::FromRawIoHandle; + unsafe { std::fs::File::from_raw_io_handle(fd as _) } + }; + let mut buf = Vec::new(); + // seek to beginning. after the file is written the position will be inherited by this subprocess, + // and also this file might have been read before + file.seek(std::io::SeekFrom::Start(0)).unwrap(); + file + .read_to_end(&mut buf) + .inspect_err(|e| { + log::error!("failed to read npm process state from fd {fd}: {e}"); + }) + .ok()?; + let state: NpmProcessState = serde_json::from_slice(&buf) + .inspect_err(|e| { + log::error!( + "failed to deserialize npm process state: {e} {}", + String::from_utf8_lossy(&buf) + ) + }) + .ok()?; Some(state) }); @@ -776,13 +791,12 @@ pub struct CliOptions { // application need not concern itself with, so keep these private flags: Arc, initial_cwd: PathBuf, + main_module_cell: std::sync::OnceLock>, maybe_node_modules_folder: Option, npmrc: Arc, maybe_lockfile: Option>, overrides: CliOptionOverrides, pub start_dir: Arc, - pub disable_deprecated_api_warning: bool, - pub verbose_deprecated_api_warning: bool, pub deno_dir_provider: Arc, } @@ -813,27 +827,18 @@ impl CliOptions { } let maybe_lockfile = maybe_lockfile.filter(|_| !force_global_cache); - let root_folder = start_dir.workspace.root_folder_configs(); let deno_dir_provider = - Arc::new(DenoDirProvider::new(flags.cache_path.clone())); + Arc::new(DenoDirProvider::new(flags.internal.cache_path.clone())); let maybe_node_modules_folder = resolve_node_modules_folder( &initial_cwd, &flags, - root_folder.deno_json.as_deref(), - root_folder.pkg_json.as_deref(), + &start_dir.workspace, &deno_dir_provider, ) .with_context(|| "Resolving node_modules folder.")?; load_env_variables_from_env_file(flags.env_file.as_ref()); - let disable_deprecated_api_warning = flags.log_level - == Some(log::Level::Error) - || std::env::var("DENO_NO_DEPRECATION_WARNINGS").ok().is_some(); - - let verbose_deprecated_api_warning = - std::env::var("DENO_VERBOSE_WARNINGS").ok().is_some(); - Ok(Self { flags, initial_cwd, @@ -841,9 +846,8 @@ impl CliOptions { npmrc, maybe_node_modules_folder, overrides: Default::default(), + main_module_cell: std::sync::OnceLock::new(), start_dir, - disable_deprecated_api_warning, - verbose_deprecated_api_warning, deno_dir_provider, }) } @@ -960,6 +964,9 @@ impl CliOptions { match self.sub_command() { DenoSubcommand::Cache(_) => GraphKind::All, DenoSubcommand::Check(_) => GraphKind::TypesOnly, + DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(_), + }) => GraphKind::All, _ => self.type_check_mode().as_graph_kind(), } } @@ -1083,27 +1090,13 @@ impl CliOptions { None => None, } }; - Ok( - self - .workspace() - .create_resolver( - CreateResolverOptions { - pkg_json_dep_resolution, - specified_import_map: cli_arg_specified_import_map, - }, - |specifier| { - let specifier = specifier.clone(); - async move { - let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await? - .into_text_decoded()?; - Ok(file.source.to_string()) - } - }, - ) - .await?, - ) + Ok(self.workspace().create_resolver( + CreateResolverOptions { + pkg_json_dep_resolution, + specified_import_map: cli_arg_specified_import_map, + }, + |path| Ok(std::fs::read_to_string(path)?), + )?) } pub fn node_ipc_fd(&self) -> Option { @@ -1137,47 +1130,39 @@ impl CliOptions { self.flags.env_file.as_ref() } - pub fn enable_future_features(&self) -> bool { - *DENO_FUTURE - } + pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> { + self + .main_module_cell + .get_or_init(|| { + let main_module = match &self.flags.subcommand { + DenoSubcommand::Compile(compile_flags) => { + resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())? + } + DenoSubcommand::Eval(_) => { + resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())? + } + DenoSubcommand::Repl(_) => { + resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())? + } + DenoSubcommand::Run(run_flags) => { + if run_flags.is_stdin() { + resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())? + } else { + resolve_url_or_path(&run_flags.script, self.initial_cwd())? + } + } + DenoSubcommand::Serve(run_flags) => { + resolve_url_or_path(&run_flags.script, self.initial_cwd())? + } + _ => { + bail!("No main module.") + } + }; - pub fn resolve_main_module(&self) -> Result { - let main_module = match &self.flags.subcommand { - DenoSubcommand::Bundle(bundle_flags) => { - resolve_url_or_path(&bundle_flags.source_file, self.initial_cwd())? - } - DenoSubcommand::Compile(compile_flags) => { - resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())? - } - DenoSubcommand::Eval(_) => { - resolve_url_or_path("./$deno$eval", self.initial_cwd())? - } - DenoSubcommand::Repl(_) => { - resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())? - } - DenoSubcommand::Run(run_flags) => { - if run_flags.is_stdin() { - std::env::current_dir() - .context("Unable to get CWD") - .and_then(|cwd| { - resolve_url_or_path("./$deno$stdin.ts", &cwd) - .map_err(AnyError::from) - })? - } else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() { - ModuleSpecifier::parse(&run_flags.script)? - } else { - resolve_url_or_path(&run_flags.script, self.initial_cwd())? - } - } - DenoSubcommand::Serve(run_flags) => { - resolve_url_or_path(&run_flags.script, self.initial_cwd())? - } - _ => { - bail!("No main module.") - } - }; - - Ok(main_module) + Ok(main_module) + }) + .as_ref() + .map_err(|err| deno_core::anyhow::anyhow!("{}", err)) } pub fn resolve_file_header_overrides( @@ -1198,7 +1183,7 @@ impl CliOptions { (maybe_main_specifier, maybe_content_type) { HashMap::from([( - main_specifier, + main_specifier.clone(), HashMap::from([("content-type".to_string(), content_type.to_string())]), )]) } else { @@ -1227,11 +1212,6 @@ impl CliOptions { NPM_PROCESS_STATE.is_some() } - /// Overrides the import map specifier to use. - pub fn set_import_map_specifier(&mut self, path: Option) { - self.overrides.import_map_specifier = Some(path); - } - pub fn has_node_modules_dir(&self) -> bool { self.maybe_node_modules_folder.is_some() } @@ -1240,26 +1220,13 @@ impl CliOptions { self.maybe_node_modules_folder.as_ref() } - pub fn with_node_modules_dir_path(&self, path: PathBuf) -> Self { - Self { - flags: self.flags.clone(), - initial_cwd: self.initial_cwd.clone(), - maybe_node_modules_folder: Some(path), - npmrc: self.npmrc.clone(), - maybe_lockfile: self.maybe_lockfile.clone(), - start_dir: self.start_dir.clone(), - overrides: self.overrides.clone(), - disable_deprecated_api_warning: self.disable_deprecated_api_warning, - verbose_deprecated_api_warning: self.verbose_deprecated_api_warning, - deno_dir_provider: self.deno_dir_provider.clone(), + pub fn node_modules_dir( + &self, + ) -> Result, AnyError> { + if let Some(flag) = self.flags.node_modules_dir { + return Ok(Some(flag)); } - } - - pub fn node_modules_dir_enablement(&self) -> Option { - self - .flags - .node_modules_dir - .or_else(|| self.workspace().node_modules_dir()) + self.workspace().node_modules_dir().map_err(Into::into) } pub fn vendor_dir_path(&self) -> Option<&PathBuf> { @@ -1270,23 +1237,7 @@ impl CliOptions { &self, config_type: TsConfigType, ) -> Result { - let result = self.workspace().resolve_ts_config_for_emit(config_type); - - match result { - Ok(mut ts_config_for_emit) => { - if matches!(self.flags.subcommand, DenoSubcommand::Bundle(..)) { - // For backwards compatibility, force `experimentalDecorators` setting - // to true. - *ts_config_for_emit - .ts_config - .0 - .get_mut("experimentalDecorators") - .unwrap() = serde_json::Value::Bool(true); - } - Ok(ts_config_for_emit) - } - Err(err) => Err(err), - } + self.workspace().resolve_ts_config_for_emit(config_type) } pub fn resolve_inspector_server( @@ -1354,10 +1305,7 @@ impl CliOptions { pub fn resolve_config_unstable_fmt_options(&self) -> UnstableFmtOptions { let workspace = self.workspace(); UnstableFmtOptions { - css: workspace.has_unstable("fmt-css"), - html: workspace.has_unstable("fmt-html"), component: workspace.has_unstable("fmt-component"), - yaml: workspace.has_unstable("fmt-yaml"), } } @@ -1398,11 +1346,9 @@ impl CliOptions { )?; Ok(deno_lint::linter::LintConfig { - default_jsx_factory: transpile_options - .jsx_automatic + default_jsx_factory: (!transpile_options.jsx_automatic) .then(|| transpile_options.jsx_factory.clone()), - default_jsx_fragment_factory: transpile_options - .jsx_automatic + default_jsx_fragment_factory: (!transpile_options.jsx_automatic) .then(|| transpile_options.jsx_fragment_factory.clone()), }) } @@ -1555,8 +1501,35 @@ impl CliOptions { &self.flags.permissions } - pub fn permissions_options(&self) -> Result { - self.flags.permissions.to_options(Some(&self.initial_cwd)) + pub fn permissions_options(&self) -> PermissionsOptions { + fn files_to_urls(files: &[String]) -> Vec> { + files + .iter() + .filter_map(|f| Url::parse(f).ok().map(Cow::Owned)) + .collect() + } + + // get a list of urls to imply for --allow-import + let cli_arg_urls = self + .resolve_main_module() + .ok() + .map(|url| vec![Cow::Borrowed(url)]) + .or_else(|| match &self.flags.subcommand { + DenoSubcommand::Cache(cache_flags) => { + Some(files_to_urls(&cache_flags.files)) + } + DenoSubcommand::Check(check_flags) => { + Some(files_to_urls(&check_flags.files)) + } + DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Global(flags), + }) => Url::parse(&flags.module_url) + .ok() + .map(|url| vec![Cow::Owned(url)]), + _ => None, + }) + .unwrap_or_default(); + self.flags.permissions.to_options(&cli_arg_urls) } pub fn reload_flag(&self) -> bool { @@ -1602,18 +1575,28 @@ impl CliOptions { &self.flags.unsafely_ignore_certificate_errors } - pub fn legacy_unstable_flag(&self) -> bool { - self.flags.unstable_config.legacy_flag_enabled - } - pub fn unstable_bare_node_builtins(&self) -> bool { self.flags.unstable_config.bare_node_builtins || self.workspace().has_unstable("bare-node-builtins") } + pub fn unstable_detect_cjs(&self) -> bool { + self.flags.unstable_config.detect_cjs + || self.workspace().has_unstable("detect-cjs") + } + + fn byonm_enabled(&self) -> bool { + // check if enabled via unstable + self.node_modules_dir().ok().flatten() == Some(NodeModulesDirMode::Manual) + || NPM_PROCESS_STATE + .as_ref() + .map(|s| matches!(s.kind, NpmProcessStateKind::Byonm)) + .unwrap_or(false) + } + pub fn use_byonm(&self) -> bool { - if self.enable_future_features() - && self.node_modules_dir_enablement().is_none() + if self.node_modules_dir().ok().flatten().is_none() + && self.maybe_node_modules_folder.is_some() && self .workspace() .config_folders() @@ -1623,13 +1606,7 @@ impl CliOptions { return true; } - // check if enabled via unstable - self.flags.unstable_config.byonm - || NPM_PROCESS_STATE - .as_ref() - .map(|s| matches!(s.kind, NpmProcessStateKind::Byonm)) - .unwrap_or(false) - || self.workspace().has_unstable("byonm") + self.byonm_enabled() } pub fn unstable_sloppy_imports(&self) -> bool { @@ -1651,38 +1628,18 @@ impl CliOptions { } }); - if *DENO_FUTURE { - let future_features = [ - deno_runtime::deno_ffi::UNSTABLE_FEATURE_NAME.to_string(), - deno_runtime::deno_fs::UNSTABLE_FEATURE_NAME.to_string(), - deno_runtime::deno_webgpu::UNSTABLE_FEATURE_NAME.to_string(), - ]; - future_features.iter().for_each(|future_feature| { - if !from_config_file.contains(future_feature) { - from_config_file.push(future_feature.to_string()); - } - }); - } - if !from_config_file.is_empty() { - // collect unstable granular flags - let mut all_valid_unstable_flags: Vec<&str> = - crate::UNSTABLE_GRANULAR_FLAGS - .iter() - .map(|granular_flag| granular_flag.0) - .collect(); - - let mut another_unstable_flags = Vec::from([ - "sloppy-imports", - "byonm", - "bare-node-builtins", - "fmt-css", - "fmt-html", - "fmt-component", - "fmt-yaml", - ]); - // add more unstable flags to the same vector holding granular flags - all_valid_unstable_flags.append(&mut another_unstable_flags); + let all_valid_unstable_flags: Vec<&str> = crate::UNSTABLE_GRANULAR_FLAGS + .iter() + .map(|granular_flag| granular_flag.name) + .chain([ + "sloppy-imports", + "byonm", + "bare-node-builtins", + "fmt-component", + "detect-cjs", + ]) + .collect(); // check and warn if the unstable flag of config file isn't supported, by // iterating through the vector holding the unstable flags @@ -1745,14 +1702,14 @@ impl CliOptions { pub fn lifecycle_scripts_config(&self) -> LifecycleScriptsConfig { LifecycleScriptsConfig { allowed: self.flags.allow_scripts.clone(), - initial_cwd: if matches!( - self.flags.allow_scripts, - PackagesAllowedScripts::None - ) { - None - } else { - Some(self.initial_cwd.clone()) - }, + initial_cwd: self.initial_cwd.clone(), + root_dir: self.workspace().root_dir_path(), + explicit_install: matches!( + self.sub_command(), + DenoSubcommand::Install(_) + | DenoSubcommand::Cache(_) + | DenoSubcommand::Add(_) + ), } } } @@ -1761,42 +1718,55 @@ impl CliOptions { fn resolve_node_modules_folder( cwd: &Path, flags: &Flags, - maybe_config_file: Option<&ConfigFile>, - maybe_package_json: Option<&PackageJson>, + workspace: &Workspace, deno_dir_provider: &Arc, ) -> Result, AnyError> { - let use_node_modules_dir = flags - .node_modules_dir - .or_else(|| maybe_config_file.and_then(|c| c.json.node_modules_dir)) - .or(flags.vendor) - .or_else(|| maybe_config_file.and_then(|c| c.json.vendor)); + fn resolve_from_root(root_folder: &FolderConfigs, cwd: &Path) -> PathBuf { + root_folder + .deno_json + .as_ref() + .map(|c| Cow::Owned(c.dir_path())) + .or_else(|| { + root_folder + .pkg_json + .as_ref() + .map(|c| Cow::Borrowed(c.dir_path())) + }) + .unwrap_or(Cow::Borrowed(cwd)) + .join("node_modules") + } + + let root_folder = workspace.root_folder_configs(); + let use_node_modules_dir = if let Some(mode) = flags.node_modules_dir { + Some(mode.uses_node_modules_dir()) + } else { + workspace + .node_modules_dir()? + .map(|m| m.uses_node_modules_dir()) + .or(flags.vendor) + .or_else(|| root_folder.deno_json.as_ref().and_then(|c| c.json.vendor)) + }; let path = if use_node_modules_dir == Some(false) { return Ok(None); } else if let Some(state) = &*NPM_PROCESS_STATE { return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from)); - } else if let Some(package_json_path) = maybe_package_json.map(|c| &c.path) { + } else if root_folder.pkg_json.is_some() { + let node_modules_dir = resolve_from_root(root_folder, cwd); if let Ok(deno_dir) = deno_dir_provider.get_or_create() { // `deno_dir.root` can be symlink in macOS if let Ok(root) = canonicalize_path_maybe_not_exists(&deno_dir.root) { - if package_json_path.starts_with(root) { + if node_modules_dir.starts_with(root) { // if the package.json is in deno_dir, then do not use node_modules // next to it as local node_modules dir return Ok(None); } } } - // auto-discover the local_node_modules_folder when a package.json exists - // and it's not in deno_dir - package_json_path.parent().unwrap().join("node_modules") + node_modules_dir } else if use_node_modules_dir.is_none() { return Ok(None); - } else if let Some(config_path) = maybe_config_file - .as_ref() - .and_then(|c| c.specifier.to_file_path().ok()) - { - config_path.parent().unwrap().join("node_modules") } else { - cwd.join("node_modules") + resolve_from_root(root_folder, cwd) }; Ok(Some(canonicalize_path_maybe_not_exists(&path)?)) } @@ -1886,19 +1856,18 @@ pub fn npm_pkg_req_ref_to_binary_command( pub fn config_to_deno_graph_workspace_member( config: &ConfigFile, ) -> Result { - let nv = deno_semver::package::PackageNv { - name: match &config.json.name { - Some(name) => name.clone(), - None => bail!("Missing 'name' field in config file."), - }, - version: match &config.json.version { - Some(name) => deno_semver::Version::parse_standard(name)?, - None => bail!("Missing 'version' field in config file."), - }, + let name = match &config.json.name { + Some(name) => name.clone(), + None => bail!("Missing 'name' field in config file."), + }; + let version = match &config.json.version { + Some(name) => Some(deno_semver::Version::parse_standard(name)?), + None => None, }; Ok(deno_graph::WorkspaceMember { base: config.specifier.join("./").unwrap(), - nv, + name, + version, exports: config.to_exports_config()?.into_map(), }) } diff --git a/cli/args/package_json.rs b/cli/args/package_json.rs index eedd0a1941..2ef39a30d2 100644 --- a/cli/args/package_json.rs +++ b/cli/args/package_json.rs @@ -4,102 +4,153 @@ use std::path::PathBuf; use std::sync::Arc; use deno_config::workspace::Workspace; +use deno_core::serde_json; use deno_package_json::PackageJsonDepValue; +use deno_package_json::PackageJsonDepValueParseError; +use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; #[derive(Debug)] pub struct InstallNpmRemotePkg { - pub alias: String, - // todo(24419): use this when setting up the node_modules dir - #[allow(dead_code)] + pub alias: Option, pub base_dir: PathBuf, pub req: PackageReq, } #[derive(Debug)] pub struct InstallNpmWorkspacePkg { - pub alias: String, - // todo(24419): use this when setting up the node_modules dir - #[allow(dead_code)] - pub base_dir: PathBuf, + pub alias: Option, pub target_dir: PathBuf, } #[derive(Debug, Default)] -pub struct PackageJsonInstallDepsProvider { +pub struct NpmInstallDepsProvider { remote_pkgs: Vec, workspace_pkgs: Vec, + pkg_json_dep_errors: Vec, } -impl PackageJsonInstallDepsProvider { +impl NpmInstallDepsProvider { pub fn empty() -> Self { Self::default() } pub fn from_workspace(workspace: &Arc) -> Self { + // todo(dsherret): estimate capacity? let mut workspace_pkgs = Vec::new(); let mut remote_pkgs = Vec::new(); + let mut pkg_json_dep_errors = Vec::new(); let workspace_npm_pkgs = workspace.npm_packages(); - for pkg_json in workspace.package_jsons() { - let deps = pkg_json.resolve_local_package_json_deps(); - let mut pkg_pkgs = Vec::with_capacity(deps.len()); - for (alias, dep) in deps { - let Ok(dep) = dep else { - continue; - }; - match dep { - PackageJsonDepValue::Req(pkg_req) => { - let workspace_pkg = workspace_npm_pkgs.iter().find(|pkg| { - pkg.matches_req(&pkg_req) - // do not resolve to the current package - && pkg.pkg_json.path != pkg_json.path - }); + + for (_, folder) in workspace.config_folders() { + // deal with the deno.json first because it takes precedence during resolution + if let Some(deno_json) = &folder.deno_json { + // don't bother with externally referenced import maps as users + // should inline their import map to get this behaviour + if let Some(serde_json::Value::Object(obj)) = &deno_json.json.imports { + let mut pkg_pkgs = Vec::with_capacity(obj.len()); + for (_alias, value) in obj { + let serde_json::Value::String(specifier) = value else { + continue; + }; + let Ok(npm_req_ref) = NpmPackageReqReference::from_str(specifier) + else { + continue; + }; + let pkg_req = npm_req_ref.into_inner().req; + let workspace_pkg = workspace_npm_pkgs + .iter() + .find(|pkg| pkg.matches_req(&pkg_req)); if let Some(pkg) = workspace_pkg { workspace_pkgs.push(InstallNpmWorkspacePkg { - alias, - base_dir: pkg_json.dir_path().to_path_buf(), + alias: None, target_dir: pkg.pkg_json.dir_path().to_path_buf(), }); } else { pkg_pkgs.push(InstallNpmRemotePkg { - alias, - base_dir: pkg_json.dir_path().to_path_buf(), + alias: None, + base_dir: deno_json.dir_path(), req: pkg_req, }); } } - PackageJsonDepValue::Workspace(version_req) => { - if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| { - pkg.matches_name_and_version_req(&alias, &version_req) - }) { - workspace_pkgs.push(InstallNpmWorkspacePkg { - alias, - base_dir: pkg_json.dir_path().to_path_buf(), - target_dir: pkg.pkg_json.dir_path().to_path_buf(), + + // sort within each package (more like npm resolution) + pkg_pkgs.sort_by(|a, b| a.req.cmp(&b.req)); + remote_pkgs.extend(pkg_pkgs); + } + } + + if let Some(pkg_json) = &folder.pkg_json { + let deps = pkg_json.resolve_local_package_json_deps(); + let mut pkg_pkgs = Vec::with_capacity(deps.len()); + for (alias, dep) in deps { + let dep = match dep { + Ok(dep) => dep, + Err(err) => { + pkg_json_dep_errors.push(err); + continue; + } + }; + match dep { + PackageJsonDepValue::Req(pkg_req) => { + let workspace_pkg = workspace_npm_pkgs.iter().find(|pkg| { + pkg.matches_req(&pkg_req) + // do not resolve to the current package + && pkg.pkg_json.path != pkg_json.path }); + + if let Some(pkg) = workspace_pkg { + workspace_pkgs.push(InstallNpmWorkspacePkg { + alias: Some(alias), + target_dir: pkg.pkg_json.dir_path().to_path_buf(), + }); + } else { + pkg_pkgs.push(InstallNpmRemotePkg { + alias: Some(alias), + base_dir: pkg_json.dir_path().to_path_buf(), + req: pkg_req, + }); + } + } + PackageJsonDepValue::Workspace(version_req) => { + if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| { + pkg.matches_name_and_version_req(&alias, &version_req) + }) { + workspace_pkgs.push(InstallNpmWorkspacePkg { + alias: Some(alias), + target_dir: pkg.pkg_json.dir_path().to_path_buf(), + }); + } } } } - } - // sort within each package - pkg_pkgs.sort_by(|a, b| a.alias.cmp(&b.alias)); - remote_pkgs.extend(pkg_pkgs); + // sort within each package as npm does + pkg_pkgs.sort_by(|a, b| a.alias.cmp(&b.alias)); + remote_pkgs.extend(pkg_pkgs); + } } + remote_pkgs.shrink_to_fit(); workspace_pkgs.shrink_to_fit(); Self { remote_pkgs, workspace_pkgs, + pkg_json_dep_errors, } } - pub fn remote_pkgs(&self) -> &Vec { + pub fn remote_pkgs(&self) -> &[InstallNpmRemotePkg] { &self.remote_pkgs } - pub fn workspace_pkgs(&self) -> &Vec { + pub fn workspace_pkgs(&self) -> &[InstallNpmWorkspacePkg] { &self.workspace_pkgs } + + pub fn pkg_json_dep_errors(&self) -> &[PackageJsonDepValueParseError] { + &self.pkg_json_dep_errors + } } diff --git a/cli/auth_tokens.rs b/cli/auth_tokens.rs index 42009ef27b..ef9f9d0746 100644 --- a/cli/auth_tokens.rs +++ b/cli/auth_tokens.rs @@ -123,19 +123,19 @@ impl AuthTokens { pub fn new(maybe_tokens_str: Option) -> Self { let mut tokens = Vec::new(); if let Some(tokens_str) = maybe_tokens_str { - for token_str in tokens_str.split(';') { + for token_str in tokens_str.trim().split(';') { if token_str.contains('@') { - let pair: Vec<&str> = token_str.rsplitn(2, '@').collect(); - let token = pair[1]; - let host = AuthDomain::from(pair[0]); + let mut iter = token_str.rsplitn(2, '@'); + let host = AuthDomain::from(iter.next().unwrap()); + let token = iter.next().unwrap(); if token.contains(':') { - let pair: Vec<&str> = token.rsplitn(2, ':').collect(); - let username = pair[1].to_string(); - let password = pair[0].to_string(); + let mut iter = token.rsplitn(2, ':'); + let password = iter.next().unwrap().to_owned(); + let username = iter.next().unwrap().to_owned(); tokens.push(AuthToken { host, token: AuthTokenData::Basic { username, password }, - }) + }); } else { tokens.push(AuthToken { host, @@ -211,6 +211,40 @@ mod tests { ); } + #[test] + fn test_auth_tokens_space() { + let auth_tokens = AuthTokens::new(Some( + " abc123@deno.land;def456@example.com\t".to_string(), + )); + let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap(); + assert_eq!( + auth_tokens.get(&fixture).unwrap().to_string(), + "Bearer abc123".to_string() + ); + let fixture = resolve_url("http://example.com/a/file.ts").unwrap(); + assert_eq!( + auth_tokens.get(&fixture).unwrap().to_string(), + "Bearer def456".to_string() + ); + } + + #[test] + fn test_auth_tokens_newline() { + let auth_tokens = AuthTokens::new(Some( + "\nabc123@deno.land;def456@example.com\n".to_string(), + )); + let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap(); + assert_eq!( + auth_tokens.get(&fixture).unwrap().to_string(), + "Bearer abc123".to_string() + ); + let fixture = resolve_url("http://example.com/a/file.ts").unwrap(); + assert_eq!( + auth_tokens.get(&fixture).unwrap().to_string(), + "Bearer def456".to_string() + ); + } + #[test] fn test_auth_tokens_port() { let auth_tokens = diff --git a/cli/bench/console.js b/cli/bench/console.js index 947061a3b9..1d336fbbde 100644 --- a/cli/bench/console.js +++ b/cli/bench/console.js @@ -1,3 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const count = 100000; for (let i = 0; i < count; i++) console.log("Hello World"); diff --git a/cli/bench/deno_common.js b/cli/bench/deno_common.js index ba88c79ca4..3693333915 100644 --- a/cli/bench/deno_common.js +++ b/cli/bench/deno_common.js @@ -46,8 +46,7 @@ Deno.bench("b64_rt_short", { n: 1e6 }, () => { const buf = new Uint8Array(100); const file = Deno.openSync("/dev/zero"); Deno.bench("read_zero", { n: 5e5 }, () => { - // deno-lint-ignore no-deprecated-deno-api - Deno.readSync(file.rid, buf); + file.readSync(buf); }); } diff --git a/cli/bench/encode_into.js b/cli/bench/encode_into.js index 4881f87528..11f5a56d90 100644 --- a/cli/bench/encode_into.js +++ b/cli/bench/encode_into.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + let [total, count] = typeof Deno !== "undefined" ? Deno.args : [process.argv[2], process.argv[3]]; diff --git a/cli/bench/getrandom.js b/cli/bench/getrandom.js index 87149afebd..3c3ec4aa19 100644 --- a/cli/bench/getrandom.js +++ b/cli/bench/getrandom.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + let [total, count] = typeof Deno !== "undefined" ? Deno.args : [process.argv[2], process.argv[3]]; diff --git a/cli/bench/http.rs b/cli/bench/http.rs deleted file mode 100644 index c43bbef32c..0000000000 --- a/cli/bench/http.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::collections::HashMap; -use std::net::TcpStream; -use std::path::Path; -use std::process::Command; -use std::sync::atomic::AtomicU16; -use std::sync::atomic::Ordering; -use std::time::Duration; -use std::time::Instant; - -use super::Result; - -pub use test_util::parse_wrk_output; -pub use test_util::WrkOutput as HttpBenchmarkResult; -// Some of the benchmarks in this file have been renamed. In case the history -// somehow gets messed up: -// "node_http" was once called "node" -// "deno_tcp" was once called "deno" -// "deno_http" was once called "deno_net_http" - -const DURATION: &str = "10s"; - -pub fn benchmark( - target_path: &Path, -) -> Result> { - let deno_exe = test_util::deno_exe_path(); - let deno_exe = deno_exe.to_string(); - - let hyper_hello_exe = target_path.join("test_server"); - let hyper_hello_exe = hyper_hello_exe.to_str().unwrap(); - - let mut res = HashMap::new(); - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - let http_dir = manifest_dir.join("bench").join("http"); - for entry in std::fs::read_dir(&http_dir)? { - let entry = entry?; - let pathbuf = entry.path(); - let path = pathbuf.to_str().unwrap(); - if path.ends_with(".lua") { - continue; - } - let file_stem = pathbuf.file_stem().unwrap().to_str().unwrap(); - - let lua_script = http_dir.join(format!("{file_stem}.lua")); - let mut maybe_lua = None; - if lua_script.exists() { - maybe_lua = Some(lua_script.to_str().unwrap()); - } - - let port = get_port(); - // deno run -A --unstable - res.insert( - file_stem.to_string(), - run( - &[ - deno_exe.as_str(), - "run", - "--allow-all", - "--unstable", - "--enable-testing-features-do-not-use", - path, - &server_addr(port), - ], - port, - None, - None, - maybe_lua, - )?, - ); - } - - res.insert("hyper".to_string(), hyper_http(hyper_hello_exe)?); - - Ok(res) -} - -fn run( - server_cmd: &[&str], - port: u16, - env: Option>, - origin_cmd: Option<&[&str]>, - lua_script: Option<&str>, -) -> Result { - // Wait for port 4544 to become available. - // TODO Need to use SO_REUSEPORT with tokio::net::TcpListener. - std::thread::sleep(Duration::from_secs(5)); - - let mut origin = None; - if let Some(cmd) = origin_cmd { - let mut com = Command::new(cmd[0]); - com.args(&cmd[1..]); - if let Some(env) = env.clone() { - com.envs(env); - } - origin = Some(com.spawn()?); - }; - - println!("{}", server_cmd.join(" ")); - let mut server = { - let mut com = Command::new(server_cmd[0]); - com.args(&server_cmd[1..]); - if let Some(env) = env { - com.envs(env); - } - com.spawn()? - }; - - // Wait for server to wake up. - let now = Instant::now(); - let addr = format!("127.0.0.1:{port}"); - while now.elapsed().as_secs() < 30 { - if TcpStream::connect(&addr).is_ok() { - break; - } - std::thread::sleep(Duration::from_millis(10)); - } - TcpStream::connect(&addr).expect("Failed to connect to server in time"); - println!("Server took {} ms to start", now.elapsed().as_millis()); - - let wrk = test_util::prebuilt_tool_path("wrk"); - assert!(wrk.is_file()); - - let addr = format!("http://{addr}/"); - let wrk = wrk.to_string(); - let mut wrk_cmd = vec![wrk.as_str(), "-d", DURATION, "--latency", &addr]; - - if let Some(lua_script) = lua_script { - wrk_cmd.push("-s"); - wrk_cmd.push(lua_script); - } - - println!("{}", wrk_cmd.join(" ")); - let output = test_util::run_collect(&wrk_cmd, None, None, None, true).0; - - std::thread::sleep(Duration::from_secs(1)); // wait to capture failure. TODO racy. - - println!("{output}"); - assert!( - server.try_wait()?.map(|s| s.success()).unwrap_or(true), - "server ended with error" - ); - - server.kill()?; - if let Some(mut origin) = origin { - origin.kill()?; - } - - Ok(parse_wrk_output(&output)) -} - -static NEXT_PORT: AtomicU16 = AtomicU16::new(4544); -pub(crate) fn get_port() -> u16 { - let p = NEXT_PORT.load(Ordering::SeqCst); - NEXT_PORT.store(p.wrapping_add(1), Ordering::SeqCst); - p -} - -fn server_addr(port: u16) -> String { - format!("0.0.0.0:{port}") -} - -fn hyper_http(exe: &str) -> Result { - let port = get_port(); - println!("http_benchmark testing RUST hyper"); - run(&[exe, &port.to_string()], port, None, None, None) -} diff --git a/cli/bench/http/deno_flash_hono_router.js b/cli/bench/http/deno_flash_hono_router.js deleted file mode 100644 index baced0cece..0000000000 --- a/cli/bench/http/deno_flash_hono_router.js +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { Hono } from "https://deno.land/x/hono@v2.0.9/mod.ts"; - -const addr = Deno.args[0] || "127.0.0.1:4500"; -const [hostname, port] = addr.split(":"); - -const app = new Hono(); -app.get("/", (c) => c.text("Hello, World!")); - -Deno.serve({ port: Number(port), hostname }, app.fetch); diff --git a/cli/bench/http/deno_flash_send_file.js b/cli/bench/http/deno_flash_send_file.js deleted file mode 100644 index bf8541f8b0..0000000000 --- a/cli/bench/http/deno_flash_send_file.js +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -const addr = Deno.args[0] || "127.0.0.1:4500"; -const [hostname, port] = addr.split(":"); -const { serve } = Deno; - -const path = new URL("../testdata/128k.bin", import.meta.url).pathname; - -function handler() { - const file = Deno.openSync(path); - return new Response(file.readable); -} - -serve({ hostname, port: Number(port) }, handler); diff --git a/cli/bench/http/deno_http_read_headers.lua b/cli/bench/http/deno_http_read_headers.lua deleted file mode 100644 index 64f1923ff3..0000000000 --- a/cli/bench/http/deno_http_read_headers.lua +++ /dev/null @@ -1,5 +0,0 @@ -wrk.headers["foo"] = "bar" -wrk.headers["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" -wrk.headers["Viewport-Width"] = "1920" -wrk.headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -wrk.headers["Accept-Language"] = "en,la;q=0.9" \ No newline at end of file diff --git a/cli/bench/http/deno_http_serve.js b/cli/bench/http/deno_http_serve.js deleted file mode 100644 index 639982ce60..0000000000 --- a/cli/bench/http/deno_http_serve.js +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -const addr = Deno.args[0] ?? "127.0.0.1:4500"; -const [hostname, port] = addr.split(":"); -const { serve } = Deno; - -function handler() { - return new Response("Hello World"); -} - -serve({ hostname, port: Number(port), reusePort: true }, handler); diff --git a/cli/bench/http/deno_post_bin.lua b/cli/bench/http/deno_post_bin.lua deleted file mode 100644 index c8f5d3e3f7..0000000000 --- a/cli/bench/http/deno_post_bin.lua +++ /dev/null @@ -1,5 +0,0 @@ -wrk.method = "POST" -wrk.headers["Content-Type"] = "application/octet-stream" - -file = io.open("./cli/bench/testdata/128k.bin", "rb") -wrk.body = file:read("*a") \ No newline at end of file diff --git a/cli/bench/http/deno_post_json.lua b/cli/bench/http/deno_post_json.lua deleted file mode 100644 index cc6c4e226d..0000000000 --- a/cli/bench/http/deno_post_json.lua +++ /dev/null @@ -1,3 +0,0 @@ -wrk.method = "POST" -wrk.headers["Content-Type"] = "application/json" -wrk.body = '{"hello":"deno"}' \ No newline at end of file diff --git a/cli/bench/http/deno_reactdom_ssr_flash.jsx b/cli/bench/http/deno_reactdom_ssr_flash.jsx deleted file mode 100644 index eaabf89121..0000000000 --- a/cli/bench/http/deno_reactdom_ssr_flash.jsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -import { renderToReadableStream } from "https://esm.run/react-dom/server"; -import * as React from "https://esm.run/react"; -const { serve } = Deno; -const addr = Deno.args[0] || "127.0.0.1:4500"; -const [hostname, port] = addr.split(":"); - -const App = () => ( - - -

Hello World

- - -); - -const headers = { - headers: { - "Content-Type": "text/html", - }, -}; - -serve({ hostname, port: Number(port) }, async () => { - return new Response(await renderToReadableStream(), headers); -}); diff --git a/cli/bench/http/deno_tcp.ts b/cli/bench/http/deno_tcp.ts deleted file mode 100644 index bac9ac4973..0000000000 --- a/cli/bench/http/deno_tcp.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// Used for benchmarking Deno's networking. -// TODO(bartlomieju): Replace this with a real HTTP server once -// https://github.com/denoland/deno/issues/726 is completed. -// Note: this is a keep-alive server. -const addr = Deno.args[0] || "127.0.0.1:4500"; -const [hostname, port] = addr.split(":"); -const listener = Deno.listen({ hostname, port: Number(port) }); -const response = new TextEncoder().encode( - "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n", -); -async function handle(conn: Deno.Conn): Promise { - const buffer = new Uint8Array(1024); - try { - while (true) { - await conn.read(buffer); - await conn.write(response); - } - } catch (e) { - if ( - !(e instanceof Deno.errors.BrokenPipe) && - !(e instanceof Deno.errors.ConnectionReset) - ) { - throw e; - } - } - conn.close(); -} - -console.log("Listening on", addr); -for await (const conn of listener) { - handle(conn); -} diff --git a/cli/bench/lsp.rs b/cli/bench/lsp.rs index f2070eb216..7baaffca7e 100644 --- a/cli/bench/lsp.rs +++ b/cli/bench/lsp.rs @@ -4,9 +4,10 @@ use deno_core::serde::Deserialize; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; -use deno_core::url::Url; +use lsp_types::Uri; use std::collections::HashMap; use std::path::Path; +use std::str::FromStr; use std::time::Duration; use test_util::lsp::LspClientBuilder; use test_util::PathRef; @@ -91,7 +92,7 @@ fn bench_deco_apps_edits(deno_exe: &Path) -> Duration { .build(); client.initialize(|c| { c.set_workspace_folders(vec![lsp_types::WorkspaceFolder { - uri: Url::from_file_path(&apps).unwrap(), + uri: apps.uri_dir(), name: "apps".to_string(), }]); c.set_deno_enable(true); @@ -149,7 +150,11 @@ fn bench_big_file_edits(deno_exe: &Path) -> Duration { .deno_exe(deno_exe) .build(); client.initialize_default(); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.change_configuration(json!({ "deno": { "enable": true } })); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.write_notification( "textDocument/didOpen", @@ -205,6 +210,8 @@ fn bench_code_lens(deno_exe: &Path) -> Duration { .deno_exe(deno_exe) .build(); client.initialize_default(); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.change_configuration(json!({ "deno": { "enable": true, "codeLens": { @@ -213,6 +220,8 @@ fn bench_code_lens(deno_exe: &Path) -> Duration { "test": true, }, } })); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.write_notification( "textDocument/didOpen", @@ -256,7 +265,11 @@ fn bench_find_replace(deno_exe: &Path) -> Duration { .deno_exe(deno_exe) .build(); client.initialize_default(); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.change_configuration(json!({ "deno": { "enable": true } })); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); for i in 0..10 { client.write_notification( @@ -283,7 +296,7 @@ fn bench_find_replace(deno_exe: &Path) -> Duration { "textDocument/didChange", lsp::DidChangeTextDocumentParams { text_document: lsp::VersionedTextDocumentIdentifier { - uri: Url::parse(&file_name).unwrap(), + uri: Uri::from_str(&file_name).unwrap(), version: 2, }, content_changes: vec![lsp::TextDocumentContentChangeEvent { @@ -310,7 +323,7 @@ fn bench_find_replace(deno_exe: &Path) -> Duration { "textDocument/formatting", lsp::DocumentFormattingParams { text_document: lsp::TextDocumentIdentifier { - uri: Url::parse(&file_name).unwrap(), + uri: Uri::from_str(&file_name).unwrap(), }, options: lsp::FormattingOptions { tab_size: 2, @@ -340,7 +353,11 @@ fn bench_startup_shutdown(deno_exe: &Path) -> Duration { .deno_exe(deno_exe) .build(); client.initialize_default(); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.change_configuration(json!({ "deno": { "enable": true } })); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.write_notification( "textDocument/didOpen", diff --git a/cli/bench/lsp_bench_standalone.rs b/cli/bench/lsp_bench_standalone.rs index 9c4f264ec9..3c946cfbe3 100644 --- a/cli/bench/lsp_bench_standalone.rs +++ b/cli/bench/lsp_bench_standalone.rs @@ -13,7 +13,11 @@ use test_util::lsp::LspClientBuilder; fn incremental_change_wait(bench: &mut Bencher) { let mut client = LspClientBuilder::new().use_diagnostic_sync(false).build(); client.initialize_default(); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.change_configuration(json!({ "deno": { "enable": true } })); + let (method, _): (String, Option) = client.read_notification(); + assert_eq!(method, "deno/didRefreshDenoConfigurationTree"); client.write_notification( "textDocument/didOpen", diff --git a/cli/bench/main.rs b/cli/bench/main.rs index 68f4c6ce3a..c3c42d2488 100644 --- a/cli/bench/main.rs +++ b/cli/bench/main.rs @@ -17,7 +17,6 @@ use std::process::Stdio; use std::time::SystemTime; use test_util::PathRef; -mod http; mod lsp; fn read_json(filename: &Path) -> Result { @@ -143,29 +142,6 @@ const EXEC_TIME_BENCHMARKS: &[(&str, &[&str], Option)] = &[ ], None, ), - ( - "bundle", - &[ - "bundle", - "--unstable", - "--config", - "tests/config/deno.json", - "tests/util/std/http/file_server_test.ts", - ], - None, - ), - ( - "bundle_no_check", - &[ - "bundle", - "--no-check", - "--unstable", - "--config", - "tests/config/deno.json", - "tests/util/std/http/file_server_test.ts", - ], - None, - ), ]; const RESULT_KEYS: &[&str] = @@ -314,40 +290,6 @@ fn get_binary_sizes(target_dir: &Path) -> Result> { Ok(sizes) } -const BUNDLES: &[(&str, &str)] = &[ - ("file_server", "./tests/util/std/http/file_server.ts"), - ("welcome", "./tests/testdata/welcome.ts"), -]; -fn bundle_benchmark(deno_exe: &Path) -> Result> { - let mut sizes = HashMap::::new(); - - for (name, url) in BUNDLES { - let path = format!("{name}.bundle.js"); - test_util::run( - &[ - deno_exe.to_str().unwrap(), - "bundle", - "--unstable", - "--config", - "tests/config/deno.json", - url, - &path, - ], - None, - None, - None, - true, - ); - - let file = PathBuf::from(path); - assert!(file.is_file()); - sizes.insert(name.to_string(), file.metadata()?.len() as i64); - let _ = fs::remove_file(file); - } - - Ok(sizes) -} - fn run_max_mem_benchmark(deno_exe: &Path) -> Result> { let mut results = HashMap::::new(); @@ -402,9 +344,11 @@ struct BenchResult { binary_size: HashMap, bundle_size: HashMap, cargo_deps: usize, + // TODO(bartlomieju): remove max_latency: HashMap, max_memory: HashMap, lsp_exec_time: HashMap, + // TODO(bartlomieju): remove req_per_sec: HashMap, syscall_count: HashMap, thread_count: HashMap, @@ -415,12 +359,10 @@ async fn main() -> Result<()> { let mut args = env::args(); let mut benchmarks = vec![ - "bundle", "exec_time", "binary_size", "cargo_deps", "lsp", - "http", "strace", "mem_usage", ]; @@ -465,11 +407,6 @@ async fn main() -> Result<()> { ..Default::default() }; - if benchmarks.contains(&"bundle") { - let bundle_size = bundle_benchmark(&deno_exe)?; - new_data.bundle_size = bundle_size; - } - if benchmarks.contains(&"exec_time") { let exec_times = run_exec_time(&deno_exe, &target_dir)?; new_data.benchmark = exec_times; @@ -490,21 +427,6 @@ async fn main() -> Result<()> { new_data.lsp_exec_time = lsp_exec_times; } - if benchmarks.contains(&"http") && cfg!(not(target_os = "windows")) { - let stats = http::benchmark(target_dir.as_path())?; - let req_per_sec = stats - .iter() - .map(|(name, result)| (name.clone(), result.requests as i64)) - .collect(); - new_data.req_per_sec = req_per_sec; - let max_latency = stats - .iter() - .map(|(name, result)| (name.clone(), result.latency)) - .collect(); - - new_data.max_latency = max_latency; - } - if cfg!(target_os = "linux") && benchmarks.contains(&"strace") { use std::io::Read; diff --git a/cli/bench/op_now.js b/cli/bench/op_now.js index ba6be9c3a0..bcc3ea3c56 100644 --- a/cli/bench/op_now.js +++ b/cli/bench/op_now.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const queueMicrotask = globalThis.queueMicrotask || process.nextTick; let [total, count] = typeof Deno !== "undefined" ? Deno.args diff --git a/cli/bench/secure_curves.js b/cli/bench/secure_curves.js index d1e909c4c8..02d248b23f 100644 --- a/cli/bench/secure_curves.js +++ b/cli/bench/secure_curves.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + let [total, count] = typeof Deno !== "undefined" ? Deno.args : [process.argv[2], process.argv[3]]; diff --git a/cli/bench/stdio/stdio.js b/cli/bench/stdio/stdio.js index 7f0e16b4a0..81bea835a6 100644 --- a/cli/bench/stdio/stdio.js +++ b/cli/bench/stdio/stdio.js @@ -2,6 +2,8 @@ // // From https://github.com/just-js/benchmarks/tree/main/01-stdio +// deno-lint-ignore-file no-console + const blocksize = parseInt(Deno.args[0] || 65536); const buf = new Uint8Array(blocksize); let size = 0; diff --git a/cli/bench/tty.js b/cli/bench/tty.js index 62319c71f2..248a901137 100644 --- a/cli/bench/tty.js +++ b/cli/bench/tty.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const queueMicrotask = globalThis.queueMicrotask || process.nextTick; let [total, count] = typeof Deno !== "undefined" ? Deno.args diff --git a/cli/bench/url_parse.js b/cli/bench/url_parse.js index c9b62107f5..367cf73f46 100644 --- a/cli/bench/url_parse.js +++ b/cli/bench/url_parse.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const queueMicrotask = globalThis.queueMicrotask || process.nextTick; let [total, count] = typeof Deno !== "undefined" ? Deno.args diff --git a/cli/bench/webstorage.js b/cli/bench/webstorage.js index b200ef2532..d19f024c63 100644 --- a/cli/bench/webstorage.js +++ b/cli/bench/webstorage.js @@ -1,5 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + // Note: when benchmarking across different Deno version, make sure to clear // the DENO_DIR cache. let [total, count] = typeof Deno !== "undefined" ? Deno.args : []; diff --git a/cli/bench/write_file.js b/cli/bench/write_file.js index ab1e2280ee..104a23a8db 100644 --- a/cli/bench/write_file.js +++ b/cli/bench/write_file.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const queueMicrotask = globalThis.queueMicrotask || process.nextTick; let [total, count] = typeof Deno !== "undefined" ? Deno.args diff --git a/cli/build.rs b/cli/build.rs index 0b964ad433..2678a8dbb0 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -13,7 +13,6 @@ mod ts { use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; - use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES; use serde::Serialize; use std::collections::HashMap; use std::io::Write; @@ -25,7 +24,6 @@ mod ts { struct BuildInfoResponse { build_specifier: String, libs: Vec, - node_built_in_module_names: Vec, } #[op2] @@ -37,14 +35,9 @@ mod ts { .iter() .map(|s| s.to_string()) .collect(); - let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES - .iter() - .map(|s| s.to_string()) - .collect(); BuildInfoResponse { build_specifier, libs: build_libs, - node_built_in_module_names, } } @@ -243,6 +236,7 @@ mod ts { "esnext.decorators", "esnext.disposable", "esnext.intl", + "esnext.iterator", "esnext.object", "esnext.promise", "esnext.regexp", @@ -371,6 +365,9 @@ fn main() { return; } + deno_napi::print_linker_flags("deno"); + deno_napi::print_linker_flags("denort"); + // Host snapshots won't work when cross compiling. let target = env::var("TARGET").unwrap(); let host = env::var("HOST").unwrap(); @@ -380,56 +377,6 @@ fn main() { panic!("Cross compiling with snapshot is not supported."); } - let symbols_file_name = match env::consts::OS { - "android" | "freebsd" | "openbsd" => { - "generated_symbol_exports_list_linux.def".to_string() - } - os => format!("generated_symbol_exports_list_{}.def", os), - }; - let symbols_path = std::path::Path::new("napi") - .join(symbols_file_name) - .canonicalize() - .expect( - "Missing symbols list! Generate using tools/napi/generate_symbols_lists.js", - ); - - #[cfg(target_os = "windows")] - println!( - "cargo:rustc-link-arg-bin=deno=/DEF:{}", - symbols_path.display() - ); - - #[cfg(target_os = "macos")] - println!( - "cargo:rustc-link-arg-bin=deno=-Wl,-exported_symbols_list,{}", - symbols_path.display() - ); - - #[cfg(target_os = "linux")] - { - // If a custom compiler is set, the glibc version is not reliable. - // Here, we assume that if a custom compiler is used, that it will be modern enough to support a dynamic symbol list. - if env::var("CC").is_err() - && glibc_version::get_version() - .map(|ver| ver.major <= 2 && ver.minor < 35) - .unwrap_or(false) - { - println!("cargo:warning=Compiling with all symbols exported, this will result in a larger binary. Please use glibc 2.35 or later for an optimised build."); - println!("cargo:rustc-link-arg-bin=deno=-rdynamic"); - } else { - println!( - "cargo:rustc-link-arg-bin=deno=-Wl,--export-dynamic-symbol-list={}", - symbols_path.display() - ); - } - } - - #[cfg(target_os = "android")] - println!( - "cargo:rustc-link-arg-bin=deno=-Wl,--export-dynamic-symbol-list={}", - symbols_path.display() - ); - // To debug snapshot issues uncomment: // op_fetch_asset::trace_serializer(); @@ -446,7 +393,7 @@ fn main() { ); let ts_version = ts::version(); - debug_assert_eq!(ts_version, "5.5.2"); // bump this assertion when it changes + debug_assert_eq!(ts_version, "5.6.2"); // bump this assertion when it changes println!("cargo:rustc-env=TS_VERSION={}", ts_version); println!("cargo:rerun-if-env-changed=TS_VERSION"); diff --git a/cli/cache/code_cache.rs b/cli/cache/code_cache.rs index d9e951af6e..abcd0d46ac 100644 --- a/cli/cache/code_cache.rs +++ b/cli/cache/code_cache.rs @@ -80,10 +80,6 @@ impl CodeCache { data, )); } - - pub fn remove_code_cache(&self, specifier: &str) { - Self::ensure_ok(self.inner.remove_code_cache(specifier)) - } } impl code_cache::CodeCache for CodeCache { @@ -162,15 +158,6 @@ impl CodeCacheInner { self.conn.execute(sql, params)?; Ok(()) } - - pub fn remove_code_cache(&self, specifier: &str) -> Result<(), AnyError> { - let sql = " - DELETE FROM codecache - WHERE specifier=$1;"; - let params = params![specifier]; - self.conn.execute(sql, params)?; - Ok(()) - } } fn serialize_code_cache_type( diff --git a/cli/cache/deno_dir.rs b/cli/cache/deno_dir.rs index 88d8a31c04..7b7059c224 100644 --- a/cli/cache/deno_dir.rs +++ b/cli/cache/deno_dir.rs @@ -126,9 +126,9 @@ impl DenoDir { self.root.join("registries") } - /// Path to the dependencies cache folder. - pub fn deps_folder_path(&self) -> PathBuf { - self.root.join("deps") + /// Path to the remote cache folder. + pub fn remote_folder_path(&self) -> PathBuf { + self.root.join("remote") } /// Path to the origin data cache folder. diff --git a/cli/cache/emit.rs b/cli/cache/emit.rs index 757df0b756..74e1c1101b 100644 --- a/cli/cache/emit.rs +++ b/cli/cache/emit.rs @@ -5,33 +5,25 @@ use std::path::PathBuf; use deno_ast::ModuleSpecifier; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; -use deno_core::serde_json; use deno_core::unsync::sync::AtomicFlag; -use serde::Deserialize; -use serde::Serialize; use super::DiskCache; -use super::FastInsecureHasher; - -#[derive(Debug, Deserialize, Serialize)] -struct EmitMetadata { - pub source_hash: u64, - pub emit_hash: u64, -} /// The cache that stores previously emitted files. pub struct EmitCache { disk_cache: DiskCache, - cli_version: &'static str, emit_failed_flag: AtomicFlag, + file_serializer: EmitFileSerializer, } impl EmitCache { pub fn new(disk_cache: DiskCache) -> Self { Self { disk_cache, - cli_version: crate::version::DENO_VERSION_INFO.deno, emit_failed_flag: Default::default(), + file_serializer: EmitFileSerializer { + cli_version: crate::version::DENO_VERSION_INFO.deno, + }, } } @@ -47,38 +39,12 @@ impl EmitCache { &self, specifier: &ModuleSpecifier, expected_source_hash: u64, - ) -> Option> { - let meta_filename = self.get_meta_filename(specifier)?; + ) -> Option { let emit_filename = self.get_emit_filename(specifier)?; - - // load and verify the meta data file is for this source and CLI version - let bytes = self.disk_cache.get(&meta_filename).ok()?; - let meta: EmitMetadata = serde_json::from_slice(&bytes).ok()?; - if meta.source_hash != expected_source_hash { - return None; - } - - // load and verify the emit is for the meta data - let emit_bytes = self.disk_cache.get(&emit_filename).ok()?; - if meta.emit_hash != compute_emit_hash(&emit_bytes, self.cli_version) { - return None; - } - - // everything looks good, return it - Some(emit_bytes) - } - - /// Gets the filepath which stores the emit. - pub fn get_emit_filepath( - &self, - specifier: &ModuleSpecifier, - ) -> Option { - Some( - self - .disk_cache - .location - .join(self.get_emit_filename(specifier)?), - ) + let bytes = self.disk_cache.get(&emit_filename).ok()?; + self + .file_serializer + .deserialize(bytes, expected_source_hash) } /// Sets the emit code in the cache. @@ -107,34 +73,15 @@ impl EmitCache { return Ok(()); } - let meta_filename = self - .get_meta_filename(specifier) - .ok_or_else(|| anyhow!("Could not get meta filename."))?; let emit_filename = self .get_emit_filename(specifier) .ok_or_else(|| anyhow!("Could not get emit filename."))?; - - // save the metadata - let metadata = EmitMetadata { - source_hash, - emit_hash: compute_emit_hash(code, self.cli_version), - }; - self - .disk_cache - .set(&meta_filename, &serde_json::to_vec(&metadata)?)?; - - // save the emit source - self.disk_cache.set(&emit_filename, code)?; + let cache_data = self.file_serializer.serialize(code, source_hash); + self.disk_cache.set(&emit_filename, &cache_data)?; Ok(()) } - fn get_meta_filename(&self, specifier: &ModuleSpecifier) -> Option { - self - .disk_cache - .get_cache_filename_with_extension(specifier, "meta") - } - fn get_emit_filename(&self, specifier: &ModuleSpecifier) -> Option { self .disk_cache @@ -142,15 +89,68 @@ impl EmitCache { } } -fn compute_emit_hash(bytes: &[u8], cli_version: &str) -> u64 { - // it's ok to use an insecure hash here because - // if someone can change the emit source then they - // can also change the version hash - FastInsecureHasher::new_without_deno_version() // use cli_version param instead - .write(bytes) - // emit should not be re-used between cli versions - .write_str(cli_version) - .finish() +const LAST_LINE_PREFIX: &str = "\n// denoCacheMetadata="; + +struct EmitFileSerializer { + cli_version: &'static str, +} + +impl EmitFileSerializer { + pub fn deserialize( + &self, + mut bytes: Vec, + expected_source_hash: u64, + ) -> Option { + let last_newline_index = bytes.iter().rposition(|&b| b == b'\n')?; + let (content, last_line) = bytes.split_at(last_newline_index); + let hashes = last_line.strip_prefix(LAST_LINE_PREFIX.as_bytes())?; + let hashes = String::from_utf8_lossy(hashes); + let (source_hash, emit_hash) = hashes.split_once(',')?; + + // verify the meta data file is for this source and CLI version + let source_hash = source_hash.parse::().ok()?; + if source_hash != expected_source_hash { + return None; + } + let emit_hash = emit_hash.parse::().ok()?; + // prevent using an emit from a different cli version or emits that were tampered with + if emit_hash != self.compute_emit_hash(content) { + return None; + } + + // everything looks good, truncate and return it + bytes.truncate(content.len()); + String::from_utf8(bytes).ok() + } + + pub fn serialize(&self, code: &[u8], source_hash: u64) -> Vec { + let source_hash = source_hash.to_string(); + let emit_hash = self.compute_emit_hash(code).to_string(); + let capacity = code.len() + + LAST_LINE_PREFIX.len() + + source_hash.len() + + 1 + + emit_hash.len(); + let mut cache_data = Vec::with_capacity(capacity); + cache_data.extend(code); + cache_data.extend(LAST_LINE_PREFIX.as_bytes()); + cache_data.extend(source_hash.as_bytes()); + cache_data.push(b','); + cache_data.extend(emit_hash.as_bytes()); + debug_assert_eq!(cache_data.len(), capacity); + cache_data + } + + fn compute_emit_hash(&self, bytes: &[u8]) -> u64 { + // it's ok to use an insecure hash here because + // if someone can change the emit source then they + // can also change the version hash + crate::cache::FastInsecureHasher::new_without_deno_version() // use cli_version property instead + .write(bytes) + // emit should not be re-used between cli versions + .write_str(self.cli_version) + .finish() + } } #[cfg(test)] @@ -165,11 +165,11 @@ mod test { let disk_cache = DiskCache::new(temp_dir.path().as_path()); let cache = EmitCache { disk_cache: disk_cache.clone(), - cli_version: "1.0.0", + file_serializer: EmitFileSerializer { + cli_version: "1.0.0", + }, emit_failed_flag: Default::default(), }; - let to_string = - |bytes: Vec| -> String { String::from_utf8(bytes).unwrap() }; let specifier1 = ModuleSpecifier::from_file_path(temp_dir.path().join("file1.ts")) @@ -186,18 +186,17 @@ mod test { assert_eq!(cache.get_emit_code(&specifier1, 5), None); // providing the correct source hash assert_eq!( - cache.get_emit_code(&specifier1, 10).map(to_string), + cache.get_emit_code(&specifier1, 10), Some(emit_code1.clone()), ); - assert_eq!( - cache.get_emit_code(&specifier2, 2).map(to_string), - Some(emit_code2) - ); + assert_eq!(cache.get_emit_code(&specifier2, 2), Some(emit_code2)); // try changing the cli version (should not load previous ones) let cache = EmitCache { disk_cache: disk_cache.clone(), - cli_version: "2.0.0", + file_serializer: EmitFileSerializer { + cli_version: "2.0.0", + }, emit_failed_flag: Default::default(), }; assert_eq!(cache.get_emit_code(&specifier1, 10), None); @@ -206,21 +205,17 @@ mod test { // recreating the cache should still load the data because the CLI version is the same let cache = EmitCache { disk_cache, - cli_version: "2.0.0", + file_serializer: EmitFileSerializer { + cli_version: "2.0.0", + }, emit_failed_flag: Default::default(), }; - assert_eq!( - cache.get_emit_code(&specifier1, 5).map(to_string), - Some(emit_code1) - ); + assert_eq!(cache.get_emit_code(&specifier1, 5), Some(emit_code1)); // adding when already exists should not cause issue let emit_code3 = "asdf".to_string(); cache.set_emit_code(&specifier1, 20, emit_code3.as_bytes()); assert_eq!(cache.get_emit_code(&specifier1, 5), None); - assert_eq!( - cache.get_emit_code(&specifier1, 20).map(to_string), - Some(emit_code3) - ); + assert_eq!(cache.get_emit_code(&specifier1, 20), Some(emit_code3)); } } diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index 772d2359d3..bf8f1b1f0b 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -1,13 +1,21 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use crate::args::jsr_url; use crate::args::CacheSetting; use crate::errors::get_error_class_name; use crate::file_fetcher::FetchNoFollowOptions; use crate::file_fetcher::FetchOptions; +use crate::file_fetcher::FetchPermissionsOptionRef; use crate::file_fetcher::FileFetcher; use crate::file_fetcher::FileOrRedirect; use crate::npm::CliNpmResolver; +use crate::resolver::CliNodeResolver; use crate::util::fs::atomic_write_file_with_retries; +use crate::util::fs::atomic_write_file_with_retries_and_fs; +use crate::util::fs::AtomicWriteFileFsAdapter; +use crate::util::path::specifier_has_extension; +use crate::util::text_encoding::arc_str_to_bytes; +use crate::util::text_encoding::from_utf8_lossy_owned; use deno_ast::MediaType; use deno_core::futures; @@ -52,6 +60,7 @@ pub use fast_check::FastCheckCache; pub use incremental::IncrementalCache; pub use module_info::ModuleInfoCache; pub use node::NodeAnalysisCache; +pub use parsed_source::EsmOrCjsChecker; pub use parsed_source::LazyGraphSourceParser; pub use parsed_source::ParsedSourceCache; @@ -62,12 +71,8 @@ pub const CACHE_PERM: u32 = 0o644; pub struct RealDenoCacheEnv; impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv { - fn read_file_bytes(&self, path: &Path) -> std::io::Result>> { - match std::fs::read(path) { - Ok(s) => Ok(Some(s)), - Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None), - Err(err) => Err(err), - } + fn read_file_bytes(&self, path: &Path) -> std::io::Result> { + std::fs::read(path) } fn atomic_write_file( @@ -78,6 +83,14 @@ impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv { atomic_write_file_with_retries(path, bytes, CACHE_PERM) } + fn canonicalize_path(&self, path: &Path) -> std::io::Result { + crate::util::fs::canonicalize_path(path) + } + + fn create_dir_all(&self, path: &Path) -> std::io::Result<()> { + std::fs::create_dir_all(path) + } + fn modified(&self, path: &Path) -> std::io::Result> { match std::fs::metadata(path) { Ok(metadata) => Ok(Some( @@ -97,43 +110,117 @@ impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv { } } +#[derive(Debug, Clone)] +pub struct DenoCacheEnvFsAdapter<'a>( + pub &'a dyn deno_runtime::deno_fs::FileSystem, +); + +impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> { + fn read_file_bytes(&self, path: &Path) -> std::io::Result> { + self + .0 + .read_file_sync(path, None) + .map_err(|err| err.into_io_error()) + } + + fn atomic_write_file( + &self, + path: &Path, + bytes: &[u8], + ) -> std::io::Result<()> { + atomic_write_file_with_retries_and_fs( + &AtomicWriteFileFsAdapter { + fs: self.0, + write_mode: CACHE_PERM, + }, + path, + bytes, + ) + } + + fn canonicalize_path(&self, path: &Path) -> std::io::Result { + self.0.realpath_sync(path).map_err(|e| e.into_io_error()) + } + + fn create_dir_all(&self, path: &Path) -> std::io::Result<()> { + self + .0 + .mkdir_sync(path, true, None) + .map_err(|e| e.into_io_error()) + } + + fn modified(&self, path: &Path) -> std::io::Result> { + self + .0 + .stat_sync(path) + .map(|stat| { + stat + .mtime + .map(|ts| SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(ts)) + }) + .map_err(|e| e.into_io_error()) + } + + fn is_file(&self, path: &Path) -> bool { + self.0.is_file_sync(path) + } + + fn time_now(&self) -> SystemTime { + SystemTime::now() + } +} + pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache; pub type LocalHttpCache = deno_cache_dir::LocalHttpCache; pub type LocalLspHttpCache = deno_cache_dir::LocalLspHttpCache; pub use deno_cache_dir::HttpCache; +pub struct FetchCacherOptions { + pub file_header_overrides: HashMap>, + pub permissions: PermissionsContainer, + /// If we're publishing for `deno publish`. + pub is_deno_publish: bool, + pub unstable_detect_cjs: bool, +} + /// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides /// a concise interface to the DENO_DIR when building module graphs. pub struct FetchCacher { - emit_cache: Arc, + pub file_header_overrides: HashMap>, + esm_or_cjs_checker: Arc, file_fetcher: Arc, - file_header_overrides: HashMap>, global_http_cache: Arc, + node_resolver: Arc, npm_resolver: Arc, module_info_cache: Arc, permissions: PermissionsContainer, + is_deno_publish: bool, + unstable_detect_cjs: bool, cache_info_enabled: bool, } impl FetchCacher { pub fn new( - emit_cache: Arc, + esm_or_cjs_checker: Arc, file_fetcher: Arc, - file_header_overrides: HashMap>, global_http_cache: Arc, + node_resolver: Arc, npm_resolver: Arc, module_info_cache: Arc, - permissions: PermissionsContainer, + options: FetchCacherOptions, ) -> Self { Self { - emit_cache, file_fetcher, - file_header_overrides, + esm_or_cjs_checker, global_http_cache, + node_resolver, npm_resolver, module_info_cache, - permissions, + file_header_overrides: options.file_header_overrides, + permissions: options.permissions, + is_deno_publish: options.is_deno_publish, + unstable_detect_cjs: options.unstable_detect_cjs, cache_info_enabled: false, } } @@ -144,15 +231,7 @@ impl FetchCacher { self.cache_info_enabled = true; } - // DEPRECATED: Where the file is stored and how it's stored should be an implementation - // detail of the cache. - // - // todo(dsheret): remove once implementing - // * https://github.com/denoland/deno/issues/17707 - // * https://github.com/denoland/deno/issues/17703 - #[deprecated( - note = "There should not be a way to do this because the file may not be cached at a local path in the future." - )] + /// Only use this for `deno info`. fn get_local_path(&self, specifier: &ModuleSpecifier) -> Option { // TODO(@kitsonk) fix when deno_graph does not query cache for synthetic // modules @@ -179,15 +258,7 @@ impl Loader for FetchCacher { #[allow(deprecated)] let local = self.get_local_path(specifier)?; if local.is_file() { - let emit = self - .emit_cache - .get_emit_filepath(specifier) - .filter(|p| p.is_file()); - Some(CacheInfo { - local: Some(local), - emit, - map: None, - }) + Some(CacheInfo { local: Some(local) }) } else { None } @@ -200,27 +271,90 @@ impl Loader for FetchCacher { ) -> LoadFuture { use deno_graph::source::CacheSetting as LoaderCacheSetting; - if specifier.scheme() == "file" - && specifier.path().contains("/node_modules/") - { - // The specifier might be in a completely different symlinked tree than - // what the node_modules url is in (ex. `/my-project-1/node_modules` - // symlinked to `/my-project-2/node_modules`), so first we checked if the path - // is in a node_modules dir to avoid needlessly canonicalizing, then now compare - // against the canonicalized specifier. - let specifier = - crate::node::resolve_specifier_into_node_modules(specifier); - if self.npm_resolver.in_npm_package(&specifier) { + if specifier.scheme() == "file" { + if specifier.path().contains("/node_modules/") { + // The specifier might be in a completely different symlinked tree than + // what the node_modules url is in (ex. `/my-project-1/node_modules` + // symlinked to `/my-project-2/node_modules`), so first we checked if the path + // is in a node_modules dir to avoid needlessly canonicalizing, then now compare + // against the canonicalized specifier. + let specifier = + crate::node::resolve_specifier_into_node_modules(specifier); + if self.npm_resolver.in_npm_package(&specifier) { + return Box::pin(futures::future::ready(Ok(Some( + LoadResponse::External { specifier }, + )))); + } + } + + // make local CJS modules external to the graph + if specifier_has_extension(specifier, "cjs") { return Box::pin(futures::future::ready(Ok(Some( - LoadResponse::External { specifier }, + LoadResponse::External { + specifier: specifier.clone(), + }, )))); } + + if self.unstable_detect_cjs && specifier_has_extension(specifier, "js") { + if let Ok(Some(pkg_json)) = + self.node_resolver.get_closest_package_json(specifier) + { + if pkg_json.typ == "commonjs" { + if let Ok(path) = specifier.to_file_path() { + if let Ok(bytes) = std::fs::read(&path) { + let text: Arc = from_utf8_lossy_owned(bytes).into(); + let is_es_module = match self.esm_or_cjs_checker.is_esm( + specifier, + text.clone(), + MediaType::JavaScript, + ) { + Ok(value) => value, + Err(err) => { + return Box::pin(futures::future::ready(Err(err.into()))); + } + }; + if !is_es_module { + self.node_resolver.mark_cjs_resolution(specifier.clone()); + return Box::pin(futures::future::ready(Ok(Some( + LoadResponse::External { + specifier: specifier.clone(), + }, + )))); + } else { + return Box::pin(futures::future::ready(Ok(Some( + LoadResponse::Module { + specifier: specifier.clone(), + content: arc_str_to_bytes(text), + maybe_headers: None, + }, + )))); + } + } + } + } + } + } + } + + if self.is_deno_publish + && matches!(specifier.scheme(), "http" | "https") + && !specifier.as_str().starts_with(jsr_url().as_str()) + { + // mark non-JSR remote modules as external so we don't need --allow-import + // permissions as these will error out later when publishing + return Box::pin(futures::future::ready(Ok(Some( + LoadResponse::External { + specifier: specifier.clone(), + }, + )))); } let file_fetcher = self.file_fetcher.clone(); let file_header_overrides = self.file_header_overrides.clone(); let permissions = self.permissions.clone(); let specifier = specifier.clone(); + let is_statically_analyzable = !options.was_dynamic_root; async move { let maybe_cache_setting = match options.cache_setting { @@ -239,7 +373,12 @@ impl Loader for FetchCacher { .fetch_no_follow_with_options(FetchNoFollowOptions { fetch_options: FetchOptions { specifier: &specifier, - permissions: &permissions, + permissions: if is_statically_analyzable { + FetchPermissionsOptionRef::StaticContainer(&permissions) + } else { + FetchPermissionsOptionRef::DynamicContainer(&permissions) + }, + maybe_auth: None, maybe_accept: None, maybe_cache_setting: maybe_cache_setting.as_ref(), }, @@ -293,6 +432,7 @@ impl Loader for FetchCacher { fn cache_module_info( &self, specifier: &ModuleSpecifier, + media_type: MediaType, source: &Arc<[u8]>, module_info: &deno_graph::ModuleInfo, ) { @@ -300,7 +440,7 @@ impl Loader for FetchCacher { let source_hash = CacheDBHash::from_source(source); let result = self.module_info_cache.set_module_info( specifier, - MediaType::from_specifier(specifier), + media_type, source_hash, module_info, ); diff --git a/cli/cache/parsed_source.rs b/cli/cache/parsed_source.rs index e956361f46..df6e45c35e 100644 --- a/cli/cache/parsed_source.rs +++ b/cli/cache/parsed_source.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; +use deno_ast::ParseDiagnostic; use deno_ast::ParsedSource; use deno_core::parking_lot::Mutex; use deno_graph::CapturingModuleParser; @@ -149,3 +150,42 @@ impl deno_graph::ParsedSourceStore for ParsedSourceCache { } } } + +pub struct EsmOrCjsChecker { + parsed_source_cache: Arc, +} + +impl EsmOrCjsChecker { + pub fn new(parsed_source_cache: Arc) -> Self { + Self { + parsed_source_cache, + } + } + + pub fn is_esm( + &self, + specifier: &ModuleSpecifier, + source: Arc, + media_type: MediaType, + ) -> Result { + // todo(dsherret): add a file cache here to avoid parsing with swc on each run + let source = match self.parsed_source_cache.get_parsed_source(specifier) { + Some(source) => source.clone(), + None => { + let source = deno_ast::parse_program(deno_ast::ParseParams { + specifier: specifier.clone(), + text: source, + media_type, + capture_tokens: true, // capture because it's used for cjs export analysis + scope_analysis: false, + maybe_syntax: None, + })?; + self + .parsed_source_cache + .set_parsed_source(specifier.clone(), source.clone()); + source + } + }; + Ok(source.is_module()) + } +} diff --git a/cli/clippy.toml b/cli/clippy.toml index c4afef17c4..e20c56c47a 100644 --- a/cli/clippy.toml +++ b/cli/clippy.toml @@ -4,3 +4,6 @@ disallowed-methods = [ disallowed-types = [ { path = "reqwest::Client", reason = "use crate::http_util::HttpClient instead" }, ] +ignore-interior-mutability = [ + "lsp_types::Uri", +] diff --git a/cli/emit.rs b/cli/emit.rs index 61397d1ab7..8e93092e67 100644 --- a/cli/emit.rs +++ b/cli/emit.rs @@ -5,12 +5,14 @@ use crate::cache::FastInsecureHasher; use crate::cache::ParsedSourceCache; use deno_ast::SourceMapOption; +use deno_ast::SourceRange; +use deno_ast::SourceRanged; +use deno_ast::SourceRangedForSpanned; use deno_ast::TranspileResult; use deno_core::error::AnyError; use deno_core::futures::stream::FuturesUnordered; use deno_core::futures::FutureExt; use deno_core::futures::StreamExt; -use deno_core::ModuleCodeBytes; use deno_core::ModuleSpecifier; use deno_graph::MediaType; use deno_graph::Module; @@ -57,6 +59,7 @@ impl Emitter { continue; }; + // todo(https://github.com/denoland/deno_media_type/pull/12): use is_emittable() let is_emittable = matches!( module.media_type, MediaType::TypeScript @@ -90,7 +93,7 @@ impl Emitter { &self, specifier: &ModuleSpecifier, source: &str, - ) -> Option> { + ) -> Option { let source_hash = self.get_source_hash(source); self.emit_cache.get_emit_code(specifier, source_hash) } @@ -100,7 +103,7 @@ impl Emitter { specifier: &ModuleSpecifier, media_type: MediaType, source: &Arc, - ) -> Result { + ) -> Result { // Note: keep this in sync with the sync version below let helper = EmitParsedSourceHelper(self); match helper.pre_emit_parsed_source(specifier, source) { @@ -109,7 +112,7 @@ impl Emitter { let parsed_source_cache = self.parsed_source_cache.clone(); let transpile_and_emit_options = self.transpile_and_emit_options.clone(); - let transpile_result = deno_core::unsync::spawn_blocking({ + let transpiled_source = deno_core::unsync::spawn_blocking({ let specifier = specifier.clone(); let source = source.clone(); move || -> Result<_, AnyError> { @@ -125,11 +128,12 @@ impl Emitter { }) .await .unwrap()?; - Ok(helper.post_emit_parsed_source( + helper.post_emit_parsed_source( specifier, - transpile_result, + &transpiled_source, source_hash, - )) + ); + Ok(transpiled_source) } } } @@ -139,13 +143,13 @@ impl Emitter { specifier: &ModuleSpecifier, media_type: MediaType, source: &Arc, - ) -> Result { + ) -> Result { // Note: keep this in sync with the async version above let helper = EmitParsedSourceHelper(self); match helper.pre_emit_parsed_source(specifier, source) { PreEmitResult::Cached(emitted_text) => Ok(emitted_text), PreEmitResult::NotCached { source_hash } => { - let transpile_result = EmitParsedSourceHelper::transpile( + let transpiled_source = EmitParsedSourceHelper::transpile( &self.parsed_source_cache, specifier, source.clone(), @@ -153,11 +157,12 @@ impl Emitter { &self.transpile_and_emit_options.0, &self.transpile_and_emit_options.1, )?; - Ok(helper.post_emit_parsed_source( + helper.post_emit_parsed_source( specifier, - transpile_result, + &transpiled_source, source_hash, - )) + ); + Ok(transpiled_source) } } } @@ -223,7 +228,7 @@ impl Emitter { } enum PreEmitResult { - Cached(ModuleCodeBytes), + Cached(String), NotCached { source_hash: u64 }, } @@ -241,7 +246,7 @@ impl<'a> EmitParsedSourceHelper<'a> { if let Some(emit_code) = self.0.emit_cache.get_emit_code(specifier, source_hash) { - PreEmitResult::Cached(emit_code.into_boxed_slice().into()) + PreEmitResult::Cached(emit_code) } else { PreEmitResult::NotCached { source_hash } } @@ -254,20 +259,14 @@ impl<'a> EmitParsedSourceHelper<'a> { media_type: MediaType, transpile_options: &deno_ast::TranspileOptions, emit_options: &deno_ast::EmitOptions, - ) -> Result { + ) -> Result { // nothing else needs the parsed source at this point, so remove from // the cache in order to not transpile owned let parsed_source = parsed_source_cache .remove_or_parse_module(specifier, source, media_type)?; - Ok(parsed_source.transpile(transpile_options, emit_options)?) - } - - pub fn post_emit_parsed_source( - &self, - specifier: &ModuleSpecifier, - transpile_result: TranspileResult, - source_hash: u64, - ) -> ModuleCodeBytes { + ensure_no_import_assertion(&parsed_source)?; + let transpile_result = + parsed_source.transpile(transpile_options, emit_options)?; let transpiled_source = match transpile_result { TranspileResult::Owned(source) => source, TranspileResult::Cloned(source) => { @@ -276,11 +275,90 @@ impl<'a> EmitParsedSourceHelper<'a> { } }; debug_assert!(transpiled_source.source_map.is_none()); + let text = String::from_utf8(transpiled_source.source)?; + Ok(text) + } + + pub fn post_emit_parsed_source( + &self, + specifier: &ModuleSpecifier, + transpiled_source: &str, + source_hash: u64, + ) { self.0.emit_cache.set_emit_code( specifier, source_hash, - &transpiled_source.source, + transpiled_source.as_bytes(), ); - transpiled_source.source.into_boxed_slice().into() } } + +// todo(dsherret): this is a temporary measure until we have swc erroring for this +fn ensure_no_import_assertion( + parsed_source: &deno_ast::ParsedSource, +) -> Result<(), AnyError> { + fn has_import_assertion(text: &str) -> bool { + // good enough + text.contains(" assert ") && !text.contains(" with ") + } + + fn create_err( + parsed_source: &deno_ast::ParsedSource, + range: SourceRange, + ) -> AnyError { + let text_info = parsed_source.text_info_lazy(); + let loc = text_info.line_and_column_display(range.start); + let mut msg = "Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword.".to_string(); + msg.push_str("\n\n"); + msg.push_str(range.text_fast(text_info)); + msg.push_str("\n\n"); + msg.push_str(&format!( + " at {}:{}:{}\n", + parsed_source.specifier(), + loc.line_number, + loc.column_number, + )); + deno_core::anyhow::anyhow!("{}", msg) + } + + let Some(module) = parsed_source.program_ref().as_module() else { + return Ok(()); + }; + + for item in &module.body { + match item { + deno_ast::swc::ast::ModuleItem::ModuleDecl(decl) => match decl { + deno_ast::swc::ast::ModuleDecl::Import(n) => { + if n.with.is_some() + && has_import_assertion(n.text_fast(parsed_source.text_info_lazy())) + { + return Err(create_err(parsed_source, n.range())); + } + } + deno_ast::swc::ast::ModuleDecl::ExportAll(n) => { + if n.with.is_some() + && has_import_assertion(n.text_fast(parsed_source.text_info_lazy())) + { + return Err(create_err(parsed_source, n.range())); + } + } + deno_ast::swc::ast::ModuleDecl::ExportNamed(n) => { + if n.with.is_some() + && has_import_assertion(n.text_fast(parsed_source.text_info_lazy())) + { + return Err(create_err(parsed_source, n.range())); + } + } + deno_ast::swc::ast::ModuleDecl::ExportDecl(_) + | deno_ast::swc::ast::ModuleDecl::ExportDefaultDecl(_) + | deno_ast::swc::ast::ModuleDecl::ExportDefaultExpr(_) + | deno_ast::swc::ast::ModuleDecl::TsImportEquals(_) + | deno_ast::swc::ast::ModuleDecl::TsExportAssignment(_) + | deno_ast::swc::ast::ModuleDecl::TsNamespaceExport(_) => {} + }, + deno_ast::swc::ast::ModuleItem::Stmt(_) => {} + } + } + + Ok(()) +} diff --git a/cli/factory.rs b/cli/factory.rs index 25f6afa749..d5ef4fd8b3 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -1,11 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use crate::args::check_warn_tsconfig; use crate::args::get_root_cert_store; use crate::args::CaData; use crate::args::CliOptions; use crate::args::DenoSubcommand; use crate::args::Flags; -use crate::args::PackageJsonInstallDepsProvider; +use crate::args::NpmInstallDepsProvider; use crate::args::StorageKeyResolver; use crate::args::TsConfigType; use crate::cache::Caches; @@ -13,6 +14,7 @@ use crate::cache::CodeCache; use crate::cache::DenoDir; use crate::cache::DenoDirProvider; use crate::cache::EmitCache; +use crate::cache::EsmOrCjsChecker; use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::cache::LocalHttpCache; @@ -31,17 +33,19 @@ use crate::module_loader::ModuleLoadPreparer; use crate::node::CliCjsCodeAnalyzer; use crate::node::CliNodeCodeTranslator; use crate::npm::create_cli_npm_resolver; +use crate::npm::CliByonmNpmResolverCreateOptions; use crate::npm::CliNpmResolver; -use crate::npm::CliNpmResolverByonmCreateOptions; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::resolver::CjsResolutionStore; +use crate::resolver::CliDenoResolverFs; use crate::resolver::CliGraphResolver; use crate::resolver::CliGraphResolverOptions; use crate::resolver::CliNodeResolver; +use crate::resolver::CliSloppyImportsResolver; use crate::resolver::NpmModuleLoader; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::SloppyImportsCachedFs; use crate::standalone::DenoCompileBinaryWriter; use crate::tools::check::TypeChecker; use crate::tools::coverage::CoverageCollector; @@ -64,10 +68,13 @@ use deno_core::FeatureChecker; use deno_runtime::deno_fs; use deno_runtime::deno_node::DenoFsNodeResolverEnv; use deno_runtime::deno_node::NodeResolver; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; use deno_runtime::deno_web::BlobStore; use deno_runtime::inspector_server::InspectorServer; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use log::warn; use node_resolver::analyze::NodeCodeTranslator; use once_cell::sync::OnceCell; @@ -165,6 +172,7 @@ struct CliFactoryServices { http_client_provider: Deferred>, emit_cache: Deferred>, emitter: Deferred>, + esm_or_cjs_checker: Deferred>, fs: Deferred>, main_graph_container: Deferred>, maybe_inspector_server: Deferred>>, @@ -180,7 +188,9 @@ struct CliFactoryServices { node_code_translator: Deferred>, node_resolver: Deferred>, npm_resolver: Deferred>, - sloppy_imports_resolver: Deferred>>, + permission_desc_parser: Deferred>, + root_permissions_container: Deferred, + sloppy_imports_resolver: Deferred>>, text_only_progress_bar: Deferred, type_checker: Deferred>, cjs_resolutions: Deferred>, @@ -290,10 +300,16 @@ impl CliFactory { .get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly)) } + pub fn esm_or_cjs_checker(&self) -> &Arc { + self.services.esm_or_cjs_checker.get_or_init(|| { + Arc::new(EsmOrCjsChecker::new(self.parsed_source_cache().clone())) + }) + } + pub fn global_http_cache(&self) -> Result<&Arc, AnyError> { self.services.global_http_cache.get_or_try_init(|| { Ok(Arc::new(GlobalHttpCache::new( - self.deno_dir()?.deps_folder_path(), + self.deno_dir()?.remote_folder_path(), crate::cache::RealDenoCacheEnv, ))) }) @@ -304,8 +320,11 @@ impl CliFactory { let global_cache = self.global_http_cache()?.clone(); match self.cli_options()?.vendor_dir_path() { Some(local_path) => { - let local_cache = - LocalHttpCache::new(local_path.clone(), global_cache); + let local_cache = LocalHttpCache::new( + local_path.clone(), + global_cache, + deno_cache_dir::GlobalToLocalCopy::Allow, + ); Ok(Arc::new(local_cache)) } None => Ok(global_cache), @@ -351,8 +370,8 @@ impl CliFactory { let cli_options = self.cli_options()?; // For `deno install` we want to force the managed resolver so it can set up `node_modules/` directory. create_cli_npm_resolver(if cli_options.use_byonm() && !matches!(cli_options.sub_command(), DenoSubcommand::Install(_) | DenoSubcommand::Add(_) | DenoSubcommand::Remove(_)) { - CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions { - fs: fs.clone(), + CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions { + fs: CliDenoResolverFs(fs.clone()), root_node_modules_dir: Some(match cli_options.node_modules_dir_path() { Some(node_modules_path) => node_modules_path.to_path_buf(), // path needs to be canonicalized for node resolution @@ -383,9 +402,7 @@ impl CliFactory { cache_setting: cli_options.cache_setting(), text_only_progress_bar: self.text_only_progress_bar().clone(), maybe_node_modules_path: cli_options.node_modules_dir_path().cloned(), - package_json_deps_provider: Arc::new(PackageJsonInstallDepsProvider::from_workspace( - cli_options.workspace(), - )), + npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::from_workspace(cli_options.workspace())), npm_system_info: cli_options.npm_system_info(), npmrc: cli_options.npmrc().clone(), lifecycle_scripts: cli_options.lifecycle_scripts_config(), @@ -397,17 +414,16 @@ impl CliFactory { pub fn sloppy_imports_resolver( &self, - ) -> Result>, AnyError> { + ) -> Result>, AnyError> { self .services .sloppy_imports_resolver .get_or_try_init(|| { - Ok( - self - .cli_options()? - .unstable_sloppy_imports() - .then(|| Arc::new(SloppyImportsResolver::new(self.fs().clone()))), - ) + Ok(self.cli_options()?.unstable_sloppy_imports().then(|| { + Arc::new(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( + self.fs().clone(), + ))) + })) }) .map(|maybe| maybe.as_ref()) } @@ -519,9 +535,7 @@ impl CliFactory { let cli_options = self.cli_options()?; let ts_config_result = cli_options.resolve_ts_config_for_emit(TsConfigType::Emit)?; - if let Some(ignored_options) = ts_config_result.maybe_ignored_options { - warn!("{}", ignored_options); - } + check_warn_tsconfig(&ts_config_result); let (transpile_options, emit_options) = crate::args::ts_config_to_transpile_and_emit_options( ts_config_result.ts_config, @@ -568,8 +582,13 @@ impl CliFactory { let caches = self.caches()?; let node_analysis_cache = NodeAnalysisCache::new(caches.node_analysis_db()); - let cjs_esm_analyzer = - CliCjsCodeAnalyzer::new(node_analysis_cache, self.fs().clone()); + let node_resolver = self.cli_node_resolver().await?.clone(); + let cjs_esm_analyzer = CliCjsCodeAnalyzer::new( + node_analysis_cache, + self.fs().clone(), + node_resolver, + Some(self.parsed_source_cache().clone()), + ); Ok(Arc::new(NodeCodeTranslator::new( cjs_esm_analyzer, @@ -609,16 +628,18 @@ impl CliFactory { Ok(Arc::new(ModuleGraphBuilder::new( cli_options.clone(), self.caches()?.clone(), + self.esm_or_cjs_checker().clone(), self.fs().clone(), self.resolver().await?.clone(), + self.cli_node_resolver().await?.clone(), self.npm_resolver().await?.clone(), self.module_info_cache()?.clone(), self.parsed_source_cache().clone(), cli_options.maybe_lockfile().cloned(), self.maybe_file_watcher_reporter().clone(), - self.emit_cache()?.clone(), self.file_fetcher()?.clone(), self.global_http_cache()?.clone(), + self.root_permissions_container()?.clone(), ))) }) .await @@ -652,6 +673,7 @@ impl CliFactory { Ok(Arc::new(MainModuleGraphContainer::new( self.cli_options()?.clone(), self.module_load_preparer().await?.clone(), + self.root_permissions_container()?.clone(), ))) }) .await @@ -709,20 +731,24 @@ impl CliFactory { .await } + pub fn permission_desc_parser( + &self, + ) -> Result<&Arc, AnyError> { + self.services.permission_desc_parser.get_or_try_init(|| { + let fs = self.fs().clone(); + Ok(Arc::new(RuntimePermissionDescriptorParser::new(fs))) + }) + } + pub fn feature_checker(&self) -> Result<&Arc, AnyError> { self.services.feature_checker.get_or_try_init(|| { let cli_options = self.cli_options()?; let mut checker = FeatureChecker::default(); checker.set_exit_cb(Box::new(crate::unstable_exit_cb)); - checker.set_warn_cb(Box::new(crate::unstable_warn_cb)); - if cli_options.legacy_unstable_flag() { - checker.enable_legacy_unstable(); - checker.warn_on_legacy_unstable(); - } let unstable_features = cli_options.unstable_features(); - for (flag_name, _, _) in crate::UNSTABLE_GRANULAR_FLAGS { - if unstable_features.contains(&flag_name.to_string()) { - checker.enable_feature(flag_name); + for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS { + if unstable_features.contains(&granular_flag.name.to_string()) { + checker.enable_feature(granular_flag.name); } } @@ -736,6 +762,7 @@ impl CliFactory { let cli_options = self.cli_options()?; Ok(DenoCompileBinaryWriter::new( self.deno_dir()?, + self.emitter()?, self.file_fetcher()?, self.http_client_provider(), self.npm_resolver().await?.as_ref(), @@ -744,6 +771,22 @@ impl CliFactory { )) } + pub fn root_permissions_container( + &self, + ) -> Result<&PermissionsContainer, AnyError> { + self + .services + .root_permissions_container + .get_or_try_init(|| { + let desc_parser = self.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + desc_parser.as_ref(), + &self.cli_options()?.permissions_options(), + )?; + Ok(PermissionsContainer::new(desc_parser, permissions)) + }) + } + pub async fn create_cli_main_worker_factory( &self, ) -> Result { @@ -752,6 +795,7 @@ impl CliFactory { let npm_resolver = self.npm_resolver().await?; let fs = self.fs(); let cli_node_resolver = self.cli_node_resolver().await?; + let cli_npm_resolver = self.npm_resolver().await?.clone(); let maybe_file_watcher_communicator = if cli_options.has_hmr() { Some(self.watcher_communicator.clone().unwrap()) } else { @@ -759,11 +803,18 @@ impl CliFactory { }; Ok(CliMainWorkerFactory::new( - StorageKeyResolver::from_options(cli_options), - cli_options.sub_command().clone(), - npm_resolver.clone(), - node_resolver.clone(), self.blob_store().clone(), + self.cjs_resolutions().clone(), + if cli_options.code_cache_enabled() { + Some(self.code_cache()?.clone()) + } else { + None + }, + self.feature_checker()?.clone(), + self.fs().clone(), + maybe_file_watcher_communicator, + self.maybe_inspector_server()?.clone(), + cli_options.maybe_lockfile().cloned(), Box::new(CliModuleLoaderFactory::new( cli_options, if cli_options.code_cache_enabled() { @@ -775,6 +826,7 @@ impl CliFactory { self.main_module_graph_container().await?.clone(), self.module_load_preparer().await?.clone(), cli_node_resolver.clone(), + cli_npm_resolver.clone(), NpmModuleLoader::new( self.cjs_resolutions().clone(), self.node_code_translator().await?.clone(), @@ -784,26 +836,13 @@ impl CliFactory { self.parsed_source_cache().clone(), self.resolver().await?.clone(), )), + node_resolver.clone(), + npm_resolver.clone(), self.root_cert_store_provider().clone(), - self.fs().clone(), - maybe_file_watcher_communicator, - self.maybe_inspector_server()?.clone(), - cli_options.maybe_lockfile().cloned(), - self.feature_checker()?.clone(), + self.root_permissions_container()?.clone(), + StorageKeyResolver::from_options(cli_options), + cli_options.sub_command().clone(), self.create_cli_main_worker_options()?, - cli_options.node_ipc_fd(), - cli_options.serve_port(), - cli_options.serve_host(), - cli_options.enable_future_features(), - // TODO(bartlomieju): temporarily disabled - // cli_options.disable_deprecated_api_warning, - true, - cli_options.verbose_deprecated_api_warning, - if cli_options.code_cache_enabled() { - Some(self.code_cache()?.clone()) - } else { - None - }, )) } @@ -865,9 +904,12 @@ impl CliFactory { unsafely_ignore_certificate_errors: cli_options .unsafely_ignore_certificate_errors() .clone(), - unstable: cli_options.legacy_unstable_flag(), create_hmr_runner, create_coverage_collector, + node_ipc: cli_options.node_ipc_fd(), + serve_port: cli_options.serve_port(), + serve_host: cli_options.serve_host(), + unstable_detect_cjs: cli_options.unstable_detect_cjs(), }) } } diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 19acf2e2b8..95d778f0bb 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -11,7 +11,6 @@ use crate::http_util::HttpClientProvider; use crate::util::progress_bar::ProgressBar; use deno_ast::MediaType; -use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::custom_error; use deno_core::error::generic_error; @@ -22,8 +21,10 @@ use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::source::LoaderChecksum; +use deno_path_util::url_to_file_path; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_web::BlobStore; +use http::header; use log::debug; use std::borrow::Cow; use std::collections::HashMap; @@ -52,6 +53,25 @@ pub enum FileOrRedirect { Redirect(ModuleSpecifier), } +impl FileOrRedirect { + fn from_deno_cache_entry( + specifier: &ModuleSpecifier, + cache_entry: deno_cache_dir::CacheEntry, + ) -> Result { + if let Some(redirect_to) = cache_entry.metadata.headers.get("location") { + let redirect = + deno_core::resolve_import(redirect_to, specifier.as_str())?; + Ok(FileOrRedirect::Redirect(redirect)) + } else { + Ok(FileOrRedirect::File(File { + specifier: specifier.clone(), + maybe_headers: Some(cache_entry.metadata.headers), + source: Arc::from(cache_entry.content), + })) + } + } +} + /// A structure representing a source file. #[derive(Debug, Clone, Eq, PartialEq)] pub struct File { @@ -117,14 +137,23 @@ impl MemoryFiles { /// Fetch a source file from the local file system. fn fetch_local(specifier: &ModuleSpecifier) -> Result { - let local = specifier.to_file_path().map_err(|_| { + let local = url_to_file_path(specifier).map_err(|_| { uri_error(format!("Invalid file path.\n Specifier: {specifier}")) })?; + // If it doesnt have a extension, we want to treat it as typescript by default + let headers = if local.extension().is_none() { + Some(HashMap::from([( + "content-type".to_string(), + "application/typescript".to_string(), + )])) + } else { + None + }; let bytes = fs::read(local)?; Ok(File { specifier: specifier.clone(), - maybe_headers: None, + maybe_headers: headers, source: bytes.into(), }) } @@ -143,9 +172,17 @@ fn get_validated_scheme( } } +#[derive(Debug, Copy, Clone)] +pub enum FetchPermissionsOptionRef<'a> { + AllowAll, + DynamicContainer(&'a PermissionsContainer), + StaticContainer(&'a PermissionsContainer), +} + pub struct FetchOptions<'a> { pub specifier: &'a ModuleSpecifier, - pub permissions: &'a PermissionsContainer, + pub permissions: FetchPermissionsOptionRef<'a>, + pub maybe_auth: Option<(header::HeaderName, header::HeaderValue)>, pub maybe_accept: Option<&'a str>, pub maybe_cache_setting: Option<&'a CacheSetting>, } @@ -238,45 +275,32 @@ impl FileFetcher { ); let cache_key = self.http_cache.cache_item_key(specifier)?; // compute this once - let Some(headers) = self.http_cache.read_headers(&cache_key)? else { - return Ok(None); - }; - if let Some(redirect_to) = headers.get("location") { - let redirect = - deno_core::resolve_import(redirect_to, specifier.as_str())?; - return Ok(Some(FileOrRedirect::Redirect(redirect))); - } - let result = self.http_cache.read_file_bytes( + let result = self.http_cache.get( &cache_key, maybe_checksum .as_ref() .map(|c| deno_cache_dir::Checksum::new(c.as_str())), - deno_cache_dir::GlobalToLocalCopy::Allow, ); - let bytes = match result { - Ok(Some(bytes)) => bytes, - Ok(None) => return Ok(None), + match result { + Ok(Some(cache_data)) => Ok(Some(FileOrRedirect::from_deno_cache_entry( + specifier, cache_data, + )?)), + Ok(None) => Ok(None), Err(err) => match err { - deno_cache_dir::CacheReadFileError::Io(err) => return Err(err.into()), + deno_cache_dir::CacheReadFileError::Io(err) => Err(err.into()), deno_cache_dir::CacheReadFileError::ChecksumIntegrity(err) => { // convert to the equivalent deno_graph error so that it // enhances it if this is passed to deno_graph - return Err( + Err( deno_graph::source::ChecksumIntegrityError { actual: err.actual, expected: err.expected, } .into(), - ); + ) } }, - }; - - Ok(Some(FileOrRedirect::File(File { - specifier: specifier.clone(), - maybe_headers: Some(headers), - source: Arc::from(bytes), - }))) + } } /// Convert a data URL into a file, resulting in an error if the URL is @@ -311,7 +335,7 @@ impl FileFetcher { ) })?; - let bytes = blob.read_all().await?; + let bytes = blob.read_all().await; let headers = HashMap::from([("content-type".to_string(), blob.media_type.clone())]); @@ -328,6 +352,7 @@ impl FileFetcher { maybe_accept: Option<&str>, cache_setting: &CacheSetting, maybe_checksum: Option<&LoaderChecksum>, + maybe_auth: Option<(header::HeaderName, header::HeaderValue)>, ) -> Result { debug!( "FileFetcher::fetch_remote_no_follow - specifier: {}", @@ -363,12 +388,30 @@ impl FileFetcher { ); } - let maybe_etag = self + let maybe_etag_cache_entry = self .http_cache .cache_item_key(specifier) .ok() - .and_then(|key| self.http_cache.read_headers(&key).ok().flatten()) - .and_then(|headers| headers.get("etag").cloned()); + .and_then(|key| { + self + .http_cache + .get( + &key, + maybe_checksum + .as_ref() + .map(|c| deno_cache_dir::Checksum::new(c.as_str())), + ) + .ok() + .flatten() + }) + .and_then(|cache_entry| { + cache_entry + .metadata + .headers + .get("etag") + .cloned() + .map(|etag| (cache_entry, etag)) + }); let maybe_auth_token = self.auth_tokens.get(specifier); async fn handle_request_or_server_error( @@ -390,7 +433,6 @@ impl FileFetcher { } } - let mut maybe_etag = maybe_etag; let mut retried = false; // retry intermittent failures let result = loop { let result = match self @@ -399,31 +441,18 @@ impl FileFetcher { .fetch_no_follow(FetchOnceArgs { url: specifier.clone(), maybe_accept: maybe_accept.map(ToOwned::to_owned), - maybe_etag: maybe_etag.clone(), + maybe_etag: maybe_etag_cache_entry + .as_ref() + .map(|(_, etag)| etag.clone()), maybe_auth_token: maybe_auth_token.clone(), + maybe_auth: maybe_auth.clone(), maybe_progress_guard: maybe_progress_guard.as_ref(), }) .await? { FetchOnceResult::NotModified => { - let file_or_redirect = - self.fetch_cached_no_follow(specifier, maybe_checksum)?; - match file_or_redirect { - Some(file_or_redirect) => Ok(file_or_redirect), - None => { - // Someone may have deleted the body from the cache since - // it's currently stored in a separate file from the headers, - // so delete the etag and try again - if maybe_etag.is_some() { - debug!("Cache body not found. Trying again without etag."); - maybe_etag = None; - continue; - } else { - // should never happen - bail!("Your deno cache directory is in an unrecoverable state. Please delete it and try again.") - } - } - } + let (cache_entry, _) = maybe_etag_cache_entry.unwrap(); + FileOrRedirect::from_deno_cache_entry(specifier, cache_entry) } FetchOnceResult::Redirect(redirect_url, headers) => { self.http_cache.set(specifier, headers, &[])?; @@ -507,16 +536,54 @@ impl FileFetcher { } } + #[inline(always)] + pub async fn fetch_bypass_permissions( + &self, + specifier: &ModuleSpecifier, + ) -> Result { + self + .fetch_inner(specifier, None, FetchPermissionsOptionRef::AllowAll) + .await + } + + #[inline(always)] + pub async fn fetch_bypass_permissions_with_maybe_auth( + &self, + specifier: &ModuleSpecifier, + maybe_auth: Option<(header::HeaderName, header::HeaderValue)>, + ) -> Result { + self + .fetch_inner(specifier, maybe_auth, FetchPermissionsOptionRef::AllowAll) + .await + } + /// Fetch a source file and asynchronously return it. + #[inline(always)] pub async fn fetch( &self, specifier: &ModuleSpecifier, permissions: &PermissionsContainer, + ) -> Result { + self + .fetch_inner( + specifier, + None, + FetchPermissionsOptionRef::StaticContainer(permissions), + ) + .await + } + + async fn fetch_inner( + &self, + specifier: &ModuleSpecifier, + maybe_auth: Option<(header::HeaderName, header::HeaderValue)>, + permissions: FetchPermissionsOptionRef<'_>, ) -> Result { self .fetch_with_options(FetchOptions { specifier, permissions, + maybe_auth, maybe_accept: None, maybe_cache_setting: None, }) @@ -536,12 +603,14 @@ impl FileFetcher { max_redirect: usize, ) -> Result { let mut specifier = Cow::Borrowed(options.specifier); + let mut maybe_auth = options.maybe_auth.clone(); for _ in 0..=max_redirect { match self .fetch_no_follow_with_options(FetchNoFollowOptions { fetch_options: FetchOptions { specifier: &specifier, permissions: options.permissions, + maybe_auth: maybe_auth.clone(), maybe_accept: options.maybe_accept, maybe_cache_setting: options.maybe_cache_setting, }, @@ -553,6 +622,10 @@ impl FileFetcher { return Ok(file); } FileOrRedirect::Redirect(redirect_specifier) => { + // If we were redirected to another origin, don't send the auth header anymore. + if redirect_specifier.origin() != specifier.origin() { + maybe_auth = None; + } specifier = Cow::Owned(redirect_specifier); } } @@ -575,7 +648,23 @@ impl FileFetcher { specifier ); let scheme = get_validated_scheme(specifier)?; - options.permissions.check_specifier(specifier)?; + match options.permissions { + FetchPermissionsOptionRef::AllowAll => { + // allow + } + FetchPermissionsOptionRef::StaticContainer(permissions) => { + permissions.check_specifier( + specifier, + deno_runtime::deno_permissions::CheckSpecifierKind::Static, + )?; + } + FetchPermissionsOptionRef::DynamicContainer(permissions) => { + permissions.check_specifier( + specifier, + deno_runtime::deno_permissions::CheckSpecifierKind::Dynamic, + )?; + } + } if let Some(file) = self.memory_files.get(specifier) { Ok(FileOrRedirect::File(file)) } else if scheme == "file" { @@ -601,6 +690,7 @@ impl FileFetcher { options.maybe_accept, options.maybe_cache_setting.unwrap_or(&self.cache_setting), maybe_checksum, + options.maybe_auth, ) .await } @@ -661,7 +751,7 @@ mod tests { maybe_temp_dir: Option, ) -> (FileFetcher, TempDir, Arc) { let temp_dir = maybe_temp_dir.unwrap_or_default(); - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let blob_store: Arc = Default::default(); let file_fetcher = FileFetcher::new( Arc::new(GlobalHttpCache::new(location, RealDenoCacheEnv)), @@ -676,9 +766,7 @@ mod tests { async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) { let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None); - let result = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(specifier).await; assert!(result.is_ok()); (result.unwrap(), file_fetcher) } @@ -692,7 +780,8 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, + maybe_auth: None, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -788,9 +877,7 @@ mod tests { }; file_fetcher.insert_memory_files(file.clone()); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let result_file = result.unwrap(); assert_eq!(result_file, file); @@ -801,9 +888,7 @@ mod tests { let (file_fetcher, _) = setup(CacheSetting::Use, None); let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -832,9 +917,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -854,9 +937,7 @@ mod tests { let specifier = ModuleSpecifier::parse("http://localhost:4545/subdir/mod2.ts").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -874,9 +955,7 @@ mod tests { .set(&specifier, headers.clone(), file.source.as_bytes()) .unwrap(); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -900,9 +979,7 @@ mod tests { .set(&specifier, headers.clone(), file.source.as_bytes()) .unwrap(); - let result = file_fetcher_02 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -913,7 +990,7 @@ mod tests { // This creates a totally new instance, simulating another Deno process // invocation and indicates to "cache bust". - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let file_fetcher = FileFetcher::new( Arc::new(GlobalHttpCache::new( location, @@ -925,9 +1002,7 @@ mod tests { Default::default(), None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -941,7 +1016,7 @@ mod tests { async fn test_fetch_uses_cache() { let _http_server_guard = test_util::http_server(); let temp_dir = TempDir::new(); - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let specifier = resolve_url("http://localhost:4545/subdir/mismatch_ext.ts").unwrap(); @@ -958,9 +1033,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = file_fetcher.http_cache.cache_item_key(&specifier).unwrap(); @@ -994,9 +1067,7 @@ mod tests { Default::default(), None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = @@ -1033,9 +1104,7 @@ mod tests { resolve_url("http://localhost:4545/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_specifier); @@ -1074,9 +1143,7 @@ mod tests { resolve_url("http://localhost:4545/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_02_specifier); @@ -1115,7 +1182,7 @@ mod tests { async fn test_fetch_uses_cache_with_redirects() { let _http_server_guard = test_util::http_server(); let temp_dir = TempDir::new(); - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let specifier = resolve_url("http://localhost:4548/subdir/mismatch_ext.ts").unwrap(); let redirected_specifier = @@ -1134,9 +1201,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = file_fetcher @@ -1174,7 +1239,7 @@ mod tests { None, ); let result = file_fetcher - .fetch(&redirected_specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&redirected_specifier) .await; assert!(result.is_ok()); @@ -1215,7 +1280,8 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, + maybe_auth: None, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -1228,7 +1294,8 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, + maybe_auth: None, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -1256,9 +1323,7 @@ mod tests { resolve_url("http://localhost:4550/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_specifier); @@ -1287,7 +1352,7 @@ mod tests { async fn test_fetch_no_remote() { let _http_server_guard = test_util::http_server(); let temp_dir = TempDir::new(); - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let file_fetcher = FileFetcher::new( Arc::new(GlobalHttpCache::new( location, @@ -1302,9 +1367,7 @@ mod tests { let specifier = resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_err()); let err = result.unwrap_err(); assert_eq!(get_custom_error_class(&err), Some("NoRemote")); @@ -1315,7 +1378,7 @@ mod tests { async fn test_fetch_cache_only() { let _http_server_guard = test_util::http_server(); let temp_dir = TempDir::new(); - let location = temp_dir.path().join("deps").to_path_buf(); + let location = temp_dir.path().join("remote").to_path_buf(); let file_fetcher_01 = FileFetcher::new( Arc::new(GlobalHttpCache::new(location.clone(), RealDenoCacheEnv)), CacheSetting::Only, @@ -1335,22 +1398,16 @@ mod tests { let specifier = resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_err()); let err = result.unwrap_err(); assert_eq!(err.to_string(), "Specifier not found in cache: \"http://localhost:4545/run/002_hello.ts\", --cached-only is specified."); assert_eq!(get_custom_error_class(&err), Some("NotCached")); - let result = file_fetcher_02 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); } @@ -1360,17 +1417,13 @@ mod tests { let fixture_path = temp_dir.path().join("mod.ts"); let specifier = ModuleSpecifier::from_file_path(&fixture_path).unwrap(); fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!(&*file.source, r#"console.log("hello deno");"#); fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!(&*file.source, r#"console.log("goodbye deno");"#); @@ -1384,18 +1437,14 @@ mod tests { setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let first = file.source; let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let second = file.source; @@ -1411,18 +1460,14 @@ mod tests { setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let first = file.source; let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let second = file.source; @@ -1480,13 +1525,10 @@ mod tests { let cache_key = file_fetcher.http_cache.cache_item_key(url).unwrap(); let bytes = file_fetcher .http_cache - .read_file_bytes( - &cache_key, - None, - deno_cache_dir::GlobalToLocalCopy::Allow, - ) + .get(&cache_key, None) .unwrap() - .unwrap(); + .unwrap() + .content; String::from_utf8(bytes).unwrap() } diff --git a/cli/graph_container.rs b/cli/graph_container.rs index cf913464fd..c463d71a6a 100644 --- a/cli/graph_container.rs +++ b/cli/graph_container.rs @@ -3,15 +3,18 @@ use std::sync::Arc; use deno_ast::ModuleSpecifier; +use deno_config::glob::FilePatterns; +use deno_config::glob::PathOrPatternSet; use deno_core::error::AnyError; use deno_core::parking_lot::RwLock; -use deno_core::resolve_url_or_path; use deno_graph::ModuleGraph; use deno_runtime::colors; use deno_runtime::deno_permissions::PermissionsContainer; use crate::args::CliOptions; use crate::module_loader::ModuleLoadPreparer; +use crate::util::fs::collect_specifiers; +use crate::util::path::is_script_ext; pub trait ModuleGraphContainer: Clone + 'static { /// Acquires a permit to modify the module graph without other code @@ -42,12 +45,14 @@ pub struct MainModuleGraphContainer { inner: Arc>>, cli_options: Arc, module_load_preparer: Arc, + root_permissions: PermissionsContainer, } impl MainModuleGraphContainer { pub fn new( cli_options: Arc, module_load_preparer: Arc, + root_permissions: PermissionsContainer, ) -> Self { Self { update_queue: Default::default(), @@ -56,12 +61,14 @@ impl MainModuleGraphContainer { )))), cli_options, module_load_preparer, + root_permissions, } } pub async fn check_specifiers( &self, specifiers: &[ModuleSpecifier], + ext_overwrite: Option<&String>, ) -> Result<(), AnyError> { let mut graph_permit = self.acquire_update_permit().await; let graph = graph_permit.graph_mut(); @@ -72,7 +79,8 @@ impl MainModuleGraphContainer { specifiers, false, self.cli_options.ts_type_lib_window(), - PermissionsContainer::allow_all(), + self.root_permissions.clone(), + ext_overwrite, ) .await?; graph_permit.commit(); @@ -91,7 +99,7 @@ impl MainModuleGraphContainer { log::warn!("{} No matching files found.", colors::yellow("Warning")); } - self.check_specifiers(&specifiers).await + self.check_specifiers(&specifiers, None).await } pub fn collect_specifiers( @@ -99,24 +107,20 @@ impl MainModuleGraphContainer { files: &[String], ) -> Result, AnyError> { let excludes = self.cli_options.workspace().resolve_config_excludes()?; - Ok( - files - .iter() - .filter_map(|file| { - let file_url = - resolve_url_or_path(file, self.cli_options.initial_cwd()).ok()?; - if file_url.scheme() != "file" { - return Some(file_url); - } - // ignore local files that match any of files listed in `exclude` option - let file_path = file_url.to_file_path().ok()?; - if excludes.matches_path(&file_path) { - None - } else { - Some(file_url) - } - }) - .collect::>(), + let include_patterns = + PathOrPatternSet::from_include_relative_path_or_patterns( + self.cli_options.initial_cwd(), + files, + )?; + let file_patterns = FilePatterns { + base: self.cli_options.initial_cwd().to_path_buf(), + include: Some(include_patterns), + exclude: excludes, + }; + collect_specifiers( + file_patterns, + self.cli_options.vendor_dir_path().map(ToOwned::to_owned), + |e| is_script_ext(e.path), ) } } diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 647307bd91..e67ae7821b 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -6,6 +6,7 @@ use crate::args::CliLockfile; use crate::args::CliOptions; use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS; use crate::cache; +use crate::cache::EsmOrCjsChecker; use crate::cache::GlobalHttpCache; use crate::cache::ModuleInfoCache; use crate::cache::ParsedSourceCache; @@ -14,51 +15,55 @@ use crate::errors::get_error_class_name; use crate::file_fetcher::FileFetcher; use crate::npm::CliNpmResolver; use crate::resolver::CliGraphResolver; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliNodeResolver; +use crate::resolver::CliSloppyImportsResolver; +use crate::resolver::SloppyImportsCachedFs; use crate::tools::check; use crate::tools::check::TypeChecker; use crate::util::file_watcher::WatcherCommunicator; use crate::util::fs::canonicalize_path; use deno_config::workspace::JsrPackageConfig; -use deno_emit::LoaderChecksum; +use deno_core::anyhow::bail; +use deno_graph::source::LoaderChecksum; +use deno_graph::FillFromLockfileOptions; use deno_graph::JsrLoadError; use deno_graph::ModuleLoadError; use deno_graph::WorkspaceFastCheckOption; -use deno_runtime::fs_util::specifier_to_file_path; -use deno_core::anyhow::bail; use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::ModuleSpecifier; use deno_graph::source::Loader; -use deno_graph::source::ResolutionMode; use deno_graph::source::ResolveError; use deno_graph::GraphKind; -use deno_graph::Module; use deno_graph::ModuleError; use deno_graph::ModuleGraph; use deno_graph::ModuleGraphError; use deno_graph::ResolutionError; use deno_graph::SpecifierError; +use deno_path_util::url_to_file_path; +use deno_resolver::sloppy_imports::SloppyImportsResolutionMode; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node; use deno_runtime::deno_permissions::PermissionsContainer; +use deno_semver::jsr::JsrDepPackageReq; use deno_semver::package::PackageNv; -use deno_semver::package::PackageReq; use import_map::ImportMapError; use std::collections::HashSet; +use std::error::Error; +use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct GraphValidOptions { pub check_js: bool, - pub follow_type_only: bool, - pub is_vendoring: bool, - /// Whether to exit the process for lockfile errors. - /// Otherwise, surfaces lockfile errors as errors. - pub exit_lockfile_errors: bool, + pub kind: GraphKind, + /// Whether to exit the process for integrity check errors such as + /// lockfile checksum mismatches and JSR integrity failures. + /// Otherwise, surfaces integrity errors as errors. + pub exit_integrity_errors: bool, } /// Check if `roots` and their deps are available. Returns `Ok(())` if @@ -74,17 +79,54 @@ pub fn graph_valid( roots: &[ModuleSpecifier], options: GraphValidOptions, ) -> Result<(), AnyError> { - if options.exit_lockfile_errors { - graph_exit_lock_errors(graph); + if options.exit_integrity_errors { + graph_exit_integrity_errors(graph); } - let mut errors = graph + let mut errors = graph_walk_errors( + graph, + fs, + roots, + GraphWalkErrorsOptions { + check_js: options.check_js, + kind: options.kind, + }, + ); + if let Some(error) = errors.next() { + Err(error) + } else { + // finally surface the npm resolution result + if let Err(err) = &graph.npm_dep_graph_result { + return Err(custom_error( + get_error_class_name(err), + format_deno_graph_error(err.as_ref().deref()), + )); + } + Ok(()) + } +} + +#[derive(Clone)] +pub struct GraphWalkErrorsOptions { + pub check_js: bool, + pub kind: GraphKind, +} + +/// Walks the errors found in the module graph that should be surfaced to users +/// and enhances them with CLI information. +pub fn graph_walk_errors<'a>( + graph: &'a ModuleGraph, + fs: &'a Arc, + roots: &'a [ModuleSpecifier], + options: GraphWalkErrorsOptions, +) -> impl Iterator + 'a { + graph .walk( roots.iter(), deno_graph::WalkOptions { check_js: options.check_js, - follow_type_only: options.follow_type_only, - follow_dynamic: options.is_vendoring, + kind: options.kind, + follow_dynamic: false, prefer_fast_check_graph: false, }, ) @@ -108,9 +150,9 @@ pub fn graph_valid( ) } ModuleGraphError::ModuleError(error) => { - enhanced_lockfile_error_message(error) + enhanced_integrity_error_message(error) .or_else(|| enhanced_sloppy_imports_error_message(fs, error)) - .unwrap_or_else(|| format!("{}", error)) + .unwrap_or_else(|| format_deno_graph_error(error)) } }; @@ -131,53 +173,18 @@ pub fn graph_valid( return None; } - if options.is_vendoring { - // warn about failing dynamic imports when vendoring, but don't fail completely - if matches!( - error, - ModuleGraphError::ModuleError(ModuleError::MissingDynamic(_, _)) - ) { - log::warn!("Ignoring: {}", message); - return None; - } - - // ignore invalid downgrades and invalid local imports when vendoring - match &error { - ModuleGraphError::ResolutionError(err) - | ModuleGraphError::TypesResolutionError(err) => { - if matches!( - err, - ResolutionError::InvalidDowngrade { .. } - | ResolutionError::InvalidLocalImport { .. } - ) { - return None; - } - } - ModuleGraphError::ModuleError(_) => {} - } - } - Some(custom_error(get_error_class_name(&error.into()), message)) - }); - if let Some(error) = errors.next() { - Err(error) - } else { - // finally surface the npm resolution result - if let Err(err) = &graph.npm_dep_graph_result { - return Err(custom_error(get_error_class_name(err), format!("{}", err))); - } - Ok(()) - } + }) } -pub fn graph_exit_lock_errors(graph: &ModuleGraph) { +pub fn graph_exit_integrity_errors(graph: &ModuleGraph) { for error in graph.module_errors() { - exit_for_lockfile_error(error); + exit_for_integrity_error(error); } } -fn exit_for_lockfile_error(err: &ModuleError) { - if let Some(err_message) = enhanced_lockfile_error_message(err) { +fn exit_for_integrity_error(err: &ModuleError) { + if let Some(err_message) = enhanced_integrity_error_message(err) { log::error!("{} {}", colors::red("error:"), err_message); std::process::exit(10); } @@ -245,6 +252,19 @@ impl ModuleGraphCreator { package_configs: &[JsrPackageConfig], build_fast_check_graph: bool, ) -> Result { + fn graph_has_external_remote(graph: &ModuleGraph) -> bool { + // Earlier on, we marked external non-JSR modules as external. + // If the graph contains any of those, it would cause type checking + // to crash, so since publishing is going to fail anyway, skip type + // checking. + graph.modules().any(|module| match module { + deno_graph::Module::External(external_module) => { + matches!(external_module.specifier.scheme(), "http" | "https") + } + _ => false, + }) + } + let mut roots = Vec::new(); for package_config in package_configs { roots.extend(package_config.config_file.resolve_export_value_urls()?); @@ -258,9 +278,12 @@ impl ModuleGraphCreator { }) .await?; self.graph_valid(&graph)?; - if self.options.type_check_mode().is_true() { + if self.options.type_check_mode().is_true() + && !graph_has_external_remote(&graph) + { self.type_check_graph(graph.clone()).await?; } + if build_fast_check_graph { let fast_check_workspace_members = package_configs .iter() @@ -275,6 +298,7 @@ impl ModuleGraphCreator { }, )?; } + Ok(graph) } @@ -357,16 +381,18 @@ pub struct BuildFastCheckGraphOptions<'a> { pub struct ModuleGraphBuilder { options: Arc, caches: Arc, + esm_or_cjs_checker: Arc, fs: Arc, resolver: Arc, + node_resolver: Arc, npm_resolver: Arc, module_info_cache: Arc, parsed_source_cache: Arc, lockfile: Option>, maybe_file_watcher_reporter: Option, - emit_cache: Arc, file_fetcher: Arc, global_http_cache: Arc, + root_permissions_container: PermissionsContainer, } impl ModuleGraphBuilder { @@ -374,30 +400,34 @@ impl ModuleGraphBuilder { pub fn new( options: Arc, caches: Arc, + esm_or_cjs_checker: Arc, fs: Arc, resolver: Arc, + node_resolver: Arc, npm_resolver: Arc, module_info_cache: Arc, parsed_source_cache: Arc, lockfile: Option>, maybe_file_watcher_reporter: Option, - emit_cache: Arc, file_fetcher: Arc, global_http_cache: Arc, + root_permissions_container: PermissionsContainer, ) -> Self { Self { options, caches, + esm_or_cjs_checker, fs, resolver, + node_resolver, npm_resolver, module_info_cache, parsed_source_cache, lockfile, maybe_file_watcher_reporter, - emit_cache, file_fetcher, global_http_cache, + root_permissions_container, } } @@ -463,7 +493,7 @@ impl ModuleGraphBuilder { .content .packages .jsr - .get(&package_nv.to_string()) + .get(package_nv) .map(|s| LoaderChecksum::new(s.integrity.clone())) } @@ -477,7 +507,7 @@ impl ModuleGraphBuilder { self .0 .lock() - .insert_package(package_nv.to_string(), checksum.into_string()); + .insert_package(package_nv.clone(), checksum.into_string()); } } @@ -535,7 +565,12 @@ impl ModuleGraphBuilder { ) -> Result<(), AnyError> { // ensure an "npm install" is done if the user has explicitly // opted into using a node_modules directory - if self.options.node_modules_dir_enablement() == Some(true) { + if self + .options + .node_modules_dir()? + .map(|m| m.uses_node_modules_dir()) + .unwrap_or(false) + { if let Some(npm_resolver) = self.npm_resolver.as_managed() { npm_resolver.ensure_top_level_package_json_install().await?; } @@ -547,28 +582,19 @@ impl ModuleGraphBuilder { // populate the information from the lockfile if let Some(lockfile) = &self.lockfile { let lockfile = lockfile.lock(); - for (from, to) in &lockfile.content.redirects { - if let Ok(from) = ModuleSpecifier::parse(from) { - if let Ok(to) = ModuleSpecifier::parse(to) { - if !matches!(from.scheme(), "file" | "npm" | "jsr") { - graph.redirects.insert(from, to); - } - } - } - } - for (key, value) in &lockfile.content.packages.specifiers { - if let Some(key) = key - .strip_prefix("jsr:") - .and_then(|key| PackageReq::from_str(key).ok()) - { - if let Some(value) = value - .strip_prefix("jsr:") - .and_then(|value| PackageNv::from_str(value).ok()) - { - graph.packages.add_nv(key, value); - } - } - } + graph.fill_from_lockfile(FillFromLockfileOptions { + redirects: lockfile + .content + .redirects + .iter() + .map(|(from, to)| (from.as_str(), to.as_str())), + package_specifiers: lockfile + .content + .packages + .specifiers + .iter() + .map(|(dep, id)| (dep, id.as_str())), + }); } } @@ -576,6 +602,12 @@ impl ModuleGraphBuilder { let initial_package_deps_len = graph.packages.package_deps_sum(); let initial_package_mappings_len = graph.packages.mappings().len(); + if roots.iter().any(|r| r.scheme() == "npm") + && self.npm_resolver.as_byonm().is_some() + { + bail!("Resolving npm specifier entrypoints this way is currently not supported with \"nodeModules\": \"manual\". In the meantime, try with --node-modules-dir=auto instead"); + } + graph.build(roots, loader, options).await; let has_redirects_changed = graph.redirects.len() != initial_redirects_len; @@ -603,16 +635,15 @@ impl ModuleGraphBuilder { if has_jsr_package_mappings_changed { for (from, to) in graph.packages.mappings() { lockfile.insert_package_specifier( - format!("jsr:{}", from), - format!("jsr:{}", to), + JsrDepPackageReq::jsr(from.clone()), + to.version.to_string(), ); } } // jsr packages if has_jsr_package_deps_changed { - for (name, deps) in graph.packages.packages_with_deps() { - lockfile - .add_package_deps(&name.to_string(), deps.map(|s| s.to_string())); + for (nv, deps) in graph.packages.packages_with_deps() { + lockfile.add_package_deps(nv, deps.cloned()); } } } @@ -660,7 +691,7 @@ impl ModuleGraphBuilder { /// Creates the default loader used for creating a graph. pub fn create_graph_loader(&self) -> cache::FetchCacher { - self.create_fetch_cacher(PermissionsContainer::allow_all()) + self.create_fetch_cacher(self.root_permissions_container.clone()) } pub fn create_fetch_cacher( @@ -668,13 +699,21 @@ impl ModuleGraphBuilder { permissions: PermissionsContainer, ) -> cache::FetchCacher { cache::FetchCacher::new( - self.emit_cache.clone(), + self.esm_or_cjs_checker.clone(), self.file_fetcher.clone(), - self.options.resolve_file_header_overrides(), self.global_http_cache.clone(), + self.node_resolver.clone(), self.npm_resolver.clone(), self.module_info_cache.clone(), - permissions, + cache::FetchCacherOptions { + file_header_overrides: self.options.resolve_file_header_overrides(), + permissions, + is_deno_publish: matches!( + self.options.sub_command(), + crate::args::DenoSubcommand::Publish { .. } + ), + unstable_detect_cjs: self.options.unstable_detect_cjs(), + }, ) } @@ -698,42 +737,41 @@ impl ModuleGraphBuilder { &self.fs, roots, GraphValidOptions { - is_vendoring: false, - follow_type_only: self.options.type_check_mode().is_true(), + kind: if self.options.type_check_mode().is_true() { + GraphKind::All + } else { + GraphKind::CodeOnly + }, check_js: self.options.check_js(), - exit_lockfile_errors: true, + exit_integrity_errors: true, }, ) } } -pub fn error_for_any_npm_specifier( - graph: &ModuleGraph, -) -> Result<(), AnyError> { - for module in graph.modules() { - match module { - Module::Npm(module) => { - bail!("npm specifiers have not yet been implemented for this subcommand (https://github.com/denoland/deno/issues/15960). Found: {}", module.specifier) - } - Module::Node(module) => { - bail!("Node specifiers have not yet been implemented for this subcommand (https://github.com/denoland/deno/issues/15960). Found: node:{}", module.module_name) - } - Module::Js(_) | Module::Json(_) | Module::External(_) => {} - } - } - Ok(()) -} - /// Adds more explanatory information to a resolution error. pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String { - let mut message = format!("{error}"); + let mut message = format_deno_graph_error(error); - if let Some(specifier) = get_resolution_error_bare_node_specifier(error) { + let maybe_hint = if let Some(specifier) = + get_resolution_error_bare_node_specifier(error) + { if !*DENO_DISABLE_PEDANTIC_NODE_WARNINGS { - message.push_str(&format!( - "\nIf you want to use a built-in Node module, add a \"node:\" prefix (ex. \"node:{specifier}\")." - )); + Some(format!("If you want to use a built-in Node module, add a \"node:\" prefix (ex. \"node:{specifier}\").")) + } else { + None } + } else { + get_import_prefix_missing_error(error).map(|specifier| { + format!( + "If you want to use a JSR or npm package, try running `deno add jsr:{}` or `deno add npm:{}`", + specifier, specifier + ) + }) + }; + + if let Some(hint) = maybe_hint { + message.push_str(&format!("\n {} {}", colors::cyan("hint:"), hint)); } message @@ -746,8 +784,8 @@ fn enhanced_sloppy_imports_error_message( match error { ModuleError::LoadingErr(specifier, _, ModuleLoadError::Loader(_)) // ex. "Is a directory" error | ModuleError::Missing(specifier, _) => { - let additional_message = SloppyImportsResolver::new(fs.clone()) - .resolve(specifier, ResolutionMode::Execution)? + let additional_message = CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(fs.clone())) + .resolve(specifier, SloppyImportsResolutionMode::Execution)? .as_suggestion_message(); Some(format!( "{} {} or run with --unstable-sloppy-imports", @@ -759,7 +797,7 @@ fn enhanced_sloppy_imports_error_message( } } -fn enhanced_lockfile_error_message(err: &ModuleError) -> Option { +fn enhanced_integrity_error_message(err: &ModuleError) -> Option { match err { ModuleError::LoadingErr( specifier, @@ -803,7 +841,7 @@ fn enhanced_lockfile_error_message(err: &ModuleError) -> Option { "This could be caused by:\n", " * the lock file may be corrupt\n", " * the source itself may be corrupt\n\n", - "Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server." + "Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server." ), package_nv, checksum_err.actual, @@ -824,7 +862,7 @@ fn enhanced_lockfile_error_message(err: &ModuleError) -> Option { "This could be caused by:\n", " * the lock file may be corrupt\n", " * the source itself may be corrupt\n\n", - "Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server." + "Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server." ), specifier, checksum_err.actual, @@ -868,6 +906,50 @@ fn get_resolution_error_bare_specifier( } } +fn get_import_prefix_missing_error(error: &ResolutionError) -> Option<&str> { + let mut maybe_specifier = None; + if let ResolutionError::InvalidSpecifier { + error: SpecifierError::ImportPrefixMissing { specifier, .. }, + range, + } = error + { + if range.specifier.scheme() == "file" { + maybe_specifier = Some(specifier); + } + } else if let ResolutionError::ResolverError { error, range, .. } = error { + if range.specifier.scheme() == "file" { + match error.as_ref() { + ResolveError::Specifier(specifier_error) => { + if let SpecifierError::ImportPrefixMissing { specifier, .. } = + specifier_error + { + maybe_specifier = Some(specifier); + } + } + ResolveError::Other(other_error) => { + if let Some(SpecifierError::ImportPrefixMissing { + specifier, .. + }) = other_error.downcast_ref::() + { + maybe_specifier = Some(specifier); + } + } + } + } + } + + // NOTE(bartlomieju): For now, return None if a specifier contains a dot or a space. This is because + // suggesting to `deno add bad-module.ts` makes no sense and is worse than not providing + // a suggestion at all. This should be improved further in the future + if let Some(specifier) = maybe_specifier { + if specifier.contains('.') || specifier.contains(' ') { + return None; + } + } + + maybe_specifier.map(|s| s.as_str()) +} + /// Gets if any of the specified root's "file:" dependents are in the /// provided changed set. pub fn has_graph_root_local_dependent_changed( @@ -879,13 +961,13 @@ pub fn has_graph_root_local_dependent_changed( std::iter::once(root), deno_graph::WalkOptions { follow_dynamic: true, - follow_type_only: true, + kind: GraphKind::All, prefer_fast_check_graph: true, check_js: true, }, ); while let Some((s, _)) = dependent_specifiers.next() { - if let Ok(path) = specifier_to_file_path(s) { + if let Ok(path) = url_to_file_path(s) { if let Ok(path) = canonicalize_path(&path) { if canonicalized_changed_paths.contains(&path) { return true; @@ -1022,6 +1104,49 @@ impl deno_graph::source::JsrUrlProvider for CliJsrUrlProvider { } } +// todo(dsherret): We should change ModuleError to use thiserror so that +// we don't need to do this. +fn format_deno_graph_error(err: &dyn Error) -> String { + use std::fmt::Write; + + let mut message = format!("{}", err); + let mut maybe_source = err.source(); + + if maybe_source.is_some() { + let mut past_message = message.clone(); + let mut count = 0; + let mut display_count = 0; + while let Some(source) = maybe_source { + let current_message = format!("{}", source); + maybe_source = source.source(); + + // sometimes an error might be repeated due to + // being boxed multiple times in another AnyError + if current_message != past_message { + write!(message, "\n {}: ", display_count,).unwrap(); + for (i, line) in current_message.lines().enumerate() { + if i > 0 { + write!(message, "\n {}", line).unwrap(); + } else { + write!(message, "{}", line).unwrap(); + } + } + display_count += 1; + } + + if count > 8 { + write!(message, "\n {}: ...", count).unwrap(); + break; + } + + past_message = current_message; + count += 1; + } + } + + message +} + #[cfg(test)] mod test { use std::sync::Arc; diff --git a/cli/http_util.rs b/cli/http_util.rs index cf244c525a..4b17936d68 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -19,6 +19,7 @@ use deno_runtime::deno_fetch; use deno_runtime::deno_fetch::create_http_client; use deno_runtime::deno_fetch::CreateHttpClientOptions; use deno_runtime::deno_tls::RootCertStoreProvider; +use http::header; use http::header::HeaderName; use http::header::HeaderValue; use http::header::ACCEPT; @@ -204,6 +205,7 @@ pub struct FetchOnceArgs<'a> { pub maybe_accept: Option, pub maybe_etag: Option, pub maybe_auth_token: Option, + pub maybe_auth: Option<(header::HeaderName, header::HeaderValue)>, pub maybe_progress_guard: Option<&'a UpdateGuard>, } @@ -382,6 +384,8 @@ impl HttpClient { request .headers_mut() .insert(AUTHORIZATION, authorization_val); + } else if let Some((header, value)) = args.maybe_auth { + request.headers_mut().insert(header, value); } if let Some(accept) = args.maybe_accept { let accepts_val = HeaderValue::from_str(&accept)?; @@ -470,15 +474,23 @@ impl HttpClient { } } - pub async fn download_with_progress( + pub async fn download_with_progress_and_retries( &self, url: Url, maybe_header: Option<(HeaderName, HeaderValue)>, progress_guard: &UpdateGuard, ) -> Result>, DownloadError> { - self - .download_inner(url, maybe_header, Some(progress_guard)) - .await + crate::util::retry::retry( + || { + self.download_inner( + url.clone(), + maybe_header.clone(), + Some(progress_guard), + ) + }, + |e| matches!(e, DownloadError::BadResponse(_) | DownloadError::Fetch(_)), + ) + .await } pub async fn get_redirected_url( @@ -784,6 +796,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -810,6 +823,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -837,6 +851,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -858,6 +873,7 @@ mod test { maybe_etag: Some("33a64df551425fcc55e".to_string()), maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; assert_eq!(res.unwrap(), FetchOnceResult::NotModified); @@ -877,6 +893,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -906,6 +923,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, _)) = result { @@ -931,6 +949,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Redirect(url, _)) = result { @@ -966,6 +985,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -1013,6 +1033,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; @@ -1075,6 +1096,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; @@ -1128,6 +1150,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -1169,6 +1192,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -1191,6 +1215,7 @@ mod test { maybe_etag: Some("33a64df551425fcc55e".to_string()), maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; assert_eq!(res.unwrap(), FetchOnceResult::NotModified); @@ -1225,6 +1250,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -1254,6 +1280,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; assert!(result.is_err()); @@ -1275,6 +1302,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; @@ -1298,6 +1326,7 @@ mod test { maybe_etag: None, maybe_auth_token: None, maybe_progress_guard: None, + maybe_auth: None, }) .await; diff --git a/cli/js/40_bench.js b/cli/js/40_bench.js index a94c782fc5..b07df3993c 100644 --- a/cli/js/40_bench.js +++ b/cli/js/40_bench.js @@ -104,12 +104,12 @@ function bench( } if (optionsOrFn.fn != undefined) { throw new TypeError( - "Unexpected 'fn' field in options, bench function is already provided as the third argument.", + "Unexpected 'fn' field in options, bench function is already provided as the third argument", ); } if (optionsOrFn.name != undefined) { throw new TypeError( - "Unexpected 'name' field in options, bench name is already provided as the first argument.", + "Unexpected 'name' field in options, bench name is already provided as the first argument", ); } benchDesc = { @@ -141,7 +141,7 @@ function bench( fn = optionsOrFn; if (nameOrFnOrOptions.fn != undefined) { throw new TypeError( - "Unexpected 'fn' field in options, bench function is already provided as the second argument.", + "Unexpected 'fn' field in options, bench function is already provided as the second argument", ); } name = nameOrFnOrOptions.name ?? fn.name; @@ -150,7 +150,7 @@ function bench( !nameOrFnOrOptions.fn || typeof nameOrFnOrOptions.fn !== "function" ) { throw new TypeError( - "Expected 'fn' field in the first argument to be a bench function.", + "Expected 'fn' field in the first argument to be a bench function", ); } fn = nameOrFnOrOptions.fn; @@ -385,12 +385,12 @@ function createBenchContext(desc) { start() { if (currentBenchId !== desc.id) { throw new TypeError( - "The benchmark which this context belongs to is not being executed.", + "The benchmark which this context belongs to is not being executed", ); } if (currentBenchUserExplicitStart != null) { throw new TypeError( - "BenchContext::start() has already been invoked.", + "BenchContext::start() has already been invoked", ); } currentBenchUserExplicitStart = benchNow(); @@ -399,11 +399,11 @@ function createBenchContext(desc) { const end = benchNow(); if (currentBenchId !== desc.id) { throw new TypeError( - "The benchmark which this context belongs to is not being executed.", + "The benchmark which this context belongs to is not being executed", ); } if (currentBenchUserExplicitEnd != null) { - throw new TypeError("BenchContext::end() has already been invoked."); + throw new TypeError("BenchContext::end() has already been invoked"); } currentBenchUserExplicitEnd = end; }, diff --git a/cli/js/40_test.js b/cli/js/40_test.js index 5a081e2175..ea526a17d4 100644 --- a/cli/js/40_test.js +++ b/cli/js/40_test.js @@ -113,7 +113,7 @@ function assertExit(fn, isTest) { throw new Error( `${ isTest ? "Test case" : "Bench" - } finished with exit code set to ${exitCode}.`, + } finished with exit code set to ${exitCode}`, ); } if (innerResult) { @@ -242,12 +242,12 @@ function testInner( } if (optionsOrFn.fn != undefined) { throw new TypeError( - "Unexpected 'fn' field in options, test function is already provided as the third argument.", + "Unexpected 'fn' field in options, test function is already provided as the third argument", ); } if (optionsOrFn.name != undefined) { throw new TypeError( - "Unexpected 'name' field in options, test name is already provided as the first argument.", + "Unexpected 'name' field in options, test name is already provided as the first argument", ); } testDesc = { @@ -279,7 +279,7 @@ function testInner( fn = optionsOrFn; if (nameOrFnOrOptions.fn != undefined) { throw new TypeError( - "Unexpected 'fn' field in options, test function is already provided as the second argument.", + "Unexpected 'fn' field in options, test function is already provided as the second argument", ); } name = nameOrFnOrOptions.name ?? fn.name; @@ -288,7 +288,7 @@ function testInner( !nameOrFnOrOptions.fn || typeof nameOrFnOrOptions.fn !== "function" ) { throw new TypeError( - "Expected 'fn' field in the first argument to be a test function.", + "Expected 'fn' field in the first argument to be a test function", ); } fn = nameOrFnOrOptions.fn; @@ -426,7 +426,7 @@ function createTestContext(desc) { let stepDesc; if (typeof nameOrFnOrOptions === "string") { if (typeof maybeFn !== "function") { - throw new TypeError("Expected function for second argument."); + throw new TypeError("Expected function for second argument"); } stepDesc = { name: nameOrFnOrOptions, @@ -434,7 +434,7 @@ function createTestContext(desc) { }; } else if (typeof nameOrFnOrOptions === "function") { if (!nameOrFnOrOptions.name) { - throw new TypeError("The step function must have a name."); + throw new TypeError("The step function must have a name"); } if (maybeFn != undefined) { throw new TypeError( @@ -449,7 +449,7 @@ function createTestContext(desc) { stepDesc = nameOrFnOrOptions; } else { throw new TypeError( - "Expected a test definition or name and function.", + "Expected a test definition or name and function", ); } stepDesc.ignore ??= false; diff --git a/cli/jsr.rs b/cli/jsr.rs index 87a54af22b..767d304d60 100644 --- a/cli/jsr.rs +++ b/cli/jsr.rs @@ -6,7 +6,6 @@ use dashmap::DashMap; use deno_core::serde_json; use deno_graph::packages::JsrPackageInfo; use deno_graph::packages::JsrPackageVersionInfo; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use std::sync::Arc; @@ -68,10 +67,7 @@ impl JsrFetchResolver { let file_fetcher = self.file_fetcher.clone(); // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { - file_fetcher - .fetch(&meta_url, &PermissionsContainer::allow_all()) - .await - .ok() + file_fetcher.fetch_bypass_permissions(&meta_url).await.ok() }) .await .ok()??; @@ -96,10 +92,7 @@ impl JsrFetchResolver { let file_fetcher = self.file_fetcher.clone(); // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { - file_fetcher - .fetch(&meta_url, &PermissionsContainer::allow_all()) - .await - .ok() + file_fetcher.fetch_bypass_permissions(&meta_url).await.ok() }) .await .ok()??; diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs index 9f2c7ffc86..39f1ae6482 100644 --- a/cli/lsp/analysis.rs +++ b/cli/lsp/analysis.rs @@ -2,20 +2,22 @@ use super::diagnostics::DenoDiagnostic; use super::diagnostics::DiagnosticSource; +use super::documents::Document; use super::documents::Documents; use super::language_server; use super::resolver::LspResolver; use super::tsc; +use super::urls::url_to_uri; use crate::args::jsr_url; +use crate::lsp::search::PackageSearchApi; use crate::tools::lint::CliLinter; +use deno_config::workspace::MappedResolution; use deno_lint::diagnostic::LintDiagnosticRange; -use deno_runtime::fs_util::specifier_to_file_path; use deno_ast::SourceRange; use deno_ast::SourceRangedForSpanned; use deno_ast::SourceTextInfo; -use deno_core::anyhow::anyhow; use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::serde::Deserialize; @@ -23,6 +25,7 @@ use deno_core::serde::Serialize; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::ModuleSpecifier; +use deno_path_util::url_to_file_path; use deno_runtime::deno_node::PathClean; use deno_semver::jsr::JsrPackageNvReference; use deno_semver::jsr::JsrPackageReqReference; @@ -36,10 +39,12 @@ use import_map::ImportMap; use node_resolver::NpmResolver; use once_cell::sync::Lazy; use regex::Regex; +use std::borrow::Cow; use std::cmp::Ordering; use std::collections::HashMap; use std::collections::HashSet; use std::path::Path; +use text_lines::LineAndColumnIndex; use tower_lsp::lsp_types as lsp; use tower_lsp::lsp_types::Position; use tower_lsp::lsp_types::Range; @@ -224,6 +229,7 @@ pub struct TsResponseImportMapper<'a> { documents: &'a Documents, maybe_import_map: Option<&'a ImportMap>, resolver: &'a LspResolver, + file_referrer: ModuleSpecifier, } impl<'a> TsResponseImportMapper<'a> { @@ -231,11 +237,13 @@ impl<'a> TsResponseImportMapper<'a> { documents: &'a Documents, maybe_import_map: Option<&'a ImportMap>, resolver: &'a LspResolver, + file_referrer: &ModuleSpecifier, ) -> Self { Self { documents, maybe_import_map, resolver, + file_referrer: file_referrer.clone(), } } @@ -256,8 +264,6 @@ impl<'a> TsResponseImportMapper<'a> { } } - let file_referrer = self.documents.get_file_referrer(referrer); - if let Some(jsr_path) = specifier.as_str().strip_prefix(jsr_url().as_str()) { let mut segments = jsr_path.split('/'); @@ -272,7 +278,7 @@ impl<'a> TsResponseImportMapper<'a> { let export = self.resolver.jsr_lookup_export_for_path( &nv, &path, - file_referrer.as_deref(), + Some(&self.file_referrer), )?; let sub_path = (export != ".").then_some(export); let mut req = None; @@ -298,7 +304,7 @@ impl<'a> TsResponseImportMapper<'a> { req = req.or_else(|| { self .resolver - .jsr_lookup_req_for_nv(&nv, file_referrer.as_deref()) + .jsr_lookup_req_for_nv(&nv, Some(&self.file_referrer)) }); let spec_str = if let Some(req) = req { let req_ref = PackageReqReference { req, sub_path }; @@ -328,7 +334,7 @@ impl<'a> TsResponseImportMapper<'a> { if let Some(npm_resolver) = self .resolver - .maybe_managed_npm_resolver(file_referrer.as_deref()) + .maybe_managed_npm_resolver(Some(&self.file_referrer)) { if npm_resolver.in_npm_package(specifier) { if let Ok(Some(pkg_id)) = @@ -400,7 +406,7 @@ impl<'a> TsResponseImportMapper<'a> { .flatten()?; let root_folder = package_json.path.parent()?; - let specifier_path = specifier_to_file_path(specifier).ok()?; + let specifier_path = url_to_file_path(specifier).ok()?; let mut search_paths = vec![specifier_path.clone()]; // TypeScript will provide a .js extension for quick fixes, so do // a search for the .d.ts file instead @@ -464,6 +470,26 @@ impl<'a> TsResponseImportMapper<'a> { } None } + + pub fn is_valid_import( + &self, + specifier_text: &str, + referrer: &ModuleSpecifier, + ) -> bool { + self + .resolver + .as_graph_resolver(Some(&self.file_referrer)) + .resolve( + specifier_text, + &deno_graph::Range { + specifier: referrer.clone(), + start: deno_graph::Position::zeroed(), + end: deno_graph::Position::zeroed(), + }, + deno_graph::source::ResolutionMode::Types, + ) + .is_ok() + } } fn try_reverse_map_package_json_exports( @@ -572,66 +598,62 @@ pub fn fix_ts_import_changes( /// Fix tsc import code actions so that the module specifier is correct for /// resolution by Deno (includes the extension). -fn fix_ts_import_action( +fn fix_ts_import_action<'a>( referrer: &ModuleSpecifier, - action: &tsc::CodeFixAction, + action: &'a tsc::CodeFixAction, import_mapper: &TsResponseImportMapper, -) -> Result { - if matches!( +) -> Option> { + if !matches!( action.fix_name.as_str(), "import" | "fixMissingFunctionDeclaration" ) { - let change = action + return Some(Cow::Borrowed(action)); + } + let specifier = (|| { + let text_change = action.changes.first()?.text_changes.first()?; + let captures = IMPORT_SPECIFIER_RE.captures(&text_change.new_text)?; + Some(captures.get(1)?.as_str()) + })(); + let Some(specifier) = specifier else { + return Some(Cow::Borrowed(action)); + }; + if let Some(new_specifier) = + import_mapper.check_unresolved_specifier(specifier, referrer) + { + let description = action.description.replace(specifier, &new_specifier); + let changes = action .changes - .first() - .ok_or_else(|| anyhow!("Unexpected action changes."))?; - let text_change = change - .text_changes - .first() - .ok_or_else(|| anyhow!("Missing text change."))?; - if let Some(captures) = IMPORT_SPECIFIER_RE.captures(&text_change.new_text) - { - let specifier = captures - .get(1) - .ok_or_else(|| anyhow!("Missing capture."))? - .as_str(); - if let Some(new_specifier) = - import_mapper.check_unresolved_specifier(specifier, referrer) - { - let description = action.description.replace(specifier, &new_specifier); - let changes = action - .changes + .iter() + .map(|c| { + let text_changes = c + .text_changes .iter() - .map(|c| { - let text_changes = c - .text_changes - .iter() - .map(|tc| tsc::TextChange { - span: tc.span.clone(), - new_text: tc.new_text.replace(specifier, &new_specifier), - }) - .collect(); - tsc::FileTextChanges { - file_name: c.file_name.clone(), - text_changes, - is_new_file: c.is_new_file, - } + .map(|tc| tsc::TextChange { + span: tc.span.clone(), + new_text: tc.new_text.replace(specifier, &new_specifier), }) .collect(); + tsc::FileTextChanges { + file_name: c.file_name.clone(), + text_changes, + is_new_file: c.is_new_file, + } + }) + .collect(); - return Ok(tsc::CodeFixAction { - description, - changes, - commands: None, - fix_name: action.fix_name.clone(), - fix_id: None, - fix_all_description: None, - }); - } - } + Some(Cow::Owned(tsc::CodeFixAction { + description, + changes, + commands: None, + fix_name: action.fix_name.clone(), + fix_id: None, + fix_all_description: None, + })) + } else if !import_mapper.is_valid_import(specifier, referrer) { + None + } else { + Some(Cow::Borrowed(action)) } - - Ok(action.clone()) } /// Determines if two TypeScript diagnostic codes are effectively equivalent. @@ -750,10 +772,11 @@ impl CodeActionCollection { .as_ref() .and_then(|d| serde_json::from_value::>(d.clone()).ok()) { + let uri = url_to_uri(specifier)?; for quick_fix in data_quick_fixes { let mut changes = HashMap::new(); changes.insert( - specifier.clone(), + uri.clone(), quick_fix .changes .into_iter() @@ -795,6 +818,7 @@ impl CodeActionCollection { maybe_text_info: Option<&SourceTextInfo>, maybe_parsed_source: Option<&deno_ast::ParsedSource>, ) -> Result<(), AnyError> { + let uri = url_to_uri(specifier)?; let code = diagnostic .code .as_ref() @@ -811,7 +835,7 @@ impl CodeActionCollection { let mut changes = HashMap::new(); changes.insert( - specifier.clone(), + uri.clone(), vec![lsp::TextEdit { new_text: prepend_whitespace( format!("// deno-lint-ignore {code}\n"), @@ -892,7 +916,7 @@ impl CodeActionCollection { } let mut changes = HashMap::new(); - changes.insert(specifier.clone(), vec![lsp::TextEdit { new_text, range }]); + changes.insert(uri.clone(), vec![lsp::TextEdit { new_text, range }]); let ignore_file_action = lsp::CodeAction { title: format!("Disable {code} for the entire file"), kind: Some(lsp::CodeActionKind::QUICKFIX), @@ -913,7 +937,7 @@ impl CodeActionCollection { let mut changes = HashMap::new(); changes.insert( - specifier.clone(), + uri, vec![lsp::TextEdit { new_text: "// deno-lint-ignore-file\n".to_string(), range: lsp::Range { @@ -970,11 +994,13 @@ impl CodeActionCollection { "The action returned from TypeScript is unsupported.", )); } - let action = fix_ts_import_action( + let Some(action) = fix_ts_import_action( specifier, action, &language_server.get_ts_response_import_mapper(specifier), - )?; + ) else { + return Ok(()); + }; let edit = ts_changes_to_edit(&action.changes, language_server)?; let code_action = lsp::CodeAction { title: action.description.clone(), @@ -994,7 +1020,7 @@ impl CodeActionCollection { }); self .actions - .push(CodeActionKind::Tsc(code_action, action.clone())); + .push(CodeActionKind::Tsc(code_action, action.as_ref().clone())); if let Some(fix_id) = &action.fix_id { if let Some(CodeActionKind::Tsc(existing_fix_all, existing_action)) = @@ -1148,6 +1174,191 @@ impl CodeActionCollection { ..Default::default() })); } + + pub async fn add_source_actions( + &mut self, + document: &Document, + range: &lsp::Range, + language_server: &language_server::Inner, + ) { + fn import_start_from_specifier( + document: &Document, + import: &deno_graph::Import, + ) -> Option { + // find the top level statement that contains the specifier + let parsed_source = document.maybe_parsed_source()?.as_ref().ok()?; + let text_info = parsed_source.text_info_lazy(); + let specifier_range = SourceRange::new( + text_info.loc_to_source_pos(LineAndColumnIndex { + line_index: import.specifier_range.start.line, + column_index: import.specifier_range.start.character, + }), + text_info.loc_to_source_pos(LineAndColumnIndex { + line_index: import.specifier_range.end.line, + column_index: import.specifier_range.end.character, + }), + ); + + match parsed_source.program_ref() { + deno_ast::swc::ast::Program::Module(module) => module + .body + .iter() + .find(|i| i.range().contains(&specifier_range)) + .map(|i| text_info.line_and_column_index(i.range().start)), + deno_ast::swc::ast::Program::Script(_) => None, + } + } + + async fn deno_types_for_npm_action( + document: &Document, + range: &lsp::Range, + language_server: &language_server::Inner, + ) -> Option { + let (dep_key, dependency, _) = + document.get_maybe_dependency(&range.end)?; + if dependency.maybe_deno_types_specifier.is_some() { + return None; + } + if dependency.maybe_code.maybe_specifier().is_none() + && dependency.maybe_type.maybe_specifier().is_none() + { + // We're using byonm and the package is not cached. + return None; + } + let position = deno_graph::Position::new( + range.end.line as usize, + range.end.character as usize, + ); + let import_start = dependency.imports.iter().find_map(|i| { + if json!(i.kind) != json!("es") && json!(i.kind) != json!("tsType") { + return None; + } + if !i.specifier_range.includes(&position) { + return None; + } + + import_start_from_specifier(document, i) + })?; + let referrer = document.specifier(); + let file_referrer = document.file_referrer(); + let config_data = language_server + .config + .tree + .data_for_specifier(file_referrer?)?; + let workspace_resolver = config_data.resolver.clone(); + let npm_ref = if let Ok(resolution) = + workspace_resolver.resolve(&dep_key, document.specifier()) + { + let specifier = match resolution { + MappedResolution::Normal { specifier, .. } + | MappedResolution::ImportMap { specifier, .. } => specifier, + _ => { + return None; + } + }; + NpmPackageReqReference::from_specifier(&specifier).ok()? + } else { + // Only resolve bare package.json deps for byonm. + if !config_data.byonm { + return None; + } + if !language_server + .resolver + .is_bare_package_json_dep(&dep_key, referrer) + { + return None; + } + NpmPackageReqReference::from_str(&format!("npm:{}", &dep_key)).ok()? + }; + let package_name = &npm_ref.req().name; + if package_name.starts_with("@types/") { + return None; + } + let managed_npm_resolver = language_server + .resolver + .maybe_managed_npm_resolver(file_referrer); + if let Some(npm_resolver) = managed_npm_resolver { + if !npm_resolver.is_pkg_req_folder_cached(npm_ref.req()) { + return None; + } + } + if language_server + .resolver + .npm_to_file_url(&npm_ref, document.specifier(), file_referrer) + .is_some() + { + // The package import has types. + return None; + } + let types_package_name = format!("@types/{package_name}"); + let types_package_version = language_server + .npm_search_api + .versions(&types_package_name) + .await + .ok() + .and_then(|versions| versions.first().cloned())?; + let types_specifier_text = + if let Some(npm_resolver) = managed_npm_resolver { + let mut specifier_text = if let Some(req) = + npm_resolver.top_package_req_for_name(&types_package_name) + { + format!("npm:{req}") + } else { + format!("npm:{}@^{}", &types_package_name, types_package_version) + }; + let specifier = ModuleSpecifier::parse(&specifier_text).ok()?; + if let Some(file_referrer) = file_referrer { + if let Some(text) = language_server + .get_ts_response_import_mapper(file_referrer) + .check_specifier(&specifier, referrer) + { + specifier_text = text; + } + } + specifier_text + } else { + types_package_name.clone() + }; + let uri = language_server + .url_map + .specifier_to_uri(referrer, file_referrer) + .ok()?; + let position = lsp::Position { + line: import_start.line_index as u32, + character: import_start.column_index as u32, + }; + let new_text = format!( + "{}// @deno-types=\"{}\"\n", + if position.character == 0 { "" } else { "\n" }, + &types_specifier_text + ); + let text_edit = lsp::TextEdit { + range: lsp::Range { + start: position, + end: position, + }, + new_text, + }; + Some(lsp::CodeAction { + title: format!( + "Add @deno-types directive for \"{}\"", + &types_specifier_text + ), + kind: Some(lsp::CodeActionKind::QUICKFIX), + diagnostics: None, + edit: Some(lsp::WorkspaceEdit { + changes: Some([(uri, vec![text_edit])].into_iter().collect()), + ..Default::default() + }), + ..Default::default() + }) + } + if let Some(action) = + deno_types_for_npm_action(document, range, language_server).await + { + self.actions.push(CodeActionKind::Deno(action)); + } + } } /// Prepend the whitespace characters found at the start of line_content to content. diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs index 5dae38c206..fbf9ea6f1b 100644 --- a/cli/lsp/cache.rs +++ b/cli/lsp/cache.rs @@ -7,26 +7,16 @@ use crate::cache::LocalLspHttpCache; use crate::lsp::config::Config; use crate::lsp::logging::lsp_log; use crate::lsp::logging::lsp_warn; -use deno_runtime::fs_util::specifier_to_file_path; use deno_core::url::Url; use deno_core::ModuleSpecifier; +use deno_path_util::url_to_file_path; use std::collections::BTreeMap; use std::fs; use std::path::Path; use std::sync::Arc; use std::time::SystemTime; -/// In the LSP, we disallow the cache from automatically copying from -/// the global cache to the local cache for technical reasons. -/// -/// 1. We need to verify the checksums from the lockfile are correct when -/// moving from the global to the local cache. -/// 2. We need to verify the checksums for JSR https specifiers match what -/// is found in the package's manifest. -pub const LSP_DISALLOW_GLOBAL_TO_LOCAL_COPY: deno_cache_dir::GlobalToLocalCopy = - deno_cache_dir::GlobalToLocalCopy::Disallow; - pub fn calculate_fs_version( cache: &LspCache, specifier: &ModuleSpecifier, @@ -34,7 +24,7 @@ pub fn calculate_fs_version( ) -> Option { match specifier.scheme() { "npm" | "node" | "data" | "blob" => None, - "file" => specifier_to_file_path(specifier) + "file" => url_to_file_path(specifier) .ok() .and_then(|path| calculate_fs_version_at_path(&path)), _ => calculate_fs_version_in_cache(cache, specifier, file_referrer), @@ -92,7 +82,7 @@ impl Default for LspCache { impl LspCache { pub fn new(global_cache_url: Option) -> Self { let global_cache_path = global_cache_url.and_then(|s| { - specifier_to_file_path(&s) + url_to_file_path(&s) .inspect(|p| { lsp_log!("Resolved global cache path: \"{}\"", p.to_string_lossy()); }) @@ -104,7 +94,7 @@ impl LspCache { let deno_dir = DenoDir::new(global_cache_path) .expect("should be infallible with absolute custom root"); let global = Arc::new(GlobalHttpCache::new( - deno_dir.deps_folder_path(), + deno_dir.remote_folder_path(), crate::cache::RealDenoCacheEnv, )); Self { @@ -175,7 +165,7 @@ impl LspCache { &self, specifier: &ModuleSpecifier, ) -> Option { - let path = specifier_to_file_path(specifier).ok()?; + let path = url_to_file_path(specifier).ok()?; let vendor = self .vendors_by_scope .iter() @@ -186,7 +176,7 @@ impl LspCache { } pub fn is_valid_file_referrer(&self, specifier: &ModuleSpecifier) -> bool { - if let Ok(path) = specifier_to_file_path(specifier) { + if let Ok(path) = url_to_file_path(specifier) { if !path.starts_with(&self.deno_dir().root) { return true; } diff --git a/cli/lsp/capabilities.rs b/cli/lsp/capabilities.rs index 650fea5718..5cdb1224d8 100644 --- a/cli/lsp/capabilities.rs +++ b/cli/lsp/capabilities.rs @@ -147,12 +147,14 @@ pub fn server_capabilities( moniker_provider: None, experimental: Some(json!({ "denoConfigTasks": true, - "testingApi":true, + "testingApi": true, + "didRefreshDenoConfigurationTreeNotifications": true, })), inlay_hint_provider: Some(OneOf::Left(true)), position_encoding: None, - // TODO(nayeemrmn): Support pull-based diagnostics. diagnostic_provider: None, inline_value_provider: None, + inline_completion_provider: None, + notebook_document_sync: None, } } diff --git a/cli/lsp/client.rs b/cli/lsp/client.rs index 719ce53f6e..65865d5b32 100644 --- a/cli/lsp/client.rs +++ b/cli/lsp/client.rs @@ -8,6 +8,7 @@ use deno_core::anyhow::bail; use deno_core::error::AnyError; use deno_core::serde_json::json; use deno_core::unsync::spawn; +use lsp_types::Uri; use tower_lsp::lsp_types as lsp; use tower_lsp::lsp_types::ConfigurationItem; @@ -17,7 +18,6 @@ use super::config::WorkspaceSettings; use super::config::SETTINGS_SECTION; use super::lsp_custom; use super::testing::lsp_custom as testing_lsp_custom; -use super::urls::LspClientUrl; #[derive(Debug)] pub enum TestingNotification { @@ -52,14 +52,11 @@ impl Client { pub async fn publish_diagnostics( &self, - uri: LspClientUrl, + uri: Uri, diags: Vec, version: Option, ) { - self - .0 - .publish_diagnostics(uri.into_url(), diags, version) - .await; + self.0.publish_diagnostics(uri, diags, version).await; } pub fn send_registry_state_notification( @@ -95,6 +92,19 @@ impl Client { }); } + pub fn send_did_refresh_deno_configuration_tree_notification( + &self, + params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams, + ) { + // do on a task in case the caller currently is in the lsp lock + let client = self.0.clone(); + spawn(async move { + client + .send_did_refresh_deno_configuration_tree_notification(params) + .await; + }); + } + pub fn send_did_change_deno_configuration_notification( &self, params: lsp_custom::DidChangeDenoConfigurationNotificationParams, @@ -149,7 +159,7 @@ impl OutsideLockClient { pub async fn workspace_configuration( &self, - scopes: Vec>, + scopes: Vec>, ) -> Result, AnyError> { self.0.workspace_configuration(scopes).await } @@ -159,7 +169,7 @@ impl OutsideLockClient { trait ClientTrait: Send + Sync { async fn publish_diagnostics( &self, - uri: lsp::Url, + uri: lsp::Uri, diagnostics: Vec, version: Option, ); @@ -172,6 +182,10 @@ trait ClientTrait: Send + Sync { params: lsp_custom::DiagnosticBatchNotificationParams, ); async fn send_test_notification(&self, params: TestingNotification); + async fn send_did_refresh_deno_configuration_tree_notification( + &self, + params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams, + ); async fn send_did_change_deno_configuration_notification( &self, params: lsp_custom::DidChangeDenoConfigurationNotificationParams, @@ -182,7 +196,7 @@ trait ClientTrait: Send + Sync { ); async fn workspace_configuration( &self, - scopes: Vec>, + scopes: Vec>, ) -> Result, AnyError>; async fn show_message(&self, message_type: lsp::MessageType, text: String); async fn register_capability( @@ -198,7 +212,7 @@ struct TowerClient(tower_lsp::Client); impl ClientTrait for TowerClient { async fn publish_diagnostics( &self, - uri: lsp::Url, + uri: lsp::Uri, diagnostics: Vec, version: Option, ) { @@ -252,6 +266,18 @@ impl ClientTrait for TowerClient { } } + async fn send_did_refresh_deno_configuration_tree_notification( + &self, + params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams, + ) { + self + .0 + .send_notification::( + params, + ) + .await + } + async fn send_did_change_deno_configuration_notification( &self, params: lsp_custom::DidChangeDenoConfigurationNotificationParams, @@ -276,7 +302,7 @@ impl ClientTrait for TowerClient { async fn workspace_configuration( &self, - scopes: Vec>, + scopes: Vec>, ) -> Result, AnyError> { let config_response = self .0 @@ -349,7 +375,7 @@ struct ReplClient; impl ClientTrait for ReplClient { async fn publish_diagnostics( &self, - _uri: lsp::Url, + _uri: lsp::Uri, _diagnostics: Vec, _version: Option, ) { @@ -369,6 +395,12 @@ impl ClientTrait for ReplClient { async fn send_test_notification(&self, _params: TestingNotification) {} + async fn send_did_refresh_deno_configuration_tree_notification( + &self, + _params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams, + ) { + } + async fn send_did_change_deno_configuration_notification( &self, _params: lsp_custom::DidChangeDenoConfigurationNotificationParams, @@ -383,7 +415,7 @@ impl ClientTrait for ReplClient { async fn workspace_configuration( &self, - scopes: Vec>, + scopes: Vec>, ) -> Result, AnyError> { Ok(vec![get_repl_workspace_settings(); scopes.len()]) } diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs index 7e0705e99d..1590743b2b 100644 --- a/cli/lsp/completions.rs +++ b/cli/lsp/completions.rs @@ -19,7 +19,6 @@ use crate::util::path::relative_specifier; use deno_graph::source::ResolutionMode; use deno_graph::Range; use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES; -use deno_runtime::fs_util::specifier_to_file_path; use deno_ast::LineAndColumnIndex; use deno_ast::SourceTextInfo; @@ -30,6 +29,7 @@ use deno_core::serde::Serialize; use deno_core::serde_json::json; use deno_core::url::Position; use deno_core::ModuleSpecifier; +use deno_path_util::url_to_file_path; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::package::PackageNv; use import_map::ImportMap; @@ -200,15 +200,11 @@ pub async fn get_import_completions( { // completions for import map specifiers Some(lsp::CompletionResponse::List(completion_list)) - } else if text.starts_with("./") - || text.starts_with("../") - || text.starts_with('/') + } else if let Some(completion_list) = + get_local_completions(specifier, &text, &range, resolver) { // completions for local relative modules - Some(lsp::CompletionResponse::List(CompletionList { - is_incomplete: false, - items: get_local_completions(specifier, &text, &range, resolver)?, - })) + Some(lsp::CompletionResponse::List(completion_list)) } else if !text.is_empty() { // completion of modules from a module registry or cache check_auto_config_registry( @@ -249,7 +245,7 @@ pub async fn get_import_completions( .collect(); let mut is_incomplete = false; if let Some(import_map) = maybe_import_map { - items.extend(get_base_import_map_completions(import_map)); + items.extend(get_base_import_map_completions(import_map, specifier)); } if let Some(origin_items) = module_registries.get_origin_completions(&text, &range) @@ -268,20 +264,20 @@ pub async fn get_import_completions( /// map as completion items. fn get_base_import_map_completions( import_map: &ImportMap, + referrer: &ModuleSpecifier, ) -> Vec { import_map - .imports() - .keys() - .map(|key| { + .entries_for_referrer(referrer) + .map(|entry| { // for some strange reason, keys that start with `/` get stored in the // import map as `file:///`, and so when we pull the keys out, we need to // change the behavior - let mut label = if key.starts_with("file://") { - FILE_PROTO_RE.replace(key, "").to_string() + let mut label = if entry.key.starts_with("file://") { + FILE_PROTO_RE.replace(entry.key, "").to_string() } else { - key.to_string() + entry.key.to_string() }; - let kind = if key.ends_with('/') { + let kind = if entry.key.ends_with('/') { label.pop(); Some(lsp::CompletionItemKind::FOLDER) } else { @@ -363,15 +359,15 @@ fn get_local_completions( text: &str, range: &lsp::Range, resolver: &LspResolver, -) -> Option> { +) -> Option { if base.scheme() != "file" { return None; } - let parent = base.join(text).ok()?.join(".").ok()?; + let parent = &text[..text.char_indices().rfind(|(_, c)| *c == '/')?.0 + 1]; let resolved_parent = resolver .as_graph_resolver(Some(base)) .resolve( - parent.as_str(), + parent, &Range { specifier: base.clone(), start: deno_graph::Position::zeroed(), @@ -380,63 +376,63 @@ fn get_local_completions( ResolutionMode::Execution, ) .ok()?; - let resolved_parent_path = specifier_to_file_path(&resolved_parent).ok()?; - let raw_parent = - &text[..text.char_indices().rfind(|(_, c)| *c == '/')?.0 + 1]; + let resolved_parent_path = url_to_file_path(&resolved_parent).ok()?; if resolved_parent_path.is_dir() { let cwd = std::env::current_dir().ok()?; - let items = std::fs::read_dir(resolved_parent_path).ok()?; - Some( - items - .filter_map(|de| { - let de = de.ok()?; - let label = de.path().file_name()?.to_string_lossy().to_string(); - let entry_specifier = resolve_path(de.path().to_str()?, &cwd).ok()?; - if entry_specifier == *base { - return None; - } - let full_text = format!("{raw_parent}{label}"); - let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { - range: *range, - new_text: full_text.clone(), - })); - let filter_text = Some(full_text); - match de.file_type() { - Ok(file_type) if file_type.is_dir() => Some(lsp::CompletionItem { - label, - kind: Some(lsp::CompletionItemKind::FOLDER), - detail: Some("(local)".to_string()), - filter_text, - sort_text: Some("1".to_string()), - text_edit, - commit_characters: Some( - IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(), - ), - ..Default::default() - }), - Ok(file_type) if file_type.is_file() => { - if is_importable_ext(&de.path()) { - Some(lsp::CompletionItem { - label, - kind: Some(lsp::CompletionItemKind::FILE), - detail: Some("(local)".to_string()), - filter_text, - sort_text: Some("1".to_string()), - text_edit, - commit_characters: Some( - IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(), - ), - ..Default::default() - }) - } else { - None - } + let entries = std::fs::read_dir(resolved_parent_path).ok()?; + let items = entries + .filter_map(|de| { + let de = de.ok()?; + let label = de.path().file_name()?.to_string_lossy().to_string(); + let entry_specifier = resolve_path(de.path().to_str()?, &cwd).ok()?; + if entry_specifier == *base { + return None; + } + let full_text = format!("{parent}{label}"); + let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { + range: *range, + new_text: full_text.clone(), + })); + let filter_text = Some(full_text); + match de.file_type() { + Ok(file_type) if file_type.is_dir() => Some(lsp::CompletionItem { + label, + kind: Some(lsp::CompletionItemKind::FOLDER), + detail: Some("(local)".to_string()), + filter_text, + sort_text: Some("1".to_string()), + text_edit, + commit_characters: Some( + IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(), + ), + ..Default::default() + }), + Ok(file_type) if file_type.is_file() => { + if is_importable_ext(&de.path()) { + Some(lsp::CompletionItem { + label, + kind: Some(lsp::CompletionItemKind::FILE), + detail: Some("(local)".to_string()), + filter_text, + sort_text: Some("1".to_string()), + text_edit, + commit_characters: Some( + IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(), + ), + ..Default::default() + }) + } else { + None } - _ => None, } - }) - .collect(), - ) + _ => None, + } + }) + .collect(); + Some(CompletionList { + is_incomplete: false, + items, + }) } else { None } @@ -838,7 +834,7 @@ mod tests { fs_sources: &[(&str, &str)], ) -> Documents { let temp_dir = TempDir::new(); - let cache = LspCache::new(Some(temp_dir.uri().join(".deno_dir").unwrap())); + let cache = LspCache::new(Some(temp_dir.url().join(".deno_dir").unwrap())); let mut documents = Documents::default(); documents.update_config( &Default::default(), @@ -859,7 +855,7 @@ mod tests { .set(&specifier, HashMap::default(), source.as_bytes()) .expect("could not cache file"); let document = documents - .get_or_load(&specifier, Some(&temp_dir.uri().join("$").unwrap())); + .get_or_load(&specifier, Some(&temp_dir.url().join("$").unwrap())); assert!(document.is_some(), "source could not be setup"); } documents @@ -921,11 +917,11 @@ mod tests { }, }, &Default::default(), - ); - assert!(actual.is_some()); - let actual = actual.unwrap(); - assert_eq!(actual.len(), 3); - for item in actual { + ) + .unwrap(); + assert!(!actual.is_incomplete); + assert_eq!(actual.items.len(), 3); + for item in actual.items { match item.text_edit { Some(lsp::CompletionTextEdit::Edit(text_edit)) => { assert!(["./b", "./f.mjs", "./g.json"] diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index f99f1fa103..3ffc9e657a 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -5,6 +5,7 @@ use deno_config::deno_json::DenoJsonCache; use deno_config::deno_json::FmtConfig; use deno_config::deno_json::FmtOptionsConfig; use deno_config::deno_json::LintConfig; +use deno_config::deno_json::NodeModulesDirMode; use deno_config::deno_json::TestConfig; use deno_config::deno_json::TsConfig; use deno_config::fs::DenoConfigFs; @@ -30,35 +31,39 @@ use deno_core::serde::Serialize; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; +use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_lint::linter::LintConfig as DenoLintConfig; use deno_npm::npm_rc::ResolvedNpmRc; use deno_package_json::PackageJsonCache; +use deno_path_util::url_to_file_path; use deno_runtime::deno_node::PackageJson; -use deno_runtime::deno_permissions::PermissionsContainer; -use deno_runtime::fs_util::specifier_to_file_path; use indexmap::IndexSet; -use lsp::Url; use lsp_types::ClientCapabilities; use std::collections::BTreeMap; use std::collections::HashMap; +use std::ops::Deref; +use std::ops::DerefMut; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; use tower_lsp::lsp_types as lsp; use super::logging::lsp_log; +use super::lsp_custom; +use super::urls::url_to_uri; use crate::args::discover_npmrc_from_workspace; use crate::args::has_flag_env_var; use crate::args::CliLockfile; +use crate::args::CliLockfileReadFromPathOptions; use crate::args::ConfigFile; use crate::args::LintFlags; use crate::args::LintOptions; -use crate::args::DENO_FUTURE; use crate::cache::FastInsecureHasher; use crate::file_fetcher::FileFetcher; use crate::lsp::logging::lsp_warn; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; +use crate::resolver::SloppyImportsCachedFs; use crate::tools::lint::CliLinter; use crate::tools::lint::CliLinterOptions; use crate::tools::lint::LintRuleProvider; @@ -70,6 +75,54 @@ fn is_true() -> bool { true } +/// Wrapper that defaults if it fails to deserialize. Good for individual +/// settings. +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct SafeValue { + inner: T, +} + +impl<'de, T: Default + for<'de2> Deserialize<'de2>> Deserialize<'de> + for SafeValue +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Self { + inner: Deserialize::deserialize(deserializer).unwrap_or_default(), + }) + } +} + +impl Serialize for SafeValue { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.inner.serialize(serializer) + } +} + +impl Deref for SafeValue { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for SafeValue { + fn deref_mut(&mut self) -> &mut T { + &mut self.inner + } +} + +impl SafeValue { + pub fn as_deref(&self) -> &T { + &self.inner + } +} + #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct CodeLensSettings { @@ -386,6 +439,8 @@ pub struct LanguagePreferences { pub use_aliases_for_renames: bool, #[serde(default)] pub quote_style: QuoteStyle, + #[serde(default)] + pub prefer_type_only_auto_imports: bool, } impl Default for LanguagePreferences { @@ -396,6 +451,7 @@ impl Default for LanguagePreferences { auto_import_file_exclude_patterns: vec![], use_aliases_for_renames: true, quote_style: Default::default(), + prefer_type_only_auto_imports: false, } } } @@ -538,7 +594,7 @@ pub struct WorkspaceSettings { pub unsafely_ignore_certificate_errors: Option>, #[serde(default)] - pub unstable: bool, + pub unstable: SafeValue>, #[serde(default)] pub javascript: LanguageWorkspaceSettings, @@ -568,7 +624,7 @@ impl Default for WorkspaceSettings { testing: Default::default(), tls_certificate: None, unsafely_ignore_certificate_errors: None, - unstable: false, + unstable: Default::default(), javascript: Default::default(), typescript: Default::default(), } @@ -752,7 +808,7 @@ impl Settings { /// Returns `None` if the value should be deferred to the presence of a /// `deno.json` file. pub fn specifier_enabled(&self, specifier: &ModuleSpecifier) -> Option { - let Ok(path) = specifier_to_file_path(specifier) else { + let Ok(path) = url_to_file_path(specifier) else { // Non-file URLs are not disabled by these settings. return Some(true); }; @@ -761,7 +817,7 @@ impl Settings { let mut disable_paths = vec![]; let mut enable_paths = None; if let Some(folder_uri) = folder_uri { - if let Ok(folder_path) = specifier_to_file_path(folder_uri) { + if let Ok(folder_path) = url_to_file_path(folder_uri) { disable_paths = settings .disable_paths .iter() @@ -798,12 +854,12 @@ impl Settings { &self, specifier: &ModuleSpecifier, ) -> (&WorkspaceSettings, Option<&ModuleSpecifier>) { - let Ok(path) = specifier_to_file_path(specifier) else { + let Ok(path) = url_to_file_path(specifier) else { return (&self.unscoped, self.first_folder.as_ref()); }; for (folder_uri, settings) in self.by_workspace_folder.iter().rev() { if let Some(settings) = settings { - let Ok(folder_path) = specifier_to_file_path(folder_uri) else { + let Ok(folder_path) = url_to_file_path(folder_uri) else { continue; }; if path.starts_with(folder_path) { @@ -844,14 +900,17 @@ pub struct Config { impl Config { #[cfg(test)] - pub fn new_with_roots(root_uris: impl IntoIterator) -> Self { + pub fn new_with_roots(root_urls: impl IntoIterator) -> Self { + use super::urls::url_to_uri; + let mut config = Self::default(); let mut folders = vec![]; - for root_uri in root_uris { - let name = root_uri.path_segments().and_then(|s| s.last()); + for root_url in root_urls { + let root_uri = url_to_uri(&root_url).unwrap(); + let name = root_url.path_segments().and_then(|s| s.last()); let name = name.unwrap_or_default().to_string(); folders.push(( - root_uri.clone(), + root_url, lsp::WorkspaceFolder { uri: root_uri, name, @@ -1077,11 +1136,11 @@ impl Default for LspTsConfig { "module": "esnext", "moduleDetection": "force", "noEmit": true, + "noImplicitOverride": true, "resolveJsonModule": true, "strict": true, "target": "esnext", "useDefineForClassFields": true, - "useUnknownInCatchVariables": false, "jsx": "react", "jsxFactory": "React.createElement", "jsxFragmentFactory": "React.Fragment", @@ -1129,7 +1188,7 @@ pub struct ConfigData { pub lockfile: Option>, pub npmrc: Option>, pub resolver: Arc, - pub sloppy_imports_resolver: Option>, + pub sloppy_imports_resolver: Option>, pub import_map_from_settings: Option, watched_files: HashMap, } @@ -1384,11 +1443,12 @@ impl ConfigData { } } - let byonm = std::env::var("DENO_UNSTABLE_BYONM").is_ok() - || member_dir.workspace.has_unstable("byonm") - || (*DENO_FUTURE - && member_dir.workspace.package_jsons().next().is_some() - && member_dir.workspace.node_modules_dir().is_none()); + let node_modules_dir = + member_dir.workspace.node_modules_dir().unwrap_or_default(); + let byonm = match node_modules_dir { + Some(mode) => mode == NodeModulesDirMode::Manual, + None => member_dir.workspace.root_pkg_json().is_some(), + }; if byonm { lsp_log!(" Enabled 'bring your own node_modules'."); } @@ -1398,9 +1458,10 @@ impl ConfigData { // Mark the import map as a watched file if let Some(import_map_specifier) = member_dir .workspace - .to_import_map_specifier() + .to_import_map_path() .ok() .flatten() + .and_then(|path| Url::from_file_path(path).ok()) { add_watched_file( import_map_specifier.clone(), @@ -1456,17 +1517,16 @@ impl ConfigData { ConfigWatchedFileType::ImportMap, ); // spawn due to the lsp's `Send` requirement - let fetch_result = deno_core::unsync::spawn({ - let file_fetcher = file_fetcher.cloned().unwrap(); - let import_map_url = import_map_url.clone(); - async move { - file_fetcher - .fetch(&import_map_url, &PermissionsContainer::allow_all()) - .await - } - }) - .await - .unwrap(); + let fetch_result = + deno_core::unsync::spawn({ + let file_fetcher = file_fetcher.cloned().unwrap(); + let import_map_url = import_map_url.clone(); + async move { + file_fetcher.fetch_bypass_permissions(&import_map_url).await + } + }) + .await + .unwrap(); let value_result = fetch_result.and_then(|f| { serde_json::from_slice::(&f.source).map_err(|e| e.into()) @@ -1490,50 +1550,32 @@ impl ConfigData { None } }; - let resolver = deno_core::unsync::spawn({ - let workspace = member_dir.workspace.clone(); - let file_fetcher = file_fetcher.cloned(); - async move { - workspace - .create_resolver( - CreateResolverOptions { - pkg_json_dep_resolution, - specified_import_map, - }, - move |specifier| { - let specifier = specifier.clone(); - let file_fetcher = file_fetcher.clone().unwrap(); - async move { - let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await? - .into_text_decoded()?; - Ok(file.source.to_string()) - } - }, - ) - .await - .inspect_err(|err| { - lsp_warn!( - " Failed to load resolver: {}", - err // will contain the specifier - ); - }) - .ok() - } - }) - .await - .unwrap() - .unwrap_or_else(|| { - // create a dummy resolver - WorkspaceResolver::new_raw( - scope.clone(), - None, - member_dir.workspace.resolver_jsr_pkgs().collect(), - member_dir.workspace.package_jsons().cloned().collect(), - pkg_json_dep_resolution, + let resolver = member_dir + .workspace + .create_resolver( + CreateResolverOptions { + pkg_json_dep_resolution, + specified_import_map, + }, + |path| Ok(std::fs::read_to_string(path)?), ) - }); + .inspect_err(|err| { + lsp_warn!( + " Failed to load resolver: {}", + err // will contain the specifier + ); + }) + .ok() + .unwrap_or_else(|| { + // create a dummy resolver + WorkspaceResolver::new_raw( + scope.clone(), + None, + member_dir.workspace.resolver_jsr_pkgs().collect(), + member_dir.workspace.package_jsons().cloned().collect(), + pkg_json_dep_resolution, + ) + }); if !resolver.diagnostics().is_empty() { lsp_warn!( " Import map diagnostics:\n{}", @@ -1549,9 +1591,11 @@ impl ConfigData { .is_ok() || member_dir.workspace.has_unstable("sloppy-imports"); let sloppy_imports_resolver = unstable_sloppy_imports.then(|| { - Arc::new(SloppyImportsResolver::new_without_stat_cache(Arc::new( - deno_runtime::deno_fs::RealFs, - ))) + Arc::new(CliSloppyImportsResolver::new( + SloppyImportsCachedFs::new_without_stat_cache(Arc::new( + deno_runtime::deno_fs::RealFs, + )), + )) }); let resolver = Arc::new(resolver); let lint_rule_provider = LintRuleProvider::new( @@ -1677,23 +1721,28 @@ impl ConfigTree { .unwrap_or_else(|| Arc::new(FmtConfig::new_with_base(PathBuf::from("/")))) } - /// Returns (scope_uri, type). + /// Returns (scope_url, type). pub fn watched_file_type( &self, specifier: &ModuleSpecifier, ) -> Option<(&ModuleSpecifier, ConfigWatchedFileType)> { - for (scope_uri, data) in self.scopes.iter() { + for (scope_url, data) in self.scopes.iter() { if let Some(typ) = data.watched_files.get(specifier) { - return Some((scope_uri, *typ)); + return Some((scope_url, *typ)); } } None } pub fn is_watched_file(&self, specifier: &ModuleSpecifier) -> bool { - if specifier.path().ends_with("/deno.json") - || specifier.path().ends_with("/deno.jsonc") - || specifier.path().ends_with("/package.json") + let path = specifier.path(); + if path.ends_with("/deno.json") + || path.ends_with("/deno.jsonc") + || path.ends_with("/package.json") + || path.ends_with("/node_modules/.package-lock.json") + || path.ends_with("/node_modules/.yarn-integrity.json") + || path.ends_with("/node_modules/.modules.yaml") + || path.ends_with("/node_modules/.deno/.setup-cache.bin") { return true; } @@ -1703,6 +1752,46 @@ impl ConfigTree { .any(|data| data.watched_files.contains_key(specifier)) } + pub fn to_did_refresh_params( + &self, + ) -> lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams { + let data = self + .scopes + .values() + .filter_map(|data| { + let workspace_root_scope_uri = + Some(data.member_dir.workspace.root_dir()) + .filter(|s| *s != data.member_dir.dir_url()) + .and_then(|s| url_to_uri(s).ok()); + Some(lsp_custom::DenoConfigurationData { + scope_uri: url_to_uri(&data.scope).ok()?, + deno_json: data.maybe_deno_json().and_then(|c| { + if workspace_root_scope_uri.is_some() + && Some(&c.specifier) + == data + .member_dir + .workspace + .root_deno_json() + .map(|c| &c.specifier) + { + return None; + } + Some(lsp::TextDocumentIdentifier { + uri: url_to_uri(&c.specifier).ok()?, + }) + }), + package_json: data.maybe_pkg_json().and_then(|p| { + Some(lsp::TextDocumentIdentifier { + uri: url_to_uri(&p.specifier()).ok()?, + }) + }), + workspace_root_scope_uri, + }) + }) + .collect(); + lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams { data } + } + pub async fn refresh( &mut self, settings: &Settings, @@ -1727,7 +1816,7 @@ impl ConfigTree { let config_file_path = (|| { let config_setting = ws_settings.config.as_ref()?; let config_uri = folder_uri.join(config_setting).ok()?; - specifier_to_file_path(&config_uri).ok() + url_to_file_path(&config_uri).ok() })(); if config_file_path.is_some() || ws_settings.import_map.is_some() { scopes.insert( @@ -1804,7 +1893,7 @@ impl ConfigTree { let scope = config_file.specifier.join(".").unwrap(); let json_text = serde_json::to_string(&config_file.json).unwrap(); let test_fs = deno_runtime::deno_fs::InMemoryFs::default(); - let config_path = specifier_to_file_path(&config_file.specifier).unwrap(); + let config_path = url_to_file_path(&config_file.specifier).unwrap(); test_fs.setup_text_files(vec![( config_path.to_string_lossy().to_string(), json_text, @@ -1862,13 +1951,17 @@ fn resolve_node_modules_dir( // `nodeModulesDir: true` setting in the deno.json file. This is to // reduce the chance of modifying someone's node_modules directory // without them having asked us to do so. - let explicitly_disabled = workspace.node_modules_dir() == Some(false); + let node_modules_mode = workspace.node_modules_dir().ok().flatten(); + let explicitly_disabled = node_modules_mode == Some(NodeModulesDirMode::None); if explicitly_disabled { return None; } let enabled = byonm - || workspace.node_modules_dir() == Some(true) + || node_modules_mode + .map(|m| m.uses_node_modules_dir()) + .unwrap_or(false) || workspace.vendor_dir_path().is_some(); + if !enabled { return None; } @@ -1884,7 +1977,11 @@ fn resolve_lockfile_from_path( lockfile_path: PathBuf, frozen: bool, ) -> Option { - match CliLockfile::read_from_path(lockfile_path, frozen) { + match CliLockfile::read_from_path(CliLockfileReadFromPathOptions { + file_path: lockfile_path, + frozen, + skip_write: false, + }) { Ok(value) => { if value.filename.exists() { if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename) @@ -2129,7 +2226,7 @@ mod tests { }, tls_certificate: None, unsafely_ignore_certificate_errors: None, - unstable: false, + unstable: Default::default(), javascript: LanguageWorkspaceSettings { inlay_hints: InlayHintsSettings { parameter_names: InlayHintsParamNamesOptions { @@ -2157,6 +2254,7 @@ mod tests { auto_import_file_exclude_patterns: vec![], use_aliases_for_renames: true, quote_style: QuoteStyle::Auto, + prefer_type_only_auto_imports: false, }, suggest: CompletionSettings { complete_function_calls: false, @@ -2202,6 +2300,7 @@ mod tests { auto_import_file_exclude_patterns: vec![], use_aliases_for_renames: true, quote_style: QuoteStyle::Auto, + prefer_type_only_auto_imports: false, }, suggest: CompletionSettings { complete_function_calls: false, diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index a8faee1a85..83c00d27ed 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -12,14 +12,15 @@ use super::language_server::StateSnapshot; use super::performance::Performance; use super::tsc; use super::tsc::TsServer; -use super::urls::LspClientUrl; +use super::urls::uri_parse_unencoded; +use super::urls::url_to_uri; use super::urls::LspUrlMap; use crate::graph_util; use crate::graph_util::enhanced_resolution_error_message; use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams; -use crate::resolver::SloppyImportsResolution; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; +use crate::resolver::SloppyImportsCachedFs; use crate::tools::lint::CliLinter; use crate::tools::lint::CliLinterOptions; use crate::tools::lint::LintRuleProvider; @@ -37,12 +38,14 @@ use deno_core::serde_json::json; use deno_core::unsync::spawn; use deno_core::unsync::spawn_blocking; use deno_core::unsync::JoinHandle; +use deno_core::url::Url; use deno_core::ModuleSpecifier; -use deno_graph::source::ResolutionMode; use deno_graph::source::ResolveError; use deno_graph::Resolution; use deno_graph::ResolutionError; use deno_graph::SpecifierError; +use deno_resolver::sloppy_imports::SloppyImportsResolution; +use deno_resolver::sloppy_imports::SloppyImportsResolutionMode; use deno_runtime::deno_fs; use deno_runtime::deno_node; use deno_runtime::tokio_util::create_basic_runtime; @@ -160,15 +163,14 @@ impl DiagnosticsPublisher { .state .update(&record.specifier, version, &all_specifier_diagnostics); let file_referrer = documents.get_file_referrer(&record.specifier); + let Ok(uri) = + url_map.specifier_to_uri(&record.specifier, file_referrer.as_deref()) + else { + continue; + }; self .client - .publish_diagnostics( - url_map - .normalize_specifier(&record.specifier, file_referrer.as_deref()) - .unwrap_or(LspClientUrl::new(record.specifier)), - all_specifier_diagnostics, - version, - ) + .publish_diagnostics(uri, all_specifier_diagnostics, version) .await; messages_sent += 1; } @@ -191,15 +193,14 @@ impl DiagnosticsPublisher { // clear out any diagnostics for this specifier self.state.update(specifier, removed_value.version, &[]); let file_referrer = documents.get_file_referrer(specifier); + let Ok(uri) = + url_map.specifier_to_uri(specifier, file_referrer.as_deref()) + else { + continue; + }; self .client - .publish_diagnostics( - url_map - .normalize_specifier(specifier, file_referrer.as_deref()) - .unwrap_or_else(|_| LspClientUrl::new(specifier.clone())), - Vec::new(), - removed_value.version, - ) + .publish_diagnostics(uri, Vec::new(), removed_value.version) .await; messages_sent += 1; } @@ -337,9 +338,9 @@ impl DiagnosticsState { if diagnostic.code == Some(lsp::NumberOrString::String("no-cache".to_string())) || diagnostic.code - == Some(lsp::NumberOrString::String("no-cache-jsr".to_string())) + == Some(lsp::NumberOrString::String("not-installed-jsr".to_string())) || diagnostic.code - == Some(lsp::NumberOrString::String("no-cache-npm".to_string())) + == Some(lsp::NumberOrString::String("not-installed-npm".to_string())) { no_cache_diagnostics.push(diagnostic.clone()); } @@ -737,7 +738,7 @@ fn to_lsp_related_information( if let (Some(file_name), Some(start), Some(end)) = (&ri.file_name, &ri.start, &ri.end) { - let uri = lsp::Url::parse(file_name).unwrap(); + let uri = uri_parse_unencoded(file_name).unwrap(); Some(lsp::DiagnosticRelatedInformation { location: lsp::Location { uri, @@ -991,9 +992,9 @@ pub enum DenoDiagnostic { /// A remote module was not found in the cache. NoCache(ModuleSpecifier), /// A remote jsr package reference was not found in the cache. - NoCacheJsr(PackageReq, ModuleSpecifier), + NotInstalledJsr(PackageReq, ModuleSpecifier), /// A remote npm package reference was not found in the cache. - NoCacheNpm(PackageReq, ModuleSpecifier), + NotInstalledNpm(PackageReq, ModuleSpecifier), /// A local module was not found on the local file system. NoLocal(ModuleSpecifier), /// The specifier resolved to a remote specifier that was redirected to @@ -1018,8 +1019,8 @@ impl DenoDiagnostic { Self::InvalidAttributeType(_) => "invalid-attribute-type", Self::NoAttributeType => "no-attribute-type", Self::NoCache(_) => "no-cache", - Self::NoCacheJsr(_, _) => "no-cache-jsr", - Self::NoCacheNpm(_, _) => "no-cache-npm", + Self::NotInstalledJsr(_, _) => "not-installed-jsr", + Self::NotInstalledNpm(_, _) => "not-installed-npm", Self::NoLocal(_) => "no-local", Self::Redirect { .. } => "redirect", Self::ResolutionError(err) => { @@ -1070,7 +1071,7 @@ impl DenoDiagnostic { diagnostics: Some(vec![diagnostic.clone()]), edit: Some(lsp::WorkspaceEdit { changes: Some(HashMap::from([( - specifier.clone(), + url_to_uri(specifier)?, vec![lsp::TextEdit { new_text: format!("\"{to}\""), range: diagnostic.range, @@ -1087,7 +1088,7 @@ impl DenoDiagnostic { diagnostics: Some(vec![diagnostic.clone()]), edit: Some(lsp::WorkspaceEdit { changes: Some(HashMap::from([( - specifier.clone(), + url_to_uri(specifier)?, vec![lsp::TextEdit { new_text: " with { type: \"json\" }".to_string(), range: lsp::Range { @@ -1100,17 +1101,22 @@ impl DenoDiagnostic { }), ..Default::default() }, - "no-cache" | "no-cache-jsr" | "no-cache-npm" => { + "no-cache" | "not-installed-jsr" | "not-installed-npm" => { let data = diagnostic .data .clone() .ok_or_else(|| anyhow!("Diagnostic is missing data"))?; let data: DiagnosticDataSpecifier = serde_json::from_value(data)?; + let title = if matches!( + code.as_str(), + "not-installed-jsr" | "not-installed-npm" + ) { + format!("Install \"{}\" and its dependencies.", data.specifier) + } else { + format!("Cache \"{}\" and its dependencies.", data.specifier) + }; lsp::CodeAction { - title: format!( - "Cache \"{}\" and its dependencies.", - data.specifier - ), + title, kind: Some(lsp::CodeActionKind::QUICKFIX), diagnostics: Some(vec![diagnostic.clone()]), command: Some(lsp::Command { @@ -1133,7 +1139,7 @@ impl DenoDiagnostic { diagnostics: Some(vec![diagnostic.clone()]), edit: Some(lsp::WorkspaceEdit { changes: Some(HashMap::from([( - specifier.clone(), + url_to_uri(specifier)?, vec![lsp::TextEdit { new_text: format!( "\"{}\"", @@ -1159,7 +1165,7 @@ impl DenoDiagnostic { diagnostics: Some(vec![diagnostic.clone()]), edit: Some(lsp::WorkspaceEdit { changes: Some(HashMap::from([( - specifier.clone(), + url_to_uri(specifier)?, vec![lsp::TextEdit { new_text: format!( "\"{}\"", @@ -1185,7 +1191,7 @@ impl DenoDiagnostic { diagnostics: Some(vec![diagnostic.clone()]), edit: Some(lsp::WorkspaceEdit { changes: Some(HashMap::from([( - specifier.clone(), + url_to_uri(specifier)?, vec![lsp::TextEdit { new_text: format!("\"node:{}\"", data.specifier), range: diagnostic.range, @@ -1216,8 +1222,8 @@ impl DenoDiagnostic { match code.as_str() { "import-map-remap" | "no-cache" - | "no-cache-jsr" - | "no-cache-npm" + | "not-installed-jsr" + | "not-installed-npm" | "no-attribute-type" | "redirect" | "import-node-prefix-missing" => true, @@ -1255,10 +1261,12 @@ impl DenoDiagnostic { Self::InvalidAttributeType(assert_type) => (lsp::DiagnosticSeverity::ERROR, format!("The module is a JSON module and expected an attribute type of \"json\". Instead got \"{assert_type}\"."), None), Self::NoAttributeType => (lsp::DiagnosticSeverity::ERROR, "The module is a JSON module and not being imported with an import attribute. Consider adding `with { type: \"json\" }` to the import statement.".to_string(), None), Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: {specifier}"), Some(json!({ "specifier": specifier }))), - Self::NoCacheJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing jsr package: {}", pkg_req), Some(json!({ "specifier": specifier }))), - Self::NoCacheNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: {}", pkg_req), Some(json!({ "specifier": specifier }))), + Self::NotInstalledJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("JSR package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))), + Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("NPM package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))), Self::NoLocal(specifier) => { - let maybe_sloppy_resolution = SloppyImportsResolver::new(Arc::new(deno_fs::RealFs)).resolve(specifier, ResolutionMode::Execution); + let maybe_sloppy_resolution = CliSloppyImportsResolver::new( + SloppyImportsCachedFs::new(Arc::new(deno_fs::RealFs)) + ).resolve(specifier, SloppyImportsResolutionMode::Execution); let data = maybe_sloppy_resolution.as_ref().map(|res| { json!({ "specifier": specifier, @@ -1303,10 +1311,7 @@ impl DenoDiagnostic { } } -fn specifier_text_for_redirected( - redirect: &lsp::Url, - referrer: &lsp::Url, -) -> String { +fn specifier_text_for_redirected(redirect: &Url, referrer: &Url) -> String { if redirect.scheme() == "file" && referrer.scheme() == "file" { // use a relative specifier when it's going to a file url relative_specifier(redirect, referrer) @@ -1315,7 +1320,7 @@ fn specifier_text_for_redirected( } } -fn relative_specifier(specifier: &lsp::Url, referrer: &lsp::Url) -> String { +fn relative_specifier(specifier: &Url, referrer: &Url) -> String { match referrer.make_relative(specifier) { Some(relative) => { if relative.starts_with('.') { @@ -1410,7 +1415,8 @@ fn diagnose_resolution( JsrPackageReqReference::from_specifier(specifier) { let req = pkg_ref.into_inner().req; - diagnostics.push(DenoDiagnostic::NoCacheJsr(req, specifier.clone())); + diagnostics + .push(DenoDiagnostic::NotInstalledJsr(req, specifier.clone())); } else if let Ok(pkg_ref) = NpmPackageReqReference::from_specifier(specifier) { @@ -1419,7 +1425,7 @@ fn diagnose_resolution( let req = pkg_ref.into_inner().req; if !npm_resolver.is_pkg_req_folder_cached(&req) { diagnostics - .push(DenoDiagnostic::NoCacheNpm(req, specifier.clone())); + .push(DenoDiagnostic::NotInstalledNpm(req, specifier.clone())); } } } else if let Some(module_name) = specifier.as_str().strip_prefix("node:") @@ -1445,7 +1451,7 @@ fn diagnose_resolution( // check that a @types/node package exists in the resolver let types_node_req = PackageReq::from_str("@types/node").unwrap(); if !npm_resolver.is_pkg_req_folder_cached(&types_node_req) { - diagnostics.push(DenoDiagnostic::NoCacheNpm( + diagnostics.push(DenoDiagnostic::NotInstalledNpm( types_node_req, ModuleSpecifier::parse("npm:@types/node").unwrap(), )); @@ -1493,7 +1499,11 @@ fn diagnose_dependency( .data_for_specifier(referrer_doc.file_referrer().unwrap_or(referrer)) .and_then(|d| d.resolver.maybe_import_map()); if let Some(import_map) = import_map { - if let Resolution::Ok(resolved) = &dependency.maybe_code { + let resolved = dependency + .maybe_code + .ok() + .or_else(|| dependency.maybe_type.ok()); + if let Some(resolved) = resolved { if let Some(to) = import_map.lookup(&resolved.specifier, referrer) { if dependency_key != to { diagnostics.push( @@ -1511,17 +1521,19 @@ fn diagnose_dependency( let import_ranges: Vec<_> = dependency .imports .iter() - .map(|i| documents::to_lsp_range(&i.range)) + .map(|i| documents::to_lsp_range(&i.specifier_range)) .collect(); // TODO(nayeemrmn): This is a crude way of detecting `@deno-types` which has // a different specifier and therefore needs a separate call to // `diagnose_resolution()`. It would be much cleaner if that were modelled as // a separate dependency: https://github.com/denoland/deno_graph/issues/247. let is_types_deno_types = !dependency.maybe_type.is_none() - && !dependency - .imports - .iter() - .any(|i| dependency.maybe_type.includes(&i.range.start).is_some()); + && !dependency.imports.iter().any(|i| { + dependency + .maybe_type + .includes(&i.specifier_range.start) + .is_some() + }); diagnostics.extend( diagnose_resolution( @@ -1634,7 +1646,8 @@ mod tests { use test_util::TempDir; fn mock_config() -> Config { - let root_uri = resolve_url("file:///").unwrap(); + let root_url = resolve_url("file:///").unwrap(); + let root_uri = url_to_uri(&root_url).unwrap(); Config { settings: Arc::new(Settings { unscoped: Arc::new(WorkspaceSettings { @@ -1645,7 +1658,7 @@ mod tests { ..Default::default() }), workspace_folders: Arc::new(vec![( - root_uri.clone(), + root_url, lsp::WorkspaceFolder { uri: root_uri, name: "".to_string(), @@ -1660,7 +1673,7 @@ mod tests { maybe_import_map: Option<(&str, &str)>, ) -> (TempDir, StateSnapshot) { let temp_dir = TempDir::new(); - let root_uri = temp_dir.uri(); + let root_uri = temp_dir.url(); let cache = LspCache::new(Some(root_uri.join(".deno_dir").unwrap())); let mut config = Config::new_with_roots([root_uri.clone()]); if let Some((relative_path, json_string)) = maybe_import_map { @@ -1827,7 +1840,7 @@ let c: number = "a"; assert_eq!(actual.len(), 2); for record in actual { let relative_specifier = - temp_dir.uri().make_relative(&record.specifier).unwrap(); + temp_dir.url().make_relative(&record.specifier).unwrap(); match relative_specifier.as_str() { "std/assert/mod.ts" => { assert_eq!(json!(record.versioned.diagnostics), json!([])) @@ -2046,7 +2059,7 @@ let c: number = "a"; "source": "deno", "message": format!( "Unable to load a local module: {}🦕.ts\nPlease check the file path.", - temp_dir.uri(), + temp_dir.url(), ), } ]) diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index e91cfe0ac2..7d1ca6810d 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -2,7 +2,6 @@ use super::cache::calculate_fs_version; use super::cache::LspCache; -use super::cache::LSP_DISALLOW_GLOBAL_TO_LOCAL_COPY; use super::config::Config; use super::resolver::LspResolver; use super::testing::TestCollector; @@ -12,7 +11,6 @@ use super::tsc; use super::tsc::AssetDocument; use crate::graph_util::CliJsrUrlProvider; -use deno_runtime::fs_util::specifier_to_file_path; use dashmap::DashMap; use deno_ast::swc::visit::VisitWith; @@ -28,6 +26,7 @@ use deno_core::parking_lot::Mutex; use deno_core::ModuleSpecifier; use deno_graph::source::ResolutionMode; use deno_graph::Resolution; +use deno_path_util::url_to_file_path; use deno_runtime::deno_node; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::npm::NpmPackageReqReference; @@ -61,6 +60,9 @@ pub enum LanguageId { Json, JsonC, Markdown, + Html, + Css, + Yaml, Unknown, } @@ -74,6 +76,9 @@ impl LanguageId { LanguageId::Json => Some("json"), LanguageId::JsonC => Some("jsonc"), LanguageId::Markdown => Some("md"), + LanguageId::Html => Some("html"), + LanguageId::Css => Some("css"), + LanguageId::Yaml => Some("yaml"), LanguageId::Unknown => None, } } @@ -86,6 +91,9 @@ impl LanguageId { LanguageId::Tsx => Some("text/tsx"), LanguageId::Json | LanguageId::JsonC => Some("application/json"), LanguageId::Markdown => Some("text/markdown"), + LanguageId::Html => Some("text/html"), + LanguageId::Css => Some("text/css"), + LanguageId::Yaml => Some("application/yaml"), LanguageId::Unknown => None, } } @@ -110,6 +118,9 @@ impl FromStr for LanguageId { "json" => Ok(Self::Json), "jsonc" => Ok(Self::JsonC), "markdown" => Ok(Self::Markdown), + "html" => Ok(Self::Html), + "css" => Ok(Self::Css), + "yaml" => Ok(Self::Yaml), _ => Ok(Self::Unknown), } } @@ -838,7 +849,7 @@ impl FileSystemDocuments { file_referrer: Option<&ModuleSpecifier>, ) -> Option> { let doc = if specifier.scheme() == "file" { - let path = specifier_to_file_path(specifier).ok()?; + let path = url_to_file_path(specifier).ok()?; let bytes = fs::read(path).ok()?; let content = deno_graph::source::decode_owned_source(specifier, bytes, None).ok()?; @@ -872,22 +883,19 @@ impl FileSystemDocuments { } else { let http_cache = cache.for_specifier(file_referrer); let cache_key = http_cache.cache_item_key(specifier).ok()?; - let bytes = http_cache - .read_file_bytes(&cache_key, None, LSP_DISALLOW_GLOBAL_TO_LOCAL_COPY) - .ok()??; - let specifier_headers = http_cache.read_headers(&cache_key).ok()??; + let cached_file = http_cache.get(&cache_key, None).ok()??; let (_, maybe_charset) = deno_graph::source::resolve_media_type_and_charset_from_headers( specifier, - Some(&specifier_headers), + Some(&cached_file.metadata.headers), ); let content = deno_graph::source::decode_owned_source( specifier, - bytes, + cached_file.content, maybe_charset, ) .ok()?; - let maybe_headers = Some(specifier_headers); + let maybe_headers = Some(cached_file.metadata.headers); Document::new( specifier.clone(), content.into(), @@ -1128,7 +1136,7 @@ impl Documents { return true; } if specifier.scheme() == "file" { - return specifier_to_file_path(&specifier) + return url_to_file_path(&specifier) .map(|p| p.is_file()) .unwrap_or(false); } @@ -1243,7 +1251,7 @@ impl Documents { /// tsc when type checking. pub fn resolve( &self, - specifiers: &[String], + raw_specifiers: &[String], referrer: &ModuleSpecifier, file_referrer: Option<&ModuleSpecifier>, ) -> Vec> { @@ -1254,16 +1262,16 @@ impl Documents { .or(file_referrer); let dependencies = document.as_ref().map(|d| d.dependencies()); let mut results = Vec::new(); - for specifier in specifiers { - if specifier.starts_with("asset:") { - if let Ok(specifier) = ModuleSpecifier::parse(specifier) { + for raw_specifier in raw_specifiers { + if raw_specifier.starts_with("asset:") { + if let Ok(specifier) = ModuleSpecifier::parse(raw_specifier) { let media_type = MediaType::from_specifier(&specifier); results.push(Some((specifier, media_type))); } else { results.push(None); } } else if let Some(dep) = - dependencies.as_ref().and_then(|d| d.get(specifier)) + dependencies.as_ref().and_then(|d| d.get(raw_specifier)) { if let Some(specifier) = dep.maybe_type.maybe_specifier() { results.push(self.resolve_dependency( @@ -1282,7 +1290,7 @@ impl Documents { } } else if let Ok(specifier) = self.resolver.as_graph_resolver(file_referrer).resolve( - specifier, + raw_specifier, &deno_graph::Range { specifier: referrer.clone(), start: deno_graph::Position::zeroed(), @@ -1317,7 +1325,7 @@ impl Documents { let fs_docs = &self.file_system_docs; // Clean up non-existent documents. fs_docs.docs.retain(|specifier, _| { - let Ok(path) = specifier_to_file_path(specifier) else { + let Ok(path) = url_to_file_path(specifier) else { // Remove non-file schemed docs (deps). They may not be dependencies // anymore after updating resolvers. return false; @@ -1414,11 +1422,9 @@ impl Documents { if let Some(lockfile) = config_data.lockfile.as_ref() { let reqs = npm_reqs_by_scope.entry(Some(scope.clone())).or_default(); let lockfile = lockfile.lock(); - for key in lockfile.content.packages.specifiers.keys() { - if let Some(key) = key.strip_prefix("npm:") { - if let Ok(req) = PackageReq::from_str(key) { - reqs.insert(req); - } + for dep_req in lockfile.content.packages.specifiers.keys() { + if dep_req.kind == deno_semver::package::PackageKind::Npm { + reqs.insert(dep_req.req.clone()); } } } @@ -1518,12 +1524,16 @@ impl<'a> deno_graph::source::Loader for OpenDocumentsGraphLoader<'a> { fn cache_module_info( &self, specifier: &deno_ast::ModuleSpecifier, + media_type: MediaType, source: &Arc<[u8]>, module_info: &deno_graph::ModuleInfo, ) { - self - .inner_loader - .cache_module_info(specifier, source, module_info) + self.inner_loader.cache_module_info( + specifier, + media_type, + source, + module_info, + ) } } @@ -1607,7 +1617,7 @@ mod tests { async fn setup() -> (Documents, LspCache, TempDir) { let temp_dir = TempDir::new(); temp_dir.create_dir_all(".deno_dir"); - let cache = LspCache::new(Some(temp_dir.uri().join(".deno_dir").unwrap())); + let cache = LspCache::new(Some(temp_dir.url().join(".deno_dir").unwrap())); let config = Config::default(); let resolver = Arc::new(LspResolver::from_config(&config, &cache, None).await); @@ -1690,7 +1700,7 @@ console.log(b, "hello deno"); // but we'll guard against it anyway let (mut documents, _, temp_dir) = setup().await; let file_path = temp_dir.path().join("file.ts"); - let file_specifier = temp_dir.uri().join("file.ts").unwrap(); + let file_specifier = temp_dir.url().join("file.ts").unwrap(); file_path.write(""); // open the document @@ -1718,18 +1728,18 @@ console.log(b, "hello deno"); let (mut documents, cache, temp_dir) = setup().await; let file1_path = temp_dir.path().join("file1.ts"); - let file1_specifier = temp_dir.uri().join("file1.ts").unwrap(); + let file1_specifier = temp_dir.url().join("file1.ts").unwrap(); fs::write(&file1_path, "").unwrap(); let file2_path = temp_dir.path().join("file2.ts"); - let file2_specifier = temp_dir.uri().join("file2.ts").unwrap(); + let file2_specifier = temp_dir.url().join("file2.ts").unwrap(); fs::write(&file2_path, "").unwrap(); let file3_path = temp_dir.path().join("file3.ts"); - let file3_specifier = temp_dir.uri().join("file3.ts").unwrap(); + let file3_specifier = temp_dir.url().join("file3.ts").unwrap(); fs::write(&file3_path, "").unwrap(); - let mut config = Config::new_with_roots([temp_dir.uri()]); + let mut config = Config::new_with_roots([temp_dir.url()]); let workspace_settings = serde_json::from_str(r#"{ "enable": true }"#).unwrap(); config.set_workspace_settings(workspace_settings, vec![]); diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index 9ffcdf9e61..9a738ec287 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -14,7 +14,6 @@ use deno_graph::packages::JsrPackageInfo; use deno_graph::packages::JsrPackageInfoVersion; use deno_graph::packages::JsrPackageVersionInfo; use deno_graph::ModuleSpecifier; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; @@ -92,20 +91,23 @@ impl JsrCacheResolver { } } if let Some(lockfile) = config_data.and_then(|d| d.lockfile.as_ref()) { - for (req_url, nv_url) in &lockfile.lock().content.packages.specifiers { - let Some(req) = req_url.strip_prefix("jsr:") else { + for (dep_req, version) in &lockfile.lock().content.packages.specifiers { + let req = match dep_req.kind { + deno_semver::package::PackageKind::Jsr => &dep_req.req, + deno_semver::package::PackageKind::Npm => { + continue; + } + }; + let Ok(version) = Version::parse_standard(version) else { continue; }; - let Some(nv) = nv_url.strip_prefix("jsr:") else { - continue; - }; - let Ok(req) = PackageReq::from_str(req) else { - continue; - }; - let Ok(nv) = PackageNv::from_str(nv) else { - continue; - }; - nv_by_req.insert(req, Some(nv)); + nv_by_req.insert( + req.clone(), + Some(PackageNv { + name: req.name.clone(), + version, + }), + ); } } Self { @@ -258,12 +260,9 @@ fn read_cached_url( cache: &Arc, ) -> Option> { cache - .read_file_bytes( - &cache.cache_item_key(url).ok()?, - None, - deno_cache_dir::GlobalToLocalCopy::Disallow, - ) + .get(&cache.cache_item_key(url).ok()?, None) .ok()? + .map(|f| f.content) } #[derive(Debug)] @@ -311,7 +310,7 @@ impl PackageSearchApi for CliJsrSearchApi { // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&search_url) .await? .into_text_decoded() }) diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index ff3a7f0c68..33ae539f85 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use base64::Engine; use deno_ast::MediaType; use deno_config::workspace::WorkspaceDirectory; use deno_config::workspace::WorkspaceDiscoverOptions; @@ -12,9 +11,11 @@ use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::unsync::spawn; use deno_core::url; +use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::GraphKind; use deno_graph::Resolution; +use deno_path_util::url_to_file_path; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; use deno_semver::jsr::JsrPackageReqReference; @@ -31,6 +32,7 @@ use std::collections::VecDeque; use std::env; use std::fmt::Write as _; use std::path::PathBuf; +use std::str::FromStr; use std::sync::Arc; use tokio::sync::mpsc::unbounded_channel; use tokio::sync::mpsc::UnboundedReceiver; @@ -85,6 +87,8 @@ use super::tsc::ChangeKind; use super::tsc::GetCompletionDetailsArgs; use super::tsc::TsServer; use super::urls; +use super::urls::uri_to_url; +use super::urls::url_to_uri; use crate::args::create_default_npmrc; use crate::args::get_root_cert_store; use crate::args::has_flag_env_var; @@ -92,6 +96,7 @@ use crate::args::CaData; use crate::args::CacheSetting; use crate::args::CliOptions; use crate::args::Flags; +use crate::args::InternalFlags; use crate::args::UnstableFmtOptions; use crate::factory::CliFactory; use crate::file_fetcher::FileFetcher; @@ -109,7 +114,6 @@ use crate::util::fs::remove_dir_all_if_exists; use crate::util::path::is_importable_ext; use crate::util::path::to_percent_decoded_str; use crate::util::sync::AsyncFlag; -use deno_runtime::fs_util::specifier_to_file_path; struct LspRootCertStoreProvider(RootCertStore); @@ -204,11 +208,11 @@ pub struct Inner { module_registry: ModuleRegistry, /// A lazily create "server" for handling test run requests. maybe_testing_server: Option, - npm_search_api: CliNpmSearchApi, + pub npm_search_api: CliNpmSearchApi, project_version: usize, /// A collection of measurements which instrument that performance of the LSP. performance: Arc, - resolver: Arc, + pub resolver: Arc, task_queue: LanguageServerTaskQueue, /// A memoized version of fixable diagnostic codes retrieved from TypeScript. ts_fixable_diagnostics: Vec, @@ -237,7 +241,7 @@ impl LanguageServer { } } - /// Similar to `deno cache` on the command line, where modules will be cached + /// Similar to `deno install --entrypoint` on the command line, where modules will be cached /// in the Deno cache, including any of their dependencies. pub async fn cache( &self, @@ -271,10 +275,9 @@ impl LanguageServer { factory.fs(), &roots, graph_util::GraphValidOptions { - is_vendoring: false, - follow_type_only: true, + kind: GraphKind::All, check_js: false, - exit_lockfile_errors: false, + exit_integrity_errors: false, }, )?; @@ -624,7 +627,7 @@ impl Inner { let maybe_root_path = self .config .root_uri() - .and_then(|uri| specifier_to_file_path(uri).ok()); + .and_then(|uri| url_to_file_path(uri).ok()); let root_cert_store = get_root_cert_store( maybe_root_path, workspace_settings.certificate_stores.clone(), @@ -720,7 +723,9 @@ impl Inner { .into_iter() .map(|folder| { ( - self.url_map.normalize_url(&folder.uri, LspUrlKind::Folder), + self + .url_map + .uri_to_specifier(&folder.uri, LspUrlKind::Folder), folder, ) }) @@ -728,14 +733,17 @@ impl Inner { } // rootUri is deprecated by the LSP spec. If it's specified, merge it into // workspace_folders. + #[allow(deprecated)] if let Some(root_uri) = params.root_uri { if !workspace_folders.iter().any(|(_, f)| f.uri == root_uri) { - let name = root_uri.path_segments().and_then(|s| s.last()); + let root_url = + self.url_map.uri_to_specifier(&root_uri, LspUrlKind::Folder); + let name = root_url.path_segments().and_then(|s| s.last()); let name = name.unwrap_or_default().to_string(); workspace_folders.insert( 0, ( - self.url_map.normalize_url(&root_uri, LspUrlKind::Folder), + root_url, WorkspaceFolder { uri: root_uri, name, @@ -795,7 +803,7 @@ impl Inner { let mut roots = config .workspace_folders .iter() - .filter_map(|p| specifier_to_file_path(&p.0).ok()) + .filter_map(|p| url_to_file_path(&p.0).ok()) .collect::>(); roots.sort(); let roots = roots @@ -955,32 +963,43 @@ impl Inner { .tree .refresh(&self.config.settings, &self.workspace_files, &file_fetcher) .await; + self + .client + .send_did_refresh_deno_configuration_tree_notification( + self.config.tree.to_did_refresh_params(), + ); for config_file in self.config.tree.config_files() { - if let Ok((compiler_options, _)) = config_file.to_compiler_options() { - if let Some(compiler_options_obj) = compiler_options.as_object() { - if let Some(jsx_import_source) = - compiler_options_obj.get("jsxImportSource") - { - if let Some(jsx_import_source) = jsx_import_source.as_str() { - let specifiers = vec![Url::parse(&format!( - "data:application/typescript;base64,{}", - base64::engine::general_purpose::STANDARD - .encode(format!("import '{jsx_import_source}/jsx-runtime';")) - )) - .unwrap()]; - let referrer = config_file.specifier.clone(); - self.task_queue.queue_task(Box::new(|ls: LanguageServer| { - spawn(async move { - if let Err(err) = ls.cache(specifiers, referrer, false).await - { - lsp_warn!("{:#}", err); - } - }); - })); + (|| { + let compiler_options = config_file.to_compiler_options().ok()?.options; + let jsx_import_source = compiler_options.get("jsxImportSource")?; + let jsx_import_source = jsx_import_source.as_str()?.to_string(); + let referrer = config_file.specifier.clone(); + let specifier = format!("{jsx_import_source}/jsx-runtime"); + self.task_queue.queue_task(Box::new(|ls: LanguageServer| { + spawn(async move { + let specifier = { + let inner = ls.inner.read().await; + let resolver = inner.resolver.as_graph_resolver(Some(&referrer)); + let Ok(specifier) = resolver.resolve( + &specifier, + &deno_graph::Range { + specifier: referrer.clone(), + start: deno_graph::Position::zeroed(), + end: deno_graph::Position::zeroed(), + }, + deno_graph::source::ResolutionMode::Types, + ) else { + return; + }; + specifier + }; + if let Err(err) = ls.cache(vec![specifier], referrer, false).await { + lsp_warn!("{:#}", err); } - } - } - } + }); + })); + Some(()) + })(); } } @@ -1012,7 +1031,10 @@ impl Inner { async fn did_open(&mut self, params: DidOpenTextDocumentParams) { let mark = self.performance.mark_with_args("lsp.did_open", ¶ms); - if params.text_document.uri.scheme() == "deno" { + let Some(scheme) = params.text_document.uri.scheme() else { + return; + }; + if scheme.as_str() == "deno" { // we can ignore virtual text documents opening, as they don't need to // be tracked in memory, as they are static assets that won't change // already managed by the language service @@ -1031,16 +1053,14 @@ impl Inner { lsp_warn!( "Unsupported language id \"{}\" received for document \"{}\".", params.text_document.language_id, - params.text_document.uri + params.text_document.uri.as_str() ); } - let file_referrer = (self - .documents - .is_valid_file_referrer(¶ms.text_document.uri)) - .then(|| params.text_document.uri.clone()); + let file_referrer = Some(uri_to_url(¶ms.text_document.uri)) + .filter(|s| self.documents.is_valid_file_referrer(s)); let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); let document = self.documents.open( specifier.clone(), params.text_document.version, @@ -1062,7 +1082,7 @@ impl Inner { let mark = self.performance.mark_with_args("lsp.did_change", ¶ms); let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); match self.documents.change( &specifier, params.text_document.version, @@ -1099,7 +1119,7 @@ impl Inner { let _mark = self.performance.measure_scope("lsp.did_save"); let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); self.documents.save(&specifier); if !self .config @@ -1110,7 +1130,7 @@ impl Inner { { return; } - match specifier_to_file_path(&specifier) { + match url_to_file_path(&specifier) { Ok(path) if is_importable_ext(&path) => {} _ => return, } @@ -1134,8 +1154,10 @@ impl Inner { async fn did_close(&mut self, params: DidCloseTextDocumentParams) { let mark = self.performance.mark_with_args("lsp.did_close", ¶ms); - self.diagnostics_state.clear(¶ms.text_document.uri); - if params.text_document.uri.scheme() == "deno" { + let Some(scheme) = params.text_document.uri.scheme() else { + return; + }; + if scheme.as_str() == "deno" { // we can ignore virtual text documents closing, as they don't need to // be tracked in memory, as they are static assets that won't change // already managed by the language service @@ -1143,7 +1165,8 @@ impl Inner { } let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); + self.diagnostics_state.clear(&specifier); if self.is_diagnosable(&specifier) { self.refresh_npm_specifiers().await; self.diagnostics_server.invalidate(&[specifier.clone()]); @@ -1196,7 +1219,7 @@ impl Inner { let changes = params .changes .into_iter() - .map(|e| (self.url_map.normalize_url(&e.uri, LspUrlKind::File), e)) + .map(|e| (self.url_map.uri_to_specifier(&e.uri, LspUrlKind::File), e)) .collect::>(); if changes .iter() @@ -1215,7 +1238,7 @@ impl Inner { _ => return None, }; Some(lsp_custom::DenoConfigurationChangeEvent { - scope_uri: t.0.clone(), + scope_uri: url_to_uri(t.0).ok()?, file_uri: e.uri.clone(), typ: lsp_custom::DenoConfigurationChangeType::from_file_change_type( e.typ, @@ -1250,7 +1273,7 @@ impl Inner { _ => return None, }; Some(lsp_custom::DenoConfigurationChangeEvent { - scope_uri: t.0.clone(), + scope_uri: url_to_uri(t.0).ok()?, file_uri: e.uri.clone(), typ: lsp_custom::DenoConfigurationChangeType::from_file_change_type( e.typ, @@ -1276,7 +1299,7 @@ impl Inner { ) -> LspResult> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -1316,13 +1339,11 @@ impl Inner { &self, params: DocumentFormattingParams, ) -> LspResult>> { - let file_referrer = (self - .documents - .is_valid_file_referrer(¶ms.text_document.uri)) - .then(|| params.text_document.uri.clone()); + let file_referrer = Some(uri_to_url(¶ms.text_document.uri)) + .filter(|s| self.documents.is_valid_file_referrer(s)); let mut specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); // skip formatting any files ignored by the config file if !self .config @@ -1343,11 +1364,11 @@ impl Inner { // counterparts, but for formatting we want to favour the file URL. // TODO(nayeemrmn): Implement `Document::file_resource_path()` or similar. if specifier.scheme() != "file" - && params.text_document.uri.scheme() == "file" + && params.text_document.uri.scheme().map(|s| s.as_str()) == Some("file") { - specifier = params.text_document.uri.clone(); + specifier = uri_to_url(¶ms.text_document.uri); } - let file_path = specifier_to_file_path(&specifier).map_err(|err| { + let file_path = url_to_file_path(&specifier).map_err(|err| { error!("{:#}", err); LspError::invalid_request() })?; @@ -1369,18 +1390,9 @@ impl Inner { .data_for_specifier(&specifier) .map(|d| &d.member_dir.workspace); let unstable_options = UnstableFmtOptions { - css: maybe_workspace - .map(|w| w.has_unstable("fmt-css")) - .unwrap_or(false), - html: maybe_workspace - .map(|w| w.has_unstable("fmt-html")) - .unwrap_or(false), component: maybe_workspace .map(|w| w.has_unstable("fmt-component")) .unwrap_or(false), - yaml: maybe_workspace - .map(|w| w.has_unstable("fmt-yaml")) - .unwrap_or(false), }; let document = document.clone(); move || { @@ -1404,6 +1416,7 @@ impl Inner { document.content(), &fmt_options, &unstable_options, + None, ) } }; @@ -1437,7 +1450,7 @@ impl Inner { } async fn hover(&self, params: HoverParams) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -1570,7 +1583,7 @@ impl Inner { ) -> LspResult> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -1605,8 +1618,8 @@ impl Inner { None => false, }) .collect(); + let mut code_actions = CodeActionCollection::default(); if !fixable_diagnostics.is_empty() { - let mut code_actions = CodeActionCollection::default(); let file_diagnostics = self .diagnostics_server .get_ts_diagnostics(&specifier, asset_or_doc.document_lsp_version()); @@ -1667,9 +1680,9 @@ impl Inner { if diagnostic.code == Some(NumberOrString::String("no-cache".to_string())) || diagnostic.code - == Some(NumberOrString::String("no-cache-jsr".to_string())) + == Some(NumberOrString::String("not-installed-jsr".to_string())) || diagnostic.code - == Some(NumberOrString::String("no-cache-npm".to_string())) + == Some(NumberOrString::String("not-installed-npm".to_string())) { includes_no_cache = true; } @@ -1714,9 +1727,14 @@ impl Inner { .add_cache_all_action(&specifier, no_cache_diagnostics.to_owned()); } } - code_actions.set_preferred_fixes(); - all_actions.extend(code_actions.get_response()); } + if let Some(document) = asset_or_doc.document() { + code_actions + .add_source_actions(document, ¶ms.range, self) + .await; + } + code_actions.set_preferred_fixes(); + all_actions.extend(code_actions.get_response()); // Refactor let only = params @@ -1905,6 +1923,7 @@ impl Inner { // as the import map is an implementation detail .and_then(|d| d.resolver.maybe_import_map()), self.resolver.as_ref(), + file_referrer, ) } @@ -1914,7 +1933,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -2000,7 +2019,7 @@ impl Inner { &self, params: DocumentHighlightParams, ) -> LspResult>> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2044,7 +2063,7 @@ impl Inner { &self, params: ReferenceParams, ) -> LspResult>> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position.text_document.uri, LspUrlKind::File, ); @@ -2100,7 +2119,7 @@ impl Inner { &self, params: GotoDefinitionParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2139,7 +2158,7 @@ impl Inner { &self, params: GotoTypeDefinitionParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2185,7 +2204,7 @@ impl Inner { &self, params: CompletionParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position.text_document.uri, LspUrlKind::File, ); @@ -2374,7 +2393,7 @@ impl Inner { &self, params: GotoImplementationParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2425,7 +2444,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -2472,7 +2491,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.item.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.item.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -2501,7 +2520,7 @@ impl Inner { let maybe_root_path_owned = self .config .root_uri() - .and_then(|uri| specifier_to_file_path(uri).ok()); + .and_then(|uri| url_to_file_path(uri).ok()); let mut resolved_items = Vec::::new(); for item in incoming_calls.iter() { if let Some(resolved) = item.try_resolve_call_hierarchy_incoming_call( @@ -2521,7 +2540,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.item.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.item.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -2547,7 +2566,7 @@ impl Inner { let maybe_root_path_owned = self .config .root_uri() - .and_then(|uri| specifier_to_file_path(uri).ok()); + .and_then(|uri| url_to_file_path(uri).ok()); let mut resolved_items = Vec::::new(); for item in outgoing_calls.iter() { if let Some(resolved) = item.try_resolve_call_hierarchy_outgoing_call( @@ -2566,7 +2585,7 @@ impl Inner { &self, params: CallHierarchyPrepareParams, ) -> LspResult>> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2596,7 +2615,7 @@ impl Inner { let maybe_root_path_owned = self .config .root_uri() - .and_then(|uri| specifier_to_file_path(uri).ok()); + .and_then(|uri| url_to_file_path(uri).ok()); let mut resolved_items = Vec::::new(); match one_or_many { tsc::OneOrMany::One(item) => { @@ -2630,7 +2649,7 @@ impl Inner { &self, params: RenameParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position.text_document.uri, LspUrlKind::File, ); @@ -2679,7 +2698,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) { @@ -2717,7 +2736,7 @@ impl Inner { ) -> LspResult> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) { return Ok(None); } @@ -2770,7 +2789,7 @@ impl Inner { ) -> LspResult> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) { return Ok(None); } @@ -2819,7 +2838,7 @@ impl Inner { &self, params: SignatureHelpParams, ) -> LspResult> { - let specifier = self.url_map.normalize_url( + let specifier = self.url_map.uri_to_specifier( ¶ms.text_document_position_params.text_document.uri, LspUrlKind::File, ); @@ -2873,8 +2892,8 @@ impl Inner { ) -> LspResult> { let mut changes = vec![]; for rename in params.files { - let old_specifier = self.url_map.normalize_url( - &resolve_url(&rename.old_uri).unwrap(), + let old_specifier = self.url_map.uri_to_specifier( + &Uri::from_str(&rename.old_uri).unwrap(), LspUrlKind::File, ); let options = self @@ -2899,8 +2918,8 @@ impl Inner { .get_edits_for_file_rename( self.snapshot(), old_specifier, - self.url_map.normalize_url( - &resolve_url(&rename.new_uri).unwrap(), + self.url_map.uri_to_specifier( + &Uri::from_str(&rename.new_uri).unwrap(), LspUrlKind::File, ), format_code_settings, @@ -3498,22 +3517,29 @@ impl Inner { } let mut config_events = vec![]; - for (scope_uri, config_data) in self.config.tree.data_by_scope().iter() { + for (scope_url, config_data) in self.config.tree.data_by_scope().iter() { + let Ok(scope_uri) = url_to_uri(scope_url) else { + continue; + }; if let Some(config_file) = config_data.maybe_deno_json() { - config_events.push(lsp_custom::DenoConfigurationChangeEvent { - scope_uri: scope_uri.clone(), - file_uri: config_file.specifier.clone(), - typ: lsp_custom::DenoConfigurationChangeType::Added, - configuration_type: lsp_custom::DenoConfigurationType::DenoJson, - }); + if let Ok(file_uri) = url_to_uri(&config_file.specifier) { + config_events.push(lsp_custom::DenoConfigurationChangeEvent { + scope_uri: scope_uri.clone(), + file_uri, + typ: lsp_custom::DenoConfigurationChangeType::Added, + configuration_type: lsp_custom::DenoConfigurationType::DenoJson, + }); + } } if let Some(package_json) = config_data.maybe_pkg_json() { - config_events.push(lsp_custom::DenoConfigurationChangeEvent { - scope_uri: scope_uri.clone(), - file_uri: package_json.specifier(), - typ: lsp_custom::DenoConfigurationChangeType::Added, - configuration_type: lsp_custom::DenoConfigurationType::PackageJson, - }); + if let Ok(file_uri) = url_to_uri(&package_json.specifier()) { + config_events.push(lsp_custom::DenoConfigurationChangeEvent { + scope_uri, + file_uri, + typ: lsp_custom::DenoConfigurationChangeType::Added, + configuration_type: lsp_custom::DenoConfigurationType::PackageJson, + }); + } } } if !config_events.is_empty() { @@ -3533,19 +3559,22 @@ impl Inner { force_global_cache: bool, ) -> Result { let config_data = self.config.tree.data_for_specifier(&referrer); + let byonm = config_data.map(|d| d.byonm).unwrap_or(false); let mut roots = if !specifiers.is_empty() { specifiers } else { vec![referrer.clone()] }; - // always include the npm packages since resolution of one npm package - // might affect the resolution of other npm packages - if let Some(npm_reqs) = self + if byonm { + roots.retain(|s| s.scheme() != "npm"); + } else if let Some(npm_reqs) = self .documents .npm_reqs_by_scope() .get(&config_data.map(|d| d.scope.as_ref().clone())) { + // always include the npm packages since resolution of one npm package + // might affect the resolution of other npm packages roots.extend( npm_reqs .iter() @@ -3583,7 +3612,10 @@ impl Inner { }; let cli_options = CliOptions::new( Arc::new(Flags { - cache_path: Some(self.cache.deno_dir().root.clone()), + internal: InternalFlags { + cache_path: Some(self.cache.deno_dir().root.clone()), + ..Default::default() + }, ca_stores: workspace_settings.certificate_stores.clone(), ca_data: workspace_settings.tls_certificate.clone().map(CaData::File), unsafely_ignore_certificate_errors: workspace_settings @@ -3594,13 +3626,13 @@ impl Inner { .as_ref() .map(|url| url.to_string()) }), - node_modules_dir: Some( - config_data - .and_then(|d| d.node_modules_dir.as_ref()) - .is_some(), - ), // bit of a hack to force the lsp to cache the @types/node package type_check_mode: crate::args::TypeCheckMode::Local, + permissions: crate::args::PermissionFlags { + // allow remote import permissions in the lsp for now + allow_import: Some(vec![]), + ..Default::default() + }, ..Default::default() }), initial_cwd, @@ -3640,7 +3672,9 @@ impl Inner { .into_iter() .map(|folder| { ( - self.url_map.normalize_url(&folder.uri, LspUrlKind::Folder), + self + .url_map + .uri_to_specifier(&folder.uri, LspUrlKind::Folder), folder, ) }) @@ -3716,7 +3750,8 @@ impl Inner { result.push(TaskDefinition { name: name.clone(), command: command.to_string(), - source_uri: config_file.specifier.clone(), + source_uri: url_to_uri(&config_file.specifier) + .map_err(|_| LspError::internal_error())?, }); } }; @@ -3727,7 +3762,8 @@ impl Inner { result.push(TaskDefinition { name: name.clone(), command: command.clone(), - source_uri: package_json.specifier(), + source_uri: url_to_uri(&package_json.specifier()) + .map_err(|_| LspError::internal_error())?, }); } } @@ -3742,7 +3778,7 @@ impl Inner { ) -> LspResult>> { let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); if !self.is_diagnosable(&specifier) || !self.config.specifier_enabled(&specifier) || !self.config.enabled_inlay_hints_for_specifier(&specifier) @@ -3776,7 +3812,7 @@ impl Inner { let maybe_inlay_hints = maybe_inlay_hints.map(|hints| { hints .iter() - .map(|hint| hint.to_lsp(line_index.clone())) + .map(|hint| hint.to_lsp(line_index.clone(), self)) .collect() }); self.performance.measure(mark); @@ -3805,7 +3841,7 @@ impl Inner { .mark_with_args("lsp.virtual_text_document", ¶ms); let specifier = self .url_map - .normalize_url(¶ms.text_document.uri, LspUrlKind::File); + .uri_to_specifier(¶ms.text_document.uri, LspUrlKind::File); let contents = if specifier.scheme() == "deno" && specifier.path() == "/status.md" { @@ -3844,7 +3880,11 @@ impl Inner { "#, - serde_json::to_string_pretty(&workspace_settings).unwrap(), + serde_json::to_string_pretty(&workspace_settings) + .inspect_err(|e| { + dbg!(e); + }) + .unwrap(), documents_specifiers.len(), documents_specifiers .into_iter() @@ -3957,11 +3997,11 @@ mod tests { temp_dir.write("root4_parent/root4/main.ts", ""); // yes, enabled let mut config = Config::new_with_roots(vec![ - temp_dir.uri().join("root1/").unwrap(), - temp_dir.uri().join("root2/").unwrap(), - temp_dir.uri().join("root2/root2.1/").unwrap(), - temp_dir.uri().join("root3/").unwrap(), - temp_dir.uri().join("root4_parent/root4/").unwrap(), + temp_dir.url().join("root1/").unwrap(), + temp_dir.url().join("root2/").unwrap(), + temp_dir.url().join("root2/root2.1/").unwrap(), + temp_dir.url().join("root3/").unwrap(), + temp_dir.url().join("root4_parent/root4/").unwrap(), ]); config.set_client_capabilities(ClientCapabilities { workspace: Some(Default::default()), @@ -3971,14 +4011,14 @@ mod tests { Default::default(), vec![ ( - temp_dir.uri().join("root1/").unwrap(), + temp_dir.url().join("root1/").unwrap(), WorkspaceSettings { enable: Some(true), ..Default::default() }, ), ( - temp_dir.uri().join("root2/").unwrap(), + temp_dir.url().join("root2/").unwrap(), WorkspaceSettings { enable: Some(true), enable_paths: Some(vec![ @@ -3990,21 +4030,21 @@ mod tests { }, ), ( - temp_dir.uri().join("root2/root2.1/").unwrap(), + temp_dir.url().join("root2/root2.1/").unwrap(), WorkspaceSettings { enable: Some(true), ..Default::default() }, ), ( - temp_dir.uri().join("root3/").unwrap(), + temp_dir.url().join("root3/").unwrap(), WorkspaceSettings { enable: Some(false), ..Default::default() }, ), ( - temp_dir.uri().join("root4_parent/root4/").unwrap(), + temp_dir.url().join("root4_parent/root4/").unwrap(), WorkspaceSettings { enable: Some(true), ..Default::default() @@ -4018,22 +4058,22 @@ mod tests { assert_eq!( json!(workspace_files), json!([ - temp_dir.uri().join("root4_parent/deno.json").unwrap(), - temp_dir.uri().join("root1/mod0.ts").unwrap(), - temp_dir.uri().join("root1/mod1.js").unwrap(), - temp_dir.uri().join("root1/mod2.tsx").unwrap(), - temp_dir.uri().join("root1/mod3.d.ts").unwrap(), - temp_dir.uri().join("root1/mod4.jsx").unwrap(), - temp_dir.uri().join("root1/mod5.mjs").unwrap(), - temp_dir.uri().join("root1/mod6.mts").unwrap(), - temp_dir.uri().join("root1/mod7.d.mts").unwrap(), - temp_dir.uri().join("root1/mod8.json").unwrap(), - temp_dir.uri().join("root1/mod9.jsonc").unwrap(), - temp_dir.uri().join("root2/file1.ts").unwrap(), - temp_dir.uri().join("root4_parent/root4/main.ts").unwrap(), - temp_dir.uri().join("root1/folder/mod.ts").unwrap(), - temp_dir.uri().join("root2/folder/main.ts").unwrap(), - temp_dir.uri().join("root2/root2.1/main.ts").unwrap(), + temp_dir.url().join("root4_parent/deno.json").unwrap(), + temp_dir.url().join("root1/mod0.ts").unwrap(), + temp_dir.url().join("root1/mod1.js").unwrap(), + temp_dir.url().join("root1/mod2.tsx").unwrap(), + temp_dir.url().join("root1/mod3.d.ts").unwrap(), + temp_dir.url().join("root1/mod4.jsx").unwrap(), + temp_dir.url().join("root1/mod5.mjs").unwrap(), + temp_dir.url().join("root1/mod6.mts").unwrap(), + temp_dir.url().join("root1/mod7.d.mts").unwrap(), + temp_dir.url().join("root1/mod8.json").unwrap(), + temp_dir.url().join("root1/mod9.jsonc").unwrap(), + temp_dir.url().join("root2/file1.ts").unwrap(), + temp_dir.url().join("root4_parent/root4/main.ts").unwrap(), + temp_dir.url().join("root1/folder/mod.ts").unwrap(), + temp_dir.url().join("root2/folder/main.ts").unwrap(), + temp_dir.url().join("root2/root2.1/main.ts").unwrap(), ]) ); } diff --git a/cli/lsp/lsp_custom.rs b/cli/lsp/lsp_custom.rs index 637a88bdae..b570b6d0e2 100644 --- a/cli/lsp/lsp_custom.rs +++ b/cli/lsp/lsp_custom.rs @@ -17,7 +17,7 @@ pub struct TaskDefinition { // TODO(nayeemrmn): Rename this to `command` in vscode_deno. #[serde(rename = "detail")] pub command: String, - pub source_uri: lsp::Url, + pub source_uri: lsp::Uri, } #[derive(Debug, Deserialize, Serialize)] @@ -46,6 +46,30 @@ pub struct DiagnosticBatchNotificationParams { pub messages_len: usize, } +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DenoConfigurationData { + pub scope_uri: lsp::Uri, + pub workspace_root_scope_uri: Option, + pub deno_json: Option, + pub package_json: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DidRefreshDenoConfigurationTreeNotificationParams { + pub data: Vec, +} + +pub enum DidRefreshDenoConfigurationTreeNotification {} + +impl lsp::notification::Notification + for DidRefreshDenoConfigurationTreeNotification +{ + type Params = DidRefreshDenoConfigurationTreeNotificationParams; + const METHOD: &'static str = "deno/didRefreshDenoConfigurationTree"; +} + #[derive(Debug, Eq, Hash, PartialEq, Copy, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub enum DenoConfigurationChangeType { @@ -75,8 +99,8 @@ pub enum DenoConfigurationType { #[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct DenoConfigurationChangeEvent { - pub scope_uri: lsp::Url, - pub file_uri: lsp::Url, + pub scope_uri: lsp::Uri, + pub file_uri: lsp::Uri, #[serde(rename = "type")] pub typ: DenoConfigurationChangeType, pub configuration_type: DenoConfigurationType, @@ -88,13 +112,15 @@ pub struct DidChangeDenoConfigurationNotificationParams { pub changes: Vec, } +// TODO(nayeemrmn): This is being replaced by +// `DidRefreshDenoConfigurationTreeNotification` for Deno > v2.0.0. Remove it +// soon. pub enum DidChangeDenoConfigurationNotification {} impl lsp::notification::Notification for DidChangeDenoConfigurationNotification { type Params = DidChangeDenoConfigurationNotificationParams; - const METHOD: &'static str = "deno/didChangeDenoConfiguration"; } @@ -102,7 +128,6 @@ pub enum DidUpgradeCheckNotification {} impl lsp::notification::Notification for DidUpgradeCheckNotification { type Params = DidUpgradeCheckNotificationParams; - const METHOD: &'static str = "deno/didUpgradeCheck"; } @@ -125,6 +150,5 @@ pub enum DiagnosticBatchNotification {} impl lsp::notification::Notification for DiagnosticBatchNotification { type Params = DiagnosticBatchNotificationParams; - const METHOD: &'static str = "deno/internalTestDiagnosticBatch"; } diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs index e5aa337440..2decfc3429 100644 --- a/cli/lsp/npm.rs +++ b/cli/lsp/npm.rs @@ -4,7 +4,7 @@ use dashmap::DashMap; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::serde_json; -use deno_runtime::deno_permissions::PermissionsContainer; +use deno_npm::npm_rc::NpmRc; use deno_semver::package::PackageNv; use deno_semver::Version; use serde::Deserialize; @@ -26,7 +26,10 @@ pub struct CliNpmSearchApi { impl CliNpmSearchApi { pub fn new(file_fetcher: Arc) -> Self { - let resolver = NpmFetchResolver::new(file_fetcher.clone()); + let resolver = NpmFetchResolver::new( + file_fetcher.clone(), + Arc::new(NpmRc::default().as_resolved(npm_registry_url()).unwrap()), + ); Self { file_fetcher, resolver, @@ -55,7 +58,7 @@ impl PackageSearchApi for CliNpmSearchApi { let file_fetcher = self.file_fetcher.clone(); let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&search_url) .await? .into_text_decoded() }) diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index c709831d42..ade353e683 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -16,6 +16,7 @@ use crate::args::CacheSetting; use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::file_fetcher::FetchOptions; +use crate::file_fetcher::FetchPermissionsOptionRef; use crate::file_fetcher::FileFetcher; use crate::http_util::HttpClientProvider; @@ -30,7 +31,6 @@ use deno_core::url::Position; use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::Dependency; -use deno_runtime::deno_permissions::PermissionsContainer; use log::error; use once_cell::sync::Lazy; use std::borrow::Cow; @@ -481,7 +481,8 @@ impl ModuleRegistry { file_fetcher .fetch_with_options(FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, + maybe_auth: None, maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"), maybe_cache_setting: None, }) @@ -584,7 +585,7 @@ impl ModuleRegistry { let file = deno_core::unsync::spawn({ async move { file_fetcher - .fetch(&endpoint, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&endpoint) .await .ok()? .into_text_decoded() @@ -983,7 +984,7 @@ impl ModuleRegistry { // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .ok()? .into_text_decoded() @@ -1049,7 +1050,7 @@ impl ModuleRegistry { let specifier = specifier.clone(); async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .map_err(|err| { error!( @@ -1095,7 +1096,7 @@ impl ModuleRegistry { let specifier = specifier.clone(); async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .map_err(|err| { error!( diff --git a/cli/lsp/repl.rs b/cli/lsp/repl.rs index 2db7b1f725..fa5809045e 100644 --- a/cli/lsp/repl.rs +++ b/cli/lsp/repl.rs @@ -8,6 +8,7 @@ use deno_ast::SourceTextInfo; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::serde_json; +use lsp_types::Uri; use tower_lsp::lsp_types::ClientCapabilities; use tower_lsp::lsp_types::ClientInfo; use tower_lsp::lsp_types::CompletionContext; @@ -40,6 +41,8 @@ use super::config::LanguageWorkspaceSettings; use super::config::ObjectLiteralMethodSnippets; use super::config::TestingSettings; use super::config::WorkspaceSettings; +use super::urls::uri_parse_unencoded; +use super::urls::url_to_uri; #[derive(Debug)] pub struct ReplCompletionItem { @@ -73,7 +76,7 @@ impl ReplLanguageServer { .initialize(InitializeParams { process_id: None, root_path: None, - root_uri: Some(cwd_uri.clone()), + root_uri: Some(url_to_uri(&cwd_uri).unwrap()), initialization_options: Some( serde_json::to_value(get_repl_workspace_settings()).unwrap(), ), @@ -84,6 +87,7 @@ impl ReplLanguageServer { general: None, experimental: None, offset_encoding: None, + notebook_document: None, }, trace: None, workspace_folders: None, @@ -92,6 +96,7 @@ impl ReplLanguageServer { version: None, }), locale: None, + work_done_progress_params: Default::default(), }) .await?; @@ -133,7 +138,7 @@ impl ReplLanguageServer { .completion(CompletionParams { text_document_position: TextDocumentPositionParams { text_document: TextDocumentIdentifier { - uri: self.get_document_specifier(), + uri: self.get_document_uri(), }, position: Position { line: line_and_column.line_index as u32, @@ -208,7 +213,7 @@ impl ReplLanguageServer { .language_server .did_change(DidChangeTextDocumentParams { text_document: VersionedTextDocumentIdentifier { - uri: self.get_document_specifier(), + uri: self.get_document_uri(), version: self.document_version, }, content_changes: vec![TextDocumentContentChangeEvent { @@ -233,7 +238,7 @@ impl ReplLanguageServer { .language_server .did_close(DidCloseTextDocumentParams { text_document: TextDocumentIdentifier { - uri: self.get_document_specifier(), + uri: self.get_document_uri(), }, }) .await; @@ -248,7 +253,7 @@ impl ReplLanguageServer { .language_server .did_open(DidOpenTextDocumentParams { text_document: TextDocumentItem { - uri: self.get_document_specifier(), + uri: self.get_document_uri(), language_id: "typescript".to_string(), version: self.document_version, text: format!("{}{}", self.document_text, self.pending_text), @@ -257,8 +262,9 @@ impl ReplLanguageServer { .await; } - fn get_document_specifier(&self) -> ModuleSpecifier { - self.cwd_uri.join("$deno$repl.ts").unwrap() + fn get_document_uri(&self) -> Uri { + uri_parse_unencoded(self.cwd_uri.join("$deno$repl.ts").unwrap().as_str()) + .unwrap() } } @@ -306,7 +312,7 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings { document_preload_limit: 0, // don't pre-load any modules as it's expensive and not useful for the repl tls_certificate: None, unsafely_ignore_certificate_errors: None, - unstable: false, + unstable: Default::default(), suggest: DenoCompletionSettings { imports: ImportCompletionSettings { auto_discover: false, diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index d279031e32..c89273147a 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -1,28 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::args::create_default_npmrc; -use crate::args::CacheSetting; -use crate::args::CliLockfile; -use crate::args::PackageJsonInstallDepsProvider; -use crate::graph_util::CliJsrUrlProvider; -use crate::http_util::HttpClientProvider; -use crate::lsp::config::Config; -use crate::lsp::config::ConfigData; -use crate::lsp::logging::lsp_warn; -use crate::npm::create_cli_npm_resolver_for_lsp; -use crate::npm::CliNpmResolver; -use crate::npm::CliNpmResolverByonmCreateOptions; -use crate::npm::CliNpmResolverCreateOptions; -use crate::npm::CliNpmResolverManagedCreateOptions; -use crate::npm::CliNpmResolverManagedSnapshotOption; -use crate::npm::ManagedCliNpmResolver; -use crate::resolver::CjsResolutionStore; -use crate::resolver::CliGraphResolver; -use crate::resolver::CliGraphResolverOptions; -use crate::resolver::CliNodeResolver; -use crate::resolver::WorkerCliNpmGraphResolver; -use crate::util::progress_bar::ProgressBar; -use crate::util::progress_bar::ProgressBarStyle; use dashmap::DashMap; use deno_ast::MediaType; use deno_cache_dir::HttpCache; @@ -33,10 +10,10 @@ use deno_graph::source::Resolver; use deno_graph::GraphImport; use deno_graph::ModuleSpecifier; use deno_npm::NpmSystemInfo; +use deno_path_util::url_to_file_path; use deno_runtime::deno_fs; use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_node::PackageJson; -use deno_runtime::fs_util::specifier_to_file_path; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageNv; @@ -55,6 +32,30 @@ use std::sync::Arc; use super::cache::LspCache; use super::jsr::JsrCacheResolver; +use crate::args::create_default_npmrc; +use crate::args::CacheSetting; +use crate::args::CliLockfile; +use crate::args::NpmInstallDepsProvider; +use crate::graph_util::CliJsrUrlProvider; +use crate::http_util::HttpClientProvider; +use crate::lsp::config::Config; +use crate::lsp::config::ConfigData; +use crate::lsp::logging::lsp_warn; +use crate::npm::create_cli_npm_resolver_for_lsp; +use crate::npm::CliByonmNpmResolverCreateOptions; +use crate::npm::CliNpmResolver; +use crate::npm::CliNpmResolverCreateOptions; +use crate::npm::CliNpmResolverManagedCreateOptions; +use crate::npm::CliNpmResolverManagedSnapshotOption; +use crate::npm::ManagedCliNpmResolver; +use crate::resolver::CjsResolutionStore; +use crate::resolver::CliDenoResolverFs; +use crate::resolver::CliGraphResolver; +use crate::resolver::CliGraphResolverOptions; +use crate::resolver::CliNodeResolver; +use crate::resolver::WorkerCliNpmGraphResolver; +use crate::util::progress_bar::ProgressBar; +use crate::util::progress_bar::ProgressBarStyle; #[derive(Debug, Clone)] struct LspScopeResolver { @@ -327,11 +328,11 @@ impl LspResolver { ) -> Option<(ModuleSpecifier, MediaType)> { let resolver = self.get_scope_resolver(file_referrer); let node_resolver = resolver.node_resolver.as_ref()?; - Some(NodeResolution::into_specifier_and_media_type( + Some(NodeResolution::into_specifier_and_media_type(Some( node_resolver .resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types) - .ok(), - )) + .ok()?, + ))) } pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool { @@ -372,6 +373,26 @@ impl LspResolver { Some(NodeResolution::into_specifier_and_media_type(Some(resolution)).1) } + pub fn is_bare_package_json_dep( + &self, + specifier_text: &str, + referrer: &ModuleSpecifier, + ) -> bool { + let resolver = self.get_scope_resolver(Some(referrer)); + let Some(node_resolver) = resolver.node_resolver.as_ref() else { + return false; + }; + node_resolver + .resolve_if_for_npm_pkg( + specifier_text, + referrer, + NodeResolutionMode::Types, + ) + .ok() + .flatten() + .is_some() + } + pub fn get_closest_package_json( &self, referrer: &ModuleSpecifier, @@ -439,11 +460,11 @@ async fn create_npm_resolver( ) -> Option> { let enable_byonm = config_data.map(|d| d.byonm).unwrap_or(false); let options = if enable_byonm { - CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions { - fs: Arc::new(deno_fs::RealFs), + CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions { + fs: CliDenoResolverFs(Arc::new(deno_fs::RealFs)), root_node_modules_dir: config_data.and_then(|config_data| { config_data.node_modules_dir.clone().or_else(|| { - specifier_to_file_path(&config_data.scope) + url_to_file_path(&config_data.scope) .ok() .map(|p| p.join("node_modules/")) }) @@ -474,9 +495,7 @@ async fn create_npm_resolver( maybe_node_modules_path: config_data .and_then(|d| d.node_modules_dir.clone()), // only used for top level install, so we can ignore this - package_json_deps_provider: Arc::new( - PackageJsonInstallDepsProvider::empty(), - ), + npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::empty()), npmrc: config_data .and_then(|d| d.npmrc.clone()) .unwrap_or_else(create_default_npmrc), diff --git a/cli/lsp/testing/definitions.rs b/cli/lsp/testing/definitions.rs index 43a07c2e31..f23411852f 100644 --- a/cli/lsp/testing/definitions.rs +++ b/cli/lsp/testing/definitions.rs @@ -5,10 +5,12 @@ use super::lsp_custom::TestData; use crate::lsp::client::TestingNotification; use crate::lsp::logging::lsp_warn; +use crate::lsp::urls::url_to_uri; use crate::tools::test::TestDescription; use crate::tools::test::TestStepDescription; use crate::util::checksum; +use deno_core::error::AnyError; use deno_core::ModuleSpecifier; use lsp::Range; use std::collections::HashMap; @@ -143,21 +145,23 @@ impl TestModule { pub fn as_replace_notification( &self, maybe_root_uri: Option<&ModuleSpecifier>, - ) -> TestingNotification { + ) -> Result { let label = self.label(maybe_root_uri); - TestingNotification::Module(lsp_custom::TestModuleNotificationParams { - text_document: lsp::TextDocumentIdentifier { - uri: self.specifier.clone(), + Ok(TestingNotification::Module( + lsp_custom::TestModuleNotificationParams { + text_document: lsp::TextDocumentIdentifier { + uri: url_to_uri(&self.specifier)?, + }, + kind: lsp_custom::TestModuleNotificationKind::Replace, + label, + tests: self + .defs + .iter() + .filter(|(_, def)| def.parent_id.is_none()) + .map(|(id, _)| self.get_test_data(id)) + .collect(), }, - kind: lsp_custom::TestModuleNotificationKind::Replace, - label, - tests: self - .defs - .iter() - .filter(|(_, def)| def.parent_id.is_none()) - .map(|(id, _)| self.get_test_data(id)) - .collect(), - }) + )) } pub fn label(&self, maybe_root_uri: Option<&ModuleSpecifier>) -> String { diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index 14196baa36..88fb496e4e 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -12,6 +12,9 @@ use crate::lsp::client::Client; use crate::lsp::client::TestingNotification; use crate::lsp::config; use crate::lsp::logging::lsp_log; +use crate::lsp::urls::uri_parse_unencoded; +use crate::lsp::urls::uri_to_url; +use crate::lsp::urls::url_to_uri; use crate::tools::test; use crate::tools::test::create_test_event_channel; use crate::tools::test::FailFastTracker; @@ -28,8 +31,10 @@ use deno_core::unsync::spawn; use deno_core::unsync::spawn_blocking; use deno_core::ModuleSpecifier; use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::tokio_util::create_and_run_current_thread; use indexmap::IndexMap; +use std::borrow::Cow; use std::collections::HashMap; use std::collections::HashSet; use std::num::NonZeroUsize; @@ -53,12 +58,12 @@ fn as_queue_and_filters( if let Some(include) = ¶ms.include { for item in include { - if let Some((test_definitions, _)) = tests.get(&item.text_document.uri) { - queue.insert(item.text_document.uri.clone()); + let url = uri_to_url(&item.text_document.uri); + if let Some((test_definitions, _)) = tests.get(&url) { + queue.insert(url.clone()); if let Some(id) = &item.id { if let Some(test) = test_definitions.get(id) { - let filter = - filters.entry(item.text_document.uri.clone()).or_default(); + let filter = filters.entry(url).or_default(); if let Some(include) = filter.include.as_mut() { include.insert(test.id.clone(), test.clone()); } else { @@ -75,19 +80,19 @@ fn as_queue_and_filters( } for item in ¶ms.exclude { - if let Some((test_definitions, _)) = tests.get(&item.text_document.uri) { + let url = uri_to_url(&item.text_document.uri); + if let Some((test_definitions, _)) = tests.get(&url) { if let Some(id) = &item.id { // there is no way to exclude a test step if item.step_id.is_none() { if let Some(test) = test_definitions.get(id) { - let filter = - filters.entry(item.text_document.uri.clone()).or_default(); + let filter = filters.entry(url.clone()).or_default(); filter.exclude.insert(test.id.clone(), test.clone()); } } } else { // the entire test module is excluded - queue.remove(&item.text_document.uri); + queue.remove(&url); } } } @@ -182,7 +187,7 @@ impl TestRun { self .queue .iter() - .map(|s| { + .filter_map(|s| { let ids = if let Some((test_module, _)) = tests.get(s) { if let Some(filter) = self.filters.get(s) { filter.as_ids(test_module) @@ -192,10 +197,12 @@ impl TestRun { } else { Vec::new() }; - lsp_custom::EnqueuedTestModule { - text_document: lsp::TextDocumentIdentifier { uri: s.clone() }, + Some(lsp_custom::EnqueuedTestModule { + text_document: lsp::TextDocumentIdentifier { + uri: url_to_uri(s).ok()?, + }, ids, - } + }) }) .collect() } @@ -213,26 +220,23 @@ impl TestRun { ) -> Result<(), AnyError> { let args = self.get_args(); lsp_log!("Executing test run with arguments: {}", args.join(" ")); - let flags = - Arc::new(flags_from_vec(args.into_iter().map(From::from).collect())?); + let flags = Arc::new(flags_from_vec( + args.into_iter().map(|s| From::from(s.as_ref())).collect(), + )?); let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; // Various test files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let main_graph_container = factory.main_module_graph_container().await?; - test::check_specifiers( - factory.file_fetcher()?, - main_graph_container, - self - .queue - .iter() - .map(|s| (s.clone(), test::TestMode::Executable)) - .collect(), - ) - .await?; + main_graph_container + .check_specifiers(&self.queue.iter().cloned().collect::>(), None) + .await?; let (concurrent_jobs, fail_fast) = if let DenoSubcommand::Test(test_flags) = cli_options.sub_command() { @@ -269,7 +273,10 @@ impl TestRun { let join_handles = queue.into_iter().map(move |specifier| { let specifier = specifier.clone(); let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permission_desc_parser.clone(), + permissions.clone(), + ); let worker_sender = test_event_sender_factory.worker(); let fail_fast_tracker = fail_fast_tracker.clone(); let lsp_filter = self.filters.get(&specifier); @@ -298,7 +305,7 @@ impl TestRun { // channel. create_and_run_current_thread(test::test_specifier( worker_factory, - permissions, + permissions_container, specifier, worker_sender, fail_fast_tracker, @@ -446,37 +453,42 @@ impl TestRun { Ok(()) } - fn get_args(&self) -> Vec<&str> { - let mut args = vec!["deno", "test"]; + fn get_args(&self) -> Vec> { + let mut args = vec![Cow::Borrowed("deno"), Cow::Borrowed("test")]; args.extend( self .workspace_settings .testing .args .iter() - .map(|s| s.as_str()), + .map(|s| Cow::Borrowed(s.as_str())), ); - args.push("--trace-leaks"); - if self.workspace_settings.unstable && !args.contains(&"--unstable") { - args.push("--unstable"); + args.push(Cow::Borrowed("--trace-leaks")); + for unstable_feature in self.workspace_settings.unstable.as_deref() { + let flag = format!("--unstable-{unstable_feature}"); + if !args.contains(&Cow::Borrowed(&flag)) { + args.push(Cow::Owned(flag)); + } } if let Some(config) = &self.workspace_settings.config { - if !args.contains(&"--config") && !args.contains(&"-c") { - args.push("--config"); - args.push(config.as_str()); + if !args.contains(&Cow::Borrowed("--config")) + && !args.contains(&Cow::Borrowed("-c")) + { + args.push(Cow::Borrowed("--config")); + args.push(Cow::Borrowed(config.as_str())); } } if let Some(import_map) = &self.workspace_settings.import_map { - if !args.contains(&"--import-map") { - args.push("--import-map"); - args.push(import_map.as_str()); + if !args.contains(&Cow::Borrowed("--import-map")) { + args.push(Cow::Borrowed("--import-map")); + args.push(Cow::Borrowed(import_map.as_str())); } } if self.kind == lsp_custom::TestRunKind::Debug - && !args.contains(&"--inspect") - && !args.contains(&"--inspect-brk") + && !args.contains(&Cow::Borrowed("--inspect")) + && !args.contains(&Cow::Borrowed("--inspect-brk")) { - args.push("--inspect"); + args.push(Cow::Borrowed("--inspect")); } args } @@ -523,7 +535,7 @@ impl LspTestDescription { &self, tests: &IndexMap, ) -> lsp_custom::TestIdentifier { - let uri = ModuleSpecifier::parse(&self.location().file_name).unwrap(); + let uri = uri_parse_unencoded(&self.location().file_name).unwrap(); let static_id = self.static_id(); let mut root_desc = self; while let Some(parent_id) = root_desc.parent_id() { @@ -587,6 +599,9 @@ impl LspTestReporter { let (test_module, _) = files .entry(specifier.clone()) .or_insert_with(|| (TestModule::new(specifier), "1".to_string())); + let Ok(uri) = url_to_uri(&test_module.specifier) else { + return; + }; let (static_id, is_new) = test_module.register_dynamic(desc); self.tests.insert( desc.id, @@ -597,9 +612,7 @@ impl LspTestReporter { .client .send_test_notification(TestingNotification::Module( lsp_custom::TestModuleNotificationParams { - text_document: lsp::TextDocumentIdentifier { - uri: test_module.specifier.clone(), - }, + text_document: lsp::TextDocumentIdentifier { uri }, kind: lsp_custom::TestModuleNotificationKind::Insert, label: test_module.label(self.maybe_root_uri.as_ref()), tests: vec![test_module.get_test_data(&static_id)], @@ -697,6 +710,9 @@ impl LspTestReporter { let (test_module, _) = files .entry(specifier.clone()) .or_insert_with(|| (TestModule::new(specifier), "1".to_string())); + let Ok(uri) = url_to_uri(&test_module.specifier) else { + return; + }; let (static_id, is_new) = test_module.register_step_dynamic( desc, self.tests.get(&desc.parent_id).unwrap().static_id(), @@ -710,9 +726,7 @@ impl LspTestReporter { .client .send_test_notification(TestingNotification::Module( lsp_custom::TestModuleNotificationParams { - text_document: lsp::TextDocumentIdentifier { - uri: test_module.specifier.clone(), - }, + text_document: lsp::TextDocumentIdentifier { uri }, kind: lsp_custom::TestModuleNotificationKind::Insert, label: test_module.label(self.maybe_root_uri.as_ref()), tests: vec![test_module.get_test_data(&static_id)], @@ -796,14 +810,14 @@ mod tests { include: Some(vec![ lsp_custom::TestIdentifier { text_document: lsp::TextDocumentIdentifier { - uri: specifier.clone(), + uri: url_to_uri(&specifier).unwrap(), }, id: None, step_id: None, }, lsp_custom::TestIdentifier { text_document: lsp::TextDocumentIdentifier { - uri: non_test_specifier.clone(), + uri: url_to_uri(&non_test_specifier).unwrap(), }, id: None, step_id: None, @@ -811,7 +825,7 @@ mod tests { ]), exclude: vec![lsp_custom::TestIdentifier { text_document: lsp::TextDocumentIdentifier { - uri: specifier.clone(), + uri: url_to_uri(&specifier).unwrap(), }, id: Some( "69d9fe87f64f5b66cb8b631d4fd2064e8224b8715a049be54276c42189ff8f9f" diff --git a/cli/lsp/testing/server.rs b/cli/lsp/testing/server.rs index ff59e1033d..c9c39d9ffc 100644 --- a/cli/lsp/testing/server.rs +++ b/cli/lsp/testing/server.rs @@ -10,6 +10,7 @@ use crate::lsp::config; use crate::lsp::documents::DocumentsFilter; use crate::lsp::language_server::StateSnapshot; use crate::lsp::performance::Performance; +use crate::lsp::urls::url_to_uri; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; @@ -26,12 +27,16 @@ use tower_lsp::jsonrpc::Error as LspError; use tower_lsp::jsonrpc::Result as LspResult; use tower_lsp::lsp_types as lsp; -fn as_delete_notification(uri: ModuleSpecifier) -> TestingNotification { - TestingNotification::DeleteModule( +fn as_delete_notification( + url: &ModuleSpecifier, +) -> Result { + Ok(TestingNotification::DeleteModule( lsp_custom::TestModuleDeleteNotificationParams { - text_document: lsp::TextDocumentIdentifier { uri }, + text_document: lsp::TextDocumentIdentifier { + uri: url_to_uri(url)?, + }, }, - ) + )) } pub type TestServerTests = @@ -123,20 +128,24 @@ impl TestServer { .map(|tm| tm.as_ref().clone()) .unwrap_or_else(|| TestModule::new(specifier.clone())); if !test_module.is_empty() { - client.send_test_notification( - test_module.as_replace_notification(mru.as_ref()), - ); + if let Ok(params) = + test_module.as_replace_notification(mru.as_ref()) + { + client.send_test_notification(params); + } } else if !was_empty { - client.send_test_notification(as_delete_notification( - specifier.clone(), - )); + if let Ok(params) = as_delete_notification(specifier) { + client.send_test_notification(params); + } } tests .insert(specifier.clone(), (test_module, script_version)); } } - for key in keys { - client.send_test_notification(as_delete_notification(key)); + for key in &keys { + if let Ok(params) = as_delete_notification(key) { + client.send_test_notification(params); + } } performance.measure(mark); } diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 3ac25507cd..0f31d7dd3b 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -19,8 +19,10 @@ use super::refactor::EXTRACT_TYPE; use super::semantic_tokens; use super::semantic_tokens::SemanticTokensBuilder; use super::text::LineIndex; -use super::urls::LspClientUrl; +use super::urls::uri_to_url; +use super::urls::url_to_uri; use super::urls::INVALID_SPECIFIER; +use super::urls::INVALID_URI; use crate::args::jsr_url; use crate::args::FmtOptionsConfig; @@ -37,7 +39,6 @@ use deno_core::convert::ToV8; use deno_core::error::StdAnyError; use deno_core::futures::stream::FuturesOrdered; use deno_core::futures::StreamExt; -use deno_runtime::fs_util::specifier_to_file_path; use dashmap::DashMap; use deno_ast::MediaType; @@ -61,6 +62,7 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_core::PollEventLoopOptions; use deno_core::RuntimeOptions; +use deno_path_util::url_to_file_path; use deno_runtime::inspector_server::InspectorServer; use deno_runtime::tokio_util::create_basic_runtime; use indexmap::IndexMap; @@ -2046,7 +2048,7 @@ impl DocumentSpan { let file_referrer = target_asset_or_doc.file_referrer(); let target_uri = language_server .url_map - .normalize_specifier(&target_specifier, file_referrer) + .specifier_to_uri(&target_specifier, file_referrer) .ok()?; let (target_range, target_selection_range) = if let Some(context_span) = &self.context_span { @@ -2071,7 +2073,7 @@ impl DocumentSpan { }; let link = lsp::LocationLink { origin_selection_range, - target_uri: target_uri.into_url(), + target_uri, target_range, target_selection_range, }; @@ -2091,11 +2093,11 @@ impl DocumentSpan { let line_index = asset_or_doc.line_index(); let range = self.text_span.to_range(line_index); let file_referrer = asset_or_doc.file_referrer(); - let mut target = language_server + let target_uri = language_server .url_map - .normalize_specifier(&specifier, file_referrer) - .ok()? - .into_url(); + .specifier_to_uri(&specifier, file_referrer) + .ok()?; + let mut target = uri_to_url(&target_uri); target.set_fragment(Some(&format!( "L{},{}", range.start.line + 1, @@ -2154,13 +2156,10 @@ impl NavigateToItem { let file_referrer = asset_or_doc.file_referrer(); let uri = language_server .url_map - .normalize_specifier(&specifier, file_referrer) + .specifier_to_uri(&specifier, file_referrer) .ok()?; let range = self.text_span.to_range(line_index); - let location = lsp::Location { - uri: uri.into_url(), - range, - }; + let location = lsp::Location { uri, range }; let mut tags: Option> = None; let kind_modifiers = parse_kind_modifier(&self.kind_modifiers); @@ -2183,6 +2182,50 @@ impl NavigateToItem { } } +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InlayHintDisplayPart { + pub text: String, + pub span: Option, + pub file: Option, +} + +impl InlayHintDisplayPart { + pub fn to_lsp( + &self, + language_server: &language_server::Inner, + ) -> lsp::InlayHintLabelPart { + let location = self.file.as_ref().map(|f| { + let specifier = + resolve_url(f).unwrap_or_else(|_| INVALID_SPECIFIER.clone()); + let file_referrer = + language_server.documents.get_file_referrer(&specifier); + let uri = language_server + .url_map + .specifier_to_uri(&specifier, file_referrer.as_deref()) + .unwrap_or_else(|_| INVALID_URI.clone()); + let range = self + .span + .as_ref() + .and_then(|s| { + let asset_or_doc = + language_server.get_asset_or_document(&specifier).ok()?; + Some(s.to_range(asset_or_doc.line_index())) + }) + .unwrap_or_else(|| { + lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)) + }); + lsp::Location { uri, range } + }); + lsp::InlayHintLabelPart { + value: self.text.clone(), + tooltip: None, + location, + command: None, + } + } +} + #[derive(Debug, Clone, Deserialize)] pub enum InlayHintKind { Type, @@ -2204,6 +2247,7 @@ impl InlayHintKind { #[serde(rename_all = "camelCase")] pub struct InlayHint { pub text: String, + pub display_parts: Option>, pub position: u32, pub kind: InlayHintKind, pub whitespace_before: Option, @@ -2211,10 +2255,23 @@ pub struct InlayHint { } impl InlayHint { - pub fn to_lsp(&self, line_index: Arc) -> lsp::InlayHint { + pub fn to_lsp( + &self, + line_index: Arc, + language_server: &language_server::Inner, + ) -> lsp::InlayHint { lsp::InlayHint { position: line_index.position_tsc(self.position.into()), - label: lsp::InlayHintLabel::String(self.text.clone()), + label: if let Some(display_parts) = &self.display_parts { + lsp::InlayHintLabel::LabelParts( + display_parts + .iter() + .map(|p| p.to_lsp(language_server)) + .collect(), + ) + } else { + lsp::InlayHintLabel::String(self.text.clone()) + }, kind: self.kind.to_lsp(), padding_left: self.whitespace_before, padding_right: self.whitespace_after, @@ -2413,12 +2470,10 @@ impl ImplementationLocation { let file_referrer = language_server.documents.get_file_referrer(&specifier); let uri = language_server .url_map - .normalize_specifier(&specifier, file_referrer.as_deref()) - .unwrap_or_else(|_| { - LspClientUrl::new(ModuleSpecifier::parse("deno://invalid").unwrap()) - }); + .specifier_to_uri(&specifier, file_referrer.as_deref()) + .unwrap_or_else(|_| INVALID_URI.clone()); lsp::Location { - uri: uri.into_url(), + uri, range: self.document_span.text_span.to_range(line_index), } } @@ -2474,7 +2529,7 @@ impl RenameLocations { language_server.documents.get_file_referrer(&specifier); let uri = language_server .url_map - .normalize_specifier(&specifier, file_referrer.as_deref())?; + .specifier_to_uri(&specifier, file_referrer.as_deref())?; let asset_or_doc = language_server.get_asset_or_document(&specifier)?; // ensure TextDocumentEdit for `location.file_name`. @@ -2483,7 +2538,7 @@ impl RenameLocations { uri.clone(), lsp::TextDocumentEdit { text_document: lsp::OptionalVersionedTextDocumentIdentifier { - uri: uri.as_url().clone(), + uri: uri.clone(), version: asset_or_doc.document_lsp_version(), }, edits: @@ -2685,7 +2740,7 @@ impl FileTextChanges { .collect(); Ok(lsp::TextDocumentEdit { text_document: lsp::OptionalVersionedTextDocumentIdentifier { - uri: specifier, + uri: url_to_uri(&specifier)?, version: asset_or_doc.document_lsp_version(), }, edits, @@ -2712,7 +2767,7 @@ impl FileTextChanges { if self.is_new_file.unwrap_or(false) { ops.push(lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create( lsp::CreateFile { - uri: specifier.clone(), + uri: url_to_uri(&specifier)?, options: Some(lsp::CreateFileOptions { ignore_if_exists: Some(true), overwrite: None, @@ -2729,7 +2784,7 @@ impl FileTextChanges { .collect(); ops.push(lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit { text_document: lsp::OptionalVersionedTextDocumentIdentifier { - uri: specifier, + uri: url_to_uri(&specifier)?, version: maybe_asset_or_document.and_then(|d| d.document_lsp_version()), }, edits, @@ -3127,10 +3182,10 @@ impl ReferenceEntry { let file_referrer = language_server.documents.get_file_referrer(&specifier); let uri = language_server .url_map - .normalize_specifier(&specifier, file_referrer.as_deref()) - .unwrap_or_else(|_| LspClientUrl::new(INVALID_SPECIFIER.clone())); + .specifier_to_uri(&specifier, file_referrer.as_deref()) + .unwrap_or_else(|_| INVALID_URI.clone()); lsp::Location { - uri: uri.into_url(), + uri, range: self.document_span.text_span.to_range(line_index), } } @@ -3188,12 +3243,13 @@ impl CallHierarchyItem { .get_file_referrer(&target_specifier); let uri = language_server .url_map - .normalize_specifier(&target_specifier, file_referrer.as_deref()) - .unwrap_or_else(|_| LspClientUrl::new(INVALID_SPECIFIER.clone())); + .specifier_to_uri(&target_specifier, file_referrer.as_deref()) + .unwrap_or_else(|_| INVALID_URI.clone()); let use_file_name = self.is_source_file_item(); - let maybe_file_path = if uri.as_url().scheme() == "file" { - specifier_to_file_path(uri.as_url()).ok() + let maybe_file_path = if uri.scheme().is_some_and(|s| s.as_str() == "file") + { + url_to_file_path(&uri_to_url(&uri)).ok() } else { None }; @@ -3237,7 +3293,7 @@ impl CallHierarchyItem { lsp::CallHierarchyItem { name, tags, - uri: uri.into_url(), + uri, detail: Some(detail), kind: self.kind.clone().into(), range: self.span.to_range(line_index.clone()), @@ -3941,7 +3997,7 @@ pub struct OutliningSpan { kind: OutliningSpanKind, } -const FOLD_END_PAIR_CHARACTERS: &[u8] = &[b'}', b']', b')', b'`']; +const FOLD_END_PAIR_CHARACTERS: &[u8] = b"}])`"; impl OutliningSpan { pub fn to_folding_range( @@ -4894,6 +4950,10 @@ pub struct UserPreferences { pub allow_rename_of_import_path: Option, #[serde(skip_serializing_if = "Option::is_none")] pub auto_import_file_exclude_patterns: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub interactive_inlay_hints: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub prefer_type_only_auto_imports: Option, } impl UserPreferences { @@ -4911,6 +4971,7 @@ impl UserPreferences { include_completions_with_snippet_text: Some( config.snippet_support_capable(), ), + interactive_inlay_hints: Some(true), provide_refactor_not_applicable_reason: Some(true), quote_preference: Some(fmt_config.into()), use_label_details_in_completion_entries: Some(true), @@ -5015,6 +5076,9 @@ impl UserPreferences { } else { Some(language_settings.preferences.quote_style) }, + prefer_type_only_auto_imports: Some( + language_settings.preferences.prefer_type_only_auto_imports, + ), ..base_preferences } } @@ -5398,7 +5462,7 @@ mod tests { sources: &[(&str, &str, i32, LanguageId)], ) -> (TempDir, TsServer, Arc, LspCache) { let temp_dir = TempDir::new(); - let cache = LspCache::new(Some(temp_dir.uri().join(".deno_dir").unwrap())); + let cache = LspCache::new(Some(temp_dir.url().join(".deno_dir").unwrap())); let mut config = Config::default(); config .tree @@ -5408,7 +5472,7 @@ mod tests { "compilerOptions": ts_config, }) .to_string(), - temp_dir.uri().join("deno.json").unwrap(), + temp_dir.url().join("deno.json").unwrap(), &Default::default(), ) .unwrap(), @@ -5419,7 +5483,7 @@ mod tests { let mut documents = Documents::default(); documents.update_config(&config, &resolver, &cache, &Default::default()); for (relative_specifier, source, version, language_id) in sources { - let specifier = temp_dir.uri().join(relative_specifier).unwrap(); + let specifier = temp_dir.url().join(relative_specifier).unwrap(); documents.open(specifier, *version, *language_id, (*source).into(), None); } let snapshot = Arc::new(StateSnapshot { @@ -5477,7 +5541,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "noEmit": true, "lib": [], }), @@ -5489,7 +5552,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5523,7 +5586,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "jsx": "react", "lib": ["esnext", "dom", "deno.ns"], "noEmit": true, @@ -5536,7 +5598,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5549,7 +5611,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5567,7 +5628,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5580,7 +5641,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5594,7 +5654,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5626,7 +5686,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5644,7 +5703,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5657,7 +5716,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5678,7 +5736,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5724,7 +5782,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5736,7 +5793,7 @@ mod tests { )], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics(snapshot, vec![specifier.clone()], Default::default()) .await @@ -5802,7 +5859,6 @@ mod tests { let (temp_dir, ts_server, snapshot, cache) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -5829,7 +5885,7 @@ mod tests { b"export const b = \"b\";\n", ) .unwrap(); - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics( snapshot.clone(), @@ -5879,7 +5935,7 @@ mod tests { [(&specifier_dep, ChangeKind::Opened)], None, ); - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let diagnostics = ts_server .get_diagnostics( snapshot.clone(), @@ -5944,14 +6000,13 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), &[("a.ts", fixture, 1, LanguageId::TypeScript)], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let info = ts_server .get_completions( snapshot.clone(), @@ -5966,7 +6021,7 @@ mod tests { trigger_kind: None, }, Default::default(), - Some(temp_dir.uri()), + Some(temp_dir.url()), ) .await .unwrap(); @@ -5983,7 +6038,7 @@ mod tests { preferences: None, data: None, }, - Some(temp_dir.uri()), + Some(temp_dir.url()), ) .await .unwrap() @@ -6095,7 +6150,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -6105,7 +6159,7 @@ mod tests { ], ) .await; - let specifier = temp_dir.uri().join("a.ts").unwrap(); + let specifier = temp_dir.url().join("a.ts").unwrap(); let fmt_options_config = FmtOptionsConfig { semi_colons: Some(false), single_quote: Some(true), @@ -6126,7 +6180,7 @@ mod tests { ..Default::default() }, FormatCodeSettings::from(&fmt_options_config), - Some(temp_dir.uri()), + Some(temp_dir.url()), ) .await .unwrap(); @@ -6152,7 +6206,7 @@ mod tests { }), data: entry.data.clone(), }, - Some(temp_dir.uri()), + Some(temp_dir.url()), ) .await .unwrap() @@ -6204,7 +6258,6 @@ mod tests { let (temp_dir, ts_server, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -6217,8 +6270,8 @@ mod tests { let changes = ts_server .get_edits_for_file_rename( snapshot, - temp_dir.uri().join("b.ts").unwrap(), - temp_dir.uri().join("🦕.ts").unwrap(), + temp_dir.url().join("b.ts").unwrap(), + temp_dir.url().join("🦕.ts").unwrap(), FormatCodeSettings::default(), UserPreferences::default(), ) @@ -6227,7 +6280,7 @@ mod tests { assert_eq!( changes, vec![FileTextChanges { - file_name: temp_dir.uri().join("a.ts").unwrap().to_string(), + file_name: temp_dir.url().join("a.ts").unwrap().to_string(), text_changes: vec![TextChange { span: TextSpan { start: 8, @@ -6275,7 +6328,6 @@ mod tests { let (temp_dir, _, snapshot, _) = setup( json!({ "target": "esnext", - "module": "esnext", "lib": ["deno.ns", "deno.window"], "noEmit": true, }), @@ -6286,7 +6338,7 @@ mod tests { let resolved = op_resolve_inner( &mut state, ResolveArgs { - base: temp_dir.uri().join("a.ts").unwrap().to_string(), + base: temp_dir.url().join("a.ts").unwrap().to_string(), is_base_cjs: false, specifiers: vec!["./b.ts".to_string()], }, @@ -6295,7 +6347,7 @@ mod tests { assert_eq!( resolved, vec![Some(( - temp_dir.uri().join("b.ts").unwrap().to_string(), + temp_dir.url().join("b.ts").unwrap().to_string(), MediaType::TypeScript.as_ts_extension().to_string() ))] ); diff --git a/cli/lsp/urls.rs b/cli/lsp/urls.rs index 594c223b43..6c7da4f134 100644 --- a/cli/lsp/urls.rs +++ b/cli/lsp/urls.rs @@ -6,17 +6,25 @@ use deno_core::parking_lot::Mutex; use deno_core::url::Position; use deno_core::url::Url; use deno_core::ModuleSpecifier; +use lsp_types::Uri; use once_cell::sync::Lazy; use std::collections::HashMap; +use std::str::FromStr; use std::sync::Arc; use super::cache::LspCache; +use super::logging::lsp_warn; /// Used in situations where a default URL needs to be used where otherwise a /// panic is undesired. pub static INVALID_SPECIFIER: Lazy = Lazy::new(|| ModuleSpecifier::parse("deno://invalid").unwrap()); +/// Used in situations where a default URL needs to be used where otherwise a +/// panic is undesired. +pub static INVALID_URI: Lazy = + Lazy::new(|| Uri::from_str("deno://invalid").unwrap()); + /// Matches the `encodeURIComponent()` encoding from JavaScript, which matches /// the component percent encoding set. /// @@ -47,6 +55,25 @@ const COMPONENT: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS .add(b'+') .add(b','); +/// Characters that may be left unencoded in a `Url` path but not valid in a +/// `Uri` path. +const URL_TO_URI_PATH: &percent_encoding::AsciiSet = + &percent_encoding::CONTROLS + .add(b'[') + .add(b']') + .add(b'^') + .add(b'|'); + +/// Characters that may be left unencoded in a `Url` query but not valid in a +/// `Uri` query. +const URL_TO_URI_QUERY: &percent_encoding::AsciiSet = + &URL_TO_URI_PATH.add(b'\\').add(b'`').add(b'{').add(b'}'); + +/// Characters that may be left unencoded in a `Url` fragment but not valid in +/// a `Uri` fragment. +const URL_TO_URI_FRAGMENT: &percent_encoding::AsciiSet = + &URL_TO_URI_PATH.add(b'#').add(b'\\').add(b'{').add(b'}'); + fn hash_data_specifier(specifier: &ModuleSpecifier) -> String { let mut file_name_str = specifier.path().to_string(); if let Some(query) = specifier.query() { @@ -56,7 +83,7 @@ fn hash_data_specifier(specifier: &ModuleSpecifier) -> String { crate::util::checksum::gen(&[file_name_str.as_bytes()]) } -fn to_deno_url(specifier: &Url) -> String { +fn to_deno_uri(specifier: &Url) -> String { let mut string = String::with_capacity(specifier.as_str().len() + 6); string.push_str("deno:/"); string.push_str(specifier.scheme()); @@ -93,58 +120,62 @@ fn from_deno_url(url: &Url) -> Option { Url::parse(&string).ok() } -/// This exists to make it a little bit harder to accidentally use a `Url` -/// in the wrong place where a client url should be used. -#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] -pub struct LspClientUrl(Url); - -impl LspClientUrl { - pub fn new(url: Url) -> Self { - Self(url) - } - - pub fn as_url(&self) -> &Url { - &self.0 - } - - pub fn into_url(self) -> Url { - self.0 - } - - pub fn as_str(&self) -> &str { - self.0.as_str() - } -} - -impl std::fmt::Display for LspClientUrl { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} - #[derive(Debug, Default)] struct LspUrlMapInner { - specifier_to_url: HashMap, - url_to_specifier: HashMap, + specifier_to_uri: HashMap, + uri_to_specifier: HashMap, } impl LspUrlMapInner { - fn put(&mut self, specifier: ModuleSpecifier, url: LspClientUrl) { - self - .url_to_specifier - .insert(url.as_url().clone(), specifier.clone()); - self.specifier_to_url.insert(specifier, url); + fn put(&mut self, specifier: ModuleSpecifier, uri: Uri) { + self.uri_to_specifier.insert(uri.clone(), specifier.clone()); + self.specifier_to_uri.insert(specifier, uri); } - fn get_url(&self, specifier: &ModuleSpecifier) -> Option<&LspClientUrl> { - self.specifier_to_url.get(specifier) + fn get_uri(&self, specifier: &ModuleSpecifier) -> Option<&Uri> { + self.specifier_to_uri.get(specifier) } - fn get_specifier(&self, url: &Url) -> Option<&ModuleSpecifier> { - self.url_to_specifier.get(url) + fn get_specifier(&self, uri: &Uri) -> Option<&ModuleSpecifier> { + self.uri_to_specifier.get(uri) } } +pub fn uri_parse_unencoded(s: &str) -> Result { + url_to_uri(&Url::parse(s)?) +} + +pub fn url_to_uri(url: &Url) -> Result { + let components = deno_core::url::quirks::internal_components(url); + let mut input = String::with_capacity(url.as_str().len()); + input.push_str(&url.as_str()[..components.path_start as usize]); + input.push_str( + &percent_encoding::utf8_percent_encode(url.path(), URL_TO_URI_PATH) + .to_string(), + ); + if let Some(query) = url.query() { + input.push('?'); + input.push_str( + &percent_encoding::utf8_percent_encode(query, URL_TO_URI_QUERY) + .to_string(), + ); + } + if let Some(fragment) = url.fragment() { + input.push('#'); + input.push_str( + &percent_encoding::utf8_percent_encode(fragment, URL_TO_URI_FRAGMENT) + .to_string(), + ); + } + Ok(Uri::from_str(&input).inspect_err(|err| { + lsp_warn!("Could not convert URL \"{url}\" to URI: {err}") + })?) +} + +pub fn uri_to_url(uri: &Uri) -> Url { + Url::parse(uri.as_str()).unwrap() +} + #[derive(Debug, Clone, Copy)] pub enum LspUrlKind { File, @@ -167,24 +198,24 @@ impl LspUrlMap { /// Normalize a specifier that is used internally within Deno (or tsc) to a /// URL that can be handled as a "virtual" document by an LSP client. - pub fn normalize_specifier( + pub fn specifier_to_uri( &self, specifier: &ModuleSpecifier, file_referrer: Option<&ModuleSpecifier>, - ) -> Result { + ) -> Result { if let Some(file_url) = self.cache.vendored_specifier(specifier, file_referrer) { - return Ok(LspClientUrl(file_url)); + return url_to_uri(&file_url); } let mut inner = self.inner.lock(); - if let Some(url) = inner.get_url(specifier).cloned() { - Ok(url) + if let Some(uri) = inner.get_uri(specifier).cloned() { + Ok(uri) } else { - let url = if specifier.scheme() == "file" { - LspClientUrl(specifier.clone()) + let uri = if specifier.scheme() == "file" { + url_to_uri(specifier)? } else { - let specifier_str = if specifier.scheme() == "asset" { + let uri_str = if specifier.scheme() == "asset" { format!("deno:/asset{}", specifier.path()) } else if specifier.scheme() == "data" { let data_url = deno_graph::source::RawDataUrl::parse(specifier)?; @@ -200,13 +231,13 @@ impl LspUrlMap { extension ) } else { - to_deno_url(specifier) + to_deno_uri(specifier) }; - let url = LspClientUrl(Url::parse(&specifier_str)?); - inner.put(specifier.clone(), url.clone()); - url + let uri = uri_parse_unencoded(&uri_str)?; + inner.put(specifier.clone(), uri.clone()); + uri }; - Ok(url) + Ok(uri) } } @@ -218,12 +249,17 @@ impl LspUrlMap { /// Note: Sometimes the url provided by the client may not have a trailing slash, /// so we need to force it to in the mapping and nee to explicitly state whether /// this is a file or directory url. - pub fn normalize_url(&self, url: &Url, kind: LspUrlKind) -> ModuleSpecifier { - if let Some(remote_url) = self.cache.unvendored_specifier(url) { + pub fn uri_to_specifier( + &self, + uri: &Uri, + kind: LspUrlKind, + ) -> ModuleSpecifier { + let url = uri_to_url(uri); + if let Some(remote_url) = self.cache.unvendored_specifier(&url) { return remote_url; } let mut inner = self.inner.lock(); - if let Some(specifier) = inner.get_specifier(url).cloned() { + if let Some(specifier) = inner.get_specifier(uri).cloned() { return specifier; } let mut specifier = None; @@ -234,13 +270,13 @@ impl LspUrlMap { LspUrlKind::File => Url::from_file_path(path).unwrap(), }); } - } else if let Some(s) = file_like_to_file_specifier(url) { + } else if let Some(s) = file_like_to_file_specifier(&url) { specifier = Some(s); - } else if let Some(s) = from_deno_url(url) { + } else if let Some(s) = from_deno_url(&url) { specifier = Some(s); } let specifier = specifier.unwrap_or_else(|| url.clone()); - inner.put(specifier.clone(), LspClientUrl(url.clone())); + inner.put(specifier.clone(), uri.clone()); specifier } } @@ -288,15 +324,14 @@ mod tests { fn test_lsp_url_map() { let map = LspUrlMap::default(); let fixture = resolve_url("https://deno.land/x/pkg@1.0.0/mod.ts").unwrap(); - let actual_url = map - .normalize_specifier(&fixture, None) + let actual_uri = map + .specifier_to_uri(&fixture, None) .expect("could not handle specifier"); - let expected_url = - Url::parse("deno:/https/deno.land/x/pkg%401.0.0/mod.ts").unwrap(); - assert_eq!(actual_url.as_url(), &expected_url); - - let actual_specifier = - map.normalize_url(actual_url.as_url(), LspUrlKind::File); + assert_eq!( + actual_uri.as_str(), + "deno:/https/deno.land/x/pkg%401.0.0/mod.ts" + ); + let actual_specifier = map.uri_to_specifier(&actual_uri, LspUrlKind::File); assert_eq!(actual_specifier, fixture); } @@ -304,18 +339,14 @@ mod tests { fn test_lsp_url_reverse() { let map = LspUrlMap::default(); let fixture = - resolve_url("deno:/https/deno.land/x/pkg%401.0.0/mod.ts").unwrap(); - let actual_specifier = map.normalize_url(&fixture, LspUrlKind::File); + Uri::from_str("deno:/https/deno.land/x/pkg%401.0.0/mod.ts").unwrap(); + let actual_specifier = map.uri_to_specifier(&fixture, LspUrlKind::File); let expected_specifier = Url::parse("https://deno.land/x/pkg@1.0.0/mod.ts").unwrap(); assert_eq!(&actual_specifier, &expected_specifier); - let actual_url = map - .normalize_specifier(&actual_specifier, None) - .unwrap() - .as_url() - .clone(); - assert_eq!(actual_url, fixture); + let actual_uri = map.specifier_to_uri(&actual_specifier, None).unwrap(); + assert_eq!(actual_uri, fixture); } #[test] @@ -323,14 +354,11 @@ mod tests { // Test fix for #9741 - not properly encoding certain URLs let map = LspUrlMap::default(); let fixture = resolve_url("https://cdn.skypack.dev/-/postcss@v8.2.9-E4SktPp9c0AtxrJHp8iV/dist=es2020,mode=types/lib/postcss.d.ts").unwrap(); - let actual_url = map - .normalize_specifier(&fixture, None) + let actual_uri = map + .specifier_to_uri(&fixture, None) .expect("could not handle specifier"); - let expected_url = Url::parse("deno:/https/cdn.skypack.dev/-/postcss%40v8.2.9-E4SktPp9c0AtxrJHp8iV/dist%3Des2020%2Cmode%3Dtypes/lib/postcss.d.ts").unwrap(); - assert_eq!(actual_url.as_url(), &expected_url); - - let actual_specifier = - map.normalize_url(actual_url.as_url(), LspUrlKind::File); + assert_eq!(actual_uri.as_str(), "deno:/https/cdn.skypack.dev/-/postcss%40v8.2.9-E4SktPp9c0AtxrJHp8iV/dist%3Des2020%2Cmode%3Dtypes/lib/postcss.d.ts"); + let actual_specifier = map.uri_to_specifier(&actual_uri, LspUrlKind::File); assert_eq!(actual_specifier, fixture); } @@ -338,14 +366,13 @@ mod tests { fn test_lsp_url_map_data() { let map = LspUrlMap::default(); let fixture = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap(); - let actual_url = map - .normalize_specifier(&fixture, None) + let actual_uri = map + .specifier_to_uri(&fixture, None) .expect("could not handle specifier"); let expected_url = Url::parse("deno:/c21c7fc382b2b0553dc0864aa81a3acacfb7b3d1285ab5ae76da6abec213fb37/data_url.ts").unwrap(); - assert_eq!(actual_url.as_url(), &expected_url); + assert_eq!(&uri_to_url(&actual_uri), &expected_url); - let actual_specifier = - map.normalize_url(actual_url.as_url(), LspUrlKind::File); + let actual_specifier = map.uri_to_specifier(&actual_uri, LspUrlKind::File); assert_eq!(actual_specifier, fixture); } @@ -353,15 +380,11 @@ mod tests { fn test_lsp_url_map_host_with_port() { let map = LspUrlMap::default(); let fixture = resolve_url("http://localhost:8000/mod.ts").unwrap(); - let actual_url = map - .normalize_specifier(&fixture, None) + let actual_uri = map + .specifier_to_uri(&fixture, None) .expect("could not handle specifier"); - let expected_url = - Url::parse("deno:/http/localhost%3A8000/mod.ts").unwrap(); - assert_eq!(actual_url.as_url(), &expected_url); - - let actual_specifier = - map.normalize_url(actual_url.as_url(), LspUrlKind::File); + assert_eq!(actual_uri.as_str(), "deno:/http/localhost%3A8000/mod.ts"); + let actual_specifier = map.uri_to_specifier(&actual_uri, LspUrlKind::File); assert_eq!(actual_specifier, fixture); } @@ -369,11 +392,11 @@ mod tests { #[test] fn test_normalize_windows_path() { let map = LspUrlMap::default(); - let fixture = resolve_url( + let fixture = Uri::from_str( "file:///c%3A/Users/deno/Desktop/file%20with%20spaces%20in%20name.txt", ) .unwrap(); - let actual = map.normalize_url(&fixture, LspUrlKind::File); + let actual = map.uri_to_specifier(&fixture, LspUrlKind::File); let expected = Url::parse("file:///C:/Users/deno/Desktop/file with spaces in name.txt") .unwrap(); @@ -384,11 +407,11 @@ mod tests { #[test] fn test_normalize_percent_encoded_path() { let map = LspUrlMap::default(); - let fixture = resolve_url( + let fixture = Uri::from_str( "file:///Users/deno/Desktop/file%20with%20spaces%20in%20name.txt", ) .unwrap(); - let actual = map.normalize_url(&fixture, LspUrlKind::File); + let actual = map.uri_to_specifier(&fixture, LspUrlKind::File); let expected = Url::parse("file:///Users/deno/Desktop/file with spaces in name.txt") .unwrap(); @@ -398,9 +421,9 @@ mod tests { #[test] fn test_normalize_deno_status() { let map = LspUrlMap::default(); - let fixture = resolve_url("deno:/status.md").unwrap(); - let actual = map.normalize_url(&fixture, LspUrlKind::File); - assert_eq!(actual, fixture); + let fixture = Uri::from_str("deno:/status.md").unwrap(); + let actual = map.uri_to_specifier(&fixture, LspUrlKind::File); + assert_eq!(actual.as_str(), fixture.as_str()); } #[test] diff --git a/cli/main.rs b/cli/main.rs index 6a7575deec..c2639c9088 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -15,7 +15,6 @@ mod js; mod jsr; mod lsp; mod module_loader; -mod napi; mod node; mod npm; mod ops; @@ -32,13 +31,12 @@ mod worker; use crate::args::flags_from_vec; use crate::args::DenoSubcommand; use crate::args::Flags; -use crate::args::DENO_FUTURE; -use crate::graph_container::ModuleGraphContainer; use crate::util::display; use crate::util::v8::get_v8_flags_from_env; use crate::util::v8::init_v8_flags; use args::TaskFlags; +use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError; use deno_runtime::WorkerExecutionMode; pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS; @@ -52,13 +50,20 @@ use deno_runtime::fmt_errors::format_js_error; use deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics; use deno_terminal::colors; use factory::CliFactory; +use npm::ResolvePkgFolderFromDenoReqError; use standalone::MODULE_NOT_FOUND; +use standalone::UNSUPPORTED_SCHEME; use std::env; use std::future::Future; +use std::io::IsTerminal; use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; +#[cfg(feature = "dhat-heap")] +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + /// Ensures that all subcommands return an i32 exit code and an [`AnyError`] error type. trait SubcommandOutput { fn output(self) -> Result; @@ -110,9 +115,7 @@ async fn run_subcommand(flags: Arc) -> Result { tools::bench::run_benchmarks(flags, bench_flags).await } }), - DenoSubcommand::Bundle(bundle_flags) => spawn_subcommand(async { - tools::bundle::bundle(flags, bundle_flags).await - }), + DenoSubcommand::Bundle => exit_with_message("⚠️ `deno bundle` was removed in Deno 2.\n\nSee the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations", 1), DenoSubcommand::Doc(doc_flags) => { spawn_subcommand(async { tools::doc::doc(flags, doc_flags).await }) } @@ -120,22 +123,10 @@ async fn run_subcommand(flags: Arc) -> Result { tools::run::eval_command(flags, eval_flags).await }), DenoSubcommand::Cache(cache_flags) => spawn_subcommand(async move { - let factory = CliFactory::from_flags(flags); - let emitter = factory.emitter()?; - let main_graph_container = - factory.main_module_graph_container().await?; - main_graph_container - .load_and_type_check_files(&cache_flags.files) - .await?; - emitter.cache_module_emits(&main_graph_container.graph()).await + tools::installer::install_from_entrypoints(flags, &cache_flags.files).await }), DenoSubcommand::Check(check_flags) => spawn_subcommand(async move { - let factory = CliFactory::from_flags(flags); - let main_graph_container = - factory.main_module_graph_container().await?; - main_graph_container - .load_and_type_check_files(&check_flags.files) - .await + tools::check::check(flags, check_flags).await }), DenoSubcommand::Clean => spawn_subcommand(async move { tools::clean::clean() @@ -171,9 +162,21 @@ async fn run_subcommand(flags: Arc) -> Result { tools::jupyter::kernel(flags, jupyter_flags).await }), DenoSubcommand::Uninstall(uninstall_flags) => spawn_subcommand(async { - tools::installer::uninstall(uninstall_flags) + tools::installer::uninstall(flags, uninstall_flags).await + }), + DenoSubcommand::Lsp => spawn_subcommand(async { + if std::io::stderr().is_terminal() { + log::warn!( + "{} command is intended to be run by text editors and IDEs and shouldn't be run manually. + + Visit https://docs.deno.com/runtime/getting_started/setup_your_environment/ for instruction + how to setup your favorite text editor. + + Press Ctrl+C to exit. + ", colors::cyan("deno lsp")); + } + lsp::start().await }), - DenoSubcommand::Lsp => spawn_subcommand(async { lsp::start().await }), DenoSubcommand::Lint(lint_flags) => spawn_subcommand(async { if lint_flags.rules { tools::lint::print_rules_list( @@ -196,7 +199,23 @@ async fn run_subcommand(flags: Arc) -> Result { match result { Ok(v) => Ok(v), Err(script_err) => { - if script_err.to_string().starts_with(MODULE_NOT_FOUND) { + if let Some(ResolvePkgFolderFromDenoReqError::Byonm(ByonmResolvePkgFolderFromDenoReqError::UnmatchedReq(_))) = script_err.downcast_ref::() { + if flags.node_modules_dir.is_none() { + let mut flags = flags.deref().clone(); + let watch = match &flags.subcommand { + DenoSubcommand::Run(run_flags) => run_flags.watch.clone(), + _ => unreachable!(), + }; + flags.node_modules_dir = Some(deno_config::deno_json::NodeModulesDirMode::None); + // use the current lockfile, but don't write it out + if flags.frozen_lockfile.is_none() { + flags.internal.lockfile_skip_write = true; + } + return tools::run::run_script(WorkerExecutionMode::Run, Arc::new(flags), watch).await; + } + } + let script_err_msg = script_err.to_string(); + if script_err_msg.starts_with(MODULE_NOT_FOUND) || script_err_msg.starts_with(UNSUPPORTED_SCHEME) { if run_flags.bare { let mut cmd = args::clap_root(); cmd.build(); @@ -218,9 +237,10 @@ async fn run_subcommand(flags: Arc) -> Result { let task_flags = TaskFlags { cwd: None, task: Some(run_flags.script.clone()), + is_run: true, }; new_flags.subcommand = DenoSubcommand::Task(task_flags.clone()); - let result = tools::task::execute_script(Arc::new(new_flags), task_flags.clone(), true).await; + let result = tools::task::execute_script(Arc::new(new_flags), task_flags.clone()).await; match result { Ok(v) => Ok(v), Err(_) => { @@ -240,7 +260,7 @@ async fn run_subcommand(flags: Arc) -> Result { tools::serve::serve(flags, serve_flags).await }), DenoSubcommand::Task(task_flags) => spawn_subcommand(async { - tools::task::execute_script(flags, task_flags, false).await + tools::task::execute_script(flags, task_flags).await }), DenoSubcommand::Test(test_flags) => { spawn_subcommand(async { @@ -283,14 +303,26 @@ async fn run_subcommand(flags: Arc) -> Result { "This deno was built without the \"upgrade\" feature. Please upgrade using the installation method originally used to install Deno.", 1, ), - DenoSubcommand::Vendor(vendor_flags) => spawn_subcommand(async { - tools::vendor::vendor(flags, vendor_flags).await - }), + DenoSubcommand::Vendor => exit_with_message("⚠️ `deno vendor` was removed in Deno 2.\n\nSee the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations", 1), DenoSubcommand::Publish(publish_flags) => spawn_subcommand(async { tools::registry::publish(flags, publish_flags).await }), DenoSubcommand::Help(help_flags) => spawn_subcommand(async move { - display::write_to_stdout_ignore_sigpipe(help_flags.help.ansi().to_string().as_bytes()) + use std::io::Write; + + let mut stream = anstream::AutoStream::new(std::io::stdout(), if colors::use_color() { + anstream::ColorChoice::Auto + } else { + anstream::ColorChoice::Never + }); + + match stream.write_all(help_flags.help.ansi().to_string().as_bytes()) { + Ok(()) => Ok(()), + Err(e) => match e.kind() { + std::io::ErrorKind::BrokenPipe => Ok(()), + _ => Err(e), + }, + } }), }; @@ -357,19 +389,10 @@ pub(crate) fn unstable_exit_cb(feature: &str, api_name: &str) { std::process::exit(70); } -// TODO(bartlomieju): remove when `--unstable` flag is removed. -#[allow(clippy::print_stderr)] -pub(crate) fn unstable_warn_cb(feature: &str, api_name: &str) { - eprintln!( - "⚠️ {}", - colors::yellow(format!( - "The `{}` API was used with `--unstable` flag. The `--unstable` flag is deprecated and will be removed in Deno 2.0. Use granular `--unstable-{}` instead.\nLearn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags", - api_name, feature - )) - ); -} - pub fn main() { + #[cfg(feature = "dhat-heap")] + let profiler = dhat::Profiler::new_heap(); + setup_panic_hook(); util::unix::raise_fd_limit(); @@ -390,7 +413,12 @@ pub fn main() { run_subcommand(Arc::new(flags)).await }; - match create_and_run_current_thread_with_maybe_metrics(future) { + let result = create_and_run_current_thread_with_maybe_metrics(future); + + #[cfg(feature = "dhat-heap")] + drop(profiler); + + match result { Ok(exit_code) => std::process::exit(exit_code), Err(err) => exit_for_error(err), } @@ -411,25 +439,14 @@ fn resolve_flags_and_init( Err(err) => exit_for_error(AnyError::from(err)), }; - // TODO(bartlomieju): remove when `--unstable` flag is removed. + // TODO(bartlomieju): remove in Deno v2.5 and hard error then. if flags.unstable_config.legacy_flag_enabled { - #[allow(clippy::print_stderr)] - if matches!(flags.subcommand, DenoSubcommand::Check(_)) { - // can't use log crate because that's not setup yet - eprintln!( - "⚠️ {}", - colors::yellow( - "The `--unstable` flag is not needed for `deno check` anymore." - ) - ); - } else { - eprintln!( - "⚠️ {}", - colors::yellow( - "The `--unstable` flag is deprecated and will be removed in Deno 2.0. Use granular `--unstable-*` flags instead.\nLearn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags" - ) - ); - } + log::warn!( + "⚠️ {}", + colors::yellow( + "The `--unstable` flag has been removed in Deno 2.0. Use granular `--unstable-*` flags instead.\nLearn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags" + ) + ); } let default_v8_flags = match flags.subcommand { @@ -437,30 +454,19 @@ fn resolve_flags_and_init( // https://github.com/microsoft/vscode/blob/48d4ba271686e8072fc6674137415bc80d936bc7/extensions/typescript-language-features/src/configuration/configuration.ts#L213-L214 DenoSubcommand::Lsp => vec!["--max-old-space-size=3072".to_string()], _ => { - if *DENO_FUTURE { - // TODO(bartlomieju): I think this can be removed as it's handled by `deno_core` - // and its settings. - // deno_ast removes TypeScript `assert` keywords, so this flag only affects JavaScript - // TODO(petamoriken): Need to check TypeScript `assert` keywords in deno_ast - vec!["--no-harmony-import-assertions".to_string()] - } else { - vec![ - // TODO(bartlomieju): I think this can be removed as it's handled by `deno_core` - // and its settings. - // If we're still in v1.X version we want to support import assertions. - // V8 12.6 unshipped the support by default, so force it by passing a - // flag. - "--harmony-import-assertions".to_string(), - // Verify with DENO_FUTURE for now. - "--no-maglev".to_string(), - ] - } + // TODO(bartlomieju): I think this can be removed as it's handled by `deno_core` + // and its settings. + // deno_ast removes TypeScript `assert` keywords, so this flag only affects JavaScript + // TODO(petamoriken): Need to check TypeScript `assert` keywords in deno_ast + vec!["--no-harmony-import-assertions".to_string()] } }; init_v8_flags(&default_v8_flags, &flags.v8_flags, get_v8_flags_from_env()); - // TODO(bartlomieju): remove last argument in Deno 2. - deno_core::JsRuntime::init_platform(None, !*DENO_FUTURE); + // TODO(bartlomieju): remove last argument once Deploy no longer needs it + deno_core::JsRuntime::init_platform( + None, /* import assertions enabled */ false, + ); util::logger::init(flags.log_level); Ok(flags) diff --git a/cli/mainrt.rs b/cli/mainrt.rs index 02d58fcee1..f5b798f817 100644 --- a/cli/mainrt.rs +++ b/cli/mainrt.rs @@ -88,11 +88,10 @@ fn main() { let standalone = standalone::extract_standalone(Cow::Owned(args)); let future = async move { match standalone { - Ok(Some(future)) => { - let (metadata, eszip) = future.await?; - util::logger::init(metadata.log_level); - load_env_vars(&metadata.env_vars_from_env_file); - let exit_code = standalone::run(eszip, metadata).await?; + Ok(Some(data)) => { + util::logger::init(data.metadata.log_level); + load_env_vars(&data.metadata.env_vars_from_env_file); + let exit_code = standalone::run(data).await?; std::process::exit(exit_code); } Ok(None) => Ok(()), diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 9f52089363..4a020516e7 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -2,7 +2,6 @@ use std::borrow::Cow; use std::cell::RefCell; -use std::collections::HashSet; use std::path::PathBuf; use std::pin::Pin; use std::rc::Rc; @@ -18,13 +17,13 @@ use crate::cache::CodeCache; use crate::cache::FastInsecureHasher; use crate::cache::ParsedSourceCache; use crate::emit::Emitter; -use crate::factory::CliFactory; use crate::graph_container::MainModuleGraphContainer; use crate::graph_container::ModuleGraphContainer; use crate::graph_container::ModuleGraphUpdatePermit; use crate::graph_util::CreateGraphOptions; use crate::graph_util::ModuleGraphBuilder; use crate::node; +use crate::npm::CliNpmResolver; use crate::resolver::CliGraphResolver; use crate::resolver::CliNodeResolver; use crate::resolver::ModuleCodeStringSource; @@ -45,7 +44,6 @@ use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::futures::future::FutureExt; use deno_core::futures::Future; -use deno_core::parking_lot::Mutex; use deno_core::resolve_url; use deno_core::ModuleCodeString; use deno_core::ModuleLoader; @@ -70,54 +68,6 @@ use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use node_resolver::NodeResolutionMode; -pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> { - let npm_resolver = factory.npm_resolver().await?; - let cli_options = factory.cli_options()?; - if let Some(npm_resolver) = npm_resolver.as_managed() { - if !npm_resolver.ensure_top_level_package_json_install().await? { - if let Some(lockfile) = cli_options.maybe_lockfile() { - lockfile.error_if_changed()?; - } - - npm_resolver.cache_packages().await?; - } - } - // cache as many entries in the import map as we can - let resolver = factory.workspace_resolver().await?; - if let Some(import_map) = resolver.maybe_import_map() { - let roots = import_map - .imports() - .entries() - .filter_map(|entry| { - if entry.key.ends_with('/') { - None - } else { - entry.value.cloned() - } - }) - .collect::>(); - let mut graph_permit = factory - .main_module_graph_container() - .await? - .acquire_update_permit() - .await; - let graph = graph_permit.graph_mut(); - factory - .module_load_preparer() - .await? - .prepare_module_load( - graph, - &roots, - false, - factory.cli_options()?.ts_type_lib_window(), - deno_runtime::deno_permissions::PermissionsContainer::allow_all(), - ) - .await?; - } - - Ok(()) -} - pub struct ModuleLoadPreparer { options: Arc, lockfile: Option>, @@ -156,11 +106,32 @@ impl ModuleLoadPreparer { is_dynamic: bool, lib: TsTypeLib, permissions: PermissionsContainer, + ext_overwrite: Option<&String>, ) -> Result<(), AnyError> { log::debug!("Preparing module load."); let _pb_clear_guard = self.progress_bar.clear_guard(); let mut cache = self.module_graph_builder.create_fetch_cacher(permissions); + if let Some(ext) = ext_overwrite { + let maybe_content_type = match ext.as_str() { + "ts" => Some("text/typescript"), + "tsx" => Some("text/tsx"), + "js" => Some("text/javascript"), + "jsx" => Some("text/jsx"), + _ => None, + }; + if let Some(content_type) = maybe_content_type { + for root in roots { + cache.file_header_overrides.insert( + root.clone(), + std::collections::HashMap::from([( + "content-type".to_string(), + content_type.to_string(), + )]), + ); + } + } + } log::debug!("Building module graph."); let has_type_checked = !graph.roots.is_empty(); @@ -233,6 +204,7 @@ struct SharedCliModuleLoaderState { main_module_graph_container: Arc, module_load_preparer: Arc, node_resolver: Arc, + npm_resolver: Arc, npm_module_loader: NpmModuleLoader, parsed_source_cache: Arc, resolver: Arc, @@ -251,6 +223,7 @@ impl CliModuleLoaderFactory { main_module_graph_container: Arc, module_load_preparer: Arc, node_resolver: Arc, + npm_resolver: Arc, npm_module_loader: NpmModuleLoader, parsed_source_cache: Arc, resolver: Arc, @@ -271,6 +244,7 @@ impl CliModuleLoaderFactory { main_module_graph_container, module_load_preparer, node_resolver, + npm_resolver, npm_module_loader, parsed_source_cache, resolver, @@ -282,18 +256,19 @@ impl CliModuleLoaderFactory { &self, graph_container: TGraphContainer, lib: TsTypeLib, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, + is_worker: bool, + parent_permissions: PermissionsContainer, + permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter { let loader = Rc::new(CliModuleLoader(Rc::new(CliModuleLoaderInner { lib, - root_permissions, - dynamic_permissions, + is_worker, + parent_permissions, + permissions, graph_container, emitter: self.shared.emitter.clone(), parsed_source_cache: self.shared.parsed_source_cache.clone(), shared: self.shared.clone(), - prevent_v8_code_cache: Default::default(), }))); ModuleLoaderAndSourceMapGetter { module_loader: loader, @@ -305,20 +280,20 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory { fn create_for_main( &self, root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter { self.create_with_lib( (*self.shared.main_module_graph_container).clone(), self.shared.lib_window, + /* is worker */ false, + root_permissions.clone(), root_permissions, - dynamic_permissions, ) } fn create_for_worker( &self, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, + parent_permissions: PermissionsContainer, + permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter { self.create_with_lib( // create a fresh module graph for the worker @@ -326,29 +301,25 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory { self.shared.graph_kind, ))), self.shared.lib_worker, - root_permissions, - dynamic_permissions, + /* is worker */ true, + parent_permissions, + permissions, ) } } struct CliModuleLoaderInner { lib: TsTypeLib, + is_worker: bool, /// The initial set of permissions used to resolve the static imports in the /// worker. These are "allow all" for main worker, and parent thread /// permissions for Web Worker. - root_permissions: PermissionsContainer, - /// Permissions used to resolve dynamic imports, these get passed as - /// "root permissions" for Web Worker. - dynamic_permissions: PermissionsContainer, + parent_permissions: PermissionsContainer, + permissions: PermissionsContainer, shared: Arc, emitter: Arc, parsed_source_cache: Arc, graph_container: TGraphContainer, - // NOTE(bartlomieju): this is temporary, for deprecated import assertions. - // Should be removed in Deno 2. - // Modules stored here should not be V8 code-cached. - prevent_v8_code_cache: Arc>>, } impl @@ -360,15 +331,23 @@ impl maybe_referrer: Option<&ModuleSpecifier>, requested_module_type: RequestedModuleType, ) -> Result { - let code_source = if let Some(result) = self - .shared - .npm_module_loader - .load_if_in_npm_package(specifier, maybe_referrer) - .await - { - result? - } else { - self.load_prepared_module(specifier, maybe_referrer).await? + let code_source = match self.load_prepared_module(specifier).await? { + Some(code_source) => code_source, + None => { + if self.shared.npm_module_loader.if_in_npm_package(specifier) { + self + .shared + .npm_module_loader + .load(specifier, maybe_referrer) + .await? + } else { + let mut msg = format!("Loading unprepared module: {specifier}"); + if let Some(referrer) = maybe_referrer { + msg = format!("{}, imported from: {}", msg, referrer.as_str()); + } + return Err(anyhow!(msg)); + } + } }; let code = if self.shared.is_inspecting { // we need the code with the source map in order for @@ -450,7 +429,7 @@ impl fn inner_resolve( &self, - specifier: &str, + raw_specifier: &str, referrer: &ModuleSpecifier, ) -> Result { if self.shared.node_resolver.in_npm_package(referrer) { @@ -458,7 +437,7 @@ impl self .shared .node_resolver - .resolve(specifier, referrer, NodeResolutionMode::Execution)? + .resolve(raw_specifier, referrer, NodeResolutionMode::Execution)? .into_url(), ); } @@ -467,7 +446,7 @@ impl let resolution = match graph.get(referrer) { Some(Module::Js(module)) => module .dependencies - .get(specifier) + .get(raw_specifier) .map(|d| &d.maybe_code) .unwrap_or(&Resolution::None), _ => &Resolution::None, @@ -482,7 +461,7 @@ impl )); } Resolution::None => Cow::Owned(self.shared.resolver.resolve( - specifier, + raw_specifier, &deno_graph::Range { specifier: referrer.clone(), start: deno_graph::Position::zeroed(), @@ -511,7 +490,6 @@ impl Some(Module::Npm(module)) => { let package_folder = self .shared - .node_resolver .npm_resolver .as_managed() .unwrap() // byonm won't create a Module::Npm @@ -544,17 +522,12 @@ impl async fn load_prepared_module( &self, specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - ) -> Result { + ) -> Result, AnyError> { // Note: keep this in sync with the sync version below let graph = self.graph_container.graph(); - match self.load_prepared_module_or_defer_emit( - &graph, - specifier, - maybe_referrer, - ) { - Ok(CodeOrDeferredEmit::Code(code_source)) => Ok(code_source), - Ok(CodeOrDeferredEmit::DeferredEmit { + match self.load_prepared_module_or_defer_emit(&graph, specifier)? { + Some(CodeOrDeferredEmit::Code(code_source)) => Ok(Some(code_source)), + Some(CodeOrDeferredEmit::DeferredEmit { specifier, media_type, source, @@ -567,30 +540,26 @@ impl // at this point, we no longer need the parsed source in memory, so free it self.parsed_source_cache.free(specifier); - Ok(ModuleCodeStringSource { - code: ModuleSourceCode::Bytes(transpile_result), + Ok(Some(ModuleCodeStringSource { + // note: it's faster to provide a string if we know it's a string + code: ModuleSourceCode::String(transpile_result.into()), found_url: specifier.clone(), media_type, - }) + })) } - Err(err) => Err(err), + None => Ok(None), } } fn load_prepared_module_sync( &self, specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - ) -> Result { + ) -> Result, AnyError> { // Note: keep this in sync with the async version above let graph = self.graph_container.graph(); - match self.load_prepared_module_or_defer_emit( - &graph, - specifier, - maybe_referrer, - ) { - Ok(CodeOrDeferredEmit::Code(code_source)) => Ok(code_source), - Ok(CodeOrDeferredEmit::DeferredEmit { + match self.load_prepared_module_or_defer_emit(&graph, specifier)? { + Some(CodeOrDeferredEmit::Code(code_source)) => Ok(Some(code_source)), + Some(CodeOrDeferredEmit::DeferredEmit { specifier, media_type, source, @@ -602,13 +571,14 @@ impl // at this point, we no longer need the parsed source in memory, so free it self.parsed_source_cache.free(specifier); - Ok(ModuleCodeStringSource { - code: ModuleSourceCode::Bytes(transpile_result), + Ok(Some(ModuleCodeStringSource { + // note: it's faster to provide a string if we know it's a string + code: ModuleSourceCode::String(transpile_result.into()), found_url: specifier.clone(), media_type, - }) + })) } - Err(err) => Err(err), + None => Ok(None), } } @@ -616,8 +586,7 @@ impl &self, graph: &'graph ModuleGraph, specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - ) -> Result, AnyError> { + ) -> Result>, AnyError> { if specifier.scheme() == "node" { // Node built-in modules should be handled internally. unreachable!("Deno bug. {} was misconfigured internally.", specifier); @@ -629,11 +598,11 @@ impl media_type, specifier, .. - })) => Ok(CodeOrDeferredEmit::Code(ModuleCodeStringSource { + })) => Ok(Some(CodeOrDeferredEmit::Code(ModuleCodeStringSource { code: ModuleSourceCode::String(source.clone().into()), found_url: specifier.clone(), media_type: *media_type, - })), + }))), Some(deno_graph::Module::Js(JsModule { source, media_type, @@ -654,11 +623,11 @@ impl | MediaType::Cts | MediaType::Jsx | MediaType::Tsx => { - return Ok(CodeOrDeferredEmit::DeferredEmit { + return Ok(Some(CodeOrDeferredEmit::DeferredEmit { specifier, media_type: *media_type, source, - }); + })); } MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => { panic!("Unexpected media type {media_type} for {specifier}") @@ -668,24 +637,18 @@ impl // at this point, we no longer need the parsed source in memory, so free it self.parsed_source_cache.free(specifier); - Ok(CodeOrDeferredEmit::Code(ModuleCodeStringSource { + Ok(Some(CodeOrDeferredEmit::Code(ModuleCodeStringSource { code: ModuleSourceCode::String(code), found_url: specifier.clone(), media_type: *media_type, - })) + }))) } Some( deno_graph::Module::External(_) | deno_graph::Module::Node(_) | deno_graph::Module::Npm(_), ) - | None => { - let mut msg = format!("Loading unprepared module: {specifier}"); - if let Some(referrer) = maybe_referrer { - msg = format!("{}, imported from: {}", msg, referrer.as_str()); - } - Err(anyhow!(msg)) - } + | None => Ok(None), } } } @@ -804,11 +767,12 @@ impl ModuleLoader } } - let root_permissions = if is_dynamic { - inner.dynamic_permissions.clone() + let permissions = if is_dynamic { + inner.permissions.clone() } else { - inner.root_permissions.clone() + inner.parent_permissions.clone() }; + let is_dynamic = is_dynamic || inner.is_worker; // consider workers as dynamic for permissions let lib = inner.lib; let mut update_permit = graph_container.acquire_update_permit().await; let graph = update_permit.graph_mut(); @@ -818,7 +782,8 @@ impl ModuleLoader &[specifier], is_dynamic, lib, - root_permissions, + permissions, + None, ) .await?; update_permit.commit(); @@ -834,14 +799,6 @@ impl ModuleLoader code_cache: &[u8], ) -> Pin>> { if let Some(cache) = self.0.shared.code_cache.as_ref() { - if self - .0 - .prevent_v8_code_cache - .lock() - .contains(specifier.as_str()) - { - return std::future::ready(()).boxed_local(); - } // This log line is also used by tests. log::debug!( "Updating V8 code cache for ES module: {specifier}, [{source_hash:?}]" @@ -856,19 +813,6 @@ impl ModuleLoader std::future::ready(()).boxed_local() } - fn purge_and_prevent_code_cache(&self, specifier: &str) { - if let Some(cache) = self.0.shared.code_cache.as_ref() { - // This log line is also used by tests. - log::debug!("Remove V8 code cache for ES module: {specifier}"); - cache.remove_code_cache(specifier); - self - .0 - .prevent_v8_code_cache - .lock() - .insert(specifier.to_string()); - } - } - fn get_source_map(&self, file_name: &str) -> Option> { let specifier = resolve_url(file_name).ok()?; match specifier.scheme() { @@ -877,7 +821,7 @@ impl ModuleLoader "wasm" | "file" | "http" | "https" | "data" | "blob" => (), _ => return None, } - let source = self.0.load_prepared_module_sync(&specifier, None).ok()?; + let source = self.0.load_prepared_module_sync(&specifier).ok()??; source_map_from_code(source.code.as_bytes()) } diff --git a/cli/napi/README.md b/cli/napi/README.md deleted file mode 100644 index 7b359ac6ec..0000000000 --- a/cli/napi/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# napi - -This directory contains source for Deno's Node-API implementation. It depends on -`napi_sym` and `deno_napi`. - -Files are generally organized the same as in Node.js's implementation to ease in -ensuring compatibility. - -## Adding a new function - -Add the symbol name to -[`cli/napi_sym/symbol_exports.json`](../napi_sym/symbol_exports.json). - -```diff -{ - "symbols": [ - ... - "napi_get_undefined", -- "napi_get_null" -+ "napi_get_null", -+ "napi_get_boolean" - ] -} -``` - -Determine where to place the implementation. `napi_get_boolean` is related to JS -values so we will place it in `js_native_api.rs`. If something is not clear, -just create a new file module. - -See [`napi_sym`](../napi_sym/) for writing the implementation: - -```rust -#[napi_sym::napi_sym] -pub fn napi_get_boolean( - env: *mut Env, - value: bool, - result: *mut napi_value, -) -> Result { - // ... - Ok(()) -} -``` - -Update the generated symbol lists using the script: - -``` -deno run --allow-write tools/napi/generate_symbols_lists.js -``` - -Add a test in [`/tests/napi`](../../tests/napi/). You can also refer to Node.js -test suite for Node-API. - -```js -// tests/napi/boolean_test.js -import { assertEquals, loadTestLibrary } from "./common.js"; -const lib = loadTestLibrary(); -Deno.test("napi get boolean", function () { - assertEquals(lib.test_get_boolean(true), true); - assertEquals(lib.test_get_boolean(false), false); -}); -``` - -```rust -// tests/napi/src/boolean.rs - -use napi_sys::Status::napi_ok; -use napi_sys::ValueType::napi_boolean; -use napi_sys::*; - -extern "C" fn test_boolean( - env: napi_env, - info: napi_callback_info, -) -> napi_value { - let (args, argc, _) = crate::get_callback_info!(env, info, 1); - assert_eq!(argc, 1); - - let mut ty = -1; - assert!(unsafe { napi_typeof(env, args[0], &mut ty) } == napi_ok); - assert_eq!(ty, napi_boolean); - - // Use napi_get_boolean here... - - value -} - -pub fn init(env: napi_env, exports: napi_value) { - let properties = &[crate::new_property!(env, "test_boolean\0", test_boolean)]; - - unsafe { - napi_define_properties(env, exports, properties.len(), properties.as_ptr()) - }; -} -``` - -```diff -// tests/napi/src/lib.rs - -+ mod boolean; - -... - -#[no_mangle] -unsafe extern "C" fn napi_register_module_v1( - env: napi_env, - exports: napi_value, -) -> napi_value { - ... -+ boolean::init(env, exports); - - exports -} -``` - -Run the test using `cargo test -p tests/napi`. diff --git a/cli/napi/mod.rs b/cli/napi/mod.rs deleted file mode 100644 index 122d2ff060..0000000000 --- a/cli/napi/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -#![allow(unused_mut)] -#![allow(non_camel_case_types)] -#![allow(clippy::undocumented_unsafe_blocks)] - -//! Symbols to be exported are now defined in this JSON file. -//! The `#[napi_sym]` macro checks for missing entries and panics. -//! -//! `./tools/napi/generate_symbols_list.js` is used to generate the LINK `cli/exports.def` on Windows, -//! which is also checked into git. -//! -//! To add a new napi function: -//! 1. Place `#[napi_sym]` on top of your implementation. -//! 2. Add the function's identifier to this JSON list. -//! 3. Finally, run `tools/napi/generate_symbols_list.js` to update `cli/napi/generated_symbol_exports_list_*.def`. - -pub mod js_native_api; -pub mod node_api; -pub mod util; diff --git a/cli/node.rs b/cli/node.rs index 0fd18e2991..733d5f8717 100644 --- a/cli/node.rs +++ b/cli/node.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; +use deno_graph::ParsedSourceStore; use deno_runtime::deno_fs; use deno_runtime::deno_node::DenoFsNodeResolverEnv; use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis; @@ -16,6 +17,8 @@ use serde::Serialize; use crate::cache::CacheDBHash; use crate::cache::NodeAnalysisCache; +use crate::cache::ParsedSourceCache; +use crate::resolver::CliNodeResolver; use crate::util::fs::canonicalize_path_maybe_not_exists; pub type CliNodeCodeTranslator = @@ -54,11 +57,23 @@ pub enum CliCjsAnalysis { pub struct CliCjsCodeAnalyzer { cache: NodeAnalysisCache, fs: deno_fs::FileSystemRc, + node_resolver: Arc, + parsed_source_cache: Option>, } impl CliCjsCodeAnalyzer { - pub fn new(cache: NodeAnalysisCache, fs: deno_fs::FileSystemRc) -> Self { - Self { cache, fs } + pub fn new( + cache: NodeAnalysisCache, + fs: deno_fs::FileSystemRc, + node_resolver: Arc, + parsed_source_cache: Option>, + ) -> Self { + Self { + cache, + fs, + node_resolver, + parsed_source_cache, + } } async fn inner_cjs_analysis( @@ -73,7 +88,7 @@ impl CliCjsCodeAnalyzer { return Ok(analysis); } - let media_type = MediaType::from_specifier(specifier); + let mut media_type = MediaType::from_specifier(specifier); if media_type == MediaType::Json { return Ok(CliCjsAnalysis::Cjs { exports: vec![], @@ -81,24 +96,55 @@ impl CliCjsCodeAnalyzer { }); } + if media_type == MediaType::JavaScript { + if let Some(package_json) = + self.node_resolver.get_closest_package_json(specifier)? + { + match package_json.typ.as_str() { + "commonjs" => { + media_type = MediaType::Cjs; + } + "module" => { + media_type = MediaType::Mjs; + } + _ => {} + } + } + } + + let maybe_parsed_source = self + .parsed_source_cache + .as_ref() + .and_then(|c| c.remove_parsed_source(specifier)); + let analysis = deno_core::unsync::spawn_blocking({ let specifier = specifier.clone(); let source: Arc = source.into(); move || -> Result<_, deno_ast::ParseDiagnostic> { - let parsed_source = deno_ast::parse_program(deno_ast::ParseParams { - specifier, - text: source, - media_type, - capture_tokens: true, - scope_analysis: false, - maybe_syntax: None, - })?; + let parsed_source = + maybe_parsed_source.map(Ok).unwrap_or_else(|| { + deno_ast::parse_program(deno_ast::ParseParams { + specifier, + text: source, + media_type, + capture_tokens: true, + scope_analysis: false, + maybe_syntax: None, + }) + })?; if parsed_source.is_script() { let analysis = parsed_source.analyze_cjs(); Ok(CliCjsAnalysis::Cjs { exports: analysis.exports, reexports: analysis.reexports, }) + } else if media_type == MediaType::Cjs { + // FIXME: `deno_ast` should internally handle MediaType::Cjs implying that + // the result must never be Esm + Ok(CliCjsAnalysis::Cjs { + exports: vec![], + reexports: vec![], + }) } else { Ok(CliCjsAnalysis::Esm) } @@ -125,10 +171,23 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer { let source = match source { Some(source) => source, None => { - self - .fs - .read_text_file_lossy_async(specifier.to_file_path().unwrap(), None) - .await? + if let Ok(path) = specifier.to_file_path() { + if let Ok(source_from_file) = + self.fs.read_text_file_lossy_async(path, None).await + { + source_from_file + } else { + return Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports { + exports: vec![], + reexports: vec![], + })); + } + } else { + return Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports { + exports: vec![], + reexports: vec![], + })); + } } }; let analysis = self.inner_cjs_analysis(specifier, &source).await?; diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs index a0f23fc66b..fc095ab16f 100644 --- a/cli/npm/byonm.rs +++ b/cli/npm/byonm.rs @@ -5,317 +5,99 @@ use std::path::Path; use std::path::PathBuf; use std::sync::Arc; -use deno_ast::ModuleSpecifier; -use deno_core::anyhow::bail; use deno_core::error::AnyError; use deno_core::serde_json; -use deno_package_json::PackageJsonDepValue; -use deno_runtime::deno_fs::FileSystem; -use deno_runtime::deno_node::DenoPkgJsonFsAdapter; +use deno_core::url::Url; +use deno_resolver::npm::ByonmNpmResolver; +use deno_resolver::npm::ByonmNpmResolverCreateOptions; use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeRequireResolver; -use deno_runtime::deno_node::NpmProcessStateProvider; -use deno_runtime::deno_node::PackageJson; +use deno_runtime::ops::process::NpmProcessStateProvider; use deno_semver::package::PackageReq; -use node_resolver::errors::PackageFolderResolveError; -use node_resolver::errors::PackageFolderResolveIoError; -use node_resolver::errors::PackageJsonLoadError; -use node_resolver::errors::PackageNotFoundError; -use node_resolver::load_pkg_json; use node_resolver::NpmResolver; use crate::args::NpmProcessState; use crate::args::NpmProcessStateKind; -use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs; -use deno_runtime::fs_util::specifier_to_file_path; +use crate::resolver::CliDenoResolverFs; use super::CliNpmResolver; use super::InnerCliNpmResolverRef; +use super::ResolvePkgFolderFromDenoReqError; -pub struct CliNpmResolverByonmCreateOptions { - pub fs: Arc, - // todo(dsherret): investigate removing this - pub root_node_modules_dir: Option, -} - -pub fn create_byonm_npm_resolver( - options: CliNpmResolverByonmCreateOptions, -) -> Arc { - Arc::new(ByonmCliNpmResolver { - fs: options.fs, - root_node_modules_dir: options.root_node_modules_dir, - }) -} +pub type CliByonmNpmResolverCreateOptions = + ByonmNpmResolverCreateOptions; +pub type CliByonmNpmResolver = ByonmNpmResolver; +// todo(dsherret): the services hanging off `CliNpmResolver` doesn't seem ideal. We should probably decouple. #[derive(Debug)] -pub struct ByonmCliNpmResolver { - fs: Arc, - root_node_modules_dir: Option, -} +struct CliByonmWrapper(Arc); -impl ByonmCliNpmResolver { - fn load_pkg_json( - &self, - path: &Path, - ) -> Result>, PackageJsonLoadError> { - load_pkg_json(&DenoPkgJsonFsAdapter(self.fs.as_ref()), path) - } -} - -impl ByonmCliNpmResolver { - /// Finds the ancestor package.json that contains the specified dependency. - pub fn find_ancestor_package_json_with_dep( - &self, - dep_name: &str, - referrer: &ModuleSpecifier, - ) -> Option> { - let referrer_path = referrer.to_file_path().ok()?; - let mut current_folder = referrer_path.parent()?; - loop { - let pkg_json_path = current_folder.join("package.json"); - if let Ok(Some(pkg_json)) = self.load_pkg_json(&pkg_json_path) { - if let Some(deps) = &pkg_json.dependencies { - if deps.contains_key(dep_name) { - return Some(pkg_json); - } - } - if let Some(deps) = &pkg_json.dev_dependencies { - if deps.contains_key(dep_name) { - return Some(pkg_json); - } - } - } - - if let Some(parent) = current_folder.parent() { - current_folder = parent; - } else { - return None; - } - } - } - - fn resolve_pkg_json_and_alias_for_req( - &self, - req: &PackageReq, - referrer: &ModuleSpecifier, - ) -> Result<(Arc, String), AnyError> { - fn resolve_alias_from_pkg_json( - req: &PackageReq, - pkg_json: &PackageJson, - ) -> Option { - let deps = pkg_json.resolve_local_package_json_deps(); - for (key, value) in deps { - if let Ok(value) = value { - match value { - PackageJsonDepValue::Req(dep_req) => { - if dep_req.name == req.name - && dep_req.version_req.intersects(&req.version_req) - { - return Some(key); - } - } - PackageJsonDepValue::Workspace(_workspace) => { - if key == req.name && req.version_req.tag() == Some("workspace") { - return Some(key); - } - } - } - } - } - None - } - - // attempt to resolve the npm specifier from the referrer's package.json, - if let Ok(file_path) = specifier_to_file_path(referrer) { - let mut current_path = file_path.as_path(); - while let Some(dir_path) = current_path.parent() { - let package_json_path = dir_path.join("package.json"); - if let Some(pkg_json) = self.load_pkg_json(&package_json_path)? { - if let Some(alias) = - resolve_alias_from_pkg_json(req, pkg_json.as_ref()) - { - return Ok((pkg_json, alias)); - } - } - current_path = dir_path; - } - } - - // otherwise, fall fallback to the project's package.json - if let Some(root_node_modules_dir) = &self.root_node_modules_dir { - let root_pkg_json_path = - root_node_modules_dir.parent().unwrap().join("package.json"); - if let Some(pkg_json) = self.load_pkg_json(&root_pkg_json_path)? { - if let Some(alias) = resolve_alias_from_pkg_json(req, pkg_json.as_ref()) - { - return Ok((pkg_json, alias)); - } - } - } - - bail!( - concat!( - "Could not find a matching package for 'npm:{}' in a package.json file. ", - "You must specify this as a package.json dependency when the ", - "node_modules folder is not managed by Deno.", - ), - req, - ); - } -} - -impl NpmResolver for ByonmCliNpmResolver { - fn resolve_package_folder_from_package( - &self, - name: &str, - referrer: &ModuleSpecifier, - ) -> Result { - fn inner( - fs: &dyn FileSystem, - name: &str, - referrer: &ModuleSpecifier, - ) -> Result { - let maybe_referrer_file = specifier_to_file_path(referrer).ok(); - let maybe_start_folder = - maybe_referrer_file.as_ref().and_then(|f| f.parent()); - if let Some(start_folder) = maybe_start_folder { - for current_folder in start_folder.ancestors() { - let node_modules_folder = if current_folder.ends_with("node_modules") - { - Cow::Borrowed(current_folder) - } else { - Cow::Owned(current_folder.join("node_modules")) - }; - - let sub_dir = join_package_name(&node_modules_folder, name); - if fs.is_dir_sync(&sub_dir) { - return Ok(sub_dir); - } - } - } - - Err( - PackageNotFoundError { - package_name: name.to_string(), - referrer: referrer.clone(), - referrer_extra: None, - } - .into(), - ) - } - - let path = inner(&*self.fs, name, referrer)?; - self.fs.realpath_sync(&path).map_err(|err| { - PackageFolderResolveIoError { - package_name: name.to_string(), - referrer: referrer.clone(), - source: err.into_io_error(), - } - .into() - }) - } - - fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { - specifier.scheme() == "file" - && specifier - .path() - .to_ascii_lowercase() - .contains("/node_modules/") - } -} - -impl NodeRequireResolver for ByonmCliNpmResolver { - fn ensure_read_permission( +impl NodeRequireResolver for CliByonmWrapper { + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { + path: &'a Path, + ) -> Result, AnyError> { if !path .components() .any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules") { - permissions.check_read(path)?; + permissions.check_read_path(path) + } else { + Ok(Cow::Borrowed(path)) } - Ok(()) } } -impl NpmProcessStateProvider for ByonmCliNpmResolver { +impl NpmProcessStateProvider for CliByonmWrapper { fn get_npm_process_state(&self) -> String { serde_json::to_string(&NpmProcessState { kind: NpmProcessStateKind::Byonm, local_node_modules_path: self - .root_node_modules_dir - .as_ref() + .0 + .root_node_modules_dir() .map(|p| p.to_string_lossy().to_string()), }) .unwrap() } } -impl CliNpmResolver for ByonmCliNpmResolver { +impl CliNpmResolver for CliByonmNpmResolver { fn into_npm_resolver(self: Arc) -> Arc { self } fn into_require_resolver(self: Arc) -> Arc { - self + Arc::new(CliByonmWrapper(self)) } fn into_process_state_provider( self: Arc, ) -> Arc { - self + Arc::new(CliByonmWrapper(self)) } fn clone_snapshotted(&self) -> Arc { - Arc::new(Self { - fs: self.fs.clone(), - root_node_modules_dir: self.root_node_modules_dir.clone(), - }) + Arc::new(self.clone()) } fn as_inner(&self) -> InnerCliNpmResolverRef { InnerCliNpmResolverRef::Byonm(self) } - fn root_node_modules_path(&self) -> Option<&PathBuf> { - self.root_node_modules_dir.as_ref() + fn root_node_modules_path(&self) -> Option<&Path> { + self.root_node_modules_dir() } fn resolve_pkg_folder_from_deno_module_req( &self, req: &PackageReq, - referrer: &ModuleSpecifier, - ) -> Result { - // resolve the pkg json and alias - let (pkg_json, alias) = - self.resolve_pkg_json_and_alias_for_req(req, referrer)?; - // now try node resolution - for ancestor in pkg_json.path.parent().unwrap().ancestors() { - let node_modules_folder = ancestor.join("node_modules"); - let sub_dir = join_package_name(&node_modules_folder, &alias); - if self.fs.is_dir_sync(&sub_dir) { - return Ok(canonicalize_path_maybe_not_exists_with_fs( - &sub_dir, - self.fs.as_ref(), - )?); - } - } - - bail!( - concat!( - "Could not find \"{}\" in a node_modules folder. ", - "Deno expects the node_modules/ directory to be up to date. ", - "Did you forget to run `{}`?" - ), - alias, - if *crate::args::DENO_FUTURE { - "deno install" - } else { - "npm install" - } - ); + referrer: &Url, + ) -> Result { + ByonmNpmResolver::resolve_pkg_folder_from_deno_module_req( + self, req, referrer, + ) + .map_err(ResolvePkgFolderFromDenoReqError::Byonm) } fn check_state_hash(&self) -> Option { @@ -324,12 +106,3 @@ impl CliNpmResolver for ByonmCliNpmResolver { None } } - -fn join_package_name(path: &Path, package_name: &str) -> PathBuf { - let mut path = path.to_path_buf(); - // ensure backslashes are used on windows - for part in package_name.split('/') { - path = path.join(part); - } - path -} diff --git a/cli/npm/cache_dir.rs b/cli/npm/cache_dir.rs deleted file mode 100644 index 4467d685ec..0000000000 --- a/cli/npm/cache_dir.rs +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::path::Path; -use std::path::PathBuf; - -use deno_ast::ModuleSpecifier; -use deno_core::anyhow::Context; -use deno_core::error::AnyError; -use deno_core::url::Url; -use deno_npm::NpmPackageCacheFolderId; -use deno_semver::package::PackageNv; -use deno_semver::Version; - -use crate::util::fs::canonicalize_path; -use crate::util::path::root_url_to_safe_local_dirname; - -/// The global cache directory of npm packages. -#[derive(Clone, Debug)] -pub struct NpmCacheDir { - root_dir: PathBuf, - // cached url representation of the root directory - root_dir_url: Url, - // A list of all registry that were discovered via `.npmrc` files - // turned into a safe directory names. - known_registries_dirnames: Vec, -} - -impl NpmCacheDir { - pub fn new(root_dir: PathBuf, known_registries_urls: Vec) -> Self { - fn try_get_canonicalized_root_dir( - root_dir: &Path, - ) -> Result { - if !root_dir.exists() { - std::fs::create_dir_all(root_dir) - .with_context(|| format!("Error creating {}", root_dir.display()))?; - } - Ok(canonicalize_path(root_dir)?) - } - - // this may fail on readonly file systems, so just ignore if so - let root_dir = - try_get_canonicalized_root_dir(&root_dir).unwrap_or(root_dir); - let root_dir_url = Url::from_directory_path(&root_dir).unwrap(); - - let known_registries_dirnames: Vec<_> = known_registries_urls - .into_iter() - .map(|url| { - root_url_to_safe_local_dirname(&url) - .to_string_lossy() - .replace('\\', "/") - }) - .collect(); - - Self { - root_dir, - root_dir_url, - known_registries_dirnames, - } - } - - pub fn root_dir(&self) -> &Path { - &self.root_dir - } - - pub fn root_dir_url(&self) -> &Url { - &self.root_dir_url - } - - pub fn package_folder_for_id( - &self, - folder_id: &NpmPackageCacheFolderId, - registry_url: &Url, - ) -> PathBuf { - if folder_id.copy_index == 0 { - self.package_folder_for_nv(&folder_id.nv, registry_url) - } else { - self - .package_name_folder(&folder_id.nv.name, registry_url) - .join(format!("{}_{}", folder_id.nv.version, folder_id.copy_index)) - } - } - - pub fn package_folder_for_nv( - &self, - package: &PackageNv, - registry_url: &Url, - ) -> PathBuf { - self - .package_name_folder(&package.name, registry_url) - .join(package.version.to_string()) - } - - pub fn package_name_folder(&self, name: &str, registry_url: &Url) -> PathBuf { - let mut dir = self.registry_folder(registry_url); - if name.to_lowercase() != name { - let encoded_name = mixed_case_package_name_encode(name); - // Using the encoded directory may have a collision with an actual package name - // so prefix it with an underscore since npm packages can't start with that - dir.join(format!("_{encoded_name}")) - } else { - // ensure backslashes are used on windows - for part in name.split('/') { - dir = dir.join(part); - } - dir - } - } - - fn registry_folder(&self, registry_url: &Url) -> PathBuf { - self - .root_dir - .join(root_url_to_safe_local_dirname(registry_url)) - } - - pub fn resolve_package_folder_id_from_specifier( - &self, - specifier: &ModuleSpecifier, - ) -> Option { - let mut maybe_relative_url = None; - - // Iterate through known registries and try to get a match. - for registry_dirname in &self.known_registries_dirnames { - let registry_root_dir = self - .root_dir_url - .join(&format!("{}/", registry_dirname)) - // this not succeeding indicates a fatal issue, so unwrap - .unwrap(); - - let Some(relative_url) = registry_root_dir.make_relative(specifier) - else { - continue; - }; - - if relative_url.starts_with("../") { - continue; - } - - maybe_relative_url = Some(relative_url); - break; - } - - let mut relative_url = maybe_relative_url?; - - // base32 decode the url if it starts with an underscore - // * Ex. _{base32(package_name)}/ - if let Some(end_url) = relative_url.strip_prefix('_') { - let mut parts = end_url - .split('/') - .map(ToOwned::to_owned) - .collect::>(); - match mixed_case_package_name_decode(&parts[0]) { - Some(part) => { - parts[0] = part; - } - None => return None, - } - relative_url = parts.join("/"); - } - - // examples: - // * chalk/5.0.1/ - // * @types/chalk/5.0.1/ - // * some-package/5.0.1_1/ -- where the `_1` (/_\d+/) is a copy of the folder for peer deps - let is_scoped_package = relative_url.starts_with('@'); - let mut parts = relative_url - .split('/') - .enumerate() - .take(if is_scoped_package { 3 } else { 2 }) - .map(|(_, part)| part) - .collect::>(); - if parts.len() < 2 { - return None; - } - let version_part = parts.pop().unwrap(); - let name = parts.join("/"); - let (version, copy_index) = - if let Some((version, copy_count)) = version_part.split_once('_') { - (version, copy_count.parse::().ok()?) - } else { - (version_part, 0) - }; - Some(NpmPackageCacheFolderId { - nv: PackageNv { - name, - version: Version::parse_from_npm(version).ok()?, - }, - copy_index, - }) - } - - pub fn get_cache_location(&self) -> PathBuf { - self.root_dir.clone() - } -} - -pub fn mixed_case_package_name_encode(name: &str) -> String { - // use base32 encoding because it's reversible and the character set - // only includes the characters within 0-9 and A-Z so it can be lower cased - base32::encode( - base32::Alphabet::Rfc4648Lower { padding: false }, - name.as_bytes(), - ) - .to_lowercase() -} - -pub fn mixed_case_package_name_decode(name: &str) -> Option { - base32::decode(base32::Alphabet::Rfc4648Lower { padding: false }, name) - .and_then(|b| String::from_utf8(b).ok()) -} - -#[cfg(test)] -mod test { - use deno_core::url::Url; - use deno_semver::package::PackageNv; - use deno_semver::Version; - - use super::NpmCacheDir; - use crate::npm::cache_dir::NpmPackageCacheFolderId; - - #[test] - fn should_get_package_folder() { - let deno_dir = crate::cache::DenoDir::new(None).unwrap(); - let root_dir = deno_dir.npm_folder_path(); - let registry_url = Url::parse("https://registry.npmjs.org/").unwrap(); - let cache = NpmCacheDir::new(root_dir.clone(), vec![registry_url.clone()]); - - assert_eq!( - cache.package_folder_for_id( - &NpmPackageCacheFolderId { - nv: PackageNv { - name: "json".to_string(), - version: Version::parse_from_npm("1.2.5").unwrap(), - }, - copy_index: 0, - }, - ®istry_url, - ), - root_dir - .join("registry.npmjs.org") - .join("json") - .join("1.2.5"), - ); - - assert_eq!( - cache.package_folder_for_id( - &NpmPackageCacheFolderId { - nv: PackageNv { - name: "json".to_string(), - version: Version::parse_from_npm("1.2.5").unwrap(), - }, - copy_index: 1, - }, - ®istry_url, - ), - root_dir - .join("registry.npmjs.org") - .join("json") - .join("1.2.5_1"), - ); - - assert_eq!( - cache.package_folder_for_id( - &NpmPackageCacheFolderId { - nv: PackageNv { - name: "JSON".to_string(), - version: Version::parse_from_npm("2.1.5").unwrap(), - }, - copy_index: 0, - }, - ®istry_url, - ), - root_dir - .join("registry.npmjs.org") - .join("_jjju6tq") - .join("2.1.5"), - ); - - assert_eq!( - cache.package_folder_for_id( - &NpmPackageCacheFolderId { - nv: PackageNv { - name: "@types/JSON".to_string(), - version: Version::parse_from_npm("2.1.5").unwrap(), - }, - copy_index: 0, - }, - ®istry_url, - ), - root_dir - .join("registry.npmjs.org") - .join("_ib2hs4dfomxuuu2pjy") - .join("2.1.5"), - ); - } -} diff --git a/cli/npm/common.rs b/cli/npm/common.rs index a3a828e745..de282310a1 100644 --- a/cli/npm/common.rs +++ b/cli/npm/common.rs @@ -40,7 +40,7 @@ pub fn maybe_auth_header_for_npm_registry( header::AUTHORIZATION, header::HeaderValue::from_str(&format!( "Basic {}", - BASE64_STANDARD.encode(&format!( + BASE64_STANDARD.encode(format!( "{}:{}", username.unwrap(), password.unwrap() diff --git a/cli/npm/managed/cache/mod.rs b/cli/npm/managed/cache/mod.rs index f409744b98..aaec486681 100644 --- a/cli/npm/managed/cache/mod.rs +++ b/cli/npm/managed/cache/mod.rs @@ -8,6 +8,7 @@ use std::path::PathBuf; use std::sync::Arc; use deno_ast::ModuleSpecifier; +use deno_cache_dir::npm::NpmCacheDir; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; @@ -18,14 +19,14 @@ use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageInfo; use deno_npm::NpmPackageCacheFolderId; use deno_semver::package::PackageNv; +use deno_semver::Version; use crate::args::CacheSetting; use crate::cache::CACHE_PERM; -use crate::npm::NpmCacheDir; use crate::util::fs::atomic_write_file_with_retries; use crate::util::fs::hard_link_dir_recursive; -mod registry_info; +pub mod registry_info; mod tarball; mod tarball_extract; @@ -87,9 +88,12 @@ impl NpmCache { ) -> Result<(), AnyError> { let registry_url = self.npmrc.get_registry_url(&folder_id.nv.name); assert_ne!(folder_id.copy_index, 0); - let package_folder = self - .cache_dir - .package_folder_for_id(folder_id, registry_url); + let package_folder = self.cache_dir.package_folder_for_id( + &folder_id.nv.name, + &folder_id.nv.version.to_string(), + folder_id.copy_index, + registry_url, + ); if package_folder.exists() // if this file exists, then the package didn't successfully initialize @@ -100,9 +104,12 @@ impl NpmCache { return Ok(()); } - let original_package_folder = self - .cache_dir - .package_folder_for_nv(&folder_id.nv, registry_url); + let original_package_folder = self.cache_dir.package_folder_for_id( + &folder_id.nv.name, + &folder_id.nv.version.to_string(), + 0, // original copy index + registry_url, + ); // it seems Windows does an "AccessDenied" error when moving a // directory with hard links, so that's why this solution is done @@ -114,7 +121,12 @@ impl NpmCache { pub fn package_folder_for_id(&self, id: &NpmPackageCacheFolderId) -> PathBuf { let registry_url = self.npmrc.get_registry_url(&id.nv.name); - self.cache_dir.package_folder_for_id(id, registry_url) + self.cache_dir.package_folder_for_id( + &id.nv.name, + &id.nv.version.to_string(), + id.copy_index, + registry_url, + ) } pub fn package_folder_for_nv(&self, package: &PackageNv) -> PathBuf { @@ -127,7 +139,12 @@ impl NpmCache { package: &PackageNv, registry_url: &Url, ) -> PathBuf { - self.cache_dir.package_folder_for_nv(package, registry_url) + self.cache_dir.package_folder_for_id( + &package.name, + &package.version.to_string(), + 0, // original copy_index + registry_url, + ) } pub fn package_name_folder(&self, name: &str) -> PathBuf { @@ -146,6 +163,15 @@ impl NpmCache { self .cache_dir .resolve_package_folder_id_from_specifier(specifier) + .and_then(|cache_id| { + Some(NpmPackageCacheFolderId { + nv: PackageNv { + name: cache_id.name, + version: Version::parse_from_npm(&cache_id.version).ok()?, + }, + copy_index: cache_id.copy_index, + }) + }) } pub fn load_package_info( diff --git a/cli/npm/managed/cache/registry_info.rs b/cli/npm/managed/cache/registry_info.rs index 28b19373e9..6d39d3c13f 100644 --- a/cli/npm/managed/cache/registry_info.rs +++ b/cli/npm/managed/cache/registry_info.rs @@ -84,7 +84,7 @@ impl RegistryInfoDownloader { self.load_package_info_inner(name).await.with_context(|| { format!( "Error getting response at {} for package \"{}\"", - self.get_package_url(name), + get_package_url(&self.npmrc, name), name ) }) @@ -190,7 +190,7 @@ impl RegistryInfoDownloader { fn create_load_future(self: &Arc, name: &str) -> LoadFuture { let downloader = self.clone(); - let package_url = self.get_package_url(name); + let package_url = get_package_url(&self.npmrc, name); let registry_config = self.npmrc.get_registry_config(name); let maybe_auth_header = match maybe_auth_header_for_npm_registry(registry_config) { @@ -202,10 +202,13 @@ impl RegistryInfoDownloader { let guard = self.progress_bar.update(package_url.as_str()); let name = name.to_string(); async move { - let maybe_bytes = downloader - .http_client_provider - .get_or_create()? - .download_with_progress(package_url, maybe_auth_header, &guard) + let client = downloader.http_client_provider.get_or_create()?; + let maybe_bytes = client + .download_with_progress_and_retries( + package_url, + maybe_auth_header, + &guard, + ) .await?; match maybe_bytes { Some(bytes) => { @@ -236,25 +239,36 @@ impl RegistryInfoDownloader { .map(|r| r.map_err(Arc::new)) .boxed_local() } - - fn get_package_url(&self, name: &str) -> Url { - let registry_url = self.npmrc.get_registry_url(name); - // list of all characters used in npm packages: - // !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~ - const ASCII_SET: percent_encoding::AsciiSet = - percent_encoding::NON_ALPHANUMERIC - .remove(b'!') - .remove(b'\'') - .remove(b'(') - .remove(b')') - .remove(b'*') - .remove(b'-') - .remove(b'.') - .remove(b'/') - .remove(b'@') - .remove(b'_') - .remove(b'~'); - let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET); - registry_url.join(&name.to_string()).unwrap() - } +} + +pub fn get_package_url(npmrc: &ResolvedNpmRc, name: &str) -> Url { + let registry_url = npmrc.get_registry_url(name); + // The '/' character in scoped package names "@scope/name" must be + // encoded for older third party registries. Newer registries and + // npm itself support both ways + // - encoded: https://registry.npmjs.org/@rollup%2fplugin-json + // - non-ecoded: https://registry.npmjs.org/@rollup/plugin-json + // To support as many third party registries as possible we'll + // always encode the '/' character. + + // list of all characters used in npm packages: + // !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~ + const ASCII_SET: percent_encoding::AsciiSet = + percent_encoding::NON_ALPHANUMERIC + .remove(b'!') + .remove(b'\'') + .remove(b'(') + .remove(b')') + .remove(b'*') + .remove(b'-') + .remove(b'.') + .remove(b'@') + .remove(b'_') + .remove(b'~'); + let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET); + registry_url + // Ensure that scoped package name percent encoding is lower cased + // to match npm. + .join(&name.to_string().replace("%2F", "%2f")) + .unwrap() } diff --git a/cli/npm/managed/cache/tarball.rs b/cli/npm/managed/cache/tarball.rs index 4bcee38ea8..7cf88d6d64 100644 --- a/cli/npm/managed/cache/tarball.rs +++ b/cli/npm/managed/cache/tarball.rs @@ -172,7 +172,7 @@ impl TarballCache { let guard = tarball_cache.progress_bar.update(&dist.tarball); let result = tarball_cache.http_client_provider .get_or_create()? - .download_with_progress(tarball_uri, maybe_auth_header, &guard) + .download_with_progress_and_retries(tarball_uri, maybe_auth_header, &guard) .await; let maybe_bytes = match result { Ok(maybe_bytes) => maybe_bytes, diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs index 8f82ddea20..d0880557fe 100644 --- a/cli/npm/managed/mod.rs +++ b/cli/npm/managed/mod.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -7,6 +8,7 @@ use std::sync::Arc; use cache::RegistryInfoDownloader; use cache::TarballCache; use deno_ast::ModuleSpecifier; +use deno_cache_dir::npm::NpmCacheDir; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::serde_json; @@ -19,10 +21,11 @@ use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; +use deno_runtime::colors; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeRequireResolver; -use deno_runtime::deno_node::NpmProcessStateProvider; +use deno_runtime::ops::process::NpmProcessStateProvider; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use node_resolver::errors::PackageFolderResolveError; @@ -32,9 +35,10 @@ use resolution::AddPkgReqsResult; use crate::args::CliLockfile; use crate::args::LifecycleScriptsConfig; +use crate::args::NpmInstallDepsProvider; use crate::args::NpmProcessState; use crate::args::NpmProcessStateKind; -use crate::args::PackageJsonInstallDepsProvider; +use crate::cache::DenoCacheEnvFsAdapter; use crate::cache::FastInsecureHasher; use crate::http_util::HttpClientProvider; use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs; @@ -49,9 +53,9 @@ use self::resolvers::NpmPackageFsResolver; use super::CliNpmResolver; use super::InnerCliNpmResolverRef; -use super::NpmCacheDir; +use super::ResolvePkgFolderFromDenoReqError; -mod cache; +pub mod cache; mod registry; mod resolution; mod resolvers; @@ -71,7 +75,7 @@ pub struct CliNpmResolverManagedCreateOptions { pub text_only_progress_bar: crate::util::progress_bar::ProgressBar, pub maybe_node_modules_path: Option, pub npm_system_info: NpmSystemInfo, - pub package_json_deps_provider: Arc, + pub npm_install_deps_provider: Arc, pub npmrc: Arc, pub lifecycle_scripts: LifecycleScriptsConfig, } @@ -97,7 +101,7 @@ pub async fn create_managed_npm_resolver_for_lsp( npm_api, npm_cache, options.npmrc, - options.package_json_deps_provider, + options.npm_install_deps_provider, options.text_only_progress_bar, options.maybe_node_modules_path, options.npm_system_info, @@ -122,7 +126,7 @@ pub async fn create_managed_npm_resolver( npm_api, npm_cache, options.npmrc, - options.package_json_deps_provider, + options.npm_install_deps_provider, options.text_only_progress_bar, options.maybe_node_modules_path, options.npm_system_info, @@ -139,7 +143,7 @@ fn create_inner( npm_api: Arc, npm_cache: Arc, npm_rc: Arc, - package_json_deps_provider: Arc, + npm_install_deps_provider: Arc, text_only_progress_bar: crate::util::progress_bar::ProgressBar, node_modules_dir_path: Option, npm_system_info: NpmSystemInfo, @@ -161,7 +165,7 @@ fn create_inner( let fs_resolver = create_npm_fs_resolver( fs.clone(), npm_cache.clone(), - &package_json_deps_provider, + &npm_install_deps_provider, &text_only_progress_bar, resolution.clone(), tarball_cache.clone(), @@ -175,7 +179,7 @@ fn create_inner( maybe_lockfile, npm_api, npm_cache, - package_json_deps_provider, + npm_install_deps_provider, resolution, tarball_cache, text_only_progress_bar, @@ -187,6 +191,7 @@ fn create_inner( fn create_cache(options: &CliNpmResolverManagedCreateOptions) -> Arc { Arc::new(NpmCache::new( NpmCacheDir::new( + &DenoCacheEnvFsAdapter(options.fs.as_ref()), options.npm_global_cache_dir.clone(), options.npmrc.get_all_known_registries_urls(), ), @@ -261,7 +266,7 @@ pub struct ManagedCliNpmResolver { maybe_lockfile: Option>, npm_api: Arc, npm_cache: Arc, - package_json_deps_provider: Arc, + npm_install_deps_provider: Arc, resolution: Arc, tarball_cache: Arc, text_only_progress_bar: ProgressBar, @@ -286,7 +291,7 @@ impl ManagedCliNpmResolver { maybe_lockfile: Option>, npm_api: Arc, npm_cache: Arc, - package_json_deps_provider: Arc, + npm_install_deps_provider: Arc, resolution: Arc, tarball_cache: Arc, text_only_progress_bar: ProgressBar, @@ -299,7 +304,7 @@ impl ManagedCliNpmResolver { maybe_lockfile, npm_api, npm_cache, - package_json_deps_provider, + npm_install_deps_provider, text_only_progress_bar, resolution, tarball_cache, @@ -406,8 +411,7 @@ impl ManagedCliNpmResolver { } } if result.dependencies_result.is_ok() { - result.dependencies_result = - self.cache_packages().await.map_err(AnyError::from); + result.dependencies_result = self.cache_packages().await; } result @@ -427,6 +431,16 @@ impl ManagedCliNpmResolver { self.resolution.snapshot() } + pub fn top_package_req_for_name(&self, name: &str) -> Option { + let package_reqs = self.resolution.package_reqs(); + let mut entries = package_reqs + .iter() + .filter(|(_, nv)| nv.name == name) + .collect::>(); + entries.sort_by_key(|(_, nv)| &nv.version); + Some(entries.last()?.0.clone()) + } + pub fn serialized_valid_snapshot_for_system( &self, system_info: &NpmSystemInfo, @@ -466,6 +480,25 @@ impl ManagedCliNpmResolver { self.resolution.resolve_pkg_id_from_pkg_req(req) } + pub fn ensure_no_pkg_json_dep_errors(&self) -> Result<(), AnyError> { + for err in self.npm_install_deps_provider.pkg_json_dep_errors() { + match err { + deno_package_json::PackageJsonDepValueParseError::VersionReq(_) => { + return Err( + AnyError::from(err.clone()) + .context("Failed to install from package.json"), + ); + } + deno_package_json::PackageJsonDepValueParseError::Unsupported { + .. + } => { + log::warn!("{} {} in package.json", colors::yellow("Warning"), err) + } + } + } + Ok(()) + } + /// Ensures that the top level `package.json` dependencies are installed. /// This may set up the `node_modules` directory. /// @@ -477,7 +510,8 @@ impl ManagedCliNpmResolver { if !self.top_level_install_flag.raise() { return Ok(false); // already did this } - let pkg_json_remote_pkgs = self.package_json_deps_provider.remote_pkgs(); + + let pkg_json_remote_pkgs = self.npm_install_deps_provider.remote_pkgs(); if pkg_json_remote_pkgs.is_empty() { return Ok(false); } @@ -560,11 +594,11 @@ impl NpmResolver for ManagedCliNpmResolver { } impl NodeRequireResolver for ManagedCliNpmResolver { - fn ensure_read_permission( + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { + path: &'a Path, + ) -> Result, AnyError> { self.fs_resolver.ensure_read_permission(permissions, path) } } @@ -573,7 +607,7 @@ impl NpmProcessStateProvider for ManagedCliNpmResolver { fn get_npm_process_state(&self) -> String { npm_process_state( self.resolution.serialized_valid_snapshot(), - self.fs_resolver.node_modules_path().map(|p| p.as_path()), + self.fs_resolver.node_modules_path(), ) } } @@ -606,7 +640,7 @@ impl CliNpmResolver for ManagedCliNpmResolver { create_npm_fs_resolver( self.fs.clone(), self.npm_cache.clone(), - &self.package_json_deps_provider, + &self.npm_install_deps_provider, &self.text_only_progress_bar, npm_resolution.clone(), self.tarball_cache.clone(), @@ -617,7 +651,7 @@ impl CliNpmResolver for ManagedCliNpmResolver { self.maybe_lockfile.clone(), self.npm_api.clone(), self.npm_cache.clone(), - self.package_json_deps_provider.clone(), + self.npm_install_deps_provider.clone(), npm_resolution, self.tarball_cache.clone(), self.text_only_progress_bar.clone(), @@ -630,7 +664,7 @@ impl CliNpmResolver for ManagedCliNpmResolver { InnerCliNpmResolverRef::Managed(self) } - fn root_node_modules_path(&self) -> Option<&PathBuf> { + fn root_node_modules_path(&self) -> Option<&Path> { self.fs_resolver.node_modules_path() } @@ -638,9 +672,13 @@ impl CliNpmResolver for ManagedCliNpmResolver { &self, req: &PackageReq, _referrer: &ModuleSpecifier, - ) -> Result { - let pkg_id = self.resolve_pkg_id_from_pkg_req(req)?; - self.resolve_pkg_folder_from_pkg_id(&pkg_id) + ) -> Result { + let pkg_id = self + .resolve_pkg_id_from_pkg_req(req) + .map_err(|err| ResolvePkgFolderFromDenoReqError::Managed(err.into()))?; + self + .resolve_pkg_folder_from_pkg_id(&pkg_id) + .map_err(ResolvePkgFolderFromDenoReqError::Managed) } fn check_state_hash(&self) -> Option { diff --git a/cli/npm/managed/resolution.rs b/cli/npm/managed/resolution.rs index 3d13e17353..ecfe5cb25c 100644 --- a/cli/npm/managed/resolution.rs +++ b/cli/npm/managed/resolution.rs @@ -22,6 +22,7 @@ use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; +use deno_semver::jsr::JsrDepPackageReq; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use deno_semver::VersionReq; @@ -317,7 +318,7 @@ fn get_npm_pending_resolver( // WARNING: When bumping this version, check if anything needs to be // updated in the `setNodeOnlyGlobalNames` call in 99_main_compiler.js types_node_version_req: Some( - VersionReq::parse_from_npm("18.0.0 - 18.16.19").unwrap(), + VersionReq::parse_from_npm("22.0.0 - 22.5.4").unwrap(), ), }, ) @@ -329,16 +330,10 @@ fn populate_lockfile_from_snapshot( ) { let mut lockfile = lockfile.lock(); for (package_req, nv) in snapshot.package_reqs() { + let id = &snapshot.resolve_package_from_deno_module(nv).unwrap().id; lockfile.insert_package_specifier( - format!("npm:{}", package_req), - format!( - "npm:{}", - snapshot - .resolve_package_from_deno_module(nv) - .unwrap() - .id - .as_serialized() - ), + JsrDepPackageReq::npm(package_req.clone()), + format!("{}{}", id.nv.version, id.peer_deps_serialized()), ); } for package in snapshot.all_packages_for_every_system() { diff --git a/cli/npm/managed/resolvers/common.rs b/cli/npm/managed/resolvers/common.rs index 170dc2ae6b..867bb4168a 100644 --- a/cli/npm/managed/resolvers/common.rs +++ b/cli/npm/managed/resolvers/common.rs @@ -1,5 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +pub mod bin_entries; +pub mod lifecycle_scripts; + +use std::borrow::Cow; use std::collections::HashMap; use std::io::ErrorKind; use std::path::Path; @@ -30,7 +34,7 @@ pub trait NpmPackageFsResolver: Send + Sync { fn root_dir_url(&self) -> &Url; /// The local node_modules folder if it is applicable to the implementation. - fn node_modules_path(&self) -> Option<&PathBuf>; + fn node_modules_path(&self) -> Option<&Path>; fn maybe_package_folder(&self, package_id: &NpmPackageId) -> Option; @@ -59,11 +63,12 @@ pub trait NpmPackageFsResolver: Send + Sync { async fn cache_packages(&self) -> Result<(), AnyError>; - fn ensure_read_permission( + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError>; + path: &'a Path, + ) -> Result, AnyError>; } #[derive(Debug)] @@ -82,11 +87,15 @@ impl RegistryReadPermissionChecker { } } - pub fn ensure_registry_read_permission( + pub fn ensure_registry_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { + path: &'a Path, + ) -> Result, AnyError> { + if permissions.query_read_all() { + return Ok(Cow::Borrowed(path)); // skip permissions checks below + } + // allow reading if it's in the node_modules let is_path_in_node_modules = path.starts_with(&self.registry_path) && path @@ -115,25 +124,26 @@ impl RegistryReadPermissionChecker { }, } }; - let Some(registry_path_canon) = canonicalize(&self.registry_path)? else { - return Ok(()); // not exists, allow reading - }; - let Some(path_canon) = canonicalize(path)? else { - return Ok(()); // not exists, allow reading - }; - - if path_canon.starts_with(registry_path_canon) { - return Ok(()); + if let Some(registry_path_canon) = canonicalize(&self.registry_path)? { + if let Some(path_canon) = canonicalize(path)? { + if path_canon.starts_with(registry_path_canon) { + return Ok(Cow::Owned(path_canon)); + } + } else if path.starts_with(registry_path_canon) + || path.starts_with(&self.registry_path) + { + return Ok(Cow::Borrowed(path)); + } } } - permissions.check_read(path) + permissions.check_read_path(path) } } /// Caches all the packages in parallel. pub async fn cache_packages( - packages: Vec, + packages: &[NpmResolutionPackage], tarball_cache: &Arc, ) -> Result<(), AnyError> { let mut futures_unordered = futures::stream::FuturesUnordered::new(); diff --git a/cli/npm/managed/resolvers/local/bin_entries.rs b/cli/npm/managed/resolvers/common/bin_entries.rs similarity index 73% rename from cli/npm/managed/resolvers/local/bin_entries.rs rename to cli/npm/managed/resolvers/common/bin_entries.rs index 980a2653b7..4524ce8326 100644 --- a/cli/npm/managed/resolvers/local/bin_entries.rs +++ b/cli/npm/managed/resolvers/common/bin_entries.rs @@ -12,12 +12,12 @@ use std::path::Path; use std::path::PathBuf; #[derive(Default)] -pub(super) struct BinEntries { +pub struct BinEntries<'a> { /// Packages that have colliding bin names - collisions: HashSet, - seen_names: HashMap, + collisions: HashSet<&'a NpmPackageId>, + seen_names: HashMap<&'a str, &'a NpmPackageId>, /// The bin entries - entries: Vec<(NpmResolutionPackage, PathBuf)>, + entries: Vec<(&'a NpmResolutionPackage, PathBuf)>, } /// Returns the name of the default binary for the given package. @@ -31,37 +31,32 @@ fn default_bin_name(package: &NpmResolutionPackage) -> &str { .map_or(package.id.nv.name.as_str(), |(_, name)| name) } -impl BinEntries { - pub(super) fn new() -> Self { +impl<'a> BinEntries<'a> { + pub fn new() -> Self { Self::default() } /// Add a new bin entry (package with a bin field) - pub(super) fn add( + pub fn add( &mut self, - package: NpmResolutionPackage, + package: &'a NpmResolutionPackage, package_path: PathBuf, ) { // check for a new collision, if we haven't already // found one match package.bin.as_ref().unwrap() { deno_npm::registry::NpmPackageVersionBinEntry::String(_) => { - let bin_name = default_bin_name(&package); + let bin_name = default_bin_name(package); - if let Some(other) = self - .seen_names - .insert(bin_name.to_string(), package.id.clone()) - { - self.collisions.insert(package.id.clone()); + if let Some(other) = self.seen_names.insert(bin_name, &package.id) { + self.collisions.insert(&package.id); self.collisions.insert(other); } } deno_npm::registry::NpmPackageVersionBinEntry::Map(entries) => { for name in entries.keys() { - if let Some(other) = - self.seen_names.insert(name.to_string(), package.id.clone()) - { - self.collisions.insert(package.id.clone()); + if let Some(other) = self.seen_names.insert(name, &package.id) { + self.collisions.insert(&package.id); self.collisions.insert(other); } } @@ -74,7 +69,11 @@ impl BinEntries { fn for_each_entry( &mut self, snapshot: &NpmResolutionSnapshot, - mut f: impl FnMut( + mut already_seen: impl FnMut( + &Path, + &str, // bin script + ) -> Result<(), AnyError>, + mut new: impl FnMut( &NpmResolutionPackage, &Path, &str, // bin name @@ -95,18 +94,20 @@ impl BinEntries { deno_npm::registry::NpmPackageVersionBinEntry::String(script) => { let name = default_bin_name(package); if !seen.insert(name) { + already_seen(package_path, script)?; // we already set up a bin entry with this name continue; } - f(package, package_path, name, script)?; + new(package, package_path, name, script)?; } deno_npm::registry::NpmPackageVersionBinEntry::Map(entries) => { for (name, script) in entries { if !seen.insert(name) { + already_seen(package_path, script)?; // we already set up a bin entry with this name continue; } - f(package, package_path, name, script)?; + new(package, package_path, name, script)?; } } } @@ -117,23 +118,27 @@ impl BinEntries { } /// Collect the bin entries into a vec of (name, script path) - pub(super) fn into_bin_files( + pub fn into_bin_files( mut self, snapshot: &NpmResolutionSnapshot, ) -> Vec<(String, PathBuf)> { let mut bins = Vec::new(); self - .for_each_entry(snapshot, |_, package_path, name, script| { - bins.push((name.to_string(), package_path.join(script))); - Ok(()) - }) + .for_each_entry( + snapshot, + |_, _| Ok(()), + |_, package_path, name, script| { + bins.push((name.to_string(), package_path.join(script))); + Ok(()) + }, + ) .unwrap(); bins } /// Finish setting up the bin entries, writing the necessary files /// to disk. - pub(super) fn finish( + pub fn finish( mut self, snapshot: &NpmResolutionSnapshot, bin_node_modules_dir_path: &Path, @@ -144,15 +149,26 @@ impl BinEntries { )?; } - self.for_each_entry(snapshot, |package, package_path, name, script| { - set_up_bin_entry( - package, - name, - script, - package_path, - bin_node_modules_dir_path, - ) - })?; + self.for_each_entry( + snapshot, + |_package_path, _script| { + #[cfg(unix)] + { + let path = _package_path.join(_script); + make_executable_if_exists(&path)?; + } + Ok(()) + }, + |package, package_path, name, script| { + set_up_bin_entry( + package, + name, + script, + package_path, + bin_node_modules_dir_path, + ) + }, + )?; Ok(()) } @@ -162,8 +178,8 @@ impl BinEntries { // that has a bin entry, then sort them by depth fn sort_by_depth( snapshot: &NpmResolutionSnapshot, - bin_entries: &mut [(NpmResolutionPackage, PathBuf)], - collisions: &mut HashSet, + bin_entries: &mut [(&NpmResolutionPackage, PathBuf)], + collisions: &mut HashSet<&NpmPackageId>, ) { enum Entry<'a> { Pkg(&'a NpmPackageId), @@ -217,7 +233,7 @@ fn sort_by_depth( }); } -pub(super) fn set_up_bin_entry( +pub fn set_up_bin_entry( package: &NpmResolutionPackage, bin_name: &str, #[allow(unused_variables)] bin_script: &str, @@ -259,6 +275,32 @@ fn set_up_bin_shim( Ok(()) } +#[cfg(unix)] +/// Make the file at `path` executable if it exists. +/// Returns `true` if the file exists, `false` otherwise. +fn make_executable_if_exists(path: &Path) -> Result { + use std::io; + use std::os::unix::fs::PermissionsExt; + let mut perms = match std::fs::metadata(path) { + Ok(metadata) => metadata.permissions(), + Err(err) => { + if err.kind() == io::ErrorKind::NotFound { + return Ok(false); + } + return Err(err.into()); + } + }; + if perms.mode() & 0o111 == 0 { + // if the original file is not executable, make it executable + perms.set_mode(perms.mode() | 0o111); + std::fs::set_permissions(path, perms).with_context(|| { + format!("Setting permissions on '{}'", path.display()) + })?; + } + + Ok(true) +} + #[cfg(unix)] fn symlink_bin_entry( _package: &NpmResolutionPackage, @@ -272,32 +314,20 @@ fn symlink_bin_entry( let link = bin_node_modules_dir_path.join(bin_name); let original = package_path.join(bin_script); - use std::os::unix::fs::PermissionsExt; - let mut perms = match std::fs::metadata(&original) { - Ok(metadata) => metadata.permissions(), - Err(err) => { - if err.kind() == io::ErrorKind::NotFound { - log::warn!( - "{} Trying to set up '{}' bin for \"{}\", but the entry point \"{}\" doesn't exist.", - deno_terminal::colors::yellow("Warning"), - bin_name, - package_path.display(), - original.display() - ); - return Ok(()); - } - return Err(err).with_context(|| { - format!("Can't set up '{}' bin at {}", bin_name, original.display()) - }); - } - }; - if perms.mode() & 0o111 == 0 { - // if the original file is not executable, make it executable - perms.set_mode(perms.mode() | 0o111); - std::fs::set_permissions(&original, perms).with_context(|| { - format!("Setting permissions on '{}'", original.display()) - })?; + let found = make_executable_if_exists(&original).with_context(|| { + format!("Can't set up '{}' bin at {}", bin_name, original.display()) + })?; + if !found { + log::warn!( + "{} Trying to set up '{}' bin for \"{}\", but the entry point \"{}\" doesn't exist.", + deno_terminal::colors::yellow("Warning"), + bin_name, + package_path.display(), + original.display() + ); + return Ok(()); } + let original_relative = crate::util::path::relative_path(bin_node_modules_dir_path, &original) .unwrap_or(original); diff --git a/cli/npm/managed/resolvers/common/lifecycle_scripts.rs b/cli/npm/managed/resolvers/common/lifecycle_scripts.rs new file mode 100644 index 0000000000..5735f52482 --- /dev/null +++ b/cli/npm/managed/resolvers/common/lifecycle_scripts.rs @@ -0,0 +1,368 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use super::bin_entries::BinEntries; +use crate::args::LifecycleScriptsConfig; +use crate::task_runner::TaskStdio; +use crate::util::progress_bar::ProgressBar; +use deno_core::anyhow::Context; +use deno_npm::resolution::NpmResolutionSnapshot; +use deno_runtime::deno_io::FromRawIoHandle; +use deno_semver::package::PackageNv; +use deno_semver::Version; +use std::borrow::Cow; +use std::rc::Rc; + +use std::path::Path; +use std::path::PathBuf; + +use deno_core::error::AnyError; +use deno_npm::NpmResolutionPackage; + +pub trait LifecycleScriptsStrategy { + fn can_run_scripts(&self) -> bool { + true + } + fn package_path(&self, package: &NpmResolutionPackage) -> PathBuf; + + fn warn_on_scripts_not_run( + &self, + packages: &[(&NpmResolutionPackage, PathBuf)], + ) -> Result<(), AnyError>; + + fn has_warned(&self, package: &NpmResolutionPackage) -> bool; + + fn has_run(&self, package: &NpmResolutionPackage) -> bool; + + fn did_run_scripts( + &self, + package: &NpmResolutionPackage, + ) -> Result<(), AnyError>; +} + +pub struct LifecycleScripts<'a> { + packages_with_scripts: Vec<(&'a NpmResolutionPackage, PathBuf)>, + packages_with_scripts_not_run: Vec<(&'a NpmResolutionPackage, PathBuf)>, + + config: &'a LifecycleScriptsConfig, + strategy: Box, +} + +impl<'a> LifecycleScripts<'a> { + pub fn new( + config: &'a LifecycleScriptsConfig, + strategy: T, + ) -> Self { + Self { + config, + packages_with_scripts: Vec::new(), + packages_with_scripts_not_run: Vec::new(), + strategy: Box::new(strategy), + } + } +} + +fn has_lifecycle_scripts( + package: &NpmResolutionPackage, + package_path: &Path, +) -> bool { + if let Some(install) = package.scripts.get("install") { + // default script + if !is_broken_default_install_script(install, package_path) { + return true; + } + } + package.scripts.contains_key("preinstall") + || package.scripts.contains_key("postinstall") +} + +// npm defaults to running `node-gyp rebuild` if there is a `binding.gyp` file +// but it always fails if the package excludes the `binding.gyp` file when they publish. +// (for example, `fsevents` hits this) +fn is_broken_default_install_script(script: &str, package_path: &Path) -> bool { + script == "node-gyp rebuild" && !package_path.join("binding.gyp").exists() +} + +impl<'a> LifecycleScripts<'a> { + fn can_run_scripts(&self, package_nv: &PackageNv) -> bool { + if !self.strategy.can_run_scripts() { + return false; + } + use crate::args::PackagesAllowedScripts; + match &self.config.allowed { + PackagesAllowedScripts::All => true, + // TODO: make this more correct + PackagesAllowedScripts::Some(allow_list) => allow_list.iter().any(|s| { + let s = s.strip_prefix("npm:").unwrap_or(s); + s == package_nv.name || s == package_nv.to_string() + }), + PackagesAllowedScripts::None => false, + } + } + /// Register a package for running lifecycle scripts, if applicable. + /// + /// `package_path` is the path containing the package's code (its root dir). + /// `package_meta_path` is the path to serve as the base directory for lifecycle + /// script-related metadata (e.g. to store whether the scripts have been run already) + pub fn add( + &mut self, + package: &'a NpmResolutionPackage, + package_path: Cow, + ) { + if has_lifecycle_scripts(package, &package_path) { + if self.can_run_scripts(&package.id.nv) { + if !self.strategy.has_run(package) { + self + .packages_with_scripts + .push((package, package_path.into_owned())); + } + } else if !self.strategy.has_run(package) + && (self.config.explicit_install || !self.strategy.has_warned(package)) + { + // Skip adding `esbuild` as it is known that it can work properly without lifecycle script + // being run, and it's also very popular - any project using Vite would raise warnings. + { + let nv = &package.id.nv; + if nv.name == "esbuild" + && nv.version >= Version::parse_standard("0.18.0").unwrap() + { + return; + } + } + + self + .packages_with_scripts_not_run + .push((package, package_path.into_owned())); + } + } + } + + pub fn warn_not_run_scripts(&self) -> Result<(), AnyError> { + if !self.packages_with_scripts_not_run.is_empty() { + self + .strategy + .warn_on_scripts_not_run(&self.packages_with_scripts_not_run)?; + } + Ok(()) + } + + pub async fn finish( + self, + snapshot: &NpmResolutionSnapshot, + packages: &[NpmResolutionPackage], + root_node_modules_dir_path: Option<&Path>, + progress_bar: &ProgressBar, + ) -> Result<(), AnyError> { + self.warn_not_run_scripts()?; + let get_package_path = + |p: &NpmResolutionPackage| self.strategy.package_path(p); + let mut failed_packages = Vec::new(); + if !self.packages_with_scripts.is_empty() { + // get custom commands for each bin available in the node_modules dir (essentially + // the scripts that are in `node_modules/.bin`) + let base = + resolve_baseline_custom_commands(snapshot, packages, get_package_path)?; + let init_cwd = &self.config.initial_cwd; + let process_state = crate::npm::managed::npm_process_state( + snapshot.as_valid_serialized(), + root_node_modules_dir_path, + ); + + let mut env_vars = crate::task_runner::real_env_vars(); + // we want to pass the current state of npm resolution down to the deno subprocess + // (that may be running as part of the script). we do this with an inherited temp file + // + // SAFETY: we are sharing a single temp file across all of the scripts. the file position + // will be shared among these, which is okay since we run only one script at a time. + // However, if we concurrently run scripts in the future we will + // have to have multiple temp files. + let temp_file_fd = + deno_runtime::ops::process::npm_process_state_tempfile( + process_state.as_bytes(), + ).context("failed to create npm process state tempfile for running lifecycle scripts")?; + // SAFETY: fd/handle is valid + let _temp_file = + unsafe { std::fs::File::from_raw_io_handle(temp_file_fd) }; // make sure the file gets closed + env_vars.insert( + deno_runtime::ops::process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME + .to_string(), + (temp_file_fd as usize).to_string(), + ); + for (package, package_path) in self.packages_with_scripts { + // add custom commands for binaries from the package's dependencies. this will take precedence over the + // baseline commands, so if the package relies on a bin that conflicts with one higher in the dependency tree, the + // correct bin will be used. + let custom_commands = resolve_custom_commands_from_deps( + base.clone(), + package, + snapshot, + get_package_path, + )?; + for script_name in ["preinstall", "install", "postinstall"] { + if let Some(script) = package.scripts.get(script_name) { + if script_name == "install" + && is_broken_default_install_script(script, &package_path) + { + continue; + } + let _guard = progress_bar.update_with_prompt( + crate::util::progress_bar::ProgressMessagePrompt::Initialize, + &format!("{}: running '{script_name}' script", package.id.nv), + ); + let crate::task_runner::TaskResult { + exit_code, + stderr, + stdout, + } = crate::task_runner::run_task( + crate::task_runner::RunTaskOptions { + task_name: script_name, + script, + cwd: &package_path, + env_vars: env_vars.clone(), + custom_commands: custom_commands.clone(), + init_cwd, + argv: &[], + root_node_modules_dir: root_node_modules_dir_path, + stdio: Some(crate::task_runner::TaskIo { + stderr: TaskStdio::piped(), + stdout: TaskStdio::piped(), + }), + }, + ) + .await?; + let stdout = stdout.unwrap(); + let stderr = stderr.unwrap(); + if exit_code != 0 { + log::warn!( + "error: script '{}' in '{}' failed with exit code {}{}{}", + script_name, + package.id.nv, + exit_code, + if !stdout.trim_ascii().is_empty() { + format!( + "\nstdout:\n{}\n", + String::from_utf8_lossy(&stdout).trim() + ) + } else { + String::new() + }, + if !stderr.trim_ascii().is_empty() { + format!( + "\nstderr:\n{}\n", + String::from_utf8_lossy(&stderr).trim() + ) + } else { + String::new() + }, + ); + failed_packages.push(&package.id.nv); + // assume if earlier script fails, later ones will fail too + break; + } + } + } + self.strategy.did_run_scripts(package)?; + } + } + if failed_packages.is_empty() { + Ok(()) + } else { + Err(AnyError::msg(format!( + "failed to run scripts for packages: {}", + failed_packages + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", ") + ))) + } + } +} + +// take in all (non copy) packages from snapshot, +// and resolve the set of available binaries to create +// custom commands available to the task runner +fn resolve_baseline_custom_commands( + snapshot: &NpmResolutionSnapshot, + packages: &[NpmResolutionPackage], + get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf, +) -> Result { + let mut custom_commands = crate::task_runner::TaskCustomCommands::new(); + custom_commands + .insert("npx".to_string(), Rc::new(crate::task_runner::NpxCommand)); + + custom_commands + .insert("npm".to_string(), Rc::new(crate::task_runner::NpmCommand)); + + custom_commands + .insert("node".to_string(), Rc::new(crate::task_runner::NodeCommand)); + + custom_commands.insert( + "node-gyp".to_string(), + Rc::new(crate::task_runner::NodeGypCommand), + ); + + // TODO: this recreates the bin entries which could be redoing some work, but the ones + // we compute earlier in `sync_resolution_with_fs` may not be exhaustive (because we skip + // doing it for packages that are set up already. + // realistically, scripts won't be run very often so it probably isn't too big of an issue. + resolve_custom_commands_from_packages( + custom_commands, + snapshot, + packages, + get_package_path, + ) +} + +// resolves the custom commands from an iterator of packages +// and adds them to the existing custom commands. +// note that this will overwrite any existing custom commands +fn resolve_custom_commands_from_packages< + 'a, + P: IntoIterator, +>( + mut commands: crate::task_runner::TaskCustomCommands, + snapshot: &'a NpmResolutionSnapshot, + packages: P, + get_package_path: impl Fn(&'a NpmResolutionPackage) -> PathBuf, +) -> Result { + let mut bin_entries = BinEntries::new(); + for package in packages { + let package_path = get_package_path(package); + + if package.bin.is_some() { + bin_entries.add(package, package_path); + } + } + let bins = bin_entries.into_bin_files(snapshot); + for (bin_name, script_path) in bins { + commands.insert( + bin_name.clone(), + Rc::new(crate::task_runner::NodeModulesFileRunCommand { + command_name: bin_name, + path: script_path, + }), + ); + } + + Ok(commands) +} + +// resolves the custom commands from the dependencies of a package +// and adds them to the existing custom commands. +// note that this will overwrite any existing custom commands. +fn resolve_custom_commands_from_deps( + baseline: crate::task_runner::TaskCustomCommands, + package: &NpmResolutionPackage, + snapshot: &NpmResolutionSnapshot, + get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf, +) -> Result { + resolve_custom_commands_from_packages( + baseline, + snapshot, + package + .dependencies + .values() + .map(|id| snapshot.package_from_id(id).unwrap()), + get_package_path, + ) +} diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs index 7f8f285f3e..5be315e992 100644 --- a/cli/npm/managed/resolvers/global.rs +++ b/cli/npm/managed/resolvers/global.rs @@ -2,16 +2,19 @@ //! Code for global npm cache resolution. +use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; +use crate::colors; use async_trait::async_trait; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_core::url::Url; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; +use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::NodePermissions; @@ -19,10 +22,14 @@ use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use crate::args::LifecycleScriptsConfig; +use crate::cache::FastInsecureHasher; + use super::super::cache::NpmCache; use super::super::cache::TarballCache; use super::super::resolution::NpmResolution; use super::common::cache_packages; +use super::common::lifecycle_scripts::LifecycleScriptsStrategy; use super::common::NpmPackageFsResolver; use super::common::RegistryReadPermissionChecker; @@ -34,6 +41,7 @@ pub struct GlobalNpmPackageResolver { resolution: Arc, system_info: NpmSystemInfo, registry_read_permission_checker: RegistryReadPermissionChecker, + lifecycle_scripts: LifecycleScriptsConfig, } impl GlobalNpmPackageResolver { @@ -43,6 +51,7 @@ impl GlobalNpmPackageResolver { tarball_cache: Arc, resolution: Arc, system_info: NpmSystemInfo, + lifecycle_scripts: LifecycleScriptsConfig, ) -> Self { Self { registry_read_permission_checker: RegistryReadPermissionChecker::new( @@ -53,6 +62,7 @@ impl GlobalNpmPackageResolver { tarball_cache, resolution, system_info, + lifecycle_scripts, } } } @@ -63,7 +73,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { self.cache.root_dir_url() } - fn node_modules_path(&self) -> Option<&PathBuf> { + fn node_modules_path(&self) -> Option<&Path> { None } @@ -149,8 +159,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { let package_partitions = self .resolution .all_system_packages_partitioned(&self.system_info); - - cache_packages(package_partitions.packages, &self.tarball_cache).await?; + cache_packages(&package_partitions.packages, &self.tarball_cache).await?; // create the copy package folders for copy in package_partitions.copy_packages { @@ -159,16 +168,103 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { .ensure_copy_package(©.get_package_cache_folder_id())?; } + let mut lifecycle_scripts = + super::common::lifecycle_scripts::LifecycleScripts::new( + &self.lifecycle_scripts, + GlobalLifecycleScripts::new(self, &self.lifecycle_scripts.root_dir), + ); + for package in &package_partitions.packages { + let package_folder = self.cache.package_folder_for_nv(&package.id.nv); + lifecycle_scripts.add(package, Cow::Borrowed(&package_folder)); + } + + lifecycle_scripts.warn_not_run_scripts()?; + Ok(()) } - fn ensure_read_permission( + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { + path: &'a Path, + ) -> Result, AnyError> { self .registry_read_permission_checker .ensure_registry_read_permission(permissions, path) } } + +struct GlobalLifecycleScripts<'a> { + resolver: &'a GlobalNpmPackageResolver, + path_hash: u64, +} + +impl<'a> GlobalLifecycleScripts<'a> { + fn new(resolver: &'a GlobalNpmPackageResolver, root_dir: &Path) -> Self { + let mut hasher = FastInsecureHasher::new_without_deno_version(); + hasher.write(root_dir.to_string_lossy().as_bytes()); + let path_hash = hasher.finish(); + Self { + resolver, + path_hash, + } + } + + fn warned_scripts_file(&self, package: &NpmResolutionPackage) -> PathBuf { + self + .package_path(package) + .join(format!(".scripts-warned-{}", self.path_hash)) + } +} + +impl<'a> super::common::lifecycle_scripts::LifecycleScriptsStrategy + for GlobalLifecycleScripts<'a> +{ + fn can_run_scripts(&self) -> bool { + false + } + fn package_path(&self, package: &NpmResolutionPackage) -> PathBuf { + self.resolver.cache.package_folder_for_nv(&package.id.nv) + } + + fn warn_on_scripts_not_run( + &self, + packages: &[(&NpmResolutionPackage, PathBuf)], + ) -> std::result::Result<(), deno_core::anyhow::Error> { + log::warn!("{} The following packages contained npm lifecycle scripts ({}) that were not executed:", colors::yellow("Warning"), colors::gray("preinstall/install/postinstall")); + for (package, _) in packages { + log::warn!("┠─ {}", colors::gray(format!("npm:{}", package.id.nv))); + } + log::warn!("┃"); + log::warn!( + "┠─ {}", + colors::italic("This may cause the packages to not work correctly.") + ); + log::warn!("┠─ {}", colors::italic("Lifecycle scripts are only supported when using a `node_modules` directory.")); + log::warn!( + "┠─ {}", + colors::italic("Enable it in your deno config file:") + ); + log::warn!("┖─ {}", colors::bold("\"nodeModulesDir\": \"auto\"")); + + for (package, _) in packages { + std::fs::write(self.warned_scripts_file(package), "")?; + } + Ok(()) + } + + fn did_run_scripts( + &self, + _package: &NpmResolutionPackage, + ) -> std::result::Result<(), deno_core::anyhow::Error> { + Ok(()) + } + + fn has_warned(&self, package: &NpmResolutionPackage) -> bool { + self.warned_scripts_file(package).exists() + } + + fn has_run(&self, _package: &NpmResolutionPackage) -> bool { + false + } +} diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs index adfd04b9e4..54f7576ade 100644 --- a/cli/npm/managed/resolvers/local.rs +++ b/cli/npm/managed/resolvers/local.rs @@ -2,14 +2,13 @@ //! Code for local node_modules resolution. -mod bin_entries; - use std::borrow::Cow; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::hash_map::Entry; use std::collections::BTreeMap; use std::collections::HashMap; +use std::collections::HashSet; use std::fs; use std::path::Path; use std::path::PathBuf; @@ -17,20 +16,22 @@ use std::rc::Rc; use std::sync::Arc; use crate::args::LifecycleScriptsConfig; -use crate::args::PackagesAllowedScripts; +use crate::colors; use async_trait::async_trait; use deno_ast::ModuleSpecifier; -use deno_core::anyhow; +use deno_cache_dir::npm::mixed_case_package_name_decode; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures::stream::FuturesUnordered; use deno_core::futures::StreamExt; +use deno_core::parking_lot::Mutex; use deno_core::url::Url; use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; +use deno_resolver::npm::normalize_pkg_name_for_node_modules_deno_folder; use deno_runtime::deno_fs; use deno_runtime::deno_node::NodePermissions; use deno_semver::package::PackageNv; @@ -41,10 +42,8 @@ use node_resolver::errors::ReferrerNotFoundError; use serde::Deserialize; use serde::Serialize; -use crate::args::PackageJsonInstallDepsProvider; +use crate::args::NpmInstallDepsProvider; use crate::cache::CACHE_PERM; -use crate::npm::cache_dir::mixed_case_package_name_decode; -use crate::npm::cache_dir::mixed_case_package_name_encode; use crate::util::fs::atomic_write_file_with_retries; use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs; use crate::util::fs::clone_dir_recursive; @@ -65,7 +64,7 @@ use super::common::RegistryReadPermissionChecker; pub struct LocalNpmPackageResolver { cache: Arc, fs: Arc, - pkg_json_deps_provider: Arc, + npm_install_deps_provider: Arc, progress_bar: ProgressBar, resolution: Arc, tarball_cache: Arc, @@ -81,7 +80,7 @@ impl LocalNpmPackageResolver { pub fn new( cache: Arc, fs: Arc, - pkg_json_deps_provider: Arc, + npm_install_deps_provider: Arc, progress_bar: ProgressBar, resolution: Arc, tarball_cache: Arc, @@ -92,7 +91,7 @@ impl LocalNpmPackageResolver { Self { cache, fs: fs.clone(), - pkg_json_deps_provider, + npm_install_deps_provider, progress_bar, resolution, tarball_cache, @@ -160,8 +159,8 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { &self.root_node_modules_url } - fn node_modules_path(&self) -> Option<&PathBuf> { - Some(&self.root_node_modules_path) + fn node_modules_path(&self) -> Option<&Path> { + Some(self.root_node_modules_path.as_ref()) } fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { @@ -248,7 +247,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { sync_resolution_with_fs( &self.resolution.snapshot(), &self.cache, - &self.pkg_json_deps_provider, + &self.npm_install_deps_provider, &self.progress_bar, &self.tarball_cache, &self.root_node_modules_path, @@ -258,88 +257,21 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { .await } - fn ensure_read_permission( + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { + path: &'a Path, + ) -> Result, AnyError> { self .registry_read_permission_checker .ensure_registry_read_permission(permissions, path) } } -// take in all (non copy) packages from snapshot, -// and resolve the set of available binaries to create -// custom commands available to the task runner -fn resolve_baseline_custom_commands( - snapshot: &NpmResolutionSnapshot, - packages: &[NpmResolutionPackage], - local_registry_dir: &Path, -) -> Result { - let mut custom_commands = crate::task_runner::TaskCustomCommands::new(); - custom_commands - .insert("npx".to_string(), Rc::new(crate::task_runner::NpxCommand)); - - custom_commands - .insert("npm".to_string(), Rc::new(crate::task_runner::NpmCommand)); - - custom_commands - .insert("node".to_string(), Rc::new(crate::task_runner::NodeCommand)); - - custom_commands.insert( - "node-gyp".to_string(), - Rc::new(crate::task_runner::NodeGypCommand), - ); - - // TODO: this recreates the bin entries which could be redoing some work, but the ones - // we compute earlier in `sync_resolution_with_fs` may not be exhaustive (because we skip - // doing it for packages that are set up already. - // realistically, scripts won't be run very often so it probably isn't too big of an issue. - resolve_custom_commands_from_packages( - custom_commands, - snapshot, - packages, - local_registry_dir, - ) -} - -// resolves the custom commands from an iterator of packages -// and adds them to the existing custom commands. -// note that this will overwrite any existing custom commands -fn resolve_custom_commands_from_packages< - 'a, - P: IntoIterator, ->( - mut commands: crate::task_runner::TaskCustomCommands, - snapshot: &'a NpmResolutionSnapshot, - packages: P, - local_registry_dir: &Path, -) -> Result { - let mut bin_entries = bin_entries::BinEntries::new(); - for package in packages { - let package_path = - local_node_modules_package_path(local_registry_dir, package); - - if package.bin.is_some() { - bin_entries.add(package.clone(), package_path); - } - } - let bins = bin_entries.into_bin_files(snapshot); - for (bin_name, script_path) in bins { - commands.insert( - bin_name.clone(), - Rc::new(crate::task_runner::NodeModulesFileRunCommand { - command_name: bin_name, - path: script_path, - }), - ); - } - - Ok(commands) -} - -fn local_node_modules_package_path( +/// `node_modules/.deno//node_modules/` +/// +/// Where the actual package is stored. +fn local_node_modules_package_contents_path( local_registry_dir: &Path, package: &NpmResolutionPackage, ) -> PathBuf { @@ -351,75 +283,21 @@ fn local_node_modules_package_path( .join(&package.id.nv.name) } -// resolves the custom commands from the dependencies of a package -// and adds them to the existing custom commands. -// note that this will overwrite any existing custom commands. -fn resolve_custom_commands_from_deps( - baseline: crate::task_runner::TaskCustomCommands, - package: &NpmResolutionPackage, - snapshot: &NpmResolutionSnapshot, - local_registry_dir: &Path, -) -> Result { - resolve_custom_commands_from_packages( - baseline, - snapshot, - package - .dependencies - .values() - .map(|id| snapshot.package_from_id(id).unwrap()), - local_registry_dir, - ) -} - -fn can_run_scripts( - allow_scripts: &PackagesAllowedScripts, - package_nv: &PackageNv, -) -> bool { - match allow_scripts { - PackagesAllowedScripts::All => true, - // TODO: make this more correct - PackagesAllowedScripts::Some(allow_list) => allow_list.iter().any(|s| { - let s = s.strip_prefix("npm:").unwrap_or(s); - s == package_nv.name || s == package_nv.to_string() - }), - PackagesAllowedScripts::None => false, - } -} - -// npm defaults to running `node-gyp rebuild` if there is a `binding.gyp` file -// but it always fails if the package excludes the `binding.gyp` file when they publish. -// (for example, `fsevents` hits this) -fn is_broken_default_install_script(script: &str, package_path: &Path) -> bool { - script == "node-gyp rebuild" && !package_path.join("binding.gyp").exists() -} - -fn has_lifecycle_scripts( - package: &NpmResolutionPackage, - package_path: &Path, -) -> bool { - if let Some(install) = package.scripts.get("install") { - // default script - if !is_broken_default_install_script(install, package_path) { - return true; - } - } - package.scripts.contains_key("preinstall") - || package.scripts.contains_key("postinstall") -} - /// Creates a pnpm style folder structure. #[allow(clippy::too_many_arguments)] async fn sync_resolution_with_fs( snapshot: &NpmResolutionSnapshot, cache: &Arc, - pkg_json_deps_provider: &PackageJsonInstallDepsProvider, + npm_install_deps_provider: &NpmInstallDepsProvider, progress_bar: &ProgressBar, tarball_cache: &Arc, root_node_modules_dir_path: &Path, system_info: &NpmSystemInfo, lifecycle_scripts: &LifecycleScriptsConfig, ) -> Result<(), AnyError> { - if snapshot.is_empty() && pkg_json_deps_provider.workspace_pkgs().is_empty() { + if snapshot.is_empty() + && npm_install_deps_provider.workspace_pkgs().is_empty() + { return Ok(()); // don't create the directory } @@ -455,9 +333,24 @@ async fn sync_resolution_with_fs( let mut cache_futures = FuturesUnordered::new(); let mut newest_packages_by_name: HashMap<&String, &NpmResolutionPackage> = HashMap::with_capacity(package_partitions.packages.len()); - let bin_entries = Rc::new(RefCell::new(bin_entries::BinEntries::new())); - let mut packages_with_scripts = Vec::with_capacity(2); - let mut packages_with_scripts_not_run = Vec::new(); + let bin_entries = + Rc::new(RefCell::new(super::common::bin_entries::BinEntries::new())); + let mut lifecycle_scripts = + super::common::lifecycle_scripts::LifecycleScripts::new( + lifecycle_scripts, + LocalLifecycleScripts { + deno_local_registry_dir: &deno_local_registry_dir, + }, + ); + let packages_with_deprecation_warnings = Arc::new(Mutex::new(Vec::new())); + + let mut package_tags: HashMap<&PackageNv, Vec<&str>> = HashMap::new(); + for (package_req, package_nv) in snapshot.package_reqs() { + if let Some(tag) = package_req.version_req.tag() { + package_tags.entry(package_nv).or_default().push(tag); + } + } + for package in &package_partitions.packages { if let Some(current_pkg) = newest_packages_by_name.get_mut(&package.id.nv.name) @@ -472,11 +365,29 @@ async fn sync_resolution_with_fs( let package_folder_name = get_package_folder_id_folder_name(&package.get_package_cache_folder_id()); let folder_path = deno_local_registry_dir.join(&package_folder_name); + let tags = package_tags + .get(&package.id.nv) + .map(|tags| tags.join(",")) + .unwrap_or_default(); + enum PackageFolderState { + UpToDate, + Uninitialized, + TagsOutdated, + } let initialized_file = folder_path.join(".initialized"); + let package_state = std::fs::read_to_string(&initialized_file) + .map(|s| { + if s != tags { + PackageFolderState::TagsOutdated + } else { + PackageFolderState::UpToDate + } + }) + .unwrap_or(PackageFolderState::Uninitialized); if !cache .cache_setting() .should_use_for_npm_package(&package.id.nv.name) - || !initialized_file.exists() + || matches!(package_state, PackageFolderState::Uninitialized) { // cache bust the dep from the dep setup cache so the symlinks // are forced to be recreated @@ -484,6 +395,9 @@ async fn sync_resolution_with_fs( let folder_path = folder_path.clone(); let bin_entries_to_setup = bin_entries.clone(); + let packages_with_deprecation_warnings = + packages_with_deprecation_warnings.clone(); + cache_futures.push(async move { tarball_cache .ensure_package(&package.id.nv, &package.dist) @@ -502,7 +416,7 @@ async fn sync_resolution_with_fs( move || { clone_dir_recursive(&cache_folder, &package_path)?; // write out a file that indicates this folder has been initialized - fs::write(initialized_file, "")?; + fs::write(initialized_file, tags)?; Ok::<_, AnyError>(()) } @@ -510,35 +424,27 @@ async fn sync_resolution_with_fs( .await??; if package.bin.is_some() { - bin_entries_to_setup - .borrow_mut() - .add(package.clone(), package_path); + bin_entries_to_setup.borrow_mut().add(package, package_path); + } + + if let Some(deprecated) = &package.deprecated { + packages_with_deprecation_warnings + .lock() + .push((package.id.clone(), deprecated.clone())); } // finally stop showing the progress bar drop(pb_guard); // explicit for clarity Ok::<_, AnyError>(()) }); + } else if matches!(package_state, PackageFolderState::TagsOutdated) { + fs::write(initialized_file, tags)?; } let sub_node_modules = folder_path.join("node_modules"); let package_path = join_package_name(&sub_node_modules, &package.id.nv.name); - if has_lifecycle_scripts(package, &package_path) { - let scripts_run = folder_path.join(".scripts-run"); - let has_warned = folder_path.join(".scripts-warned"); - if can_run_scripts(&lifecycle_scripts.allowed, &package.id.nv) { - if !scripts_run.exists() { - packages_with_scripts.push(( - package.clone(), - package_path, - scripts_run, - )); - } - } else if !scripts_run.exists() && !has_warned.exists() { - packages_with_scripts_not_run.push((has_warned, package.id.nv.clone())); - } - } + lifecycle_scripts.add(package, package_path.into()); } while let Some(result) = cache_futures.next().await { @@ -609,9 +515,12 @@ async fn sync_resolution_with_fs( let mut found_names: HashMap<&String, &PackageNv> = HashMap::new(); + // set of node_modules in workspace packages that we've already ensured exist + let mut existing_child_node_modules_dirs: HashSet = HashSet::new(); + // 4. Create symlinks for package json dependencies { - for remote in pkg_json_deps_provider.remote_pkgs() { + for remote in npm_install_deps_provider.remote_pkgs() { let remote_pkg = if let Ok(remote_pkg) = snapshot.resolve_pkg_from_pkg_req(&remote.req) { @@ -627,17 +536,20 @@ async fn sync_resolution_with_fs( } else { continue; // skip, package not found }; - let alias_clashes = remote.req.name != remote.alias - && newest_packages_by_name.contains_key(&remote.alias); + let Some(remote_alias) = &remote.alias else { + continue; + }; + let alias_clashes = remote.req.name != *remote_alias + && newest_packages_by_name.contains_key(remote_alias); let install_in_child = { // we'll install in the child if the alias is taken by another package, or // if there's already a package with the same name but different version // linked into the root - match found_names.entry(&remote.alias) { + match found_names.entry(remote_alias) { Entry::Occupied(nv) => { - alias_clashes - || remote.req.name != nv.get().name // alias to a different package (in case of duplicate aliases) - || !remote.req.version_req.matches(&nv.get().version) // incompatible version + // alias to a different package (in case of duplicate aliases) + // or the version doesn't match the version in the root node_modules + alias_clashes || &remote_pkg.id.nv != *nv.get() } Entry::Vacant(entry) => { entry.insert(&remote_pkg.id.nv); @@ -656,8 +568,15 @@ async fn sync_resolution_with_fs( ); if install_in_child { // symlink the dep into the package's child node_modules folder - let dest_path = - remote.base_dir.join("node_modules").join(&remote.alias); + let dest_node_modules = remote.base_dir.join("node_modules"); + if !existing_child_node_modules_dirs.contains(&dest_node_modules) { + fs::create_dir_all(&dest_node_modules).with_context(|| { + format!("Creating '{}'", dest_node_modules.display()) + })?; + existing_child_node_modules_dirs.insert(dest_node_modules.clone()); + } + let mut dest_path = dest_node_modules; + dest_path.push(remote_alias); symlink_package_dir(&local_registry_package_path, &dest_path)?; } else { @@ -667,7 +586,7 @@ async fn sync_resolution_with_fs( { symlink_package_dir( &local_registry_package_path, - &join_package_name(root_node_modules_dir_path, &remote.alias), + &join_package_name(root_node_modules_dir_path, remote_alias), )?; } } @@ -675,7 +594,7 @@ async fn sync_resolution_with_fs( } // 5. Create symlinks for the remaining top level packages in the node_modules folder. - // (These may be present if they are not in the package.json dependencies, such as ) + // (These may be present if they are not in the package.json dependencies) // Symlink node_modules/.deno//node_modules/ to // node_modules/ let mut ids = snapshot @@ -748,100 +667,55 @@ async fn sync_resolution_with_fs( // 8. Create symlinks for the workspace packages { - // todo(#24419): this is not exactly correct because it should + // todo(dsherret): this is not exactly correct because it should // install correctly for a workspace (potentially in sub directories), // but this is good enough for a first pass - for workspace in pkg_json_deps_provider.workspace_pkgs() { + for workspace in npm_install_deps_provider.workspace_pkgs() { + let Some(workspace_alias) = &workspace.alias else { + continue; + }; symlink_package_dir( &workspace.target_dir, - &root_node_modules_dir_path.join(&workspace.alias), + &root_node_modules_dir_path.join(workspace_alias), )?; } } - if !packages_with_scripts.is_empty() { - // get custom commands for each bin available in the node_modules dir (essentially - // the scripts that are in `node_modules/.bin`) - let base = resolve_baseline_custom_commands( - snapshot, - &package_partitions.packages, - &deno_local_registry_dir, - )?; - let init_cwd = lifecycle_scripts.initial_cwd.as_deref().unwrap(); - let process_state = crate::npm::managed::npm_process_state( - snapshot.as_valid_serialized(), - Some(root_node_modules_dir_path), - ); - - let mut env_vars = crate::task_runner::real_env_vars(); - env_vars.insert( - crate::args::NPM_RESOLUTION_STATE_ENV_VAR_NAME.to_string(), - process_state, - ); - for (package, package_path, scripts_run_path) in packages_with_scripts { - // add custom commands for binaries from the package's dependencies. this will take precedence over the - // baseline commands, so if the package relies on a bin that conflicts with one higher in the dependency tree, the - // correct bin will be used. - let custom_commands = resolve_custom_commands_from_deps( - base.clone(), - &package, - snapshot, - &deno_local_registry_dir, - )?; - for script_name in ["preinstall", "install", "postinstall"] { - if let Some(script) = package.scripts.get(script_name) { - if script_name == "install" - && is_broken_default_install_script(script, &package_path) - { - continue; - } - let exit_code = - crate::task_runner::run_task(crate::task_runner::RunTaskOptions { - task_name: script_name, - script, - cwd: &package_path, - env_vars: env_vars.clone(), - custom_commands: custom_commands.clone(), - init_cwd, - argv: &[], - root_node_modules_dir: Some(root_node_modules_dir_path), - }) - .await?; - if exit_code != 0 { - anyhow::bail!( - "script '{}' in '{}' failed with exit code {}", - script_name, - package.id.nv, - exit_code, - ); - } + { + let packages_with_deprecation_warnings = + packages_with_deprecation_warnings.lock(); + if !packages_with_deprecation_warnings.is_empty() { + log::warn!( + "{} The following packages are deprecated:", + colors::yellow("Warning") + ); + let len = packages_with_deprecation_warnings.len(); + for (idx, (package_id, msg)) in + packages_with_deprecation_warnings.iter().enumerate() + { + if idx != len - 1 { + log::warn!( + "┠─ {}", + colors::gray(format!("npm:{:?} ({})", package_id, msg)) + ); + } else { + log::warn!( + "┖─ {}", + colors::gray(format!("npm:{:?} ({})", package_id, msg)) + ); } } - fs::write(scripts_run_path, "")?; } } - if !packages_with_scripts_not_run.is_empty() { - let (maybe_install, maybe_install_example) = if *crate::args::DENO_FUTURE { - ( - " or `deno install`", - " or `deno install --allow-scripts=pkg1,pkg2`", - ) - } else { - ("", "") - }; - let packages = packages_with_scripts_not_run - .iter() - .map(|(_, p)| format!("npm:{p}")) - .collect::>() - .join(", "); - log::warn!("{}: Packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed. - This may cause the packages to not work correctly. To run them, use the `--allow-scripts` flag with `deno cache`{maybe_install} - (e.g. `deno cache --allow-scripts=pkg1,pkg2 `{maybe_install_example}):\n {packages}", crate::colors::yellow("warning")); - for (scripts_warned_path, _) in packages_with_scripts_not_run { - let _ignore_err = fs::write(scripts_warned_path, ""); - } - } + lifecycle_scripts + .finish( + snapshot, + &package_partitions.packages, + Some(root_node_modules_dir_path), + progress_bar, + ) + .await?; setup_cache.save(); drop(single_process_lock); @@ -850,6 +724,98 @@ async fn sync_resolution_with_fs( Ok(()) } +/// `node_modules/.deno//` +fn local_node_modules_package_folder( + local_registry_dir: &Path, + package: &NpmResolutionPackage, +) -> PathBuf { + local_registry_dir.join(get_package_folder_id_folder_name( + &package.get_package_cache_folder_id(), + )) +} + +struct LocalLifecycleScripts<'a> { + deno_local_registry_dir: &'a Path, +} + +impl<'a> LocalLifecycleScripts<'a> { + /// `node_modules/.deno//.scripts-run` + fn ran_scripts_file(&self, package: &NpmResolutionPackage) -> PathBuf { + local_node_modules_package_folder(self.deno_local_registry_dir, package) + .join(".scripts-run") + } + + /// `node_modules/.deno//.scripts-warned` + fn warned_scripts_file(&self, package: &NpmResolutionPackage) -> PathBuf { + local_node_modules_package_folder(self.deno_local_registry_dir, package) + .join(".scripts-warned") + } +} + +impl<'a> super::common::lifecycle_scripts::LifecycleScriptsStrategy + for LocalLifecycleScripts<'a> +{ + fn package_path(&self, package: &NpmResolutionPackage) -> PathBuf { + local_node_modules_package_contents_path( + self.deno_local_registry_dir, + package, + ) + } + + fn did_run_scripts( + &self, + package: &NpmResolutionPackage, + ) -> std::result::Result<(), deno_core::anyhow::Error> { + std::fs::write(self.ran_scripts_file(package), "")?; + Ok(()) + } + + fn warn_on_scripts_not_run( + &self, + packages: &[(&NpmResolutionPackage, std::path::PathBuf)], + ) -> Result<(), AnyError> { + if !packages.is_empty() { + log::warn!("{} The following packages contained npm lifecycle scripts ({}) that were not executed:", colors::yellow("Warning"), colors::gray("preinstall/install/postinstall")); + + for (package, _) in packages { + log::warn!("┠─ {}", colors::gray(format!("npm:{}", package.id.nv))); + } + + log::warn!("┃"); + log::warn!( + "┠─ {}", + colors::italic("This may cause the packages to not work correctly.") + ); + log::warn!("┖─ {}", colors::italic("To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`:")); + let packages_comma_separated = packages + .iter() + .map(|(p, _)| format!("npm:{}", p.id.nv)) + .collect::>() + .join(","); + log::warn!( + " {}", + colors::bold(format!( + "deno install --allow-scripts={}", + packages_comma_separated + )) + ); + + for (package, _) in packages { + let _ignore_err = fs::write(self.warned_scripts_file(package), ""); + } + } + Ok(()) + } + + fn has_warned(&self, package: &NpmResolutionPackage) -> bool { + self.warned_scripts_file(package).exists() + } + + fn has_run(&self, package: &NpmResolutionPackage) -> bool { + self.ran_scripts_file(package).exists() + } +} + // Uses BTreeMap to preserve the ordering of the elements in memory, to ensure // the file generated from this datastructure is deterministic. // See: https://github.com/denoland/deno/issues/24479 @@ -988,17 +954,13 @@ fn get_package_folder_id_folder_name( folder_id: &NpmPackageCacheFolderId, ) -> String { let copy_str = if folder_id.copy_index == 0 { - "".to_string() + Cow::Borrowed("") } else { - format!("_{}", folder_id.copy_index) + Cow::Owned(format!("_{}", folder_id.copy_index)) }; let nv = &folder_id.nv; - let name = if nv.name.to_lowercase() == nv.name { - Cow::Borrowed(&nv.name) - } else { - Cow::Owned(format!("_{}", mixed_case_package_name_encode(&nv.name))) - }; - format!("{}@{}{}", name, nv.version, copy_str).replace('/', "+") + let name = normalize_pkg_name_for_node_modules_deno_folder(&nv.name); + format!("{}@{}{}", name, nv.version, copy_str) } fn get_package_folder_id_from_folder_name( @@ -1039,42 +1001,50 @@ fn symlink_package_dir( // need to delete the previous symlink before creating a new one let _ignore = fs::remove_dir_all(new_path); + let old_path_relative = + crate::util::path::relative_path(new_parent, old_path) + .unwrap_or_else(|| old_path.to_path_buf()); + #[cfg(windows)] - return junction_or_symlink_dir(old_path, new_path); + { + junction_or_symlink_dir(&old_path_relative, old_path, new_path) + } #[cfg(not(windows))] - symlink_dir(old_path, new_path) + { + symlink_dir(&old_path_relative, new_path).map_err(Into::into) + } } #[cfg(windows)] fn junction_or_symlink_dir( + old_path_relative: &Path, old_path: &Path, new_path: &Path, ) -> Result<(), AnyError> { - use deno_core::anyhow::bail; - // Use junctions because they're supported on ntfs file systems without - // needing to elevate privileges on Windows + static USE_JUNCTIONS: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); - match junction::create(old_path, new_path) { + if USE_JUNCTIONS.load(std::sync::atomic::Ordering::Relaxed) { + // Use junctions because they're supported on ntfs file systems without + // needing to elevate privileges on Windows. + // Note: junctions don't support relative paths, so we need to use the + // absolute path here. + return junction::create(old_path, new_path) + .context("Failed creating junction in node_modules folder"); + } + + match symlink_dir(old_path_relative, new_path) { Ok(()) => Ok(()), - Err(junction_err) => { - if cfg!(debug_assertions) { - // When running the tests, junctions should be created, but if not then - // surface this error. - log::warn!("Error creating junction. {:#}", junction_err); - } - - match symlink_dir(old_path, new_path) { - Ok(()) => Ok(()), - Err(symlink_err) => bail!( - concat!( - "Failed creating junction and fallback symlink in node_modules folder.\n\n", - "{:#}\n\n{:#}", - ), - junction_err, - symlink_err, - ), - } + Err(symlink_err) + if symlink_err.kind() == std::io::ErrorKind::PermissionDenied => + { + USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed); + junction::create(old_path, new_path).map_err(Into::into) } + Err(symlink_err) => Err( + AnyError::from(symlink_err) + .context("Failed creating symlink in node_modules folder"), + ), } } diff --git a/cli/npm/managed/resolvers/mod.rs b/cli/npm/managed/resolvers/mod.rs index 2dfc323e91..36d795ee7e 100644 --- a/cli/npm/managed/resolvers/mod.rs +++ b/cli/npm/managed/resolvers/mod.rs @@ -11,7 +11,7 @@ use deno_npm::NpmSystemInfo; use deno_runtime::deno_fs::FileSystem; use crate::args::LifecycleScriptsConfig; -use crate::args::PackageJsonInstallDepsProvider; +use crate::args::NpmInstallDepsProvider; use crate::util::progress_bar::ProgressBar; pub use self::common::NpmPackageFsResolver; @@ -27,7 +27,7 @@ use super::resolution::NpmResolution; pub fn create_npm_fs_resolver( fs: Arc, npm_cache: Arc, - pkg_json_deps_provider: &Arc, + npm_install_deps_provider: &Arc, progress_bar: &ProgressBar, resolution: Arc, tarball_cache: Arc, @@ -39,7 +39,7 @@ pub fn create_npm_fs_resolver( Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new( npm_cache, fs, - pkg_json_deps_provider.clone(), + npm_install_deps_provider.clone(), progress_bar.clone(), resolution, tarball_cache, @@ -53,6 +53,7 @@ pub fn create_npm_fs_resolver( tarball_cache, resolution, system_info, + lifecycle_scripts, )), } } diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index c8f87e6aff..f48f7a7405 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -1,38 +1,49 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. mod byonm; -mod cache_dir; mod common; mod managed; +use std::path::Path; use std::path::PathBuf; use std::sync::Arc; +use common::maybe_auth_header_for_npm_registry; use dashmap::DashMap; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_core::serde_json; +use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageInfo; +use deno_resolver::npm::ByonmNpmResolver; +use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError; use deno_runtime::deno_node::NodeRequireResolver; -use deno_runtime::deno_node::NpmProcessStateProvider; -use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::ops::process::NpmProcessStateProvider; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; +use managed::cache::registry_info::get_package_url; use node_resolver::NpmResolver; +use thiserror::Error; -use crate::args::npm_registry_url; use crate::file_fetcher::FileFetcher; -pub use self::byonm::ByonmCliNpmResolver; -pub use self::byonm::CliNpmResolverByonmCreateOptions; -pub use self::cache_dir::NpmCacheDir; +pub use self::byonm::CliByonmNpmResolver; +pub use self::byonm::CliByonmNpmResolverCreateOptions; pub use self::managed::CliNpmResolverManagedCreateOptions; pub use self::managed::CliNpmResolverManagedSnapshotOption; pub use self::managed::ManagedCliNpmResolver; +#[derive(Debug, Error)] +pub enum ResolvePkgFolderFromDenoReqError { + #[error(transparent)] + Managed(deno_core::error::AnyError), + #[error(transparent)] + Byonm(#[from] ByonmResolvePkgFolderFromDenoReqError), +} + pub enum CliNpmResolverCreateOptions { Managed(CliNpmResolverManagedCreateOptions), - Byonm(CliNpmResolverByonmCreateOptions), + Byonm(CliByonmNpmResolverCreateOptions), } pub async fn create_cli_npm_resolver_for_lsp( @@ -43,7 +54,7 @@ pub async fn create_cli_npm_resolver_for_lsp( Managed(options) => { managed::create_managed_npm_resolver_for_lsp(options).await } - Byonm(options) => byonm::create_byonm_npm_resolver(options), + Byonm(options) => Arc::new(ByonmNpmResolver::new(options)), } } @@ -53,14 +64,14 @@ pub async fn create_cli_npm_resolver( use CliNpmResolverCreateOptions::*; match options { Managed(options) => managed::create_managed_npm_resolver(options).await, - Byonm(options) => Ok(byonm::create_byonm_npm_resolver(options)), + Byonm(options) => Ok(Arc::new(ByonmNpmResolver::new(options))), } } pub enum InnerCliNpmResolverRef<'a> { Managed(&'a ManagedCliNpmResolver), #[allow(dead_code)] - Byonm(&'a ByonmCliNpmResolver), + Byonm(&'a CliByonmNpmResolver), } pub trait CliNpmResolver: NpmResolver { @@ -81,20 +92,20 @@ pub trait CliNpmResolver: NpmResolver { } } - fn as_byonm(&self) -> Option<&ByonmCliNpmResolver> { + fn as_byonm(&self) -> Option<&CliByonmNpmResolver> { match self.as_inner() { InnerCliNpmResolverRef::Managed(_) => None, InnerCliNpmResolverRef::Byonm(inner) => Some(inner), } } - fn root_node_modules_path(&self) -> Option<&PathBuf>; + fn root_node_modules_path(&self) -> Option<&Path>; fn resolve_pkg_folder_from_deno_module_req( &self, req: &PackageReq, referrer: &ModuleSpecifier, - ) -> Result; + ) -> Result; /// Returns a hash returning the state of the npm resolver /// or `None` if the state currently can't be determined. @@ -106,14 +117,19 @@ pub struct NpmFetchResolver { nv_by_req: DashMap>, info_by_name: DashMap>>, file_fetcher: Arc, + npmrc: Arc, } impl NpmFetchResolver { - pub fn new(file_fetcher: Arc) -> Self { + pub fn new( + file_fetcher: Arc, + npmrc: Arc, + ) -> Self { Self { nv_by_req: Default::default(), info_by_name: Default::default(), file_fetcher, + npmrc, } } @@ -148,12 +164,19 @@ impl NpmFetchResolver { return info.value().clone(); } let fetch_package_info = || async { - let info_url = npm_registry_url().join(name).ok()?; + let info_url = get_package_url(&self.npmrc, name); let file_fetcher = self.file_fetcher.clone(); + let registry_config = self.npmrc.get_registry_config(name); + // TODO(bartlomieju): this should error out, not use `.ok()`. + let maybe_auth_header = + maybe_auth_header_for_npm_registry(registry_config).ok()?; // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&info_url, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions_with_maybe_auth( + &info_url, + maybe_auth_header, + ) .await .ok() }) diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 5521253ffd..5d1e6e746d 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -11,7 +11,6 @@ use deno_core::op2; use deno_core::v8; use deno_core::ModuleSpecifier; use deno_core::OpState; -use deno_runtime::deno_permissions::create_child_permissions; use deno_runtime::deno_permissions::ChildPermissionsArg; use deno_runtime::deno_permissions::PermissionsContainer; use tokio::sync::mpsc::UnboundedSender; @@ -60,11 +59,7 @@ pub fn op_pledge_test_permissions( ) -> Result { let token = Uuid::new_v4(); let parent_permissions = state.borrow_mut::(); - let worker_permissions = { - let mut parent_permissions = parent_permissions.0.lock(); - let perms = create_child_permissions(&mut parent_permissions, args)?; - PermissionsContainer::new(perms) - }; + let worker_permissions = parent_permissions.create_child_permissions(args)?; let parent_permissions = parent_permissions.clone(); if state.try_take::().is_some() { @@ -74,7 +69,6 @@ pub fn op_pledge_test_permissions( state.put::(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put(worker_permissions.0.clone()); state.put::(worker_permissions); Ok(token) @@ -91,7 +85,6 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put(permissions.0.clone()); state.put::(permissions); Ok(()) } else { diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index b8839a6f8b..c3f469656c 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -16,7 +16,6 @@ use deno_core::op2; use deno_core::v8; use deno_core::ModuleSpecifier; use deno_core::OpState; -use deno_runtime::deno_permissions::create_child_permissions; use deno_runtime::deno_permissions::ChildPermissionsArg; use deno_runtime::deno_permissions::PermissionsContainer; use std::sync::atomic::AtomicUsize; @@ -55,11 +54,7 @@ pub fn op_pledge_test_permissions( ) -> Result { let token = Uuid::new_v4(); let parent_permissions = state.borrow_mut::(); - let worker_permissions = { - let mut parent_permissions = parent_permissions.0.lock(); - let perms = create_child_permissions(&mut parent_permissions, args)?; - PermissionsContainer::new(perms) - }; + let worker_permissions = parent_permissions.create_child_permissions(args)?; let parent_permissions = parent_permissions.clone(); if state.try_take::().is_some() { @@ -68,7 +63,6 @@ pub fn op_pledge_test_permissions( state.put::(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put(worker_permissions.0.clone()); state.put::(worker_permissions); Ok(token) @@ -85,7 +79,6 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put(permissions.0.clone()); state.put::(permissions); Ok(()) } else { diff --git a/cli/resolver.rs b/cli/resolver.rs index a62828b6ec..84c671268a 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -22,12 +22,13 @@ use deno_graph::NpmLoadError; use deno_graph::NpmResolvePkgReqsResult; use deno_npm::resolution::NpmResolutionError; use deno_package_json::PackageJsonDepValue; +use deno_resolver::sloppy_imports::SloppyImportsResolutionMode; +use deno_resolver::sloppy_imports::SloppyImportsResolver; use deno_runtime::colors; use deno_runtime::deno_fs; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::is_builtin_node_module; use deno_runtime::deno_node::NodeResolver; -use deno_runtime::fs_util::specifier_to_file_path; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; use node_resolver::errors::ClosestPkgJsonError; @@ -42,7 +43,6 @@ use node_resolver::NodeModuleKind; use node_resolver::NodeResolution; use node_resolver::NodeResolutionMode; use node_resolver::PackageJson; -use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -52,7 +52,9 @@ use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS; use crate::node::CliNodeCodeTranslator; use crate::npm::CliNpmResolver; use crate::npm::InnerCliNpmResolverRef; +use crate::util::path::specifier_has_extension; use crate::util::sync::AtomicFlag; +use crate::util::text_encoding::from_utf8_lossy_owned; pub struct ModuleCodeStringSource { pub code: ModuleSourceCode, @@ -60,13 +62,52 @@ pub struct ModuleCodeStringSource { pub media_type: MediaType, } +#[derive(Debug, Clone)] +pub struct CliDenoResolverFs(pub Arc); + +impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs { + fn read_to_string_lossy(&self, path: &Path) -> std::io::Result { + self + .0 + .read_text_file_lossy_sync(path, None) + .map_err(|e| e.into_io_error()) + } + + fn realpath_sync(&self, path: &Path) -> std::io::Result { + self.0.realpath_sync(path).map_err(|e| e.into_io_error()) + } + + fn is_dir_sync(&self, path: &Path) -> bool { + self.0.is_dir_sync(path) + } + + fn read_dir_sync( + &self, + dir_path: &Path, + ) -> std::io::Result> { + self + .0 + .read_dir_sync(dir_path) + .map(|entries| { + entries + .into_iter() + .map(|e| deno_resolver::fs::DirEntry { + name: e.name, + is_file: e.is_file, + is_directory: e.is_directory, + }) + .collect::>() + }) + .map_err(|err| err.into_io_error()) + } +} + #[derive(Debug)] pub struct CliNodeResolver { cjs_resolutions: Arc, fs: Arc, node_resolver: Arc, - // todo(dsherret): remove this pub(crate) - pub(crate) npm_resolver: Arc, + npm_resolver: Arc, } impl CliNodeResolver { @@ -146,7 +187,7 @@ impl CliNodeResolver { concat!( "Could not resolve \"{}\", but found it in a package.json. ", "Deno expects the node_modules/ directory to be up to date. ", - "Did you forget to run `npm install`?" + "Did you forget to run `deno install`?" ), specifier )); @@ -175,7 +216,7 @@ impl CliNodeResolver { referrer: &ModuleSpecifier, mode: NodeResolutionMode, ) -> Result { - let referrer_kind = if self.cjs_resolutions.contains(referrer) { + let referrer_kind = if self.cjs_resolutions.is_known_cjs(referrer) { NodeModuleKind::Cjs } else { NodeModuleKind::Esm @@ -225,13 +266,8 @@ impl CliNodeResolver { let package_json_path = package_folder.join("package.json"); if !self.fs.exists_sync(&package_json_path) { return Err(anyhow!( - "Could not find '{}'. Deno expects the node_modules/ directory to be up to date. Did you forget to run `{}`?", + "Could not find '{}'. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?", package_json_path.display(), - if *crate::args::DENO_FUTURE { - "deno install" - } else { - "npm install" - }, )); } } @@ -275,9 +311,7 @@ impl CliNodeResolver { if self.in_npm_package(&specifier) { let resolution = self.node_resolver.url_to_node_resolution(specifier)?; - if let NodeResolution::CommonJs(specifier) = &resolution { - self.cjs_resolutions.insert(specifier.clone()); - } + let resolution = self.handle_node_resolution(resolution); return Ok(Some(resolution.into_url())); } } @@ -298,12 +332,17 @@ impl CliNodeResolver { ) -> NodeResolution { if let NodeResolution::CommonJs(specifier) = &resolution { // remember that this was a common js resolution - self.cjs_resolutions.insert(specifier.clone()); + self.mark_cjs_resolution(specifier.clone()); } resolution } + + pub fn mark_cjs_resolution(&self, specifier: ModuleSpecifier) { + self.cjs_resolutions.insert(specifier); + } } +// todo(dsherret): move to module_loader.rs #[derive(Clone)] pub struct NpmModuleLoader { cjs_resolutions: Arc, @@ -327,16 +366,9 @@ impl NpmModuleLoader { } } - pub async fn load_if_in_npm_package( - &self, - specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - ) -> Option> { - if self.node_resolver.in_npm_package(specifier) { - Some(self.load(specifier, maybe_referrer).await) - } else { - None - } + pub fn if_in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { + self.node_resolver.in_npm_package(specifier) + || self.cjs_resolutions.is_known_cjs(specifier) } pub async fn load( @@ -381,14 +413,9 @@ impl NpmModuleLoader { } })?; - let code = if self.cjs_resolutions.contains(specifier) { + let code = if self.cjs_resolutions.is_known_cjs(specifier) { // translate cjs to esm if it's cjs and inject node globals - let code = match String::from_utf8_lossy(&code) { - Cow::Owned(code) => code, - // SAFETY: `String::from_utf8_lossy` guarantees that the result is valid - // UTF-8 if `Cow::Borrowed` is returned. - Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(code) }, - }; + let code = from_utf8_lossy_owned(code); ModuleSourceCode::String( self .node_code_translator @@ -413,8 +440,12 @@ impl NpmModuleLoader { pub struct CjsResolutionStore(DashSet); impl CjsResolutionStore { - pub fn contains(&self, specifier: &ModuleSpecifier) -> bool { - self.0.contains(specifier) + pub fn is_known_cjs(&self, specifier: &ModuleSpecifier) -> bool { + if specifier.scheme() != "file" { + return false; + } + + specifier_has_extension(specifier, "cjs") || self.0.contains(specifier) } pub fn insert(&self, specifier: ModuleSpecifier) { @@ -422,13 +453,16 @@ impl CjsResolutionStore { } } +pub type CliSloppyImportsResolver = + SloppyImportsResolver; + /// A resolver that takes care of resolution, taking into account loaded /// import map, JSX settings. #[derive(Debug)] pub struct CliGraphResolver { node_resolver: Option>, npm_resolver: Option>, - sloppy_imports_resolver: Option>, + sloppy_imports_resolver: Option>, workspace_resolver: Arc, maybe_default_jsx_import_source: Option, maybe_default_jsx_import_source_types: Option, @@ -442,7 +476,7 @@ pub struct CliGraphResolver { pub struct CliGraphResolverOptions<'a> { pub node_resolver: Option>, pub npm_resolver: Option>, - pub sloppy_imports_resolver: Option>, + pub sloppy_imports_resolver: Option>, pub workspace_resolver: Arc, pub bare_node_builtins_enabled: bool, pub maybe_jsx_import_source_config: Option, @@ -507,7 +541,7 @@ impl Resolver for CliGraphResolver { fn resolve( &self, - specifier: &str, + raw_specifier: &str, referrer_range: &deno_graph::Range, mode: ResolutionMode, ) -> Result { @@ -524,7 +558,7 @@ impl Resolver for CliGraphResolver { if let Some(node_resolver) = self.node_resolver.as_ref() { if referrer.scheme() == "file" && node_resolver.in_npm_package(referrer) { return node_resolver - .resolve(specifier, referrer, to_node_mode(mode)) + .resolve(raw_specifier, referrer, to_node_mode(mode)) .map(|res| res.into_url()) .map_err(|e| ResolveError::Other(e.into())); } @@ -533,7 +567,7 @@ impl Resolver for CliGraphResolver { // Attempt to resolve with the workspace resolver let result: Result<_, ResolveError> = self .workspace_resolver - .resolve(specifier, referrer) + .resolve(raw_specifier, referrer) .map_err(|err| match err { MappedResolutionError::Specifier(err) => ResolveError::Specifier(err), MappedResolutionError::ImportMap(err) => { @@ -566,7 +600,15 @@ impl Resolver for CliGraphResolver { if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver { Ok( sloppy_imports_resolver - .resolve(&specifier, mode) + .resolve( + &specifier, + match mode { + ResolutionMode::Execution => { + SloppyImportsResolutionMode::Execution + } + ResolutionMode::Types => SloppyImportsResolutionMode::Types, + }, + ) .map(|s| s.into_specifier()) .unwrap_or(specifier), ) @@ -705,10 +747,17 @@ impl Resolver for CliGraphResolver { // If byonm, check if the bare specifier resolves to an npm package if is_byonm && referrer.scheme() == "file" { let maybe_resolution = node_resolver - .resolve_if_for_npm_pkg(specifier, referrer, to_node_mode(mode)) + .resolve_if_for_npm_pkg(raw_specifier, referrer, to_node_mode(mode)) .map_err(ResolveError::Other)?; if let Some(res) = maybe_resolution { - return Ok(res.into_url()); + match res { + NodeResolution::Esm(url) | NodeResolution::CommonJs(url) => { + return Ok(url) + } + NodeResolution::BuiltIn(_) => { + // don't resolve bare specifiers for built-in modules via node resolution + } + } } } @@ -754,7 +803,7 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> { let line = start.line + 1; let column = start.character + 1; if !*DENO_DISABLE_PEDANTIC_NODE_WARNINGS { - log::warn!("Warning: Resolving \"{module_name}\" as \"node:{module_name}\" at {specifier}:{line}:{column}. If you want to use a built-in Node module, add a \"node:\" prefix.") + log::warn!("{} Resolving \"{module_name}\" as \"node:{module_name}\" at {specifier}:{line}:{column}. If you want to use a built-in Node module, add a \"node:\" prefix.", colors::yellow("Warning")) } } @@ -841,96 +890,18 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum SloppyImportsFsEntry { - File, - Dir, -} - -impl SloppyImportsFsEntry { - pub fn from_fs_stat( - stat: &deno_runtime::deno_io::fs::FsStat, - ) -> Option { - if stat.is_file { - Some(SloppyImportsFsEntry::File) - } else if stat.is_directory { - Some(SloppyImportsFsEntry::Dir) - } else { - None - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum SloppyImportsResolution { - /// Ex. `./file.js` to `./file.ts` - JsToTs(ModuleSpecifier), - /// Ex. `./file` to `./file.ts` - NoExtension(ModuleSpecifier), - /// Ex. `./dir` to `./dir/index.ts` - Directory(ModuleSpecifier), -} - -impl SloppyImportsResolution { - pub fn as_specifier(&self) -> &ModuleSpecifier { - match self { - Self::JsToTs(specifier) => specifier, - Self::NoExtension(specifier) => specifier, - Self::Directory(specifier) => specifier, - } - } - - pub fn into_specifier(self) -> ModuleSpecifier { - match self { - Self::JsToTs(specifier) => specifier, - Self::NoExtension(specifier) => specifier, - Self::Directory(specifier) => specifier, - } - } - - pub fn as_suggestion_message(&self) -> String { - format!("Maybe {}", self.as_base_message()) - } - - pub fn as_quick_fix_message(&self) -> String { - let message = self.as_base_message(); - let mut chars = message.chars(); - format!( - "{}{}.", - chars.next().unwrap().to_uppercase(), - chars.as_str() - ) - } - - fn as_base_message(&self) -> String { - match self { - SloppyImportsResolution::JsToTs(specifier) => { - let media_type = MediaType::from_specifier(specifier); - format!("change the extension to '{}'", media_type.as_ts_extension()) - } - SloppyImportsResolution::NoExtension(specifier) => { - let media_type = MediaType::from_specifier(specifier); - format!("add a '{}' extension", media_type.as_ts_extension()) - } - SloppyImportsResolution::Directory(specifier) => { - let file_name = specifier - .path() - .rsplit_once('/') - .map(|(_, file_name)| file_name) - .unwrap_or(specifier.path()); - format!("specify path to '{}' file in directory instead", file_name) - } - } - } -} - #[derive(Debug)] -pub struct SloppyImportsResolver { - fs: Arc, - cache: Option>>, +pub struct SloppyImportsCachedFs { + fs: Arc, + cache: Option< + DashMap< + PathBuf, + Option, + >, + >, } -impl SloppyImportsResolver { +impl SloppyImportsCachedFs { pub fn new(fs: Arc) -> Self { Self { fs, @@ -941,409 +912,34 @@ impl SloppyImportsResolver { pub fn new_without_stat_cache(fs: Arc) -> Self { Self { fs, cache: None } } +} - pub fn resolve( +impl deno_resolver::sloppy_imports::SloppyImportResolverFs + for SloppyImportsCachedFs +{ + fn stat_sync( &self, - specifier: &ModuleSpecifier, - mode: ResolutionMode, - ) -> Option { - fn path_without_ext( - path: &Path, - media_type: MediaType, - ) -> Option> { - let old_path_str = path.to_string_lossy(); - match media_type { - MediaType::Unknown => Some(old_path_str), - _ => old_path_str - .strip_suffix(media_type.as_ts_extension()) - .map(|s| Cow::Owned(s.to_string())), - } - } - - fn media_types_to_paths( - path_no_ext: &str, - original_media_type: MediaType, - probe_media_type_types: Vec, - reason: SloppyImportsResolutionReason, - ) -> Vec<(PathBuf, SloppyImportsResolutionReason)> { - probe_media_type_types - .into_iter() - .filter(|media_type| *media_type != original_media_type) - .map(|media_type| { - ( - PathBuf::from(format!( - "{}{}", - path_no_ext, - media_type.as_ts_extension() - )), - reason, - ) - }) - .collect::>() - } - - if specifier.scheme() != "file" { - return None; - } - - let path = specifier_to_file_path(specifier).ok()?; - - #[derive(Clone, Copy)] - enum SloppyImportsResolutionReason { - JsToTs, - NoExtension, - Directory, - } - - let probe_paths: Vec<(PathBuf, SloppyImportsResolutionReason)> = - match self.stat_sync(&path) { - Some(SloppyImportsFsEntry::File) => { - if mode.is_types() { - let media_type = MediaType::from_specifier(specifier); - // attempt to resolve the .d.ts file before the .js file - let probe_media_type_types = match media_type { - MediaType::JavaScript => { - vec![(MediaType::Dts), MediaType::JavaScript] - } - MediaType::Mjs => { - vec![MediaType::Dmts, MediaType::Dts, MediaType::Mjs] - } - MediaType::Cjs => { - vec![MediaType::Dcts, MediaType::Dts, MediaType::Cjs] - } - _ => return None, - }; - let path_no_ext = path_without_ext(&path, media_type)?; - media_types_to_paths( - &path_no_ext, - media_type, - probe_media_type_types, - SloppyImportsResolutionReason::JsToTs, - ) - } else { - return None; - } - } - entry @ None | entry @ Some(SloppyImportsFsEntry::Dir) => { - let media_type = MediaType::from_specifier(specifier); - let probe_media_type_types = match media_type { - MediaType::JavaScript => ( - if mode.is_types() { - vec![MediaType::TypeScript, MediaType::Tsx, MediaType::Dts] - } else { - vec![MediaType::TypeScript, MediaType::Tsx] - }, - SloppyImportsResolutionReason::JsToTs, - ), - MediaType::Jsx => { - (vec![MediaType::Tsx], SloppyImportsResolutionReason::JsToTs) - } - MediaType::Mjs => ( - if mode.is_types() { - vec![MediaType::Mts, MediaType::Dmts, MediaType::Dts] - } else { - vec![MediaType::Mts] - }, - SloppyImportsResolutionReason::JsToTs, - ), - MediaType::Cjs => ( - if mode.is_types() { - vec![MediaType::Cts, MediaType::Dcts, MediaType::Dts] - } else { - vec![MediaType::Cts] - }, - SloppyImportsResolutionReason::JsToTs, - ), - MediaType::TypeScript - | MediaType::Mts - | MediaType::Cts - | MediaType::Dts - | MediaType::Dmts - | MediaType::Dcts - | MediaType::Tsx - | MediaType::Json - | MediaType::Wasm - | MediaType::TsBuildInfo - | MediaType::SourceMap => { - return None; - } - MediaType::Unknown => ( - if mode.is_types() { - vec![ - MediaType::TypeScript, - MediaType::Tsx, - MediaType::Mts, - MediaType::Dts, - MediaType::Dmts, - MediaType::Dcts, - MediaType::JavaScript, - MediaType::Jsx, - MediaType::Mjs, - ] - } else { - vec![ - MediaType::TypeScript, - MediaType::JavaScript, - MediaType::Tsx, - MediaType::Jsx, - MediaType::Mts, - MediaType::Mjs, - ] - }, - SloppyImportsResolutionReason::NoExtension, - ), - }; - let mut probe_paths = match path_without_ext(&path, media_type) { - Some(path_no_ext) => media_types_to_paths( - &path_no_ext, - media_type, - probe_media_type_types.0, - probe_media_type_types.1, - ), - None => vec![], - }; - - if matches!(entry, Some(SloppyImportsFsEntry::Dir)) { - // try to resolve at the index file - if mode.is_types() { - probe_paths.push(( - path.join("index.ts"), - SloppyImportsResolutionReason::Directory, - )); - - probe_paths.push(( - path.join("index.mts"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.d.ts"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.d.mts"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.js"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.mjs"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.tsx"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.jsx"), - SloppyImportsResolutionReason::Directory, - )); - } else { - probe_paths.push(( - path.join("index.ts"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.mts"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.tsx"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.js"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.mjs"), - SloppyImportsResolutionReason::Directory, - )); - probe_paths.push(( - path.join("index.jsx"), - SloppyImportsResolutionReason::Directory, - )); - } - } - if probe_paths.is_empty() { - return None; - } - probe_paths - } - }; - - for (probe_path, reason) in probe_paths { - if self.stat_sync(&probe_path) == Some(SloppyImportsFsEntry::File) { - if let Ok(specifier) = ModuleSpecifier::from_file_path(probe_path) { - match reason { - SloppyImportsResolutionReason::JsToTs => { - return Some(SloppyImportsResolution::JsToTs(specifier)); - } - SloppyImportsResolutionReason::NoExtension => { - return Some(SloppyImportsResolution::NoExtension(specifier)); - } - SloppyImportsResolutionReason::Directory => { - return Some(SloppyImportsResolution::Directory(specifier)); - } - } - } - } - } - - None - } - - fn stat_sync(&self, path: &Path) -> Option { + path: &Path, + ) -> Option { if let Some(cache) = &self.cache { if let Some(entry) = cache.get(path) { return *entry; } } - let entry = self - .fs - .stat_sync(path) - .ok() - .and_then(|stat| SloppyImportsFsEntry::from_fs_stat(&stat)); + let entry = self.fs.stat_sync(path).ok().and_then(|stat| { + if stat.is_file { + Some(deno_resolver::sloppy_imports::SloppyImportsFsEntry::File) + } else if stat.is_directory { + Some(deno_resolver::sloppy_imports::SloppyImportsFsEntry::Dir) + } else { + None + } + }); + if let Some(cache) = &self.cache { cache.insert(path.to_owned(), entry); } entry } } - -#[cfg(test)] -mod test { - use test_util::TestContext; - - use super::*; - - #[test] - fn test_unstable_sloppy_imports() { - fn resolve(specifier: &ModuleSpecifier) -> Option { - resolve_with_mode(specifier, ResolutionMode::Execution) - } - - fn resolve_types( - specifier: &ModuleSpecifier, - ) -> Option { - resolve_with_mode(specifier, ResolutionMode::Types) - } - - fn resolve_with_mode( - specifier: &ModuleSpecifier, - mode: ResolutionMode, - ) -> Option { - SloppyImportsResolver::new(Arc::new(deno_fs::RealFs)) - .resolve(specifier, mode) - } - - let context = TestContext::default(); - let temp_dir = context.temp_dir().path(); - - // scenarios like resolving ./example.js to ./example.ts - for (ext_from, ext_to) in [("js", "ts"), ("js", "tsx"), ("mjs", "mts")] { - let ts_file = temp_dir.join(format!("file.{}", ext_to)); - ts_file.write(""); - assert_eq!(resolve(&ts_file.uri_file()), None); - assert_eq!( - resolve( - &temp_dir - .uri_dir() - .join(&format!("file.{}", ext_from)) - .unwrap() - ), - Some(SloppyImportsResolution::JsToTs(ts_file.uri_file())), - ); - ts_file.remove_file(); - } - - // no extension scenarios - for ext in ["js", "ts", "js", "tsx", "jsx", "mjs", "mts"] { - let file = temp_dir.join(format!("file.{}", ext)); - file.write(""); - assert_eq!( - resolve( - &temp_dir - .uri_dir() - .join("file") // no ext - .unwrap() - ), - Some(SloppyImportsResolution::NoExtension(file.uri_file())) - ); - file.remove_file(); - } - - // .ts and .js exists, .js specified (goes to specified) - { - let ts_file = temp_dir.join("file.ts"); - ts_file.write(""); - let js_file = temp_dir.join("file.js"); - js_file.write(""); - assert_eq!(resolve(&js_file.uri_file()), None); - } - - // only js exists, .js specified - { - let js_only_file = temp_dir.join("js_only.js"); - js_only_file.write(""); - assert_eq!(resolve(&js_only_file.uri_file()), None); - assert_eq!(resolve_types(&js_only_file.uri_file()), None); - } - - // resolving a directory to an index file - { - let routes_dir = temp_dir.join("routes"); - routes_dir.create_dir_all(); - let index_file = routes_dir.join("index.ts"); - index_file.write(""); - assert_eq!( - resolve(&routes_dir.uri_file()), - Some(SloppyImportsResolution::Directory(index_file.uri_file())), - ); - } - - // both a directory and a file with specifier is present - { - let api_dir = temp_dir.join("api"); - api_dir.create_dir_all(); - let bar_file = api_dir.join("bar.ts"); - bar_file.write(""); - let api_file = temp_dir.join("api.ts"); - api_file.write(""); - assert_eq!( - resolve(&api_dir.uri_file()), - Some(SloppyImportsResolution::NoExtension(api_file.uri_file())), - ); - } - } - - #[test] - fn test_sloppy_import_resolution_suggestion_message() { - // directory - assert_eq!( - SloppyImportsResolution::Directory( - ModuleSpecifier::parse("file:///dir/index.js").unwrap() - ) - .as_suggestion_message(), - "Maybe specify path to 'index.js' file in directory instead" - ); - // no ext - assert_eq!( - SloppyImportsResolution::NoExtension( - ModuleSpecifier::parse("file:///dir/index.mjs").unwrap() - ) - .as_suggestion_message(), - "Maybe add a '.mjs' extension" - ); - // js to ts - assert_eq!( - SloppyImportsResolution::JsToTs( - ModuleSpecifier::parse("file:///dir/index.mts").unwrap() - ) - .as_suggestion_message(), - "Maybe change the extension to '.mts'" - ); - } -} diff --git a/cli/schemas/config-file.v1.json b/cli/schemas/config-file.v1.json index 733a9cab60..27c8499ea2 100644 --- a/cli/schemas/config-file.v1.json +++ b/cli/schemas/config-file.v1.json @@ -1,6 +1,6 @@ { "$id": "https://deno.land/x/deno/cli/schemas/config-file.v1.json", - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "description": "A JSON representation of a Deno configuration file.", "required": [], "title": "Deno configuration file Schema", @@ -9,6 +9,7 @@ "compilerOptions": { "type": "object", "description": "Instructs the TypeScript compiler how to compile .ts files.", + "additionalProperties": false, "properties": { "allowJs": { "description": "Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files.", @@ -34,17 +35,31 @@ "default": false, "markdownDescription": "Enable error reporting in type-checked JavaScript files.\n\nSee more: https://www.typescriptlang.org/tsconfig#checkJs" }, - "exactOptionalPropertyTypes": { - "description": "Differentiate between undefined and not present when type checking", + "emitDecoratorMetadata": { + "description": "Emit design-type metadata for decorated declarations in source files.", "type": "boolean", "default": false, - "markdownDescription": "Differentiate between undefined and not present when type checking\n\nSee more: https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes" + "deprecated": true, + "markdownDescription": "Emit design-type metadata for decorated declarations in source files.\n\nSee more: https://www.typescriptlang.org/tsconfig/#emitDecoratorMetadata" + }, + "exactOptionalPropertyTypes": { + "description": "Interpret optional property types as written, rather than adding 'undefined'.", + "type": "boolean", + "default": false, + "markdownDescription": "Interpret optional property types as written, rather than adding 'undefined'.\n\nSee more: https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes" }, "experimentalDecorators": { - "description": "Enable experimental support for TC39 stage 2 draft decorators.", + "description": "Enable experimental support for legacy experimental decorators.", "type": "boolean", - "default": true, - "markdownDescription": "Enable experimental support for TC39 stage 2 draft decorators.\n\nSee more: https://www.typescriptlang.org/tsconfig#experimentalDecorators" + "default": false, + "deprecated": true, + "markdownDescription": "Enable experimental support for legacy experimental decorators.\n\nSee more: https://www.typescriptlang.org/tsconfig#experimentalDecorators" + }, + "isolatedDeclarations": { + "description": "Require sufficient annotation on exports so other tools can trivially generate declaration files.", + "type": "boolean", + "default": false, + "markdownDescription": "Require sufficient annotation on exports so other tools can trivially generate declaration files.\n\nSee more: https://www.typescriptlang.org/tsconfig/#isolatedDeclarations" }, "jsx": { "description": "Specify what JSX code is generated.", @@ -90,12 +105,6 @@ }, "markdownDescription": "Specify list of elements that should be exempt from being precompiled when the jsx `precompile` transform is used." }, - "keyofStringsOnly": { - "description": "Make keyof only return strings instead of string, numbers or symbols. Legacy option.", - "type": "boolean", - "default": false, - "markdownDescription": "Make keyof only return strings instead of string, numbers or symbols. Legacy option.\n\nSee more: https://www.typescriptlang.org/tsconfig#keyofStringsOnly" - }, "lib": { "description": "Specify a set of bundled library declaration files that describe the target runtime environment.", "type": "array", @@ -119,15 +128,15 @@ "markdownDescription": "Enable error reporting for fallthrough cases in switch statements.\n\nSee more: https://www.typescriptlang.org/tsconfig#noFallthroughCasesInSwitch" }, "noImplicitAny": { - "description": "Enable error reporting for expressions and declarations with an implied `any` type..", + "description": "Enable error reporting for expressions and declarations with an implied `any` type.", "type": "boolean", "default": true, - "markdownDescription": "Enable error reporting for expressions and declarations with an implied `any` type..\n\nSee more: https://www.typescriptlang.org/tsconfig#noImplicitAny" + "markdownDescription": "Enable error reporting for expressions and declarations with an implied `any` type.\n\nSee more: https://www.typescriptlang.org/tsconfig#noImplicitAny" }, "noImplicitOverride": { "description": "Ensure overriding members in derived classes are marked with an override modifier.", "type": "boolean", - "default": false, + "default": true, "markdownDescription": "Ensure overriding members in derived classes are marked with an override modifier.\n\nSee more: https://www.typescriptlang.org/tsconfig#noImplicitOverride" }, "noImplicitReturns": { @@ -142,17 +151,17 @@ "default": true, "markdownDescription": "Enable error reporting when `this` is given the type `any`.\n\nSee more: https://www.typescriptlang.org/tsconfig#noImplicitThis" }, - "noImplicitUseStrict": { - "description": "Disable adding 'use strict' directives in emitted JavaScript files.", - "type": "boolean", - "default": true, - "markdownDescription": "Disable adding 'use strict' directives in emitted JavaScript files.\n\nSee more: https://www.typescriptlang.org/tsconfig#noImplicitUseStrict" - }, - "noStrictGenericChecks": { - "description": "Disable strict checking of generic signatures in function types.", + "noPropertyAccessFromIndexSignature": { + "description": "Enforces using indexed accessors for keys declared using an indexed type.", "type": "boolean", "default": false, - "markdownDescription": "Disable strict checking of generic signatures in function types.\n\nSee more: https://www.typescriptlang.org/tsconfig#noStrictGenericChecks" + "markdownDescription": "Enforces using indexed accessors for keys declared using an indexed type.\n\nSee more: https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature" + }, + "noUncheckedIndexedAccess": { + "description": "Add `undefined` to a type when accessed using an index.", + "type": "boolean", + "default": false, + "markdownDescription": "Add `undefined` to a type when accessed using an index.\n\nSee more: https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess" }, "noUnusedLocals": { "description": "Enable error reporting when a local variables aren't read.", @@ -166,12 +175,6 @@ "default": false, "markdownDescription": "Raise an error when a function parameter isn't read\n\nSee more: https://www.typescriptlang.org/tsconfig#noUnusedParameters" }, - "noUncheckedIndexedAccess": { - "description": "Add `undefined` to a type when accessed using an index.", - "type": "boolean", - "default": false, - "markdownDescription": "Add `undefined` to a type when accessed using an index.\n\nSee more: https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess" - }, "strict": { "description": "Enable all strict type checking options.", "type": "boolean", @@ -184,35 +187,49 @@ "default": true, "markdownDescription": "Check that the arguments for `bind`, `call`, and `apply` methods match the original function.\n\nSee more: https://www.typescriptlang.org/tsconfig#strictBindCallApply" }, + "strictBuiltinIteratorReturn": { + "description": "Built-in iterators are instantiated with a `TReturn` type of undefined instead of `any`.", + "type": "boolean", + "default": true, + "markdownDescription": "Built-in iterators are instantiated with a `TReturn` type of undefined instead of `any`.\n\nSee more: https://www.typescriptlang.org/tsconfig/#strictBuiltinIteratorReturn" + }, "strictFunctionTypes": { "description": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.", "type": "boolean", "default": true, "markdownDescription": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.\n\nSee more: https://www.typescriptlang.org/tsconfig#strictFunctionTypes" }, - "strictPropertyInitialization": { - "description": "Check for class properties that are declared but not set in the constructor.", - "type": "boolean", - "default": true, - "markdownDescription": "Check for class properties that are declared but not set in the constructor.\n\nSee more: https://www.typescriptlang.org/tsconfig#strictPropertyInitialization" - }, "strictNullChecks": { "description": "When type checking, take into account `null` and `undefined`.", "type": "boolean", "default": true, "markdownDescription": "When type checking, take into account `null` and `undefined`.\n\nSee more: https://www.typescriptlang.org/tsconfig#strictNullChecks" }, - "suppressExcessPropertyErrors": { - "description": "Disable reporting of excess property errors during the creation of object literals.", + "strictPropertyInitialization": { + "description": "Check for class properties that are declared but not set in the constructor.", "type": "boolean", - "default": false, - "markdownDescription": "Disable reporting of excess property errors during the creation of object literals.\n\nSee more: https://www.typescriptlang.org/tsconfig#suppressExcessPropertyErrors" + "default": true, + "markdownDescription": "Check for class properties that are declared but not set in the constructor.\n\nSee more: https://www.typescriptlang.org/tsconfig#strictPropertyInitialization" }, - "suppressImplicitAnyIndexErrors": { - "description": "Suppress `noImplicitAny` errors when indexing objects that lack index signatures.", + "types": { + "description": "Specify type package names to be included without being referenced in a source file.", + "type": "array", + "items": { + "type": "string" + }, + "markdownDescription": "Specify type package names to be included without being referenced in a source file.\n\nSee more: https://www.typescriptlang.org/tsconfig/#types" + }, + "useUnknownInCatchVariables": { + "description": "Default catch clause variables as `unknown` instead of `any`.", + "type": "boolean", + "default": true, + "markdownDescription": "Default catch clause variables as `unknown` instead of `any`.\n\nSee more: https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables" + }, + "verbatimModuleSyntax": { + "description": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.", "type": "boolean", "default": false, - "markdownDescription": "Suppress `noImplicitAny` errors when indexing objects that lack index signatures.\n\nSee more: https://www.typescriptlang.org/tsconfig#suppressImplicitAnyIndexErrors" + "markdownDescription": "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting.\n\nSee more: https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax" } } }, @@ -267,25 +284,6 @@ "type": "string" } }, - "files": { - "type": "object", - "properties": { - "include": { - "type": "array", - "description": "List of files, directories or globs that will be linted.", - "items": { - "type": "string" - } - }, - "exclude": { - "type": "array", - "description": "List of files, directories or globs that will not be linted.", - "items": { - "type": "string" - } - } - } - }, "rules": { "type": "object", "properties": { @@ -293,7 +291,7 @@ "type": "array", "description": "List of tag names that will be run. Empty list disables all tags and will only use rules from `include`.", "items": { - "type": "string" + "$ref": "https://raw.githubusercontent.com/denoland/deno_lint/main/schemas/tags.v1.json" }, "minItems": 0, "uniqueItems": true @@ -302,7 +300,7 @@ "type": "array", "description": "List of rule names that will be excluded from configured tag sets. If the same rule is in `include` it will be run.", "items": { - "type": "string" + "$ref": "https://raw.githubusercontent.com/denoland/deno_lint/main/schemas/rules.v1.json" }, "minItems": 0, "uniqueItems": true @@ -311,7 +309,7 @@ "type": "array", "description": "List of rule names that will be run. Even if the same rule is in `exclude` it will be run.", "items": { - "type": "string" + "$ref": "https://raw.githubusercontent.com/denoland/deno_lint/main/schemas/rules.v1.json" }, "minItems": 0, "uniqueItems": true @@ -343,25 +341,6 @@ "type": "string" } }, - "files": { - "type": "object", - "properties": { - "include": { - "type": "array", - "description": "List of files, directories or globs that will be formatted.", - "items": { - "type": "string" - } - }, - "exclude": { - "type": "array", - "description": "List of files, directories or globs that will not be formatted.", - "items": { - "type": "string" - } - } - } - }, "useTabs": { "description": "Whether to use tabs (true) or spaces (false) for indentation.", "type": "boolean", @@ -430,8 +409,18 @@ } }, "nodeModulesDir": { - "description": "Enables or disables the use of a local node_modules folder for npm packages. Alternatively, use the `--node-modules-dir` flag or override the config via `--node-modules-dir=false`. Requires Deno 1.34 or later.", - "type": "boolean" + "oneOf": [ + { + "description": "Sets the node_modules management mode for npm packages. Alternatively, use the `--node-modules-dir=` flag. Requires Deno 2.0-rc.1 or later.", + "default": "none", + "enum": ["auto", "manual", "none"] + }, + { + "description": "Enables or disables the use of a local node_modules folder for npm packages. Alternatively, use the `--node-modules-dir` flag or override the config via `--node-modules-dir=false`. Requires Deno 1.34 or later.", + "type": "boolean", + "deprecated": false + } + ] }, "vendor": { "description": "Enables or disables the use of a local vendor folder as a local cache for remote modules and node_modules folder for npm packages. Alternatively, use the `--vendor` flag or override the config via `--vendor=false`. Requires Deno 1.36.1 or later.", @@ -465,25 +454,6 @@ "items": { "type": "string" } - }, - "files": { - "type": "object", - "properties": { - "include": { - "type": "array", - "description": "List of files, directories or globs that will be searched for tests.", - "items": { - "type": "string" - } - }, - "exclude": { - "type": "array", - "description": "List of files, directories or globs that will not be searched for tests.", - "items": { - "type": "string" - } - } - } } } }, @@ -524,25 +494,6 @@ "items": { "type": "string" } - }, - "files": { - "type": "object", - "properties": { - "include": { - "type": "array", - "description": "List of files, directories or globs that will be searched for benchmarks.", - "items": { - "type": "string" - } - }, - "exclude": { - "type": "array", - "description": "List of files, directories or globs that will not be searched for benchmarks.", - "items": { - "type": "string" - } - } - } } } }, @@ -577,8 +528,10 @@ "bare-node-builtins", "byonm", "cron", + "detect-cjs", "ffi", "fs", + "fmt-component", "http", "kv", "net", @@ -610,6 +563,11 @@ { "type": "object", "description": "A map of package exports to files in this JSR package.", + "propertyNames": { + "description": "Package export name", + "examples": [".", "./foo", "./bar"], + "pattern": "^\\.(/.*)?$" + }, "patternProperties": { "^\\.(/.*)?$": { "type": "string", diff --git a/cli/schemas/module-graph.json b/cli/schemas/module-graph.json index b761badded..ea32d843be 100644 --- a/cli/schemas/module-graph.json +++ b/cli/schemas/module-graph.json @@ -83,14 +83,6 @@ "type": "string", "description": "The checksum of the local source file. This can be used to validate if the current on disk version matches the version described here." }, - "emit": { - "type": "string", - "description": "The path to an emitted version of the module, if the module requires transpilation to be loaded into the Deno runtime." - }, - "map": { - "type": "string", - "description": "The path to an optionally emitted source map between the original and emitted version of the file." - }, "error": { "type": "string", "description": "If when resolving the module, Deno encountered an error and the module is unavailable, the text of that error will be indicated here." diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index d80f8a969d..f41f3003ff 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -9,14 +9,18 @@ use std::ffi::OsString; use std::fs; use std::fs::File; use std::future::Future; +use std::io::ErrorKind; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; use std::io::Write; +use std::ops::Range; use std::path::Path; use std::path::PathBuf; use std::process::Command; +use std::sync::Arc; +use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::ResolverWorkspaceJsrPackage; @@ -30,13 +34,22 @@ use deno_core::futures::AsyncReadExt; use deno_core::futures::AsyncSeekExt; use deno_core::serde_json; use deno_core::url::Url; +use deno_graph::source::RealFileSystem; +use deno_graph::ModuleGraph; +use deno_npm::resolution::SerializedNpmResolutionSnapshot; +use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; +use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; +use deno_npm::NpmPackageId; use deno_npm::NpmSystemInfo; +use deno_runtime::deno_fs; +use deno_runtime::deno_fs::FileSystem; +use deno_runtime::deno_fs::RealFs; +use deno_runtime::deno_io::fs::FsError; use deno_runtime::deno_node::PackageJson; use deno_semver::npm::NpmVersionReqParseError; use deno_semver::package::PackageReq; use deno_semver::Version; use deno_semver::VersionReqSpecifierParseError; -use eszip::EszipRelativeFileBaseUrl; use indexmap::IndexMap; use log::Level; use serde::Deserialize; @@ -45,10 +58,11 @@ use serde::Serialize; use crate::args::CaData; use crate::args::CliOptions; use crate::args::CompileFlags; -use crate::args::PackageJsonInstallDepsProvider; +use crate::args::NpmInstallDepsProvider; use crate::args::PermissionFlags; use crate::args::UnstableConfig; use crate::cache::DenoDir; +use crate::emit::Emitter; use crate::file_fetcher::FileFetcher; use crate::http_util::HttpClientProvider; use crate::npm::CliNpmResolver; @@ -60,12 +74,63 @@ use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBarStyle; +use super::file_system::DenoCompileFileSystem; +use super::serialization::deserialize_binary_data_section; +use super::serialization::serialize_binary_data_section; +use super::serialization::DenoCompileModuleData; +use super::serialization::DeserializedDataSection; +use super::serialization::RemoteModulesStore; +use super::serialization::RemoteModulesStoreBuilder; use super::virtual_fs::FileBackedVfs; use super::virtual_fs::VfsBuilder; use super::virtual_fs::VfsRoot; use super::virtual_fs::VirtualDirectory; -const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd"; +/// A URL that can be designated as the base for relative URLs. +/// +/// After creation, this URL may be used to get the key for a +/// module in the binary. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct StandaloneRelativeFileBaseUrl<'a>(&'a Url); + +impl<'a> From<&'a Url> for StandaloneRelativeFileBaseUrl<'a> { + fn from(url: &'a Url) -> Self { + Self(url) + } +} + +impl<'a> StandaloneRelativeFileBaseUrl<'a> { + pub fn new(url: &'a Url) -> Self { + debug_assert_eq!(url.scheme(), "file"); + Self(url) + } + + /// Gets the module map key of the provided specifier. + /// + /// * Descendant file specifiers will be made relative to the base. + /// * Non-descendant file specifiers will stay as-is (absolute). + /// * Non-file specifiers will stay as-is. + pub fn specifier_key<'b>(&self, target: &'b Url) -> Cow<'b, str> { + if target.scheme() != "file" { + return Cow::Borrowed(target.as_str()); + } + + match self.0.make_relative(target) { + Some(relative) => { + if relative.starts_with("../") { + Cow::Borrowed(target.as_str()) + } else { + Cow::Owned(relative) + } + } + None => Cow::Borrowed(target.as_str()), + } + } + + pub fn inner(&self) -> &Url { + self.0 + } +} #[derive(Deserialize, Serialize)] pub enum NodeModules { @@ -117,82 +182,26 @@ pub struct Metadata { pub workspace_resolver: SerializedWorkspaceResolver, pub entrypoint_key: String, pub node_modules: Option, - pub disable_deprecated_api_warning: bool, pub unstable_config: UnstableConfig, } -pub fn load_npm_vfs(root_dir_path: PathBuf) -> Result { - let data = libsui::find_section("d3n0l4nd").unwrap(); - - // We do the first part sync so it can complete quickly - let trailer: [u8; TRAILER_SIZE] = data[0..TRAILER_SIZE].try_into().unwrap(); - let trailer = match Trailer::parse(&trailer)? { - None => panic!("Could not find trailer"), - Some(trailer) => trailer, - }; - let data = &data[TRAILER_SIZE..]; - - let vfs_data = - &data[trailer.npm_vfs_pos as usize..trailer.npm_files_pos as usize]; - let mut dir: VirtualDirectory = serde_json::from_slice(vfs_data)?; - - // align the name of the directory with the root dir - dir.name = root_dir_path - .file_name() - .unwrap() - .to_string_lossy() - .to_string(); - - let fs_root = VfsRoot { - dir, - root_path: root_dir_path, - start_file_offset: trailer.npm_files_pos, - }; - Ok(FileBackedVfs::new(data.to_vec(), fs_root)) -} - fn write_binary_bytes( mut file_writer: File, original_bin: Vec, metadata: &Metadata, - eszip: eszip::EszipV2, - npm_vfs: Option<&VirtualDirectory>, - npm_files: &Vec>, + npm_snapshot: Option, + remote_modules: &RemoteModulesStoreBuilder, + vfs: VfsBuilder, compile_flags: &CompileFlags, ) -> Result<(), AnyError> { - let metadata = serde_json::to_string(metadata)?.as_bytes().to_vec(); - let npm_vfs = serde_json::to_string(&npm_vfs)?.as_bytes().to_vec(); - let eszip_archive = eszip.into_bytes(); - - let mut writer = Vec::new(); - - // write the trailer, which includes the positions - // of the data blocks in the file - writer.write_all(&{ - let metadata_pos = eszip_archive.len() as u64; - let npm_vfs_pos = metadata_pos + (metadata.len() as u64); - let npm_files_pos = npm_vfs_pos + (npm_vfs.len() as u64); - Trailer { - eszip_pos: 0, - metadata_pos, - npm_vfs_pos, - npm_files_pos, - } - .as_bytes() - })?; - - writer.write_all(&eszip_archive)?; - writer.write_all(&metadata)?; - writer.write_all(&npm_vfs)?; - for file in npm_files { - writer.write_all(file)?; - } + let data_section_bytes = + serialize_binary_data_section(metadata, npm_snapshot, remote_modules, vfs)?; let target = compile_flags.resolve_target(); if target.contains("linux") { libsui::Elf::new(&original_bin).append( "d3n0l4nd", - &writer, + &data_section_bytes, &mut file_writer, )?; } else if target.contains("windows") { @@ -202,11 +211,11 @@ fn write_binary_bytes( pe = pe.set_icon(&icon)?; } - pe.write_resource("d3n0l4nd", writer)? + pe.write_resource("d3n0l4nd", data_section_bytes)? .build(&mut file_writer)?; } else if target.contains("darwin") { libsui::Macho::from(original_bin)? - .write_section("d3n0l4nd", writer)? + .write_section("d3n0l4nd", data_section_bytes)? .build_and_sign(&mut file_writer)?; } Ok(()) @@ -222,6 +231,63 @@ pub fn is_standalone_binary(exe_path: &Path) -> bool { || libsui::utils::is_macho(&data) } +pub struct StandaloneData { + pub fs: Arc, + pub metadata: Metadata, + pub modules: StandaloneModules, + pub npm_snapshot: Option, + pub root_path: PathBuf, + pub vfs: Arc, +} + +pub struct StandaloneModules { + remote_modules: RemoteModulesStore, + vfs: Arc, +} + +impl StandaloneModules { + pub fn resolve_specifier<'a>( + &'a self, + specifier: &'a ModuleSpecifier, + ) -> Result, AnyError> { + if specifier.scheme() == "file" { + Ok(Some(specifier)) + } else { + self.remote_modules.resolve_specifier(specifier) + } + } + + pub fn read<'a>( + &'a self, + specifier: &'a ModuleSpecifier, + ) -> Result>, AnyError> { + if specifier.scheme() == "file" { + let path = deno_path_util::url_to_file_path(specifier)?; + let bytes = match self.vfs.file_entry(&path) { + Ok(entry) => self.vfs.read_file_all(entry)?, + Err(err) if err.kind() == ErrorKind::NotFound => { + let bytes = match RealFs.read_file_sync(&path, None) { + Ok(bytes) => bytes, + Err(FsError::Io(err)) if err.kind() == ErrorKind::NotFound => { + return Ok(None) + } + Err(err) => return Err(err.into()), + }; + Cow::Owned(bytes) + } + Err(err) => return Err(err.into()), + }; + Ok(Some(DenoCompileModuleData { + media_type: MediaType::from_specifier(specifier), + specifier, + data: bytes, + })) + } else { + self.remote_modules.read(specifier) + } + } +} + /// This function will try to run this binary as a standalone binary /// produced by `deno compile`. It determines if this is a standalone /// binary by skipping over the trailer width at the end of the file, @@ -229,110 +295,66 @@ pub fn is_standalone_binary(exe_path: &Path) -> bool { /// the bundle is executed. If not, this function exits with `Ok(None)`. pub fn extract_standalone( cli_args: Cow>, -) -> Result< - Option>>, - AnyError, -> { +) -> Result, AnyError> { let Some(data) = libsui::find_section("d3n0l4nd") else { return Ok(None); }; - // We do the first part sync so it can complete quickly - let trailer = match Trailer::parse(&data[0..TRAILER_SIZE])? { + let DeserializedDataSection { + mut metadata, + npm_snapshot, + remote_modules, + mut vfs_dir, + vfs_files_data, + } = match deserialize_binary_data_section(data)? { + Some(data_section) => data_section, None => return Ok(None), - Some(trailer) => trailer, }; + let root_path = { + let maybe_current_exe = std::env::current_exe().ok(); + let current_exe_name = maybe_current_exe + .as_ref() + .and_then(|p| p.file_name()) + .map(|p| p.to_string_lossy()) + // should never happen + .unwrap_or_else(|| Cow::Borrowed("binary")); + std::env::temp_dir().join(format!("deno-compile-{}", current_exe_name)) + }; let cli_args = cli_args.into_owned(); - // If we have an eszip, read it out - Ok(Some(async move { - let bufreader = - deno_core::futures::io::BufReader::new(&data[TRAILER_SIZE..]); + metadata.argv.reserve(cli_args.len() - 1); + for arg in cli_args.into_iter().skip(1) { + metadata.argv.push(arg.into_string().unwrap()); + } + let vfs = { + // align the name of the directory with the root dir + vfs_dir.name = root_path.file_name().unwrap().to_string_lossy().to_string(); - let (eszip, loader) = eszip::EszipV2::parse(bufreader) - .await - .context("Failed to parse eszip header")?; - - let bufreader = loader.await.context("Failed to parse eszip archive")?; - - let mut metadata = String::new(); - - bufreader - .take(trailer.metadata_len()) - .read_to_string(&mut metadata) - .await - .context("Failed to read metadata from the current executable")?; - - let mut metadata: Metadata = serde_json::from_str(&metadata).unwrap(); - metadata.argv.reserve(cli_args.len() - 1); - for arg in cli_args.into_iter().skip(1) { - metadata.argv.push(arg.into_string().unwrap()); - } - - Ok((metadata, eszip)) + let fs_root = VfsRoot { + dir: vfs_dir, + root_path: root_path.clone(), + start_file_offset: 0, + }; + Arc::new(FileBackedVfs::new(Cow::Borrowed(vfs_files_data), fs_root)) + }; + let fs: Arc = + Arc::new(DenoCompileFileSystem::new(vfs.clone())); + Ok(Some(StandaloneData { + fs, + metadata, + modules: StandaloneModules { + remote_modules, + vfs: vfs.clone(), + }, + npm_snapshot, + root_path, + vfs, })) } -const TRAILER_SIZE: usize = std::mem::size_of::() + 8; // 8 bytes for the magic trailer string - -struct Trailer { - eszip_pos: u64, - metadata_pos: u64, - npm_vfs_pos: u64, - npm_files_pos: u64, -} - -impl Trailer { - pub fn parse(trailer: &[u8]) -> Result, AnyError> { - let (magic_trailer, rest) = trailer.split_at(8); - if magic_trailer != MAGIC_TRAILER { - return Ok(None); - } - - let (eszip_archive_pos, rest) = rest.split_at(8); - let (metadata_pos, rest) = rest.split_at(8); - let (npm_vfs_pos, npm_files_pos) = rest.split_at(8); - let eszip_archive_pos = u64_from_bytes(eszip_archive_pos)?; - let metadata_pos = u64_from_bytes(metadata_pos)?; - let npm_vfs_pos = u64_from_bytes(npm_vfs_pos)?; - let npm_files_pos = u64_from_bytes(npm_files_pos)?; - Ok(Some(Trailer { - eszip_pos: eszip_archive_pos, - metadata_pos, - npm_vfs_pos, - npm_files_pos, - })) - } - - pub fn metadata_len(&self) -> u64 { - self.npm_vfs_pos - self.metadata_pos - } - - pub fn npm_vfs_len(&self) -> u64 { - self.npm_files_pos - self.npm_vfs_pos - } - - pub fn as_bytes(&self) -> Vec { - let mut trailer = MAGIC_TRAILER.to_vec(); - trailer.write_all(&self.eszip_pos.to_be_bytes()).unwrap(); - trailer.write_all(&self.metadata_pos.to_be_bytes()).unwrap(); - trailer.write_all(&self.npm_vfs_pos.to_be_bytes()).unwrap(); - trailer - .write_all(&self.npm_files_pos.to_be_bytes()) - .unwrap(); - trailer - } -} - -fn u64_from_bytes(arr: &[u8]) -> Result { - let fixed_arr: &[u8; 8] = arr - .try_into() - .context("Failed to convert the buffer into a fixed-size array")?; - Ok(u64::from_be_bytes(*fixed_arr)) -} - pub struct DenoCompileBinaryWriter<'a> { deno_dir: &'a DenoDir, + emitter: &'a Emitter, file_fetcher: &'a FileFetcher, http_client_provider: &'a HttpClientProvider, npm_resolver: &'a dyn CliNpmResolver, @@ -344,6 +366,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { #[allow(clippy::too_many_arguments)] pub fn new( deno_dir: &'a DenoDir, + emitter: &'a Emitter, file_fetcher: &'a FileFetcher, http_client_provider: &'a HttpClientProvider, npm_resolver: &'a dyn CliNpmResolver, @@ -352,6 +375,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { ) -> Self { Self { deno_dir, + emitter, file_fetcher, http_client_provider, npm_resolver, @@ -363,8 +387,8 @@ impl<'a> DenoCompileBinaryWriter<'a> { pub async fn write_bin( &self, writer: File, - eszip: eszip::EszipV2, - root_dir_url: EszipRelativeFileBaseUrl<'_>, + graph: &ModuleGraph, + root_dir_url: StandaloneRelativeFileBaseUrl<'_>, entrypoint: &ModuleSpecifier, compile_flags: &CompileFlags, cli_options: &CliOptions, @@ -391,15 +415,17 @@ impl<'a> DenoCompileBinaryWriter<'a> { ) } } - self.write_standalone_binary( - writer, - original_binary, - eszip, - root_dir_url, - entrypoint, - cli_options, - compile_flags, - ) + self + .write_standalone_binary( + writer, + original_binary, + graph, + root_dir_url, + entrypoint, + cli_options, + compile_flags, + ) + .await } async fn get_base_binary( @@ -428,13 +454,9 @@ impl<'a> DenoCompileBinaryWriter<'a> { binary_name ) } - ReleaseChannel::Stable => { + _ => { format!("release/v{}/{}", env!("CARGO_PKG_VERSION"), binary_name) } - _ => bail!( - "`deno compile` current doesn't support {} release channel", - crate::version::DENO_VERSION_INFO.release_channel.name() - ), }; let download_directory = self.deno_dir.dl_folder_path(); @@ -473,7 +495,11 @@ impl<'a> DenoCompileBinaryWriter<'a> { self .http_client_provider .get_or_create()? - .download_with_progress(download_url.parse()?, None, &progress) + .download_with_progress_and_retries( + download_url.parse()?, + None, + &progress, + ) .await? }; let bytes = match maybe_bytes { @@ -494,12 +520,12 @@ impl<'a> DenoCompileBinaryWriter<'a> { /// This functions creates a standalone deno binary by appending a bundle /// and magic trailer to the currently executing binary. #[allow(clippy::too_many_arguments)] - fn write_standalone_binary( + async fn write_standalone_binary( &self, writer: File, original_bin: Vec, - mut eszip: eszip::EszipV2, - root_dir_url: EszipRelativeFileBaseUrl<'_>, + graph: &ModuleGraph, + root_dir_url: StandaloneRelativeFileBaseUrl<'_>, entrypoint: &ModuleSpecifier, cli_options: &CliOptions, compile_flags: &CompileFlags, @@ -513,19 +539,17 @@ impl<'a> DenoCompileBinaryWriter<'a> { None => None, }; let root_path = root_dir_url.inner().to_file_path().unwrap(); - let (npm_vfs, npm_files, node_modules) = match self.npm_resolver.as_inner() + let (maybe_npm_vfs, node_modules, npm_snapshot) = match self + .npm_resolver + .as_inner() { InnerCliNpmResolverRef::Managed(managed) => { let snapshot = managed.serialized_valid_snapshot_for_system(&self.npm_system_info); if !snapshot.as_serialized().packages.is_empty() { - let (root_dir, files) = self - .build_vfs(&root_path, cli_options)? - .into_dir_and_files(); - eszip.add_npm_snapshot(snapshot); + let npm_vfs_builder = self.build_npm_vfs(&root_path, cli_options)?; ( - Some(root_dir), - files, + Some(npm_vfs_builder), Some(NodeModules::Managed { node_modules_dir: self.npm_resolver.root_node_modules_path().map( |path| { @@ -537,18 +561,16 @@ impl<'a> DenoCompileBinaryWriter<'a> { }, ), }), + Some(snapshot), ) } else { - (None, Vec::new(), None) + (None, None, None) } } InnerCliNpmResolverRef::Byonm(resolver) => { - let (root_dir, files) = self - .build_vfs(&root_path, cli_options)? - .into_dir_and_files(); + let npm_vfs_builder = self.build_npm_vfs(&root_path, cli_options)?; ( - Some(root_dir), - files, + Some(npm_vfs_builder), Some(NodeModules::Byonm { root_node_modules_dir: resolver.root_node_modules_path().map( |node_modules_dir| { @@ -561,9 +583,67 @@ impl<'a> DenoCompileBinaryWriter<'a> { }, ), }), + None, ) } }; + let mut vfs = if let Some(npm_vfs) = maybe_npm_vfs { + npm_vfs + } else { + VfsBuilder::new(root_path.clone())? + }; + let mut remote_modules_store = RemoteModulesStoreBuilder::default(); + for module in graph.modules() { + if module.specifier().scheme() == "data" { + continue; // don't store data urls as an entry as they're in the code + } + let (maybe_source, media_type) = match module { + deno_graph::Module::Js(m) => { + // todo(https://github.com/denoland/deno_media_type/pull/12): use is_emittable() + let is_emittable = matches!( + m.media_type, + MediaType::TypeScript + | MediaType::Mts + | MediaType::Cts + | MediaType::Jsx + | MediaType::Tsx + ); + let source = if is_emittable { + let source = self + .emitter + .emit_parsed_source(&m.specifier, m.media_type, &m.source) + .await?; + source.into_bytes() + } else { + m.source.as_bytes().to_vec() + }; + (Some(source), m.media_type) + } + deno_graph::Module::Json(m) => { + (Some(m.source.as_bytes().to_vec()), m.media_type) + } + deno_graph::Module::Npm(_) + | deno_graph::Module::Node(_) + | deno_graph::Module::External(_) => (None, MediaType::Unknown), + }; + if module.specifier().scheme() == "file" { + let file_path = deno_path_util::url_to_file_path(module.specifier())?; + vfs + .add_file_with_data( + &file_path, + match maybe_source { + Some(source) => source, + None => RealFs.read_file_sync(&file_path, None)?, + }, + ) + .with_context(|| { + format!("Failed adding '{}'", file_path.display()) + })?; + } else if let Some(source) = maybe_source { + remote_modules_store.add(module.specifier(), media_type, source); + } + } + remote_modules_store.add_redirects(&graph.redirects); let env_vars_from_env_file = match cli_options.env_file_name() { Some(env_filename) => { @@ -624,12 +704,10 @@ impl<'a> DenoCompileBinaryWriter<'a> { pkg_json_resolution: self.workspace_resolver.pkg_json_dep_resolution(), }, node_modules, - disable_deprecated_api_warning: cli_options - .disable_deprecated_api_warning, unstable_config: UnstableConfig { - legacy_flag_enabled: cli_options.legacy_unstable_flag(), + legacy_flag_enabled: false, bare_node_builtins: cli_options.unstable_bare_node_builtins(), - byonm: cli_options.use_byonm(), + detect_cjs: cli_options.unstable_detect_cjs(), sloppy_imports: cli_options.unstable_sloppy_imports(), features: cli_options.unstable_features(), }, @@ -639,14 +717,14 @@ impl<'a> DenoCompileBinaryWriter<'a> { writer, original_bin, &metadata, - eszip, - npm_vfs.as_ref(), - &npm_files, + npm_snapshot.map(|s| s.into_serialized()), + &remote_modules_store, + vfs, compile_flags, ) } - fn build_vfs( + fn build_npm_vfs( &self, root_path: &Path, cli_options: &CliOptions, @@ -667,8 +745,8 @@ impl<'a> DenoCompileBinaryWriter<'a> { } else { // DO NOT include the user's registry url as it may contain credentials, // but also don't make this dependent on the registry url - let root_path = npm_resolver.global_cache_root_folder(); - let mut builder = VfsBuilder::new(root_path)?; + let global_cache_root_path = npm_resolver.global_cache_root_folder(); + let mut builder = VfsBuilder::new(global_cache_root_path)?; let mut packages = npm_resolver.all_system_packages(&self.npm_system_info); packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism @@ -678,12 +756,12 @@ impl<'a> DenoCompileBinaryWriter<'a> { builder.add_dir_recursive(&folder)?; } - // Flatten all the registries folders into a single "node_modules/localhost" folder + // Flatten all the registries folders into a single ".deno_compile_node_modules/localhost" folder // that will be used by denort when loading the npm cache. This avoids us exposing // the user's private registry information and means we don't have to bother // serializing all the different registry config into the binary. builder.with_root_dir(|root_dir| { - root_dir.name = "node_modules".to_string(); + root_dir.name = ".deno_compile_node_modules".to_string(); let mut new_entries = Vec::with_capacity(root_dir.entries.len()); let mut localhost_entries = IndexMap::new(); for entry in std::mem::take(&mut root_dir.entries) { @@ -718,6 +796,8 @@ impl<'a> DenoCompileBinaryWriter<'a> { root_dir.entries = new_entries; }); + builder.set_new_root_path(root_path.to_path_buf())?; + Ok(builder) } } diff --git a/cli/standalone/file_system.rs b/cli/standalone/file_system.rs index 536b17f277..712c6ee918 100644 --- a/cli/standalone/file_system.rs +++ b/cli/standalone/file_system.rs @@ -22,8 +22,8 @@ use super::virtual_fs::FileBackedVfs; pub struct DenoCompileFileSystem(Arc); impl DenoCompileFileSystem { - pub fn new(vfs: FileBackedVfs) -> Self { - Self(Arc::new(vfs)) + pub fn new(vfs: Arc) -> Self { + Self(vfs) } fn error_if_in_vfs(&self, path: &Path) -> FsResult<()> { @@ -102,7 +102,7 @@ impl FileSystem for DenoCompileFileSystem { &self, path: &Path, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()> { self.error_if_in_vfs(path)?; RealFs.mkdir_sync(path, recursive, mode) @@ -111,7 +111,7 @@ impl FileSystem for DenoCompileFileSystem { &self, path: PathBuf, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()> { self.error_if_in_vfs(&path)?; RealFs.mkdir_async(path, recursive, mode).await diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 68e1334762..3a62b6ff96 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -5,7 +5,10 @@ #![allow(dead_code)] #![allow(unused_imports)] +use binary::StandaloneData; +use binary::StandaloneModules; use deno_ast::MediaType; +use deno_cache_dir::npm::NpmCacheDir; use deno_config::workspace::MappedResolution; use deno_config::workspace::MappedResolutionError; use deno_config::workspace::ResolverWorkspaceJsrPackage; @@ -32,10 +35,11 @@ use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; +use deno_runtime::deno_web::BlobStore; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::WorkerExecutionMode; use deno_runtime::WorkerLogLevel; use deno_semver::npm::NpmPackageReqReference; -use eszip::EszipRelativeFileBaseUrl; use import_map::parse_from_json; use node_resolver::analyze::NodeCodeTranslator; use node_resolver::NodeResolutionMode; @@ -48,20 +52,22 @@ use crate::args::get_root_cert_store; use crate::args::npm_pkg_req_ref_to_binary_command; use crate::args::CaData; use crate::args::CacheSetting; -use crate::args::PackageJsonInstallDepsProvider; +use crate::args::NpmInstallDepsProvider; use crate::args::StorageKeyResolver; use crate::cache::Caches; +use crate::cache::DenoCacheEnvFsAdapter; use crate::cache::DenoDirProvider; use crate::cache::NodeAnalysisCache; +use crate::cache::RealDenoCacheEnv; use crate::http_util::HttpClientProvider; use crate::node::CliCjsCodeAnalyzer; use crate::npm::create_cli_npm_resolver; -use crate::npm::CliNpmResolverByonmCreateOptions; +use crate::npm::CliByonmNpmResolverCreateOptions; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; -use crate::npm::NpmCacheDir; use crate::resolver::CjsResolutionStore; +use crate::resolver::CliDenoResolverFs; use crate::resolver::CliNodeResolver; use crate::resolver::NpmModuleLoader; use crate::util::progress_bar::ProgressBar; @@ -74,52 +80,18 @@ use crate::worker::ModuleLoaderFactory; pub mod binary; mod file_system; +mod serialization; mod virtual_fs; pub use binary::extract_standalone; pub use binary::is_standalone_binary; pub use binary::DenoCompileBinaryWriter; -use self::binary::load_npm_vfs; use self::binary::Metadata; use self::file_system::DenoCompileFileSystem; -struct WorkspaceEszipModule { - specifier: ModuleSpecifier, - inner: eszip::Module, -} - -struct WorkspaceEszip { - eszip: eszip::EszipV2, - root_dir_url: Arc, -} - -impl WorkspaceEszip { - pub fn get_module( - &self, - specifier: &ModuleSpecifier, - ) -> Option { - if specifier.scheme() == "file" { - let specifier_key = EszipRelativeFileBaseUrl::new(&self.root_dir_url) - .specifier_key(specifier); - let module = self.eszip.get_module(&specifier_key)?; - let specifier = self.root_dir_url.join(&module.specifier).unwrap(); - Some(WorkspaceEszipModule { - specifier, - inner: module, - }) - } else { - let module = self.eszip.get_module(specifier.as_str())?; - Some(WorkspaceEszipModule { - specifier: ModuleSpecifier::parse(&module.specifier).unwrap(), - inner: module, - }) - } - } -} - struct SharedModuleLoaderState { - eszip: WorkspaceEszip, + modules: StandaloneModules, workspace_resolver: WorkspaceResolver, node_resolver: Arc, npm_module_loader: Arc, @@ -128,16 +100,15 @@ struct SharedModuleLoaderState { #[derive(Clone)] struct EmbeddedModuleLoader { shared: Arc, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, } pub const MODULE_NOT_FOUND: &str = "Module not found"; +pub const UNSUPPORTED_SCHEME: &str = "Unsupported scheme"; impl ModuleLoader for EmbeddedModuleLoader { fn resolve( &self, - specifier: &str, + raw_specifier: &str, referrer: &str, kind: ResolutionKind, ) -> Result { @@ -161,13 +132,15 @@ impl ModuleLoader for EmbeddedModuleLoader { self .shared .node_resolver - .resolve(specifier, &referrer, NodeResolutionMode::Execution)? + .resolve(raw_specifier, &referrer, NodeResolutionMode::Execution)? .into_url(), ); } - let mapped_resolution = - self.shared.workspace_resolver.resolve(specifier, &referrer); + let mapped_resolution = self + .shared + .workspace_resolver + .resolve(raw_specifier, &referrer); match mapped_resolution { Ok(MappedResolution::WorkspaceJsrPackage { specifier, .. }) => { @@ -244,8 +217,10 @@ impl ModuleLoader for EmbeddedModuleLoader { } if specifier.scheme() == "jsr" { - if let Some(module) = self.shared.eszip.get_module(&specifier) { - return Ok(module.specifier); + if let Some(specifier) = + self.shared.modules.resolve_specifier(&specifier)? + { + return Ok(specifier.clone()); } } @@ -261,7 +236,7 @@ impl ModuleLoader for EmbeddedModuleLoader { if err.is_unmapped_bare_specifier() && referrer.scheme() == "file" => { let maybe_res = self.shared.node_resolver.resolve_if_for_npm_pkg( - specifier, + raw_specifier, &referrer, NodeResolutionMode::Execution, )?; @@ -340,56 +315,30 @@ impl ModuleLoader for EmbeddedModuleLoader { ); } - let Some(module) = self.shared.eszip.get_module(original_specifier) else { - return deno_core::ModuleLoadResponse::Sync(Err(type_error(format!( - "{MODULE_NOT_FOUND}: {}", - original_specifier - )))); - }; - let original_specifier = original_specifier.clone(); - - deno_core::ModuleLoadResponse::Async( - async move { - let code = module.inner.source().await.ok_or_else(|| { - type_error(format!("Module not found: {}", original_specifier)) - })?; - let code = arc_u8_to_arc_str(code) - .map_err(|_| type_error("Module source is not utf-8"))?; - Ok(deno_core::ModuleSource::new_with_redirect( - match module.inner.kind { - eszip::ModuleKind::JavaScript => ModuleType::JavaScript, - eszip::ModuleKind::Json => ModuleType::Json, - eszip::ModuleKind::Jsonc => { - return Err(type_error("jsonc modules not supported")) - } - eszip::ModuleKind::OpaqueData => { - unreachable!(); - } - }, - ModuleSourceCode::String(code.into()), - &original_specifier, - &module.specifier, - None, + match self.shared.modules.read(original_specifier) { + Ok(Some(module)) => { + let (module_specifier, module_type, module_source) = + module.into_for_v8(); + deno_core::ModuleLoadResponse::Sync(Ok( + deno_core::ModuleSource::new_with_redirect( + module_type, + module_source, + original_specifier, + module_specifier, + None, + ), )) } - .boxed_local(), - ) + Ok(None) => deno_core::ModuleLoadResponse::Sync(Err(type_error( + format!("{MODULE_NOT_FOUND}: {}", original_specifier), + ))), + Err(err) => deno_core::ModuleLoadResponse::Sync(Err(type_error( + format!("{:?}", err), + ))), + } } } -fn arc_u8_to_arc_str( - arc_u8: Arc<[u8]>, -) -> Result, std::str::Utf8Error> { - // Check that the string is valid UTF-8. - std::str::from_utf8(&arc_u8)?; - // SAFETY: the string is valid UTF-8, and the layout Arc<[u8]> is the same as - // Arc. This is proven by the From> impl for Arc<[u8]> from the - // standard library. - Ok(unsafe { - std::mem::transmute::, std::sync::Arc>(arc_u8) - }) -} - struct StandaloneModuleLoaderFactory { shared: Arc, } @@ -397,28 +346,23 @@ struct StandaloneModuleLoaderFactory { impl ModuleLoaderFactory for StandaloneModuleLoaderFactory { fn create_for_main( &self, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, + _root_permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter { ModuleLoaderAndSourceMapGetter { module_loader: Rc::new(EmbeddedModuleLoader { shared: self.shared.clone(), - root_permissions, - dynamic_permissions, }), } } fn create_for_worker( &self, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, + _parent_permissions: PermissionsContainer, + _permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter { ModuleLoaderAndSourceMapGetter { module_loader: Rc::new(EmbeddedModuleLoader { shared: self.shared.clone(), - root_permissions, - dynamic_permissions, }), } } @@ -439,14 +383,15 @@ impl RootCertStoreProvider for StandaloneRootCertStoreProvider { } } -pub async fn run( - mut eszip: eszip::EszipV2, - metadata: Metadata, -) -> Result { - let current_exe_path = std::env::current_exe().unwrap(); - let current_exe_name = - current_exe_path.file_name().unwrap().to_string_lossy(); - let maybe_cwd = std::env::current_dir().ok(); +pub async fn run(data: StandaloneData) -> Result { + let StandaloneData { + fs, + metadata, + modules, + npm_snapshot, + root_path, + vfs, + } = data; let deno_dir_provider = Arc::new(DenoDirProvider::new(None)); let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider { ca_stores: metadata.ca_stores, @@ -460,111 +405,83 @@ pub async fn run( )); // use a dummy npm registry url let npm_registry_url = ModuleSpecifier::parse("https://localhost/").unwrap(); - let root_path = - std::env::temp_dir().join(format!("deno-compile-{}", current_exe_name)); let root_dir_url = Arc::new(ModuleSpecifier::from_directory_path(&root_path).unwrap()); let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap(); - let root_node_modules_path = root_path.join("node_modules"); - let npm_cache_dir = NpmCacheDir::new( - root_node_modules_path.clone(), - vec![npm_registry_url.clone()], - ); - let npm_global_cache_dir = npm_cache_dir.get_cache_location(); + let npm_global_cache_dir = root_path.join(".deno_compile_node_modules"); let cache_setting = CacheSetting::Only; - let (fs, npm_resolver, maybe_vfs_root) = match metadata.node_modules { + let npm_resolver = match metadata.node_modules { Some(binary::NodeModules::Managed { node_modules_dir }) => { - // this will always have a snapshot - let snapshot = eszip.take_npm_snapshot().unwrap(); - let vfs_root_dir_path = if node_modules_dir.is_some() { - root_path.clone() - } else { - npm_cache_dir.root_dir().to_owned() - }; - let vfs = load_npm_vfs(vfs_root_dir_path.clone()) - .context("Failed to load npm vfs.")?; + let snapshot = npm_snapshot.unwrap(); let maybe_node_modules_path = node_modules_dir - .map(|node_modules_dir| vfs_root_dir_path.join(node_modules_dir)); - let fs = Arc::new(DenoCompileFileSystem::new(vfs)) - as Arc; - let npm_resolver = - create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( - CliNpmResolverManagedCreateOptions { - snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some( - snapshot, - )), - maybe_lockfile: None, - fs: fs.clone(), - http_client_provider: http_client_provider.clone(), - npm_global_cache_dir, - cache_setting, - text_only_progress_bar: progress_bar, - maybe_node_modules_path, - npm_system_info: Default::default(), - package_json_deps_provider: Arc::new( - // this is only used for installing packages, which isn't necessary with deno compile - PackageJsonInstallDepsProvider::empty(), - ), - // create an npmrc that uses the fake npm_registry_url to resolve packages - npmrc: Arc::new(ResolvedNpmRc { - default_config: deno_npm::npm_rc::RegistryConfigWithUrl { - registry_url: npm_registry_url.clone(), - config: Default::default(), - }, - scopes: Default::default(), - registry_configs: Default::default(), - }), - lifecycle_scripts: Default::default(), - }, - )) - .await?; - (fs, npm_resolver, Some(vfs_root_dir_path)) + .map(|node_modules_dir| root_path.join(node_modules_dir)); + create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( + CliNpmResolverManagedCreateOptions { + snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some( + snapshot, + )), + maybe_lockfile: None, + fs: fs.clone(), + http_client_provider: http_client_provider.clone(), + npm_global_cache_dir, + cache_setting, + text_only_progress_bar: progress_bar, + maybe_node_modules_path, + npm_system_info: Default::default(), + npm_install_deps_provider: Arc::new( + // this is only used for installing packages, which isn't necessary with deno compile + NpmInstallDepsProvider::empty(), + ), + // create an npmrc that uses the fake npm_registry_url to resolve packages + npmrc: Arc::new(ResolvedNpmRc { + default_config: deno_npm::npm_rc::RegistryConfigWithUrl { + registry_url: npm_registry_url.clone(), + config: Default::default(), + }, + scopes: Default::default(), + registry_configs: Default::default(), + }), + lifecycle_scripts: Default::default(), + }, + )) + .await? } Some(binary::NodeModules::Byonm { root_node_modules_dir, }) => { - let vfs_root_dir_path = root_path.clone(); - let vfs = load_npm_vfs(vfs_root_dir_path.clone()) - .context("Failed to load vfs.")?; let root_node_modules_dir = root_node_modules_dir.map(|p| vfs.root().join(p)); - let fs = Arc::new(DenoCompileFileSystem::new(vfs)) - as Arc; - let npm_resolver = create_cli_npm_resolver( - CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions { - fs: fs.clone(), + create_cli_npm_resolver(CliNpmResolverCreateOptions::Byonm( + CliByonmNpmResolverCreateOptions { + fs: CliDenoResolverFs(fs.clone()), root_node_modules_dir, - }), - ) - .await?; - (fs, npm_resolver, Some(vfs_root_dir_path)) + }, + )) + .await? } None => { - let fs = Arc::new(deno_fs::RealFs) as Arc; - let npm_resolver = - create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( - CliNpmResolverManagedCreateOptions { - snapshot: CliNpmResolverManagedSnapshotOption::Specified(None), - maybe_lockfile: None, - fs: fs.clone(), - http_client_provider: http_client_provider.clone(), - npm_global_cache_dir, - cache_setting, - text_only_progress_bar: progress_bar, - maybe_node_modules_path: None, - npm_system_info: Default::default(), - package_json_deps_provider: Arc::new( - // this is only used for installing packages, which isn't necessary with deno compile - PackageJsonInstallDepsProvider::empty(), - ), - // Packages from different registries are already inlined in the ESZip, - // so no need to create actual `.npmrc` configuration. - npmrc: create_default_npmrc(), - lifecycle_scripts: Default::default(), - }, - )) - .await?; - (fs, npm_resolver, None) + create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( + CliNpmResolverManagedCreateOptions { + snapshot: CliNpmResolverManagedSnapshotOption::Specified(None), + maybe_lockfile: None, + fs: fs.clone(), + http_client_provider: http_client_provider.clone(), + npm_global_cache_dir, + cache_setting, + text_only_progress_bar: progress_bar, + maybe_node_modules_path: None, + npm_system_info: Default::default(), + npm_install_deps_provider: Arc::new( + // this is only used for installing packages, which isn't necessary with deno compile + NpmInstallDepsProvider::empty(), + ), + // Packages from different registries are already inlined in the binary, + // so no need to create actual `.npmrc` configuration. + npmrc: create_default_npmrc(), + lifecycle_scripts: Default::default(), + }, + )) + .await? } }; @@ -576,8 +493,18 @@ pub async fn run( let cjs_resolutions = Arc::new(CjsResolutionStore::default()); let cache_db = Caches::new(deno_dir_provider.clone()); let node_analysis_cache = NodeAnalysisCache::new(cache_db.node_analysis_db()); - let cjs_esm_code_analyzer = - CliCjsCodeAnalyzer::new(node_analysis_cache, fs.clone()); + let cli_node_resolver = Arc::new(CliNodeResolver::new( + cjs_resolutions.clone(), + fs.clone(), + node_resolver.clone(), + npm_resolver.clone(), + )); + let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new( + node_analysis_cache, + fs.clone(), + cli_node_resolver.clone(), + None, + ); let node_code_translator = Arc::new(NodeCodeTranslator::new( cjs_esm_code_analyzer, deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()), @@ -633,22 +560,13 @@ pub async fn run( metadata.workspace_resolver.pkg_json_resolution, ) }; - let cli_node_resolver = Arc::new(CliNodeResolver::new( - cjs_resolutions.clone(), - fs.clone(), - node_resolver.clone(), - npm_resolver.clone(), - )); let module_loader_factory = StandaloneModuleLoaderFactory { shared: Arc::new(SharedModuleLoaderState { - eszip: WorkspaceEszip { - eszip, - root_dir_url, - }, + modules, workspace_resolver, node_resolver: cli_node_resolver.clone(), npm_module_loader: Arc::new(NpmModuleLoader::new( - cjs_resolutions, + cjs_resolutions.clone(), node_code_translator, fs.clone(), cli_node_resolver, @@ -658,33 +576,30 @@ pub async fn run( let permissions = { let mut permissions = - metadata.permissions.to_options(maybe_cwd.as_deref())?; - // if running with an npm vfs, grant read access to it - if let Some(vfs_root) = maybe_vfs_root { - match &mut permissions.allow_read { - Some(vec) if vec.is_empty() => { - // do nothing, already granted - } - Some(vec) => { - vec.push(vfs_root); - } - None => { - permissions.allow_read = Some(vec![vfs_root]); - } + metadata.permissions.to_options(/* cli_arg_urls */ &[]); + // grant read access to the vfs + match &mut permissions.allow_read { + Some(vec) if vec.is_empty() => { + // do nothing, already granted + } + Some(vec) => { + vec.push(root_path.to_string_lossy().to_string()); + } + None => { + permissions.allow_read = + Some(vec![root_path.to_string_lossy().to_string()]); } } - PermissionsContainer::new(Permissions::from_options(&permissions)?) + let desc_parser = + Arc::new(RuntimePermissionDescriptorParser::new(fs.clone())); + let permissions = + Permissions::from_options(desc_parser.as_ref(), &permissions)?; + PermissionsContainer::new(desc_parser, permissions) }; let feature_checker = Arc::new({ let mut checker = FeatureChecker::default(); checker.set_exit_cb(Box::new(crate::unstable_exit_cb)); - // TODO(bartlomieju): enable, once we deprecate `--unstable` in favor - // of granular --unstable-* flags. - // feature_checker.set_warn_cb(Box::new(crate::unstable_warn_cb)); - if metadata.unstable_config.legacy_flag_enabled { - checker.enable_legacy_unstable(); - } for feature in metadata.unstable_config.features { // `metadata` is valid for the whole lifetime of the program, so we // can leak the string here. @@ -693,18 +608,22 @@ pub async fn run( checker }); let worker_factory = CliMainWorkerFactory::new( - StorageKeyResolver::empty(), - crate::args::DenoSubcommand::Run(Default::default()), - npm_resolver, - node_resolver, - Default::default(), - Box::new(module_loader_factory), - root_cert_store_provider, + Arc::new(BlobStore::default()), + cjs_resolutions, + // Code cache is not supported for standalone binary yet. + None, + feature_checker, fs, None, None, None, - feature_checker, + Box::new(module_loader_factory), + node_resolver, + npm_resolver, + root_cert_store_provider, + permissions, + StorageKeyResolver::empty(), + crate::args::DenoSubcommand::Run(Default::default()), CliMainWorkerOptions { argv: metadata.argv, log_level: WorkerLogLevel::Info, @@ -728,29 +647,22 @@ pub async fn run( seed: metadata.seed, unsafely_ignore_certificate_errors: metadata .unsafely_ignore_certificate_errors, - unstable: metadata.unstable_config.legacy_flag_enabled, create_hmr_runner: None, create_coverage_collector: None, + node_ipc: None, + serve_port: None, + serve_host: None, + unstable_detect_cjs: metadata.unstable_config.detect_cjs, }, - None, - None, - None, - false, - // TODO(bartlomieju): temporarily disabled - // metadata.disable_deprecated_api_warning, - true, - false, - // Code cache is not supported for standalone binary yet. - None, ); // Initialize v8 once from the main thread. v8_set_flags(construct_v8_flags(&[], &metadata.v8_flags, vec![])); - // TODO(bartlomieju): remove last argument in Deno 2. + // TODO(bartlomieju): remove last argument once Deploy no longer needs it deno_core::JsRuntime::init_platform(None, true); let mut worker = worker_factory - .create_main_worker(WorkerExecutionMode::Run, main_module, permissions) + .create_main_worker(WorkerExecutionMode::Run, main_module) .await?; let exit_code = worker.run().await?; diff --git a/cli/standalone/serialization.rs b/cli/standalone/serialization.rs new file mode 100644 index 0000000000..12927845bc --- /dev/null +++ b/cli/standalone/serialization.rs @@ -0,0 +1,642 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::io::Write; + +use deno_ast::MediaType; +use deno_core::anyhow::bail; +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_core::serde_json; +use deno_core::url::Url; +use deno_core::FastString; +use deno_core::ModuleSourceCode; +use deno_core::ModuleType; +use deno_npm::resolution::SerializedNpmResolutionSnapshot; +use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; +use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; +use deno_npm::NpmPackageId; +use deno_semver::package::PackageReq; + +use crate::standalone::virtual_fs::VirtualDirectory; + +use super::binary::Metadata; +use super::virtual_fs::VfsBuilder; + +const MAGIC_BYTES: &[u8; 8] = b"d3n0l4nd"; + +/// Binary format: +/// * d3n0l4nd +/// * +/// * +/// * +/// * +/// * +/// * d3n0l4nd +pub fn serialize_binary_data_section( + metadata: &Metadata, + npm_snapshot: Option, + remote_modules: &RemoteModulesStoreBuilder, + vfs: VfsBuilder, +) -> Result, AnyError> { + fn write_bytes_with_len(bytes: &mut Vec, data: &[u8]) { + bytes.extend_from_slice(&(data.len() as u64).to_le_bytes()); + bytes.extend_from_slice(data); + } + + let mut bytes = Vec::new(); + bytes.extend_from_slice(MAGIC_BYTES); + + // 1. Metadata + { + let metadata = serde_json::to_string(metadata)?; + write_bytes_with_len(&mut bytes, metadata.as_bytes()); + } + // 2. Npm snapshot + { + let npm_snapshot = + npm_snapshot.map(serialize_npm_snapshot).unwrap_or_default(); + write_bytes_with_len(&mut bytes, &npm_snapshot); + } + // 3. Remote modules + { + let update_index = bytes.len(); + bytes.extend_from_slice(&(0_u64).to_le_bytes()); + let start_index = bytes.len(); + remote_modules.write(&mut bytes)?; + let length = bytes.len() - start_index; + let length_bytes = (length as u64).to_le_bytes(); + bytes[update_index..update_index + length_bytes.len()] + .copy_from_slice(&length_bytes); + } + // 4. VFS + { + let (vfs, vfs_files) = vfs.into_dir_and_files(); + let vfs = serde_json::to_string(&vfs)?; + write_bytes_with_len(&mut bytes, vfs.as_bytes()); + let vfs_bytes_len = vfs_files.iter().map(|f| f.len() as u64).sum::(); + bytes.extend_from_slice(&vfs_bytes_len.to_le_bytes()); + for file in &vfs_files { + bytes.extend_from_slice(file); + } + } + + // write the magic bytes at the end so we can use it + // to make sure we've deserialized correctly + bytes.extend_from_slice(MAGIC_BYTES); + + Ok(bytes) +} + +pub struct DeserializedDataSection { + pub metadata: Metadata, + pub npm_snapshot: Option, + pub remote_modules: RemoteModulesStore, + pub vfs_dir: VirtualDirectory, + pub vfs_files_data: &'static [u8], +} + +pub fn deserialize_binary_data_section( + data: &'static [u8], +) -> Result, AnyError> { + fn read_bytes_with_len(input: &[u8]) -> Result<(&[u8], &[u8]), AnyError> { + let (input, len) = read_u64(input)?; + let (input, data) = read_bytes(input, len as usize)?; + Ok((input, data)) + } + + fn read_magic_bytes(input: &[u8]) -> Result<(&[u8], bool), AnyError> { + if input.len() < MAGIC_BYTES.len() { + bail!("Unexpected end of data. Could not find magic bytes."); + } + let (magic_bytes, input) = input.split_at(MAGIC_BYTES.len()); + if magic_bytes != MAGIC_BYTES { + return Ok((input, false)); + } + Ok((input, true)) + } + + let (input, found) = read_magic_bytes(data)?; + if !found { + return Ok(None); + } + + // 1. Metadata + let (input, data) = read_bytes_with_len(input).context("reading metadata")?; + let metadata: Metadata = + serde_json::from_slice(data).context("deserializing metadata")?; + // 2. Npm snapshot + let (input, data) = + read_bytes_with_len(input).context("reading npm snapshot")?; + let npm_snapshot = if data.is_empty() { + None + } else { + Some(deserialize_npm_snapshot(data).context("deserializing npm snapshot")?) + }; + // 3. Remote modules + let (input, data) = + read_bytes_with_len(input).context("reading remote modules data")?; + let remote_modules = + RemoteModulesStore::build(data).context("deserializing remote modules")?; + // 4. VFS + let (input, data) = read_bytes_with_len(input).context("vfs")?; + let vfs_dir: VirtualDirectory = + serde_json::from_slice(data).context("deserializing vfs data")?; + let (input, vfs_files_data) = + read_bytes_with_len(input).context("reading vfs files data")?; + + // finally ensure we read the magic bytes at the end + let (_input, found) = read_magic_bytes(input)?; + if !found { + bail!("Could not find magic bytes at the end of the data."); + } + + Ok(Some(DeserializedDataSection { + metadata, + npm_snapshot, + remote_modules, + vfs_dir, + vfs_files_data, + })) +} + +#[derive(Default)] +pub struct RemoteModulesStoreBuilder { + specifiers: Vec<(String, u64)>, + data: Vec<(MediaType, Vec)>, + data_byte_len: u64, + redirects: Vec<(String, String)>, + redirects_len: u64, +} + +impl RemoteModulesStoreBuilder { + pub fn add(&mut self, specifier: &Url, media_type: MediaType, data: Vec) { + let specifier = specifier.to_string(); + self.specifiers.push((specifier, self.data_byte_len)); + self.data_byte_len += 1 + 8 + data.len() as u64; // media type (1 byte), data length (8 bytes), data + self.data.push((media_type, data)); + } + + pub fn add_redirects(&mut self, redirects: &BTreeMap) { + self.redirects.reserve(redirects.len()); + for (from, to) in redirects { + let from = from.to_string(); + let to = to.to_string(); + self.redirects_len += (4 + from.len() + 4 + to.len()) as u64; + self.redirects.push((from, to)); + } + } + + fn write(&self, writer: &mut dyn Write) -> Result<(), AnyError> { + writer.write_all(&(self.specifiers.len() as u32).to_le_bytes())?; + writer.write_all(&(self.redirects.len() as u32).to_le_bytes())?; + for (specifier, offset) in &self.specifiers { + writer.write_all(&(specifier.len() as u32).to_le_bytes())?; + writer.write_all(specifier.as_bytes())?; + writer.write_all(&offset.to_le_bytes())?; + } + for (from, to) in &self.redirects { + writer.write_all(&(from.len() as u32).to_le_bytes())?; + writer.write_all(from.as_bytes())?; + writer.write_all(&(to.len() as u32).to_le_bytes())?; + writer.write_all(to.as_bytes())?; + } + for (media_type, data) in &self.data { + writer.write_all(&[serialize_media_type(*media_type)])?; + writer.write_all(&(data.len() as u64).to_le_bytes())?; + writer.write_all(data)?; + } + Ok(()) + } +} + +pub struct DenoCompileModuleData<'a> { + pub specifier: &'a Url, + pub media_type: MediaType, + pub data: Cow<'static, [u8]>, +} + +impl<'a> DenoCompileModuleData<'a> { + pub fn into_for_v8(self) -> (&'a Url, ModuleType, ModuleSourceCode) { + fn into_bytes(data: Cow<'static, [u8]>) -> ModuleSourceCode { + ModuleSourceCode::Bytes(match data { + Cow::Borrowed(d) => d.into(), + Cow::Owned(d) => d.into_boxed_slice().into(), + }) + } + + fn into_string_unsafe(data: Cow<'static, [u8]>) -> ModuleSourceCode { + // todo(https://github.com/denoland/deno_core/pull/943): store whether + // the string is ascii or not ahead of time so we can avoid the is_ascii() + // check in FastString::from_static + match data { + Cow::Borrowed(d) => ModuleSourceCode::String( + // SAFETY: we know this is a valid utf8 string + unsafe { FastString::from_static(std::str::from_utf8_unchecked(d)) }, + ), + Cow::Owned(d) => ModuleSourceCode::Bytes(d.into_boxed_slice().into()), + } + } + + let (media_type, source) = match self.media_type { + MediaType::JavaScript + | MediaType::Jsx + | MediaType::Mjs + | MediaType::Cjs + | MediaType::TypeScript + | MediaType::Mts + | MediaType::Cts + | MediaType::Dts + | MediaType::Dmts + | MediaType::Dcts + | MediaType::Tsx => { + (ModuleType::JavaScript, into_string_unsafe(self.data)) + } + MediaType::Json => (ModuleType::Json, into_string_unsafe(self.data)), + MediaType::Wasm => (ModuleType::Wasm, into_bytes(self.data)), + // just assume javascript if we made it here + MediaType::TsBuildInfo | MediaType::SourceMap | MediaType::Unknown => { + (ModuleType::JavaScript, into_bytes(self.data)) + } + }; + (self.specifier, media_type, source) + } +} + +enum RemoteModulesStoreSpecifierValue { + Data(usize), + Redirect(Url), +} + +pub struct RemoteModulesStore { + specifiers: HashMap, + files_data: &'static [u8], +} + +impl RemoteModulesStore { + fn build(data: &'static [u8]) -> Result { + fn read_specifier(input: &[u8]) -> Result<(&[u8], (Url, u64)), AnyError> { + let (input, specifier) = read_string_lossy(input)?; + let specifier = Url::parse(&specifier)?; + let (input, offset) = read_u64(input)?; + Ok((input, (specifier, offset))) + } + + fn read_redirect(input: &[u8]) -> Result<(&[u8], (Url, Url)), AnyError> { + let (input, from) = read_string_lossy(input)?; + let from = Url::parse(&from)?; + let (input, to) = read_string_lossy(input)?; + let to = Url::parse(&to)?; + Ok((input, (from, to))) + } + + fn read_headers( + input: &[u8], + ) -> Result<(&[u8], HashMap), AnyError> + { + let (input, specifiers_len) = read_u32_as_usize(input)?; + let (mut input, redirects_len) = read_u32_as_usize(input)?; + let mut specifiers = + HashMap::with_capacity(specifiers_len + redirects_len); + for _ in 0..specifiers_len { + let (current_input, (specifier, offset)) = + read_specifier(input).context("reading specifier")?; + input = current_input; + specifiers.insert( + specifier, + RemoteModulesStoreSpecifierValue::Data(offset as usize), + ); + } + + for _ in 0..redirects_len { + let (current_input, (from, to)) = read_redirect(input)?; + input = current_input; + specifiers.insert(from, RemoteModulesStoreSpecifierValue::Redirect(to)); + } + + Ok((input, specifiers)) + } + + let (files_data, specifiers) = read_headers(data)?; + + Ok(Self { + specifiers, + files_data, + }) + } + + pub fn resolve_specifier<'a>( + &'a self, + specifier: &'a Url, + ) -> Result, AnyError> { + let mut count = 0; + let mut current = specifier; + loop { + if count > 10 { + bail!("Too many redirects resolving '{}'", specifier); + } + match self.specifiers.get(current) { + Some(RemoteModulesStoreSpecifierValue::Redirect(to)) => { + current = to; + count += 1; + } + Some(RemoteModulesStoreSpecifierValue::Data(_)) => { + return Ok(Some(current)); + } + None => { + return Ok(None); + } + } + } + } + + pub fn read<'a>( + &'a self, + specifier: &'a Url, + ) -> Result>, AnyError> { + let mut count = 0; + let mut current = specifier; + loop { + if count > 10 { + bail!("Too many redirects resolving '{}'", specifier); + } + match self.specifiers.get(current) { + Some(RemoteModulesStoreSpecifierValue::Redirect(to)) => { + current = to; + count += 1; + } + Some(RemoteModulesStoreSpecifierValue::Data(offset)) => { + let input = &self.files_data[*offset..]; + let (input, media_type_byte) = read_bytes(input, 1)?; + let media_type = deserialize_media_type(media_type_byte[0])?; + let (input, len) = read_u64(input)?; + let (_input, data) = read_bytes(input, len as usize)?; + return Ok(Some(DenoCompileModuleData { + specifier, + media_type, + data: Cow::Borrowed(data), + })); + } + None => { + return Ok(None); + } + } + } + } +} + +fn serialize_npm_snapshot( + mut snapshot: SerializedNpmResolutionSnapshot, +) -> Vec { + fn append_string(bytes: &mut Vec, string: &str) { + let len = string.len() as u32; + bytes.extend_from_slice(&len.to_le_bytes()); + bytes.extend_from_slice(string.as_bytes()); + } + + snapshot.packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism + let ids_to_stored_ids = snapshot + .packages + .iter() + .enumerate() + .map(|(i, pkg)| (&pkg.id, i as u32)) + .collect::>(); + + let mut root_packages: Vec<_> = snapshot.root_packages.iter().collect(); + root_packages.sort(); + let mut bytes = Vec::new(); + + bytes.extend_from_slice(&(snapshot.packages.len() as u32).to_le_bytes()); + for pkg in &snapshot.packages { + append_string(&mut bytes, &pkg.id.as_serialized()); + } + + bytes.extend_from_slice(&(root_packages.len() as u32).to_le_bytes()); + for (req, id) in root_packages { + append_string(&mut bytes, &req.to_string()); + let id = ids_to_stored_ids.get(&id).unwrap(); + bytes.extend_from_slice(&id.to_le_bytes()); + } + + for pkg in &snapshot.packages { + let deps_len = pkg.dependencies.len() as u32; + bytes.extend_from_slice(&deps_len.to_le_bytes()); + let mut deps: Vec<_> = pkg.dependencies.iter().collect(); + deps.sort(); + for (req, id) in deps { + append_string(&mut bytes, req); + let id = ids_to_stored_ids.get(&id).unwrap(); + bytes.extend_from_slice(&id.to_le_bytes()); + } + } + + bytes +} + +fn deserialize_npm_snapshot( + input: &[u8], +) -> Result { + fn parse_id(input: &[u8]) -> Result<(&[u8], NpmPackageId), AnyError> { + let (input, id) = read_string_lossy(input)?; + let id = NpmPackageId::from_serialized(&id)?; + Ok((input, id)) + } + + #[allow(clippy::needless_lifetimes)] // clippy bug + fn parse_root_package<'a>( + id_to_npm_id: &'a impl Fn(usize) -> Result, + ) -> impl Fn(&[u8]) -> Result<(&[u8], (PackageReq, NpmPackageId)), AnyError> + 'a + { + |input| { + let (input, req) = read_string_lossy(input)?; + let req = PackageReq::from_str(&req)?; + let (input, id) = read_u32_as_usize(input)?; + Ok((input, (req, id_to_npm_id(id)?))) + } + } + + #[allow(clippy::needless_lifetimes)] // clippy bug + fn parse_package_dep<'a>( + id_to_npm_id: &'a impl Fn(usize) -> Result, + ) -> impl Fn(&[u8]) -> Result<(&[u8], (String, NpmPackageId)), AnyError> + 'a + { + |input| { + let (input, req) = read_string_lossy(input)?; + let (input, id) = read_u32_as_usize(input)?; + Ok((input, (req.into_owned(), id_to_npm_id(id)?))) + } + } + + fn parse_package<'a>( + input: &'a [u8], + id: NpmPackageId, + id_to_npm_id: &impl Fn(usize) -> Result, + ) -> Result<(&'a [u8], SerializedNpmResolutionSnapshotPackage), AnyError> { + let (input, deps_len) = read_u32_as_usize(input)?; + let (input, dependencies) = + parse_hashmap_n_times(input, deps_len, parse_package_dep(id_to_npm_id))?; + Ok(( + input, + SerializedNpmResolutionSnapshotPackage { + id, + system: Default::default(), + dist: Default::default(), + dependencies, + optional_dependencies: Default::default(), + bin: None, + scripts: Default::default(), + deprecated: Default::default(), + }, + )) + } + + let (input, packages_len) = read_u32_as_usize(input)?; + + // get a hashmap of all the npm package ids to their serialized ids + let (input, data_ids_to_npm_ids) = + parse_vec_n_times(input, packages_len, parse_id) + .context("deserializing id")?; + let data_id_to_npm_id = |id: usize| { + data_ids_to_npm_ids + .get(id) + .cloned() + .ok_or_else(|| deno_core::anyhow::anyhow!("Invalid npm package id")) + }; + + let (input, root_packages_len) = read_u32_as_usize(input)?; + let (input, root_packages) = parse_hashmap_n_times( + input, + root_packages_len, + parse_root_package(&data_id_to_npm_id), + ) + .context("deserializing root package")?; + let (input, packages) = + parse_vec_n_times_with_index(input, packages_len, |input, index| { + parse_package(input, data_id_to_npm_id(index)?, &data_id_to_npm_id) + }) + .context("deserializing package")?; + + if !input.is_empty() { + bail!("Unexpected data left over"); + } + + Ok( + SerializedNpmResolutionSnapshot { + packages, + root_packages, + } + // this is ok because we have already verified that all the + // identifiers found in the snapshot are valid via the + // npm package id -> npm package id mapping + .into_valid_unsafe(), + ) +} + +fn serialize_media_type(media_type: MediaType) -> u8 { + match media_type { + MediaType::JavaScript => 0, + MediaType::Jsx => 1, + MediaType::Mjs => 2, + MediaType::Cjs => 3, + MediaType::TypeScript => 4, + MediaType::Mts => 5, + MediaType::Cts => 6, + MediaType::Dts => 7, + MediaType::Dmts => 8, + MediaType::Dcts => 9, + MediaType::Tsx => 10, + MediaType::Json => 11, + MediaType::Wasm => 12, + MediaType::TsBuildInfo => 13, + MediaType::SourceMap => 14, + MediaType::Unknown => 15, + } +} + +fn deserialize_media_type(value: u8) -> Result { + match value { + 0 => Ok(MediaType::JavaScript), + 1 => Ok(MediaType::Jsx), + 2 => Ok(MediaType::Mjs), + 3 => Ok(MediaType::Cjs), + 4 => Ok(MediaType::TypeScript), + 5 => Ok(MediaType::Mts), + 6 => Ok(MediaType::Cts), + 7 => Ok(MediaType::Dts), + 8 => Ok(MediaType::Dmts), + 9 => Ok(MediaType::Dcts), + 10 => Ok(MediaType::Tsx), + 11 => Ok(MediaType::Json), + 12 => Ok(MediaType::Wasm), + 13 => Ok(MediaType::TsBuildInfo), + 14 => Ok(MediaType::SourceMap), + 15 => Ok(MediaType::Unknown), + _ => bail!("Unknown media type value: {}", value), + } +} + +fn parse_hashmap_n_times( + mut input: &[u8], + times: usize, + parse: impl Fn(&[u8]) -> Result<(&[u8], (TKey, TValue)), AnyError>, +) -> Result<(&[u8], HashMap), AnyError> { + let mut results = HashMap::with_capacity(times); + for _ in 0..times { + let result = parse(input); + let (new_input, (key, value)) = result?; + results.insert(key, value); + input = new_input; + } + Ok((input, results)) +} + +fn parse_vec_n_times( + input: &[u8], + times: usize, + parse: impl Fn(&[u8]) -> Result<(&[u8], TResult), AnyError>, +) -> Result<(&[u8], Vec), AnyError> { + parse_vec_n_times_with_index(input, times, |input, _index| parse(input)) +} + +fn parse_vec_n_times_with_index( + mut input: &[u8], + times: usize, + parse: impl Fn(&[u8], usize) -> Result<(&[u8], TResult), AnyError>, +) -> Result<(&[u8], Vec), AnyError> { + let mut results = Vec::with_capacity(times); + for i in 0..times { + let result = parse(input, i); + let (new_input, result) = result?; + results.push(result); + input = new_input; + } + Ok((input, results)) +} + +fn read_bytes(input: &[u8], len: usize) -> Result<(&[u8], &[u8]), AnyError> { + if input.len() < len { + bail!("Unexpected end of data.",); + } + let (len_bytes, input) = input.split_at(len); + Ok((input, len_bytes)) +} + +fn read_string_lossy(input: &[u8]) -> Result<(&[u8], Cow), AnyError> { + let (input, str_len) = read_u32_as_usize(input)?; + let (input, data_bytes) = read_bytes(input, str_len)?; + Ok((input, String::from_utf8_lossy(data_bytes))) +} + +fn read_u32_as_usize(input: &[u8]) -> Result<(&[u8], usize), AnyError> { + let (input, len_bytes) = read_bytes(input, 4)?; + let len = u32::from_le_bytes(len_bytes.try_into()?); + Ok((input, len as usize)) +} + +fn read_u64(input: &[u8]) -> Result<(&[u8], u64), AnyError> { + let (input, len_bytes) = read_bytes(input, 8)?; + let len = u64::from_le_bytes(len_bytes.try_into()?); + Ok((input, len)) +} diff --git a/cli/standalone/virtual_fs.rs b/cli/standalone/virtual_fs.rs index 53d045b625..0ae00accbf 100644 --- a/cli/standalone/virtual_fs.rs +++ b/cli/standalone/virtual_fs.rs @@ -7,6 +7,7 @@ use std::fs::File; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; +use std::ops::Range; use std::path::Path; use std::path::PathBuf; use std::rc::Rc; @@ -67,6 +68,26 @@ impl VfsBuilder { }) } + pub fn set_new_root_path( + &mut self, + root_path: PathBuf, + ) -> Result<(), AnyError> { + let root_path = canonicalize_path(&root_path)?; + self.root_path = root_path; + self.root_dir = VirtualDirectory { + name: self + .root_path + .file_stem() + .map(|s| s.to_string_lossy().into_owned()) + .unwrap_or("root".to_string()), + entries: vec![VfsEntry::Dir(VirtualDirectory { + name: std::mem::take(&mut self.root_dir.name), + entries: std::mem::take(&mut self.root_dir.entries), + })], + }; + Ok(()) + } + pub fn with_root_dir( &mut self, with_root: impl FnOnce(&mut VirtualDirectory) -> R, @@ -119,7 +140,7 @@ impl VfsBuilder { // inline the symlink and make the target file let file_bytes = std::fs::read(&target) .with_context(|| format!("Reading {}", path.display()))?; - self.add_file(&path, file_bytes)?; + self.add_file_with_data_inner(&path, file_bytes)?; } else { log::warn!( "{} Symlink target is outside '{}'. Excluding symlink at '{}' with target '{}'.", @@ -191,16 +212,32 @@ impl VfsBuilder { self.add_file_at_path_not_symlink(&target_path) } - pub fn add_file_at_path_not_symlink( + fn add_file_at_path_not_symlink( &mut self, path: &Path, ) -> Result<(), AnyError> { let file_bytes = std::fs::read(path) .with_context(|| format!("Reading {}", path.display()))?; - self.add_file(path, file_bytes) + self.add_file_with_data_inner(path, file_bytes) } - fn add_file(&mut self, path: &Path, data: Vec) -> Result<(), AnyError> { + pub fn add_file_with_data( + &mut self, + path: &Path, + data: Vec, + ) -> Result<(), AnyError> { + let target_path = canonicalize_path(path)?; + if target_path != path { + self.add_symlink(path, &target_path)?; + } + self.add_file_with_data_inner(&target_path, data) + } + + fn add_file_with_data_inner( + &mut self, + path: &Path, + data: Vec, + ) -> Result<(), AnyError> { log::debug!("Adding file '{}'", path.display()); let checksum = util::checksum::gen(&[&data]); let offset = if let Some(offset) = self.file_offsets.get(&checksum) { @@ -249,8 +286,15 @@ impl VfsBuilder { path.display(), target.display() ); - let dest = self.path_relative_root(target)?; - if dest == self.path_relative_root(path)? { + let relative_target = self.path_relative_root(target)?; + let relative_path = match self.path_relative_root(path) { + Ok(path) => path, + Err(StripRootError { .. }) => { + // ignore if the original path is outside the root directory + return Ok(()); + } + }; + if relative_target == relative_path { // it's the same, ignore return Ok(()); } @@ -263,7 +307,7 @@ impl VfsBuilder { insert_index, VfsEntry::Symlink(VirtualSymlink { name: name.to_string(), - dest_parts: dest + dest_parts: relative_target .components() .map(|c| c.as_os_str().to_string_lossy().to_string()) .collect::>(), @@ -751,14 +795,14 @@ impl deno_io::fs::File for FileBackedVfsFile { #[derive(Debug)] pub struct FileBackedVfs { - file: Mutex>, + vfs_data: Cow<'static, [u8]>, fs_root: VfsRoot, } impl FileBackedVfs { - pub fn new(file: Vec, fs_root: VfsRoot) -> Self { + pub fn new(data: Cow<'static, [u8]>, fs_root: VfsRoot) -> Self { Self { - file: Mutex::new(file), + vfs_data: data, fs_root, } } @@ -827,10 +871,15 @@ impl FileBackedVfs { Ok(path) } - pub fn read_file_all(&self, file: &VirtualFile) -> std::io::Result> { - let mut buf = vec![0; file.len as usize]; - self.read_file(file, 0, &mut buf)?; - Ok(buf) + pub fn read_file_all( + &self, + file: &VirtualFile, + ) -> std::io::Result> { + let read_range = self.get_read_range(file, 0, file.len)?; + match &self.vfs_data { + Cow::Borrowed(data) => Ok(Cow::Borrowed(&data[read_range])), + Cow::Owned(data) => Ok(Cow::Owned(data[read_range].to_vec())), + } } pub fn read_file( @@ -839,18 +888,27 @@ impl FileBackedVfs { pos: u64, buf: &mut [u8], ) -> std::io::Result { - let data = self.file.lock(); + let read_range = self.get_read_range(file, pos, buf.len() as u64)?; + buf.copy_from_slice(&self.vfs_data[read_range]); + Ok(buf.len()) + } + + fn get_read_range( + &self, + file: &VirtualFile, + pos: u64, + len: u64, + ) -> std::io::Result> { + let data = &self.vfs_data; let start = self.fs_root.start_file_offset + file.offset + pos; - let end = start + buf.len() as u64; + let end = start + len; if end > data.len() as u64 { return Err(std::io::Error::new( std::io::ErrorKind::UnexpectedEof, "unexpected EOF", )); } - - buf.copy_from_slice(&data[start as usize..end as usize]); - Ok(buf.len()) + Ok(start as usize..end as usize) } pub fn dir_entry(&self, path: &Path) -> std::io::Result<&VirtualDirectory> { @@ -888,7 +946,7 @@ mod test { #[track_caller] fn read_file(vfs: &FileBackedVfs, path: &Path) -> String { let file = vfs.file_entry(path).unwrap(); - String::from_utf8(vfs.read_file_all(file).unwrap()).unwrap() + String::from_utf8(vfs.read_file_all(file).unwrap().into_owned()).unwrap() } #[test] @@ -901,20 +959,23 @@ mod test { let src_path = src_path.to_path_buf(); let mut builder = VfsBuilder::new(src_path.clone()).unwrap(); builder - .add_file(&src_path.join("a.txt"), "data".into()) + .add_file_with_data_inner(&src_path.join("a.txt"), "data".into()) .unwrap(); builder - .add_file(&src_path.join("b.txt"), "data".into()) + .add_file_with_data_inner(&src_path.join("b.txt"), "data".into()) .unwrap(); assert_eq!(builder.files.len(), 1); // because duplicate data builder - .add_file(&src_path.join("c.txt"), "c".into()) + .add_file_with_data_inner(&src_path.join("c.txt"), "c".into()) .unwrap(); builder - .add_file(&src_path.join("sub_dir").join("d.txt"), "d".into()) + .add_file_with_data_inner( + &src_path.join("sub_dir").join("d.txt"), + "d".into(), + ) .unwrap(); builder - .add_file(&src_path.join("e.txt"), "e".into()) + .add_file_with_data_inner(&src_path.join("e.txt"), "e".into()) .unwrap(); builder .add_symlink( @@ -1031,7 +1092,7 @@ mod test { ( dest_path.to_path_buf(), FileBackedVfs::new( - data, + Cow::Owned(data), VfsRoot { dir: root_dir, root_path: dest_path.to_path_buf(), @@ -1082,7 +1143,7 @@ mod test { let temp_path = temp_dir.path().canonicalize(); let mut builder = VfsBuilder::new(temp_path.to_path_buf()).unwrap(); builder - .add_file( + .add_file_with_data_inner( temp_path.join("a.txt").as_path(), "0123456789".to_string().into_bytes(), ) diff --git a/cli/task_runner.rs b/cli/task_runner.rs index e8937590db..418043b23f 100644 --- a/cli/task_runner.rs +++ b/cli/task_runner.rs @@ -16,8 +16,11 @@ use deno_task_shell::ExecutableCommand; use deno_task_shell::ExecuteResult; use deno_task_shell::ShellCommand; use deno_task_shell::ShellCommandContext; +use deno_task_shell::ShellPipeReader; +use deno_task_shell::ShellPipeWriter; use lazy_regex::Lazy; use regex::Regex; +use tokio::task::JoinHandle; use tokio::task::LocalSet; use crate::npm::CliNpmResolver; @@ -36,6 +39,35 @@ pub fn get_script_with_args(script: &str, argv: &[String]) -> String { script.trim().to_owned() } +pub struct TaskStdio(Option, ShellPipeWriter); + +impl TaskStdio { + pub fn stdout() -> Self { + Self(None, ShellPipeWriter::stdout()) + } + pub fn stderr() -> Self { + Self(None, ShellPipeWriter::stderr()) + } + pub fn piped() -> Self { + let (r, w) = deno_task_shell::pipe(); + Self(Some(r), w) + } +} + +pub struct TaskIo { + pub stdout: TaskStdio, + pub stderr: TaskStdio, +} + +impl Default for TaskIo { + fn default() -> Self { + Self { + stderr: TaskStdio::stderr(), + stdout: TaskStdio::stdout(), + } + } +} + pub struct RunTaskOptions<'a> { pub task_name: &'a str, pub script: &'a str, @@ -45,24 +77,69 @@ pub struct RunTaskOptions<'a> { pub argv: &'a [String], pub custom_commands: HashMap>, pub root_node_modules_dir: Option<&'a Path>, + pub stdio: Option, } pub type TaskCustomCommands = HashMap>; -pub async fn run_task(opts: RunTaskOptions<'_>) -> Result { +pub struct TaskResult { + pub exit_code: i32, + pub stdout: Option>, + pub stderr: Option>, +} + +pub async fn run_task( + opts: RunTaskOptions<'_>, +) -> Result { let script = get_script_with_args(opts.script, opts.argv); let seq_list = deno_task_shell::parser::parse(&script) .with_context(|| format!("Error parsing script '{}'.", opts.task_name))?; let env_vars = prepare_env_vars(opts.env_vars, opts.init_cwd, opts.root_node_modules_dir); + let state = + deno_task_shell::ShellState::new(env_vars, opts.cwd, opts.custom_commands); + let stdio = opts.stdio.unwrap_or_default(); + let ( + TaskStdio(stdout_read, stdout_write), + TaskStdio(stderr_read, stderr_write), + ) = (stdio.stdout, stdio.stderr); + + fn read(reader: ShellPipeReader) -> JoinHandle, AnyError>> { + tokio::task::spawn_blocking(move || { + let mut buf = Vec::new(); + reader.pipe_to(&mut buf)?; + Ok(buf) + }) + } + + let stdout = stdout_read.map(read); + let stderr = stderr_read.map(read); + let local = LocalSet::new(); - let future = deno_task_shell::execute( - seq_list, - env_vars, - opts.cwd, - opts.custom_commands, - ); - Ok(local.run_until(future).await) + let future = async move { + let exit_code = deno_task_shell::execute_with_pipes( + seq_list, + state, + ShellPipeReader::stdin(), + stdout_write, + stderr_write, + ) + .await; + Ok::<_, AnyError>(TaskResult { + exit_code, + stdout: if let Some(stdout) = stdout { + Some(stdout.await??) + } else { + None + }, + stderr: if let Some(stderr) = stderr { + Some(stderr.await??) + } else { + None + }, + }) + }; + local.run_until(future).await } fn prepare_env_vars( @@ -213,8 +290,8 @@ impl ShellCommand for NodeGypCommand { ) -> LocalBoxFuture<'static, ExecuteResult> { // at the moment this shell command is just to give a warning if node-gyp is not found // in the future, we could try to run/install node-gyp for the user with deno - if which::which("node-gyp").is_err() { - log::warn!("{}: node-gyp was used in a script, but was not listed as a dependency. Either add it as a dependency or install it globally (e.g. `npm install -g node-gyp`)", crate::colors::yellow("warning")); + if context.state.resolve_command_path("node-gyp").is_err() { + log::warn!("{} node-gyp was used in a script, but was not listed as a dependency. Either add it as a dependency or install it globally (e.g. `npm install -g node-gyp`)", crate::colors::yellow("Warning")); } ExecutableCommand::new( "node-gyp".to_string(), diff --git a/cli/tools/bench/mitata.rs b/cli/tools/bench/mitata.rs index 64c5d5f69a..e43ee30fa9 100644 --- a/cli/tools/bench/mitata.rs +++ b/cli/tools/bench/mitata.rs @@ -7,10 +7,21 @@ // 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 crate::colors; -use std::str::FromStr; + +/// Taken from https://stackoverflow.com/a/76572321 +fn precision_f64(x: f64, decimals: u32) -> f64 { + if x == 0. || decimals == 0 { + 0. + } else { + let shift = decimals as i32 - x.abs().log10().ceil() as i32; + let shift_factor = 10_f64.powi(shift); + + (x * shift_factor).round() / shift_factor + } +} fn avg_to_iter_per_s(time: f64) -> String { - let iter_per_s = 1e9 / time; + let iter_per_s = precision_f64(1e9 / time, 4); let (decimals, fractional) = into_decimal_and_fractional_parts(iter_per_s); human_readable_decimal_with_fractional(decimals, fractional) } @@ -47,55 +58,34 @@ fn human_readable_decimal_with_fractional( .unwrap() .join(","); - format!("{}.{}", fmt_decimal, fractional) + if fmt_decimal.len() >= 4 { + fmt_decimal + } else { + format!("{}.{}", fmt_decimal, fractional) + } } pub fn fmt_duration(time: f64) -> String { - // SAFETY: this is safe since its just reformatting numbers - unsafe { - if time < 1e0 { - return format!( - "{} ps", - f64::from_str(&format!("{:.2}", time * 1e3)).unwrap_unchecked() - ); - } - - if time < 1e3 { - return format!( - "{} ns", - f64::from_str(&format!("{:.2}", time)).unwrap_unchecked() - ); - } - if time < 1e6 { - return format!( - "{} µs", - f64::from_str(&format!("{:.2}", time / 1e3)).unwrap_unchecked() - ); - } - if time < 1e9 { - return format!( - "{} ms", - f64::from_str(&format!("{:.2}", time / 1e6)).unwrap_unchecked() - ); - } - if time < 1e12 { - return format!( - "{} s", - f64::from_str(&format!("{:.2}", time / 1e9)).unwrap_unchecked() - ); - } - if time < 36e11 { - return format!( - "{} m", - f64::from_str(&format!("{:.2}", time / 60e9)).unwrap_unchecked() - ); - } - - format!( - "{} h", - f64::from_str(&format!("{:.2}", time / 36e11)).unwrap_unchecked() - ) + if time < 1e0 { + return format!("{:.1} ps", time * 1e3); } + if time < 1e3 { + return format!("{:.1} ns", time); + } + if time < 1e6 { + return format!("{:.1} µs", time / 1e3); + } + if time < 1e9 { + return format!("{:.1} ms", time / 1e6); + } + if time < 1e12 { + return format!("{:.1} s", time / 1e9); + } + if time < 36e11 { + return format!("{:.1} m", time / 60e9); + } + + format!("{:.1} h", time / 36e11) } pub mod cpu { @@ -231,16 +221,19 @@ pub mod reporter { pub fn br(options: &Options) -> String { let mut s = String::new(); - s.push_str(&"-".repeat( - options.size - + 14 * options.avg as usize - + 14 * options.avg as usize - + 24 * options.min_max as usize, - )); + s.push_str(&"-".repeat(options.size)); + if options.avg { + s.push(' '); + s.push_str(&"-".repeat(15 + 1 + 13)); + } + if options.min_max { + s.push(' '); + s.push_str(&"-".repeat(21)); + } if options.percentiles { s.push(' '); - s.push_str(&"-".repeat(9 + 10 + 10)); + s.push_str(&"-".repeat(8 + 1 + 8 + 1 + 8)); } s @@ -251,7 +244,7 @@ pub mod reporter { let mut s = String::new(); s.push_str(&format!("{:14}", "time (avg)")); - s.push_str(&format!("{:>14}", "iter/s")); + s.push_str(&format!(" {:<15}", "time/iter (avg)")); + s.push_str(&format!(" {:>13}", "iter/s")); } if options.min_max { - s.push_str(&format!("{:>24}", "(min … max)")); + s.push_str(&format!(" {:^21}", "(min … max)")); } if options.percentiles { - s.push_str(&format!(" {:>9} {:>9} {:>9}", "p75", "p99", "p995")); + s.push_str(&format!(" {:>8} {:>8} {:>8}", "p75", "p99", "p995")); } s @@ -293,28 +286,28 @@ pub mod reporter { if options.avg { s.push_str(&format!( - "{:>30}", - format!("{}/iter", colors::yellow(fmt_duration(stats.avg))) + " {}", + colors::yellow(&format!("{:>15}", fmt_duration(stats.avg))) )); - s.push_str(&format!("{:>14}", avg_to_iter_per_s(stats.avg))); + s.push_str(&format!(" {:>13}", &avg_to_iter_per_s(stats.avg))); } if options.min_max { s.push_str(&format!( - "{:>50}", - format!( - "({} … {})", - colors::cyan(fmt_duration(stats.min)), - colors::magenta(fmt_duration(stats.max)) - ) + " ({} … {})", + colors::cyan(format!("{:>8}", fmt_duration(stats.min))), + colors::magenta(format!("{:>8}", fmt_duration(stats.max))) )); } if options.percentiles { - s.push_str(&format!( - " {:>22} {:>22} {:>22}", - colors::magenta(fmt_duration(stats.p75)), - colors::magenta(fmt_duration(stats.p99)), - colors::magenta(fmt_duration(stats.p995)) - )); + s.push_str( + &colors::magenta(format!( + " {:>8} {:>8} {:>8}", + fmt_duration(stats.p75), + fmt_duration(stats.p99), + fmt_duration(stats.p995) + )) + .to_string(), + ); } s @@ -337,22 +330,25 @@ pub mod reporter { for b in benchmarks.iter().filter(|b| *b != baseline) { let faster = b.stats.avg >= baseline.stats.avg; - let diff = f64::from_str(&format!( - "{:.2}", - 1.0 / baseline.stats.avg * b.stats.avg - )) - .unwrap(); - let inv_diff = f64::from_str(&format!( - "{:.2}", - 1.0 / b.stats.avg * baseline.stats.avg - )) - .unwrap(); - s.push_str(&format!( - "\n {}x {} than {}", + let x_faster = precision_f64( if faster { - colors::green(diff.to_string()).to_string() + b.stats.avg / baseline.stats.avg } else { - colors::red(inv_diff.to_string()).to_string() + baseline.stats.avg / b.stats.avg + }, + 4, + ); + let diff = if x_faster > 1000. { + &format!("{:>9.0}", x_faster) + } else { + &format!("{:>9.2}", x_faster) + }; + s.push_str(&format!( + "\n{}x {} than {}", + if faster { + colors::green(diff) + } else { + colors::red(diff) }, if faster { "faster" } else { "slower" }, colors::cyan_bold(&b.name) @@ -384,9 +380,10 @@ mod tests { #[test] fn test_avg_to_iter_per_s() { - assert_eq!(avg_to_iter_per_s(55.85), "17,905,103.0"); + assert_eq!(avg_to_iter_per_s(55.85), "17,910,000"); assert_eq!(avg_to_iter_per_s(64_870_000.0), "15.4"); assert_eq!(avg_to_iter_per_s(104_370_000.0), "9.6"); + assert_eq!(avg_to_iter_per_s(640_000.0), "1,563"); assert_eq!(avg_to_iter_per_s(6_400_000.0), "156.3"); assert_eq!(avg_to_iter_per_s(46_890_000.0), "21.3"); assert_eq!(avg_to_iter_per_s(100_000_000.0), "10.0"); diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index 44ae8321d2..be5d0ad0e1 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -30,6 +30,7 @@ use deno_core::ModuleSpecifier; use deno_core::PollEventLoopOptions; use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::WorkerExecutionMode; use indexmap::IndexMap; @@ -144,14 +145,14 @@ fn create_reporter( /// Run a single specifier as an executable bench module. async fn bench_specifier( worker_factory: Arc, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, sender: UnboundedSender, filter: TestFilter, ) -> Result<(), AnyError> { match bench_specifier_inner( worker_factory, - permissions, + permissions_container, specifier.clone(), &sender, filter, @@ -176,7 +177,7 @@ async fn bench_specifier( /// Run a single specifier as an executable bench module. async fn bench_specifier_inner( worker_factory: Arc, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, sender: &UnboundedSender, filter: TestFilter, @@ -185,7 +186,7 @@ async fn bench_specifier_inner( .create_custom_worker( WorkerExecutionMode::Bench, specifier.clone(), - PermissionsContainer::new(permissions), + permissions_container, vec![ops::bench::deno_bench::init_ops(sender.clone())], Default::default(), ) @@ -264,6 +265,7 @@ async fn bench_specifier_inner( async fn bench_specifiers( worker_factory: Arc, permissions: &Permissions, + permissions_desc_parser: &Arc, specifiers: Vec, options: BenchSpecifierOptions, ) -> Result<(), AnyError> { @@ -273,13 +275,16 @@ async fn bench_specifiers( let join_handles = specifiers.into_iter().map(move |specifier| { let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permissions_desc_parser.clone(), + permissions.clone(), + ); let sender = sender.clone(); let options = option_for_handles.clone(); spawn_blocking(move || { let future = bench_specifier( worker_factory, - permissions, + permissions_container, specifier, sender, options.filter, @@ -410,8 +415,11 @@ pub async fn run_benchmarks( // Various bench files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let members_with_bench_options = cli_options.resolve_bench_options_for_members(&bench_flags)?; @@ -434,7 +442,9 @@ pub async fn run_benchmarks( } let main_graph_container = factory.main_module_graph_container().await?; - main_graph_container.check_specifiers(&specifiers).await?; + main_graph_container + .check_specifiers(&specifiers, cli_options.ext_flag().as_ref()) + .await?; if workspace_bench_options.no_run { return Ok(()); @@ -446,6 +456,7 @@ pub async fn run_benchmarks( bench_specifiers( worker_factory, &permissions, + &permission_desc_parser, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), @@ -519,8 +530,11 @@ pub async fn run_benchmarks_with_watch( // Various bench files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let graph = module_graph_creator .create_graph(graph_kind, collected_bench_modules.clone()) @@ -557,7 +571,7 @@ pub async fn run_benchmarks_with_watch( factory .main_module_graph_container() .await? - .check_specifiers(&specifiers) + .check_specifiers(&specifiers, cli_options.ext_flag().as_ref()) .await?; if workspace_bench_options.no_run { @@ -568,6 +582,7 @@ pub async fn run_benchmarks_with_watch( bench_specifiers( worker_factory, &permissions, + &permission_desc_parser, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), diff --git a/cli/tools/bench/reporters.rs b/cli/tools/bench/reporters.rs index 3f244ed621..9aabd760b3 100644 --- a/cli/tools/bench/reporters.rs +++ b/cli/tools/bench/reporters.rs @@ -18,8 +18,11 @@ pub trait BenchReporter { fn report_uncaught_error(&mut self, origin: &str, error: Box); } +const JSON_SCHEMA_VERSION: u8 = 1; + #[derive(Debug, Serialize)] struct JsonReporterOutput { + version: u8, runtime: String, cpu: String, benches: Vec, @@ -28,6 +31,7 @@ struct JsonReporterOutput { impl Default for JsonReporterOutput { fn default() -> Self { Self { + version: JSON_SCHEMA_VERSION, runtime: format!( "{} {}", version::DENO_VERSION_INFO.user_agent, @@ -152,11 +156,14 @@ impl BenchReporter for ConsoleReporter { .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst) .is_ok() { - println!("{}", colors::gray(format!("cpu: {}", mitata::cpu::name()))); + println!( + "{}", + colors::gray(format!(" CPU | {}", mitata::cpu::name())) + ); println!( "{}\n", colors::gray(format!( - "runtime: deno {} ({})", + "Runtime | Deno {} ({})", crate::version::DENO_VERSION_INFO.deno, env!("TARGET") )) @@ -166,7 +173,7 @@ impl BenchReporter for ConsoleReporter { } println!( - "{}\n{}\n{}", + "{}\n\n{}\n{}", colors::gray(&plan.origin), mitata::reporter::header(options), mitata::reporter::br(options) diff --git a/cli/tools/bundle.rs b/cli/tools/bundle.rs deleted file mode 100644 index f2157ecd8c..0000000000 --- a/cli/tools/bundle.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::path::PathBuf; -use std::sync::Arc; - -use deno_core::error::AnyError; -use deno_graph::Module; -use deno_terminal::colors; - -use crate::args::BundleFlags; -use crate::args::CliOptions; -use crate::args::Flags; -use crate::args::TsConfigType; -use crate::factory::CliFactory; -use crate::graph_util::error_for_any_npm_specifier; -use crate::util; -use crate::util::display; - -pub async fn bundle( - flags: Arc, - bundle_flags: BundleFlags, -) -> Result<(), AnyError> { - log::info!( - "{}", - colors::yellow("⚠️ Warning: `deno bundle` is deprecated and will be removed in Deno 2.0.\nUse an alternative bundler like \"deno_emit\", \"esbuild\" or \"rollup\" instead."), - ); - - if let Some(watch_flags) = &bundle_flags.watch { - util::file_watcher::watch_func( - flags, - util::file_watcher::PrintConfig::new( - "Bundle", - !watch_flags.no_clear_screen, - ), - move |flags, watcher_communicator, _changed_paths| { - let bundle_flags = bundle_flags.clone(); - Ok(async move { - let factory = CliFactory::from_flags_for_watcher( - flags, - watcher_communicator.clone(), - ); - let cli_options = factory.cli_options()?; - let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); - bundle_action(factory, &bundle_flags).await?; - - Ok(()) - }) - }, - ) - .await?; - } else { - let factory = CliFactory::from_flags(flags); - bundle_action(factory, &bundle_flags).await?; - } - - Ok(()) -} - -async fn bundle_action( - factory: CliFactory, - bundle_flags: &BundleFlags, -) -> Result<(), AnyError> { - let cli_options = factory.cli_options()?; - let module_specifier = cli_options.resolve_main_module()?; - log::debug!(">>>>> bundle START"); - let module_graph_creator = factory.module_graph_creator().await?; - let cli_options = factory.cli_options()?; - - let graph = module_graph_creator - .create_graph_and_maybe_check(vec![module_specifier.clone()]) - .await?; - - let mut paths_to_watch: Vec = graph - .specifiers() - .filter_map(|(_, r)| { - r.ok().and_then(|module| match module { - Module::Js(m) => m.specifier.to_file_path().ok(), - Module::Json(m) => m.specifier.to_file_path().ok(), - // nothing to watch - Module::Node(_) | Module::Npm(_) | Module::External(_) => None, - }) - }) - .collect(); - - if let Ok(Some(import_map_path)) = cli_options - .resolve_specified_import_map_specifier() - .map(|ms| ms.and_then(|ref s| s.to_file_path().ok())) - { - paths_to_watch.push(import_map_path); - } - - // at the moment, we don't support npm specifiers in deno bundle, so show an error - error_for_any_npm_specifier(&graph)?; - - let bundle_output = bundle_module_graph(graph.as_ref(), cli_options)?; - log::debug!(">>>>> bundle END"); - let out_file = &bundle_flags.out_file; - - if let Some(out_file) = out_file { - let out_file = cli_options.initial_cwd().join(out_file); - let output_bytes = bundle_output.code.as_bytes(); - let output_len = output_bytes.len(); - util::fs::write_file(&out_file, output_bytes, 0o644)?; - log::info!( - "{} {:?} ({})", - colors::green("Emit"), - out_file, - colors::gray(display::human_size(output_len as f64)) - ); - if let Some(bundle_map) = bundle_output.maybe_map { - let map_bytes = bundle_map.as_bytes(); - let map_len = map_bytes.len(); - let ext = if let Some(curr_ext) = out_file.extension() { - format!("{}.map", curr_ext.to_string_lossy()) - } else { - "map".to_string() - }; - let map_out_file = out_file.with_extension(ext); - util::fs::write_file(&map_out_file, map_bytes, 0o644)?; - log::info!( - "{} {:?} ({})", - colors::green("Emit"), - map_out_file, - colors::gray(display::human_size(map_len as f64)) - ); - } - } else { - #[allow(clippy::print_stdout)] - { - println!("{}", bundle_output.code); - } - } - Ok(()) -} - -fn bundle_module_graph( - graph: &deno_graph::ModuleGraph, - cli_options: &CliOptions, -) -> Result { - log::info!("{} {}", colors::green("Bundle"), graph.roots[0]); - - let ts_config_result = - cli_options.resolve_ts_config_for_emit(TsConfigType::Bundle)?; - if !cli_options.type_check_mode().is_true() { - if let Some(ignored_options) = ts_config_result.maybe_ignored_options { - log::warn!("{}", ignored_options); - } - } - - let (transpile_options, emit_options) = - crate::args::ts_config_to_transpile_and_emit_options( - ts_config_result.ts_config, - )?; - deno_emit::bundle_graph( - graph, - deno_emit::BundleOptions { - minify: false, - bundle_type: deno_emit::BundleType::Module, - emit_options, - emit_ignore_directives: true, - transpile_options, - }, - ) -} diff --git a/cli/tools/check.rs b/cli/tools/check.rs index 4ec677f8f3..7edb392d48 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -14,7 +14,10 @@ use deno_terminal::colors; use once_cell::sync::Lazy; use regex::Regex; +use crate::args::check_warn_tsconfig; +use crate::args::CheckFlags; use crate::args::CliOptions; +use crate::args::Flags; use crate::args::TsConfig; use crate::args::TsConfigType; use crate::args::TsTypeLib; @@ -23,13 +26,58 @@ use crate::cache::CacheDBHash; use crate::cache::Caches; use crate::cache::FastInsecureHasher; use crate::cache::TypeCheckCache; +use crate::factory::CliFactory; use crate::graph_util::BuildFastCheckGraphOptions; use crate::graph_util::ModuleGraphBuilder; use crate::npm::CliNpmResolver; use crate::tsc; use crate::tsc::Diagnostics; +use crate::util::extract; use crate::util::path::to_percent_decoded_str; +pub async fn check( + flags: Arc, + check_flags: CheckFlags, +) -> Result<(), AnyError> { + let factory = CliFactory::from_flags(flags); + + let main_graph_container = factory.main_module_graph_container().await?; + + let specifiers = + main_graph_container.collect_specifiers(&check_flags.files)?; + if specifiers.is_empty() { + log::warn!("{} No matching files found.", colors::yellow("Warning")); + } + + let specifiers_for_typecheck = if check_flags.doc || check_flags.doc_only { + let file_fetcher = factory.file_fetcher()?; + let root_permissions = factory.root_permissions_container()?; + + let mut specifiers_for_typecheck = if check_flags.doc { + specifiers.clone() + } else { + vec![] + }; + + for s in specifiers { + let file = file_fetcher.fetch(&s, root_permissions).await?; + let snippet_files = extract::extract_snippet_files(file)?; + for snippet_file in snippet_files { + specifiers_for_typecheck.push(snippet_file.specifier.clone()); + file_fetcher.insert_memory_files(snippet_file); + } + } + + specifiers_for_typecheck + } else { + specifiers + }; + + main_graph_container + .check_specifiers(&specifiers_for_typecheck, None) + .await +} + /// Options for performing a check of a module graph. Note that the decision to /// emit or not is determined by the `ts_config` settings. pub struct CheckOptions { @@ -83,7 +131,9 @@ impl TypeChecker { graph: ModuleGraph, options: CheckOptions, ) -> Result, AnyError> { - let (graph, diagnostics) = self.check_diagnostics(graph, options).await?; + let (graph, mut diagnostics) = + self.check_diagnostics(graph, options).await?; + diagnostics.emit_warnings(); if diagnostics.is_empty() { Ok(graph) } else { @@ -118,9 +168,7 @@ impl TypeChecker { .cli_options .resolve_ts_config_for_emit(TsConfigType::Check { lib: options.lib })?; if options.log_ignored_options { - if let Some(ignored_options) = ts_config_result.maybe_ignored_options { - log::warn!("{}", ignored_options); - } + check_warn_tsconfig(&ts_config_result); } let type_check_mode = options.type_check_mode; @@ -427,7 +475,7 @@ fn get_tsc_roots( // now walk the graph that only includes the fast check dependencies while let Some(specifier) = pending.pop_front() { - let Some(module) = graph.get(&specifier) else { + let Some(module) = graph.get(specifier) else { continue; }; if let Some(entry) = maybe_get_check_entry(module, check_js) { diff --git a/cli/tools/compile.rs b/cli/tools/compile.rs index 90ee0e2706..5a4a938bb9 100644 --- a/cli/tools/compile.rs +++ b/cli/tools/compile.rs @@ -1,9 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use crate::args::check_warn_tsconfig; use crate::args::CompileFlags; use crate::args::Flags; use crate::factory::CliFactory; use crate::http_util::HttpClientProvider; +use crate::standalone::binary::StandaloneRelativeFileBaseUrl; use crate::standalone::is_standalone_binary; use deno_ast::ModuleSpecifier; use deno_core::anyhow::bail; @@ -13,7 +15,6 @@ use deno_core::error::AnyError; use deno_core::resolve_url_or_path; use deno_graph::GraphKind; use deno_terminal::colors; -use eszip::EszipRelativeFileBaseUrl; use rand::Rng; use std::path::Path; use std::path::PathBuf; @@ -28,7 +29,6 @@ pub async fn compile( let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; let module_graph_creator = factory.module_graph_creator().await?; - let parsed_source_cache = factory.parsed_source_cache(); let binary_writer = factory.create_compile_binary_writer().await?; let http_client = factory.http_client_provider(); let module_specifier = cli_options.resolve_main_module()?; @@ -53,6 +53,16 @@ pub async fn compile( ); } + if cli_options.unstable_detect_cjs() { + log::warn!( + concat!( + "{} --unstable-detect-cjs is not properly supported in deno compile. ", + "The compiled executable may encounter runtime errors.", + ), + crate::colors::yellow("Warning"), + ); + } + let output_path = resolve_compile_executable_output_path( http_client, &compile_flags, @@ -69,7 +79,7 @@ pub async fn compile( let graph = if cli_options.type_check_mode().is_true() { // In this case, the previous graph creation did type checking, which will // create a module graph with types information in it. We don't want to - // store that in the eszip so create a code only module graph from scratch. + // store that in the binary so create a code only module graph from scratch. module_graph_creator .create_graph(GraphKind::CodeOnly, module_roots) .await? @@ -79,11 +89,7 @@ pub async fn compile( let ts_config_for_emit = cli_options .resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?; - let (transpile_options, emit_options) = - crate::args::ts_config_to_transpile_and_emit_options( - ts_config_for_emit.ts_config, - )?; - let parser = parsed_source_cache.as_capturing_parser(); + check_warn_tsconfig(&ts_config_for_emit); let root_dir_url = resolve_root_dir_from_specifiers( cli_options.workspace().root_dir(), graph.specifiers().map(|(s, _)| s).chain( @@ -94,17 +100,6 @@ pub async fn compile( ), ); log::debug!("Binary root dir: {}", root_dir_url); - let root_dir_url = EszipRelativeFileBaseUrl::new(&root_dir_url); - let eszip = eszip::EszipV2::from_graph(eszip::FromGraphOptions { - graph, - parser, - transpile_options, - emit_options, - // make all the modules relative to the root folder - relative_file_base: Some(root_dir_url), - npm_packages: None, - })?; - log::info!( "{} {} to {}", colors::green("Compile"), @@ -131,15 +126,18 @@ pub async fn compile( let write_result = binary_writer .write_bin( file, - eszip, - root_dir_url, - &module_specifier, + &graph, + StandaloneRelativeFileBaseUrl::from(&root_dir_url), + module_specifier, &compile_flags, cli_options, ) .await .with_context(|| { - format!("Writing temporary file '{}'", temp_path.display()) + format!( + "Writing deno compile executable to temporary file '{}'", + temp_path.display() + ) }); // set it as executable diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs index f88b3bc645..3b08f2c77a 100644 --- a/cli/tools/coverage/mod.rs +++ b/cli/tools/coverage/mod.rs @@ -452,6 +452,11 @@ fn filter_coverages( let exclude: Vec = exclude.iter().map(|e| Regex::new(e).unwrap()).collect(); + // Matches virtual file paths for doc testing + // e.g. file:///path/to/mod.ts$23-29.ts + let doc_test_re = + Regex::new(r"\$\d+-\d+\.(js|mjs|cjs|jsx|ts|mts|cts|tsx)$").unwrap(); + coverages .into_iter() .filter(|e| { @@ -460,6 +465,7 @@ fn filter_coverages( || e.url.ends_with("$deno$test.js") || e.url.ends_with(".snap") || is_supported_test_path(Path::new(e.url.as_str())) + || doc_test_re.is_match(e.url.as_str()) || Url::parse(&e.url) .ok() .map(|url| npm_resolver.in_npm_package(&url)) @@ -565,7 +571,7 @@ pub async fn cover_files( | MediaType::Cjs | MediaType::Mjs | MediaType::Json => None, - MediaType::Dts | MediaType::Dmts | MediaType::Dcts => Some(Vec::new()), + MediaType::Dts | MediaType::Dmts | MediaType::Dcts => Some(String::new()), MediaType::TypeScript | MediaType::Jsx | MediaType::Mts @@ -587,8 +593,7 @@ pub async fn cover_files( } }; let runtime_code: String = match transpiled_code { - Some(code) => String::from_utf8(code) - .with_context(|| format!("Failed decoding {}", file.specifier))?, + Some(code) => code, None => original_source.to_string(), }; diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index ce31c80684..5e18546a28 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -5,10 +5,11 @@ use crate::args::DocHtmlFlag; use crate::args::DocSourceFileFlag; use crate::args::Flags; use crate::colors; -use crate::display::write_json_to_stdout; -use crate::display::write_to_stdout_ignore_sigpipe; +use crate::display; use crate::factory::CliFactory; -use crate::graph_util::graph_exit_lock_errors; +use crate::graph_util::graph_exit_integrity_errors; +use crate::graph_util::graph_walk_errors; +use crate::graph_util::GraphWalkErrorsOptions; use crate::tsc::get_types_declaration_file_text; use crate::util::fs::collect_specifiers; use deno_ast::diagnostics::Diagnostic; @@ -17,6 +18,7 @@ use deno_config::glob::PathOrPatternSet; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; +use deno_core::serde_json; use deno_doc as doc; use deno_doc::html::UrlResolveKind; use deno_graph::source::NullFileSystem; @@ -31,6 +33,8 @@ use std::collections::BTreeMap; use std::rc::Rc; use std::sync::Arc; +const JSON_SCHEMA_VERSION: u8 = 1; + async fn generate_doc_nodes_for_builtin_types( doc_flags: DocFlags, parser: &dyn ModuleParser, @@ -105,7 +109,7 @@ pub async fn doc( } DocSourceFileFlag::Paths(ref source_files) => { let module_graph_creator = factory.module_graph_creator().await?; - let maybe_lockfile = cli_options.maybe_lockfile(); + let fs = factory.fs(); let module_specifiers = collect_specifiers( FilePatterns { @@ -125,8 +129,18 @@ pub async fn doc( .create_graph(GraphKind::TypesOnly, module_specifiers.clone()) .await?; - if maybe_lockfile.is_some() { - graph_exit_lock_errors(&graph); + graph_exit_integrity_errors(&graph); + let errors = graph_walk_errors( + &graph, + fs, + &module_specifiers, + GraphWalkErrorsOptions { + check_js: false, + kind: GraphKind::TypesOnly, + }, + ); + for error in errors { + log::warn!("{} {}", colors::yellow("Warning"), error); } let doc_parser = doc::DocParser::new( @@ -181,7 +195,7 @@ pub async fn doc( kind_with_drilldown: deno_doc::html::DocNodeKindWithDrilldown::Other(node.kind()), inner: Rc::new(node), - drilldown_parent_kind: None, + drilldown_name: None, parent: None, }) .collect::>(), @@ -228,7 +242,11 @@ pub async fn doc( doc_nodes_by_url.into_values().flatten().collect::>(); if doc_flags.json { - write_json_to_stdout(&doc_nodes) + let json_output = serde_json::json!({ + "version": JSON_SCHEMA_VERSION, + "nodes": &doc_nodes + }); + display::write_json_to_stdout(&json_output) } else if doc_flags.lint { // don't output docs if running with only the --lint flag log::info!( @@ -244,7 +262,7 @@ pub async fn doc( } struct DocResolver { - deno_ns: std::collections::HashSet>, + deno_ns: std::collections::HashMap, Option>>, strip_trailing_html: bool, } @@ -268,7 +286,7 @@ impl deno_doc::html::HrefResolver for DocResolver { } fn resolve_global_symbol(&self, symbol: &[String]) -> Option { - if self.deno_ns.contains(symbol) { + if self.deno_ns.contains_key(symbol) { Some(format!( "https://deno.land/api@v{}?s={}", env!("CARGO_PKG_VERSION"), @@ -437,7 +455,7 @@ impl deno_doc::html::HrefResolver for NodeDocResolver { fn generate_docs_directory( doc_nodes_by_url: IndexMap>, html_options: &DocHtmlFlag, - deno_ns: std::collections::HashSet>, + deno_ns: std::collections::HashMap, Option>>, rewrite_map: Option>, ) -> Result<(), AnyError> { let cwd = std::env::current_dir().context("Failed to get CWD")?; @@ -495,7 +513,6 @@ fn generate_docs_directory( rewrite_map, href_resolver, usage_composer: None, - composable_output: false, category_docs, disable_search: internal_env.is_some(), symbol_redirect_map, @@ -553,7 +570,8 @@ fn print_docs_to_stdout( ) }; - write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(AnyError::from) + display::write_to_stdout_ignore_sigpipe(details.as_bytes()) + .map_err(AnyError::from) } fn check_diagnostics(diagnostics: &[DocDiagnostic]) -> Result<(), AnyError> { diff --git a/cli/tools/fmt.rs b/cli/tools/fmt.rs index 2d06aafca2..81af25c34b 100644 --- a/cli/tools/fmt.rs +++ b/cli/tools/fmt.rs @@ -33,6 +33,7 @@ use deno_core::error::AnyError; use deno_core::futures; use deno_core::parking_lot::Mutex; use deno_core::unsync::spawn_blocking; +use deno_core::url::Url; use log::debug; use log::info; use log::warn; @@ -120,7 +121,13 @@ pub async fn format( }; } - format_files(caches, &fmt_flags, paths_with_options_batches).await?; + format_files( + caches, + cli_options, + &fmt_flags, + paths_with_options_batches, + ) + .await?; Ok(()) }) @@ -133,7 +140,8 @@ pub async fn format( let caches = factory.caches()?; let paths_with_options_batches = resolve_paths_with_options_batches(cli_options, &fmt_flags)?; - format_files(caches, &fmt_flags, paths_with_options_batches).await?; + format_files(caches, cli_options, &fmt_flags, paths_with_options_batches) + .await?; } Ok(()) @@ -172,6 +180,7 @@ fn resolve_paths_with_options_batches( async fn format_files( caches: &Arc, + cli_options: &Arc, fmt_flags: &FmtFlags, paths_with_options_batches: Vec, ) -> Result<(), AnyError> { @@ -199,6 +208,7 @@ async fn format_files( fmt_options.options, fmt_options.unstable, incremental_cache.clone(), + cli_options.ext_flag().clone(), ) .await?; incremental_cache.wait_completion().await; @@ -211,11 +221,14 @@ fn collect_fmt_files( cli_options: &CliOptions, files: FilePatterns, ) -> Result, AnyError> { - FileCollector::new(|e| is_supported_ext_fmt(e.path)) - .ignore_git_folder() - .ignore_node_modules() - .set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned)) - .collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files) + FileCollector::new(|e| { + is_supported_ext_fmt(e.path) + || (e.path.extension().is_none() && cli_options.ext_flag().is_some()) + }) + .ignore_git_folder() + .ignore_node_modules() + .set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned)) + .collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files) } /// Formats markdown (using ) and its code blocks @@ -253,6 +266,8 @@ fn format_markdown( | "svelte" | "vue" | "astro" + | "vto" + | "njk" | "yml" | "yaml" ) { @@ -273,44 +288,24 @@ fn format_markdown( dprint_plugin_json::format_text(&fake_filename, text, &json_config) } "css" | "scss" | "sass" | "less" => { - if unstable_options.css { - format_css(&fake_filename, text, fmt_options) - } else { - Ok(None) - } + format_css(&fake_filename, text, fmt_options) } - "html" => { - if unstable_options.html { - format_html(&fake_filename, text, fmt_options) - } else { - Ok(None) - } - } - "svelte" | "vue" | "astro" => { + "html" => format_html(&fake_filename, text, fmt_options), + "svelte" | "vue" | "astro" | "vto" | "njk" => { if unstable_options.component { format_html(&fake_filename, text, fmt_options) } else { Ok(None) } } - "yml" | "yaml" => { - if unstable_options.yaml { - pretty_yaml::format_text( - text, - &get_resolved_yaml_config(fmt_options), - ) - .map(Some) - .map_err(AnyError::from) - } else { - Ok(None) - } - } + "yml" | "yaml" => format_yaml(text, fmt_options), _ => { let mut codeblock_config = get_resolved_typescript_config(fmt_options); codeblock_config.line_width = line_width; dprint_plugin_typescript::format_text( &fake_filename, + None, text.to_string(), &codeblock_config, ) @@ -340,13 +335,33 @@ pub fn format_css( file_text: &str, fmt_options: &FmtOptionsConfig, ) -> Result, AnyError> { - malva::format_text( + let formatted_str = malva::format_text( file_text, malva::detect_syntax(file_path).unwrap_or(malva::Syntax::Css), &get_resolved_malva_config(fmt_options), ) - .map(Some) - .map_err(AnyError::from) + .map_err(AnyError::from)?; + + Ok(if formatted_str == file_text { + None + } else { + Some(formatted_str) + }) +} + +fn format_yaml( + file_text: &str, + fmt_options: &FmtOptionsConfig, +) -> Result, AnyError> { + let formatted_str = + pretty_yaml::format_text(file_text, &get_resolved_yaml_config(fmt_options)) + .map_err(AnyError::from)?; + + Ok(if formatted_str == file_text { + None + } else { + Some(formatted_str) + }) } pub fn format_html( @@ -354,7 +369,7 @@ pub fn format_html( file_text: &str, fmt_options: &FmtOptionsConfig, ) -> Result, AnyError> { - markup_fmt::format_text( + let format_result = markup_fmt::format_text( file_text, markup_fmt::detect_language(file_path) .unwrap_or(markup_fmt::Language::Html), @@ -403,17 +418,9 @@ pub fn format_html( let mut typescript_config = get_resolved_typescript_config(fmt_options); typescript_config.line_width = hints.print_width as u32; - if hints.attr { - typescript_config.quote_style = if let Some(true) = - fmt_options.single_quote - { - dprint_plugin_typescript::configuration::QuoteStyle::AlwaysDouble - } else { - dprint_plugin_typescript::configuration::QuoteStyle::AlwaysSingle - }; - } dprint_plugin_typescript::format_text( &path, + None, text.to_string(), &typescript_config, ) @@ -428,9 +435,30 @@ pub fn format_html( } }, ) - .map(Some) .map_err(|error| match error { - markup_fmt::FormatError::Syntax(error) => AnyError::from(error), + markup_fmt::FormatError::Syntax(error) => { + fn inner( + error: &markup_fmt::SyntaxError, + file_path: &Path, + ) -> Option { + let url = Url::from_file_path(file_path).ok()?; + + let error_msg = format!( + "Syntax error ({}) at {}:{}:{}\n", + error.kind, + url.as_str(), + error.line, + error.column + ); + Some(error_msg) + } + + if let Some(error_msg) = inner(&error, file_path) { + AnyError::from(generic_error(error_msg)) + } else { + AnyError::from(error) + } + } markup_fmt::FormatError::External(errors) => { let last = errors.len() - 1; AnyError::msg( @@ -447,6 +475,14 @@ pub fn format_html( .collect::(), ) } + }); + + let formatted_str = format_result?; + + Ok(if formatted_str == file_text { + None + } else { + Some(formatted_str) }) } @@ -456,8 +492,11 @@ pub fn format_file( file_text: &str, fmt_options: &FmtOptionsConfig, unstable_options: &UnstableFmtOptions, + ext: Option, ) -> Result, AnyError> { - let ext = get_extension(file_path).unwrap_or_default(); + let ext = ext + .or_else(|| get_extension(file_path)) + .unwrap_or("ts".to_string()); match ext.as_str() { "md" | "mkd" | "mkdn" | "mdwn" | "mdown" | "markdown" => { @@ -465,48 +504,28 @@ pub fn format_file( } "json" | "jsonc" => format_json(file_path, file_text, fmt_options), "css" | "scss" | "sass" | "less" => { - if unstable_options.css { - format_css(file_path, file_text, fmt_options) - } else { - Ok(None) - } + format_css(file_path, file_text, fmt_options) } - "html" => { - if unstable_options.html { - format_html(file_path, file_text, fmt_options) - } else { - Ok(None) - } - } - "svelte" | "vue" | "astro" => { + "html" => format_html(file_path, file_text, fmt_options), + "svelte" | "vue" | "astro" | "vto" | "njk" => { if unstable_options.component { format_html(file_path, file_text, fmt_options) } else { Ok(None) } } - "yml" | "yaml" => { - if unstable_options.yaml { - pretty_yaml::format_text( - file_text, - &get_resolved_yaml_config(fmt_options), - ) - .map(Some) - .map_err(AnyError::from) - } else { - Ok(None) - } - } + "yml" | "yaml" => format_yaml(file_text, fmt_options), "ipynb" => dprint_plugin_jupyter::format_text( file_text, |file_path: &Path, file_text: String| { - format_file(file_path, &file_text, fmt_options, unstable_options) + format_file(file_path, &file_text, fmt_options, unstable_options, None) }, ), _ => { let config = get_resolved_typescript_config(fmt_options); dprint_plugin_typescript::format_text( file_path, + Some(&ext), file_text.to_string(), &config, ) @@ -532,6 +551,7 @@ trait Formatter { fmt_options: FmtOptionsConfig, unstable_options: UnstableFmtOptions, incremental_cache: Arc, + ext: Option, ) -> Result<(), AnyError>; fn finish(&self) -> Result<(), AnyError>; @@ -551,6 +571,7 @@ impl Formatter for CheckFormatter { fmt_options: FmtOptionsConfig, unstable_options: UnstableFmtOptions, incremental_cache: Arc, + ext: Option, ) -> Result<(), AnyError> { // prevent threads outputting at the same time let output_lock = Arc::new(Mutex::new(0)); @@ -572,6 +593,7 @@ impl Formatter for CheckFormatter { &file_text, &fmt_options, &unstable_options, + ext.clone(), ) { Ok(Some(formatted_text)) => { not_formatted_files_count.fetch_add(1, Ordering::Relaxed); @@ -649,6 +671,7 @@ impl Formatter for RealFormatter { fmt_options: FmtOptionsConfig, unstable_options: UnstableFmtOptions, incremental_cache: Arc, + ext: Option, ) -> Result<(), AnyError> { let output_lock = Arc::new(Mutex::new(0)); // prevent threads outputting at the same time @@ -668,7 +691,13 @@ impl Formatter for RealFormatter { &file_path, &file_contents.text, |file_path, file_text| { - format_file(file_path, file_text, &fmt_options, &unstable_options) + format_file( + file_path, + file_text, + &fmt_options, + &unstable_options, + ext.clone(), + ) }, ) { Ok(Some(formatted_text)) => { @@ -794,6 +823,7 @@ fn format_stdin( &source, &fmt_options.options, &fmt_options.unstable, + None, )?; if fmt_flags.check { #[allow(clippy::print_stdout)] @@ -916,6 +946,7 @@ fn get_resolved_malva_config( }; let language_options = LanguageOptions { + align_comments: true, hex_case: HexCase::Lower, hex_color_length: None, quotes: if let Some(true) = options.single_quote { @@ -947,6 +978,7 @@ fn get_resolved_malva_config( single_line_top_level_declarations: false, selector_override_comment_directive: "deno-fmt-selector-override".into(), ignore_comment_directive: "deno-fmt-ignore".into(), + ignore_file_comment_directive: "deno-fmt-ignore-file".into(), }; FormatOptions { @@ -1005,6 +1037,7 @@ fn get_resolved_markup_fmt_config( svelte_directive_shorthand: Some(true), astro_attr_shorthand: Some(true), ignore_comment_directive: "deno-fmt-ignore".into(), + ignore_file_comment_directive: "deno-fmt-ignore-file".into(), }; FormatOptions { @@ -1020,7 +1053,6 @@ fn get_resolved_yaml_config( let layout_options = LayoutOptions { print_width: options.line_width.unwrap_or(80) as usize, - use_tabs: options.use_tabs.unwrap_or_default(), indent_width: options.indent_width.unwrap_or(2) as usize, line_break: LineBreak::Lf, }; @@ -1037,6 +1069,9 @@ fn get_resolved_yaml_config( brace_spacing: true, bracket_spacing: false, dash_spacing: DashSpacing::OneSpace, + prefer_single_line: false, + flow_sequence_prefer_single_line: None, + flow_map_prefer_single_line: None, trim_trailing_whitespaces: true, trim_trailing_zero: false, ignore_comment_directive: "deno-fmt-ignore".into(), @@ -1148,6 +1183,8 @@ fn is_supported_ext_fmt(path: &Path) -> bool { | "svelte" | "vue" | "astro" + | "vto" + | "njk" | "md" | "mkd" | "mkdn" @@ -1206,6 +1243,10 @@ mod test { assert!(is_supported_ext_fmt(Path::new("foo.VUE"))); assert!(is_supported_ext_fmt(Path::new("foo.astro"))); assert!(is_supported_ext_fmt(Path::new("foo.AsTrO"))); + assert!(is_supported_ext_fmt(Path::new("foo.vto"))); + assert!(is_supported_ext_fmt(Path::new("foo.Vto"))); + assert!(is_supported_ext_fmt(Path::new("foo.njk"))); + assert!(is_supported_ext_fmt(Path::new("foo.NJk"))); assert!(is_supported_ext_fmt(Path::new("foo.yml"))); assert!(is_supported_ext_fmt(Path::new("foo.Yml"))); assert!(is_supported_ext_fmt(Path::new("foo.yaml"))); @@ -1272,6 +1313,7 @@ mod test { ..Default::default() }, &UnstableFmtOptions::default(), + None, ) .unwrap() .unwrap(); diff --git a/cli/tools/info.rs b/cli/tools/info.rs index a15252c7c4..3febaff579 100644 --- a/cli/tools/info.rs +++ b/cli/tools/info.rs @@ -11,13 +11,14 @@ use deno_core::anyhow::bail; use deno_core::error::AnyError; use deno_core::resolve_url_or_path; use deno_core::serde_json; -use deno_core::serde_json::json; +use deno_core::url; use deno_graph::Dependency; use deno_graph::GraphKind; use deno_graph::Module; use deno_graph::ModuleError; use deno_graph::ModuleGraph; use deno_graph::Resolution; +use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; @@ -30,11 +31,13 @@ use crate::args::Flags; use crate::args::InfoFlags; use crate::display; use crate::factory::CliFactory; -use crate::graph_util::graph_exit_lock_errors; +use crate::graph_util::graph_exit_integrity_errors; use crate::npm::CliNpmResolver; use crate::npm::ManagedCliNpmResolver; use crate::util::checksum; +const JSON_SCHEMA_VERSION: u8 = 1; + pub async fn info( flags: Arc, info_flags: InfoFlags, @@ -46,20 +49,23 @@ pub async fn info( let module_graph_creator = factory.module_graph_creator().await?; let npm_resolver = factory.npm_resolver().await?; let maybe_lockfile = cli_options.maybe_lockfile(); + let npmrc = cli_options.npmrc(); let resolver = factory.workspace_resolver().await?; - let maybe_import_specifier = - if let Some(import_map) = resolver.maybe_import_map() { - if let Ok(imports_specifier) = - import_map.resolve(&specifier, import_map.base_url()) - { - Some(imports_specifier) - } else { - None - } + let cwd_url = + url::Url::from_directory_path(cli_options.initial_cwd()).unwrap(); + + let maybe_import_specifier = if let Some(import_map) = + resolver.maybe_import_map() + { + if let Ok(imports_specifier) = import_map.resolve(&specifier, &cwd_url) { + Some(imports_specifier) } else { None - }; + } + } else { + None + }; let specifier = match maybe_import_specifier { Some(specifier) => specifier, @@ -74,13 +80,21 @@ pub async fn info( // write out the lockfile if there is one if let Some(lockfile) = &maybe_lockfile { - graph_exit_lock_errors(&graph); + graph_exit_integrity_errors(&graph); lockfile.write_if_changed()?; } if info_flags.json { - let mut json_graph = json!(graph); - add_npm_packages_to_json(&mut json_graph, npm_resolver.as_ref()); + let mut json_graph = serde_json::json!(graph); + if let Some(output) = json_graph.as_object_mut() { + output.shift_insert( + 0, + "version".to_string(), + JSON_SCHEMA_VERSION.into(), + ); + } + + add_npm_packages_to_json(&mut json_graph, npm_resolver.as_ref(), npmrc); display::write_json_to_stdout(&json_graph)?; } else { let mut output = String::new(); @@ -121,7 +135,8 @@ fn print_cache_info( let local_storage_dir = origin_dir.join("local_storage"); if json { - let mut output = json!({ + let mut json_output = serde_json::json!({ + "version": JSON_SCHEMA_VERSION, "denoDir": deno_dir, "modulesCache": modules_cache, "npmCache": npm_cache, @@ -131,10 +146,10 @@ fn print_cache_info( }); if location.is_some() { - output["localStorage"] = serde_json::to_value(local_storage_dir)?; + json_output["localStorage"] = serde_json::to_value(local_storage_dir)?; } - display::write_json_to_stdout(&output) + display::write_json_to_stdout(&json_output) } else { println!("{} {}", colors::bold("DENO_DIR location:"), deno_dir); println!( @@ -176,6 +191,7 @@ fn print_cache_info( fn add_npm_packages_to_json( json: &mut serde_json::Value, npm_resolver: &dyn CliNpmResolver, + npmrc: &ResolvedNpmRc, ) { let Some(npm_resolver) = npm_resolver.as_managed() else { return; // does not include byonm to deno info's output @@ -186,45 +202,28 @@ fn add_npm_packages_to_json( let json = json.as_object_mut().unwrap(); let modules = json.get_mut("modules").and_then(|m| m.as_array_mut()); if let Some(modules) = modules { - if modules.len() == 1 - && modules[0].get("kind").and_then(|k| k.as_str()) == Some("npm") - { - // If there is only one module and it's "external", then that means - // someone provided an npm specifier as a cli argument. In this case, - // we want to show which npm package the cli argument resolved to. - let module = &mut modules[0]; - let maybe_package = module - .get("specifier") - .and_then(|k| k.as_str()) - .and_then(|specifier| NpmPackageNvReference::from_str(specifier).ok()) - .and_then(|package_ref| { - snapshot - .resolve_package_from_deno_module(package_ref.nv()) - .ok() - }); - if let Some(pkg) = maybe_package { - if let Some(module) = module.as_object_mut() { - module - .insert("npmPackage".to_string(), pkg.id.as_serialized().into()); - } - } - } else { - // Filter out npm package references from the modules and instead - // have them only listed as dependencies. This is done because various - // npm specifiers modules in the graph are really just unresolved - // references. So there could be listed multiple npm specifiers - // that would resolve to a single npm package. - for i in (0..modules.len()).rev() { - if matches!( - modules[i].get("kind").and_then(|k| k.as_str()), - Some("npm") | Some("external") - ) { - modules.remove(i); - } - } - } - for module in modules.iter_mut() { + if matches!(module.get("kind").and_then(|k| k.as_str()), Some("npm")) { + // If there is only one module and it's "external", then that means + // someone provided an npm specifier as a cli argument. In this case, + // we want to show which npm package the cli argument resolved to. + let maybe_package = module + .get("specifier") + .and_then(|k| k.as_str()) + .and_then(|specifier| NpmPackageNvReference::from_str(specifier).ok()) + .and_then(|package_ref| { + snapshot + .resolve_package_from_deno_module(package_ref.nv()) + .ok() + }); + if let Some(pkg) = maybe_package { + if let Some(module) = module.as_object_mut() { + module + .insert("npmPackage".to_string(), pkg.id.as_serialized().into()); + } + } + } + let dependencies = module .get_mut("dependencies") .and_then(|d| d.as_array_mut()); @@ -256,7 +255,7 @@ fn add_npm_packages_to_json( let mut json_packages = serde_json::Map::with_capacity(sorted_packages.len()); for pkg in sorted_packages { let mut kv = serde_json::Map::new(); - kv.insert("name".to_string(), pkg.id.nv.name.to_string().into()); + kv.insert("name".to_string(), pkg.id.nv.name.clone().into()); kv.insert("version".to_string(), pkg.id.nv.version.to_string().into()); let mut deps = pkg.dependencies.values().collect::>(); deps.sort(); @@ -265,6 +264,8 @@ fn add_npm_packages_to_json( .map(|id| serde_json::Value::String(id.as_serialized())) .collect::>(); kv.insert("dependencies".to_string(), deps.into()); + let registry_url = npmrc.get_registry_url(&pkg.id.nv.name); + kv.insert("registryUrl".to_string(), registry_url.to_string().into()); json_packages.insert(pkg.id.as_serialized(), kv.into()); } @@ -440,7 +441,7 @@ impl<'a> GraphDisplayContext<'a> { } let root_specifier = self.graph.resolve(&self.graph.roots[0]); - match self.graph.try_get(&root_specifier) { + match self.graph.try_get(root_specifier) { Ok(Some(root)) => { let maybe_cache_info = match root { Module::Js(module) => module.maybe_cache_info.as_ref(), @@ -456,22 +457,6 @@ impl<'a> GraphDisplayContext<'a> { local.to_string_lossy() )?; } - if let Some(emit) = &cache_info.emit { - writeln!( - writer, - "{} {}", - colors::bold("emit:"), - emit.to_string_lossy() - )?; - } - if let Some(map) = &cache_info.map { - writeln!( - writer, - "{} {}", - colors::bold("map:"), - map.to_string_lossy() - )?; - } } if let Some(module) = root.js() { writeln!(writer, "{} {}", colors::bold("type:"), module.media_type)?; @@ -655,8 +640,21 @@ impl<'a> GraphDisplayContext<'a> { ModuleError::InvalidTypeAssertion { .. } => { self.build_error_msg(specifier, "(invalid import attribute)") } - ModuleError::LoadingErr(_, _, _) => { - self.build_error_msg(specifier, "(loading error)") + ModuleError::LoadingErr(_, _, err) => { + use deno_graph::ModuleLoadError::*; + let message = match err { + HttpsChecksumIntegrity(_) => "(checksum integrity error)", + Decode(_) => "(loading decode error)", + Loader(err) => match deno_core::error::get_custom_error_class(err) { + Some("NotCapable") => "(not capable, requires --allow-import)", + _ => "(loading error)", + }, + Jsr(_) => "(loading error)", + NodeUnknownBuiltinModule(_) => "(unknown node built-in error)", + Npm(_) => "(npm loading error)", + TooManyRedirects => "(too many redirects error)", + }; + self.build_error_msg(specifier, message.as_ref()) } ModuleError::ParseErr(_, _) => { self.build_error_msg(specifier, "(parsing error)") @@ -694,9 +692,9 @@ impl<'a> GraphDisplayContext<'a> { Resolution::Ok(resolved) => { let specifier = &resolved.specifier; let resolved_specifier = self.graph.resolve(specifier); - Some(match self.graph.try_get(&resolved_specifier) { + Some(match self.graph.try_get(resolved_specifier) { Ok(Some(module)) => self.build_module_info(module, type_dep), - Err(err) => self.build_error_info(err, &resolved_specifier), + Err(err) => self.build_error_info(err, resolved_specifier), Ok(None) => TreeNode::from_text(format!( "{} {}", colors::red(specifier), diff --git a/cli/tools/init/mod.rs b/cli/tools/init/mod.rs index b9ae803c73..2d6a894e13 100644 --- a/cli/tools/init/mod.rs +++ b/cli/tools/init/mod.rs @@ -37,7 +37,7 @@ const routes: Route[] = [ }, { pattern: new URLPattern({ pathname: "/static/*" }), - handler: (req) => serveDir(req, { urlRoot: "./" }), + handler: (req) => serveDir(req), }, ]; @@ -52,7 +52,6 @@ export default { return handler(req); }, } satisfies Deno.ServeDefaultExport; - "#, )?; create_file( @@ -80,13 +79,23 @@ Deno.test(async function serverFetchUsers() { }); Deno.test(async function serverFetchStatic() { - const req = new Request("https://deno.land/static/main.ts"); + const req = new Request("https://deno.land/static/hello.js"); const res = await server.fetch(req); - assertEquals(res.headers.get("content-type"), "text/plain;charset=UTF-8"); + assertEquals(await res.text(), 'console.log("Hello, world!");\n'); + assertEquals(res.headers.get("content-type"), "text/javascript; charset=UTF-8"); }); "#, )?; + let static_dir = dir.join("static"); + std::fs::create_dir_all(&static_dir)?; + create_file( + &static_dir, + "hello.js", + r#"console.log("Hello, world!"); +"#, + )?; + create_json_file( &dir, "deno.json", @@ -203,7 +212,7 @@ Deno.test(function addTest() { info!(" deno task dev"); info!(""); info!(" {}", colors::gray("# Run the tests")); - info!(" deno -R test"); + info!(" deno test -R"); } else if init_flags.lib { info!(" {}", colors::gray("# Run the tests")); info!(" deno test"); diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs index 456e5c1a68..ed86e86c79 100644 --- a/cli/tools/installer.rs +++ b/cli/tools/installer.rs @@ -7,14 +7,17 @@ use crate::args::ConfigFlag; use crate::args::Flags; use crate::args::InstallFlags; use crate::args::InstallFlagsGlobal; +use crate::args::InstallFlagsLocal; use crate::args::InstallKind; use crate::args::TypeCheckMode; use crate::args::UninstallFlags; use crate::args::UninstallKind; use crate::factory::CliFactory; +use crate::graph_container::ModuleGraphContainer; use crate::http_util::HttpClientProvider; use crate::util::fs::canonicalize_path_maybe_not_exists; +use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -195,14 +198,15 @@ pub async fn infer_name_from_url( Some(stem.to_string()) } -pub fn uninstall(uninstall_flags: UninstallFlags) -> Result<(), AnyError> { - if !uninstall_flags.global { - log::warn!("⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag."); - } - +pub async fn uninstall( + flags: Arc, + uninstall_flags: UninstallFlags, +) -> Result<(), AnyError> { let uninstall_flags = match uninstall_flags.kind { UninstallKind::Global(flags) => flags, - UninstallKind::Local => unreachable!(), + UninstallKind::Local(remove_flags) => { + return super::registry::remove(flags, remove_flags).await; + } }; let cwd = std::env::current_dir().context("Unable to get CWD")?; @@ -261,26 +265,69 @@ pub fn uninstall(uninstall_flags: UninstallFlags) -> Result<(), AnyError> { Ok(()) } +pub(crate) async fn install_from_entrypoints( + flags: Arc, + entrypoints: &[String], +) -> Result<(), AnyError> { + let factory = CliFactory::from_flags(flags.clone()); + let emitter = factory.emitter()?; + let main_graph_container = factory.main_module_graph_container().await?; + main_graph_container + .load_and_type_check_files(entrypoints) + .await?; + emitter + .cache_module_emits(&main_graph_container.graph()) + .await +} + async fn install_local( flags: Arc, - maybe_add_flags: Option, + install_flags: InstallFlagsLocal, ) -> Result<(), AnyError> { - if let Some(add_flags) = maybe_add_flags { - return super::registry::add( - flags, - add_flags, - super::registry::AddCommandName::Install, - ) - .await; + match install_flags { + InstallFlagsLocal::Add(add_flags) => { + super::registry::add( + flags, + add_flags, + super::registry::AddCommandName::Install, + ) + .await + } + InstallFlagsLocal::Entrypoints(entrypoints) => { + install_from_entrypoints(flags, &entrypoints).await + } + InstallFlagsLocal::TopLevel => { + let factory = CliFactory::from_flags(flags); + // surface any errors in the package.json + if let Some(npm_resolver) = factory.npm_resolver().await?.as_managed() { + npm_resolver.ensure_no_pkg_json_dep_errors()?; + } + crate::tools::registry::cache_top_level_deps(&factory, None).await?; + + if let Some(lockfile) = factory.cli_options()?.maybe_lockfile() { + lockfile.write_if_changed()?; + } + + Ok(()) + } } +} - let factory = CliFactory::from_flags(flags); - crate::module_loader::load_top_level_deps(&factory).await?; - - if let Some(lockfile) = factory.cli_options()?.maybe_lockfile() { - lockfile.write_if_changed()?; +fn check_if_installs_a_single_package_globally( + maybe_add_flags: Option<&AddFlags>, +) -> Result<(), AnyError> { + let Some(add_flags) = maybe_add_flags else { + return Ok(()); + }; + if add_flags.packages.len() != 1 { + return Ok(()); + } + let Ok(url) = Url::parse(&add_flags.packages[0]) else { + return Ok(()); + }; + if matches!(url.scheme(), "http" | "https") { + bail!("Failed to install \"{}\" specifier. If you are trying to install {} globally, run again with `-g` flag:\n deno install -g {}", url.scheme(), url.as_str(), url.as_str()); } - Ok(()) } @@ -290,14 +337,13 @@ pub async fn install_command( ) -> Result<(), AnyError> { match install_flags.kind { InstallKind::Global(global_flags) => { - if !install_flags.global { - log::warn!("⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag."); - } - install_global(flags, global_flags).await } - InstallKind::Local(maybe_add_flags) => { - install_local(flags, maybe_add_flags).await + InstallKind::Local(local_flags) => { + if let InstallFlagsLocal::Add(add_flags) = &local_flags { + check_if_installs_a_single_package_globally(Some(add_flags))?; + } + install_local(flags, local_flags).await } } } @@ -448,10 +494,6 @@ async fn resolve_shim_data( TypeCheckMode::Local => executable_args.push("--check".to_string()), } - if flags.unstable_config.legacy_flag_enabled { - executable_args.push("--unstable".to_string()); - } - for feature in &flags.unstable_config.features { executable_args.push(format!("--unstable-{}", feature)); } @@ -464,10 +506,6 @@ async fn resolve_shim_data( executable_args.push("--no-npm".to_string()); } - if flags.lock_write { - executable_args.push("--lock-write".to_string()); - } - if flags.cached_only { executable_args.push("--cached-only".to_string()); } @@ -784,13 +822,7 @@ mod tests { create_install_shim( &HttpClientProvider::new(None, None), - &Flags { - unstable_config: UnstableConfig { - legacy_flag_enabled: true, - ..Default::default() - }, - ..Flags::default() - }, + &Flags::default(), InstallFlagsGlobal { module_url: "http://localhost:4545/echo_server.ts".to_string(), args: vec![], @@ -812,12 +844,11 @@ mod tests { let content = fs::read_to_string(file_path).unwrap(); if cfg!(windows) { assert!(content.contains( - r#""run" "--unstable" "--no-config" "http://localhost:4545/echo_server.ts""# + r#""run" "--no-config" "http://localhost:4545/echo_server.ts""# )); } else { - assert!(content.contains( - r#"run --unstable --no-config 'http://localhost:4545/echo_server.ts'"# - )); + assert!(content + .contains(r#"run --no-config 'http://localhost:4545/echo_server.ts'"#)); } } @@ -848,13 +879,7 @@ mod tests { async fn install_unstable_legacy() { let shim_data = resolve_shim_data( &HttpClientProvider::new(None, None), - &Flags { - unstable_config: UnstableConfig { - legacy_flag_enabled: true, - ..Default::default() - }, - ..Default::default() - }, + &Default::default(), &InstallFlagsGlobal { module_url: "http://localhost:4545/echo_server.ts".to_string(), args: vec![], @@ -869,12 +894,7 @@ mod tests { assert_eq!(shim_data.name, "echo_server"); assert_eq!( shim_data.args, - vec![ - "run", - "--unstable", - "--no-config", - "http://localhost:4545/echo_server.ts", - ] + vec!["run", "--no-config", "http://localhost:4545/echo_server.ts",] ); } @@ -1471,8 +1491,8 @@ mod tests { assert!(content.contains(&expected_string)); } - #[test] - fn uninstall_basic() { + #[tokio::test] + async fn uninstall_basic() { let temp_dir = TempDir::new(); let bin_dir = temp_dir.path().join("bin"); std::fs::create_dir(&bin_dir).unwrap(); @@ -1499,13 +1519,16 @@ mod tests { File::create(file_path).unwrap(); } - uninstall(UninstallFlags { - kind: UninstallKind::Global(UninstallFlagsGlobal { - name: "echo_test".to_string(), - root: Some(temp_dir.path().to_string()), - }), - global: false, - }) + uninstall( + Default::default(), + UninstallFlags { + kind: UninstallKind::Global(UninstallFlagsGlobal { + name: "echo_test".to_string(), + root: Some(temp_dir.path().to_string()), + }), + }, + ) + .await .unwrap(); assert!(!file_path.exists()); diff --git a/cli/tools/jupyter/install.rs b/cli/tools/jupyter/install.rs index b0ddc948d6..aeff89ccf4 100644 --- a/cli/tools/jupyter/install.rs +++ b/cli/tools/jupyter/install.rs @@ -58,9 +58,9 @@ pub fn install() -> Result<(), AnyError> { let f = std::fs::File::create(kernel_json_path)?; serde_json::to_writer_pretty(f, &json_data)?; - install_icon(&user_data_dir, "logo-32x32.png", DENO_ICON_32)?; - install_icon(&user_data_dir, "logo-64x64.png", DENO_ICON_64)?; - install_icon(&user_data_dir, "logo-svg.svg", DENO_ICON_SVG)?; + install_icon(&kernel_dir, "logo-32x32.png", DENO_ICON_32)?; + install_icon(&kernel_dir, "logo-64x64.png", DENO_ICON_64)?; + install_icon(&kernel_dir, "logo-svg.svg", DENO_ICON_SVG)?; log::info!("✅ Deno kernelspec installed successfully."); Ok(()) diff --git a/cli/tools/jupyter/mod.rs b/cli/tools/jupyter/mod.rs index 14fcbd72c4..0ffd0da1ee 100644 --- a/cli/tools/jupyter/mod.rs +++ b/cli/tools/jupyter/mod.rs @@ -25,7 +25,6 @@ use deno_core::serde_json::json; use deno_core::url::Url; use deno_runtime::deno_io::Stdio; use deno_runtime::deno_io::StdioPipe; -use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use deno_terminal::colors; @@ -65,7 +64,8 @@ pub async fn kernel( resolve_url_or_path("./$deno$jupyter.ts", cli_options.initial_cwd()) .unwrap(); // TODO(bartlomieju): should we run with all permissions? - let permissions = PermissionsContainer::new(Permissions::allow_all()); + let permissions = + PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone()); let npm_resolver = factory.npm_resolver().await?.clone(); let resolver = factory.resolver().await?.clone(); let worker_factory = factory.create_cli_main_worker_factory().await?; @@ -357,56 +357,74 @@ pub struct JupyterReplSession { impl JupyterReplSession { pub async fn start(&mut self) { + let mut poll_worker = true; loop { - let Some(msg) = self.rx.recv().await else { - break; - }; - let resp = match msg { - JupyterReplRequest::LspCompletions { - line_text, - position, - } => JupyterReplResponse::LspCompletions( - self.lsp_completions(&line_text, position).await, - ), - JupyterReplRequest::JsGetProperties { object_id } => { - JupyterReplResponse::JsGetProperties( - self.get_properties(object_id).await, - ) - } - JupyterReplRequest::JsEvaluate { expr } => { - JupyterReplResponse::JsEvaluate(self.evaluate(expr).await) - } - JupyterReplRequest::JsGlobalLexicalScopeNames => { - JupyterReplResponse::JsGlobalLexicalScopeNames( - self.global_lexical_scope_names().await, - ) - } - JupyterReplRequest::JsEvaluateLineWithObjectWrapping { line } => { - JupyterReplResponse::JsEvaluateLineWithObjectWrapping( - self.evaluate_line_with_object_wrapping(&line).await, - ) - } - JupyterReplRequest::JsCallFunctionOnArgs { - function_declaration, - args, - } => JupyterReplResponse::JsCallFunctionOnArgs( - self - .call_function_on_args(function_declaration, &args) - .await, - ), - JupyterReplRequest::JsCallFunctionOn { arg0, arg1 } => { - JupyterReplResponse::JsCallFunctionOn( - self.call_function_on(arg0, arg1).await, - ) - } - }; + tokio::select! { + biased; - let Ok(()) = self.tx.send(resp) else { - break; - }; + maybe_message = self.rx.recv() => { + let Some(msg) = maybe_message else { + break; + }; + if self.handle_message(msg).await.is_err() { + break; + } + poll_worker = true; + }, + _ = self.repl_session.run_event_loop(), if poll_worker => { + poll_worker = false; + } + } } } + async fn handle_message( + &mut self, + msg: JupyterReplRequest, + ) -> Result<(), AnyError> { + let resp = match msg { + JupyterReplRequest::LspCompletions { + line_text, + position, + } => JupyterReplResponse::LspCompletions( + self.lsp_completions(&line_text, position).await, + ), + JupyterReplRequest::JsGetProperties { object_id } => { + JupyterReplResponse::JsGetProperties( + self.get_properties(object_id).await, + ) + } + JupyterReplRequest::JsEvaluate { expr } => { + JupyterReplResponse::JsEvaluate(self.evaluate(expr).await) + } + JupyterReplRequest::JsGlobalLexicalScopeNames => { + JupyterReplResponse::JsGlobalLexicalScopeNames( + self.global_lexical_scope_names().await, + ) + } + JupyterReplRequest::JsEvaluateLineWithObjectWrapping { line } => { + JupyterReplResponse::JsEvaluateLineWithObjectWrapping( + self.evaluate_line_with_object_wrapping(&line).await, + ) + } + JupyterReplRequest::JsCallFunctionOnArgs { + function_declaration, + args, + } => JupyterReplResponse::JsCallFunctionOnArgs( + self + .call_function_on_args(function_declaration, &args) + .await, + ), + JupyterReplRequest::JsCallFunctionOn { arg0, arg1 } => { + JupyterReplResponse::JsCallFunctionOn( + self.call_function_on(arg0, arg1).await, + ) + } + }; + + self.tx.send(resp).map_err(|e| e.into()) + } + pub async fn lsp_completions( &mut self, line_text: &str, diff --git a/cli/tools/jupyter/resources/deno-logo-32x32.png b/cli/tools/jupyter/resources/deno-logo-32x32.png index 97871a02ee..d59f251a24 100644 Binary files a/cli/tools/jupyter/resources/deno-logo-32x32.png and b/cli/tools/jupyter/resources/deno-logo-32x32.png differ diff --git a/cli/tools/jupyter/resources/deno-logo-64x64.png b/cli/tools/jupyter/resources/deno-logo-64x64.png index 1b9444ef63..37e98abafd 100644 Binary files a/cli/tools/jupyter/resources/deno-logo-64x64.png and b/cli/tools/jupyter/resources/deno-logo-64x64.png differ diff --git a/cli/tools/jupyter/resources/deno-logo-svg.svg b/cli/tools/jupyter/resources/deno-logo-svg.svg index d7bb9ef804..fbc22cd910 100644 --- a/cli/tools/jupyter/resources/deno-logo-svg.svg +++ b/cli/tools/jupyter/resources/deno-logo-svg.svg @@ -1 +1,17 @@ - + + + + + + + + + + + diff --git a/cli/tools/jupyter/server.rs b/cli/tools/jupyter/server.rs index 0cd80f7ddd..5680ed4c13 100644 --- a/cli/tools/jupyter/server.rs +++ b/cli/tools/jupyter/server.rs @@ -329,7 +329,12 @@ impl JupyterServer { }) .collect(); - (candidates, cursor_pos - prop_name.len()) + if prop_name.len() > cursor_pos { + // TODO(bartlomieju): most likely not correct, but better than panicking because of sub with overflow + (candidates, cursor_pos) + } else { + (candidates, cursor_pos - prop_name.len()) + } } else { // combine results of declarations and globalThis properties let mut candidates = get_expression_property_names( @@ -349,7 +354,12 @@ impl JupyterServer { candidates.sort(); candidates.dedup(); // make sure to sort first - (candidates, cursor_pos - expr.len()) + if expr.len() > cursor_pos { + // TODO(bartlomieju): most likely not correct, but better than panicking because of sub with overflow + (candidates, cursor_pos) + } else { + (candidates, cursor_pos - expr.len()) + } }; connection diff --git a/cli/tools/lint/linter.rs b/cli/tools/lint/linter.rs index 777fe4d09b..2c2bc43acb 100644 --- a/cli/tools/lint/linter.rs +++ b/cli/tools/lint/linter.rs @@ -94,9 +94,16 @@ impl CliLinter { &self, file_path: &Path, source_code: String, + ext: Option<&str>, ) -> Result<(ParsedSource, Vec), AnyError> { let specifier = specifier_from_file_path(file_path)?; - let media_type = MediaType::from_specifier(&specifier); + let media_type = if let Some(ext) = ext { + MediaType::from_str(&format!("placeholder.{ext}")) + } else if file_path.extension().is_none() { + MediaType::TypeScript + } else { + MediaType::from_specifier(&specifier) + }; if self.fix { self.lint_file_and_fix(&specifier, media_type, source_code, file_path) diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index 5b51b2b40c..e096b486ef 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -45,6 +45,7 @@ use crate::colors; use crate::factory::CliFactory; use crate::graph_util::ModuleGraphCreator; use crate::tools::fmt::run_parallelized; +use crate::util::display; use crate::util::file_watcher; use crate::util::fs::canonicalize_path; use crate::util::path::is_script_ext; @@ -60,6 +61,8 @@ pub use rules::collect_no_slow_type_diagnostics; pub use rules::ConfiguredRules; pub use rules::LintRuleProvider; +const JSON_SCHEMA_VERSION: u8 = 1; + static STDIN_FILE_NAME: &str = "$deno$stdin.ts"; pub async fn lint( @@ -114,6 +117,7 @@ pub async fn lint( for paths_with_options in paths_with_options_batches { linter .lint_files( + cli_options, paths_with_options.options, lint_config.clone(), paths_with_options.dir, @@ -152,7 +156,7 @@ pub async fn lint( start_dir.maybe_deno_json().map(|c| c.as_ref()), )?; let mut file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME); - if let Some(ext) = &lint_flags.ext { + if let Some(ext) = cli_options.ext_flag() { file_path.set_extension(ext); } let r = lint_stdin(&file_path, lint_rules, deno_lint_config); @@ -176,6 +180,7 @@ pub async fn lint( for paths_with_options in paths_with_options_batches { linter .lint_files( + cli_options, paths_with_options.options, deno_lint_config.clone(), paths_with_options.dir, @@ -261,6 +266,7 @@ impl WorkspaceLinter { pub async fn lint_files( &mut self, + cli_options: &Arc, lint_options: LintOptions, lint_config: LintConfig, member_dir: WorkspaceDirectory, @@ -345,6 +351,7 @@ impl WorkspaceLinter { let reporter_lock = self.reporter_lock.clone(); let maybe_incremental_cache = maybe_incremental_cache.clone(); let linter = linter.clone(); + let cli_options = cli_options.clone(); async move { run_parallelized(paths, { move |file_path| { @@ -358,7 +365,11 @@ impl WorkspaceLinter { } } - let r = linter.lint_file(&file_path, file_text); + let r = linter.lint_file( + &file_path, + file_text, + cli_options.ext_flag().as_deref(), + ); if let Ok((file_source, file_diagnostics)) = &r { if let Some(incremental_cache) = &maybe_incremental_cache { if file_diagnostics.is_empty() { @@ -418,11 +429,14 @@ fn collect_lint_files( cli_options: &CliOptions, files: FilePatterns, ) -> Result, AnyError> { - FileCollector::new(|e| is_script_ext(e.path)) - .ignore_git_folder() - .ignore_node_modules() - .set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned)) - .collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files) + FileCollector::new(|e| { + is_script_ext(e.path) + || (e.path.extension().is_none() && cli_options.ext_flag().is_some()) + }) + .ignore_git_folder() + .ignore_node_modules() + .set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned)) + .collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files) } #[allow(clippy::print_stdout)] @@ -440,18 +454,20 @@ pub fn print_rules_list(json: bool, maybe_rules_tags: Option>) { .rules; if json { - let json_rules: Vec = lint_rules - .iter() - .map(|rule| { - serde_json::json!({ - "code": rule.code(), - "tags": rule.tags(), - "docs": rule.docs(), + let json_output = serde_json::json!({ + "version": JSON_SCHEMA_VERSION, + "rules": lint_rules + .iter() + .map(|rule| { + serde_json::json!({ + "code": rule.code(), + "tags": rule.tags(), + "docs": rule.docs(), + }) }) - }) - .collect(); - let json_str = serde_json::to_string_pretty(&json_rules).unwrap(); - println!("{json_str}"); + .collect::>(), + }); + display::write_json_to_stdout(&json_output).unwrap(); } else { // The rules should still be printed even if `--quiet` option is enabled, // so use `println!` here instead of `info!`. @@ -492,7 +508,7 @@ fn lint_stdin( }); linter - .lint_file(file_path, deno_ast::strip_bom(source_code)) + .lint_file(file_path, deno_ast::strip_bom(source_code), None) .map_err(AnyError::from) } diff --git a/cli/tools/lint/reporters.rs b/cli/tools/lint/reporters.rs index cb00ad2962..bf80be9f20 100644 --- a/cli/tools/lint/reporters.rs +++ b/cli/tools/lint/reporters.rs @@ -12,6 +12,8 @@ use crate::args::LintReporterKind; use super::LintError; +const JSON_SCHEMA_VERSION: u8 = 1; + pub fn create_reporter(kind: LintReporterKind) -> Box { match kind { LintReporterKind::Pretty => Box::new(PrettyLintReporter::new()), @@ -170,6 +172,7 @@ struct JsonLintDiagnostic { #[derive(Serialize)] struct JsonLintReporter { + version: u8, diagnostics: Vec, errors: Vec, } @@ -177,6 +180,7 @@ struct JsonLintReporter { impl JsonLintReporter { fn new() -> JsonLintReporter { JsonLintReporter { + version: JSON_SCHEMA_VERSION, diagnostics: Vec::new(), errors: Vec::new(), } diff --git a/cli/tools/lint/rules/mod.rs b/cli/tools/lint/rules/mod.rs index 2669ffda15..dd723ad159 100644 --- a/cli/tools/lint/rules/mod.rs +++ b/cli/tools/lint/rules/mod.rs @@ -14,7 +14,7 @@ use deno_graph::ModuleGraph; use deno_lint::diagnostic::LintDiagnostic; use deno_lint::rules::LintRule; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; mod no_sloppy_imports; mod no_slow_types; @@ -144,13 +144,13 @@ impl ConfiguredRules { } pub struct LintRuleProvider { - sloppy_imports_resolver: Option>, + sloppy_imports_resolver: Option>, workspace_resolver: Option>, } impl LintRuleProvider { pub fn new( - sloppy_imports_resolver: Option>, + sloppy_imports_resolver: Option>, workspace_resolver: Option>, ) -> Self { Self { diff --git a/cli/tools/lint/rules/no_sloppy_imports.rs b/cli/tools/lint/rules/no_sloppy_imports.rs index 4180be5be1..2f60875885 100644 --- a/cli/tools/lint/rules/no_sloppy_imports.rs +++ b/cli/tools/lint/rules/no_sloppy_imports.rs @@ -16,24 +16,25 @@ use deno_lint::diagnostic::LintDiagnosticRange; use deno_lint::diagnostic::LintFix; use deno_lint::diagnostic::LintFixChange; use deno_lint::rules::LintRule; +use deno_resolver::sloppy_imports::SloppyImportsResolution; +use deno_resolver::sloppy_imports::SloppyImportsResolutionMode; use text_lines::LineAndColumnIndex; use crate::graph_util::CliJsrUrlProvider; -use crate::resolver::SloppyImportsResolution; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; use super::ExtendedLintRule; #[derive(Debug)] pub struct NoSloppyImportsRule { - sloppy_imports_resolver: Option>, + sloppy_imports_resolver: Option>, // None for making printing out the lint rules easy workspace_resolver: Option>, } impl NoSloppyImportsRule { pub fn new( - sloppy_imports_resolver: Option>, + sloppy_imports_resolver: Option>, workspace_resolver: Option>, ) -> Self { NoSloppyImportsRule { @@ -172,7 +173,7 @@ impl LintRule for NoSloppyImportsRule { #[derive(Debug)] struct SloppyImportCaptureResolver<'a> { workspace_resolver: &'a WorkspaceResolver, - sloppy_imports_resolver: &'a SloppyImportsResolver, + sloppy_imports_resolver: &'a CliSloppyImportsResolver, captures: RefCell>, } @@ -194,7 +195,13 @@ impl<'a> deno_graph::source::Resolver for SloppyImportCaptureResolver<'a> { } | deno_config::workspace::MappedResolution::ImportMap { specifier, .. - } => match self.sloppy_imports_resolver.resolve(&specifier, mode) { + } => match self.sloppy_imports_resolver.resolve( + &specifier, + match mode { + ResolutionMode::Execution => SloppyImportsResolutionMode::Execution, + ResolutionMode::Types => SloppyImportsResolutionMode::Types, + }, + ) { Some(res) => { self .captures diff --git a/cli/tools/mod.rs b/cli/tools/mod.rs index 1e1c655658..a458da9f1b 100644 --- a/cli/tools/mod.rs +++ b/cli/tools/mod.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. pub mod bench; -pub mod bundle; pub mod check; pub mod clean; pub mod compile; @@ -20,4 +19,3 @@ pub mod serve; pub mod task; pub mod test; pub mod upgrade; -pub mod vendor; diff --git a/cli/tools/registry/api.rs b/cli/tools/registry/api.rs index c382aa9ac8..2f27cb2fea 100644 --- a/cli/tools/registry/api.rs +++ b/cli/tools/registry/api.rs @@ -3,8 +3,8 @@ use crate::http_util; use deno_core::error::AnyError; use deno_core::serde_json; +use deno_core::url::Url; use deno_runtime::deno_fetch; -use lsp_types::Url; use serde::de::DeserializeOwned; use crate::http_util::HttpClient; diff --git a/cli/tools/registry/diagnostics.rs b/cli/tools/registry/diagnostics.rs index 69434f1ea8..733a78ddac 100644 --- a/cli/tools/registry/diagnostics.rs +++ b/cli/tools/registry/diagnostics.rs @@ -3,7 +3,6 @@ use std::borrow::Cow; use std::path::PathBuf; use std::sync::Arc; -use std::sync::Mutex; use deno_ast::diagnostics::Diagnostic; use deno_ast::diagnostics::DiagnosticLevel; @@ -21,9 +20,10 @@ use deno_ast::SourceRanged; use deno_ast::SourceTextInfo; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; +use deno_core::parking_lot::Mutex; +use deno_core::url::Url; use deno_graph::FastCheckDiagnostic; use deno_semver::Version; -use lsp_types::Url; use super::unfurl::SpecifierUnfurlerDiagnostic; @@ -36,7 +36,7 @@ impl PublishDiagnosticsCollector { pub fn print_and_error(&self) -> Result<(), AnyError> { let mut errors = 0; let mut has_slow_types_errors = false; - let mut diagnostics = self.diagnostics.lock().unwrap().take(); + let mut diagnostics = self.diagnostics.lock().take(); diagnostics.sort_by_cached_key(|d| d.sorting_key()); @@ -75,8 +75,16 @@ impl PublishDiagnosticsCollector { } } + pub fn has_error(&self) -> bool { + self + .diagnostics + .lock() + .iter() + .any(|d| matches!(d.level(), DiagnosticLevel::Error)) + } + pub fn push(&self, diagnostic: PublishDiagnostic) { - self.diagnostics.lock().unwrap().push(diagnostic); + self.diagnostics.lock().push(diagnostic); } } diff --git a/cli/tools/registry/graph.rs b/cli/tools/registry/graph.rs index bdcb27aa16..184557e5df 100644 --- a/cli/tools/registry/graph.rs +++ b/cli/tools/registry/graph.rs @@ -8,13 +8,13 @@ use deno_ast::ParsedSource; use deno_ast::SourceRangedForSpanned; use deno_ast::SourceTextInfo; use deno_core::error::AnyError; +use deno_core::url::Url; use deno_graph::ModuleEntryRef; use deno_graph::ModuleGraph; use deno_graph::ResolutionResolved; use deno_graph::WalkOptions; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::npm::NpmPackageReqReference; -use lsp_types::Url; use crate::cache::ParsedSourceCache; @@ -128,7 +128,7 @@ impl GraphDiagnosticsCollector { follow_dynamic: true, // search the entire graph and not just the fast check subset prefer_fast_check_graph: false, - follow_type_only: true, + kind: deno_graph::GraphKind::All, }; let mut iter = graph.walk(graph.roots.iter(), options); while let Some((specifier, entry)) = iter.next() { diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs index d6e06fb58a..4098d62e37 100644 --- a/cli/tools/registry/mod.rs +++ b/cli/tools/registry/mod.rs @@ -25,9 +25,9 @@ use deno_core::futures::StreamExt; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; +use deno_core::url::Url; use deno_terminal::colors; use http_body_util::BodyExt; -use lsp_types::Url; use serde::Deserialize; use serde::Serialize; use sha2::Digest; @@ -43,7 +43,8 @@ use crate::cache::ParsedSourceCache; use crate::factory::CliFactory; use crate::graph_util::ModuleGraphCreator; use crate::http_util::HttpClient; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; +use crate::resolver::SloppyImportsCachedFs; use crate::tools::check::CheckOptions; use crate::tools::lint::collect_no_slow_type_diagnostics; use crate::tools::registry::diagnostics::PublishDiagnostic; @@ -52,6 +53,7 @@ use crate::util::display::human_size; mod api; mod auth; + mod diagnostics; mod graph; mod paths; @@ -64,6 +66,7 @@ mod unfurl; use auth::get_auth_method; use auth::AuthMethod; pub use pm::add; +pub use pm::cache_top_level_deps; pub use pm::remove; pub use pm::AddCommandName; use publish_order::PublishOrderGraph; @@ -106,7 +109,9 @@ pub async fn publish( } let specifier_unfurler = Arc::new(SpecifierUnfurler::new( if cli_options.unstable_sloppy_imports() { - Some(SloppyImportsResolver::new(cli_factory.fs().clone())) + Some(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( + cli_factory.fs().clone(), + ))) } else { None }, @@ -339,13 +344,11 @@ impl PublishPreparer { bail!("Exiting due to DENO_INTERNAL_FAST_CHECK_OVERWRITE") } else { log::info!("Checking for slow types in the public API..."); - let mut any_pkg_had_diagnostics = false; for package in package_configs { let export_urls = package.config_file.resolve_export_value_urls()?; let diagnostics = collect_no_slow_type_diagnostics(&graph, &export_urls); if !diagnostics.is_empty() { - any_pkg_had_diagnostics = true; for diagnostic in diagnostics { diagnostics_collector .push(PublishDiagnostic::FastCheck(diagnostic)); @@ -353,7 +356,9 @@ impl PublishPreparer { } } - if any_pkg_had_diagnostics { + // skip type checking the slow type graph if there are any errors because + // errors like remote modules existing will cause type checking to crash + if diagnostics_collector.has_error() { Ok(Arc::new(graph)) } else { // fast check passed, type check the output as a temporary measure @@ -1047,7 +1052,8 @@ async fn publish_package( sha256: faster_hex::hex_string(&sha2::Sha256::digest(&meta_bytes)), }, }; - let bundle = provenance::generate_provenance(http_client, subject).await?; + let bundle = + provenance::generate_provenance(http_client, vec![subject]).await?; let tlog_entry = &bundle.verification_material.tlog_entries[0]; log::info!("{}", diff --git a/cli/tools/registry/pm.rs b/cli/tools/registry/pm.rs index 52f3310ba4..d1be901d67 100644 --- a/cli/tools/registry/pm.rs +++ b/cli/tools/registry/pm.rs @@ -1,28 +1,26 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use std::borrow::Cow; -use std::path::Path; use std::path::PathBuf; use std::sync::Arc; -use deno_ast::TextChange; -use deno_config::deno_json::FmtOptionsConfig; -use deno_core::anyhow::anyhow; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures::FutureExt; use deno_core::futures::StreamExt; -use deno_core::serde_json; -use deno_core::ModuleSpecifier; -use deno_runtime::deno_node; +use deno_path_util::url_to_file_path; +use deno_semver::jsr::JsrPackageReqReference; +use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; -use indexmap::IndexMap; -use jsonc_parser::ast::ObjectProp; -use jsonc_parser::ast::Value; +use deno_semver::VersionReq; +use jsonc_parser::cst::CstObject; +use jsonc_parser::cst::CstObjectProp; +use jsonc_parser::cst::CstRootNode; +use jsonc_parser::json; use crate::args::AddFlags; use crate::args::CacheSetting; +use crate::args::CliOptions; use crate::args::Flags; use crate::args::RemoveFlags; use crate::factory::CliFactory; @@ -30,142 +28,236 @@ use crate::file_fetcher::FileFetcher; use crate::jsr::JsrFetchResolver; use crate::npm::NpmFetchResolver; -enum DenoConfigFormat { - Json, - Jsonc, +mod cache_deps; + +pub use cache_deps::cache_top_level_deps; + +#[derive(Debug, Copy, Clone)] +enum ConfigKind { + DenoJson, + PackageJson, } -impl DenoConfigFormat { - fn from_specifier(spec: &ModuleSpecifier) -> Result { - let file_name = spec - .path_segments() - .ok_or_else(|| anyhow!("Empty path in deno config specifier: {spec}"))? - .last() - .unwrap(); - match file_name { - "deno.json" => Ok(Self::Json), - "deno.jsonc" => Ok(Self::Jsonc), - _ => bail!("Unsupported deno config file: {file_name}"), - } - } +struct ConfigUpdater { + kind: ConfigKind, + cst: CstRootNode, + root_object: CstObject, + path: PathBuf, + modified: bool, } -enum DenoOrPackageJson { - Deno(Arc, DenoConfigFormat), - Npm(Arc, Option), -} - -impl DenoOrPackageJson { - fn specifier(&self) -> Cow { - match self { - Self::Deno(d, ..) => Cow::Borrowed(&d.specifier), - Self::Npm(n, ..) => Cow::Owned(n.specifier()), - } +impl ConfigUpdater { + fn new( + kind: ConfigKind, + config_file_path: PathBuf, + ) -> Result { + let config_file_contents = std::fs::read_to_string(&config_file_path) + .with_context(|| { + format!("Reading config file '{}'", config_file_path.display()) + })?; + let cst = CstRootNode::parse(&config_file_contents, &Default::default()) + .with_context(|| { + format!("Parsing config file '{}'", config_file_path.display()) + })?; + let root_object = cst.object_value_or_set(); + Ok(Self { + kind, + cst, + root_object, + path: config_file_path, + modified: false, + }) } - /// Returns the existing imports/dependencies from the config. - fn existing_imports(&self) -> Result, AnyError> { - match self { - DenoOrPackageJson::Deno(deno, ..) => { - if let Some(imports) = deno.json.imports.clone() { - match serde_json::from_value(imports) { - Ok(map) => Ok(map), - Err(err) => { - bail!("Malformed \"imports\" configuration: {err}") + fn display_path(&self) -> String { + deno_path_util::url_from_file_path(&self.path) + .map(|u| u.to_string()) + .unwrap_or_else(|_| self.path.display().to_string()) + } + + fn obj(&self) -> &CstObject { + &self.root_object + } + + fn contents(&self) -> String { + self.cst.to_string() + } + + fn add(&mut self, selected: SelectedPackage, dev: bool) { + fn insert_index(object: &CstObject, searching_name: &str) -> usize { + object + .properties() + .into_iter() + .take_while(|prop| { + let prop_name = + prop.name().and_then(|name| name.decoded_value().ok()); + match prop_name { + Some(current_name) => { + searching_name.cmp(¤t_name) == std::cmp::Ordering::Greater } + None => true, } + }) + .count() + } + + match self.kind { + ConfigKind::DenoJson => { + let imports = self.root_object.object_value_or_set("imports"); + let value = + format!("{}@{}", selected.package_name, selected.version_req); + if let Some(prop) = imports.get(&selected.import_name) { + prop.set_value(json!(value)); } else { - Ok(Default::default()) + let index = insert_index(&imports, &selected.import_name); + imports.insert(index, &selected.import_name, json!(value)); } } - DenoOrPackageJson::Npm(npm, ..) => { - Ok(npm.dependencies.clone().unwrap_or_default()) + ConfigKind::PackageJson => { + let deps_prop = self.root_object.get("dependencies"); + let dev_deps_prop = self.root_object.get("devDependencies"); + + let dependencies = if dev { + self + .root_object + .object_value("devDependencies") + .unwrap_or_else(|| { + let index = deps_prop + .as_ref() + .map(|p| p.property_index() + 1) + .unwrap_or_else(|| self.root_object.properties().len()); + self + .root_object + .insert(index, "devDependencies", json!({})) + .object_value_or_set() + }) + } else { + self + .root_object + .object_value("dependencies") + .unwrap_or_else(|| { + let index = dev_deps_prop + .as_ref() + .map(|p| p.property_index()) + .unwrap_or_else(|| self.root_object.properties().len()); + self + .root_object + .insert(index, "dependencies", json!({})) + .object_value_or_set() + }) + }; + let other_dependencies = if dev { + deps_prop.and_then(|p| p.value().and_then(|v| v.as_object())) + } else { + dev_deps_prop.and_then(|p| p.value().and_then(|v| v.as_object())) + }; + + let (alias, value) = package_json_dependency_entry(selected); + + if let Some(other) = other_dependencies { + if let Some(prop) = other.get(&alias) { + remove_prop_and_maybe_parent_prop(prop); + } + } + + if let Some(prop) = dependencies.get(&alias) { + prop.set_value(json!(value)); + } else { + let index = insert_index(&dependencies, &alias); + dependencies.insert(index, &alias, json!(value)); + } } } + + self.modified = true; } - fn fmt_options(&self) -> FmtOptionsConfig { - match self { - DenoOrPackageJson::Deno(deno, ..) => deno - .to_fmt_config() - .ok() - .map(|f| f.options) - .unwrap_or_default(), - DenoOrPackageJson::Npm(_, config) => config.clone().unwrap_or_default(), - } - } - - fn imports_key(&self) -> &'static str { - match self { - DenoOrPackageJson::Deno(..) => "imports", - DenoOrPackageJson::Npm(..) => "dependencies", - } - } - - fn file_name(&self) -> &'static str { - match self { - DenoOrPackageJson::Deno(_, format) => match format { - DenoConfigFormat::Json => "deno.json", - DenoConfigFormat::Jsonc => "deno.jsonc", - }, - DenoOrPackageJson::Npm(..) => "package.json", - } - } - - fn is_npm(&self) -> bool { - matches!(self, Self::Npm(..)) - } - - /// Get the preferred config file to operate on - /// given the flags. If no config file is present, - /// creates a `deno.json` file - in this case - /// we also return a new `CliFactory` that knows about - /// the new config - fn from_flags(flags: Arc) -> Result<(Self, CliFactory), AnyError> { - let factory = CliFactory::from_flags(flags.clone()); - let options = factory.cli_options()?; - let start_dir = &options.start_dir; - - match (start_dir.maybe_deno_json(), start_dir.maybe_pkg_json()) { - // when both are present, for now, - // default to deno.json - (Some(deno), Some(_) | None) => Ok(( - DenoOrPackageJson::Deno( - deno.clone(), - DenoConfigFormat::from_specifier(&deno.specifier)?, - ), - factory, - )), - (None, Some(package_json)) if options.enable_future_features() => { - Ok((DenoOrPackageJson::Npm(package_json.clone(), None), factory)) + fn remove(&mut self, package: &str) -> bool { + let removed = match self.kind { + ConfigKind::DenoJson => { + if let Some(prop) = self + .root_object + .object_value("imports") + .and_then(|i| i.get(package)) + { + remove_prop_and_maybe_parent_prop(prop); + true + } else { + false + } } - (None, Some(_) | None) => { - std::fs::write(options.initial_cwd().join("deno.json"), "{}\n") - .context("Failed to create deno.json file")?; - drop(factory); // drop to prevent use - log::info!("Created deno.json configuration file."); - let factory = CliFactory::from_flags(flags.clone()); - let options = factory.cli_options()?.clone(); - let start_dir = &options.start_dir; - Ok(( - DenoOrPackageJson::Deno( - start_dir.maybe_deno_json().cloned().ok_or_else(|| { - anyhow!("config not found, but it was just created") - })?, - DenoConfigFormat::Json, - ), - factory, - )) + ConfigKind::PackageJson => { + let deps = [ + self + .root_object + .object_value("dependencies") + .and_then(|deps| deps.get(package)), + self + .root_object + .object_value("devDependencies") + .and_then(|deps| deps.get(package)), + ]; + let removed = deps.iter().any(|d| d.is_some()); + for dep in deps.into_iter().flatten() { + remove_prop_and_maybe_parent_prop(dep); + } + removed } + }; + if removed { + self.modified = true; } + removed } + + fn commit(&self) -> Result<(), AnyError> { + if !self.modified { + return Ok(()); + } + + let new_text = self.contents(); + std::fs::write(&self.path, new_text).with_context(|| { + format!("failed writing to '{}'", self.path.display()) + })?; + Ok(()) + } +} + +fn remove_prop_and_maybe_parent_prop(prop: CstObjectProp) { + let parent = prop.parent().unwrap().as_object().unwrap(); + prop.remove(); + if parent.properties().is_empty() { + let parent_property = parent.parent().unwrap(); + let root_object = parent_property.parent().unwrap().as_object().unwrap(); + // remove the property + parent_property.remove(); + root_object.ensure_multiline(); + } +} + +fn create_deno_json( + flags: &Arc, + options: &CliOptions, +) -> Result { + std::fs::write(options.initial_cwd().join("deno.json"), "{}\n") + .context("Failed to create deno.json file")?; + log::info!("Created deno.json configuration file."); + let factory = CliFactory::from_flags(flags.clone()); + Ok(factory) } fn package_json_dependency_entry( selected: SelectedPackage, ) -> (String, String) { if let Some(npm_package) = selected.package_name.strip_prefix("npm:") { - (npm_package.into(), selected.version_req) + if selected.import_name == npm_package { + (npm_package.into(), selected.version_req) + } else { + ( + selected.import_name, + format!("npm:{}@{}", npm_package, selected.version_req), + ) + } } else if let Some(jsr_package) = selected.package_name.strip_prefix("jsr:") { let jsr_package = jsr_package.strip_prefix('@').unwrap_or(jsr_package); let scope_replaced = jsr_package.replace('/', "__"); @@ -193,33 +285,79 @@ impl std::fmt::Display for AddCommandName { } } +fn load_configs( + flags: &Arc, + has_jsr_specifiers: impl FnOnce() -> bool, +) -> Result<(CliFactory, Option, Option), AnyError> +{ + let cli_factory = CliFactory::from_flags(flags.clone()); + let options = cli_factory.cli_options()?; + let start_dir = &options.start_dir; + let npm_config = match start_dir.maybe_pkg_json() { + Some(pkg_json) => Some(ConfigUpdater::new( + ConfigKind::PackageJson, + pkg_json.path.clone(), + )?), + None => None, + }; + let deno_config = match start_dir.maybe_deno_json() { + Some(deno_json) => Some(ConfigUpdater::new( + ConfigKind::DenoJson, + url_to_file_path(&deno_json.specifier)?, + )?), + None => None, + }; + + let (cli_factory, deno_config) = match deno_config { + Some(config) => (cli_factory, Some(config)), + None if npm_config.is_some() && !has_jsr_specifiers() => { + (cli_factory, None) + } + _ => { + let factory = create_deno_json(flags, options)?; + let options = factory.cli_options()?.clone(); + let deno_json = options + .start_dir + .maybe_deno_json() + .expect("Just created deno.json"); + ( + factory, + Some(ConfigUpdater::new( + ConfigKind::DenoJson, + url_to_file_path(&deno_json.specifier)?, + )?), + ) + } + }; + assert!(deno_config.is_some() || npm_config.is_some()); + Ok((cli_factory, npm_config, deno_config)) +} + pub async fn add( flags: Arc, add_flags: AddFlags, cmd_name: AddCommandName, ) -> Result<(), AnyError> { - let (config_file, cli_factory) = - DenoOrPackageJson::from_flags(flags.clone())?; - - let config_specifier = config_file.specifier(); - if config_specifier.scheme() != "file" { - bail!("Can't add dependencies to a remote configuration file"); - } - let config_file_path = config_specifier.to_file_path().unwrap(); - - let http_client = cli_factory.http_client_provider(); - - let mut selected_packages = Vec::with_capacity(add_flags.packages.len()); - let mut package_reqs = Vec::with_capacity(add_flags.packages.len()); - - for entry_text in add_flags.packages.iter() { - let req = AddPackageReq::parse(entry_text).with_context(|| { - format!("Failed to parse package required: {}", entry_text) + let (cli_factory, mut npm_config, mut deno_config) = + load_configs(&flags, || { + add_flags.packages.iter().any(|s| s.starts_with("jsr:")) })?; - package_reqs.push(req); + if let Some(deno) = &deno_config { + if deno.obj().get("importMap").is_some() { + bail!( + concat!( + "`deno {}` is not supported when configuration file contains an \"importMap\" field. ", + "Inline the import map into the Deno configuration file.\n", + " at {}", + ), + cmd_name, + deno.display_path(), + ); + } } + let http_client = cli_factory.http_client_provider(); let deps_http_cache = cli_factory.global_http_cache()?; let mut deps_file_fetcher = FileFetcher::new( deps_http_cache.clone(), @@ -229,20 +367,58 @@ pub async fn add( Default::default(), None, ); + + let npmrc = cli_factory.cli_options().unwrap().npmrc(); + deps_file_fetcher.set_download_log_level(log::Level::Trace); let deps_file_fetcher = Arc::new(deps_file_fetcher); let jsr_resolver = Arc::new(JsrFetchResolver::new(deps_file_fetcher.clone())); - let npm_resolver = Arc::new(NpmFetchResolver::new(deps_file_fetcher)); + let npm_resolver = + Arc::new(NpmFetchResolver::new(deps_file_fetcher, npmrc.clone())); + + let mut selected_packages = Vec::with_capacity(add_flags.packages.len()); + let mut package_reqs = Vec::with_capacity(add_flags.packages.len()); + + for entry_text in add_flags.packages.iter() { + let req = AddRmPackageReq::parse(entry_text).with_context(|| { + format!("Failed to parse package required: {}", entry_text) + })?; + + match req { + Ok(add_req) => package_reqs.push(add_req), + Err(package_req) => { + if jsr_resolver.req_to_nv(&package_req).await.is_some() { + bail!( + "{entry_text} is missing a prefix. Did you mean `{}`?", + crate::colors::yellow(format!("deno {cmd_name} jsr:{package_req}")) + ) + } else if npm_resolver.req_to_nv(&package_req).await.is_some() { + bail!( + "{entry_text} is missing a prefix. Did you mean `{}`?", + crate::colors::yellow(format!("deno {cmd_name} npm:{package_req}")) + ) + } else { + bail!( + "{} was not found in either jsr or npm.", + crate::colors::red(entry_text) + ); + } + } + } + } let package_futures = package_reqs .into_iter() - .map(move |package_req| { - find_package_and_select_version_for_req( - jsr_resolver.clone(), - npm_resolver.clone(), - package_req, - ) - .boxed_local() + .map({ + let jsr_resolver = jsr_resolver.clone(); + move |package_req| { + find_package_and_select_version_for_req( + jsr_resolver.clone(), + npm_resolver.clone(), + package_req, + ) + .boxed_local() + } }) .collect::>(); @@ -270,28 +446,7 @@ pub async fn add( } } - let config_file_contents = { - let contents = tokio::fs::read_to_string(&config_file_path).await.unwrap(); - if contents.trim().is_empty() { - "{}\n".into() - } else { - contents - } - }; - let ast = jsonc_parser::parse_to_ast( - &config_file_contents, - &Default::default(), - &Default::default(), - )?; - - let obj = match ast.value { - Some(Value::Object(obj)) => obj, - _ => bail!("Failed updating config file due to no object."), - }; - - let mut existing_imports = config_file.existing_imports()?; - - let is_npm = config_file.is_npm(); + let dev = add_flags.dev; for selected_package in selected_packages { log::info!( "Add {}{}{}", @@ -300,46 +455,27 @@ pub async fn add( selected_package.selected_version ); - if is_npm { - let (name, version) = package_json_dependency_entry(selected_package); - existing_imports.insert(name, version) + if selected_package.package_name.starts_with("npm:") { + if let Some(npm) = &mut npm_config { + npm.add(selected_package, dev); + } else { + deno_config.as_mut().unwrap().add(selected_package, dev); + } + } else if let Some(deno) = &mut deno_config { + deno.add(selected_package, dev); } else { - existing_imports.insert( - selected_package.import_name, - format!( - "{}@{}", - selected_package.package_name, selected_package.version_req - ), - ) - }; + npm_config.as_mut().unwrap().add(selected_package, dev); + } } - let mut import_list: Vec<(String, String)> = - existing_imports.into_iter().collect(); - import_list.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); - let generated_imports = generate_imports(import_list); + if let Some(npm) = npm_config { + npm.commit()?; + } + if let Some(deno) = deno_config { + deno.commit()?; + } - let fmt_config_options = config_file.fmt_options(); - - let new_text = update_config_file_content( - obj, - &config_file_contents, - generated_imports, - fmt_config_options, - config_file.imports_key(), - config_file.file_name(), - ); - - tokio::fs::write(&config_file_path, new_text) - .await - .context("Failed to update configuration file")?; - - // clear the previously cached package.json from memory before reloading it - node_resolver::PackageJsonThreadLocalCache::clear(); - // make a new CliFactory to pick up the updated config file - let cli_factory = CliFactory::from_flags(flags); - // cache deps - crate::module_loader::load_top_level_deps(&cli_factory).await?; + npm_install_after_modification(flags, Some(jsr_resolver)).await?; Ok(()) } @@ -363,10 +499,10 @@ enum PackageAndVersion { async fn find_package_and_select_version_for_req( jsr_resolver: Arc, npm_resolver: Arc, - add_package_req: AddPackageReq, + add_package_req: AddRmPackageReq, ) -> Result { match add_package_req.value { - AddPackageReqValue::Jsr(req) => { + AddRmPackageReqValue::Jsr(req) => { let jsr_prefixed_name = format!("jsr:{}", &req.name); let Some(nv) = jsr_resolver.req_to_nv(&req).await else { if npm_resolver.req_to_nv(&req).await.is_some() { @@ -384,9 +520,11 @@ async fn find_package_and_select_version_for_req( }); }; let range_symbol = if req.version_req.version_text().starts_with('~') { - '~' + "~" + } else if req.version_req.version_text() == nv.version.to_string() { + "" } else { - '^' + "^" }; Ok(PackageAndVersion::Selected(SelectedPackage { import_name: add_package_req.alias, @@ -395,7 +533,7 @@ async fn find_package_and_select_version_for_req( selected_version: nv.version.to_string(), })) } - AddPackageReqValue::Npm(req) => { + AddRmPackageReqValue::Npm(req) => { let npm_prefixed_name = format!("npm:{}", &req.name); let Some(nv) = npm_resolver.req_to_nv(&req).await else { return Ok(PackageAndVersion::NotFound { @@ -404,11 +542,15 @@ async fn find_package_and_select_version_for_req( package_req: req, }); }; + let range_symbol = if req.version_req.version_text().starts_with('~') { - '~' + "~" + } else if req.version_req.version_text() == nv.version.to_string() { + "" } else { - '^' + "^" }; + Ok(PackageAndVersion::Selected(SelectedPackage { import_name: add_package_req.alias, package_name: npm_prefixed_name, @@ -420,19 +562,19 @@ async fn find_package_and_select_version_for_req( } #[derive(Debug, PartialEq, Eq)] -enum AddPackageReqValue { +enum AddRmPackageReqValue { Jsr(PackageReq), Npm(PackageReq), } #[derive(Debug, PartialEq, Eq)] -struct AddPackageReq { +struct AddRmPackageReq { alias: String, - value: AddPackageReqValue, + value: AddRmPackageReqValue, } -impl AddPackageReq { - pub fn parse(entry_text: &str) -> Result { +impl AddRmPackageReq { + pub fn parse(entry_text: &str) -> Result, AnyError> { enum Prefix { Jsr, Npm, @@ -471,110 +613,84 @@ impl AddPackageReq { None => match parse_alias(entry_text) { Some((alias, text)) => { let (maybe_prefix, entry_text) = parse_prefix(text); - ( - maybe_prefix.unwrap_or(Prefix::Jsr), - Some(alias.to_string()), - entry_text, - ) + if maybe_prefix.is_none() { + return Ok(Err(PackageReq::from_str(entry_text)?)); + } + + (maybe_prefix.unwrap(), Some(alias.to_string()), entry_text) } - None => (Prefix::Jsr, None, entry_text), + None => return Ok(Err(PackageReq::from_str(entry_text)?)), }, }; match prefix { Prefix::Jsr => { - let package_req = PackageReq::from_str(entry_text)?; - Ok(AddPackageReq { + let req_ref = + JsrPackageReqReference::from_str(&format!("jsr:{}", entry_text))?; + let package_req = req_ref.into_inner().req; + Ok(Ok(AddRmPackageReq { alias: maybe_alias.unwrap_or_else(|| package_req.name.to_string()), - value: AddPackageReqValue::Jsr(package_req), - }) + value: AddRmPackageReqValue::Jsr(package_req), + })) } Prefix::Npm => { - let package_req = PackageReq::from_str(entry_text)?; - Ok(AddPackageReq { + let req_ref = + NpmPackageReqReference::from_str(&format!("npm:{}", entry_text))?; + let mut package_req = req_ref.into_inner().req; + // deno_semver defaults to a version req of `*` if none is specified + // we want to default to `latest` instead + if package_req.version_req == *deno_semver::WILDCARD_VERSION_REQ + && package_req.version_req.version_text() == "*" + && !entry_text.contains("@*") + { + package_req.version_req = VersionReq::from_raw_text_and_inner( + "latest".into(), + deno_semver::RangeSetOrTag::Tag("latest".into()), + ); + } + Ok(Ok(AddRmPackageReq { alias: maybe_alias.unwrap_or_else(|| package_req.name.to_string()), - value: AddPackageReqValue::Npm(package_req), - }) + value: AddRmPackageReqValue::Npm(package_req), + })) } } } } -fn generate_imports(packages_to_version: Vec<(String, String)>) -> String { - let mut contents = vec![]; - let len = packages_to_version.len(); - for (index, (package, version)) in packages_to_version.iter().enumerate() { - // TODO(bartlomieju): fix it, once we start support specifying version on the cli - contents.push(format!("\"{}\": \"{}\"", package, version)); - if index != len - 1 { - contents.push(",".to_string()); - } - } - contents.join("\n") -} - -fn remove_from_config( - config_path: &Path, - keys: &[&'static str], - packages_to_remove: &[String], - removed_packages: &mut Vec, - fmt_options: &FmtOptionsConfig, -) -> Result<(), AnyError> { - let mut json: serde_json::Value = - serde_json::from_slice(&std::fs::read(config_path)?)?; - for key in keys { - let Some(obj) = json.get_mut(*key).and_then(|v| v.as_object_mut()) else { - continue; - }; - for package in packages_to_remove { - if obj.shift_remove(package).is_some() { - removed_packages.push(package.clone()); - } - } - } - - let config = serde_json::to_string_pretty(&json)?; - let config = - crate::tools::fmt::format_json(config_path, &config, fmt_options) - .ok() - .flatten() - .unwrap_or(config); - - std::fs::write(config_path, config) - .context("Failed to update configuration file")?; - - Ok(()) -} - pub async fn remove( flags: Arc, remove_flags: RemoveFlags, ) -> Result<(), AnyError> { - let (config_file, factory) = DenoOrPackageJson::from_flags(flags.clone())?; - let options = factory.cli_options()?; - let start_dir = &options.start_dir; - let fmt_config_options = config_file.fmt_options(); + let (_, npm_config, deno_config) = load_configs(&flags, || false)?; - let mut removed_packages = Vec::new(); + let mut configs = [npm_config, deno_config]; - if let Some(deno_json) = start_dir.maybe_deno_json() { - remove_from_config( - &deno_json.specifier.to_file_path().unwrap(), - &["imports"], - &remove_flags.packages, - &mut removed_packages, - &fmt_config_options, - )?; - } + let mut removed_packages = vec![]; - if let Some(pkg_json) = start_dir.maybe_pkg_json() { - remove_from_config( - &pkg_json.path, - &["dependencies", "devDependencies"], - &remove_flags.packages, - &mut removed_packages, - &fmt_config_options, - )?; + for package in &remove_flags.packages { + let req = AddRmPackageReq::parse(package).with_context(|| { + format!("Failed to parse package required: {}", package) + })?; + let mut parsed_pkg_name = None; + for config in configs.iter_mut().flatten() { + match &req { + Ok(rm_pkg) => { + if config.remove(&rm_pkg.alias) && parsed_pkg_name.is_none() { + parsed_pkg_name = Some(rm_pkg.alias.clone()); + } + } + Err(pkg) => { + // An alias or a package name without registry/version + // constraints. Try to remove the package anyway. + if config.remove(&pkg.name) && parsed_pkg_name.is_none() { + parsed_pkg_name = Some(pkg.name.clone()); + } + } + } + } + if let Some(pkg) = parsed_pkg_name { + removed_packages.push(pkg); + } } if removed_packages.is_empty() { @@ -583,120 +699,98 @@ pub async fn remove( for package in &removed_packages { log::info!("Removed {}", crate::colors::green(package)); } - // Update deno.lock - node_resolver::PackageJsonThreadLocalCache::clear(); - let cli_factory = CliFactory::from_flags(flags); - crate::module_loader::load_top_level_deps(&cli_factory).await?; + for config in configs.into_iter().flatten() { + config.commit()?; + } + + npm_install_after_modification(flags, None).await?; } Ok(()) } -fn update_config_file_content( - obj: jsonc_parser::ast::Object, - config_file_contents: &str, - generated_imports: String, - fmt_options: FmtOptionsConfig, - imports_key: &str, - file_name: &str, -) -> String { - let mut text_changes = vec![]; +async fn npm_install_after_modification( + flags: Arc, + // explicitly provided to prevent redownloading + jsr_resolver: Option>, +) -> Result<(), AnyError> { + // clear the previously cached package.json from memory before reloading it + node_resolver::PackageJsonThreadLocalCache::clear(); - match obj.get(imports_key) { - Some(ObjectProp { - value: Value::Object(lit), - .. - }) => text_changes.push(TextChange { - range: (lit.range.start + 1)..(lit.range.end - 1), - new_text: generated_imports, - }), - None => { - let insert_position = obj.range.end - 1; - text_changes.push(TextChange { - range: insert_position..insert_position, - // NOTE(bartlomieju): adding `\n` here to force the formatter to always - // produce a config file that is multiline, like so: - // ``` - // { - // "imports": { - // "": ":@" - // } - // } - new_text: format!("\"{imports_key}\": {{\n {generated_imports} }}"), - }) - } - // we verified the shape of `imports`/`dependencies` above - Some(_) => unreachable!(), + // make a new CliFactory to pick up the updated config file + let cli_factory = CliFactory::from_flags(flags); + // surface any errors in the package.json + let npm_resolver = cli_factory.npm_resolver().await?; + if let Some(npm_resolver) = npm_resolver.as_managed() { + npm_resolver.ensure_no_pkg_json_dep_errors()?; + } + // npm install + cache_deps::cache_top_level_deps(&cli_factory, jsr_resolver).await?; + + if let Some(lockfile) = cli_factory.cli_options()?.maybe_lockfile() { + lockfile.write_if_changed()?; } - let new_text = - deno_ast::apply_text_changes(config_file_contents, text_changes); - - crate::tools::fmt::format_json( - &PathBuf::from(file_name), - &new_text, - &fmt_options, - ) - .ok() - .map(|formatted_text| formatted_text.unwrap_or_else(|| new_text.clone())) - .unwrap_or(new_text) + Ok(()) } #[cfg(test)] mod test { - use deno_semver::VersionReq; - use super::*; #[test] fn test_parse_add_package_req() { assert_eq!( - AddPackageReq::parse("jsr:foo").unwrap(), - AddPackageReq { + AddRmPackageReq::parse("jsr:foo").unwrap().unwrap(), + AddRmPackageReq { alias: "foo".to_string(), - value: AddPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) + value: AddRmPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) } ); assert_eq!( - AddPackageReq::parse("alias@jsr:foo").unwrap(), - AddPackageReq { + AddRmPackageReq::parse("alias@jsr:foo").unwrap().unwrap(), + AddRmPackageReq { alias: "alias".to_string(), - value: AddPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) + value: AddRmPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) } ); assert_eq!( - AddPackageReq::parse("@alias/pkg@npm:foo").unwrap(), - AddPackageReq { + AddRmPackageReq::parse("@alias/pkg@npm:foo") + .unwrap() + .unwrap(), + AddRmPackageReq { alias: "@alias/pkg".to_string(), - value: AddPackageReqValue::Npm(PackageReq::from_str("foo").unwrap()) + value: AddRmPackageReqValue::Npm( + PackageReq::from_str("foo@latest").unwrap() + ) } ); assert_eq!( - AddPackageReq::parse("@alias/pkg@jsr:foo").unwrap(), - AddPackageReq { + AddRmPackageReq::parse("@alias/pkg@jsr:foo") + .unwrap() + .unwrap(), + AddRmPackageReq { alias: "@alias/pkg".to_string(), - value: AddPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) + value: AddRmPackageReqValue::Jsr(PackageReq::from_str("foo").unwrap()) } ); assert_eq!( - AddPackageReq::parse("alias@jsr:foo@^1.5.0").unwrap(), - AddPackageReq { + AddRmPackageReq::parse("alias@jsr:foo@^1.5.0") + .unwrap() + .unwrap(), + AddRmPackageReq { alias: "alias".to_string(), - value: AddPackageReqValue::Jsr( + value: AddRmPackageReqValue::Jsr( PackageReq::from_str("foo@^1.5.0").unwrap() ) } ); assert_eq!( - AddPackageReq::parse("@scope/pkg@tag").unwrap(), - AddPackageReq { - alias: "@scope/pkg".to_string(), - value: AddPackageReqValue::Jsr(PackageReq { - name: "@scope/pkg".to_string(), - // this is a tag - version_req: VersionReq::parse_from_specifier("tag").unwrap(), - }), - } + AddRmPackageReq::parse("@scope/pkg@tag") + .unwrap() + .unwrap_err() + .to_string(), + "@scope/pkg@tag", ); } } diff --git a/cli/tools/registry/pm/cache_deps.rs b/cli/tools/registry/pm/cache_deps.rs new file mode 100644 index 0000000000..365622d11f --- /dev/null +++ b/cli/tools/registry/pm/cache_deps.rs @@ -0,0 +1,121 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::sync::Arc; + +use crate::factory::CliFactory; +use crate::graph_container::ModuleGraphContainer; +use crate::graph_container::ModuleGraphUpdatePermit; +use deno_core::error::AnyError; +use deno_core::futures::stream::FuturesUnordered; +use deno_core::futures::StreamExt; +use deno_semver::package::PackageReq; + +pub async fn cache_top_level_deps( + // todo(dsherret): don't pass the factory into this function. Instead use ctor deps + factory: &CliFactory, + jsr_resolver: Option>, +) -> Result<(), AnyError> { + let npm_resolver = factory.npm_resolver().await?; + let cli_options = factory.cli_options()?; + let root_permissions = factory.root_permissions_container()?; + if let Some(npm_resolver) = npm_resolver.as_managed() { + if !npm_resolver.ensure_top_level_package_json_install().await? { + if let Some(lockfile) = cli_options.maybe_lockfile() { + lockfile.error_if_changed()?; + } + + npm_resolver.cache_packages().await?; + } + } + // cache as many entries in the import map as we can + let resolver = factory.workspace_resolver().await?; + if let Some(import_map) = resolver.maybe_import_map() { + let jsr_resolver = if let Some(resolver) = jsr_resolver { + resolver + } else { + Arc::new(crate::jsr::JsrFetchResolver::new( + factory.file_fetcher()?.clone(), + )) + }; + + let mut roots = Vec::new(); + + let mut info_futures = FuturesUnordered::new(); + + let mut seen_reqs = std::collections::HashSet::new(); + + for entry in import_map.imports().entries() { + let Some(specifier) = entry.value else { + continue; + }; + + match specifier.scheme() { + "jsr" => { + let specifier_str = specifier.as_str(); + let specifier_str = + specifier_str.strip_prefix("jsr:").unwrap_or(specifier_str); + if let Ok(req) = PackageReq::from_str(specifier_str) { + if !seen_reqs.insert(req.clone()) { + continue; + } + let jsr_resolver = jsr_resolver.clone(); + info_futures.push(async move { + if let Some(nv) = jsr_resolver.req_to_nv(&req).await { + if let Some(info) = jsr_resolver.package_version_info(&nv).await + { + return Some((specifier.clone(), info)); + } + } + None + }); + } + } + "npm" => roots.push(specifier.clone()), + _ => { + if entry.key.ends_with('/') && specifier.as_str().ends_with('/') { + continue; + } + if specifier.scheme() == "file" { + if let Ok(path) = specifier.to_file_path() { + if !path.is_file() { + continue; + } + } + } + roots.push(specifier.clone()); + } + } + } + + while let Some(info_future) = info_futures.next().await { + if let Some((specifier, info)) = info_future { + let exports = info.exports(); + for (k, _) in exports { + if let Ok(spec) = specifier.join(k) { + roots.push(spec); + } + } + } + } + let mut graph_permit = factory + .main_module_graph_container() + .await? + .acquire_update_permit() + .await; + let graph = graph_permit.graph_mut(); + factory + .module_load_preparer() + .await? + .prepare_module_load( + graph, + &roots, + false, + deno_config::deno_json::TsTypeLib::DenoWorker, + root_permissions.clone(), + None, + ) + .await?; + } + + Ok(()) +} diff --git a/cli/tools/registry/provenance.rs b/cli/tools/registry/provenance.rs index ce3d6ff8a8..47169f2132 100644 --- a/cli/tools/registry/provenance.rs +++ b/cli/tools/registry/provenance.rs @@ -229,16 +229,16 @@ impl Predicate { struct ProvenanceAttestation { #[serde(rename = "type")] _type: &'static str, - subject: Subject, + subject: Vec, predicate_type: &'static str, predicate: Predicate, } impl ProvenanceAttestation { - pub fn new_github_actions(subject: Subject) -> Self { + pub fn new_github_actions(subjects: Vec) -> Self { Self { _type: INTOTO_STATEMENT_TYPE, - subject, + subject: subjects, predicate_type: SLSA_PREDICATE_TYPE, predicate: Predicate::new_github_actions(), } @@ -296,7 +296,7 @@ pub struct ProvenanceBundle { pub async fn generate_provenance( http_client: &HttpClient, - subject: Subject, + subjects: Vec, ) -> Result { if !is_gha() { bail!("Automatic provenance is only available in GitHub Actions"); @@ -308,7 +308,7 @@ pub async fn generate_provenance( ); }; - let slsa = ProvenanceAttestation::new_github_actions(subject); + let slsa = ProvenanceAttestation::new_github_actions(subjects); let attestation = serde_json::to_string(&slsa)?; let bundle = attest(http_client, &attestation, INTOTO_PAYLOAD_TYPE).await?; @@ -738,8 +738,13 @@ mod tests { sha256: "yourmom".to_string(), }, }; - let slsa = ProvenanceAttestation::new_github_actions(subject); - assert_eq!(slsa.subject.name, "jsr:@divy/sdl2@0.0.1"); - assert_eq!(slsa.subject.digest.sha256, "yourmom"); + let slsa = ProvenanceAttestation::new_github_actions(vec![subject]); + assert_eq!( + slsa.subject.len(), + 1, + "Subject should be an array per the in-toto specification" + ); + assert_eq!(slsa.subject[0].name, "jsr:@divy/sdl2@0.0.1"); + assert_eq!(slsa.subject[0].digest.sha256, "yourmom"); } } diff --git a/cli/tools/registry/unfurl.rs b/cli/tools/registry/unfurl.rs index 2babedb367..5ec726a640 100644 --- a/cli/tools/registry/unfurl.rs +++ b/cli/tools/registry/unfurl.rs @@ -12,9 +12,10 @@ use deno_graph::DynamicTemplatePart; use deno_graph::ParserModuleAnalyzer; use deno_graph::TypeScriptReference; use deno_package_json::PackageJsonDepValue; +use deno_resolver::sloppy_imports::SloppyImportsResolutionMode; use deno_runtime::deno_node::is_builtin_node_module; -use crate::resolver::SloppyImportsResolver; +use crate::resolver::CliSloppyImportsResolver; #[derive(Debug, Clone)] pub enum SpecifierUnfurlerDiagnostic { @@ -42,14 +43,14 @@ impl SpecifierUnfurlerDiagnostic { } pub struct SpecifierUnfurler { - sloppy_imports_resolver: Option, + sloppy_imports_resolver: Option, workspace_resolver: WorkspaceResolver, bare_node_builtins: bool, } impl SpecifierUnfurler { pub fn new( - sloppy_imports_resolver: Option, + sloppy_imports_resolver: Option, workspace_resolver: WorkspaceResolver, bare_node_builtins: bool, ) -> Self { @@ -179,7 +180,7 @@ impl SpecifierUnfurler { let resolved = if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver { sloppy_imports_resolver - .resolve(&resolved, deno_graph::source::ResolutionMode::Execution) + .resolve(&resolved, SloppyImportsResolutionMode::Execution) .map(|res| res.into_specifier()) .unwrap_or(resolved) } else { @@ -203,7 +204,7 @@ impl SpecifierUnfurler { /// or `false` when the import was not analyzable. fn try_unfurl_dynamic_dep( &self, - module_url: &lsp_types::Url, + module_url: &ModuleSpecifier, text_info: &SourceTextInfo, dep: &deno_graph::DynamicDependencyDescriptor, text_changes: &mut Vec, @@ -388,6 +389,8 @@ fn to_range( mod tests { use std::sync::Arc; + use crate::resolver::SloppyImportsCachedFs; + use super::*; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; @@ -455,7 +458,9 @@ mod tests { ); let fs = Arc::new(RealFs); let unfurler = SpecifierUnfurler::new( - Some(SloppyImportsResolver::new(fs)), + Some(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( + fs, + ))), workspace_resolver, true, ); diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index ed3d94c846..a303046879 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -16,8 +16,6 @@ use deno_core::error::AnyError; use deno_core::futures::StreamExt; use deno_core::serde_json; use deno_core::unsync::spawn_blocking; -use deno_runtime::deno_permissions::Permissions; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use rustyline::error::ReadlineError; @@ -151,9 +149,7 @@ async fn read_eval_file( let specifier = deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?; - let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await?; + let file = file_fetcher.fetch_bypass_permissions(&specifier).await?; Ok(file.into_text_decoded()?.source) } @@ -166,9 +162,7 @@ pub async fn run( let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; let main_module = cli_options.resolve_main_module()?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.root_permissions_container()?; let npm_resolver = factory.npm_resolver().await?.clone(); let resolver = factory.resolver().await?.clone(); let file_fetcher = factory.file_fetcher()?; @@ -183,7 +177,7 @@ pub async fn run( .create_custom_worker( WorkerExecutionMode::Repl, main_module.clone(), - permissions, + permissions.clone(), vec![crate::ops::testing::deno_test::init_ops(test_event_sender)], Default::default(), ) @@ -195,7 +189,7 @@ pub async fn run( npm_resolver, resolver, worker, - main_module, + main_module.clone(), test_event_receiver, ) .await?; diff --git a/cli/tools/run/mod.rs b/cli/tools/run/mod.rs index 1964cfdd9a..152e2650bd 100644 --- a/cli/tools/run/mod.rs +++ b/cli/tools/run/mod.rs @@ -3,9 +3,8 @@ use std::io::Read; use std::sync::Arc; +use deno_config::deno_json::NodeModulesDirMode; use deno_core::error::AnyError; -use deno_runtime::deno_permissions::Permissions; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use crate::args::EvalFlags; @@ -61,12 +60,9 @@ pub async fn run_script( maybe_npm_install(&factory).await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let worker_factory = factory.create_cli_main_worker_factory().await?; let mut worker = worker_factory - .create_main_worker(mode, main_module, permissions) + .create_main_worker(mode, main_module.clone()) .await?; let exit_code = worker.run().await?; @@ -82,9 +78,6 @@ pub async fn run_from_stdin(flags: Arc) -> Result { let file_fetcher = factory.file_fetcher()?; let worker_factory = factory.create_cli_main_worker_factory().await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let mut source = Vec::new(); std::io::stdin().read_to_end(&mut source)?; // Save a fake file into file fetcher cache @@ -96,7 +89,7 @@ pub async fn run_from_stdin(flags: Arc) -> Result { }); let mut worker = worker_factory - .create_main_worker(WorkerExecutionMode::Run, main_module, permissions) + .create_main_worker(WorkerExecutionMode::Run, main_module.clone()) .await?; let exit_code = worker.run().await?; Ok(exit_code) @@ -130,13 +123,10 @@ async fn run_with_watch( let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let mut worker = factory .create_cli_main_worker_factory() .await? - .create_main_worker(mode, main_module, permissions) + .create_main_worker(mode, main_module.clone()) .await?; if watch_flags.hmr { @@ -180,12 +170,9 @@ pub async fn eval_command( source: source_code.into_bytes().into(), }); - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let worker_factory = factory.create_cli_main_worker_factory().await?; let mut worker = worker_factory - .create_main_worker(WorkerExecutionMode::Eval, main_module, permissions) + .create_main_worker(WorkerExecutionMode::Eval, main_module.clone()) .await?; let exit_code = worker.run().await?; Ok(exit_code) @@ -194,7 +181,9 @@ pub async fn eval_command( pub async fn maybe_npm_install(factory: &CliFactory) -> Result<(), AnyError> { // ensure an "npm install" is done if the user has explicitly // opted into using a managed node_modules directory - if factory.cli_options()?.node_modules_dir_enablement() == Some(true) { + if factory.cli_options()?.node_modules_dir()? + == Some(NodeModulesDirMode::Auto) + { if let Some(npm_resolver) = factory.npm_resolver().await?.as_managed() { npm_resolver.ensure_top_level_package_json_install().await?; } diff --git a/cli/tools/serve.rs b/cli/tools/serve.rs index 24666b8f64..4ce1cad6f2 100644 --- a/cli/tools/serve.rs +++ b/cli/tools/serve.rs @@ -5,8 +5,6 @@ use std::sync::Arc; use deno_core::error::AnyError; use deno_core::futures::TryFutureExt; use deno_core::ModuleSpecifier; -use deno_runtime::deno_permissions::Permissions; -use deno_runtime::deno_permissions::PermissionsContainer; use super::run::check_permission_before_script; use super::run::maybe_npm_install; @@ -45,15 +43,11 @@ pub async fn serve( maybe_npm_install(&factory).await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let worker_factory = factory.create_cli_main_worker_factory().await?; do_serve( worker_factory, - main_module, - permissions, + main_module.clone(), serve_flags.worker_count, false, ) @@ -63,7 +57,6 @@ pub async fn serve( async fn do_serve( worker_factory: CliMainWorkerFactory, main_module: ModuleSpecifier, - permissions: PermissionsContainer, worker_count: Option, hmr: bool, ) -> Result { @@ -74,7 +67,6 @@ async fn do_serve( worker_count, }, main_module.clone(), - permissions.clone(), ) .await?; let worker_count = match worker_count { @@ -90,15 +82,13 @@ async fn do_serve( for i in 0..extra_workers { let worker_factory = worker_factory.clone(); let main_module = main_module.clone(); - let permissions = permissions.clone(); let (tx, rx) = tokio::sync::oneshot::channel(); channels.push(rx); std::thread::Builder::new() .name(format!("serve-worker-{i}")) .spawn(move || { deno_runtime::tokio_util::create_and_run_current_thread(async move { - let result = - run_worker(i, worker_factory, main_module, permissions, hmr).await; + let result = run_worker(i, worker_factory, main_module, hmr).await; let _ = tx.send(result); }); })?; @@ -127,7 +117,6 @@ async fn run_worker( worker_count: usize, worker_factory: CliMainWorkerFactory, main_module: ModuleSpecifier, - permissions: PermissionsContainer, hmr: bool, ) -> Result { let mut worker = worker_factory @@ -137,7 +126,6 @@ async fn run_worker( worker_count: Some(worker_count), }, main_module, - permissions, ) .await?; if hmr { @@ -174,13 +162,9 @@ async fn serve_with_watch( maybe_npm_install(&factory).await?; let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); - - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); let worker_factory = factory.create_cli_main_worker_factory().await?; - do_serve(worker_factory, main_module, permissions, worker_count, hmr) + do_serve(worker_factory, main_module.clone(), worker_count, hmr) .await?; Ok(()) diff --git a/cli/tools/task.rs b/cli/tools/task.rs index 0110d17414..502b09d2c2 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -1,5 +1,24 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; +use std::collections::HashMap; +use std::collections::HashSet; +use std::path::Path; +use std::path::PathBuf; +use std::rc::Rc; +use std::sync::Arc; + +use deno_config::deno_json::Task; +use deno_config::workspace::TaskOrScript; +use deno_config::workspace::WorkspaceDirectory; +use deno_config::workspace::WorkspaceTasksConfig; +use deno_core::anyhow::anyhow; +use deno_core::anyhow::bail; +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_path_util::normalize_path; +use deno_task_shell::ShellCommand; + use crate::args::CliOptions; use crate::args::Flags; use crate::args::TaskFlags; @@ -8,28 +27,10 @@ use crate::factory::CliFactory; use crate::npm::CliNpmResolver; use crate::task_runner; use crate::util::fs::canonicalize_path; -use deno_config::deno_json::Task; -use deno_config::workspace::TaskOrScript; -use deno_config::workspace::WorkspaceDirectory; -use deno_config::workspace::WorkspaceTasksConfig; -use deno_core::anyhow::anyhow; -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::AnyError; -use deno_core::normalize_path; -use deno_task_shell::ShellCommand; -use std::borrow::Cow; -use std::collections::HashMap; -use std::collections::HashSet; -use std::path::Path; -use std::path::PathBuf; -use std::rc::Rc; -use std::sync::Arc; pub async fn execute_script( flags: Arc, task_flags: TaskFlags, - using_run: bool, ) -> Result { let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; @@ -62,7 +63,7 @@ pub async fn execute_script( &cli_options.start_dir, &tasks_config, )?; - return Ok(1); + return Ok(0); } }; @@ -95,12 +96,9 @@ pub async fn execute_script( .await } TaskOrScript::Script(scripts, _script) => { - // ensure the npm packages are installed if using a node_modules - // directory and managed resolver - if cli_options.has_node_modules_dir() { - if let Some(npm_resolver) = npm_resolver.as_managed() { - npm_resolver.ensure_top_level_package_json_install().await?; - } + // ensure the npm packages are installed if using a managed resolver + if let Some(npm_resolver) = npm_resolver.as_managed() { + npm_resolver.ensure_top_level_package_json_install().await?; } let cwd = match task_flags.cwd { @@ -142,7 +140,7 @@ pub async fn execute_script( } }, None => { - if using_run { + if task_flags.is_run { return Err(anyhow!("Task not found: {}", task_name)); } log::error!("Task not found: {}", task_name); @@ -184,19 +182,21 @@ async fn run_task(opts: RunTaskOptions<'_>) -> Result { &task_runner::get_script_with_args(script, cli_options.argv()), ); - task_runner::run_task(task_runner::RunTaskOptions { - task_name, - script, - cwd, - env_vars, - custom_commands, - init_cwd: opts.cli_options.initial_cwd(), - argv: cli_options.argv(), - root_node_modules_dir: npm_resolver - .root_node_modules_path() - .map(|p| p.as_path()), - }) - .await + Ok( + task_runner::run_task(task_runner::RunTaskOptions { + task_name, + script, + cwd, + env_vars, + custom_commands, + init_cwd: opts.cli_options.initial_cwd(), + argv: cli_options.argv(), + root_node_modules_dir: npm_resolver.root_node_modules_path(), + stdio: None, + }) + .await? + .exit_code, + ) } fn output_task(task_name: &str, script: &str) { diff --git a/cli/tools/test/fmt.rs b/cli/tools/test/fmt.rs index 1741550727..0f6a9ed2b4 100644 --- a/cli/tools/test/fmt.rs +++ b/cli/tools/test/fmt.rs @@ -318,15 +318,12 @@ pub const OP_DETAILS: phf::Map<&'static str, [&'static str; 2]> = phf_map! { "op_fs_chown_async" => ["change the owner of a file", "awaiting the result of a `Deno.chown` call"], "op_fs_copy_file_async" => ["copy a file", "awaiting the result of a `Deno.copyFile` call"], "op_fs_events_poll" => ["get the next file system event", "breaking out of a for await loop looping over `Deno.FsEvents`"], - "op_fs_fdatasync_async" => ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fdatasync` or `Deno.FsFile.syncData` call"], - "op_fs_file_stat_async" => ["get file metadata", "awaiting the result of a `Deno.fstat` or `Deno.FsFile.stat` call"], - "op_fs_flock_async_unstable" => ["lock a file", "awaiting the result of a `Deno.flock` call"], + "op_fs_file_sync_data_async" => ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.FsFile.prototype.syncData` call"], + "op_fs_file_stat_async" => ["get file metadata", "awaiting the result of a `Deno.FsFile.prototype.stat` call"], "op_fs_flock_async" => ["lock a file", "awaiting the result of a `Deno.FsFile.lock` call"], - "op_fs_fsync_async" => ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fsync` or `Deno.FsFile.sync` call"], - "op_fs_ftruncate_async" => ["truncate a file", "awaiting the result of a `Deno.ftruncate` or `Deno.FsFile.truncate` call"], - "op_fs_funlock_async_unstable" => ["unlock a file", "awaiting the result of a `Deno.funlock` call"], + "op_fs_file_sync_async" => ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.FsFile.sync` call"], + "op_fs_file_truncate_async" => ["truncate a file", "awaiting the result of a `Deno.FsFile.prototype.truncate` call"], "op_fs_funlock_async" => ["unlock a file", "awaiting the result of a `Deno.FsFile.unlock` call"], - "op_fs_futime_async" => ["change file timestamps", "awaiting the result of a `Deno.futime` or `Deno.FsFile.utime` call"], "op_fs_link_async" => ["create a hard link", "awaiting the result of a `Deno.link` call"], "op_fs_lstat_async" => ["get file metadata", "awaiting the result of a `Deno.lstat` call"], "op_fs_make_temp_dir_async" => ["create a temporary directory", "awaiting the result of a `Deno.makeTempDir` call"], @@ -340,7 +337,7 @@ pub const OP_DETAILS: phf::Map<&'static str, [&'static str; 2]> = phf_map! { "op_fs_realpath_async" => ["resolve a path", "awaiting the result of a `Deno.realpath` call"], "op_fs_remove_async" => ["remove a file or directory", "awaiting the result of a `Deno.remove` call"], "op_fs_rename_async" => ["rename a file or directory", "awaiting the result of a `Deno.rename` call"], - "op_fs_seek_async" => ["seek in a file", "awaiting the result of a `Deno.seek` or `Deno.FsFile.seek` call"], + "op_fs_seek_async" => ["seek in a file", "awaiting the result of a `Deno.FsFile.prototype.seek` call"], "op_fs_stat_async" => ["get file metadata", "awaiting the result of a `Deno.stat` call"], "op_fs_symlink_async" => ["create a symlink", "awaiting the result of a `Deno.symlink` call"], "op_fs_truncate_async" => ["truncate a file", "awaiting the result of a `Deno.truncate` call"], diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index 0dc2133502..e81abad0b2 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -9,21 +9,18 @@ use crate::display; use crate::factory::CliFactory; use crate::file_fetcher::File; use crate::file_fetcher::FileFetcher; -use crate::graph_container::MainModuleGraphContainer; use crate::graph_util::has_graph_root_local_dependent_changed; use crate::ops; +use crate::util::extract::extract_doc_tests; use crate::util::file_watcher; use crate::util::fs::collect_specifiers; use crate::util::path::get_extension; use crate::util::path::is_script_ext; -use crate::util::path::mapped_specifier_for_tsc; use crate::util::path::matches_pattern_or_exact_path; use crate::worker::CliMainWorkerFactory; use crate::worker::CoverageCollector; -use deno_ast::swc::common::comments::CommentKind; use deno_ast::MediaType; -use deno_ast::SourceRangedForSpanned; use deno_config::glob::FilePatterns; use deno_config::glob::WalkEntry; use deno_core::anyhow; @@ -56,6 +53,7 @@ use deno_runtime::deno_io::StdioPipe; use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::fmt_errors::format_js_error; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::worker::MainWorker; use deno_runtime::WorkerExecutionMode; @@ -150,6 +148,20 @@ pub enum TestMode { Both, } +impl TestMode { + /// Returns `true` if the test mode indicates that code snippet extraction is + /// needed. + fn needs_test_extraction(&self) -> bool { + matches!(self, Self::Documentation | Self::Both) + } + + /// Returns `true` if the test mode indicates that the test should be + /// type-checked and run. + fn needs_test_run(&self) -> bool { + matches!(self, Self::Executable | Self::Both) + } +} + #[derive(Clone, Debug, Default)] pub struct TestFilter { pub substring: Option, @@ -595,7 +607,7 @@ fn get_test_reporter(options: &TestSpecifiersOptions) -> Box { async fn configure_main_worker( worker_factory: Arc, specifier: &Url, - permissions: Permissions, + permissions_container: PermissionsContainer, worker_sender: TestEventWorkerSender, options: &TestSpecifierOptions, ) -> Result<(Option>, MainWorker), anyhow::Error> { @@ -603,7 +615,7 @@ async fn configure_main_worker( .create_custom_worker( WorkerExecutionMode::Test, specifier.clone(), - PermissionsContainer::new(permissions), + permissions_container, vec![ops::testing::deno_test::init_ops(worker_sender.sender)], Stdio { stdin: StdioPipe::inherit(), @@ -646,7 +658,7 @@ async fn configure_main_worker( /// both. pub async fn test_specifier( worker_factory: Arc, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, worker_sender: TestEventWorkerSender, fail_fast_tracker: FailFastTracker, @@ -658,7 +670,7 @@ pub async fn test_specifier( let (coverage_collector, mut worker) = configure_main_worker( worker_factory, &specifier, - permissions, + permissions_container, worker_sender, &options, ) @@ -1173,240 +1185,13 @@ async fn wait_for_activity_to_stabilize( }) } -fn extract_files_from_regex_blocks( - specifier: &ModuleSpecifier, - source: &str, - media_type: MediaType, - file_line_index: usize, - blocks_regex: &Regex, - lines_regex: &Regex, -) -> Result, AnyError> { - let files = blocks_regex - .captures_iter(source) - .filter_map(|block| { - block.get(1)?; - - let maybe_attributes: Option> = block - .get(1) - .map(|attributes| attributes.as_str().split(' ').collect()); - - let file_media_type = if let Some(attributes) = maybe_attributes { - if attributes.contains(&"ignore") { - return None; - } - - match attributes.first() { - Some(&"js") => MediaType::JavaScript, - Some(&"javascript") => MediaType::JavaScript, - Some(&"mjs") => MediaType::Mjs, - Some(&"cjs") => MediaType::Cjs, - Some(&"jsx") => MediaType::Jsx, - Some(&"ts") => MediaType::TypeScript, - Some(&"typescript") => MediaType::TypeScript, - Some(&"mts") => MediaType::Mts, - Some(&"cts") => MediaType::Cts, - Some(&"tsx") => MediaType::Tsx, - _ => MediaType::Unknown, - } - } else { - media_type - }; - - if file_media_type == MediaType::Unknown { - return None; - } - - let line_offset = source[0..block.get(0).unwrap().start()] - .chars() - .filter(|c| *c == '\n') - .count(); - - let line_count = block.get(0).unwrap().as_str().split('\n').count(); - - let body = block.get(2).unwrap(); - let text = body.as_str(); - - // TODO(caspervonb) generate an inline source map - let mut file_source = String::new(); - for line in lines_regex.captures_iter(text) { - let text = line.get(1).unwrap(); - writeln!(file_source, "{}", text.as_str()).unwrap(); - } - - let file_specifier = ModuleSpecifier::parse(&format!( - "{}${}-{}", - specifier, - file_line_index + line_offset + 1, - file_line_index + line_offset + line_count + 1, - )) - .unwrap(); - let file_specifier = - mapped_specifier_for_tsc(&file_specifier, file_media_type) - .map(|s| ModuleSpecifier::parse(&s).unwrap()) - .unwrap_or(file_specifier); - - Some(File { - specifier: file_specifier, - maybe_headers: None, - source: file_source.into_bytes().into(), - }) - }) - .collect(); - - Ok(files) -} - -fn extract_files_from_source_comments( - specifier: &ModuleSpecifier, - source: Arc, - media_type: MediaType, -) -> Result, AnyError> { - let parsed_source = deno_ast::parse_module(deno_ast::ParseParams { - specifier: specifier.clone(), - text: source, - media_type, - capture_tokens: false, - maybe_syntax: None, - scope_analysis: false, - })?; - let comments = parsed_source.comments().get_vec(); - let blocks_regex = lazy_regex::regex!(r"```([^\r\n]*)\r?\n([\S\s]*?)```"); - let lines_regex = lazy_regex::regex!(r"(?:\* ?)(?:\# ?)?(.*)"); - - let files = comments - .iter() - .filter(|comment| { - if comment.kind != CommentKind::Block || !comment.text.starts_with('*') { - return false; - } - - true - }) - .flat_map(|comment| { - extract_files_from_regex_blocks( - specifier, - &comment.text, - media_type, - parsed_source.text_info_lazy().line_index(comment.start()), - blocks_regex, - lines_regex, - ) - }) - .flatten() - .collect(); - - Ok(files) -} - -fn extract_files_from_fenced_blocks( - specifier: &ModuleSpecifier, - source: &str, - media_type: MediaType, -) -> Result, AnyError> { - // The pattern matches code blocks as well as anything in HTML comment syntax, - // but it stores the latter without any capturing groups. This way, a simple - // check can be done to see if a block is inside a comment (and skip typechecking) - // or not by checking for the presence of capturing groups in the matches. - let blocks_regex = - lazy_regex::regex!(r"(?s)|```([^\r\n]*)\r?\n([\S\s]*?)```"); - let lines_regex = lazy_regex::regex!(r"(?:\# ?)?(.*)"); - - extract_files_from_regex_blocks( - specifier, - source, - media_type, - /* file line index */ 0, - blocks_regex, - lines_regex, - ) -} - -async fn fetch_inline_files( - file_fetcher: &FileFetcher, - specifiers: Vec, -) -> Result, AnyError> { - let mut files = Vec::new(); - for specifier in specifiers { - let fetch_permissions = PermissionsContainer::allow_all(); - let file = file_fetcher - .fetch(&specifier, &fetch_permissions) - .await? - .into_text_decoded()?; - - let inline_files = if file.media_type == MediaType::Unknown { - extract_files_from_fenced_blocks( - &file.specifier, - &file.source, - file.media_type, - ) - } else { - extract_files_from_source_comments( - &file.specifier, - file.source, - file.media_type, - ) - }; - - files.extend(inline_files?); - } - - Ok(files) -} - -/// Type check a collection of module and document specifiers. -pub async fn check_specifiers( - file_fetcher: &FileFetcher, - main_graph_container: &Arc, - specifiers: Vec<(ModuleSpecifier, TestMode)>, -) -> Result<(), AnyError> { - let inline_files = fetch_inline_files( - file_fetcher, - specifiers - .iter() - .filter_map(|(specifier, mode)| { - if *mode != TestMode::Executable { - Some(specifier.clone()) - } else { - None - } - }) - .collect(), - ) - .await?; - - let mut module_specifiers = specifiers - .into_iter() - .filter_map(|(specifier, mode)| { - if mode != TestMode::Documentation { - Some(specifier) - } else { - None - } - }) - .collect::>(); - - if !inline_files.is_empty() { - module_specifiers - .extend(inline_files.iter().map(|file| file.specifier.clone())); - - for file in inline_files { - file_fetcher.insert_memory_files(file); - } - } - - main_graph_container - .check_specifiers(&module_specifiers) - .await?; - - Ok(()) -} - static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false); /// Test a collection of specifiers with test modes concurrently. async fn test_specifiers( worker_factory: Arc, permissions: &Permissions, + permission_desc_parser: &Arc, specifiers: Vec, options: TestSpecifiersOptions, ) -> Result<(), AnyError> { @@ -1434,14 +1219,17 @@ async fn test_specifiers( let join_handles = specifiers.into_iter().map(move |specifier| { let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permission_desc_parser.clone(), + permissions.clone(), + ); let worker_sender = test_event_sender_factory.worker(); let fail_fast_tracker = fail_fast_tracker.clone(); let specifier_options = options.specifier.clone(); spawn_blocking(move || { create_and_run_current_thread(test_specifier( worker_factory, - permissions, + permissions_container, specifier, worker_sender, fail_fast_tracker, @@ -1739,9 +1527,7 @@ async fn fetch_specifiers_with_test_mode( .collect::>(); for (specifier, mode) in &mut specifiers_with_mode { - let file = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) - .await?; + let file = file_fetcher.fetch_bypass_permissions(specifier).await?; let (media_type, _) = file.resolve_media_type_and_charset(); if matches!(media_type, MediaType::Unknown | MediaType::Dts) { @@ -1764,8 +1550,11 @@ pub async fn run_tests( // Various test files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?; + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let log_level = cli_options.log_level(); let members_with_test_options = @@ -1778,18 +1567,27 @@ pub async fn run_tests( ) .await?; - if !workspace_test_options.allow_none && specifiers_with_mode.is_empty() { + if !workspace_test_options.permit_no_files && specifiers_with_mode.is_empty() + { return Err(generic_error("No test modules found")); } + let doc_tests = get_doc_tests(&specifiers_with_mode, file_fetcher).await?; + let specifiers_for_typecheck_and_test = + get_target_specifiers(specifiers_with_mode, &doc_tests); + for doc_test in doc_tests { + file_fetcher.insert_memory_files(doc_test); + } + let main_graph_container = factory.main_module_graph_container().await?; - check_specifiers( - file_fetcher, - main_graph_container, - specifiers_with_mode.clone(), - ) - .await?; + // Typecheck + main_graph_container + .check_specifiers( + &specifiers_for_typecheck_and_test, + cli_options.ext_flag().as_ref(), + ) + .await?; if workspace_test_options.no_run { return Ok(()); @@ -1798,16 +1596,12 @@ pub async fn run_tests( let worker_factory = Arc::new(factory.create_cli_main_worker_factory().await?); + // Run tests test_specifiers( worker_factory, &permissions, - specifiers_with_mode - .into_iter() - .filter_map(|(s, m)| match m { - TestMode::Documentation => None, - _ => Some(s), - }) - .collect(), + permission_desc_parser, + specifiers_for_typecheck_and_test, TestSpecifiersOptions { cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err( |_| { @@ -1913,8 +1707,11 @@ pub async fn run_tests_with_watch( .flatten() .collect::>(); - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?; + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let graph = module_graph_creator .create_graph(graph_kind, test_modules) .await?; @@ -1939,8 +1736,6 @@ pub async fn run_tests_with_watch( test_modules.clone() }; - let worker_factory = - Arc::new(factory.create_cli_main_worker_factory().await?); let specifiers_with_mode = fetch_specifiers_with_test_mode( &cli_options, file_fetcher, @@ -1952,29 +1747,37 @@ pub async fn run_tests_with_watch( .filter(|(specifier, _)| test_modules_to_reload.contains(specifier)) .collect::>(); + let doc_tests = + get_doc_tests(&specifiers_with_mode, file_fetcher).await?; + let specifiers_for_typecheck_and_test = + get_target_specifiers(specifiers_with_mode, &doc_tests); + for doc_test in doc_tests { + file_fetcher.insert_memory_files(doc_test); + } + let main_graph_container = factory.main_module_graph_container().await?; - check_specifiers( - file_fetcher, - main_graph_container, - specifiers_with_mode.clone(), - ) - .await?; + + // Typecheck + main_graph_container + .check_specifiers( + &specifiers_for_typecheck_and_test, + cli_options.ext_flag().as_ref(), + ) + .await?; if workspace_test_options.no_run { return Ok(()); } + let worker_factory = + Arc::new(factory.create_cli_main_worker_factory().await?); + test_specifiers( worker_factory, &permissions, - specifiers_with_mode - .into_iter() - .filter_map(|(s, m)| match m { - TestMode::Documentation => None, - _ => Some(s), - }) - .collect(), + permission_desc_parser, + specifiers_for_typecheck_and_test, TestSpecifiersOptions { cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err( |_| { @@ -2009,6 +1812,38 @@ pub async fn run_tests_with_watch( Ok(()) } +/// Extracts doc tests from files specified by the given specifiers. +async fn get_doc_tests( + specifiers_with_mode: &[(Url, TestMode)], + file_fetcher: &FileFetcher, +) -> Result, AnyError> { + let specifiers_needing_extraction = specifiers_with_mode + .iter() + .filter(|(_, mode)| mode.needs_test_extraction()) + .map(|(s, _)| s); + + let mut doc_tests = Vec::new(); + for s in specifiers_needing_extraction { + let file = file_fetcher.fetch_bypass_permissions(s).await?; + doc_tests.extend(extract_doc_tests(file)?); + } + + Ok(doc_tests) +} + +/// Get a list of specifiers that we need to perform typecheck and run tests on. +/// The result includes "pseudo specifiers" for doc tests. +fn get_target_specifiers( + specifiers_with_mode: Vec<(Url, TestMode)>, + doc_tests: &[File], +) -> Vec { + specifiers_with_mode + .into_iter() + .filter_map(|(s, mode)| mode.needs_test_run().then_some(s)) + .chain(doc_tests.iter().map(|d| d.specifier.clone())) + .collect() +} + /// Tracks failures for the `--fail-fast` argument in /// order to tell when to stop running tests. #[derive(Clone, Default)] diff --git a/cli/tools/upgrade.rs b/cli/tools/upgrade.rs index db43b8be17..77a9f72b80 100644 --- a/cli/tools/upgrade.rs +++ b/cli/tools/upgrade.rs @@ -4,6 +4,7 @@ use crate::args::Flags; use crate::args::UpgradeFlags; +use crate::args::UPGRADE_USAGE; use crate::colors; use crate::factory::CliFactory; use crate::http_util::HttpClient; @@ -35,7 +36,7 @@ use std::time::Duration; const RELEASE_URL: &str = "https://github.com/denoland/deno/releases"; const CANARY_URL: &str = "https://dl.deno.land/canary"; -const RC_URL: &str = "https://dl.deno.land/release"; +const DL_RELEASE_URL: &str = "https://dl.deno.land/release"; pub static ARCHIVE_NAME: Lazy = Lazy::new(|| format!("deno-{}.zip", env!("TARGET"))); @@ -226,15 +227,70 @@ impl< } } -fn get_minor_version(version: &str) -> &str { - version.rsplitn(2, '.').collect::>()[1] +fn get_minor_version_blog_post_url(semver: &Version) -> String { + format!("https://deno.com/blog/v{}.{}", semver.major, semver.minor) } -fn print_release_notes(current_version: &str, new_version: &str) { - // TODO(bartlomieju): we might want to reconsider this one for RC releases. - // TODO(bartlomieju): also maybe just parse using `Version::standard` instead - // of using `get_minor_version`? - if get_minor_version(current_version) == get_minor_version(new_version) { +fn get_rc_version_blog_post_url(semver: &Version) -> String { + format!( + "https://deno.com/blog/v{}.{}-rc-{}", + semver.major, semver.minor, semver.pre[1] + ) +} + +async fn print_release_notes( + current_version: &str, + new_version: &str, + client: &HttpClient, +) { + let Ok(current_semver) = Version::parse_standard(current_version) else { + return; + }; + let Ok(new_semver) = Version::parse_standard(new_version) else { + return; + }; + + let is_switching_from_deno1_to_deno2 = + new_semver.major == 2 && current_semver.major == 1; + let is_deno_2_rc = new_semver.major == 2 + && new_semver.minor == 0 + && new_semver.patch == 0 + && new_semver.pre.first() == Some(&"rc".to_string()); + + if is_deno_2_rc || is_switching_from_deno1_to_deno2 { + log::info!( + "{}\n\n {}\n", + colors::gray("Migration guide:"), + colors::bold( + "https://docs.deno.com/runtime/manual/advanced/migrate_deprecations" + ) + ); + } + + if is_deno_2_rc { + log::info!( + "{}\n\n {}\n", + colors::gray("If you find a bug, please report to:"), + colors::bold("https://github.com/denoland/deno/issues/new") + ); + + // Check if there's blog post entry for this release + let blog_url_str = get_rc_version_blog_post_url(&new_semver); + let blog_url = Url::parse(&blog_url_str).unwrap(); + if client.download(blog_url).await.is_ok() { + log::info!( + "{}\n\n {}\n", + colors::gray("Blog post:"), + colors::bold(blog_url_str) + ); + } + return; + } + + let should_print = current_semver.major != new_semver.major + || current_semver.minor != new_semver.minor; + + if !should_print { return; } @@ -249,10 +305,7 @@ fn print_release_notes(current_version: &str, new_version: &str) { log::info!( "{}\n\n {}\n", colors::gray("Blog post:"), - colors::bold(format!( - "https://deno.com/blog/v{}", - get_minor_version(new_version) - )) + colors::bold(get_minor_version_blog_post_url(&new_semver)) ); } @@ -320,18 +373,25 @@ pub fn check_for_upgrades( log::info!( "{} {}", colors::green("A new canary release of Deno is available."), - colors::italic_gray("Run `deno upgrade --canary` to install it.") + colors::italic_gray("Run `deno upgrade canary` to install it.") ); } ReleaseChannel::Rc => { log::info!( "{} {}", colors::green("A new release candidate of Deno is available."), - colors::italic_gray("Run `deno upgrade --rc` to install it.") + colors::italic_gray("Run `deno upgrade rc` to install it.") + ); + } + ReleaseChannel::Lts => { + log::info!( + "{} {} → {} {}", + colors::green("A new LTS release of Deno is available:"), + colors::cyan(version::DENO_VERSION_INFO.deno), + colors::cyan(&upgrade_version), + colors::italic_gray("Run `deno upgrade lts` to install it.") ); } - // TODO(bartlomieju) - ReleaseChannel::Lts => unreachable!(), } update_checker.store_prompted(); @@ -369,7 +429,7 @@ async fn check_for_upgrades_for_lsp_with_provider( } match release_channel { - ReleaseChannel::Stable | ReleaseChannel::Rc => { + ReleaseChannel::Stable | ReleaseChannel::Rc | ReleaseChannel::Lts => { if let Ok(current) = Version::parse_standard(¤t_version) { if let Ok(latest) = Version::parse_standard(&latest_version.version_or_hash) @@ -389,9 +449,6 @@ async fn check_for_upgrades_for_lsp_with_provider( latest_version: latest_version.version_or_hash, is_canary: true, })), - - // TODO(bartlomieju) - ReleaseChannel::Lts => unreachable!(), } } @@ -512,7 +569,9 @@ pub async fn upgrade( print_release_notes( version::DENO_VERSION_INFO.deno, &selected_version_to_upgrade.version_or_hash, - ); + &client, + ) + .await; } drop(temp_dir); return Ok(()); @@ -520,6 +579,10 @@ pub async fn upgrade( let output_exe_path = full_path_output_flag.as_ref().unwrap_or(¤t_exe_path); + + #[cfg(windows)] + kill_running_deno_lsp_processes(); + let output_result = if *output_exe_path == current_exe_path { replace_exe(&new_exe_path, output_exe_path) } else { @@ -540,7 +603,9 @@ pub async fn upgrade( print_release_notes( version::DENO_VERSION_INFO.deno, &selected_version_to_upgrade.version_or_hash, - ); + &client, + ) + .await; } drop(temp_dir); // delete the temp dir @@ -566,6 +631,7 @@ impl RequestedVersion { }; let mut maybe_passed_version = upgrade_flags.version.clone(); + // TODO(bartlomieju): prefer flags first? This whole logic could be cleaned up... if let Some(val) = &upgrade_flags.version_or_hash_or_channel { if let Ok(channel) = ReleaseChannel::deserialize(&val.to_lowercase()) { // TODO(bartlomieju): print error if any other flags passed? @@ -591,12 +657,21 @@ impl RequestedVersion { let (channel, passed_version) = if is_canary { if !re_hash.is_match(&passed_version) { - bail!("Invalid commit hash passed"); + bail!( + "Invalid commit hash passed ({})\n\nPass a semver, or a full 40 character git commit hash, or a release channel name.\n\nUsage:\n{}", + colors::gray(passed_version), + UPGRADE_USAGE + ); } + (ReleaseChannel::Canary, passed_version) } else { let Ok(semver) = Version::parse_standard(&passed_version) else { - bail!("Invalid version passed"); + bail!( + "Invalid version passed ({})\n\nPass a semver, or a full 40 character git commit hash, or a release channel name.\n\nUsage:\n{}", + colors::gray(passed_version), + UPGRADE_USAGE + ); }; if semver.pre.contains(&"rc".to_string()) { @@ -623,65 +698,26 @@ fn select_specific_version_for_upgrade( version: String, force: bool, ) -> Result, AnyError> { - match release_channel { - ReleaseChannel::Stable => { - let current_is_passed = if version::DENO_VERSION_INFO.release_channel - != ReleaseChannel::Canary - { - version::DENO_VERSION_INFO.deno == version - } else { - false - }; - - if !force && current_is_passed { - log::info!( - "Version {} is already installed", - version::DENO_VERSION_INFO.deno - ); - return Ok(None); - } - - Ok(Some(AvailableVersion { - version_or_hash: version, - release_channel, - })) + let current_is_passed = match release_channel { + ReleaseChannel::Stable | ReleaseChannel::Rc | ReleaseChannel::Lts => { + version::DENO_VERSION_INFO.release_channel == release_channel + && version::DENO_VERSION_INFO.deno == version } - ReleaseChannel::Canary => { - let current_is_passed = version::DENO_VERSION_INFO.git_hash == version; - if !force && current_is_passed { - log::info!( - "Version {} is already installed", - version::DENO_VERSION_INFO.deno - ); - return Ok(None); - } + ReleaseChannel::Canary => version::DENO_VERSION_INFO.git_hash == version, + }; - Ok(Some(AvailableVersion { - version_or_hash: version, - release_channel, - })) - } - ReleaseChannel::Rc => { - let current_is_passed = version::DENO_VERSION_INFO.release_channel - == ReleaseChannel::Rc - && version::DENO_VERSION_INFO.deno == version; - - if !force && current_is_passed { - log::info!( - "Version {} is already installed", - version::DENO_VERSION_INFO.deno - ); - return Ok(None); - } - - Ok(Some(AvailableVersion { - version_or_hash: version, - release_channel, - })) - } - // TODO(bartlomieju) - ReleaseChannel::Lts => unreachable!(), + if !force && current_is_passed { + log::info!( + "Version {} is already installed", + version::DENO_VERSION_INFO.deno + ); + return Ok(None); } + + Ok(Some(AvailableVersion { + version_or_hash: version, + release_channel, + })) } async fn find_latest_version_to_upgrade( @@ -695,52 +731,28 @@ async fn find_latest_version_to_upgrade( ); let client = http_client_provider.get_or_create()?; - let latest_version_found = - fetch_latest_version(&client, release_channel, UpgradeCheckKind::Execution) - .await?; + + let latest_version_found = match fetch_latest_version( + &client, + release_channel, + UpgradeCheckKind::Execution, + ) + .await + { + Ok(v) => v, + Err(err) => { + if err.to_string().contains("Not found") { + bail!( + "No {} release available at the moment.", + release_channel.name() + ); + } else { + return Err(err); + } + } + }; let (maybe_newer_latest_version, current_version) = match release_channel { - ReleaseChannel::Stable => { - let current_version = version::DENO_VERSION_INFO.deno; - - // If the current binary is not a stable channel, we can skip - // computation if we're on a newer release - we're not. - if version::DENO_VERSION_INFO.release_channel != ReleaseChannel::Stable { - (Some(latest_version_found), current_version) - } else { - let current = Version::parse_standard(current_version).unwrap(); - let latest = - Version::parse_standard(&latest_version_found.version_or_hash) - .unwrap(); - let current_is_most_recent = current >= latest; - - if !force && current_is_most_recent { - (None, current_version) - } else { - (Some(latest_version_found), current_version) - } - } - } - ReleaseChannel::Rc => { - let current_version = version::DENO_VERSION_INFO.deno; - - // If the current binary is not an rc channel, we can skip - // computation if we're on a newer release - we're not. - if version::DENO_VERSION_INFO.release_channel != ReleaseChannel::Rc { - (Some(latest_version_found), current_version) - } else { - let current = Version::parse_standard(current_version).unwrap(); - let latest = - Version::parse_standard(&latest_version_found.version_or_hash) - .unwrap(); - let current_is_most_recent = current >= latest; - if !force && current_is_most_recent { - (None, current_version) - } else { - (Some(latest_version_found), current_version) - } - } - } ReleaseChannel::Canary => { let current_version = version::DENO_VERSION_INFO.git_hash; let current_is_most_recent = @@ -752,8 +764,26 @@ async fn find_latest_version_to_upgrade( (Some(latest_version_found), current_version) } } - // TODO(bartlomieju) - ReleaseChannel::Lts => unreachable!(), + ReleaseChannel::Stable | ReleaseChannel::Lts | ReleaseChannel::Rc => { + let current_version = version::DENO_VERSION_INFO.deno; + + // If the current binary is not the same channel, we can skip + // computation if we're on a newer release - we're not. + if version::DENO_VERSION_INFO.release_channel != release_channel { + (Some(latest_version_found), current_version) + } else { + let current = Version::parse_standard(current_version)?; + let latest = + Version::parse_standard(&latest_version_found.version_or_hash)?; + let current_is_most_recent = current >= latest; + + if !force && current_is_most_recent { + (None, current_version) + } else { + (Some(latest_version_found), current_version) + } + } + } }; log::info!(""); @@ -833,7 +863,7 @@ fn get_latest_version_url( Cow::Owned(format!("canary-{target_tuple}-latest.txt")) } ReleaseChannel::Rc => Cow::Borrowed("release-rc-latest.txt"), - _ => unreachable!(), + ReleaseChannel::Lts => Cow::Borrowed("release-lts-latest.txt"), }; let query_param = match check_kind { UpgradeCheckKind::Execution => "", @@ -860,12 +890,14 @@ fn get_download_url( format!("{}/download/v{}/{}", RELEASE_URL, version, *ARCHIVE_NAME) } ReleaseChannel::Rc => { - format!("{}/v{}/{}", RC_URL, version, *ARCHIVE_NAME) + format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME) } ReleaseChannel::Canary => { format!("{}/{}/{}", CANARY_URL, version, *ARCHIVE_NAME) } - ReleaseChannel::Lts => unreachable!(), + ReleaseChannel::Lts => { + format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME) + } }; Url::parse(&download_url).with_context(|| { @@ -885,7 +917,7 @@ async fn download_package( // text above which will stay alive after the progress bars are complete let progress = progress_bar.update(""); let maybe_bytes = client - .download_with_progress(download_url.clone(), None, &progress) + .download_with_progress_and_retries(download_url.clone(), None, &progress) .await .with_context(|| format!("Failed downloading {download_url}. The version you requested may not have been built for the current architecture."))?; Ok(maybe_bytes) @@ -938,6 +970,34 @@ fn check_windows_access_denied_error( }) } +#[cfg(windows)] +fn kill_running_deno_lsp_processes() { + // limit this to `deno lsp` invocations to avoid killing important programs someone might be running + let is_debug = log::log_enabled!(log::Level::Debug); + let get_pipe = || { + if is_debug { + std::process::Stdio::inherit() + } else { + std::process::Stdio::null() + } + }; + let _ = Command::new("powershell.exe") + .args([ + "-Command", + r#"Get-WmiObject Win32_Process | Where-Object { + $_.Name -eq 'deno.exe' -and + $_.CommandLine -match '^(?:\"[^\"]+\"|\S+)\s+lsp\b' +} | ForEach-Object { + if ($_.Terminate()) { + Write-Host 'Terminated:' $_.ProcessId + } +}"#, + ]) + .stdout(get_pipe()) + .stderr(get_pipe()) + .output(); +} + fn set_exe_permissions( current_exe_path: &Path, output_exe_path: &Path, @@ -972,8 +1032,13 @@ fn check_exe(exe_path: &Path) -> Result<(), AnyError> { .arg("-V") .stderr(std::process::Stdio::inherit()) .output()?; - assert!(output.status.success()); - Ok(()) + if !output.status.success() { + bail!( + "Failed to validate Deno executable. This may be because your OS is unsupported or the executable is corrupted" + ) + } else { + Ok(()) + } } #[derive(Debug)] @@ -1051,6 +1116,8 @@ mod test { use std::cell::RefCell; use std::rc::Rc; + use test_util::assert_contains; + use super::*; #[test] @@ -1149,6 +1216,27 @@ mod test { "5c69b4861b52ab406e73b9cd85c254f0505cb20f".to_string() ) ); + + upgrade_flags.version_or_hash_or_channel = + Some("5c69b4861b52a".to_string()); + let err = RequestedVersion::from_upgrade_flags(upgrade_flags.clone()) + .unwrap_err() + .to_string(); + assert_contains!(err, "Invalid version passed"); + assert_contains!( + err, + "Pass a semver, or a full 40 character git commit hash, or a release channel name." + ); + + upgrade_flags.version_or_hash_or_channel = Some("11.asd.1324".to_string()); + let err = RequestedVersion::from_upgrade_flags(upgrade_flags.clone()) + .unwrap_err() + .to_string(); + assert_contains!(err, "Invalid version passed"); + assert_contains!( + err, + "Pass a semver, or a full 40 character git commit hash, or a release channel name." + ); } #[test] @@ -1556,6 +1644,46 @@ mod test { ), "https://dl.deno.land/release-rc-latest.txt?lsp" ); + assert_eq!( + get_latest_version_url( + ReleaseChannel::Lts, + "x86_64-pc-windows-msvc", + UpgradeCheckKind::Lsp + ), + "https://dl.deno.land/release-lts-latest.txt?lsp" + ); + assert_eq!( + get_latest_version_url( + ReleaseChannel::Lts, + "aarch64-apple-darwin", + UpgradeCheckKind::Execution + ), + "https://dl.deno.land/release-lts-latest.txt" + ); + assert_eq!( + get_latest_version_url( + ReleaseChannel::Lts, + "aarch64-apple-darwin", + UpgradeCheckKind::Lsp + ), + "https://dl.deno.land/release-lts-latest.txt?lsp" + ); + assert_eq!( + get_latest_version_url( + ReleaseChannel::Lts, + "x86_64-pc-windows-msvc", + UpgradeCheckKind::Execution + ), + "https://dl.deno.land/release-lts-latest.txt" + ); + assert_eq!( + get_latest_version_url( + ReleaseChannel::Lts, + "x86_64-pc-windows-msvc", + UpgradeCheckKind::Lsp + ), + "https://dl.deno.land/release-lts-latest.txt?lsp" + ); } #[test] @@ -1687,4 +1815,31 @@ mod test { ); } } + + #[test] + fn blog_post_links() { + let version = Version::parse_standard("1.46.0").unwrap(); + assert_eq!( + get_minor_version_blog_post_url(&version), + "https://deno.com/blog/v1.46" + ); + + let version = Version::parse_standard("2.1.1").unwrap(); + assert_eq!( + get_minor_version_blog_post_url(&version), + "https://deno.com/blog/v2.1" + ); + + let version = Version::parse_standard("2.0.0-rc.0").unwrap(); + assert_eq!( + get_rc_version_blog_post_url(&version), + "https://deno.com/blog/v2.0-rc-0" + ); + + let version = Version::parse_standard("2.0.0-rc.2").unwrap(); + assert_eq!( + get_rc_version_blog_post_url(&version), + "https://deno.com/blog/v2.0-rc-2" + ); + } } diff --git a/cli/tools/vendor/analyze.rs b/cli/tools/vendor/analyze.rs deleted file mode 100644 index 3e5964be66..0000000000 --- a/cli/tools/vendor/analyze.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use deno_ast::swc::ast::ExportDefaultDecl; -use deno_ast::swc::ast::ExportSpecifier; -use deno_ast::swc::ast::ModuleExportName; -use deno_ast::swc::ast::NamedExport; -use deno_ast::swc::ast::Program; -use deno_ast::swc::visit::noop_visit_type; -use deno_ast::swc::visit::Visit; -use deno_ast::swc::visit::VisitWith; -use deno_ast::ParsedSource; - -/// Gets if the parsed source has a default export. -pub fn has_default_export(source: &ParsedSource) -> bool { - let mut visitor = DefaultExportFinder { - has_default_export: false, - }; - let program = source.program(); - let program: &Program = &program; - program.visit_with(&mut visitor); - visitor.has_default_export -} - -struct DefaultExportFinder { - has_default_export: bool, -} - -impl Visit for DefaultExportFinder { - noop_visit_type!(); - - fn visit_export_default_decl(&mut self, _: &ExportDefaultDecl) { - self.has_default_export = true; - } - - fn visit_named_export(&mut self, named_export: &NamedExport) { - if named_export - .specifiers - .iter() - .any(export_specifier_has_default) - { - self.has_default_export = true; - } - } -} - -fn export_specifier_has_default(s: &ExportSpecifier) -> bool { - match s { - ExportSpecifier::Default(_) => true, - ExportSpecifier::Namespace(_) => false, - ExportSpecifier::Named(named) => { - let export_name = named.exported.as_ref().unwrap_or(&named.orig); - - match export_name { - ModuleExportName::Str(_) => false, - ModuleExportName::Ident(ident) => &*ident.sym == "default", - } - } - } -} - -#[cfg(test)] -mod test { - use deno_ast::MediaType; - use deno_ast::ModuleSpecifier; - use deno_ast::ParseParams; - use deno_ast::ParsedSource; - - use super::has_default_export; - - #[test] - fn has_default_when_export_default_decl() { - let parsed_source = parse_module("export default class Class {}"); - assert!(has_default_export(&parsed_source)); - } - - #[test] - fn has_default_when_named_export() { - let parsed_source = parse_module("export {default} from './test.ts';"); - assert!(has_default_export(&parsed_source)); - } - - #[test] - fn has_default_when_named_export_alias() { - let parsed_source = - parse_module("export {test as default} from './test.ts';"); - assert!(has_default_export(&parsed_source)); - } - - #[test] - fn not_has_default_when_named_export_not_exported() { - let parsed_source = - parse_module("export {default as test} from './test.ts';"); - assert!(!has_default_export(&parsed_source)); - } - - #[test] - fn not_has_default_when_not() { - let parsed_source = parse_module("export {test} from './test.ts'; export class Test{} export * from './test';"); - assert!(!has_default_export(&parsed_source)); - } - - fn parse_module(text: &str) -> ParsedSource { - deno_ast::parse_module(ParseParams { - specifier: ModuleSpecifier::parse("file:///mod.ts").unwrap(), - capture_tokens: false, - maybe_syntax: None, - media_type: MediaType::TypeScript, - scope_analysis: false, - text: text.into(), - }) - .unwrap() - } -} diff --git a/cli/tools/vendor/build.rs b/cli/tools/vendor/build.rs deleted file mode 100644 index a4424e3f32..0000000000 --- a/cli/tools/vendor/build.rs +++ /dev/null @@ -1,1330 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::fmt::Write as _; -use std::path::Path; -use std::sync::Arc; - -use deno_ast::ModuleSpecifier; -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::AnyError; -use deno_core::futures::future::LocalBoxFuture; -use deno_graph::source::ResolutionMode; -use deno_graph::JsModule; -use deno_graph::Module; -use deno_graph::ModuleGraph; -use deno_runtime::deno_fs; -use import_map::ImportMap; -use import_map::SpecifierMap; - -use crate::args::JsxImportSourceConfig; -use crate::cache::ParsedSourceCache; -use crate::graph_util; -use crate::tools::vendor::import_map::BuildImportMapInput; - -use super::analyze::has_default_export; -use super::import_map::build_import_map; -use super::mappings::Mappings; -use super::mappings::ProxiedModule; -use super::specifiers::is_remote_specifier; - -/// Allows substituting the environment for testing purposes. -pub trait VendorEnvironment { - fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError>; - fn write_file(&self, file_path: &Path, bytes: &[u8]) -> Result<(), AnyError>; -} - -pub struct RealVendorEnvironment; - -impl VendorEnvironment for RealVendorEnvironment { - fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError> { - Ok(std::fs::create_dir_all(dir_path)?) - } - - fn write_file(&self, file_path: &Path, bytes: &[u8]) -> Result<(), AnyError> { - std::fs::write(file_path, bytes) - .with_context(|| format!("Failed writing {}", file_path.display())) - } -} - -type BuildGraphFuture = LocalBoxFuture<'static, Result>; - -pub struct BuildInput< - 'a, - TBuildGraphFn: FnOnce(Vec) -> BuildGraphFuture, - TEnvironment: VendorEnvironment, -> { - pub entry_points: Vec, - pub build_graph: TBuildGraphFn, - pub parsed_source_cache: &'a ParsedSourceCache, - pub output_dir: &'a Path, - pub maybe_original_import_map: Option<&'a ImportMap>, - pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>, - pub resolver: &'a dyn deno_graph::source::Resolver, - pub environment: &'a TEnvironment, -} - -pub struct BuildOutput { - pub vendored_count: usize, - pub graph: ModuleGraph, -} - -/// Vendors remote modules and returns how many were vendored. -pub async fn build< - TBuildGraphFn: FnOnce(Vec) -> BuildGraphFuture, - TEnvironment: VendorEnvironment, ->( - input: BuildInput<'_, TBuildGraphFn, TEnvironment>, -) -> Result { - let BuildInput { - mut entry_points, - build_graph, - parsed_source_cache, - output_dir, - maybe_original_import_map, - maybe_jsx_import_source, - resolver, - environment, - } = input; - assert!(output_dir.is_absolute()); - let output_dir_specifier = - ModuleSpecifier::from_directory_path(output_dir).unwrap(); - - if let Some(original_im) = &maybe_original_import_map { - validate_original_import_map(original_im, &output_dir_specifier)?; - } - - // add the jsx import source to the entry points to ensure it is always vendored - if let Some(jsx_import_source) = maybe_jsx_import_source { - if let Some(specifier_text) = jsx_import_source.maybe_specifier_text() { - if let Ok(specifier) = resolver.resolve( - &specifier_text, - &deno_graph::Range { - specifier: jsx_import_source.base_url.clone(), - start: deno_graph::Position::zeroed(), - end: deno_graph::Position::zeroed(), - }, - ResolutionMode::Execution, - ) { - entry_points.push(specifier); - } - } - } - - let graph = build_graph(entry_points).await?; - - // surface any errors - let real_fs = Arc::new(deno_fs::RealFs) as Arc; - graph_util::graph_valid( - &graph, - &real_fs, - &graph.roots.iter().cloned().collect::>(), - graph_util::GraphValidOptions { - is_vendoring: true, - check_js: true, - follow_type_only: true, - exit_lockfile_errors: true, - }, - )?; - - // figure out how to map remote modules to local - let all_modules = graph.modules().collect::>(); - let remote_modules = all_modules - .iter() - .filter(|m| is_remote_specifier(m.specifier())) - .copied() - .collect::>(); - let mappings = - Mappings::from_remote_modules(&graph, &remote_modules, output_dir)?; - - // write out all the files - for module in &remote_modules { - let source = match module { - Module::Js(module) => &module.source, - Module::Json(module) => &module.source, - Module::Node(_) | Module::Npm(_) | Module::External(_) => continue, - }; - let specifier = module.specifier(); - let local_path = mappings - .proxied_path(specifier) - .unwrap_or_else(|| mappings.local_path(specifier)); - - environment.create_dir_all(local_path.parent().unwrap())?; - environment.write_file(&local_path, source.as_bytes())?; - } - - // write out the proxies - for (specifier, proxied_module) in mappings.proxied_modules() { - let proxy_path = mappings.local_path(specifier); - let module = graph.get(specifier).unwrap().js().unwrap(); - let text = - build_proxy_module_source(module, proxied_module, parsed_source_cache)?; - - environment.write_file(&proxy_path, text.as_bytes())?; - } - - // create the import map if necessary - if !remote_modules.is_empty() { - let import_map_path = output_dir.join("import_map.json"); - let import_map_text = build_import_map(BuildImportMapInput { - base_dir: &output_dir_specifier, - graph: &graph, - modules: &all_modules, - mappings: &mappings, - maybe_original_import_map, - maybe_jsx_import_source, - resolver, - parsed_source_cache, - })?; - environment.write_file(&import_map_path, import_map_text.as_bytes())?; - } - - Ok(BuildOutput { - vendored_count: remote_modules.len(), - graph, - }) -} - -fn validate_original_import_map( - import_map: &ImportMap, - output_dir: &ModuleSpecifier, -) -> Result<(), AnyError> { - fn validate_imports( - imports: &SpecifierMap, - output_dir: &ModuleSpecifier, - ) -> Result<(), AnyError> { - for entry in imports.entries() { - if let Some(value) = entry.value { - if value.as_str().starts_with(output_dir.as_str()) { - bail!( - "Providing an existing import map with entries for the output directory is not supported (\"{}\": \"{}\").", - entry.raw_key, - entry.raw_value.unwrap_or(""), - ); - } - } - } - Ok(()) - } - - validate_imports(import_map.imports(), output_dir)?; - - for scope in import_map.scopes() { - if scope.key.starts_with(output_dir.as_str()) { - bail!( - "Providing an existing import map with a scope for the output directory is not supported (\"{}\").", - scope.raw_key, - ); - } - validate_imports(scope.imports, output_dir)?; - } - - Ok(()) -} - -fn build_proxy_module_source( - module: &JsModule, - proxied_module: &ProxiedModule, - parsed_source_cache: &ParsedSourceCache, -) -> Result { - let mut text = String::new(); - writeln!( - text, - "// @deno-types=\"{}\"", - proxied_module.declaration_specifier - ) - .unwrap(); - - let relative_specifier = format!( - "./{}", - proxied_module - .output_path - .file_name() - .unwrap() - .to_string_lossy() - ); - - // for simplicity, always include the `export *` statement as it won't error - // even when the module does not contain a named export - writeln!(text, "export * from \"{relative_specifier}\";").unwrap(); - - // add a default export if one exists in the module - let parsed_source = - parsed_source_cache.get_parsed_source_from_js_module(module)?; - if has_default_export(&parsed_source) { - writeln!(text, "export {{ default }} from \"{relative_specifier}\";") - .unwrap(); - } - - Ok(text) -} - -#[cfg(test)] -mod test { - use crate::args::JsxImportSourceConfig; - use crate::tools::vendor::test::VendorTestBuilder; - use deno_core::serde_json::json; - use pretty_assertions::assert_eq; - - #[tokio::test] - async fn no_remote_modules() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", ""); - }) - .build() - .await - .unwrap(); - - assert_eq!(output.import_map, None,); - assert_eq!(output.files, vec![],); - } - - #[tokio::test] - async fn local_specifiers_to_remote() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - concat!( - r#"import "https://localhost/mod.ts";"#, - r#"import "https://localhost/other.ts?test";"#, - r#"import "https://localhost/redirect.ts";"#, - ), - ) - .add("https://localhost/mod.ts", "export class Mod {}") - .add("https://localhost/other.ts?test", "export class Other {}") - .add_redirect( - "https://localhost/redirect.ts", - "https://localhost/mod.ts", - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/other.ts?test": "./localhost/other.ts", - "https://localhost/redirect.ts": "./localhost/mod.ts", - "https://localhost/": "./localhost/", - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/mod.ts", "export class Mod {}"), - ("/vendor/localhost/other.ts", "export class Other {}"), - ]), - ); - } - - #[tokio::test] - async fn remote_specifiers() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - concat!( - r#"import "https://localhost/mod.ts";"#, - r#"import "https://other/mod.ts";"#, - ), - ) - .add( - "https://localhost/mod.ts", - concat!( - "export * from './other.ts';", - "export * from './redirect.ts';", - "export * from '/absolute.ts';", - ), - ) - .add("https://localhost/other.ts", "export class Other {}") - .add_redirect( - "https://localhost/redirect.ts", - "https://localhost/other.ts", - ) - .add("https://localhost/absolute.ts", "export class Absolute {}") - .add("https://other/mod.ts", "export * from './sub/mod.ts';") - .add( - "https://other/sub/mod.ts", - concat!( - "export * from '../sub2/mod.ts';", - "export * from '../sub2/other?asdf';", - // reference a path on a different origin - "export * from 'https://localhost/other.ts';", - "export * from 'https://localhost/redirect.ts';", - ), - ) - .add("https://other/sub2/mod.ts", "export class Mod {}") - .add_with_headers( - "https://other/sub2/other?asdf", - "export class Other {}", - &[("content-type", "application/javascript")], - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/", - "https://localhost/redirect.ts": "./localhost/other.ts", - "https://other/": "./other/", - }, - "scopes": { - "./localhost/": { - "./localhost/redirect.ts": "./localhost/other.ts", - "/absolute.ts": "./localhost/absolute.ts", - }, - "./other/": { - "./other/sub2/other?asdf": "./other/sub2/other.js" - } - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/absolute.ts", "export class Absolute {}"), - ( - "/vendor/localhost/mod.ts", - concat!( - "export * from './other.ts';", - "export * from './redirect.ts';", - "export * from '/absolute.ts';", - ) - ), - ("/vendor/localhost/other.ts", "export class Other {}"), - ("/vendor/other/mod.ts", "export * from './sub/mod.ts';"), - ( - "/vendor/other/sub/mod.ts", - concat!( - "export * from '../sub2/mod.ts';", - "export * from '../sub2/other?asdf';", - "export * from 'https://localhost/other.ts';", - "export * from 'https://localhost/redirect.ts';", - ) - ), - ("/vendor/other/sub2/mod.ts", "export class Mod {}"), - ("/vendor/other/sub2/other.js", "export class Other {}"), - ]), - ); - } - - #[tokio::test] - async fn remote_redirect_entrypoint() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - concat!( - "import * as test from 'https://x.nest.land/Yenv@1.0.0/mod.ts';\n", - "console.log(test)", - ), - ) - .add_redirect("https://x.nest.land/Yenv@1.0.0/mod.ts", "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts") - .add( - "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts", - "export * from './src/mod.ts'", - ) - .add( - "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/src/mod.ts", - "export class Test {}", - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://x.nest.land/Yenv@1.0.0/mod.ts": "./arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts", - "https://arweave.net/": "./arweave.net/" - }, - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts", "export * from './src/mod.ts'"), - ( - "/vendor/arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/src/mod.ts", - "export class Test {}", - ), - ]), - ); - } - - #[tokio::test] - async fn same_target_filename_specifiers() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - concat!( - r#"import "https://localhost/MOD.TS";"#, - r#"import "https://localhost/mod.TS";"#, - r#"import "https://localhost/mod.ts";"#, - r#"import "https://localhost/mod.ts?test";"#, - r#"import "https://localhost/CAPS.TS";"#, - ), - ) - .add("https://localhost/MOD.TS", "export class Mod {}") - .add("https://localhost/mod.TS", "export class Mod2 {}") - .add("https://localhost/mod.ts", "export class Mod3 {}") - .add("https://localhost/mod.ts?test", "export class Mod4 {}") - .add("https://localhost/CAPS.TS", "export class Caps {}"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/mod.TS": "./localhost/mod_2.TS", - "https://localhost/mod.ts": "./localhost/mod_3.ts", - "https://localhost/mod.ts?test": "./localhost/mod_4.ts", - "https://localhost/": "./localhost/", - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/CAPS.TS", "export class Caps {}"), - ("/vendor/localhost/MOD.TS", "export class Mod {}"), - ("/vendor/localhost/mod_2.TS", "export class Mod2 {}"), - ("/vendor/localhost/mod_3.ts", "export class Mod3 {}"), - ("/vendor/localhost/mod_4.ts", "export class Mod4 {}"), - ]), - ); - } - - #[tokio::test] - async fn multiple_entrypoints() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .add_entry_point("/test.deps.ts") - .with_loader(|loader| { - loader - .add("/mod.ts", r#"import "https://localhost/mod.ts";"#) - .add( - "/test.deps.ts", - r#"export * from "https://localhost/test.ts";"#, - ) - .add("https://localhost/mod.ts", "export class Mod {}") - .add("https://localhost/test.ts", "export class Test {}"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/", - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/mod.ts", "export class Mod {}"), - ("/vendor/localhost/test.ts", "export class Test {}"), - ]), - ); - } - - #[tokio::test] - async fn json_module() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - r#"import data from "https://localhost/data.json" assert { type: "json" };"#, - ) - .add("https://localhost/data.json", "{ \"a\": \"b\" }"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/" - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[("/vendor/localhost/data.json", "{ \"a\": \"b\" }"),]), - ); - } - - #[tokio::test] - async fn data_urls() { - let mut builder = VendorTestBuilder::with_default_setup(); - - let mod_file_text = r#"import * as b from "data:application/typescript,export%20*%20from%20%22https://localhost/mod.ts%22;";"#; - - let output = builder - .with_loader(|loader| { - loader - .add("/mod.ts", mod_file_text) - .add("https://localhost/mod.ts", "export class Example {}"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/" - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[("/vendor/localhost/mod.ts", "export class Example {}"),]), - ); - } - - #[tokio::test] - async fn x_typescript_types_no_default() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add("/mod.ts", r#"import "https://localhost/mod.js";"#) - .add_with_headers( - "https://localhost/mod.js", - "export class Mod {}", - &[("x-typescript-types", "https://localhost/mod.d.ts")], - ) - .add("https://localhost/mod.d.ts", "export class Mod {}"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/" - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/mod.d.ts", "export class Mod {}"), - ( - "/vendor/localhost/mod.js", - concat!( - "// @deno-types=\"https://localhost/mod.d.ts\"\n", - "export * from \"./mod.proxied.js\";\n" - ) - ), - ("/vendor/localhost/mod.proxied.js", "export class Mod {}"), - ]), - ); - } - - #[tokio::test] - async fn x_typescript_types_default_export() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add("/mod.ts", r#"import "https://localhost/mod.js";"#) - .add_with_headers( - "https://localhost/mod.js", - "export default class Mod {}", - &[("x-typescript-types", "https://localhost/mod.d.ts")], - ) - .add("https://localhost/mod.d.ts", "export default class Mod {}"); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/" - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/mod.d.ts", "export default class Mod {}"), - ( - "/vendor/localhost/mod.js", - concat!( - "// @deno-types=\"https://localhost/mod.d.ts\"\n", - "export * from \"./mod.proxied.js\";\n", - "export { default } from \"./mod.proxied.js\";\n", - ) - ), - ( - "/vendor/localhost/mod.proxied.js", - "export default class Mod {}" - ), - ]), - ); - } - - #[tokio::test] - async fn subdir() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - r#"import "http://localhost:4545/sub/logger/mod.ts?testing";"#, - ) - .add( - "http://localhost:4545/sub/logger/mod.ts?testing", - "export * from './logger.ts?test';", - ) - .add( - "http://localhost:4545/sub/logger/logger.ts?test", - "export class Logger {}", - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "http://localhost:4545/sub/logger/mod.ts?testing": "./localhost_4545/sub/logger/mod.ts", - "http://localhost:4545/": "./localhost_4545/", - }, - "scopes": { - "./localhost_4545/": { - "./localhost_4545/sub/logger/logger.ts?test": "./localhost_4545/sub/logger/logger.ts" - } - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ( - "/vendor/localhost_4545/sub/logger/logger.ts", - "export class Logger {}", - ), - ( - "/vendor/localhost_4545/sub/logger/mod.ts", - "export * from './logger.ts?test';" - ), - ]), - ); - } - - #[tokio::test] - async fn same_origin_absolute_with_redirect() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add( - "/mod.ts", - r#"import "https://localhost/subdir/sub/mod.ts";"#, - ) - .add( - "https://localhost/subdir/sub/mod.ts", - "import 'https://localhost/std/hash/mod.ts'", - ) - .add_redirect( - "https://localhost/std/hash/mod.ts", - "https://localhost/std@0.1.0/hash/mod.ts", - ) - .add( - "https://localhost/std@0.1.0/hash/mod.ts", - "export class Test {}", - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/std/hash/mod.ts": "./localhost/std@0.1.0/hash/mod.ts", - "https://localhost/": "./localhost/", - }, - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ( - "/vendor/localhost/std@0.1.0/hash/mod.ts", - "export class Test {}" - ), - ( - "/vendor/localhost/subdir/sub/mod.ts", - "import 'https://localhost/std/hash/mod.ts'" - ), - ]), - ); - } - - #[tokio::test] - async fn remote_relative_specifier_with_scheme_like_folder_name() { - let mut builder = VendorTestBuilder::with_default_setup(); - let output = builder - .with_loader(|loader| { - loader - .add("/mod.ts", "import 'https://localhost/mod.ts';") - .add( - "https://localhost/mod.ts", - "import './npm:test@1.0.0/test/test!cjs?test';import './npm:test@1.0.0/mod.ts';", - ) - .add( - "https://localhost/npm:test@1.0.0/mod.ts", - "console.log(4);", - ) - .add_with_headers( - "https://localhost/npm:test@1.0.0/test/test!cjs?test", - "console.log(5);", - &[("content-type", "application/javascript")], - ); - }) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/" - }, - "scopes": { - "./localhost/": { - "./localhost/npm:test@1.0.0/mod.ts": "./localhost/npm_test@1.0.0/mod.ts", - "./localhost/npm:test@1.0.0/test/test!cjs?test": "./localhost/npm_test@1.0.0/test/test!cjs.js", - "./localhost/npm_test@1.0.0/test/test!cjs?test": "./localhost/npm_test@1.0.0/test/test!cjs.js" - } - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ( - "/vendor/localhost/mod.ts", - "import './npm:test@1.0.0/test/test!cjs?test';import './npm:test@1.0.0/mod.ts';" - ), - ("/vendor/localhost/npm_test@1.0.0/mod.ts", "console.log(4);"), - ( - "/vendor/localhost/npm_test@1.0.0/test/test!cjs.js", - "console.log(5);" - ), - ]), - ); - } - - #[tokio::test] - async fn existing_import_map_basic() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map2.json"); - original_import_map - .imports_mut() - .append( - "https://localhost/mod.ts".to_string(), - "./local_vendor/mod.ts".to_string(), - ) - .unwrap(); - let local_vendor_scope = original_import_map - .get_or_append_scope_mut("./local_vendor/") - .unwrap(); - local_vendor_scope - .append( - "https://localhost/logger.ts".to_string(), - "./local_vendor/logger.ts".to_string(), - ) - .unwrap(); - local_vendor_scope - .append( - "/console_logger.ts".to_string(), - "./local_vendor/console_logger.ts".to_string(), - ) - .unwrap(); - - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'https://localhost/mod.ts'; import 'https://localhost/other.ts';"); - loader.add("/local_vendor/mod.ts", "import 'https://localhost/logger.ts'; import '/console_logger.ts'; console.log(5);"); - loader.add("/local_vendor/logger.ts", "export class Logger {}"); - loader.add("/local_vendor/console_logger.ts", "export class ConsoleLogger {}"); - loader.add("https://localhost/mod.ts", "console.log(6);"); - loader.add("https://localhost/other.ts", "import './mod.ts';"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/mod.ts": "../local_vendor/mod.ts", - "https://localhost/": "./localhost/" - }, - "scopes": { - "../local_vendor/": { - "https://localhost/logger.ts": "../local_vendor/logger.ts", - "/console_logger.ts": "../local_vendor/console_logger.ts", - }, - "./localhost/": { - "./localhost/mod.ts": "../local_vendor/mod.ts", - }, - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[("/vendor/localhost/other.ts", "import './mod.ts';")]), - ); - } - - #[tokio::test] - async fn existing_import_map_remote_dep_bare_specifier() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map2.json"); - original_import_map - .imports_mut() - .append( - "twind".to_string(), - "https://localhost/twind.ts".to_string(), - ) - .unwrap(); - - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'https://remote/mod.ts';"); - loader.add("https://remote/mod.ts", "import 'twind';"); - loader.add("https://localhost/twind.ts", "export class Test {}"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/", - "https://remote/": "./remote/" - }, - "scopes": { - "./remote/": { - "twind": "./localhost/twind.ts" - }, - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/twind.ts", "export class Test {}"), - ("/vendor/remote/mod.ts", "import 'twind';"), - ]), - ); - } - - #[tokio::test] - async fn existing_import_map_mapped_bare_specifier() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - let imports = original_import_map.imports_mut(); - imports - .append("$fresh".to_string(), "https://localhost/fresh".to_string()) - .unwrap(); - imports - .append("std/".to_string(), "https://deno.land/std/".to_string()) - .unwrap(); - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'std/mod.ts'; import '$fresh';"); - loader.add("https://deno.land/std/mod.ts", "export function test() {}"); - loader.add_with_headers( - "https://localhost/fresh", - "export function fresh() {}", - &[("content-type", "application/typescript")], - ); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://deno.land/": "./deno.land/", - "https://localhost/": "./localhost/", - "$fresh": "./localhost/fresh.ts", - "std/mod.ts": "./deno.land/std/mod.ts", - }, - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/deno.land/std/mod.ts", "export function test() {}"), - ("/vendor/localhost/fresh.ts", "export function fresh() {}") - ]), - ); - } - - #[tokio::test] - async fn existing_import_map_remote_absolute_specifier_local() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - original_import_map - .imports_mut() - .append( - "https://localhost/logger.ts?test".to_string(), - "./local/logger.ts".to_string(), - ) - .unwrap(); - - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'https://localhost/mod.ts'; import 'https://localhost/logger.ts?test';"); - loader.add("/local/logger.ts", "export class Logger {}"); - // absolute specifier in a remote module that will point at ./local/logger.ts - loader.add("https://localhost/mod.ts", "import '/logger.ts?test';"); - loader.add("https://localhost/logger.ts?test", "export class Logger {}"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/logger.ts?test": "../local/logger.ts", - "https://localhost/": "./localhost/", - }, - "scopes": { - "./localhost/": { - "/logger.ts?test": "../local/logger.ts", - }, - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[("/vendor/localhost/mod.ts", "import '/logger.ts?test';")]), - ); - } - - #[tokio::test] - async fn existing_import_map_imports_output_dir() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - original_import_map - .imports_mut() - .append( - "std/mod.ts".to_string(), - "./vendor/deno.land/std/mod.ts".to_string(), - ) - .unwrap(); - let err = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'std/mod.ts';"); - loader.add("/vendor/deno.land/std/mod.ts", "export function f() {}"); - loader.add("https://deno.land/std/mod.ts", "export function f() {}"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .err() - .unwrap(); - - assert_eq!( - err.to_string(), - concat!( - "Providing an existing import map with entries for the output ", - "directory is not supported ", - "(\"std/mod.ts\": \"./vendor/deno.land/std/mod.ts\").", - ) - ); - } - - #[tokio::test] - async fn existing_import_map_scopes_entry_output_dir() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - let scopes = original_import_map - .get_or_append_scope_mut("./other/") - .unwrap(); - scopes - .append("/mod.ts".to_string(), "./vendor/mod.ts".to_string()) - .unwrap(); - let err = builder - .with_loader(|loader| { - loader.add("/mod.ts", "console.log(5);"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .err() - .unwrap(); - - assert_eq!( - err.to_string(), - concat!( - "Providing an existing import map with entries for the output ", - "directory is not supported ", - "(\"/mod.ts\": \"./vendor/mod.ts\").", - ) - ); - } - - #[tokio::test] - async fn existing_import_map_scopes_key_output_dir() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - let scopes = original_import_map - .get_or_append_scope_mut("./vendor/") - .unwrap(); - scopes - .append("/mod.ts".to_string(), "./vendor/mod.ts".to_string()) - .unwrap(); - let err = builder - .with_loader(|loader| { - loader.add("/mod.ts", "console.log(5);"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .err() - .unwrap(); - - assert_eq!( - err.to_string(), - concat!( - "Providing an existing import map with a scope for the output ", - "directory is not supported (\"./vendor/\").", - ) - ); - } - - #[tokio::test] - async fn existing_import_map_http_key() { - let mut builder = VendorTestBuilder::with_default_setup(); - let mut original_import_map = builder.new_import_map("/import_map.json"); - original_import_map - .imports_mut() - .append( - "http/".to_string(), - "https://deno.land/std/http/".to_string(), - ) - .unwrap(); - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'http/mod.ts';"); - loader.add("https://deno.land/std/http/mod.ts", "console.log(5);"); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "http/mod.ts": "./deno.land/std/http/mod.ts", - "https://deno.land/": "./deno.land/", - } - })) - ); - assert_eq!( - output.files, - to_file_vec(&[("/vendor/deno.land/std/http/mod.ts", "console.log(5);")]), - ); - } - - #[tokio::test] - async fn existing_import_map_jsx_import_source_jsx_files() { - let mut builder = VendorTestBuilder::default(); - builder.add_entry_point("/mod.tsx"); - builder.set_jsx_import_source_config(JsxImportSourceConfig { - default_specifier: Some("preact".to_string()), - default_types_specifier: None, - module: "jsx-runtime".to_string(), - base_url: builder.resolve_to_url("/deno.json"), - }); - let mut original_import_map = builder.new_import_map("/import_map.json"); - let imports = original_import_map.imports_mut(); - imports - .append( - "preact/".to_string(), - "https://localhost/preact/".to_string(), - ) - .unwrap(); - let output = builder - .with_loader(|loader| { - loader.add("/mod.tsx", "const myComponent =
;"); - loader.add_with_headers( - "https://localhost/preact/jsx-runtime", - "export function stuff() {}", - &[("content-type", "application/typescript")], - ); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/", - "preact/jsx-runtime": "./localhost/preact/jsx-runtime.ts", - }, - })) - ); - assert_eq!( - output.files, - to_file_vec(&[( - "/vendor/localhost/preact/jsx-runtime.ts", - "export function stuff() {}" - ),]), - ); - } - - #[tokio::test] - async fn existing_import_map_jsx_import_source_no_jsx_files() { - let mut builder = VendorTestBuilder::default(); - builder.add_entry_point("/mod.ts"); - builder.set_jsx_import_source_config(JsxImportSourceConfig { - default_specifier: Some("preact".to_string()), - default_types_specifier: None, - module: "jsx-runtime".to_string(), - base_url: builder.resolve_to_url("/deno.json"), - }); - let mut original_import_map = builder.new_import_map("/import_map.json"); - let imports = original_import_map.imports_mut(); - imports - .append( - "preact/".to_string(), - "https://localhost/preact/".to_string(), - ) - .unwrap(); - let output = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'https://localhost/mod.ts';"); - loader.add("https://localhost/mod.ts", "console.log(1)"); - loader.add_with_headers( - "https://localhost/preact/jsx-runtime", - "export function stuff() {}", - &[("content-type", "application/typescript")], - ); - }) - .set_original_import_map(original_import_map) - .build() - .await - .unwrap(); - - assert_eq!( - output.import_map, - Some(json!({ - "imports": { - "https://localhost/": "./localhost/", - "preact/jsx-runtime": "./localhost/preact/jsx-runtime.ts" - }, - })) - ); - assert_eq!( - output.files, - to_file_vec(&[ - ("/vendor/localhost/mod.ts", "console.log(1)"), - ( - "/vendor/localhost/preact/jsx-runtime.ts", - "export function stuff() {}" - ), - ]), - ); - } - - #[tokio::test] - async fn vendor_file_fails_loading_dynamic_import() { - let mut builder = VendorTestBuilder::with_default_setup(); - let err = builder - .with_loader(|loader| { - loader.add("/mod.ts", "import 'https://localhost/mod.ts';"); - loader.add("https://localhost/mod.ts", "await import('./test.ts');"); - loader.add_failure( - "https://localhost/test.ts", - "500 Internal Server Error", - ); - }) - .build() - .await - .err() - .unwrap(); - - assert_eq!( - test_util::strip_ansi_codes(&err.to_string()), - concat!( - "500 Internal Server Error\n", - " at https://localhost/mod.ts:1:14" - ) - ); - } - - fn to_file_vec(items: &[(&str, &str)]) -> Vec<(String, String)> { - items - .iter() - .map(|(f, t)| (f.to_string(), t.to_string())) - .collect() - } -} diff --git a/cli/tools/vendor/import_map.rs b/cli/tools/vendor/import_map.rs deleted file mode 100644 index 644e84a7b3..0000000000 --- a/cli/tools/vendor/import_map.rs +++ /dev/null @@ -1,508 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use deno_ast::LineAndColumnIndex; -use deno_ast::ModuleSpecifier; -use deno_ast::SourceTextInfo; -use deno_core::error::AnyError; -use deno_graph::source::ResolutionMode; -use deno_graph::Module; -use deno_graph::ModuleGraph; -use deno_graph::Position; -use deno_graph::Range; -use deno_graph::Resolution; -use import_map::ImportMap; -use import_map::SpecifierMap; -use indexmap::IndexMap; -use log::warn; - -use crate::args::JsxImportSourceConfig; -use crate::cache::ParsedSourceCache; - -use super::mappings::Mappings; -use super::specifiers::is_remote_specifier; -use super::specifiers::is_remote_specifier_text; - -struct ImportMapBuilder<'a> { - base_dir: &'a ModuleSpecifier, - mappings: &'a Mappings, - imports: ImportsBuilder<'a>, - scopes: IndexMap>, -} - -impl<'a> ImportMapBuilder<'a> { - pub fn new(base_dir: &'a ModuleSpecifier, mappings: &'a Mappings) -> Self { - ImportMapBuilder { - base_dir, - mappings, - imports: ImportsBuilder::new(base_dir, mappings), - scopes: Default::default(), - } - } - - pub fn base_dir(&self) -> &ModuleSpecifier { - self.base_dir - } - - pub fn scope( - &mut self, - base_specifier: &ModuleSpecifier, - ) -> &mut ImportsBuilder<'a> { - self - .scopes - .entry( - self - .mappings - .relative_specifier_text(self.base_dir, base_specifier), - ) - .or_insert_with(|| ImportsBuilder::new(self.base_dir, self.mappings)) - } - - pub fn into_import_map( - self, - maybe_original_import_map: Option<&ImportMap>, - ) -> ImportMap { - fn get_local_imports( - new_relative_path: &str, - original_imports: &SpecifierMap, - ) -> Vec<(String, String)> { - let mut result = Vec::new(); - for entry in original_imports.entries() { - if let Some(raw_value) = entry.raw_value { - if raw_value.starts_with("./") || raw_value.starts_with("../") { - let sub_index = raw_value.find('/').unwrap() + 1; - result.push(( - entry.raw_key.to_string(), - format!("{}{}", new_relative_path, &raw_value[sub_index..]), - )); - } - } - } - result - } - - fn add_local_imports<'a>( - new_relative_path: &str, - original_imports: &SpecifierMap, - get_new_imports: impl FnOnce() -> &'a mut SpecifierMap, - ) { - let local_imports = - get_local_imports(new_relative_path, original_imports); - if !local_imports.is_empty() { - let new_imports = get_new_imports(); - for (key, value) in local_imports { - if let Err(warning) = new_imports.append(key, value) { - warn!("{}", warning); - } - } - } - } - - let mut import_map = ImportMap::new(self.base_dir.clone()); - - if let Some(original_im) = maybe_original_import_map { - let original_base_dir = ModuleSpecifier::from_directory_path( - original_im - .base_url() - .to_file_path() - .unwrap() - .parent() - .unwrap(), - ) - .unwrap(); - let new_relative_path = self - .mappings - .relative_specifier_text(self.base_dir, &original_base_dir); - // add the imports - add_local_imports(&new_relative_path, original_im.imports(), || { - import_map.imports_mut() - }); - - for scope in original_im.scopes() { - if scope.raw_key.starts_with("./") || scope.raw_key.starts_with("../") { - let sub_index = scope.raw_key.find('/').unwrap() + 1; - let new_key = - format!("{}{}", new_relative_path, &scope.raw_key[sub_index..]); - add_local_imports(&new_relative_path, scope.imports, || { - import_map.get_or_append_scope_mut(&new_key).unwrap() - }); - } - } - } - - let imports = import_map.imports_mut(); - for (key, value) in self.imports.imports { - if !imports.contains(&key) { - imports.append(key, value).unwrap(); - } - } - - for (scope_key, scope_value) in self.scopes { - if !scope_value.imports.is_empty() { - let imports = import_map.get_or_append_scope_mut(&scope_key).unwrap(); - for (key, value) in scope_value.imports { - if !imports.contains(&key) { - imports.append(key, value).unwrap(); - } - } - } - } - - import_map - } -} - -struct ImportsBuilder<'a> { - base_dir: &'a ModuleSpecifier, - mappings: &'a Mappings, - imports: IndexMap, -} - -impl<'a> ImportsBuilder<'a> { - pub fn new(base_dir: &'a ModuleSpecifier, mappings: &'a Mappings) -> Self { - Self { - base_dir, - mappings, - imports: Default::default(), - } - } - - pub fn add(&mut self, key: String, specifier: &ModuleSpecifier) { - let value = self - .mappings - .relative_specifier_text(self.base_dir, specifier); - - // skip creating identity entries - if key != value { - self.imports.insert(key, value); - } - } -} - -pub struct BuildImportMapInput<'a> { - pub base_dir: &'a ModuleSpecifier, - pub modules: &'a [&'a Module], - pub graph: &'a ModuleGraph, - pub mappings: &'a Mappings, - pub maybe_original_import_map: Option<&'a ImportMap>, - pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>, - pub resolver: &'a dyn deno_graph::source::Resolver, - pub parsed_source_cache: &'a ParsedSourceCache, -} - -pub fn build_import_map( - input: BuildImportMapInput<'_>, -) -> Result { - let BuildImportMapInput { - base_dir, - modules, - graph, - mappings, - maybe_original_import_map, - maybe_jsx_import_source, - resolver, - parsed_source_cache, - } = input; - let mut builder = ImportMapBuilder::new(base_dir, mappings); - visit_modules(graph, modules, mappings, &mut builder, parsed_source_cache)?; - - for base_specifier in mappings.base_specifiers() { - builder - .imports - .add(base_specifier.to_string(), base_specifier); - } - - // add the jsx import source to the destination import map, if mapped in the original import map - if let Some(jsx_import_source) = maybe_jsx_import_source { - if let Some(specifier_text) = jsx_import_source.maybe_specifier_text() { - if let Ok(resolved_url) = resolver.resolve( - &specifier_text, - &deno_graph::Range { - specifier: jsx_import_source.base_url.clone(), - start: deno_graph::Position::zeroed(), - end: deno_graph::Position::zeroed(), - }, - ResolutionMode::Execution, - ) { - builder.imports.add(specifier_text, &resolved_url); - } - } - } - - Ok(builder.into_import_map(maybe_original_import_map).to_json()) -} - -fn visit_modules( - graph: &ModuleGraph, - modules: &[&Module], - mappings: &Mappings, - import_map: &mut ImportMapBuilder, - parsed_source_cache: &ParsedSourceCache, -) -> Result<(), AnyError> { - for module in modules { - let module = match module { - Module::Js(module) => module, - // skip visiting Json modules as they are leaves - Module::Json(_) - | Module::Npm(_) - | Module::Node(_) - | Module::External(_) => continue, - }; - - let parsed_source = - parsed_source_cache.get_parsed_source_from_js_module(module)?; - let text_info = parsed_source.text_info_lazy().clone(); - - for dep in module.dependencies.values() { - visit_resolution( - &dep.maybe_code, - graph, - import_map, - &module.specifier, - mappings, - &text_info, - &module.source, - ); - visit_resolution( - &dep.maybe_type, - graph, - import_map, - &module.specifier, - mappings, - &text_info, - &module.source, - ); - } - - if let Some(types_dep) = &module.maybe_types_dependency { - visit_resolution( - &types_dep.dependency, - graph, - import_map, - &module.specifier, - mappings, - &text_info, - &module.source, - ); - } - } - - Ok(()) -} - -fn visit_resolution( - resolution: &Resolution, - graph: &ModuleGraph, - import_map: &mut ImportMapBuilder, - referrer: &ModuleSpecifier, - mappings: &Mappings, - text_info: &SourceTextInfo, - source_text: &str, -) { - if let Some(resolved) = resolution.ok() { - let text = text_from_range(text_info, source_text, &resolved.range); - // if the text is empty then it's probably an x-TypeScript-types - if !text.is_empty() { - handle_dep_specifier( - text, - &resolved.specifier, - graph, - import_map, - referrer, - mappings, - ); - } - } -} - -fn handle_dep_specifier( - text: &str, - unresolved_specifier: &ModuleSpecifier, - graph: &ModuleGraph, - import_map: &mut ImportMapBuilder, - referrer: &ModuleSpecifier, - mappings: &Mappings, -) { - let specifier = match graph.get(unresolved_specifier) { - Some(module) => module.specifier().clone(), - // Ignore when None. The graph was previous validated so this is a - // dynamic import that was missing and is ignored for vendoring - None => return, - }; - // check if it's referencing a remote module - if is_remote_specifier(&specifier) { - handle_remote_dep_specifier( - text, - unresolved_specifier, - &specifier, - import_map, - referrer, - mappings, - ) - } else if specifier.scheme() == "file" { - handle_local_dep_specifier( - text, - unresolved_specifier, - &specifier, - import_map, - referrer, - mappings, - ); - } -} - -fn handle_remote_dep_specifier( - text: &str, - unresolved_specifier: &ModuleSpecifier, - specifier: &ModuleSpecifier, - import_map: &mut ImportMapBuilder, - referrer: &ModuleSpecifier, - mappings: &Mappings, -) { - if is_remote_specifier_text(text) { - let base_specifier = mappings.base_specifier(specifier); - if text.starts_with(base_specifier.as_str()) { - let sub_path = &text[base_specifier.as_str().len()..]; - let relative_text = - mappings.relative_specifier_text(base_specifier, specifier); - let expected_sub_path = relative_text.trim_start_matches("./"); - if expected_sub_path != sub_path { - import_map.imports.add(text.to_string(), specifier); - } - } else { - // it's probably a redirect. Add it explicitly to the import map - import_map.imports.add(text.to_string(), specifier); - } - } else { - let expected_relative_specifier_text = - mappings.relative_specifier_text(referrer, specifier); - if expected_relative_specifier_text == text { - return; - } - - if !is_remote_specifier(referrer) { - // local module referencing a remote module using - // non-remote specifier text means it was something in - // the original import map, so add a mapping to it - import_map.imports.add(text.to_string(), specifier); - return; - } - - let base_referrer = mappings.base_specifier(referrer); - let base_dir = import_map.base_dir().clone(); - let imports = import_map.scope(base_referrer); - if text.starts_with("./") || text.starts_with("../") { - // resolve relative specifier key - let mut local_base_specifier = mappings.local_uri(base_referrer); - local_base_specifier = local_base_specifier - // path includes "/" so make it relative - .join(&format!(".{}", unresolved_specifier.path())) - .unwrap_or_else(|_| { - panic!( - "Error joining {} to {}", - unresolved_specifier.path(), - local_base_specifier - ) - }); - local_base_specifier.set_query(unresolved_specifier.query()); - - imports.add( - mappings.relative_specifier_text(&base_dir, &local_base_specifier), - specifier, - ); - - // add a mapping that uses the local directory name and the remote - // filename in order to support files importing this relatively - imports.add( - { - let local_path = mappings.local_path(specifier); - let mut value = - ModuleSpecifier::from_directory_path(local_path.parent().unwrap()) - .unwrap(); - value.set_query(specifier.query()); - value.set_path(&format!( - "{}{}", - value.path(), - specifier.path_segments().unwrap().last().unwrap(), - )); - mappings.relative_specifier_text(&base_dir, &value) - }, - specifier, - ); - } else { - // absolute (`/`) or bare specifier should be left as-is - imports.add(text.to_string(), specifier); - } - } -} - -fn handle_local_dep_specifier( - text: &str, - unresolved_specifier: &ModuleSpecifier, - specifier: &ModuleSpecifier, - import_map: &mut ImportMapBuilder, - referrer: &ModuleSpecifier, - mappings: &Mappings, -) { - if !is_remote_specifier(referrer) { - // do not handle local modules referencing local modules - return; - } - - // The remote module is referencing a local file. This could occur via an - // existing import map. In this case, we'll have to add an import map - // entry in order to map the path back to the local path once vendored. - let base_dir = import_map.base_dir().clone(); - let base_specifier = mappings.base_specifier(referrer); - let imports = import_map.scope(base_specifier); - - if text.starts_with("./") || text.starts_with("../") { - let referrer_local_uri = mappings.local_uri(referrer); - let mut specifier_local_uri = - referrer_local_uri.join(text).unwrap_or_else(|_| { - panic!( - "Error joining {} to {}", - unresolved_specifier.path(), - referrer_local_uri - ) - }); - specifier_local_uri.set_query(unresolved_specifier.query()); - - imports.add( - mappings.relative_specifier_text(&base_dir, &specifier_local_uri), - specifier, - ); - } else { - imports.add(text.to_string(), specifier); - } -} - -fn text_from_range<'a>( - text_info: &SourceTextInfo, - text: &'a str, - range: &Range, -) -> &'a str { - let result = &text[byte_range(text_info, range)]; - if result.starts_with('"') || result.starts_with('\'') { - // remove the quotes - &result[1..result.len() - 1] - } else { - result - } -} - -fn byte_range( - text_info: &SourceTextInfo, - range: &Range, -) -> std::ops::Range { - let start = byte_index(text_info, &range.start); - let end = byte_index(text_info, &range.end); - start..end -} - -fn byte_index(text_info: &SourceTextInfo, pos: &Position) -> usize { - // todo(https://github.com/denoland/deno_graph/issues/79): use byte indexes all the way down - text_info.loc_to_source_pos(LineAndColumnIndex { - line_index: pos.line, - column_index: pos.character, - }) - text_info.range().start -} diff --git a/cli/tools/vendor/mappings.rs b/cli/tools/vendor/mappings.rs deleted file mode 100644 index 6d2722b89c..0000000000 --- a/cli/tools/vendor/mappings.rs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::collections::HashMap; -use std::collections::HashSet; -use std::path::Path; -use std::path::PathBuf; - -use deno_ast::MediaType; -use deno_ast::ModuleSpecifier; -use deno_core::error::AnyError; -use deno_graph::Module; -use deno_graph::ModuleGraph; -use deno_graph::Position; - -use crate::util::path::path_with_stem_suffix; -use crate::util::path::relative_specifier; - -use super::specifiers::dir_name_for_root; -use super::specifiers::get_unique_path; -use super::specifiers::make_url_relative; -use super::specifiers::partition_by_root_specifiers; -use super::specifiers::sanitize_filepath; - -pub struct ProxiedModule { - pub output_path: PathBuf, - pub declaration_specifier: ModuleSpecifier, -} - -/// Constructs and holds the remote specifier to local path mappings. -pub struct Mappings { - mappings: HashMap, - base_specifiers: Vec, - proxies: HashMap, -} - -impl Mappings { - pub fn from_remote_modules( - graph: &ModuleGraph, - remote_modules: &[&Module], - output_dir: &Path, - ) -> Result { - let partitioned_specifiers = partition_by_root_specifiers( - remote_modules.iter().map(|m| m.specifier()), - ); - let mut mapped_paths = HashSet::new(); - let mut mappings = HashMap::new(); - let mut proxies = HashMap::new(); - let mut base_specifiers = Vec::new(); - - for (root, specifiers) in partitioned_specifiers.into_iter() { - let base_dir = get_unique_path( - output_dir.join(dir_name_for_root(&root)), - &mut mapped_paths, - ); - for specifier in specifiers { - let module = graph.get(&specifier).unwrap(); - let media_type = match module { - Module::Js(module) => module.media_type, - Module::Json(_) => MediaType::Json, - Module::Node(_) | Module::Npm(_) | Module::External(_) => continue, - }; - let sub_path = sanitize_filepath(&make_url_relative(&root, &{ - let mut specifier = specifier.clone(); - specifier.set_query(None); - specifier - })?); - let new_path = path_with_extension( - &base_dir.join(if cfg!(windows) { - sub_path.replace('/', "\\") - } else { - sub_path - }), - &media_type.as_ts_extension()[1..], - ); - mappings - .insert(specifier, get_unique_path(new_path, &mut mapped_paths)); - } - base_specifiers.push(root.clone()); - mappings.insert(root, base_dir); - } - - // resolve all the "proxy" paths to use for when an x-typescript-types header is specified - for module in remote_modules { - if let Some(module) = module.js() { - if let Some(resolved) = &module - .maybe_types_dependency - .as_ref() - .and_then(|d| d.dependency.ok()) - { - let range = &resolved.range; - // hack to tell if it's an x-typescript-types header - let is_ts_types_header = range.start == Position::zeroed() - && range.end == Position::zeroed(); - if is_ts_types_header { - let module_path = mappings.get(&module.specifier).unwrap(); - let proxied_path = get_unique_path( - path_with_stem_suffix(module_path, ".proxied"), - &mut mapped_paths, - ); - proxies.insert( - module.specifier.clone(), - ProxiedModule { - output_path: proxied_path, - declaration_specifier: resolved.specifier.clone(), - }, - ); - } - } - } - } - - Ok(Self { - mappings, - base_specifiers, - proxies, - }) - } - - pub fn local_uri(&self, specifier: &ModuleSpecifier) -> ModuleSpecifier { - if specifier.scheme() == "file" { - specifier.clone() - } else { - let local_path = self.local_path(specifier); - if specifier.path().ends_with('/') { - ModuleSpecifier::from_directory_path(&local_path) - } else { - ModuleSpecifier::from_file_path(&local_path) - } - .unwrap_or_else(|_| { - panic!("Could not convert {} to uri.", local_path.display()) - }) - } - } - - pub fn local_path(&self, specifier: &ModuleSpecifier) -> PathBuf { - if specifier.scheme() == "file" { - specifier.to_file_path().unwrap() - } else { - self - .mappings - .get(specifier) - .unwrap_or_else(|| panic!("Could not find local path for {specifier}")) - .to_path_buf() - } - } - - pub fn relative_specifier_text( - &self, - from: &ModuleSpecifier, - to: &ModuleSpecifier, - ) -> String { - let from = self.local_uri(from); - let to = self.local_uri(to); - relative_specifier(&from, &to).unwrap() - } - - pub fn base_specifiers(&self) -> &Vec { - &self.base_specifiers - } - - pub fn base_specifier( - &self, - child_specifier: &ModuleSpecifier, - ) -> &ModuleSpecifier { - self - .base_specifiers - .iter() - .find(|s| child_specifier.as_str().starts_with(s.as_str())) - .unwrap_or_else(|| { - panic!("Could not find base specifier for {child_specifier}") - }) - } - - pub fn proxied_path(&self, specifier: &ModuleSpecifier) -> Option { - self.proxies.get(specifier).map(|s| s.output_path.clone()) - } - - pub fn proxied_modules( - &self, - ) -> std::collections::hash_map::Iter<'_, ModuleSpecifier, ProxiedModule> { - self.proxies.iter() - } -} - -fn path_with_extension(path: &Path, new_ext: &str) -> PathBuf { - if let Some(file_stem) = path.file_stem().map(|f| f.to_string_lossy()) { - if let Some(old_ext) = path.extension().map(|f| f.to_string_lossy()) { - if file_stem.to_lowercase().ends_with(".d") { - if new_ext.to_lowercase() == format!("d.{}", old_ext.to_lowercase()) { - // maintain casing - return path.to_path_buf(); - } - return path.with_file_name(format!( - "{}.{}", - &file_stem[..file_stem.len() - ".d".len()], - new_ext - )); - } - if new_ext.to_lowercase() == old_ext.to_lowercase() { - // maintain casing - return path.to_path_buf(); - } - let media_type = MediaType::from_path(path); - if media_type == MediaType::Unknown { - return path.with_file_name(format!( - "{}.{}", - path.file_name().unwrap().to_string_lossy(), - new_ext - )); - } - } - } - path.with_extension(new_ext) -} - -#[cfg(test)] -mod test { - use pretty_assertions::assert_eq; - - use super::*; - - #[test] - fn test_path_with_extension() { - assert_eq!( - path_with_extension(&PathBuf::from("/test.D.TS"), "ts"), - PathBuf::from("/test.ts") - ); - assert_eq!( - path_with_extension(&PathBuf::from("/test.D.MTS"), "js"), - PathBuf::from("/test.js") - ); - assert_eq!( - path_with_extension(&PathBuf::from("/test.D.TS"), "d.ts"), - // maintains casing - PathBuf::from("/test.D.TS"), - ); - assert_eq!( - path_with_extension(&PathBuf::from("/test.TS"), "ts"), - // maintains casing - PathBuf::from("/test.TS"), - ); - assert_eq!( - path_with_extension(&PathBuf::from("/test.ts"), "js"), - PathBuf::from("/test.js") - ); - assert_eq!( - path_with_extension(&PathBuf::from("/test.js"), "js"), - PathBuf::from("/test.js") - ); - assert_eq!( - path_with_extension(&PathBuf::from("/chai@1.2.3"), "js"), - PathBuf::from("/chai@1.2.3.js") - ); - } -} diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs deleted file mode 100644 index e144523724..0000000000 --- a/cli/tools/vendor/mod.rs +++ /dev/null @@ -1,575 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::path::Path; -use std::path::PathBuf; -use std::sync::Arc; - -use deno_ast::ModuleSpecifier; -use deno_ast::TextChange; -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::AnyError; -use deno_core::futures::FutureExt; -use deno_core::resolve_url_or_path; -use deno_graph::GraphKind; -use deno_runtime::colors; -use log::warn; - -use crate::args::CliOptions; -use crate::args::ConfigFile; -use crate::args::Flags; -use crate::args::FmtOptionsConfig; -use crate::args::VendorFlags; -use crate::factory::CliFactory; -use crate::tools::fmt::format_json; -use crate::util::fs::canonicalize_path; -use crate::util::fs::resolve_from_cwd; -use crate::util::path::relative_specifier; -use deno_runtime::fs_util::specifier_to_file_path; - -mod analyze; -mod build; -mod import_map; -mod mappings; -mod specifiers; -#[cfg(test)] -mod test; - -pub async fn vendor( - flags: Arc, - vendor_flags: VendorFlags, -) -> Result<(), AnyError> { - log::info!( - "{}", - colors::yellow("⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.\nAdd `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead."), - ); - let mut cli_options = CliOptions::from_flags(flags)?; - let raw_output_dir = match &vendor_flags.output_path { - Some(output_path) => PathBuf::from(output_path).to_owned(), - None => PathBuf::from("vendor/"), - }; - let output_dir = resolve_from_cwd(&raw_output_dir)?; - validate_output_dir(&output_dir, &vendor_flags)?; - validate_options(&mut cli_options, &output_dir)?; - let factory = CliFactory::from_cli_options(Arc::new(cli_options)); - let cli_options = factory.cli_options()?; - if cli_options.workspace().config_folders().len() > 1 { - bail!("deno vendor is not supported in a workspace. Set `\"vendor\": true` in the workspace deno.json file instead"); - } - let entry_points = - resolve_entry_points(&vendor_flags, cli_options.initial_cwd())?; - let jsx_import_source = cli_options - .workspace() - .to_maybe_jsx_import_source_config()?; - let module_graph_creator = factory.module_graph_creator().await?.clone(); - let workspace_resolver = factory.workspace_resolver().await?; - let root_folder = cli_options.workspace().root_folder_configs(); - let maybe_config_file = root_folder.deno_json.as_ref(); - let output = build::build(build::BuildInput { - entry_points, - build_graph: move |entry_points| { - async move { - module_graph_creator - .create_graph(GraphKind::All, entry_points) - .await - } - .boxed_local() - }, - parsed_source_cache: factory.parsed_source_cache(), - output_dir: &output_dir, - maybe_original_import_map: workspace_resolver.maybe_import_map(), - maybe_jsx_import_source: jsx_import_source.as_ref(), - resolver: factory.resolver().await?.as_graph_resolver(), - environment: &build::RealVendorEnvironment, - }) - .await?; - - let vendored_count = output.vendored_count; - let graph = output.graph; - let npm_package_count = graph.npm_packages.len(); - let try_add_node_modules_dir = npm_package_count > 0 - && cli_options.node_modules_dir_enablement().unwrap_or(true); - - log::info!( - concat!("Vendored {} {} into {} directory.",), - vendored_count, - if vendored_count == 1 { - "module" - } else { - "modules" - }, - raw_output_dir.display(), - ); - - let try_add_import_map = vendored_count > 0; - let modified_result = maybe_update_config_file( - &output_dir, - maybe_config_file, - try_add_import_map, - try_add_node_modules_dir, - ); - - // cache the node_modules folder when it's been added to the config file - if modified_result.added_node_modules_dir { - let node_modules_path = - cli_options.node_modules_dir_path().cloned().or_else(|| { - maybe_config_file - .as_ref() - .map(|d| &d.specifier) - .filter(|c| c.scheme() == "file") - .and_then(|c| c.to_file_path().ok()) - .map(|config_path| config_path.parent().unwrap().join("node_modules")) - }); - if let Some(node_modules_path) = node_modules_path { - let cli_options = - cli_options.with_node_modules_dir_path(node_modules_path); - let factory = CliFactory::from_cli_options(Arc::new(cli_options)); - if let Some(managed) = factory.npm_resolver().await?.as_managed() { - managed.cache_packages().await?; - } - } - log::info!( - concat!( - "Vendored {} npm {} into node_modules directory. Set `nodeModulesDir: false` ", - "in the Deno configuration file to disable vendoring npm packages in the future.", - ), - npm_package_count, - if npm_package_count == 1 { - "package" - } else { - "packages" - }, - ); - } - - if vendored_count > 0 { - let import_map_path = raw_output_dir.join("import_map.json"); - if modified_result.updated_import_map { - log::info!( - concat!( - "\nUpdated your local Deno configuration file with a reference to the ", - "new vendored import map at {}. Invoking Deno subcommands will now ", - "automatically resolve using the vendored modules. You may override ", - "this by providing the `--import-map ` flag or by ", - "manually editing your Deno configuration file.", - ), - import_map_path.display(), - ); - } else { - log::info!( - concat!( - "\nTo use vendored modules, specify the `--import-map {}` flag when ", - r#"invoking Deno subcommands or add an `"importMap": ""` "#, - "entry to a deno.json file.", - ), - import_map_path.display(), - ); - } - } - - Ok(()) -} - -fn validate_output_dir( - output_dir: &Path, - flags: &VendorFlags, -) -> Result<(), AnyError> { - if !flags.force && !is_dir_empty(output_dir)? { - bail!(concat!( - "Output directory was not empty. Please specify an empty directory or use ", - "--force to ignore this error and potentially overwrite its contents.", - )); - } - Ok(()) -} - -fn validate_options( - options: &mut CliOptions, - output_dir: &Path, -) -> Result<(), AnyError> { - let import_map_specifier = options - .resolve_specified_import_map_specifier()? - .or_else(|| { - let config_file = options.workspace().root_deno_json()?; - config_file - .to_import_map_specifier() - .ok() - .flatten() - .or_else(|| { - if config_file.is_an_import_map() { - Some(config_file.specifier.clone()) - } else { - None - } - }) - }); - // check the import map - if let Some(import_map_path) = import_map_specifier - .and_then(|p| specifier_to_file_path(&p).ok()) - .and_then(|p| canonicalize_path(&p).ok()) - { - // make the output directory in order to canonicalize it for the check below - std::fs::create_dir_all(output_dir)?; - let output_dir = canonicalize_path(output_dir).with_context(|| { - format!("Failed to canonicalize: {}", output_dir.display()) - })?; - - if import_map_path.starts_with(output_dir) { - // canonicalize to make the test for this pass on the CI - let cwd = canonicalize_path(&std::env::current_dir()?)?; - // We don't allow using the output directory to help generate the - // new state because this may lead to cryptic error messages. - log::warn!( - concat!( - "Ignoring import map. Specifying an import map file ({}) in the ", - "deno vendor output directory is not supported. If you wish to use ", - "an import map while vendoring, please specify one located outside ", - "this directory." - ), - import_map_path - .strip_prefix(&cwd) - .unwrap_or(&import_map_path) - .display() - .to_string(), - ); - - // don't use an import map in the config - options.set_import_map_specifier(None); - } - } - - Ok(()) -} - -fn maybe_update_config_file( - output_dir: &Path, - maybe_config_file: Option<&Arc>, - try_add_import_map: bool, - try_add_node_modules_dir: bool, -) -> ModifiedResult { - assert!(output_dir.is_absolute()); - let config_file = match maybe_config_file { - Some(config_file) => config_file, - None => return ModifiedResult::default(), - }; - if config_file.specifier.scheme() != "file" { - return ModifiedResult::default(); - } - - let fmt_config_options = config_file - .to_fmt_config() - .ok() - .map(|config| config.options) - .unwrap_or_default(); - let result = update_config_file( - config_file, - &fmt_config_options, - if try_add_import_map { - Some( - ModuleSpecifier::from_file_path(output_dir.join("import_map.json")) - .unwrap(), - ) - } else { - None - }, - try_add_node_modules_dir, - ); - match result { - Ok(modified_result) => modified_result, - Err(err) => { - warn!("Error updating config file. {:#}", err); - ModifiedResult::default() - } - } -} - -fn update_config_file( - config_file: &ConfigFile, - fmt_options: &FmtOptionsConfig, - import_map_specifier: Option, - try_add_node_modules_dir: bool, -) -> Result { - let config_path = specifier_to_file_path(&config_file.specifier)?; - let config_text = std::fs::read_to_string(&config_path)?; - let import_map_specifier = - import_map_specifier.and_then(|import_map_specifier| { - relative_specifier(&config_file.specifier, &import_map_specifier) - }); - let modified_result = update_config_text( - &config_text, - fmt_options, - import_map_specifier.as_deref(), - try_add_node_modules_dir, - )?; - if let Some(new_text) = &modified_result.new_text { - std::fs::write(config_path, new_text)?; - } - Ok(modified_result) -} - -#[derive(Default)] -struct ModifiedResult { - updated_import_map: bool, - added_node_modules_dir: bool, - new_text: Option, -} - -fn update_config_text( - text: &str, - fmt_options: &FmtOptionsConfig, - import_map_specifier: Option<&str>, - try_add_node_modules_dir: bool, -) -> Result { - use jsonc_parser::ast::ObjectProp; - use jsonc_parser::ast::Value; - let text = if text.trim().is_empty() { "{}\n" } else { text }; - let ast = - jsonc_parser::parse_to_ast(text, &Default::default(), &Default::default())?; - let obj = match ast.value { - Some(Value::Object(obj)) => obj, - _ => bail!("Failed updating config file due to no object."), - }; - let mut modified_result = ModifiedResult::default(); - let mut text_changes = Vec::new(); - let mut should_format = false; - - if try_add_node_modules_dir { - // Only modify the nodeModulesDir property if it's not set - // as this allows people to opt-out of this when vendoring - // by specifying `nodeModulesDir: false` - if obj.get("nodeModulesDir").is_none() { - let insert_position = obj.range.end - 1; - text_changes.push(TextChange { - range: insert_position..insert_position, - new_text: r#""nodeModulesDir": true"#.to_string(), - }); - should_format = true; - modified_result.added_node_modules_dir = true; - } - } - - if let Some(import_map_specifier) = import_map_specifier { - let import_map_specifier = import_map_specifier.replace('\"', "\\\""); - match obj.get("importMap") { - Some(ObjectProp { - value: Value::StringLit(lit), - .. - }) => { - text_changes.push(TextChange { - range: lit.range.start..lit.range.end, - new_text: format!("\"{}\"", import_map_specifier), - }); - modified_result.updated_import_map = true; - } - None => { - // insert it crudely at a position that won't cause any issues - // with comments and format after to make it look nice - let insert_position = obj.range.end - 1; - text_changes.push(TextChange { - range: insert_position..insert_position, - new_text: format!(r#""importMap": "{}""#, import_map_specifier), - }); - should_format = true; - modified_result.updated_import_map = true; - } - // shouldn't happen - Some(_) => { - bail!("Failed updating importMap in config file due to invalid type.") - } - } - } - - if text_changes.is_empty() { - return Ok(modified_result); - } - - let new_text = deno_ast::apply_text_changes(text, text_changes); - modified_result.new_text = if should_format { - format_json(&PathBuf::from("deno.json"), &new_text, fmt_options) - .ok() - .map(|formatted_text| formatted_text.unwrap_or(new_text)) - } else { - Some(new_text) - }; - Ok(modified_result) -} - -fn is_dir_empty(dir_path: &Path) -> Result { - match std::fs::read_dir(dir_path) { - Ok(mut dir) => Ok(dir.next().is_none()), - Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(true), - Err(err) => { - bail!("Error reading directory {}: {}", dir_path.display(), err) - } - } -} - -fn resolve_entry_points( - flags: &VendorFlags, - initial_cwd: &Path, -) -> Result, AnyError> { - flags - .specifiers - .iter() - .map(|p| resolve_url_or_path(p, initial_cwd).map_err(|e| e.into())) - .collect::, _>>() -} - -#[cfg(test)] -mod internal_test { - use super::*; - use pretty_assertions::assert_eq; - - #[test] - fn update_config_text_no_existing_props_add_prop() { - let result = update_config_text( - "{\n}", - &Default::default(), - Some("./vendor/import_map.json"), - false, - ) - .unwrap(); - assert!(result.updated_import_map); - assert!(!result.added_node_modules_dir); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "importMap": "./vendor/import_map.json" -} -"# - ); - - let result = update_config_text( - "{\n}", - &Default::default(), - Some("./vendor/import_map.json"), - true, - ) - .unwrap(); - assert!(result.updated_import_map); - assert!(result.added_node_modules_dir); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "nodeModulesDir": true, - "importMap": "./vendor/import_map.json" -} -"# - ); - - let result = - update_config_text("{\n}", &Default::default(), None, true).unwrap(); - assert!(!result.updated_import_map); - assert!(result.added_node_modules_dir); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "nodeModulesDir": true -} -"# - ); - } - - #[test] - fn update_config_text_existing_props_add_prop() { - let result = update_config_text( - r#"{ - "tasks": { - "task1": "other" - } -} -"#, - &Default::default(), - Some("./vendor/import_map.json"), - false, - ) - .unwrap(); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "tasks": { - "task1": "other" - }, - "importMap": "./vendor/import_map.json" -} -"# - ); - - // trailing comma - let result = update_config_text( - r#"{ - "tasks": { - "task1": "other" - }, -} -"#, - &Default::default(), - Some("./vendor/import_map.json"), - false, - ) - .unwrap(); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "tasks": { - "task1": "other" - }, - "importMap": "./vendor/import_map.json" -} -"# - ); - } - - #[test] - fn update_config_text_update_prop() { - let result = update_config_text( - r#"{ - "importMap": "./local.json" -} -"#, - &Default::default(), - Some("./vendor/import_map.json"), - false, - ) - .unwrap(); - assert_eq!( - result.new_text.unwrap(), - r#"{ - "importMap": "./vendor/import_map.json" -} -"# - ); - } - - #[test] - fn no_update_node_modules_dir() { - // will not update if this is already set (even if it's false) - let result = update_config_text( - r#"{ - "nodeModulesDir": false -} -"#, - &Default::default(), - None, - true, - ) - .unwrap(); - assert!(!result.added_node_modules_dir); - assert!(!result.updated_import_map); - assert_eq!(result.new_text, None); - - let result = update_config_text( - r#"{ - "nodeModulesDir": true -} -"#, - &Default::default(), - None, - true, - ) - .unwrap(); - assert!(!result.added_node_modules_dir); - assert!(!result.updated_import_map); - assert_eq!(result.new_text, None); - } -} diff --git a/cli/tools/vendor/specifiers.rs b/cli/tools/vendor/specifiers.rs deleted file mode 100644 index e0e0f5337a..0000000000 --- a/cli/tools/vendor/specifiers.rs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::collections::BTreeMap; -use std::collections::HashSet; -use std::path::PathBuf; - -use deno_ast::ModuleSpecifier; -use deno_core::anyhow::anyhow; -use deno_core::error::AnyError; - -use crate::util::path::is_banned_path_char; -use crate::util::path::path_with_stem_suffix; -use crate::util::path::root_url_to_safe_local_dirname; - -/// Partitions the provided specifiers by the non-path and non-query parts of a specifier. -pub fn partition_by_root_specifiers<'a>( - specifiers: impl Iterator, -) -> BTreeMap> { - let mut root_specifiers: BTreeMap> = - Default::default(); - for remote_specifier in specifiers { - let mut root_specifier = remote_specifier.clone(); - root_specifier.set_query(None); - root_specifier.set_path("/"); - - let specifiers = root_specifiers.entry(root_specifier).or_default(); - specifiers.push(remote_specifier.clone()); - } - root_specifiers -} - -/// Gets the directory name to use for the provided root. -pub fn dir_name_for_root(root: &ModuleSpecifier) -> PathBuf { - root_url_to_safe_local_dirname(root) -} - -/// Gets a unique file path given the provided file path -/// and the set of existing file paths. Inserts to the -/// set when finding a unique path. -pub fn get_unique_path( - mut path: PathBuf, - unique_set: &mut HashSet, -) -> PathBuf { - let original_path = path.clone(); - let mut count = 2; - // case insensitive comparison so the output works on case insensitive file systems - while !unique_set.insert(path.to_string_lossy().to_lowercase()) { - path = path_with_stem_suffix(&original_path, &format!("_{count}")); - count += 1; - } - path -} - -pub fn make_url_relative( - root: &ModuleSpecifier, - url: &ModuleSpecifier, -) -> Result { - root.make_relative(url).ok_or_else(|| { - anyhow!( - "Error making url ({}) relative to root: {}", - url.to_string(), - root.to_string() - ) - }) -} - -pub fn is_remote_specifier(specifier: &ModuleSpecifier) -> bool { - matches!(specifier.scheme().to_lowercase().as_str(), "http" | "https") -} - -pub fn is_remote_specifier_text(text: &str) -> bool { - let text = text.trim_start().to_lowercase(); - text.starts_with("http:") || text.starts_with("https:") -} - -pub fn sanitize_filepath(text: &str) -> String { - text - .chars() - .map(|c| if is_banned_path_char(c) { '_' } else { c }) - .collect() -} - -#[cfg(test)] -mod test { - use super::*; - use pretty_assertions::assert_eq; - - #[test] - fn partition_by_root_specifiers_same_sub_folder() { - run_partition_by_root_specifiers_test( - vec![ - "https://deno.land/x/mod/A.ts", - "https://deno.land/x/mod/other/A.ts", - ], - vec![( - "https://deno.land/", - vec![ - "https://deno.land/x/mod/A.ts", - "https://deno.land/x/mod/other/A.ts", - ], - )], - ); - } - - #[test] - fn partition_by_root_specifiers_different_sub_folder() { - run_partition_by_root_specifiers_test( - vec![ - "https://deno.land/x/mod/A.ts", - "https://deno.land/x/other/A.ts", - ], - vec![( - "https://deno.land/", - vec![ - "https://deno.land/x/mod/A.ts", - "https://deno.land/x/other/A.ts", - ], - )], - ); - } - - #[test] - fn partition_by_root_specifiers_different_hosts() { - run_partition_by_root_specifiers_test( - vec![ - "https://deno.land/mod/A.ts", - "http://deno.land/B.ts", - "https://deno.land:8080/C.ts", - "https://localhost/mod/A.ts", - "https://other/A.ts", - ], - vec![ - ("http://deno.land/", vec!["http://deno.land/B.ts"]), - ("https://deno.land/", vec!["https://deno.land/mod/A.ts"]), - ( - "https://deno.land:8080/", - vec!["https://deno.land:8080/C.ts"], - ), - ("https://localhost/", vec!["https://localhost/mod/A.ts"]), - ("https://other/", vec!["https://other/A.ts"]), - ], - ); - } - - fn run_partition_by_root_specifiers_test( - input: Vec<&str>, - expected: Vec<(&str, Vec<&str>)>, - ) { - let input = input - .iter() - .map(|s| ModuleSpecifier::parse(s).unwrap()) - .collect::>(); - let output = partition_by_root_specifiers(input.iter()); - // the assertion is much easier to compare when everything is strings - let output = output - .into_iter() - .map(|(s, vec)| { - ( - s.to_string(), - vec.into_iter().map(|s| s.to_string()).collect::>(), - ) - }) - .collect::>(); - let expected = expected - .into_iter() - .map(|(s, vec)| { - ( - s.to_string(), - vec.into_iter().map(|s| s.to_string()).collect::>(), - ) - }) - .collect::>(); - assert_eq!(output, expected); - } - - #[test] - fn test_unique_path() { - let mut paths = HashSet::new(); - assert_eq!( - get_unique_path(PathBuf::from("/test"), &mut paths), - PathBuf::from("/test") - ); - assert_eq!( - get_unique_path(PathBuf::from("/test"), &mut paths), - PathBuf::from("/test_2") - ); - assert_eq!( - get_unique_path(PathBuf::from("/test"), &mut paths), - PathBuf::from("/test_3") - ); - assert_eq!( - get_unique_path(PathBuf::from("/TEST"), &mut paths), - PathBuf::from("/TEST_4") - ); - assert_eq!( - get_unique_path(PathBuf::from("/test.txt"), &mut paths), - PathBuf::from("/test.txt") - ); - assert_eq!( - get_unique_path(PathBuf::from("/test.txt"), &mut paths), - PathBuf::from("/test_2.txt") - ); - assert_eq!( - get_unique_path(PathBuf::from("/TEST.TXT"), &mut paths), - PathBuf::from("/TEST_3.TXT") - ); - } -} diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs deleted file mode 100644 index 65f37efdcf..0000000000 --- a/cli/tools/vendor/test.rs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::cell::RefCell; -use std::collections::HashMap; -use std::collections::HashSet; -use std::path::Path; -use std::path::PathBuf; -use std::sync::Arc; - -use deno_ast::ModuleSpecifier; -use deno_config::workspace::WorkspaceResolver; -use deno_core::anyhow::anyhow; -use deno_core::anyhow::bail; -use deno_core::error::AnyError; -use deno_core::futures; -use deno_core::futures::FutureExt; -use deno_core::serde_json; -use deno_graph::source::LoadFuture; -use deno_graph::source::LoadResponse; -use deno_graph::source::Loader; -use deno_graph::DefaultModuleAnalyzer; -use deno_graph::GraphKind; -use deno_graph::ModuleGraph; -use import_map::ImportMap; - -use crate::args::JsxImportSourceConfig; -use crate::cache::ParsedSourceCache; -use crate::resolver::CliGraphResolver; -use crate::resolver::CliGraphResolverOptions; - -use super::build::VendorEnvironment; - -// Utilities that help `deno vendor` get tested in memory. - -type RemoteFileText = String; -type RemoteFileHeaders = Option>; -type RemoteFileResult = Result<(RemoteFileText, RemoteFileHeaders), String>; - -#[derive(Clone, Default)] -pub struct TestLoader { - files: HashMap, - redirects: HashMap, -} - -impl TestLoader { - pub fn add( - &mut self, - path_or_specifier: impl AsRef, - text: impl AsRef, - ) -> &mut Self { - self.add_result(path_or_specifier, Ok((text.as_ref().to_string(), None))) - } - - pub fn add_failure( - &mut self, - path_or_specifier: impl AsRef, - message: impl AsRef, - ) -> &mut Self { - self.add_result(path_or_specifier, Err(message.as_ref().to_string())) - } - - fn add_result( - &mut self, - path_or_specifier: impl AsRef, - result: RemoteFileResult, - ) -> &mut Self { - if path_or_specifier - .as_ref() - .to_lowercase() - .starts_with("http") - { - self.files.insert( - ModuleSpecifier::parse(path_or_specifier.as_ref()).unwrap(), - result, - ); - } else { - let path = make_path(path_or_specifier.as_ref()); - let specifier = ModuleSpecifier::from_file_path(path).unwrap(); - self.files.insert(specifier, result); - } - self - } - - pub fn add_with_headers( - &mut self, - specifier: impl AsRef, - text: impl AsRef, - headers: &[(&str, &str)], - ) -> &mut Self { - let headers = headers - .iter() - .map(|(key, value)| (key.to_string(), value.to_string())) - .collect(); - self.files.insert( - ModuleSpecifier::parse(specifier.as_ref()).unwrap(), - Ok((text.as_ref().to_string(), Some(headers))), - ); - self - } - - pub fn add_redirect( - &mut self, - from: impl AsRef, - to: impl AsRef, - ) -> &mut Self { - self.redirects.insert( - ModuleSpecifier::parse(from.as_ref()).unwrap(), - ModuleSpecifier::parse(to.as_ref()).unwrap(), - ); - self - } -} - -impl Loader for TestLoader { - fn load( - &self, - specifier: &ModuleSpecifier, - _options: deno_graph::source::LoadOptions, - ) -> LoadFuture { - if let Some(redirect) = self.redirects.get(specifier) { - return Box::pin(futures::future::ready(Ok(Some( - LoadResponse::Redirect { - specifier: redirect.clone(), - }, - )))); - } - let result = self.files.get(specifier).map(|result| match result { - Ok(result) => Ok(LoadResponse::Module { - specifier: specifier.clone(), - content: result.0.clone().into_bytes().into(), - maybe_headers: result.1.clone(), - }), - Err(err) => Err(err), - }); - let result = match result { - Some(Ok(result)) => Ok(Some(result)), - Some(Err(err)) => Err(anyhow!("{}", err)), - None if specifier.scheme() == "data" => { - deno_graph::source::load_data_url(specifier) - } - None => Ok(None), - }; - Box::pin(futures::future::ready(result)) - } -} - -#[derive(Default)] -struct TestVendorEnvironment { - directories: RefCell>, - files: RefCell>, -} - -impl VendorEnvironment for TestVendorEnvironment { - fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError> { - let mut directories = self.directories.borrow_mut(); - for path in dir_path.ancestors() { - if !directories.insert(path.to_path_buf()) { - break; - } - } - Ok(()) - } - - fn write_file(&self, file_path: &Path, text: &[u8]) -> Result<(), AnyError> { - let parent = file_path.parent().unwrap(); - if !self.directories.borrow().contains(parent) { - bail!("Directory not found: {}", parent.display()); - } - self.files.borrow_mut().insert( - file_path.to_path_buf(), - String::from_utf8(text.to_vec()).unwrap(), - ); - Ok(()) - } -} - -pub struct VendorOutput { - pub files: Vec<(String, String)>, - pub import_map: Option, -} - -#[derive(Default)] -pub struct VendorTestBuilder { - entry_points: Vec, - loader: TestLoader, - maybe_original_import_map: Option, - environment: TestVendorEnvironment, - jsx_import_source_config: Option, -} - -impl VendorTestBuilder { - pub fn with_default_setup() -> Self { - let mut builder = VendorTestBuilder::default(); - builder.add_entry_point("/mod.ts"); - builder - } - - pub fn resolve_to_url(&self, path: &str) -> ModuleSpecifier { - ModuleSpecifier::from_file_path(make_path(path)).unwrap() - } - - pub fn new_import_map(&self, base_path: &str) -> ImportMap { - let base = self.resolve_to_url(base_path); - ImportMap::new(base) - } - - pub fn set_original_import_map( - &mut self, - import_map: ImportMap, - ) -> &mut Self { - self.maybe_original_import_map = Some(import_map); - self - } - - pub fn add_entry_point(&mut self, entry_point: impl AsRef) -> &mut Self { - let entry_point = make_path(entry_point.as_ref()); - self - .entry_points - .push(ModuleSpecifier::from_file_path(entry_point).unwrap()); - self - } - - pub fn set_jsx_import_source_config( - &mut self, - jsx_import_source_config: JsxImportSourceConfig, - ) -> &mut Self { - self.jsx_import_source_config = Some(jsx_import_source_config); - self - } - - pub async fn build(&mut self) -> Result { - let output_dir = make_path("/vendor"); - let entry_points = self.entry_points.clone(); - let loader = self.loader.clone(); - let parsed_source_cache = ParsedSourceCache::default(); - let resolver = Arc::new(build_resolver( - output_dir.parent().unwrap(), - self.jsx_import_source_config.clone(), - self.maybe_original_import_map.clone(), - )); - super::build::build(super::build::BuildInput { - entry_points, - build_graph: { - let resolver = resolver.clone(); - move |entry_points| { - async move { - Ok( - build_test_graph( - entry_points, - loader, - resolver.as_graph_resolver(), - &DefaultModuleAnalyzer, - ) - .await, - ) - } - .boxed_local() - } - }, - parsed_source_cache: &parsed_source_cache, - output_dir: &output_dir, - maybe_original_import_map: self.maybe_original_import_map.as_ref(), - maybe_jsx_import_source: self.jsx_import_source_config.as_ref(), - resolver: resolver.as_graph_resolver(), - environment: &self.environment, - }) - .await?; - - let mut files = self.environment.files.borrow_mut(); - let import_map = files.remove(&output_dir.join("import_map.json")); - let mut files = files - .iter() - .map(|(path, text)| (path_to_string(path), text.to_string())) - .collect::>(); - - files.sort_by(|a, b| a.0.cmp(&b.0)); - - Ok(VendorOutput { - import_map: import_map.map(|text| serde_json::from_str(&text).unwrap()), - files, - }) - } - - pub fn with_loader(&mut self, action: impl Fn(&mut TestLoader)) -> &mut Self { - action(&mut self.loader); - self - } -} - -fn build_resolver( - root_dir: &Path, - maybe_jsx_import_source_config: Option, - maybe_original_import_map: Option, -) -> CliGraphResolver { - CliGraphResolver::new(CliGraphResolverOptions { - node_resolver: None, - npm_resolver: None, - sloppy_imports_resolver: None, - workspace_resolver: Arc::new(WorkspaceResolver::new_raw( - Arc::new(ModuleSpecifier::from_directory_path(root_dir).unwrap()), - maybe_original_import_map, - Vec::new(), - Vec::new(), - deno_config::workspace::PackageJsonDepResolution::Enabled, - )), - maybe_jsx_import_source_config, - maybe_vendor_dir: None, - bare_node_builtins_enabled: false, - }) -} - -async fn build_test_graph( - roots: Vec, - loader: TestLoader, - resolver: &dyn deno_graph::source::Resolver, - analyzer: &dyn deno_graph::ModuleAnalyzer, -) -> ModuleGraph { - let mut graph = ModuleGraph::new(GraphKind::All); - graph - .build( - roots, - &loader, - deno_graph::BuildOptions { - resolver: Some(resolver), - module_analyzer: analyzer, - ..Default::default() - }, - ) - .await; - graph -} - -fn make_path(text: &str) -> PathBuf { - // This should work all in memory. We're waiting on - // https://github.com/servo/rust-url/issues/730 to provide - // a cross platform path here - assert!(text.starts_with('/')); - if cfg!(windows) { - PathBuf::from(format!("C:{}", text.replace('/', "\\"))) - } else { - PathBuf::from(text) - } -} - -fn path_to_string

(path: P) -> String -where - P: AsRef, -{ - let path = path.as_ref(); - // inverse of the function above - let path = path.to_string_lossy(); - if cfg!(windows) { - path.replace("C:\\", "\\").replace('\\', "/") - } else { - path.to_string() - } -} diff --git a/cli/tsc/00_typescript.js b/cli/tsc/00_typescript.js index e6ae49e0cd..7d20f92367 100644 --- a/cli/tsc/00_typescript.js +++ b/cli/tsc/00_typescript.js @@ -86,7 +86,6 @@ __export(typescript_exports, { GoToDefinition: () => ts_GoToDefinition_exports, HighlightSpanKind: () => HighlightSpanKind, IdentifierNameMap: () => IdentifierNameMap, - IdentifierNameMultiMap: () => IdentifierNameMultiMap, ImportKind: () => ImportKind, ImportsNotUsedAsValues: () => ImportsNotUsedAsValues, IndentStyle: () => IndentStyle, @@ -97,6 +96,7 @@ __export(typescript_exports, { InlayHintKind: () => InlayHintKind2, InlayHints: () => ts_InlayHints_exports, InternalEmitFlags: () => InternalEmitFlags, + InternalNodeBuilderFlags: () => InternalNodeBuilderFlags, InternalSymbolName: () => InternalSymbolName, IntersectionFlags: () => IntersectionFlags, InvalidatedProjectKind: () => InvalidatedProjectKind, @@ -143,6 +143,7 @@ __export(typescript_exports, { PollingInterval: () => PollingInterval, PollingWatchKind: () => PollingWatchKind, PragmaKindFlags: () => PragmaKindFlags, + PredicateSemantics: () => PredicateSemantics, PrivateIdentifierKind: () => PrivateIdentifierKind, ProcessLevel: () => ProcessLevel, ProgramUpdateLevel: () => ProgramUpdateLevel, @@ -173,7 +174,6 @@ __export(typescript_exports, { SymbolFlags: () => SymbolFlags, SymbolFormatFlags: () => SymbolFormatFlags, SyntaxKind: () => SyntaxKind, - SyntheticSymbolKind: () => SyntheticSymbolKind, Ternary: () => Ternary, ThrottledCancellationToken: () => ThrottledCancellationToken, TokenClass: () => TokenClass, @@ -196,7 +196,6 @@ __export(typescript_exports, { WatchLogLevel: () => WatchLogLevel, WatchType: () => WatchType, accessPrivateIdentifier: () => accessPrivateIdentifier, - addDisposableResourceHelper: () => addDisposableResourceHelper, addEmitFlags: () => addEmitFlags, addEmitHelper: () => addEmitHelper, addEmitHelpers: () => addEmitHelpers, @@ -219,23 +218,15 @@ __export(typescript_exports, { arrayFrom: () => arrayFrom, arrayIsEqualTo: () => arrayIsEqualTo, arrayIsHomogeneous: () => arrayIsHomogeneous, - arrayIsSorted: () => arrayIsSorted, arrayOf: () => arrayOf, arrayReverseIterator: () => arrayReverseIterator, arrayToMap: () => arrayToMap, arrayToMultiMap: () => arrayToMultiMap, arrayToNumericMap: () => arrayToNumericMap, - arraysEqual: () => arraysEqual, assertType: () => assertType, assign: () => assign, - assignHelper: () => assignHelper, - asyncDelegator: () => asyncDelegator, - asyncGeneratorHelper: () => asyncGeneratorHelper, asyncSuperHelper: () => asyncSuperHelper, - asyncValues: () => asyncValues, attachFileToDiagnostics: () => attachFileToDiagnostics, - awaitHelper: () => awaitHelper, - awaiterHelper: () => awaiterHelper, base64decode: () => base64decode, base64encode: () => base64encode, binarySearch: () => binarySearch, @@ -248,6 +239,7 @@ __export(typescript_exports, { buildOverload: () => buildOverload, bundlerModuleNameResolver: () => bundlerModuleNameResolver, canBeConvertedToAsync: () => canBeConvertedToAsync, + canEmitTsBuildInfo: () => canEmitTsBuildInfo, canHaveDecorators: () => canHaveDecorators, canHaveExportModifier: () => canHaveExportModifier, canHaveFlowNode: () => canHaveFlowNode, @@ -258,8 +250,9 @@ __export(typescript_exports, { canHaveJSDoc: () => canHaveJSDoc, canHaveLocals: () => canHaveLocals, canHaveModifiers: () => canHaveModifiers, + canHaveModuleSpecifier: () => canHaveModuleSpecifier, canHaveSymbol: () => canHaveSymbol, - canIncludeBindAndCheckDiagnsotics: () => canIncludeBindAndCheckDiagnsotics, + canIncludeBindAndCheckDiagnostics: () => canIncludeBindAndCheckDiagnostics, canJsonReportNoInputFiles: () => canJsonReportNoInputFiles, canProduceDiagnostics: () => canProduceDiagnostics, canUsePropertyAccess: () => canUsePropertyAccess, @@ -276,16 +269,13 @@ __export(typescript_exports, { changeFullExtension: () => changeFullExtension, changesAffectModuleResolution: () => changesAffectModuleResolution, changesAffectingProgramStructure: () => changesAffectingProgramStructure, - characterToRegularExpressionFlag: () => characterToRegularExpressionFlag, + characterCodeToRegularExpressionFlag: () => characterCodeToRegularExpressionFlag, childIsDecorated: () => childIsDecorated, classElementOrClassElementParameterIsDecorated: () => classElementOrClassElementParameterIsDecorated, classHasClassThisAssignment: () => classHasClassThisAssignment, classHasDeclaredOrExplicitlyAssignedName: () => classHasDeclaredOrExplicitlyAssignedName, classHasExplicitlyAssignedName: () => classHasExplicitlyAssignedName, classOrConstructorParameterIsDecorated: () => classOrConstructorParameterIsDecorated, - classPrivateFieldGetHelper: () => classPrivateFieldGetHelper, - classPrivateFieldInHelper: () => classPrivateFieldInHelper, - classPrivateFieldSetHelper: () => classPrivateFieldSetHelper, classicNameResolver: () => classicNameResolver, classifier: () => ts_classifier_exports, cleanExtendedConfigCache: () => cleanExtendedConfigCache, @@ -293,7 +283,6 @@ __export(typescript_exports, { clearMap: () => clearMap, clearSharedExtendedConfigFileWatcher: () => clearSharedExtendedConfigFileWatcher, climbPastPropertyAccess: () => climbPastPropertyAccess, - climbPastPropertyOrElementAccess: () => climbPastPropertyOrElementAccess, clone: () => clone, cloneCompilerOptions: () => cloneCompilerOptions, closeFileWatcher: () => closeFileWatcher, @@ -306,12 +295,10 @@ __export(typescript_exports, { commandLineOptionOfCustomType: () => commandLineOptionOfCustomType, commentPragmas: () => commentPragmas, commonOptionsWithBuild: () => commonOptionsWithBuild, - commonPackageFolders: () => commonPackageFolders, compact: () => compact, compareBooleans: () => compareBooleans, compareDataObjects: () => compareDataObjects, compareDiagnostics: () => compareDiagnostics, - compareDiagnosticsSkipRelatedInformation: () => compareDiagnosticsSkipRelatedInformation, compareEmitHelpers: () => compareEmitHelpers, compareNumberOfDirectorySeparators: () => compareNumberOfDirectorySeparators, comparePaths: () => comparePaths, @@ -325,26 +312,21 @@ __export(typescript_exports, { compareStringsCaseSensitiveUI: () => compareStringsCaseSensitiveUI, compareTextSpans: () => compareTextSpans, compareValues: () => compareValues, - compileOnSaveCommandLineOption: () => compileOnSaveCommandLineOption, compilerOptionsAffectDeclarationPath: () => compilerOptionsAffectDeclarationPath, compilerOptionsAffectEmit: () => compilerOptionsAffectEmit, compilerOptionsAffectSemanticDiagnostics: () => compilerOptionsAffectSemanticDiagnostics, compilerOptionsDidYouMeanDiagnostics: () => compilerOptionsDidYouMeanDiagnostics, compilerOptionsIndicateEsModules: () => compilerOptionsIndicateEsModules, - compose: () => compose, computeCommonSourceDirectoryOfFilenames: () => computeCommonSourceDirectoryOfFilenames, computeLineAndCharacterOfPosition: () => computeLineAndCharacterOfPosition, computeLineOfPosition: () => computeLineOfPosition, computeLineStarts: () => computeLineStarts, computePositionOfLineAndCharacter: () => computePositionOfLineAndCharacter, - computeSignature: () => computeSignature, computeSignatureWithDiagnostics: () => computeSignatureWithDiagnostics, computeSuggestionDiagnostics: () => computeSuggestionDiagnostics, computedOptions: () => computedOptions, concatenate: () => concatenate, concatenateDiagnosticMessageChains: () => concatenateDiagnosticMessageChains, - configDirTemplateSubstitutionOptions: () => configDirTemplateSubstitutionOptions, - configDirTemplateSubstitutionWatchOptions: () => configDirTemplateSubstitutionWatchOptions, consumesNodeCoreModules: () => consumesNodeCoreModules, contains: () => contains, containsIgnoredPath: () => containsIgnoredPath, @@ -375,16 +357,11 @@ __export(typescript_exports, { createAccessorPropertySetRedirector: () => createAccessorPropertySetRedirector, createBaseNodeFactory: () => createBaseNodeFactory, createBinaryExpressionTrampoline: () => createBinaryExpressionTrampoline, - createBindingHelper: () => createBindingHelper, - createBuildInfo: () => createBuildInfo, createBuilderProgram: () => createBuilderProgram, - createBuilderProgramUsingProgramBuildInfo: () => createBuilderProgramUsingProgramBuildInfo, + createBuilderProgramUsingIncrementalBuildInfo: () => createBuilderProgramUsingIncrementalBuildInfo, createBuilderStatusReporter: () => createBuilderStatusReporter, - createCacheWithRedirects: () => createCacheWithRedirects, createCacheableExportInfoMap: () => createCacheableExportInfoMap, createCachedDirectoryStructureHost: () => createCachedDirectoryStructureHost, - createClassNamedEvaluationHelperBlock: () => createClassNamedEvaluationHelperBlock, - createClassThisAssignmentBlock: () => createClassThisAssignmentBlock, createClassifier: () => createClassifier, createCommentDirectivesMap: () => createCommentDirectivesMap, createCompilerDiagnostic: () => createCompilerDiagnostic, @@ -436,6 +413,7 @@ __export(typescript_exports, { createMemberAccessForPropertyName: () => createMemberAccessForPropertyName, createModeAwareCache: () => createModeAwareCache, createModeAwareCacheKey: () => createModeAwareCacheKey, + createModeMismatchDetails: () => createModeMismatchDetails, createModuleNotFoundChain: () => createModuleNotFoundChain, createModuleResolutionCache: () => createModuleResolutionCache, createModuleResolutionLoader: () => createModuleResolutionLoader, @@ -506,9 +484,7 @@ __export(typescript_exports, { declarationNameToString: () => declarationNameToString, decodeMappings: () => decodeMappings, decodedTextSpanIntersectsWith: () => decodedTextSpanIntersectsWith, - decorateHelper: () => decorateHelper, deduplicate: () => deduplicate, - defaultIncludeSpec: () => defaultIncludeSpec, defaultInitCompilerOptions: () => defaultInitCompilerOptions, defaultMaximumTruncationLength: () => defaultMaximumTruncationLength, deno: () => deno_exports, @@ -520,27 +496,22 @@ __export(typescript_exports, { displayPart: () => displayPart, displayPartsToString: () => displayPartsToString, disposeEmitNodes: () => disposeEmitNodes, - disposeResourcesHelper: () => disposeResourcesHelper, documentSpansEqual: () => documentSpansEqual, dumpTracingLegend: () => dumpTracingLegend, elementAt: () => elementAt, elideNodes: () => elideNodes, - emitComments: () => emitComments, emitDetachedComments: () => emitDetachedComments, emitFiles: () => emitFiles, emitFilesAndReportErrors: () => emitFilesAndReportErrors, emitFilesAndReportErrorsAndGetExitStatus: () => emitFilesAndReportErrorsAndGetExitStatus, emitModuleKindIsNonNodeESM: () => emitModuleKindIsNonNodeESM, emitNewLineBeforeLeadingCommentOfPosition: () => emitNewLineBeforeLeadingCommentOfPosition, - emitNewLineBeforeLeadingComments: () => emitNewLineBeforeLeadingComments, - emitNewLineBeforeLeadingCommentsOfPosition: () => emitNewLineBeforeLeadingCommentsOfPosition, emitResolverSkipsTypeChecking: () => emitResolverSkipsTypeChecking, emitSkippedWithNoDiagnostics: () => emitSkippedWithNoDiagnostics, emptyArray: () => emptyArray, emptyFileSystemEntries: () => emptyFileSystemEntries, emptyMap: () => emptyMap, emptyOptions: () => emptyOptions, - emptySet: () => emptySet, endsWith: () => endsWith, ensurePathIsNonModuleName: () => ensurePathIsNonModuleName, ensureScriptKind: () => ensureScriptKind, @@ -551,7 +522,6 @@ __export(typescript_exports, { equateStringsCaseInsensitive: () => equateStringsCaseInsensitive, equateStringsCaseSensitive: () => equateStringsCaseSensitive, equateValues: () => equateValues, - esDecorateHelper: () => esDecorateHelper, escapeJsxAttributeString: () => escapeJsxAttributeString, escapeLeadingUnderscores: () => escapeLeadingUnderscores, escapeNonAsciiString: () => escapeNonAsciiString, @@ -565,15 +535,14 @@ __export(typescript_exports, { explainFiles: () => explainFiles, explainIfFileIsRedirectAndImpliedFormat: () => explainIfFileIsRedirectAndImpliedFormat, exportAssignmentIsAlias: () => exportAssignmentIsAlias, - exportStarHelper: () => exportStarHelper, expressionResultIsUnused: () => expressionResultIsUnused, extend: () => extend, - extendsHelper: () => extendsHelper, extensionFromPath: () => extensionFromPath, extensionIsTS: () => extensionIsTS, extensionsNotSupportingExtensionlessResolution: () => extensionsNotSupportingExtensionlessResolution, externalHelpersModuleNameText: () => externalHelpersModuleNameText, factory: () => factory, + fileContainsPackageImport: () => fileContainsPackageImport, fileExtensionIs: () => fileExtensionIs, fileExtensionIsOneOf: () => fileExtensionIsOneOf, fileIncludeReasonToDiagnostics: () => fileIncludeReasonToDiagnostics, @@ -595,7 +564,6 @@ __export(typescript_exports, { findLast: () => findLast, findLastIndex: () => findLastIndex, findListItemInfo: () => findListItemInfo, - findMap: () => findMap, findModifier: () => findModifier, findNextToken: () => findNextToken, findPackageJson: () => findPackageJson, @@ -643,7 +611,6 @@ __export(typescript_exports, { forEachTsConfigPropArray: () => forEachTsConfigPropArray, forEachUnique: () => forEachUnique, forEachYieldExpression: () => forEachYieldExpression, - forSomeAncestorDirectory: () => forSomeAncestorDirectory, formatColorAndReset: () => formatColorAndReset, formatDiagnostic: () => formatDiagnostic, formatDiagnostics: () => formatDiagnostics, @@ -654,11 +621,8 @@ __export(typescript_exports, { formatMessage: () => formatMessage, formatStringFromArgs: () => formatStringFromArgs, formatting: () => ts_formatting_exports, - fullTripleSlashAMDReferencePathRegEx: () => fullTripleSlashAMDReferencePathRegEx, - fullTripleSlashReferencePathRegEx: () => fullTripleSlashReferencePathRegEx, generateDjb2Hash: () => generateDjb2Hash, generateTSConfig: () => generateTSConfig, - generatorHelper: () => generatorHelper, getAdjustedReferenceLocation: () => getAdjustedReferenceLocation, getAdjustedRenameLocation: () => getAdjustedRenameLocation, getAliasDeclarationFromName: () => getAliasDeclarationFromName, @@ -677,7 +641,6 @@ __export(typescript_exports, { getAreDeclarationMapsEnabled: () => getAreDeclarationMapsEnabled, getAssignedExpandoInitializer: () => getAssignedExpandoInitializer, getAssignedName: () => getAssignedName, - getAssignedNameOfIdentifier: () => getAssignedNameOfIdentifier, getAssignmentDeclarationKind: () => getAssignmentDeclarationKind, getAssignmentDeclarationPropertyAccessKind: () => getAssignmentDeclarationPropertyAccessKind, getAssignmentTargetKind: () => getAssignmentTargetKind, @@ -718,7 +681,6 @@ __export(typescript_exports, { getContainingObjectLiteralElement: () => getContainingObjectLiteralElement, getContextualTypeFromParent: () => getContextualTypeFromParent, getContextualTypeFromParentOrAncestorTypeNode: () => getContextualTypeFromParentOrAncestorTypeNode, - getCurrentTime: () => getCurrentTime, getDeclarationDiagnostics: () => getDeclarationDiagnostics, getDeclarationEmitExtensionForPath: () => getDeclarationEmitExtensionForPath, getDeclarationEmitOutputFilePath: () => getDeclarationEmitOutputFilePath, @@ -736,6 +698,7 @@ __export(typescript_exports, { getDefaultLibFilePath: () => getDefaultLibFilePath, getDefaultLikeExportInfo: () => getDefaultLikeExportInfo, getDefaultLikeExportNameFromDeclaration: () => getDefaultLikeExportNameFromDeclaration, + getDefaultResolutionModeForFileWorker: () => getDefaultResolutionModeForFileWorker, getDiagnosticText: () => getDiagnosticText, getDiagnosticsWithinSpan: () => getDiagnosticsWithinSpan, getDirectoryPath: () => getDirectoryPath, @@ -766,6 +729,7 @@ __export(typescript_exports, { getEmitFlags: () => getEmitFlags, getEmitHelpers: () => getEmitHelpers, getEmitModuleDetectionKind: () => getEmitModuleDetectionKind, + getEmitModuleFormatOfFileWorker: () => getEmitModuleFormatOfFileWorker, getEmitModuleKind: () => getEmitModuleKind, getEmitModuleResolutionKind: () => getEmitModuleResolutionKind, getEmitScriptTarget: () => getEmitScriptTarget, @@ -816,11 +780,11 @@ __export(typescript_exports, { getIdentifierGeneratedImportReference: () => getIdentifierGeneratedImportReference, getIdentifierTypeArguments: () => getIdentifierTypeArguments, getImmediatelyInvokedFunctionExpression: () => getImmediatelyInvokedFunctionExpression, + getImpliedNodeFormatForEmitWorker: () => getImpliedNodeFormatForEmitWorker, getImpliedNodeFormatForFile: () => getImpliedNodeFormatForFile, getImpliedNodeFormatForFileWorker: () => getImpliedNodeFormatForFileWorker, getImportNeedsImportDefaultHelper: () => getImportNeedsImportDefaultHelper, getImportNeedsImportStarHelper: () => getImportNeedsImportStarHelper, - getIndentSize: () => getIndentSize, getIndentString: () => getIndentString, getInferredLibraryNameResolveFrom: () => getInferredLibraryNameResolveFrom, getInitializedVariables: () => getInitializedVariables, @@ -829,6 +793,7 @@ __export(typescript_exports, { getInterfaceBaseTypeNodes: () => getInterfaceBaseTypeNodes, getInternalEmitFlags: () => getInternalEmitFlags, getInvokedExpression: () => getInvokedExpression, + getIsFileExcluded: () => getIsFileExcluded, getIsolatedModules: () => getIsolatedModules, getJSDocAugmentsTag: () => getJSDocAugmentsTag, getJSDocClassTag: () => getJSDocClassTag, @@ -857,7 +822,6 @@ __export(typescript_exports, { getJSDocSatisfiesExpressionType: () => getJSDocSatisfiesExpressionType, getJSDocSatisfiesTag: () => getJSDocSatisfiesTag, getJSDocTags: () => getJSDocTags, - getJSDocTagsNoCache: () => getJSDocTagsNoCache, getJSDocTemplateTag: () => getJSDocTemplateTag, getJSDocThisTag: () => getJSDocThisTag, getJSDocType: () => getJSDocType, @@ -881,7 +845,6 @@ __export(typescript_exports, { getLineAndCharacterOfPosition: () => getLineAndCharacterOfPosition, getLineInfo: () => getLineInfo, getLineOfLocalPosition: () => getLineOfLocalPosition, - getLineOfLocalPositionFromLineMap: () => getLineOfLocalPositionFromLineMap, getLineStartPositionForPosition: () => getLineStartPositionForPosition, getLineStarts: () => getLineStarts, getLinesBetweenPositionAndNextNonWhitespaceCharacter: () => getLinesBetweenPositionAndNextNonWhitespaceCharacter, @@ -923,7 +886,6 @@ __export(typescript_exports, { getNameOfScriptTarget: () => getNameOfScriptTarget, getNameOrArgument: () => getNameOrArgument, getNameTable: () => getNameTable, - getNamesForExportedSymbol: () => getNamesForExportedSymbol, getNamespaceDeclarationNode: () => getNamespaceDeclarationNode, getNewLineCharacter: () => getNewLineCharacter, getNewLineKind: () => getNewLineKind, @@ -940,49 +902,43 @@ __export(typescript_exports, { getNonAssignmentOperatorForCompoundAssignment: () => getNonAssignmentOperatorForCompoundAssignment, getNonAugmentationDeclaration: () => getNonAugmentationDeclaration, getNonDecoratorTokenPosOfNode: () => getNonDecoratorTokenPosOfNode, + getNonIncrementalBuildInfoRoots: () => getNonIncrementalBuildInfoRoots, + getNonModifierTokenPosOfNode: () => getNonModifierTokenPosOfNode, getNormalizedAbsolutePath: () => getNormalizedAbsolutePath, getNormalizedAbsolutePathWithoutRoot: () => getNormalizedAbsolutePathWithoutRoot, getNormalizedPathComponents: () => getNormalizedPathComponents, getObjectFlags: () => getObjectFlags, - getOperator: () => getOperator, getOperatorAssociativity: () => getOperatorAssociativity, getOperatorPrecedence: () => getOperatorPrecedence, getOptionFromName: () => getOptionFromName, getOptionsForLibraryResolution: () => getOptionsForLibraryResolution, getOptionsNameMap: () => getOptionsNameMap, getOrCreateEmitNode: () => getOrCreateEmitNode, - getOrCreateExternalHelpersModuleNameIfNeeded: () => getOrCreateExternalHelpersModuleNameIfNeeded, getOrUpdate: () => getOrUpdate, getOriginalNode: () => getOriginalNode, getOriginalNodeId: () => getOriginalNodeId, - getOriginalSourceFile: () => getOriginalSourceFile, getOutputDeclarationFileName: () => getOutputDeclarationFileName, getOutputDeclarationFileNameWorker: () => getOutputDeclarationFileNameWorker, getOutputExtension: () => getOutputExtension, getOutputFileNames: () => getOutputFileNames, getOutputJSFileNameWorker: () => getOutputJSFileNameWorker, getOutputPathsFor: () => getOutputPathsFor, - getOutputPathsForBundle: () => getOutputPathsForBundle, getOwnEmitOutputFilePath: () => getOwnEmitOutputFilePath, getOwnKeys: () => getOwnKeys, getOwnValues: () => getOwnValues, - getPackageJsonInfo: () => getPackageJsonInfo, getPackageJsonTypesVersionsPaths: () => getPackageJsonTypesVersionsPaths, - getPackageJsonsVisibleToFile: () => getPackageJsonsVisibleToFile, getPackageNameFromTypesPackageName: () => getPackageNameFromTypesPackageName, getPackageScopeForPath: () => getPackageScopeForPath, getParameterSymbolFromJSDoc: () => getParameterSymbolFromJSDoc, - getParameterTypeNode: () => getParameterTypeNode, getParentNodeInSpan: () => getParentNodeInSpan, getParseTreeNode: () => getParseTreeNode, getParsedCommandLineOfConfigFile: () => getParsedCommandLineOfConfigFile, getPathComponents: () => getPathComponents, - getPathComponentsRelativeTo: () => getPathComponentsRelativeTo, getPathFromPathComponents: () => getPathFromPathComponents, getPathUpdater: () => getPathUpdater, getPathsBasePath: () => getPathsBasePath, getPatternFromSpec: () => getPatternFromSpec, - getPendingEmitKind: () => getPendingEmitKind, + getPendingEmitKindWithSeen: () => getPendingEmitKindWithSeen, getPositionOfLineAndCharacter: () => getPositionOfLineAndCharacter, getPossibleGenericSignatures: () => getPossibleGenericSignatures, getPossibleOriginalInputExtensionForExtension: () => getPossibleOriginalInputExtensionForExtension, @@ -995,7 +951,6 @@ __export(typescript_exports, { getPropertyArrayElementValue: () => getPropertyArrayElementValue, getPropertyAssignmentAliasLikeExpression: () => getPropertyAssignmentAliasLikeExpression, getPropertyNameForPropertyNameNode: () => getPropertyNameForPropertyNameNode, - getPropertyNameForUniqueESSymbol: () => getPropertyNameForUniqueESSymbol, getPropertyNameFromType: () => getPropertyNameFromType, getPropertyNameOfBindingOrAssignmentElement: () => getPropertyNameOfBindingOrAssignmentElement, getPropertySymbolFromBindingElement: () => getPropertySymbolFromBindingElement, @@ -1019,13 +974,14 @@ __export(typescript_exports, { getResolvePackageJsonExports: () => getResolvePackageJsonExports, getResolvePackageJsonImports: () => getResolvePackageJsonImports, getResolvedExternalModuleName: () => getResolvedExternalModuleName, + getResolvedModuleFromResolution: () => getResolvedModuleFromResolution, + getResolvedTypeReferenceDirectiveFromResolution: () => getResolvedTypeReferenceDirectiveFromResolution, getRestIndicatorOfBindingOrAssignmentElement: () => getRestIndicatorOfBindingOrAssignmentElement, getRestParameterElementType: () => getRestParameterElementType, getRightMostAssignedExpression: () => getRightMostAssignedExpression, getRootDeclaration: () => getRootDeclaration, getRootDirectoryOfResolutionCache: () => getRootDirectoryOfResolutionCache, getRootLength: () => getRootLength, - getRootPathSplitLength: () => getRootPathSplitLength, getScriptKind: () => getScriptKind, getScriptKindFromFileName: () => getScriptKindFromFileName, getScriptTargetFeatures: () => getScriptTargetFeatures, @@ -1037,14 +993,12 @@ __export(typescript_exports, { getSetAccessorValueParameter: () => getSetAccessorValueParameter, getSetExternalModuleIndicator: () => getSetExternalModuleIndicator, getShebang: () => getShebang, - getSingleInitializerOfVariableStatementOrPropertyDeclaration: () => getSingleInitializerOfVariableStatementOrPropertyDeclaration, getSingleVariableOfVariableStatement: () => getSingleVariableOfVariableStatement, getSnapshotText: () => getSnapshotText, getSnippetElement: () => getSnippetElement, getSourceFileOfModule: () => getSourceFileOfModule, getSourceFileOfNode: () => getSourceFileOfNode, getSourceFilePathInNewDir: () => getSourceFilePathInNewDir, - getSourceFilePathInNewDirWorker: () => getSourceFilePathInNewDirWorker, getSourceFileVersionAsHashFromText: () => getSourceFileVersionAsHashFromText, getSourceFilesToEmit: () => getSourceFilesToEmit, getSourceMapRange: () => getSourceMapRange, @@ -1067,7 +1021,6 @@ __export(typescript_exports, { getSwitchedType: () => getSwitchedType, getSymbolId: () => getSymbolId, getSymbolNameForPrivateIdentifier: () => getSymbolNameForPrivateIdentifier, - getSymbolParentOrFail: () => getSymbolParentOrFail, getSymbolTarget: () => getSymbolTarget, getSyntacticClassifications: () => getSyntacticClassifications, getSyntacticModifierFlags: () => getSyntacticModifierFlags, @@ -1098,7 +1051,6 @@ __export(typescript_exports, { getTouchingToken: () => getTouchingToken, getTrailingCommentRanges: () => getTrailingCommentRanges, getTrailingSemicolonDeferringWriter: () => getTrailingSemicolonDeferringWriter, - getTransformFlagsSubtreeExclusions: () => getTransformFlagsSubtreeExclusions, getTransformers: () => getTransformers, getTsBuildInfoEmitOutputFilePath: () => getTsBuildInfoEmitOutputFilePath, getTsConfigObjectLiteralExpression: () => getTsConfigObjectLiteralExpression, @@ -1126,7 +1078,6 @@ __export(typescript_exports, { hasAccessorModifier: () => hasAccessorModifier, hasAmbientModifier: () => hasAmbientModifier, hasChangesInResolutions: () => hasChangesInResolutions, - hasChildOfKind: () => hasChildOfKind, hasContextSensitiveParameters: () => hasContextSensitiveParameters, hasDecorators: () => hasDecorators, hasDocComment: () => hasDocComment, @@ -1135,6 +1086,7 @@ __export(typescript_exports, { hasEffectiveModifiers: () => hasEffectiveModifiers, hasEffectiveReadonlyModifier: () => hasEffectiveReadonlyModifier, hasExtension: () => hasExtension, + hasImplementationTSFileExtension: () => hasImplementationTSFileExtension, hasIndexSignature: () => hasIndexSignature, hasInferredType: () => hasInferredType, hasInitializer: () => hasInitializer, @@ -1162,7 +1114,6 @@ __export(typescript_exports, { hasType: () => hasType, hasTypeArguments: () => hasTypeArguments, hasZeroOrOneAsteriskCharacter: () => hasZeroOrOneAsteriskCharacter, - helperString: () => helperString, hostGetCanonicalFileName: () => hostGetCanonicalFileName, hostUsesCaseSensitiveFileNames: () => hostUsesCaseSensitiveFileNames, idText: () => idText, @@ -1172,9 +1123,8 @@ __export(typescript_exports, { identitySourceMapConsumer: () => identitySourceMapConsumer, ignoreSourceNewlines: () => ignoreSourceNewlines, ignoredPaths: () => ignoredPaths, - importDefaultHelper: () => importDefaultHelper, importFromModuleSpecifier: () => importFromModuleSpecifier, - importStarHelper: () => importStarHelper, + importSyntaxAffectsModuleResolution: () => importSyntaxAffectsModuleResolution, indexOfAnyCharCode: () => indexOfAnyCharCode, indexOfNode: () => indexOfNode, indicesOf: () => indicesOf, @@ -1182,7 +1132,6 @@ __export(typescript_exports, { injectClassNamedEvaluationHelperBlockIfMissing: () => injectClassNamedEvaluationHelperBlockIfMissing, injectClassThisAssignmentIfMissing: () => injectClassThisAssignmentIfMissing, insertImports: () => insertImports, - insertLeadingStatement: () => insertLeadingStatement, insertSorted: () => insertSorted, insertStatementAfterCustomPrologue: () => insertStatementAfterCustomPrologue, insertStatementAfterStandardPrologue: () => insertStatementAfterStandardPrologue, @@ -1198,11 +1147,9 @@ __export(typescript_exports, { isAccessibilityModifier: () => isAccessibilityModifier, isAccessor: () => isAccessor, isAccessorModifier: () => isAccessorModifier, - isAliasSymbolDeclaration: () => isAliasSymbolDeclaration, isAliasableExpression: () => isAliasableExpression, isAmbientModule: () => isAmbientModule, isAmbientPropertyDeclaration: () => isAmbientPropertyDeclaration, - isAnonymousFunctionDefinition: () => isAnonymousFunctionDefinition, isAnyDirectorySeparator: () => isAnyDirectorySeparator, isAnyImportOrBareOrAccessedRequire: () => isAnyImportOrBareOrAccessedRequire, isAnyImportOrReExport: () => isAnyImportOrReExport, @@ -1238,6 +1185,7 @@ __export(typescript_exports, { isAwaitKeyword: () => isAwaitKeyword, isBigIntLiteral: () => isBigIntLiteral, isBinaryExpression: () => isBinaryExpression, + isBinaryLogicalOperator: () => isBinaryLogicalOperator, isBinaryOperatorToken: () => isBinaryOperatorToken, isBindableObjectDefinePropertyCall: () => isBindableObjectDefinePropertyCall, isBindableStaticAccessExpression: () => isBindableStaticAccessExpression, @@ -1259,7 +1207,7 @@ __export(typescript_exports, { isBreakStatement: () => isBreakStatement, isBuild: () => isBuild, isBuildInfoFile: () => isBuildInfoFile, - isBuilderProgram: () => isBuilderProgram2, + isBuilderProgram: () => isBuilderProgram, isBundle: () => isBundle, isCallChain: () => isCallChain, isCallExpression: () => isCallExpression, @@ -1278,7 +1226,6 @@ __export(typescript_exports, { isCatchClauseVariableDeclaration: () => isCatchClauseVariableDeclaration, isCatchClauseVariableDeclarationOrBindingElement: () => isCatchClauseVariableDeclarationOrBindingElement, isCheckJsEnabledForFile: () => isCheckJsEnabledForFile, - isChildOfNodeWithKind: () => isChildOfNodeWithKind, isCircularBuildOrder: () => isCircularBuildOrder, isClassDeclaration: () => isClassDeclaration, isClassElement: () => isClassElement, @@ -1290,7 +1237,6 @@ __export(typescript_exports, { isClassOrTypeElement: () => isClassOrTypeElement, isClassStaticBlockDeclaration: () => isClassStaticBlockDeclaration, isClassThisAssignmentBlock: () => isClassThisAssignmentBlock, - isCollapsedRange: () => isCollapsedRange, isColonToken: () => isColonToken, isCommaExpression: () => isCommaExpression, isCommaListExpression: () => isCommaListExpression, @@ -1333,16 +1279,13 @@ __export(typescript_exports, { isDeleteTarget: () => isDeleteTarget, isDeprecatedDeclaration: () => isDeprecatedDeclaration, isDestructuringAssignment: () => isDestructuringAssignment, - isDiagnosticWithLocation: () => isDiagnosticWithLocation, isDiskPathRoot: () => isDiskPathRoot, isDoStatement: () => isDoStatement, isDocumentRegistryEntry: () => isDocumentRegistryEntry, isDotDotDotToken: () => isDotDotDotToken, isDottedName: () => isDottedName, isDynamicName: () => isDynamicName, - isESSymbolIdentifier: () => isESSymbolIdentifier, isEffectiveExternalModule: () => isEffectiveExternalModule, - isEffectiveModuleDeclaration: () => isEffectiveModuleDeclaration, isEffectiveStrictModeSourceFile: () => isEffectiveStrictModeSourceFile, isElementAccessChain: () => isElementAccessChain, isElementAccessExpression: () => isElementAccessExpression, @@ -1412,13 +1355,11 @@ __export(typescript_exports, { isFunctionOrModuleBlock: () => isFunctionOrModuleBlock, isFunctionSymbol: () => isFunctionSymbol, isFunctionTypeNode: () => isFunctionTypeNode, - isFutureReservedKeyword: () => isFutureReservedKeyword, isGeneratedIdentifier: () => isGeneratedIdentifier, isGeneratedPrivateIdentifier: () => isGeneratedPrivateIdentifier, isGetAccessor: () => isGetAccessor, isGetAccessorDeclaration: () => isGetAccessorDeclaration, isGetOrSetAccessorDeclaration: () => isGetOrSetAccessorDeclaration, - isGlobalDeclaration: () => isGlobalDeclaration, isGlobalScopeAugmentation: () => isGlobalScopeAugmentation, isGlobalSourceFile: () => isGlobalSourceFile, isGrammarError: () => isGrammarError, @@ -1466,6 +1407,8 @@ __export(typescript_exports, { isInTemplateString: () => isInTemplateString, isInTopLevelContext: () => isInTopLevelContext, isInTypeQuery: () => isInTypeQuery, + isIncrementalBuildInfo: () => isIncrementalBuildInfo, + isIncrementalBundleEmitBuildInfo: () => isIncrementalBundleEmitBuildInfo, isIncrementalCompilation: () => isIncrementalCompilation, isIndexSignatureDeclaration: () => isIndexSignatureDeclaration, isIndexedAccessTypeNode: () => isIndexedAccessTypeNode, @@ -1572,7 +1515,6 @@ __export(typescript_exports, { isLabeledStatement: () => isLabeledStatement, isLateVisibilityPaintedStatement: () => isLateVisibilityPaintedStatement, isLeftHandSideExpression: () => isLeftHandSideExpression, - isLeftHandSideOfAssignment: () => isLeftHandSideOfAssignment, isLet: () => isLet, isLineBreak: () => isLineBreak, isLiteralComputedPropertyDeclarationName: () => isLiteralComputedPropertyDeclarationName, @@ -1580,10 +1522,7 @@ __export(typescript_exports, { isLiteralExpressionOfObject: () => isLiteralExpressionOfObject, isLiteralImportTypeNode: () => isLiteralImportTypeNode, isLiteralKind: () => isLiteralKind, - isLiteralLikeAccess: () => isLiteralLikeAccess, - isLiteralLikeElementAccess: () => isLiteralLikeElementAccess, isLiteralNameOfPropertyDeclarationOrIndexAccess: () => isLiteralNameOfPropertyDeclarationOrIndexAccess, - isLiteralTypeLikeExpression: () => isLiteralTypeLikeExpression, isLiteralTypeLiteral: () => isLiteralTypeLiteral, isLiteralTypeNode: () => isLiteralTypeNode, isLocalName: () => isLocalName, @@ -1608,6 +1547,7 @@ __export(typescript_exports, { isModuleBlock: () => isModuleBlock, isModuleBody: () => isModuleBody, isModuleDeclaration: () => isModuleDeclaration, + isModuleExportName: () => isModuleExportName, isModuleExportsAccessExpression: () => isModuleExportsAccessExpression, isModuleIdentifier: () => isModuleIdentifier, isModuleName: () => isModuleName, @@ -1617,7 +1557,6 @@ __export(typescript_exports, { isModuleWithStringLiteralName: () => isModuleWithStringLiteralName, isNameOfFunctionDeclaration: () => isNameOfFunctionDeclaration, isNameOfModuleDeclaration: () => isNameOfModuleDeclaration, - isNamedClassElement: () => isNamedClassElement, isNamedDeclaration: () => isNamedDeclaration, isNamedEvaluation: () => isNamedEvaluation, isNamedEvaluationSource: () => isNamedEvaluationSource, @@ -1635,7 +1574,6 @@ __export(typescript_exports, { isNewExpression: () => isNewExpression, isNewExpressionTarget: () => isNewExpressionTarget, isNoSubstitutionTemplateLiteral: () => isNoSubstitutionTemplateLiteral, - isNode: () => isNode, isNodeArray: () => isNodeArray, isNodeArrayMultiLine: () => isNodeArrayMultiLine, isNodeDescendantOf: () => isNodeDescendantOf, @@ -1644,14 +1582,11 @@ __export(typescript_exports, { isNodeModulesDirectory: () => isNodeModulesDirectory, isNodeWithPossibleHoistedDeclaration: () => isNodeWithPossibleHoistedDeclaration, isNonContextualKeyword: () => isNonContextualKeyword, - isNonExportDefaultModifier: () => isNonExportDefaultModifier, isNonGlobalAmbientModule: () => isNonGlobalAmbientModule, - isNonGlobalDeclaration: () => isNonGlobalDeclaration, isNonNullAccess: () => isNonNullAccess, isNonNullChain: () => isNonNullChain, isNonNullExpression: () => isNonNullExpression, isNonStaticMethodOrAccessorWithPrivateName: () => isNonStaticMethodOrAccessorWithPrivateName, - isNotEmittedOrPartiallyEmittedNode: () => isNotEmittedOrPartiallyEmittedNode, isNotEmittedStatement: () => isNotEmittedStatement, isNullishCoalesce: () => isNullishCoalesce, isNumber: () => isNumber, @@ -1667,7 +1602,6 @@ __export(typescript_exports, { isObjectLiteralMethod: () => isObjectLiteralMethod, isObjectLiteralOrClassExpressionMethodOrAccessor: () => isObjectLiteralOrClassExpressionMethodOrAccessor, isObjectTypeDeclaration: () => isObjectTypeDeclaration, - isOctalDigit: () => isOctalDigit, isOmittedExpression: () => isOmittedExpression, isOptionalChain: () => isOptionalChain, isOptionalChainRoot: () => isOptionalChainRoot, @@ -1701,7 +1635,6 @@ __export(typescript_exports, { isPrivateIdentifierClassElementDeclaration: () => isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression: () => isPrivateIdentifierPropertyAccessExpression, isPrivateIdentifierSymbol: () => isPrivateIdentifierSymbol, - isProgramBundleEmitBuildInfo: () => isProgramBundleEmitBuildInfo, isProgramUptoDate: () => isProgramUptoDate, isPrologueDirective: () => isPrologueDirective, isPropertyAccessChain: () => isPropertyAccessChain, @@ -1714,7 +1647,6 @@ __export(typescript_exports, { isPropertyName: () => isPropertyName, isPropertyNameLiteral: () => isPropertyNameLiteral, isPropertySignature: () => isPropertySignature, - isProtoSetter: () => isProtoSetter, isPrototypeAccess: () => isPrototypeAccess, isPrototypePropertyAssignment: () => isPrototypePropertyAssignment, isPunctuation: () => isPunctuation, @@ -1724,7 +1656,6 @@ __export(typescript_exports, { isQuestionOrExclamationToken: () => isQuestionOrExclamationToken, isQuestionOrPlusOrMinusToken: () => isQuestionOrPlusOrMinusToken, isQuestionToken: () => isQuestionToken, - isRawSourceMap: () => isRawSourceMap, isReadonlyKeyword: () => isReadonlyKeyword, isReadonlyKeywordOrPlusOrMinusToken: () => isReadonlyKeywordOrPlusOrMinusToken, isRecognizedTripleSlashComment: () => isRecognizedTripleSlashComment, @@ -1746,24 +1677,22 @@ __export(typescript_exports, { isRootedDiskPath: () => isRootedDiskPath, isSameEntityName: () => isSameEntityName, isSatisfiesExpression: () => isSatisfiesExpression, - isScopeMarker: () => isScopeMarker, isSemicolonClassElement: () => isSemicolonClassElement, isSetAccessor: () => isSetAccessor, isSetAccessorDeclaration: () => isSetAccessorDeclaration, - isShebangTrivia: () => isShebangTrivia, isShiftOperatorOrHigher: () => isShiftOperatorOrHigher, isShorthandAmbientModuleSymbol: () => isShorthandAmbientModuleSymbol, isShorthandPropertyAssignment: () => isShorthandPropertyAssignment, + isSideEffectImport: () => isSideEffectImport, isSignedNumericLiteral: () => isSignedNumericLiteral, isSimpleCopiableExpression: () => isSimpleCopiableExpression, isSimpleInlineableExpression: () => isSimpleInlineableExpression, - isSimpleParameter: () => isSimpleParameter, isSimpleParameterList: () => isSimpleParameterList, isSingleOrDoubleQuote: () => isSingleOrDoubleQuote, + isSourceElement: () => isSourceElement, isSourceFile: () => isSourceFile, isSourceFileFromLibrary: () => isSourceFileFromLibrary, isSourceFileJS: () => isSourceFileJS, - isSourceFileNotJS: () => isSourceFileNotJS, isSourceFileNotJson: () => isSourceFileNotJson, isSourceMapping: () => isSourceMapping, isSpecialPropertyDeclaration: () => isSpecialPropertyDeclaration, @@ -1776,7 +1705,6 @@ __export(typescript_exports, { isStatic: () => isStatic, isStaticModifier: () => isStaticModifier, isString: () => isString, - isStringAKeyword: () => isStringAKeyword, isStringANonContextualKeyword: () => isStringANonContextualKeyword, isStringAndEmptyAnonymousObjectIntersection: () => isStringAndEmptyAnonymousObjectIntersection, isStringDoubleQuoted: () => isStringDoubleQuoted, @@ -1789,7 +1717,6 @@ __export(typescript_exports, { isStringTextContainingNode: () => isStringTextContainingNode, isSuperCall: () => isSuperCall, isSuperKeyword: () => isSuperKeyword, - isSuperOrSuperProperty: () => isSuperOrSuperProperty, isSuperProperty: () => isSuperProperty, isSupportedSourceFileName: () => isSupportedSourceFileName, isSwitchStatement: () => isSwitchStatement, @@ -1835,7 +1762,6 @@ __export(typescript_exports, { isTypeDeclaration: () => isTypeDeclaration, isTypeElement: () => isTypeElement, isTypeKeyword: () => isTypeKeyword, - isTypeKeywordToken: () => isTypeKeywordToken, isTypeKeywordTokenOrIdentifier: () => isTypeKeywordTokenOrIdentifier, isTypeLiteralNode: () => isTypeLiteralNode, isTypeNode: () => isTypeNode, @@ -1890,10 +1816,6 @@ __export(typescript_exports, { libMap: () => libMap, libs: () => libs, lineBreakPart: () => lineBreakPart, - linkNamePart: () => linkNamePart, - linkPart: () => linkPart, - linkTextPart: () => linkTextPart, - listFiles: () => listFiles, loadModuleFromGlobalCache: () => loadModuleFromGlobalCache, loadWithModeAwareCache: () => loadWithModeAwareCache, makeIdentifierFromModuleName: () => makeIdentifierFromModuleName, @@ -1903,7 +1825,6 @@ __export(typescript_exports, { map: () => map, mapAllOrFail: () => mapAllOrFail, mapDefined: () => mapDefined, - mapDefinedEntries: () => mapDefinedEntries, mapDefinedIterator: () => mapDefinedIterator, mapEntries: () => mapEntries, mapIterator: () => mapIterator, @@ -1913,18 +1834,19 @@ __export(typescript_exports, { matchPatternOrExact: () => matchPatternOrExact, matchedText: () => matchedText, matchesExclude: () => matchesExclude, + maxBy: () => maxBy, maybeBind: () => maybeBind, maybeSetLocalizedDiagnosticMessages: () => maybeSetLocalizedDiagnosticMessages, memoize: () => memoize, - memoizeCached: () => memoizeCached, memoizeOne: () => memoizeOne, - memoizeWeak: () => memoizeWeak, - metadataHelper: () => metadataHelper, min: () => min, minAndMax: () => minAndMax, missingFileModifiedTime: () => missingFileModifiedTime, modifierToFlag: () => modifierToFlag, modifiersToFlags: () => modifiersToFlags, + moduleExportNameIsDefault: () => moduleExportNameIsDefault, + moduleExportNameTextEscaped: () => moduleExportNameTextEscaped, + moduleExportNameTextUnescaped: () => moduleExportNameTextUnescaped, moduleOptionDeclaration: () => moduleOptionDeclaration, moduleResolutionIsEqualTo: () => moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter: () => moduleResolutionNameAndModeGetter, @@ -1964,11 +1886,11 @@ __export(typescript_exports, { nodePosToString: () => nodePosToString, nodeSeenTracker: () => nodeSeenTracker, nodeStartsNewLexicalEnvironment: () => nodeStartsNewLexicalEnvironment, - nodeToDisplayParts: () => nodeToDisplayParts, noop: () => noop, noopFileWatcher: () => noopFileWatcher, normalizePath: () => normalizePath, normalizeSlashes: () => normalizeSlashes, + normalizeSpans: () => normalizeSpans, not: () => not, notImplemented: () => notImplemented, notImplementedResolver: () => notImplementedResolver, @@ -1983,13 +1905,11 @@ __export(typescript_exports, { optionsForBuild: () => optionsForBuild, optionsForWatch: () => optionsForWatch, optionsHaveChanges: () => optionsHaveChanges, - optionsHaveModuleResolutionChanges: () => optionsHaveModuleResolutionChanges, or: () => or, orderedRemoveItem: () => orderedRemoveItem, orderedRemoveItemAt: () => orderedRemoveItemAt, packageIdToPackageName: () => packageIdToPackageName, packageIdToString: () => packageIdToString, - paramHelper: () => paramHelper, parameterIsThisKeyword: () => parameterIsThisKeyword, parameterNamePart: () => parameterNamePart, parseBaseNodeFactory: () => parseBaseNodeFactory, @@ -2020,10 +1940,8 @@ __export(typescript_exports, { pathIsBareSpecifier: () => pathIsBareSpecifier, pathIsRelative: () => pathIsRelative, patternText: () => patternText, - perfLogger: () => perfLogger, performIncrementalCompilation: () => performIncrementalCompilation, performance: () => ts_performance_exports, - plainJSErrors: () => plainJSErrors, positionBelongsToNode: () => positionBelongsToNode, positionIsASICandidate: () => positionIsASICandidate, positionIsSynthesized: () => positionIsSynthesized, @@ -2036,7 +1954,6 @@ __export(typescript_exports, { programContainsEsModules: () => programContainsEsModules, programContainsModules: () => programContainsModules, projectReferenceIsEqualTo: () => projectReferenceIsEqualTo, - propKeyHelper: () => propKeyHelper, propertyNamePart: () => propertyNamePart, pseudoBigIntToString: () => pseudoBigIntToString, punctuationPart: () => punctuationPart, @@ -2059,7 +1976,6 @@ __export(typescript_exports, { rangeStartPositionsAreOnSameLine: () => rangeStartPositionsAreOnSameLine, readBuilderProgram: () => readBuilderProgram, readConfigFile: () => readConfigFile, - readHelper: () => readHelper, readJson: () => readJson, readJsonConfigFile: () => readJsonConfigFile, readJsonOrUndefined: () => readJsonOrUndefined, @@ -2070,7 +1986,7 @@ __export(typescript_exports, { reducePathComponents: () => reducePathComponents, refactor: () => ts_refactor_exports, regExpEscape: () => regExpEscape, - regularExpressionFlagToCharacter: () => regularExpressionFlagToCharacter, + regularExpressionFlagToCharacterCode: () => regularExpressionFlagToCharacterCode, relativeComplement: () => relativeComplement, removeAllComments: () => removeAllComments, removeEmitHelper: () => removeEmitHelper, @@ -2078,7 +1994,6 @@ __export(typescript_exports, { removeFileExtension: () => removeFileExtension, removeIgnoredPath: () => removeIgnoredPath, removeMinAndVersionNumbers: () => removeMinAndVersionNumbers, - removeOptionality: () => removeOptionality, removePrefix: () => removePrefix, removeSuffix: () => removeSuffix, removeTrailingDirectorySeparator: () => removeTrailingDirectorySeparator, @@ -2097,20 +2012,16 @@ __export(typescript_exports, { resolveTripleslashReference: () => resolveTripleslashReference, resolveTypeReferenceDirective: () => resolveTypeReferenceDirective, resolvingEmptyArray: () => resolvingEmptyArray, - restHelper: () => restHelper, returnFalse: () => returnFalse, returnNoopFileWatcher: () => returnNoopFileWatcher, returnTrue: () => returnTrue, returnUndefined: () => returnUndefined, returnsPromise: () => returnsPromise, - runInitializersHelper: () => runInitializersHelper, sameFlatMap: () => sameFlatMap, sameMap: () => sameMap, sameMapping: () => sameMapping, - scanShebangTrivia: () => scanShebangTrivia, scanTokenAtPosition: () => scanTokenAtPosition, scanner: () => scanner, - screenStartingMessageCodes: () => screenStartingMessageCodes, semanticDiagnosticsOptionDeclarations: () => semanticDiagnosticsOptionDeclarations, serializeCompilerOptions: () => serializeCompilerOptions, server: () => ts_server_exports4, @@ -2118,16 +2029,13 @@ __export(typescript_exports, { setCommentRange: () => setCommentRange, setConfigFileInOptions: () => setConfigFileInOptions, setConstantValue: () => setConstantValue, - setEachParent: () => setEachParent, setEmitFlags: () => setEmitFlags, - setFunctionNameHelper: () => setFunctionNameHelper, setGetSourceFileAsHashVersioned: () => setGetSourceFileAsHashVersioned, setIdentifierAutoGenerate: () => setIdentifierAutoGenerate, setIdentifierGeneratedImportReference: () => setIdentifierGeneratedImportReference, setIdentifierTypeArguments: () => setIdentifierTypeArguments, setInternalEmitFlags: () => setInternalEmitFlags, setLocalizedDiagnosticMessages: () => setLocalizedDiagnosticMessages, - setModuleDefaultHelper: () => setModuleDefaultHelper, setNodeChildren: () => setNodeChildren, setNodeFlags: () => setNodeFlags, setObjectAllocator: () => setObjectAllocator, @@ -2156,7 +2064,6 @@ __export(typescript_exports, { shouldPreserveConstEnums: () => shouldPreserveConstEnums, shouldUseUriStyleNodeCoreModules: () => shouldUseUriStyleNodeCoreModules, showModuleSpecifier: () => showModuleSpecifier, - signatureHasLiteralTypes: () => signatureHasLiteralTypes, signatureHasRestParameter: () => signatureHasRestParameter, signatureToDisplayParts: () => signatureToDisplayParts, single: () => single, @@ -2165,18 +2072,17 @@ __export(typescript_exports, { singleOrMany: () => singleOrMany, singleOrUndefined: () => singleOrUndefined, skipAlias: () => skipAlias, - skipAssertions: () => skipAssertions, skipConstraint: () => skipConstraint, skipOuterExpressions: () => skipOuterExpressions, skipParentheses: () => skipParentheses, skipPartiallyEmittedExpressions: () => skipPartiallyEmittedExpressions, skipTrivia: () => skipTrivia, skipTypeChecking: () => skipTypeChecking, + skipTypeCheckingIgnoringNoCheck: () => skipTypeCheckingIgnoringNoCheck, skipTypeParentheses: () => skipTypeParentheses, skipWhile: () => skipWhile, sliceAfter: () => sliceAfter, some: () => some, - sort: () => sort, sortAndDeduplicate: () => sortAndDeduplicate, sortAndDeduplicateDiagnostics: () => sortAndDeduplicateDiagnostics, sourceFileAffectingCompilerOptions: () => sourceFileAffectingCompilerOptions, @@ -2185,8 +2091,6 @@ __export(typescript_exports, { sourceMapCommentRegExpDontCareLineStart: () => sourceMapCommentRegExpDontCareLineStart, spacePart: () => spacePart, spanMap: () => spanMap, - spreadArrayHelper: () => spreadArrayHelper, - stableSort: () => stableSort, startEndContainsRange: () => startEndContainsRange, startEndOverlapsWithStartEnd: () => startEndOverlapsWithStartEnd, startOnNewLine: () => startOnNewLine, @@ -2199,10 +2103,8 @@ __export(typescript_exports, { stringToToken: () => stringToToken, stripQuotes: () => stripQuotes, supportedDeclarationExtensions: () => supportedDeclarationExtensions, - supportedJSExtensions: () => supportedJSExtensions, supportedJSExtensionsFlat: () => supportedJSExtensionsFlat, supportedLocaleDirectories: () => supportedLocaleDirectories, - supportedTSExtensions: () => supportedTSExtensions, supportedTSExtensionsFlat: () => supportedTSExtensionsFlat, supportedTSImplementationExtensions: () => supportedTSImplementationExtensions, suppressLeadingAndTrailingTrivia: () => suppressLeadingAndTrailingTrivia, @@ -2211,16 +2113,12 @@ __export(typescript_exports, { symbolEscapedNameNoDefault: () => symbolEscapedNameNoDefault, symbolName: () => symbolName, symbolNameNoDefault: () => symbolNameNoDefault, - symbolPart: () => symbolPart, symbolToDisplayParts: () => symbolToDisplayParts, - syntaxMayBeASICandidate: () => syntaxMayBeASICandidate, - syntaxRequiresTrailingSemicolonOrASI: () => syntaxRequiresTrailingSemicolonOrASI, sys: () => sys, sysLog: () => sysLog, tagNamesAreEquivalent: () => tagNamesAreEquivalent, takeWhile: () => takeWhile, targetOptionDeclaration: () => targetOptionDeclaration, - templateObjectHelper: () => templateObjectHelper, testFormatSettings: () => testFormatSettings, textChangeRangeIsUnchanged: () => textChangeRangeIsUnchanged, textChangeRangeNewSpan: () => textChangeRangeNewSpan, @@ -2228,7 +2126,10 @@ __export(typescript_exports, { textOrKeywordPart: () => textOrKeywordPart, textPart: () => textPart, textRangeContainsPositionInclusive: () => textRangeContainsPositionInclusive, + textRangeContainsTextSpan: () => textRangeContainsTextSpan, + textRangeIntersectsWithTextSpan: () => textRangeIntersectsWithTextSpan, textSpanContainsPosition: () => textSpanContainsPosition, + textSpanContainsTextRange: () => textSpanContainsTextRange, textSpanContainsTextSpan: () => textSpanContainsTextSpan, textSpanEnd: () => textSpanEnd, textSpanIntersection: () => textSpanIntersection, @@ -2246,15 +2147,16 @@ __export(typescript_exports, { toBuilderStateFileInfoForMultiEmit: () => toBuilderStateFileInfoForMultiEmit, toEditorSettings: () => toEditorSettings, toFileNameLowerCase: () => toFileNameLowerCase, - toLowerCase: () => toLowerCase, toPath: () => toPath, toProgramEmitPending: () => toProgramEmitPending, + toSorted: () => toSorted, tokenIsIdentifierOrKeyword: () => tokenIsIdentifierOrKeyword, tokenIsIdentifierOrKeywordOrGreaterThan: () => tokenIsIdentifierOrKeywordOrGreaterThan, tokenToString: () => tokenToString, trace: () => trace, tracing: () => tracing, tracingEnabled: () => tracingEnabled, + transferSourceFileChildren: () => transferSourceFileChildren, transform: () => transform, transformClassFields: () => transformClassFields, transformDeclarations: () => transformDeclarations, @@ -2269,11 +2171,11 @@ __export(typescript_exports, { transformESDecorators: () => transformESDecorators, transformESNext: () => transformESNext, transformGenerators: () => transformGenerators, + transformImpliedNodeFormatDependentModule: () => transformImpliedNodeFormatDependentModule, transformJsx: () => transformJsx, transformLegacyDecorators: () => transformLegacyDecorators, transformModule: () => transformModule, transformNamedEvaluation: () => transformNamedEvaluation, - transformNodeModule: () => transformNodeModule, transformNodes: () => transformNodes, transformSystemModule: () => transformSystemModule, transformTypeScript: () => transformTypeScript, @@ -2300,7 +2202,6 @@ __export(typescript_exports, { tryGetPropertyNameOfBindingOrAssignmentElement: () => tryGetPropertyNameOfBindingOrAssignmentElement, tryGetSourceMappingURL: () => tryGetSourceMappingURL, tryGetTextOfPropertyName: () => tryGetTextOfPropertyName, - tryIOAndConsumeErrors: () => tryIOAndConsumeErrors, tryParseJson: () => tryParseJson, tryParsePattern: () => tryParsePattern, tryParsePatterns: () => tryParsePatterns, @@ -2322,7 +2223,6 @@ __export(typescript_exports, { unescapeLeadingUnderscores: () => unescapeLeadingUnderscores, unmangleScopedPackageName: () => unmangleScopedPackageName, unorderedRemoveItem: () => unorderedRemoveItem, - unorderedRemoveItemAt: () => unorderedRemoveItemAt, unreachableCodeIsError: () => unreachableCodeIsError, unsetNodeChildren: () => unsetNodeChildren, unusedLabelIsError: () => unusedLabelIsError, @@ -2335,11 +2235,9 @@ __export(typescript_exports, { updateSharedExtendedConfigFileWatcher: () => updateSharedExtendedConfigFileWatcher, updateSourceFile: () => updateSourceFile, updateWatchingWildcardDirectories: () => updateWatchingWildcardDirectories, - usesExtensionsOnImports: () => usesExtensionsOnImports, usingSingleLineStringWriter: () => usingSingleLineStringWriter, utf16EncodeAsString: () => utf16EncodeAsString, validateLocaleAndSetLanguage: () => validateLocaleAndSetLanguage, - valuesHelper: () => valuesHelper, version: () => version, versionMajorMinor: () => versionMajorMinor, visitArray: () => visitArray, @@ -2352,7 +2250,6 @@ __export(typescript_exports, { visitNodes: () => visitNodes2, visitParameterList: () => visitParameterList, walkUpBindingElementsAndPatterns: () => walkUpBindingElementsAndPatterns, - walkUpLexicalEnvironments: () => walkUpLexicalEnvironments, walkUpOuterExpressions: () => walkUpOuterExpressions, walkUpParenthesizedExpressions: () => walkUpParenthesizedExpressions, walkUpParenthesizedTypes: () => walkUpParenthesizedTypes, @@ -2366,8 +2263,8 @@ __export(typescript_exports, { module.exports = __toCommonJS(typescript_exports); // src/compiler/corePublic.ts -var versionMajorMinor = "5.5"; -var version = "5.5.2"; +var versionMajorMinor = "5.6"; +var version = "5.6.2"; var Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -2378,12 +2275,11 @@ var Comparison = /* @__PURE__ */ ((Comparison3) => { // src/compiler/core.ts var emptyArray = []; var emptyMap = /* @__PURE__ */ new Map(); -var emptySet = /* @__PURE__ */ new Set(); function length(array) { - return array ? array.length : 0; + return array !== void 0 ? array.length : 0; } function forEach(array, callback) { - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const result = callback(array[i], i); if (result) { @@ -2394,7 +2290,7 @@ function forEach(array, callback) { return void 0; } function forEachRight(array, callback) { - if (array) { + if (array !== void 0) { for (let i = array.length - 1; i >= 0; i--) { const result = callback(array[i], i); if (result) { @@ -2450,13 +2346,13 @@ function intersperse(input, element) { } const result = []; for (let i = 0, n = input.length; i < n; i++) { - if (i) result.push(element); + if (i !== 0) result.push(element); result.push(input[i]); } return result; } function every(array, callback) { - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { if (!callback(array[i], i)) { return false; @@ -2503,30 +2399,18 @@ function findLastIndex(array, predicate, startIndex) { } return -1; } -function findMap(array, callback) { - for (let i = 0; i < array.length; i++) { - const result = callback(array[i], i); - if (result) { - return result; - } - } - return Debug.fail(); -} function contains(array, value, equalityComparer = equateValues) { - if (array) { - for (const v of array) { - if (equalityComparer(v, value)) { + if (array !== void 0) { + for (let i = 0; i < array.length; i++) { + if (equalityComparer(array[i], value)) { return true; } } } return false; } -function arraysEqual(a, b, equalityComparer = equateValues) { - return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i])); -} function indexOfAnyCharCode(text, charCodes, start) { - for (let i = start || 0; i < text.length; i++) { + for (let i = start ?? 0; i < text.length; i++) { if (contains(charCodes, text.charCodeAt(i))) { return i; } @@ -2535,7 +2419,7 @@ function indexOfAnyCharCode(text, charCodes, start) { } function countWhere(array, predicate) { let count = 0; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const v = array[i]; if (predicate(v, i)) { @@ -2546,7 +2430,7 @@ function countWhere(array, predicate) { return count; } function filter(array, f) { - if (array) { + if (array !== void 0) { const len = array.length; let i = 0; while (i < len && f(array[i])) i++; @@ -2580,7 +2464,7 @@ function clear(array) { } function map(array, f) { let result; - if (array) { + if (array !== void 0) { result = []; for (let i = 0; i < array.length; i++) { result.push(f(array[i], i)); @@ -2594,7 +2478,7 @@ function* mapIterator(iter, mapFn) { } } function sameMap(array, f) { - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const item = array[i]; const mapped = f(item, i); @@ -2612,7 +2496,8 @@ function sameMap(array, f) { } function flatten(array) { const result = []; - for (const v of array) { + for (let i = 0; i < array.length; i++) { + const v = array[i]; if (v) { if (isArray(v)) { addRange(result, v); @@ -2625,7 +2510,7 @@ function flatten(array) { } function flatMap(array, mapfn) { let result; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const v = mapfn(array[i], i); if (v) { @@ -2637,11 +2522,11 @@ function flatMap(array, mapfn) { } } } - return result || emptyArray; + return result ?? emptyArray; } function flatMapToMutable(array, mapfn) { const result = []; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const v = mapfn(array[i], i); if (v) { @@ -2664,7 +2549,7 @@ function* flatMapIterator(iter, mapfn) { } function sameFlatMap(array, mapfn) { let result; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const item = array[i]; const mapped = mapfn(item, i); @@ -2680,7 +2565,7 @@ function sameFlatMap(array, mapfn) { } } } - return result || array; + return result ?? array; } function mapAllOrFail(array, mapFn) { const result = []; @@ -2695,7 +2580,7 @@ function mapAllOrFail(array, mapFn) { } function mapDefined(array, mapFn) { const result = []; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const mapped = mapFn(array[i], i); if (mapped !== void 0) { @@ -2713,22 +2598,6 @@ function* mapDefinedIterator(iter, mapFn) { } } } -function mapDefinedEntries(map2, f) { - if (!map2) { - return void 0; - } - const result = /* @__PURE__ */ new Map(); - map2.forEach((value, key) => { - const entry = f(key, value); - if (entry !== void 0) { - const [newKey, newValue] = entry; - if (newKey !== void 0 && newValue !== void 0) { - result.set(newKey, newValue); - } - } - }); - return result; -} function getOrUpdate(map2, key, callback) { if (map2.has(key)) { return map2.get(key); @@ -2749,7 +2618,7 @@ function* singleIterator(value) { } function spanMap(array, keyfn, mapfn) { let result; - if (array) { + if (array !== void 0) { result = []; const len = array.length; let previousKey; @@ -2781,7 +2650,7 @@ function spanMap(array, keyfn, mapfn) { return result; } function mapEntries(map2, f) { - if (!map2) { + if (map2 === void 0) { return void 0; } const result = /* @__PURE__ */ new Map(); @@ -2792,10 +2661,10 @@ function mapEntries(map2, f) { return result; } function some(array, predicate) { - if (array) { - if (predicate) { - for (const v of array) { - if (predicate(v)) { + if (array !== void 0) { + if (predicate !== void 0) { + for (let i = 0; i < array.length; i++) { + if (predicate(array[i])) { return true; } } @@ -2820,8 +2689,8 @@ function getRangesWhere(arr, pred, cb) { if (start !== void 0) cb(start, arr.length); } function concatenate(array1, array2) { - if (!some(array2)) return array1; - if (!some(array1)) return array2; + if (array2 === void 0 || array2.length === 0) return array1; + if (array1 === void 0 || array1.length === 0) return array2; return [...array1, ...array2]; } function selectIndex(_, i) { @@ -2848,8 +2717,8 @@ function deduplicateRelational(array, equalityComparer, comparer) { } function deduplicateEquality(array, equalityComparer) { const result = []; - for (const item of array) { - pushIfUnique(result, item, equalityComparer); + for (let i = 0; i < array.length; i++) { + pushIfUnique(result, array[i], equalityComparer); } return result; } @@ -2903,19 +2772,10 @@ function insertSorted(array, insert, compare, equalityComparer, allowDuplicates) return false; } function sortAndDeduplicate(array, comparer, equalityComparer) { - return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive); -} -function arrayIsSorted(array, comparer) { - if (array.length < 2) return true; - for (let i = 1, len = array.length; i < len; i++) { - if (comparer(array[i - 1], array[i]) === 1 /* GreaterThan */) { - return false; - } - } - return true; + return deduplicateSorted(toSorted(array, comparer), equalityComparer ?? comparer ?? compareStringsCaseSensitive); } function arrayIsEqualTo(array1, array2, equalityComparer = equateValues) { - if (!array1 || !array2) { + if (array1 === void 0 || array2 === void 0) { return array1 === array2; } if (array1.length !== array2.length) { @@ -2930,20 +2790,18 @@ function arrayIsEqualTo(array1, array2, equalityComparer = equateValues) { } function compact(array) { let result; - if (array) { + if (array !== void 0) { for (let i = 0; i < array.length; i++) { const v = array[i]; - if (result || !v) { - if (!result) { - result = array.slice(0, i); - } + if (result ?? !v) { + result ?? (result = array.slice(0, i)); if (v) { result.push(v); } } } } - return result || array; + return result ?? array; } function relativeComplement(arrayA, arrayB, comparer) { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; @@ -3008,7 +2866,7 @@ function pushIfUnique(array, toAdd, equalityComparer) { } } function appendIfUnique(array, toAdd, equalityComparer) { - if (array) { + if (array !== void 0) { pushIfUnique(array, toAdd, equalityComparer); return array; } else { @@ -3018,19 +2876,14 @@ function appendIfUnique(array, toAdd, equalityComparer) { function stableSortIndices(array, indices, comparer) { indices.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)); } -function sort(array, comparer) { - return array.length === 0 ? array : array.slice().sort(comparer); +function toSorted(array, comparer) { + return array.length === 0 ? emptyArray : array.slice().sort(comparer); } function* arrayReverseIterator(array) { for (let i = array.length - 1; i >= 0; i--) { yield array[i]; } } -function stableSort(array, comparer) { - const indices = indicesOf(array); - stableSortIndices(array, indices, comparer); - return indices.map((i) => array[i]); -} function rangeEquals(array1, array2, pos, end) { while (pos < end) { if (array1[pos] !== array2[pos]) { @@ -3041,7 +2894,7 @@ function rangeEquals(array1, array2, pos, end) { return true; } var elementAt = !!Array.prototype.at ? (array, offset) => array == null ? void 0 : array.at(offset) : (array, offset) => { - if (array) { + if (array !== void 0) { offset = toOffset(array, offset); if (offset < array.length) { return array[offset]; @@ -3053,7 +2906,7 @@ function firstOrUndefined(array) { return array === void 0 || array.length === 0 ? void 0 : array[0]; } function firstOrUndefinedIterator(iter) { - if (iter) { + if (iter !== void 0) { for (const value of iter) { return value; } @@ -3078,13 +2931,13 @@ function last(array) { return array[array.length - 1]; } function singleOrUndefined(array) { - return array && array.length === 1 ? array[0] : void 0; + return array !== void 0 && array.length === 1 ? array[0] : void 0; } function single(array) { return Debug.checkDefined(singleOrUndefined(array)); } function singleOrMany(array) { - return array && array.length === 1 ? array[0] : array; + return array !== void 0 && array.length === 1 ? array[0] : array; } function replaceElement(array, index, value) { const result = array.slice(0); @@ -3098,7 +2951,7 @@ function binarySearchKey(array, key, keySelector, keyComparer, offset) { if (!some(array)) { return -1; } - let low = offset || 0; + let low = offset ?? 0; let high = array.length - 1; while (low <= high) { const middle = low + (high - low >> 1); @@ -3216,7 +3069,8 @@ function equalOwnProperties(left, right, equalityComparer = equateValues) { } function arrayToMap(array, makeKey, makeValue = identity) { const result = /* @__PURE__ */ new Map(); - for (const value of array) { + for (let i = 0; i < array.length; i++) { + const value = array[i]; const key = makeKey(value); if (key !== void 0) result.set(key, makeValue(value)); } @@ -3224,14 +3078,16 @@ function arrayToMap(array, makeKey, makeValue = identity) { } function arrayToNumericMap(array, makeKey, makeValue = identity) { const result = []; - for (const value of array) { + for (let i = 0; i < array.length; i++) { + const value = array[i]; result[makeKey(value)] = makeValue(value); } return result; } function arrayToMultiMap(values, makeKey, makeValue = identity) { const result = createMultiMap(); - for (const value of values) { + for (let i = 0; i < values.length; i++) { + const value = values[i]; result.add(makeKey(value), makeValue(value)); } return result; @@ -3241,8 +3097,9 @@ function group(values, getGroupId, resultSelector = identity) { } function groupBy(values, keySelector) { const result = {}; - if (values) { - for (const value of values) { + if (values !== void 0) { + for (let i = 0; i < values.length; i++) { + const value = values[i]; const key = `${keySelector(value)}`; const array = result[key] ?? (result[key] = []); array.push(value); @@ -3281,7 +3138,7 @@ function copyProperties(first2, second) { } } function maybeBind(obj, fn) { - return fn ? fn.bind(obj) : void 0; + return fn == null ? void 0 : fn.bind(obj); } function createMultiMap() { const map2 = /* @__PURE__ */ new Map(); @@ -3291,7 +3148,7 @@ function createMultiMap() { } function multiMapAdd(key, value) { let values = this.get(key); - if (values) { + if (values !== void 0) { values.push(value); } else { this.set(key, values = [value]); @@ -3300,7 +3157,7 @@ function multiMapAdd(key, value) { } function multiMapRemove(key, value) { const values = this.get(key); - if (values) { + if (values !== void 0) { unorderedRemoveItem(values, value); if (!values.length) { this.delete(key); @@ -3308,7 +3165,7 @@ function multiMapRemove(key, value) { } } function createQueue(items) { - const elements = (items == null ? void 0 : items.slice()) || []; + const elements = (items == null ? void 0 : items.slice()) ?? []; let headIndex = 0; function isEmpty() { return headIndex === elements.length; @@ -3359,13 +3216,8 @@ function createSet(getHashCode, equals) { const hash = getHashCode(element); if (!multiMap.has(hash)) return false; const candidates = multiMap.get(hash); - if (!isArray(candidates)) return equals(candidates, element); - for (const candidate of candidates) { - if (equals(candidate, element)) { - return true; - } - } - return false; + if (isArray(candidates)) return contains(candidates, element, equals); + return equals(candidates, element); }, add(element) { const hash = getHashCode(element); @@ -3519,46 +3371,6 @@ function memoizeOne(callback) { return value; }; } -function memoizeWeak(callback) { - const map2 = /* @__PURE__ */ new WeakMap(); - return (arg) => { - let value = map2.get(arg); - if (value === void 0 && !map2.has(arg)) { - value = callback(arg); - map2.set(arg, value); - } - return value; - }; -} -function memoizeCached(callback, cache) { - return (...args) => { - let value = cache.get(args); - if (value === void 0 && !cache.has(args)) { - value = callback(...args); - cache.set(args, value); - } - return value; - }; -} -function compose(a, b, c, d, e) { - if (!!e) { - const args = []; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - return (t) => reduceLeft(args, (u, f) => f(u), t); - } else if (d) { - return (t) => d(c(b(a(t)))); - } else if (c) { - return (t) => c(b(a(t))); - } else if (b) { - return (t) => b(a(t)); - } else if (a) { - return (t) => a(t); - } else { - return (t) => t; - } -} var AssertionLevel = /* @__PURE__ */ ((AssertionLevel2) => { AssertionLevel2[AssertionLevel2["None"] = 0] = "None"; AssertionLevel2[AssertionLevel2["Normal"] = 1] = "Normal"; @@ -3584,6 +3396,12 @@ function compareValues(a, b) { function compareTextSpans(a, b) { return compareValues(a == null ? void 0 : a.start, b == null ? void 0 : b.start) || compareValues(a == null ? void 0 : a.length, b == null ? void 0 : b.length); } +function maxBy(arr, init, mapper) { + for (let i = 0; i < arr.length; i++) { + init = Math.max(init, mapper(arr[i])); + } + return init; +} function min(items, compare) { return reduceLeft(items, (x, y) => compare(x, y) === -1 /* LessThan */ ? x : y); } @@ -3635,8 +3453,8 @@ function setUILocale(value) { } } function compareStringsCaseSensitiveUI(a, b) { - const comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createUIStringComparer(uiLocale)); - return comparer(a, b); + uiComparerCaseSensitive ?? (uiComparerCaseSensitive = createUIStringComparer(uiLocale)); + return uiComparerCaseSensitive(a, b); } function compareProperties(a, b, key, comparer) { return a === b ? 0 /* EqualTo */ : a === void 0 ? -1 /* LessThan */ : b === void 0 ? 1 /* GreaterThan */ : comparer(a[key], b[key]); @@ -3796,7 +3614,8 @@ function matchedText(pattern, candidate) { function findBestPatternMatch(values, getPattern, candidate) { let matchedValue; let longestMatchPrefixLength = -1; - for (const v of values) { + for (let i = 0; i < values.length; i++) { + const v = values[i]; const pattern = getPattern(v); if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { longestMatchPrefixLength = pattern.prefix.length; @@ -3841,7 +3660,7 @@ function singleElementArray(t) { return t === void 0 ? void 0 : [t]; } function enumerateInsertsAndDeletes(newItems, oldItems, comparer, inserted, deleted, unchanged) { - unchanged = unchanged || noop; + unchanged ?? (unchanged = noop); let newIndex = 0; let oldIndex = 0; const newLen = newItems.length; @@ -3903,7 +3722,7 @@ function cartesianProductWorker(arrays, result, outer, index) { } } function takeWhile(array, predicate) { - if (array) { + if (array !== void 0) { const len = array.length; let index = 0; while (index < len && predicate(array[index])) { @@ -3913,7 +3732,7 @@ function takeWhile(array, predicate) { } } function skipWhile(array, predicate) { - if (array) { + if (array !== void 0) { const len = array.length; let index = 0; while (index < len && predicate(array[index])) { @@ -4209,7 +4028,7 @@ Node ${formatSyntaxKind(node.kind)} was unexpected.`, result.push([value, name]); } } - const sorted = stableSort(result, (x, y) => compareValues(x[0], y[0])); + const sorted = toSorted(result, (x, y) => compareValues(x[0], y[0])); enumMemberCache.set(enumObject, sorted); return sorted; } @@ -4418,7 +4237,7 @@ Node ${formatSyntaxKind(node.kind)} was unexpected.`, Object.defineProperties(array, { __tsDebuggerDisplay: { value(defaultValue) { - defaultValue = String(defaultValue).replace(/(?:,[\s\w\d_]+:[^,]+)+\]$/, "]"); + defaultValue = String(defaultValue).replace(/(?:,[\s\w]+:[^,]+)+\]$/, "]"); return `NodeArray ${defaultValue}`; } } @@ -4838,7 +4657,7 @@ m2: ${this.mapper2.__debugToString().split("\n").join("\n ")}`; } function renderGraph() { const columnCount = columnWidths.length; - const laneCount = nodes.reduce((x, n) => Math.max(x, n.lane), 0) + 1; + const laneCount = maxBy(nodes, 0, (n) => n.lane) + 1; const lanes = fill(Array(laneCount), ""); const grid = columnWidths.map(() => Array(laneCount)); const connectors = columnWidths.map(() => fill(Array(laneCount), 0)); @@ -4961,7 +4780,7 @@ var prereleaseRegExp = /^(?:0|[1-9]\d*|[a-z-][a-z0-9-]*)(?:\.(?:0|[1-9]\d*|[a-z- var prereleasePartRegExp = /^(?:0|[1-9]\d*|[a-z-][a-z0-9-]*)$/i; var buildRegExp = /^[a-z0-9-]+(?:\.[a-z0-9-]+)*$/i; var buildPartRegExp = /^[a-z0-9-]+$/i; -var numericIdentifierRegExp = /^(0|[1-9]\d*)$/; +var numericIdentifierRegExp = /^(?:0|[1-9]\d*)$/; var _Version = class _Version { constructor(major, minor = 0, patch = 0, prerelease = "", build2 = "") { if (typeof major === "string") { @@ -5084,11 +4903,11 @@ var VersionRange = class _VersionRange { return formatDisjunction(this._alternatives); } }; -var logicalOrRegExp = /\|\|/g; -var whitespaceRegExp = /\s+/g; -var partialRegExp = /^([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i; +var logicalOrRegExp = /\|\|/; +var whitespaceRegExp = /\s+/; +var partialRegExp = /^([x*0]|[1-9]\d*)(?:\.([x*0]|[1-9]\d*)(?:\.([x*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i; var hyphenRegExp = /^\s*([a-z0-9-+.*]+)\s+-\s+([a-z0-9-+.*]+)\s*$/i; -var rangeRegExp = /^(~|\^|<|<=|>|>=|=)?\s*([a-z0-9-+.*]+)$/i; +var rangeRegExp = /^([~^<>=]|<=|>=)?\s*([a-z0-9-+.*]+)$/i; function parseRange(text) { const alternatives = []; for (let range of text.trim().split(logicalOrRegExp)) { @@ -5240,10 +5059,12 @@ function tryGetPerformance() { if (isNodeLikeSystem()) { try { const { performance: performance2 } = require("perf_hooks"); - return { - shouldWriteNativeEvents: false, - performance: performance2 - }; + if (performance2) { + return { + shouldWriteNativeEvents: false, + performance: performance2 + }; + } } catch { } } @@ -5279,16 +5100,6 @@ function tryGetNativePerformanceHooks() { } var timestamp = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now; -// src/compiler/perfLogger.ts -var etwModule; -try { - const etwModulePath = process.env.TS_ETW_MODULE_PATH ?? "./node_modules/@microsoft/typescript-etw"; - etwModule = require(etwModulePath); -} catch (e) { - etwModule = void 0; -} -var perfLogger = (etwModule == null ? void 0 : etwModule.logEvent) ? etwModule : void 0; - // src/compiler/_namespaces/ts.performance.ts var ts_performance_exports = {}; __export(ts_performance_exports, { @@ -6177,12 +5988,21 @@ var RelationComparisonResult = /* @__PURE__ */ ((RelationComparisonResult3) => { RelationComparisonResult3[RelationComparisonResult3["None"] = 0] = "None"; RelationComparisonResult3[RelationComparisonResult3["Succeeded"] = 1] = "Succeeded"; RelationComparisonResult3[RelationComparisonResult3["Failed"] = 2] = "Failed"; - RelationComparisonResult3[RelationComparisonResult3["Reported"] = 4] = "Reported"; RelationComparisonResult3[RelationComparisonResult3["ReportsUnmeasurable"] = 8] = "ReportsUnmeasurable"; RelationComparisonResult3[RelationComparisonResult3["ReportsUnreliable"] = 16] = "ReportsUnreliable"; RelationComparisonResult3[RelationComparisonResult3["ReportsMask"] = 24] = "ReportsMask"; + RelationComparisonResult3[RelationComparisonResult3["ComplexityOverflow"] = 32] = "ComplexityOverflow"; + RelationComparisonResult3[RelationComparisonResult3["StackDepthOverflow"] = 64] = "StackDepthOverflow"; + RelationComparisonResult3[RelationComparisonResult3["Overflow"] = 96] = "Overflow"; return RelationComparisonResult3; })(RelationComparisonResult || {}); +var PredicateSemantics = /* @__PURE__ */ ((PredicateSemantics2) => { + PredicateSemantics2[PredicateSemantics2["None"] = 0] = "None"; + PredicateSemantics2[PredicateSemantics2["Always"] = 1] = "Always"; + PredicateSemantics2[PredicateSemantics2["Never"] = 2] = "Never"; + PredicateSemantics2[PredicateSemantics2["Sometimes"] = 3] = "Sometimes"; + return PredicateSemantics2; +})(PredicateSemantics || {}); var GeneratedIdentifierFlags = /* @__PURE__ */ ((GeneratedIdentifierFlags2) => { GeneratedIdentifierFlags2[GeneratedIdentifierFlags2["None"] = 0] = "None"; GeneratedIdentifierFlags2[GeneratedIdentifierFlags2["Auto"] = 1] = "Auto"; @@ -6227,6 +6047,7 @@ var TokenFlags = /* @__PURE__ */ ((TokenFlags2) => { TokenFlags2[TokenFlags2["HexEscape"] = 4096] = "HexEscape"; TokenFlags2[TokenFlags2["ContainsLeadingZero"] = 8192] = "ContainsLeadingZero"; TokenFlags2[TokenFlags2["ContainsInvalidSeparator"] = 16384] = "ContainsInvalidSeparator"; + TokenFlags2[TokenFlags2["PrecedingJSDocLeadingAsterisks"] = 32768] = "PrecedingJSDocLeadingAsterisks"; TokenFlags2[TokenFlags2["BinaryOrOctalSpecifier"] = 384] = "BinaryOrOctalSpecifier"; TokenFlags2[TokenFlags2["WithSpecifier"] = 448] = "WithSpecifier"; TokenFlags2[TokenFlags2["StringLiteralFlags"] = 7176] = "StringLiteralFlags"; @@ -6281,6 +6102,7 @@ var FilePreprocessingDiagnosticsKind = /* @__PURE__ */ ((FilePreprocessingDiagno var EmitOnly = /* @__PURE__ */ ((EmitOnly4) => { EmitOnly4[EmitOnly4["Js"] = 0] = "Js"; EmitOnly4[EmitOnly4["Dts"] = 1] = "Dts"; + EmitOnly4[EmitOnly4["BuilderSignature"] = 2] = "BuilderSignature"; return EmitOnly4; })(EmitOnly || {}); var StructureIsReused = /* @__PURE__ */ ((StructureIsReused2) => { @@ -6350,17 +6172,21 @@ var NodeBuilderFlags = /* @__PURE__ */ ((NodeBuilderFlags2) => { NodeBuilderFlags2[NodeBuilderFlags2["AllowEmptyTuple"] = 524288] = "AllowEmptyTuple"; NodeBuilderFlags2[NodeBuilderFlags2["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType"; NodeBuilderFlags2[NodeBuilderFlags2["AllowEmptyIndexInfoType"] = 2097152] = "AllowEmptyIndexInfoType"; - NodeBuilderFlags2[NodeBuilderFlags2["WriteComputedProps"] = 1073741824] = "WriteComputedProps"; - NodeBuilderFlags2[NodeBuilderFlags2["NoSyntacticPrinter"] = -2147483648] = "NoSyntacticPrinter"; NodeBuilderFlags2[NodeBuilderFlags2["AllowNodeModulesRelativePaths"] = 67108864] = "AllowNodeModulesRelativePaths"; - NodeBuilderFlags2[NodeBuilderFlags2["DoNotIncludeSymbolChain"] = 134217728] = "DoNotIncludeSymbolChain"; - NodeBuilderFlags2[NodeBuilderFlags2["AllowUnresolvedNames"] = 1] = "AllowUnresolvedNames"; NodeBuilderFlags2[NodeBuilderFlags2["IgnoreErrors"] = 70221824] = "IgnoreErrors"; NodeBuilderFlags2[NodeBuilderFlags2["InObjectTypeLiteral"] = 4194304] = "InObjectTypeLiteral"; NodeBuilderFlags2[NodeBuilderFlags2["InTypeAlias"] = 8388608] = "InTypeAlias"; NodeBuilderFlags2[NodeBuilderFlags2["InInitialEntityName"] = 16777216] = "InInitialEntityName"; return NodeBuilderFlags2; })(NodeBuilderFlags || {}); +var InternalNodeBuilderFlags = /* @__PURE__ */ ((InternalNodeBuilderFlags2) => { + InternalNodeBuilderFlags2[InternalNodeBuilderFlags2["None"] = 0] = "None"; + InternalNodeBuilderFlags2[InternalNodeBuilderFlags2["WriteComputedProps"] = 1] = "WriteComputedProps"; + InternalNodeBuilderFlags2[InternalNodeBuilderFlags2["NoSyntacticPrinter"] = 2] = "NoSyntacticPrinter"; + InternalNodeBuilderFlags2[InternalNodeBuilderFlags2["DoNotIncludeSymbolChain"] = 4] = "DoNotIncludeSymbolChain"; + InternalNodeBuilderFlags2[InternalNodeBuilderFlags2["AllowUnresolvedNames"] = 8] = "AllowUnresolvedNames"; + return InternalNodeBuilderFlags2; +})(InternalNodeBuilderFlags || {}); var TypeFormatFlags = /* @__PURE__ */ ((TypeFormatFlags2) => { TypeFormatFlags2[TypeFormatFlags2["None"] = 0] = "None"; TypeFormatFlags2[TypeFormatFlags2["NoTruncation"] = 1] = "NoTruncation"; @@ -6405,11 +6231,6 @@ var SymbolAccessibility = /* @__PURE__ */ ((SymbolAccessibility2) => { SymbolAccessibility2[SymbolAccessibility2["NotResolved"] = 3] = "NotResolved"; return SymbolAccessibility2; })(SymbolAccessibility || {}); -var SyntheticSymbolKind = /* @__PURE__ */ ((SyntheticSymbolKind2) => { - SyntheticSymbolKind2[SyntheticSymbolKind2["UnionOrIntersection"] = 0] = "UnionOrIntersection"; - SyntheticSymbolKind2[SyntheticSymbolKind2["Spread"] = 1] = "Spread"; - return SyntheticSymbolKind2; -})(SyntheticSymbolKind || {}); var TypePredicateKind = /* @__PURE__ */ ((TypePredicateKind2) => { TypePredicateKind2[TypePredicateKind2["This"] = 0] = "This"; TypePredicateKind2[TypePredicateKind2["Identifier"] = 1] = "Identifier"; @@ -6575,6 +6396,7 @@ var NodeCheckFlags = /* @__PURE__ */ ((NodeCheckFlags3) => { NodeCheckFlags3[NodeCheckFlags3["ContainsClassWithPrivateIdentifiers"] = 1048576] = "ContainsClassWithPrivateIdentifiers"; NodeCheckFlags3[NodeCheckFlags3["ContainsSuperPropertyInStaticInitializer"] = 2097152] = "ContainsSuperPropertyInStaticInitializer"; NodeCheckFlags3[NodeCheckFlags3["InCheckIdentifier"] = 4194304] = "InCheckIdentifier"; + NodeCheckFlags3[NodeCheckFlags3["PartiallyTypeChecked"] = 8388608] = "PartiallyTypeChecked"; NodeCheckFlags3[NodeCheckFlags3["LazyFlags"] = 539358128] = "LazyFlags"; return NodeCheckFlags3; })(NodeCheckFlags || {}); @@ -6728,7 +6550,7 @@ var AccessFlags = /* @__PURE__ */ ((AccessFlags2) => { AccessFlags2[AccessFlags2["NoIndexSignatures"] = 2] = "NoIndexSignatures"; AccessFlags2[AccessFlags2["Writing"] = 4] = "Writing"; AccessFlags2[AccessFlags2["CacheSymbol"] = 8] = "CacheSymbol"; - AccessFlags2[AccessFlags2["NoTupleBoundsCheck"] = 16] = "NoTupleBoundsCheck"; + AccessFlags2[AccessFlags2["AllowMissing"] = 16] = "AllowMissing"; AccessFlags2[AccessFlags2["ExpressionPosition"] = 32] = "ExpressionPosition"; AccessFlags2[AccessFlags2["ReportDeprecated"] = 64] = "ReportDeprecated"; AccessFlags2[AccessFlags2["SuppressNoImplicitAnyError"] = 128] = "SuppressNoImplicitAnyError"; @@ -6922,22 +6744,22 @@ var ScriptKind = /* @__PURE__ */ ((ScriptKind7) => { ScriptKind7[ScriptKind7["Deferred"] = 7] = "Deferred"; return ScriptKind7; })(ScriptKind || {}); -var ScriptTarget = /* @__PURE__ */ ((ScriptTarget11) => { - ScriptTarget11[ScriptTarget11["ES3"] = 0] = "ES3"; - ScriptTarget11[ScriptTarget11["ES5"] = 1] = "ES5"; - ScriptTarget11[ScriptTarget11["ES2015"] = 2] = "ES2015"; - ScriptTarget11[ScriptTarget11["ES2016"] = 3] = "ES2016"; - ScriptTarget11[ScriptTarget11["ES2017"] = 4] = "ES2017"; - ScriptTarget11[ScriptTarget11["ES2018"] = 5] = "ES2018"; - ScriptTarget11[ScriptTarget11["ES2019"] = 6] = "ES2019"; - ScriptTarget11[ScriptTarget11["ES2020"] = 7] = "ES2020"; - ScriptTarget11[ScriptTarget11["ES2021"] = 8] = "ES2021"; - ScriptTarget11[ScriptTarget11["ES2022"] = 9] = "ES2022"; - ScriptTarget11[ScriptTarget11["ES2023"] = 10] = "ES2023"; - ScriptTarget11[ScriptTarget11["ESNext"] = 99] = "ESNext"; - ScriptTarget11[ScriptTarget11["JSON"] = 100] = "JSON"; - ScriptTarget11[ScriptTarget11["Latest"] = 99 /* ESNext */] = "Latest"; - return ScriptTarget11; +var ScriptTarget = /* @__PURE__ */ ((ScriptTarget12) => { + ScriptTarget12[ScriptTarget12["ES3"] = 0] = "ES3"; + ScriptTarget12[ScriptTarget12["ES5"] = 1] = "ES5"; + ScriptTarget12[ScriptTarget12["ES2015"] = 2] = "ES2015"; + ScriptTarget12[ScriptTarget12["ES2016"] = 3] = "ES2016"; + ScriptTarget12[ScriptTarget12["ES2017"] = 4] = "ES2017"; + ScriptTarget12[ScriptTarget12["ES2018"] = 5] = "ES2018"; + ScriptTarget12[ScriptTarget12["ES2019"] = 6] = "ES2019"; + ScriptTarget12[ScriptTarget12["ES2020"] = 7] = "ES2020"; + ScriptTarget12[ScriptTarget12["ES2021"] = 8] = "ES2021"; + ScriptTarget12[ScriptTarget12["ES2022"] = 9] = "ES2022"; + ScriptTarget12[ScriptTarget12["ES2023"] = 10] = "ES2023"; + ScriptTarget12[ScriptTarget12["ESNext"] = 99] = "ESNext"; + ScriptTarget12[ScriptTarget12["JSON"] = 100] = "JSON"; + ScriptTarget12[ScriptTarget12["Latest"] = 99 /* ESNext */] = "Latest"; + return ScriptTarget12; })(ScriptTarget || {}); var LanguageVariant = /* @__PURE__ */ ((LanguageVariant4) => { LanguageVariant4[LanguageVariant4["Standard"] = 0] = "Standard"; @@ -7299,9 +7121,10 @@ var OuterExpressionKinds = /* @__PURE__ */ ((OuterExpressionKinds2) => { OuterExpressionKinds2[OuterExpressionKinds2["TypeAssertions"] = 2] = "TypeAssertions"; OuterExpressionKinds2[OuterExpressionKinds2["NonNullAssertions"] = 4] = "NonNullAssertions"; OuterExpressionKinds2[OuterExpressionKinds2["PartiallyEmittedExpressions"] = 8] = "PartiallyEmittedExpressions"; + OuterExpressionKinds2[OuterExpressionKinds2["ExpressionsWithTypeArguments"] = 16] = "ExpressionsWithTypeArguments"; OuterExpressionKinds2[OuterExpressionKinds2["Assertions"] = 6] = "Assertions"; - OuterExpressionKinds2[OuterExpressionKinds2["All"] = 15] = "All"; - OuterExpressionKinds2[OuterExpressionKinds2["ExcludeJSDocTypeAssertion"] = 16] = "ExcludeJSDocTypeAssertion"; + OuterExpressionKinds2[OuterExpressionKinds2["All"] = 31] = "All"; + OuterExpressionKinds2[OuterExpressionKinds2["ExcludeJSDocTypeAssertion"] = -2147483648] = "ExcludeJSDocTypeAssertion"; return OuterExpressionKinds2; })(OuterExpressionKinds || {}); var LexicalEnvironmentFlags = /* @__PURE__ */ ((LexicalEnvironmentFlags2) => { @@ -8407,7 +8230,7 @@ function patchWriteFileEnsuringDirectory(sys2) { var sys = (() => { const byteOrderMarkIndicator = "\uFEFF"; function getNodeSystem() { - const nativePattern = /^native |^\([^)]+\)$|^(internal[\\/]|[a-zA-Z0-9_\s]+(\.js)?$)/; + const nativePattern = /^native |^\([^)]+\)$|^(?:internal[\\/]|[\w\s]+(?:\.js)?$)/; const _fs = require("fs"); const _path = require("path"); const _os = require("os"); @@ -8465,6 +8288,7 @@ var sys = (() => { writeFile: writeFile2, watchFile: watchFile2, watchDirectory, + preferNonRecursiveWatch: !fsSupportsRecursiveFsWatch, resolvePath: (path) => _path.resolve(path), fileExists, directoryExists, @@ -8517,7 +8341,7 @@ var sys = (() => { disableCPUProfiler, cpuProfilingEnabled: () => !!activeSession || contains(process.execArgv, "--cpu-prof") || contains(process.execArgv, "--prof"), realpath, - debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv, (arg) => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)) || !!process.recordreplay, + debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv, (arg) => /^--(?:inspect|debug)(?:-brk)?(?:=\d+)?$/i.test(arg)) || !!process.recordreplay, tryEnableSourceMapsForHost() { try { require("source-map-support").install(); @@ -8527,7 +8351,7 @@ var sys = (() => { setTimeout, clearTimeout, clearScreen: () => { - process.stdout.write("\x1Bc"); + process.stdout.write("\x1B[2J\x1B[3J\x1B[H"); }, setBlocking: () => { var _a; @@ -8668,11 +8492,11 @@ var sys = (() => { callback ); } - function readFileWorker(fileName, _encoding) { + function readFile(fileName, _encoding) { let buffer; try { buffer = _fs.readFileSync(fileName); - } catch (e) { + } catch { return void 0; } let len = buffer.length; @@ -8693,16 +8517,7 @@ var sys = (() => { } return buffer.toString("utf8"); } - function readFile(fileName, _encoding) { - var _a, _b; - (_a = perfLogger) == null ? void 0 : _a.logStartReadFile(fileName); - const file = readFileWorker(fileName, _encoding); - (_b = perfLogger) == null ? void 0 : _b.logStopReadFile(); - return file; - } function writeFile2(fileName, data, writeByteOrderMark) { - var _a; - (_a = perfLogger) == null ? void 0 : _a.logEvent("WriteFile: " + fileName); if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; } @@ -8723,8 +8538,6 @@ var sys = (() => { } } function getAccessibleFileSystemEntries(path) { - var _a; - (_a = perfLogger) == null ? void 0 : _a.logEvent("ReadDir: " + (path || ".")); try { const entries = _fs.readdirSync(path || ".", { withFileTypes: true }); const files = []; @@ -8742,7 +8555,7 @@ var sys = (() => { if (!stat) { continue; } - } catch (e) { + } catch { continue; } } else { @@ -8757,7 +8570,7 @@ var sys = (() => { files.sort(); directories.sort(); return { files, directories }; - } catch (e) { + } catch { return emptyFileSystemEntries; } } @@ -8780,7 +8593,7 @@ var sys = (() => { default: return false; } - } catch (e) { + } catch { return false; } finally { Error.stackTraceLimit = originalStackTraceLimit; @@ -8811,7 +8624,7 @@ var sys = (() => { Error.stackTraceLimit = 0; try { return (_a = statSync(path)) == null ? void 0 : _a.mtime; - } catch (e) { + } catch { return void 0; } finally { Error.stackTraceLimit = originalStackTraceLimit; @@ -8820,14 +8633,14 @@ var sys = (() => { function setModifiedTime(path, time) { try { _fs.utimesSync(path, time, time); - } catch (e) { + } catch { return; } } function deleteFile(path) { try { return _fs.unlinkSync(path); - } catch (e) { + } catch { return; } } @@ -8881,7 +8694,7 @@ function pathIsAbsolute(path) { return getEncodedRootLength(path) !== 0; } function pathIsRelative(path) { - return /^\.\.?($|[\\/])/.test(path); + return /^\.\.?(?:$|[\\/])/.test(path); } function pathIsBareSpecifier(path) { return !pathIsAbsolute(path) && !pathIsRelative(path); @@ -9120,7 +8933,7 @@ function changeFullExtension(path, newExtension) { } return changeAnyExtension(path, newExtension); } -var relativePathSegmentRegExp = /(?:\/\/)|(?:^|\/)\.\.?(?:$|\/)/; +var relativePathSegmentRegExp = /\/\/|(?:^|\/)\.\.?(?:$|\/)/; function comparePathsWorker(a, b, componentComparer) { if (a === b) return 0 /* EqualTo */; if (a === void 0) return -1 /* LessThan */; @@ -9508,6 +9321,7 @@ var Diagnostics = { _0_resolves_to_a_type_only_declaration_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_export_type_0_as_default: diag(1290, 1 /* Error */, "_0_resolves_to_a_type_only_declaration_and_must_be_marked_type_only_in_this_file_before_re_exporting_1290", "'{0}' resolves to a type-only declaration and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'export type { {0} as default }'."), _0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_import_type_where_0_is_imported: diag(1291, 1 /* Error */, "_0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enable_1291", "'{0}' resolves to a type and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'import type' where '{0}' is imported."), _0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_export_type_0_as_default: diag(1292, 1 /* Error */, "_0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enable_1292", "'{0}' resolves to a type and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'export type { {0} as default }'."), + ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve: diag(1293, 1 /* Error */, "ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve_1293", "ESM syntax is not allowed in a CommonJS module when 'module' is set to 'preserve'."), with_statements_are_not_allowed_in_an_async_function_block: diag(1300, 1 /* Error */, "with_statements_are_not_allowed_in_an_async_function_block_1300", "'with' statements are not allowed in an async function block."), await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules: diag(1308, 1 /* Error */, "await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules_1308", "'await' expressions are only allowed within async functions and at the top levels of modules."), The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level: diag(1309, 1 /* Error */, "The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level_1309", "The current file is a CommonJS module and cannot use 'await' at the top level."), @@ -9523,7 +9337,7 @@ var Diagnostics = { Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member: diag(1321, 1 /* Error */, "Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_cal_1321", "Type of 'yield' operand in an async generator must either be a valid promise or must not contain a callable 'then' member."), Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member: diag(1322, 1 /* Error */, "Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_con_1322", "Type of iterated elements of a 'yield*' operand must either be a valid promise or must not contain a callable 'then' member."), Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext: diag(1323, 1 /* Error */, "Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd__1323", "Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', or 'nodenext'."), - Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext: diag(1324, 1 /* Error */, "Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nod_1324", "Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', or 'nodenext'."), + Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_nodenext_or_preserve: diag(1324, 1 /* Error */, "Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_nodene_1324", "Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'nodenext', or 'preserve'."), Argument_of_dynamic_import_cannot_be_spread_element: diag(1325, 1 /* Error */, "Argument_of_dynamic_import_cannot_be_spread_element_1325", "Argument of dynamic import cannot be spread element."), This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments: diag(1326, 1 /* Error */, "This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot__1326", "This use of 'import' is invalid. 'import()' calls can be written, but they must have parentheses and cannot have type arguments."), String_literal_with_double_quotes_expected: diag(1327, 1 /* Error */, "String_literal_with_double_quotes_expected_1327", "String literal with double quotes expected."), @@ -9716,6 +9530,20 @@ var Diagnostics = { This_character_cannot_be_escaped_in_a_regular_expression: diag(1535, 1 /* Error */, "This_character_cannot_be_escaped_in_a_regular_expression_1535", "This character cannot be escaped in a regular expression."), Octal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class_If_this_was_intended_as_an_escape_sequence_use_the_syntax_0_instead: diag(1536, 1 /* Error */, "Octal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class_If_this_was_intended__1536", "Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '{0}' instead."), Decimal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class: diag(1537, 1 /* Error */, "Decimal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class_1537", "Decimal escape sequences and backreferences are not allowed in a character class."), + Unicode_escape_sequences_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_set: diag(1538, 1 /* Error */, "Unicode_escape_sequences_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_se_1538", "Unicode escape sequences are only available when the Unicode (u) flag or the Unicode Sets (v) flag is set."), + A_bigint_literal_cannot_be_used_as_a_property_name: diag(1539, 1 /* Error */, "A_bigint_literal_cannot_be_used_as_a_property_name_1539", "A 'bigint' literal cannot be used as a property name."), + A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead: diag( + 1540, + 2 /* Suggestion */, + "A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_key_1540", + "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.", + /*reportsUnnecessary*/ + void 0, + /*elidedInCompatabilityPyramid*/ + void 0, + /*reportsDeprecated*/ + true + ), The_types_of_0_are_incompatible_between_these_types: diag(2200, 1 /* Error */, "The_types_of_0_are_incompatible_between_these_types_2200", "The types of '{0}' are incompatible between these types."), The_types_returned_by_0_are_incompatible_between_these_types: diag(2201, 1 /* Error */, "The_types_returned_by_0_are_incompatible_between_these_types_2201", "The types returned by '{0}' are incompatible between these types."), Call_signature_return_types_0_and_1_are_incompatible: diag( @@ -9970,7 +9798,6 @@ var Diagnostics = { The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES5_Consider_using_a_standard_function_or_method: diag(2522, 1 /* Error */, "The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES5_Consider_using_a_sta_2522", "The 'arguments' object cannot be referenced in an async function or method in ES5. Consider using a standard function or method."), yield_expressions_cannot_be_used_in_a_parameter_initializer: diag(2523, 1 /* Error */, "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523", "'yield' expressions cannot be used in a parameter initializer."), await_expressions_cannot_be_used_in_a_parameter_initializer: diag(2524, 1 /* Error */, "await_expressions_cannot_be_used_in_a_parameter_initializer_2524", "'await' expressions cannot be used in a parameter initializer."), - Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value: diag(2525, 1 /* Error */, "Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value_2525", "Initializer provides no value for this binding element and the binding element has no default value."), A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface: diag(2526, 1 /* Error */, "A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface_2526", "A 'this' type is available only in a non-static member of a class or interface."), The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary: diag(2527, 1 /* Error */, "The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527", "The inferred type of '{0}' references an inaccessible '{1}' type. A type annotation is necessary."), A_module_cannot_have_multiple_default_exports: diag(2528, 1 /* Error */, "A_module_cannot_have_multiple_default_exports_2528", "A module cannot have multiple default exports."), @@ -10283,6 +10110,11 @@ var Diagnostics = { Import_0_conflicts_with_global_value_used_in_this_file_so_must_be_declared_with_a_type_only_import_when_isolatedModules_is_enabled: diag(2866, 1 /* Error */, "Import_0_conflicts_with_global_value_used_in_this_file_so_must_be_declared_with_a_type_only_import_w_2866", "Import '{0}' conflicts with global value used in this file, so must be declared with a type-only import when 'isolatedModules' is enabled."), Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_Bun_Try_npm_i_save_dev_types_Slashbun: diag(2867, 1 /* Error */, "Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_Bun_Try_npm_i_save_dev_types_Slashbun_2867", "Cannot find name '{0}'. Do you need to install type definitions for Bun? Try `npm i --save-dev @types/bun`."), Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_Bun_Try_npm_i_save_dev_types_Slashbun_and_then_add_bun_to_the_types_field_in_your_tsconfig: diag(2868, 1 /* Error */, "Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_Bun_Try_npm_i_save_dev_types_Slashbun_2868", "Cannot find name '{0}'. Do you need to install type definitions for Bun? Try `npm i --save-dev @types/bun` and then add 'bun' to the types field in your tsconfig."), + Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish: diag(2869, 1 /* Error */, "Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish_2869", "Right operand of ?? is unreachable because the left operand is never nullish."), + This_binary_expression_is_never_nullish_Are_you_missing_parentheses: diag(2870, 1 /* Error */, "This_binary_expression_is_never_nullish_Are_you_missing_parentheses_2870", "This binary expression is never nullish. Are you missing parentheses?"), + This_expression_is_always_nullish: diag(2871, 1 /* Error */, "This_expression_is_always_nullish_2871", "This expression is always nullish."), + This_kind_of_expression_is_always_truthy: diag(2872, 1 /* Error */, "This_kind_of_expression_is_always_truthy_2872", "This kind of expression is always truthy."), + This_kind_of_expression_is_always_falsy: diag(2873, 1 /* Error */, "This_kind_of_expression_is_always_falsy_2873", "This kind of expression is always falsy."), Import_declaration_0_is_using_private_name_1: diag(4e3, 1 /* Error */, "Import_declaration_0_is_using_private_name_1_4000", "Import declaration '{0}' is using private name '{1}'."), Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: diag(4002, 1 /* Error */, "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002", "Type parameter '{0}' of exported class has or is using private name '{1}'."), Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: diag(4004, 1 /* Error */, "Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1_4004", "Type parameter '{0}' of exported interface has or is using private name '{1}'."), @@ -10359,7 +10191,7 @@ var Diagnostics = { Extends_clause_for_inferred_type_0_has_or_is_using_private_name_1: diag(4085, 1 /* Error */, "Extends_clause_for_inferred_type_0_has_or_is_using_private_name_1_4085", "Extends clause for inferred type '{0}' has or is using private name '{1}'."), Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4091, 1 /* Error */, "Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2_4091", "Parameter '{0}' of index signature from exported interface has or is using name '{1}' from private module '{2}'."), Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1: diag(4092, 1 /* Error */, "Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1_4092", "Parameter '{0}' of index signature from exported interface has or is using private name '{1}'."), - Property_0_of_exported_class_expression_may_not_be_private_or_protected: diag(4094, 1 /* Error */, "Property_0_of_exported_class_expression_may_not_be_private_or_protected_4094", "Property '{0}' of exported class expression may not be private or protected."), + Property_0_of_exported_anonymous_class_type_may_not_be_private_or_protected: diag(4094, 1 /* Error */, "Property_0_of_exported_anonymous_class_type_may_not_be_private_or_protected_4094", "Property '{0}' of exported anonymous class type may not be private or protected."), Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: diag(4095, 1 /* Error */, "Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_4095", "Public static method '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named."), Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: diag(4096, 1 /* Error */, "Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2_4096", "Public static method '{0}' of exported class has or is using name '{1}' from private module '{2}'."), Public_static_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4097, 1 /* Error */, "Public_static_method_0_of_exported_class_has_or_is_using_private_name_1_4097", "Public static method '{0}' of exported class has or is using private name '{1}'."), @@ -10396,7 +10228,6 @@ var Diagnostics = { Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, 1 /* Error */, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, 1 /* Error */, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), Cannot_read_file_0_Colon_1: diag(5012, 1 /* Error */, "Cannot_read_file_0_Colon_1_5012", "Cannot read file '{0}': {1}."), - Failed_to_parse_file_0_Colon_1: diag(5014, 1 /* Error */, "Failed_to_parse_file_0_Colon_1_5014", "Failed to parse file '{0}': {1}."), Unknown_compiler_option_0: diag(5023, 1 /* Error */, "Unknown_compiler_option_0_5023", "Unknown compiler option '{0}'."), Compiler_option_0_requires_a_value_of_type_1: diag(5024, 1 /* Error */, "Compiler_option_0_requires_a_value_of_type_1_5024", "Compiler option '{0}' requires a value of type {1}."), Unknown_compiler_option_0_Did_you_mean_1: diag(5025, 1 /* Error */, "Unknown_compiler_option_0_Did_you_mean_1_5025", "Unknown compiler option '{0}'. Did you mean '{1}'?"), @@ -10459,6 +10290,7 @@ var Diagnostics = { Option_0_1_has_been_removed_Please_remove_it_from_your_configuration: diag(5108, 1 /* Error */, "Option_0_1_has_been_removed_Please_remove_it_from_your_configuration_5108", "Option '{0}={1}' has been removed. Please remove it from your configuration."), Option_moduleResolution_must_be_set_to_0_or_left_unspecified_when_option_module_is_set_to_1: diag(5109, 1 /* Error */, "Option_moduleResolution_must_be_set_to_0_or_left_unspecified_when_option_module_is_set_to_1_5109", "Option 'moduleResolution' must be set to '{0}' (or left unspecified) when option 'module' is set to '{1}'."), Option_module_must_be_set_to_0_when_option_moduleResolution_is_set_to_1: diag(5110, 1 /* Error */, "Option_module_must_be_set_to_0_when_option_moduleResolution_is_set_to_1_5110", "Option 'module' must be set to '{0}' when option 'moduleResolution' is set to '{1}'."), + Option_tsBuildInfoFile_cannot_be_specified_without_specifying_option_incremental_or_composite_or_if_not_running_tsc_b: diag(5111, 1 /* Error */, "Option_tsBuildInfoFile_cannot_be_specified_without_specifying_option_incremental_or_composite_or_if__5111", "Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or 'composite' or if not running 'tsc -b'."), Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6e3, 3 /* Message */, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."), Concatenate_and_emit_output_to_single_file: diag(6001, 3 /* Message */, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."), Generates_corresponding_d_ts_file: diag(6002, 3 /* Message */, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."), @@ -10597,7 +10429,6 @@ var Diagnostics = { Parse_in_strict_mode_and_emit_use_strict_for_each_source_file: diag(6141, 3 /* Message */, "Parse_in_strict_mode_and_emit_use_strict_for_each_source_file_6141", 'Parse in strict mode and emit "use strict" for each source file.'), Module_0_was_resolved_to_1_but_jsx_is_not_set: diag(6142, 1 /* Error */, "Module_0_was_resolved_to_1_but_jsx_is_not_set_6142", "Module '{0}' was resolved to '{1}', but '--jsx' is not set."), Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1: diag(6144, 3 /* Message */, "Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1_6144", "Module '{0}' was resolved as locally declared ambient module in file '{1}'."), - Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified: diag(6145, 3 /* Message */, "Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified_6145", "Module '{0}' was resolved as ambient module declared in '{1}' since this file was not modified."), Specify_the_JSX_factory_function_to_use_when_targeting_react_JSX_emit_e_g_React_createElement_or_h: diag(6146, 3 /* Message */, "Specify_the_JSX_factory_function_to_use_when_targeting_react_JSX_emit_e_g_React_createElement_or_h_6146", "Specify the JSX factory function to use when targeting 'react' JSX emit, e.g. 'React.createElement' or 'h'."), Resolution_for_module_0_was_found_in_cache_from_location_1: diag(6147, 3 /* Message */, "Resolution_for_module_0_was_found_in_cache_from_location_1_6147", "Resolution for module '{0}' was found in cache from location '{1}'."), Directory_0_does_not_exist_skipping_all_lookups_in_it: diag(6148, 3 /* Message */, "Directory_0_does_not_exist_skipping_all_lookups_in_it_6148", "Directory '{0}' does not exist, skipping all lookups in it."), @@ -10839,6 +10670,8 @@ var Diagnostics = { Exiting_conditional_exports: diag(6416, 3 /* Message */, "Exiting_conditional_exports_6416", "Exiting conditional exports."), Searching_all_ancestor_node_modules_directories_for_preferred_extensions_Colon_0: diag(6417, 3 /* Message */, "Searching_all_ancestor_node_modules_directories_for_preferred_extensions_Colon_0_6417", "Searching all ancestor node_modules directories for preferred extensions: {0}."), Searching_all_ancestor_node_modules_directories_for_fallback_extensions_Colon_0: diag(6418, 3 /* Message */, "Searching_all_ancestor_node_modules_directories_for_fallback_extensions_Colon_0_6418", "Searching all ancestor node_modules directories for fallback extensions: {0}."), + Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors: diag(6419, 3 /* Message */, "Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors_6419", "Project '{0}' is out of date because buildinfo file '{1}' indicates that program needs to report errors."), + Project_0_is_out_of_date_because_1: diag(6420, 3 /* Message */, "Project_0_is_out_of_date_because_1_6420", "Project '{0}' is out of date because {1}."), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, 3 /* Message */, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, 3 /* Message */, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, 3 /* Message */, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -10885,6 +10718,7 @@ var Diagnostics = { Ensure_that_casing_is_correct_in_imports: diag(6637, 3 /* Message */, "Ensure_that_casing_is_correct_in_imports_6637", "Ensure that casing is correct in imports."), Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging: diag(6638, 3 /* Message */, "Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging_6638", "Emit a v8 CPU profile of the compiler run for debugging."), Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file: diag(6639, 3 /* Message */, "Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file_6639", "Allow importing helper functions from tslib once per project, instead of including them per-file."), + Skip_building_downstream_projects_on_error_in_upstream_project: diag(6640, 3 /* Message */, "Skip_building_downstream_projects_on_error_in_upstream_project_6640", "Skip building downstream projects on error in upstream project."), Specify_a_list_of_glob_patterns_that_match_files_to_be_included_in_compilation: diag(6641, 3 /* Message */, "Specify_a_list_of_glob_patterns_that_match_files_to_be_included_in_compilation_6641", "Specify a list of glob patterns that match files to be included in compilation."), Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects: diag(6642, 3 /* Message */, "Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects_6642", "Save .tsbuildinfo files to allow for incremental compilation of projects."), Include_sourcemap_files_inside_the_emitted_JavaScript: diag(6643, 3 /* Message */, "Include_sourcemap_files_inside_the_emitted_JavaScript_6643", "Include sourcemap files inside the emitted JavaScript."), @@ -10961,9 +10795,12 @@ var Diagnostics = { Require_undeclared_properties_from_index_signatures_to_use_element_accesses: diag(6717, 3 /* Message */, "Require_undeclared_properties_from_index_signatures_to_use_element_accesses_6717", "Require undeclared properties from index signatures to use element accesses."), Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types: diag(6718, 3 /* Message */, "Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types_6718", "Specify emit/checking behavior for imports that are only used for types."), Require_sufficient_annotation_on_exports_so_other_tools_can_trivially_generate_declaration_files: diag(6719, 3 /* Message */, "Require_sufficient_annotation_on_exports_so_other_tools_can_trivially_generate_declaration_files_6719", "Require sufficient annotation on exports so other tools can trivially generate declaration files."), + Built_in_iterators_are_instantiated_with_a_TReturn_type_of_undefined_instead_of_any: diag(6720, 3 /* Message */, "Built_in_iterators_are_instantiated_with_a_TReturn_type_of_undefined_instead_of_any_6720", "Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'."), Default_catch_clause_variables_as_unknown_instead_of_any: diag(6803, 3 /* Message */, "Default_catch_clause_variables_as_unknown_instead_of_any_6803", "Default catch clause variables as 'unknown' instead of 'any'."), Do_not_transform_or_elide_any_imports_or_exports_not_marked_as_type_only_ensuring_they_are_written_in_the_output_file_s_format_based_on_the_module_setting: diag(6804, 3 /* Message */, "Do_not_transform_or_elide_any_imports_or_exports_not_marked_as_type_only_ensuring_they_are_written_i_6804", "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting."), Disable_full_type_checking_only_critical_parse_and_emit_errors_will_be_reported: diag(6805, 3 /* Message */, "Disable_full_type_checking_only_critical_parse_and_emit_errors_will_be_reported_6805", "Disable full type checking (only critical parse and emit errors will be reported)."), + Check_side_effect_imports: diag(6806, 3 /* Message */, "Check_side_effect_imports_6806", "Check side effect imports."), + This_operation_can_be_simplified_This_shift_is_identical_to_0_1_2: diag(6807, 1 /* Error */, "This_operation_can_be_simplified_This_shift_is_identical_to_0_1_2_6807", "This operation can be simplified. This shift is identical to `{0} {1} {2}`."), one_of_Colon: diag(6900, 3 /* Message */, "one_of_Colon_6900", "one of:"), one_or_more_Colon: diag(6901, 3 /* Message */, "one_or_more_Colon_6901", "one or more:"), type_Colon: diag(6902, 3 /* Message */, "type_Colon_6902", "type:"), @@ -11457,7 +11294,8 @@ var Diagnostics = { Its_type_0_is_not_a_valid_JSX_element_type: diag(18053, 1 /* Error */, "Its_type_0_is_not_a_valid_JSX_element_type_18053", "Its type '{0}' is not a valid JSX element type."), await_using_statements_cannot_be_used_inside_a_class_static_block: diag(18054, 1 /* Error */, "await_using_statements_cannot_be_used_inside_a_class_static_block_18054", "'await using' statements cannot be used inside a class static block."), _0_has_a_string_type_but_must_have_syntactically_recognizable_string_syntax_when_isolatedModules_is_enabled: diag(18055, 1 /* Error */, "_0_has_a_string_type_but_must_have_syntactically_recognizable_string_syntax_when_isolatedModules_is__18055", "'{0}' has a string type, but must have syntactically recognizable string syntax when 'isolatedModules' is enabled."), - Enum_member_following_a_non_literal_numeric_member_must_have_an_initializer_when_isolatedModules_is_enabled: diag(18056, 1 /* Error */, "Enum_member_following_a_non_literal_numeric_member_must_have_an_initializer_when_isolatedModules_is__18056", "Enum member following a non-literal numeric member must have an initializer when 'isolatedModules' is enabled.") + Enum_member_following_a_non_literal_numeric_member_must_have_an_initializer_when_isolatedModules_is_enabled: diag(18056, 1 /* Error */, "Enum_member_following_a_non_literal_numeric_member_must_have_an_initializer_when_isolatedModules_is__18056", "Enum member following a non-literal numeric member must have an initializer when 'isolatedModules' is enabled."), + String_literal_import_and_export_names_are_not_supported_when_the_module_flag_is_set_to_es2015_or_es2020: diag(18057, 1 /* Error */, "String_literal_import_and_export_names_are_not_supported_when_the_module_flag_is_set_to_es2015_or_es_18057", "String literal import and export names are not supported when the '--module' flag is set to 'es2015' or 'es2020'.") }; // src/compiler/deno.ts @@ -11466,28 +11304,21 @@ __export(deno_exports, { createDenoForkContext: () => createDenoForkContext, parseNpmPackageReference: () => parseNpmPackageReference, setIsNodeSourceFileCallback: () => setIsNodeSourceFileCallback, - setNodeBuiltInModuleNames: () => setNodeBuiltInModuleNames, setNodeOnlyGlobalNames: () => setNodeOnlyGlobalNames, tryParseNpmPackageReference: () => tryParseNpmPackageReference }); var isNodeSourceFile = () => false; -var nodeBuiltInModuleNames = /* @__PURE__ */ new Set(); var nodeOnlyGlobalNames = /* @__PURE__ */ new Set(); function setIsNodeSourceFileCallback(callback) { isNodeSourceFile = callback; } -function setNodeBuiltInModuleNames(names) { - nodeBuiltInModuleNames = new Set(names); -} function setNodeOnlyGlobalNames(names) { - nodeBuiltInModuleNames = new Set(names); nodeOnlyGlobalNames = new Set(names); } function createDenoForkContext({ mergeSymbol, globals, - nodeGlobals, - ambientModuleSymbolRegex: ambientModuleSymbolRegex2 + nodeGlobals }) { return { hasNodeSourceFile, @@ -11501,15 +11332,6 @@ function createDenoForkContext({ return isNodeSourceFile(sourceFile); } function getGlobalsForName(id) { - if (ambientModuleSymbolRegex2.test(id)) { - if (id.startsWith('"node:')) { - const name = id.slice(6, -1); - if (nodeBuiltInModuleNames.has(name)) { - return globals; - } - } - return nodeGlobals; - } return nodeOnlyGlobalNames.has(id) ? nodeGlobals : globals; } function mergeGlobalSymbolTable(node, source, unidirectional = false) { @@ -11777,16 +11599,16 @@ var textToToken = new Map(Object.entries({ "#": 63 /* HashToken */, "`": 62 /* BacktickToken */ })); -var charToRegExpFlag = new Map(Object.entries({ - d: 1 /* HasIndices */, - g: 2 /* Global */, - i: 4 /* IgnoreCase */, - m: 8 /* Multiline */, - s: 16 /* DotAll */, - u: 32 /* Unicode */, - v: 64 /* UnicodeSets */, - y: 128 /* Sticky */ -})); +var charCodeToRegExpFlag = /* @__PURE__ */ new Map([ + [100 /* d */, 1 /* HasIndices */], + [103 /* g */, 2 /* Global */], + [105 /* i */, 4 /* IgnoreCase */], + [109 /* m */, 8 /* Multiline */], + [115 /* s */, 16 /* DotAll */], + [117 /* u */, 32 /* Unicode */], + [118 /* v */, 64 /* UnicodeSets */], + [121 /* y */, 128 /* Sticky */] +]); var regExpFlagToFirstAvailableLanguageVersion = /* @__PURE__ */ new Map([ [1 /* HasIndices */, 9 /* RegularExpressionFlagsHasIndices */], [16 /* DotAll */, 5 /* RegularExpressionFlagsDotAll */], @@ -11842,12 +11664,12 @@ function tokenToString(t) { function stringToToken(s) { return textToToken.get(s); } -var regExpFlagChars = makeReverseMap(charToRegExpFlag); -function regularExpressionFlagToCharacter(f) { - return regExpFlagChars[f]; +var regExpFlagCharCodes = makeReverseMap(charCodeToRegExpFlag); +function regularExpressionFlagToCharacterCode(f) { + return regExpFlagCharCodes[f]; } -function characterToRegularExpressionFlag(c) { - return charToRegExpFlag.get(c); +function characterCodeToRegularExpressionFlag(ch) { + return charCodeToRegExpFlag.get(ch); } function computeLineStarts(text) { const result = []; @@ -11884,7 +11706,7 @@ function computePositionOfLineAndCharacter(lineStarts, line, character, debugTex if (allowEdits) { line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line; } else { - Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== void 0 ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`); + Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== void 0 ? arrayIsEqualTo(lineStarts, computeLineStarts(debugText)) : "unknown"}`); } } const res = lineStarts[line] + character; @@ -12333,6 +12155,7 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan hasExtendedUnicodeEscape: () => (tokenFlags & 8 /* ExtendedUnicodeEscape */) !== 0, hasPrecedingLineBreak: () => (tokenFlags & 1 /* PrecedingLineBreak */) !== 0, hasPrecedingJSDocComment: () => (tokenFlags & 2 /* PrecedingJSDocComment */) !== 0, + hasPrecedingJSDocLeadingAsterisks: () => (tokenFlags & 32768 /* PrecedingJSDocLeadingAsterisks */) !== 0, isIdentifier: () => token === 80 /* Identifier */ || token > 118 /* LastReservedWord */, isReservedWord: () => token >= 83 /* FirstReservedWord */ && token <= 118 /* LastReservedWord */, isUnterminated: () => (tokenFlags & 4 /* Unterminated */) !== 0, @@ -12749,9 +12572,16 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan case 34 /* doubleQuote */: return '"'; case 117 /* u */: - if (flags & 17 /* ScanExtendedUnicodeEscape */ && pos < end && charCodeUnchecked(pos) === 123 /* openBrace */) { + if (pos < end && charCodeUnchecked(pos) === 123 /* openBrace */) { pos -= 2; - return scanExtendedUnicodeEscape(!!(flags & 6 /* ReportInvalidEscapeErrors */)); + const result = scanExtendedUnicodeEscape(!!(flags & 6 /* ReportInvalidEscapeErrors */)); + if (!(flags & 17 /* AllowExtendedUnicodeEscape */)) { + tokenFlags |= 2048 /* ContainsInvalidEscape */; + if (flags & 6 /* ReportInvalidEscapeErrors */) { + error2(Diagnostics.Unicode_escape_sequences_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_set, start2, pos - start2); + } + } + return result; } for (; pos < start2 + 6; pos++) { if (!(pos < end && isHexDigit(charCodeUnchecked(pos)))) { @@ -12769,7 +12599,7 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan const nextStart = pos; let nextPos = pos + 2; for (; nextPos < nextStart + 6; nextPos++) { - if (!isHexDigit(charCodeUnchecked(pos))) { + if (!isHexDigit(charCodeUnchecked(nextPos))) { return escapedValueString; } } @@ -12973,7 +12803,6 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan function scan() { fullStartPos = pos; tokenFlags = 0 /* None */; - let asteriskSeen = false; while (true) { tokenStart = pos; if (pos >= end) { @@ -13089,8 +12918,8 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan return pos += 2, token = 43 /* AsteriskAsteriskToken */; } pos++; - if (skipJsDocLeadingAsterisks && !asteriskSeen && tokenFlags & 1 /* PrecedingLineBreak */) { - asteriskSeen = true; + if (skipJsDocLeadingAsterisks && (tokenFlags & 32768 /* PrecedingJSDocLeadingAsterisks */) === 0 && tokenFlags & 1 /* PrecedingLineBreak */) { + tokenFlags |= 32768 /* PrecedingJSDocLeadingAsterisks */; continue; } return token = 42 /* AsteriskToken */; @@ -13563,24 +13392,25 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan pos++; let regExpFlags = 0 /* None */; while (true) { - const ch = charCodeChecked(pos); + const ch = codePointChecked(pos); if (ch === -1 /* EOF */ || !isIdentifierPart(ch, languageVersion)) { break; } + const size = charSize(ch); if (reportErrors2) { - const flag = characterToRegularExpressionFlag(String.fromCharCode(ch)); + const flag = characterCodeToRegularExpressionFlag(ch); if (flag === void 0) { - error2(Diagnostics.Unknown_regular_expression_flag, pos, 1); + error2(Diagnostics.Unknown_regular_expression_flag, pos, size); } else if (regExpFlags & flag) { - error2(Diagnostics.Duplicate_regular_expression_flag, pos, 1); + error2(Diagnostics.Duplicate_regular_expression_flag, pos, size); } else if (((regExpFlags | flag) & 96 /* AnyUnicodeMode */) === 96 /* AnyUnicodeMode */) { - error2(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, pos, 1); + error2(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, pos, size); } else { regExpFlags |= flag; - checkRegularExpressionFlagAvailable(flag, pos); + checkRegularExpressionFlagAvailability(flag, size); } } - pos++; + pos += size; } if (reportErrors2) { scanRange(startOfRegExpBody, endOfRegExpBody - startOfRegExpBody, () => { @@ -13795,22 +13625,23 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan } function scanPatternModifiers(currFlags) { while (true) { - const ch = charCodeChecked(pos); + const ch = codePointChecked(pos); if (ch === -1 /* EOF */ || !isIdentifierPart(ch, languageVersion)) { break; } - const flag = characterToRegularExpressionFlag(String.fromCharCode(ch)); + const size = charSize(ch); + const flag = characterCodeToRegularExpressionFlag(ch); if (flag === void 0) { - error2(Diagnostics.Unknown_regular_expression_flag, pos, 1); + error2(Diagnostics.Unknown_regular_expression_flag, pos, size); } else if (currFlags & flag) { - error2(Diagnostics.Duplicate_regular_expression_flag, pos, 1); + error2(Diagnostics.Duplicate_regular_expression_flag, pos, size); } else if (!(flag & 28 /* Modifiers */)) { - error2(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, 1); + error2(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, size); } else { currFlags |= flag; - checkRegularExpressionFlagAvailable(flag, pos); + checkRegularExpressionFlagAvailability(flag, size); } - pos++; + pos += size; } return currFlags; } @@ -14396,7 +14227,7 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan return value; } function scanSourceCharacter() { - const size = anyUnicodeMode ? charSize(charCodeChecked(pos)) : 1; + const size = anyUnicodeMode ? charSize(codePointChecked(pos)) : 1; pos += size; return size > 0 ? text.substring(pos - size, pos) : ""; } @@ -14414,6 +14245,12 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan forEach(groupNameReferences, (reference) => { if (!(groupSpecifiers == null ? void 0 : groupSpecifiers.has(reference.name))) { error2(Diagnostics.There_is_no_capturing_group_named_0_in_this_regular_expression, reference.pos, reference.end - reference.pos, reference.name); + if (groupSpecifiers) { + const suggestion = getSpellingSuggestion(reference.name, groupSpecifiers, identity); + if (suggestion) { + error2(Diagnostics.Did_you_mean_0, reference.pos, reference.end - reference.pos, suggestion); + } + } } }); forEach(decimalEscapes, (escape) => { @@ -14426,10 +14263,10 @@ function createScanner(languageVersion, skipTrivia2, languageVariant = 0 /* Stan } }); } - function checkRegularExpressionFlagAvailable(flag, pos2) { + function checkRegularExpressionFlagAvailability(flag, size) { const availableFrom = regExpFlagToFirstAvailableLanguageVersion.get(flag); if (availableFrom && languageVersion < availableFrom) { - error2(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos2, 1, getNameOfScriptTarget(availableFrom)); + error2(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos, size, getNameOfScriptTarget(availableFrom)); } } function appendIfCommentDirective(commentDirectives2, text2, commentDirectiveRegEx, lineStart) { @@ -14861,12 +14698,18 @@ function textSpanIsEmpty(span) { function textSpanContainsPosition(span, position) { return position >= span.start && position < textSpanEnd(span); } -function textRangeContainsPositionInclusive(span, position) { - return position >= span.pos && position <= span.end; +function textRangeContainsPositionInclusive(range, position) { + return position >= range.pos && position <= range.end; } function textSpanContainsTextSpan(span, other) { return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span); } +function textSpanContainsTextRange(span, range) { + return range.pos >= span.start && range.end <= textSpanEnd(span); +} +function textRangeContainsTextSpan(range, span) { + return span.start >= range.pos && textSpanEnd(span) <= range.end; +} function textSpanOverlapsWith(span, other) { return textSpanOverlap(span, other) !== void 0; } @@ -14888,11 +14731,34 @@ function decodedTextSpanIntersectsWith(start1, length1, start2, length2) { function textSpanIntersectsWithPosition(span, position) { return position <= textSpanEnd(span) && position >= span.start; } +function textRangeIntersectsWithTextSpan(range, span) { + return textSpanIntersectsWith(span, range.pos, range.end - range.pos); +} function textSpanIntersection(span1, span2) { const start = Math.max(span1.start, span2.start); const end = Math.min(textSpanEnd(span1), textSpanEnd(span2)); return start <= end ? createTextSpanFromBounds(start, end) : void 0; } +function normalizeSpans(spans) { + spans = spans.filter((span) => span.length > 0).sort((a, b) => { + return a.start !== b.start ? a.start - b.start : a.length - b.length; + }); + const result = []; + let i = 0; + while (i < spans.length) { + let span = spans[i]; + let j = i + 1; + while (j < spans.length && textSpanIntersectsWithTextSpan(span, spans[j])) { + const start = Math.min(span.start, spans[j].start); + const end = Math.max(textSpanEnd(span), textSpanEnd(spans[j])); + span = createTextSpanFromBounds(start, end); + j++; + } + i = j; + result.push(span); + } + return result; +} function createTextSpan(start, length2) { if (start < 0) { throw new Error("start < 0"); @@ -15010,7 +14876,7 @@ function getNodeFlags(node) { var supportedLocaleDirectories = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"]; function validateLocaleAndSetLanguage(locale, sys2, errors) { const lowerCaseLocale = locale.toLowerCase(); - const matchResult = /^([a-z]+)([_-]([a-z]+))?$/.exec(lowerCaseLocale); + const matchResult = /^([a-z]+)(?:[_-]([a-z]+))?$/.exec(lowerCaseLocale); if (!matchResult) { if (errors) { errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); @@ -15018,7 +14884,7 @@ function validateLocaleAndSetLanguage(locale, sys2, errors) { return; } const language = matchResult[1]; - const territory = matchResult[3]; + const territory = matchResult[2]; if (contains(supportedLocaleDirectories, lowerCaseLocale) && !trySetLanguageAndTerritory(language, territory, errors)) { trySetLanguageAndTerritory( language, @@ -15042,7 +14908,7 @@ function validateLocaleAndSetLanguage(locale, sys2, errors) { let fileContents = ""; try { fileContents = sys2.readFile(filePath); - } catch (e) { + } catch { if (errors2) { errors2.push(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, filePath)); } @@ -15441,13 +15307,6 @@ function getJSDocTags(node) { false ); } -function getJSDocTagsNoCache(node) { - return getJSDocTagsWorker( - node, - /*noCache*/ - true - ); -} function getFirstJSDocTag(node, predicate, noCache) { return find(getJSDocTagsWorker(node, noCache), predicate); } @@ -15550,9 +15409,6 @@ function isNamedExportBindings(node) { function isJSDocPropertyLikeTag(node) { return node.kind === 348 /* JSDocPropertyTag */ || node.kind === 341 /* JSDocParameterTag */; } -function isNode(node) { - return isNodeKind(node.kind); -} function isNodeKind(kind) { return kind >= 166 /* FirstNode */; } @@ -15764,17 +15620,6 @@ function isMethodOrAccessor(node) { return false; } } -function isNamedClassElement(node) { - switch (node.kind) { - case 174 /* MethodDeclaration */: - case 177 /* GetAccessor */: - case 178 /* SetAccessor */: - case 172 /* PropertyDeclaration */: - return true; - default: - return false; - } -} function isModifierLike(node) { return isModifier(node) || isDecorator(node); } @@ -16008,9 +15853,6 @@ function isAssertionExpression(node) { const kind = node.kind; return kind === 216 /* TypeAssertionExpression */ || kind === 234 /* AsExpression */; } -function isNotEmittedOrPartiallyEmittedNode(node) { - return isNotEmittedStatement(node) || isPartiallyEmittedExpression(node); -} function isIterationStatement(node, lookInLabeledStatements) { switch (node.kind) { case 248 /* ForStatement */: @@ -16495,6 +16337,12 @@ function projectReferenceIsEqualTo(oldRef, newRef) { function moduleResolutionIsEqualTo(oldResolution, newResolution) { return oldResolution === newResolution || oldResolution.resolvedModule === newResolution.resolvedModule || !!oldResolution.resolvedModule && !!newResolution.resolvedModule && oldResolution.resolvedModule.isExternalLibraryImport === newResolution.resolvedModule.isExternalLibraryImport && oldResolution.resolvedModule.extension === newResolution.resolvedModule.extension && oldResolution.resolvedModule.resolvedFileName === newResolution.resolvedModule.resolvedFileName && oldResolution.resolvedModule.originalPath === newResolution.resolvedModule.originalPath && packageIdIsEqual(oldResolution.resolvedModule.packageId, newResolution.resolvedModule.packageId) && oldResolution.alternateResult === newResolution.alternateResult; } +function getResolvedModuleFromResolution(resolution) { + return resolution.resolvedModule; +} +function getResolvedTypeReferenceDirectiveFromResolution(resolution) { + return resolution.resolvedTypeReferenceDirective; +} function createModuleNotFoundChain(sourceFile, host, moduleReference, mode, packageName) { var _a; const alternateResult = (_a = host.getResolvedModule(sourceFile, moduleReference, mode)) == null ? void 0 : _a.alternateResult; @@ -16529,6 +16377,34 @@ function createModuleNotFoundChain(sourceFile, host, moduleReference, mode, pack if (result) result.repopulateInfo = () => ({ moduleReference, mode, packageName: packageName === moduleReference ? void 0 : packageName }); return result; } +function createModeMismatchDetails(currentSourceFile) { + const ext = tryGetExtensionFromPath2(currentSourceFile.fileName); + const scope = currentSourceFile.packageJsonScope; + const targetExt = ext === ".ts" /* Ts */ ? ".mts" /* Mts */ : ext === ".js" /* Js */ ? ".mjs" /* Mjs */ : void 0; + const result = scope && !scope.contents.packageJsonContent.type ? targetExt ? chainDiagnosticMessages( + /*details*/ + void 0, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, + targetExt, + combinePaths(scope.packageDirectory, "package.json") + ) : chainDiagnosticMessages( + /*details*/ + void 0, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, + combinePaths(scope.packageDirectory, "package.json") + ) : targetExt ? chainDiagnosticMessages( + /*details*/ + void 0, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, + targetExt + ) : chainDiagnosticMessages( + /*details*/ + void 0, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module + ); + result.repopulateInfo = () => true; + return result; +} function packageIdIsEqual(a, b) { return a === b || !!a && !!b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version && a.peerDependencies === b.peerDependencies; } @@ -16719,7 +16595,7 @@ function getTokenPosOfNode(node, sourceFile, includeJsDoc) { } if (isJSDocNode(node) || node.kind === 12 /* JsxText */) { return skipTrivia( - (sourceFile || getSourceFileOfNode(node)).text, + (sourceFile ?? getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, @@ -16731,13 +16607,14 @@ function getTokenPosOfNode(node, sourceFile, includeJsDoc) { return getTokenPosOfNode(node.jsDoc[0], sourceFile); } if (node.kind === 352 /* SyntaxList */) { - const first2 = firstOrUndefined(getNodeChildren(node)); + sourceFile ?? (sourceFile = getSourceFileOfNode(node)); + const first2 = firstOrUndefined(getNodeChildren(node, sourceFile)); if (first2) { return getTokenPosOfNode(first2, sourceFile, includeJsDoc); } } return skipTrivia( - (sourceFile || getSourceFileOfNode(node)).text, + (sourceFile ?? getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, @@ -16753,6 +16630,13 @@ function getNonDecoratorTokenPosOfNode(node, sourceFile) { } return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastDecorator.end); } +function getNonModifierTokenPosOfNode(node, sourceFile) { + const lastModifier = !nodeIsMissing(node) && canHaveModifiers(node) && node.modifiers ? last(node.modifiers) : void 0; + if (!lastModifier) { + return getTokenPosOfNode(node, sourceFile); + } + return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastModifier.end); +} function getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia = false) { return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia); } @@ -16760,7 +16644,16 @@ function isJSDocTypeExpressionOrChild(node) { return !!findAncestor(node, isJSDocTypeExpression); } function isExportNamespaceAsDefaultDeclaration(node) { - return !!(isExportDeclaration(node) && node.exportClause && isNamespaceExport(node.exportClause) && node.exportClause.name.escapedText === "default"); + return !!(isExportDeclaration(node) && node.exportClause && isNamespaceExport(node.exportClause) && moduleExportNameIsDefault(node.exportClause.name)); +} +function moduleExportNameTextUnescaped(node) { + return node.kind === 11 /* StringLiteral */ ? node.text : unescapeLeadingUnderscores(node.escapedText); +} +function moduleExportNameTextEscaped(node) { + return node.kind === 11 /* StringLiteral */ ? escapeLeadingUnderscores(node.text) : node.escapedText; +} +function moduleExportNameIsDefault(node) { + return (node.kind === 11 /* StringLiteral */ ? node.text : node.escapedText) === "default" /* Default */; } function getTextOfNodeFromSourceText(sourceText, node, includeTrivia = false) { if (nodeIsMissing(node)) { @@ -16813,7 +16706,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Iterator: new Map(Object.entries({ @@ -17090,7 +16987,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Uint8Array: new Map(Object.entries({ @@ -17099,7 +17000,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Uint8ClampedArray: new Map(Object.entries({ @@ -17108,7 +17013,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Int16Array: new Map(Object.entries({ @@ -17117,7 +17026,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Uint16Array: new Map(Object.entries({ @@ -17126,7 +17039,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Int32Array: new Map(Object.entries({ @@ -17135,7 +17052,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Uint32Array: new Map(Object.entries({ @@ -17144,7 +17065,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Float32Array: new Map(Object.entries({ @@ -17153,7 +17078,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Float64Array: new Map(Object.entries({ @@ -17162,7 +17091,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), BigInt64Array: new Map(Object.entries({ @@ -17172,7 +17105,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), BigUint64Array: new Map(Object.entries({ @@ -17182,7 +17119,11 @@ var getScriptTargetFeatures = /* @__PURE__ */ memoize( ], es2023: [ "findLastIndex", - "findLast" + "findLast", + "toReversed", + "toSorted", + "toSpliced", + "with" ] })), Error: new Map(Object.entries({ @@ -17473,6 +17414,7 @@ function tryGetTextOfPropertyName(name) { return ((_a = name.emitNode) == null ? void 0 : _a.autoGenerate) ? void 0 : name.escapedText; case 11 /* StringLiteral */: case 9 /* NumericLiteral */: + case 10 /* BigIntLiteral */: case 15 /* NoSubstitutionTemplateLiteral */: return escapeLeadingUnderscores(name.text); case 167 /* ComputedPropertyName */: @@ -17781,12 +17723,12 @@ function getJSDocCommentRanges(node, text) { return filter(commentRanges, (comment) => comment.end <= node.end && // Due to parse errors sometime empty parameter may get comments assigned to it that end up not in parameter range text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && text.charCodeAt(comment.pos + 3) !== 47 /* slash */); } -var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; -var fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*/; -var fullTripleSlashLibReferenceRegEx = /^(\/\/\/\s*/; -var fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; -var fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*/; -var defaultLibReferenceRegEx = /^(\/\/\/\s*/; +var fullTripleSlashReferencePathRegEx = /^\/\/\/\s*/; +var fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^\/\/\/\s*/; +var fullTripleSlashLibReferenceRegEx = /^\/\/\/\s*/; +var fullTripleSlashAMDReferencePathRegEx = /^\/\/\/\s*/; +var fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*/; +var defaultLibReferenceRegEx = /^\/\/\/\s*/; function isPartOfTypeNode(node) { if (182 /* FirstTypeNode */ <= node.kind && node.kind <= 205 /* LastTypeNode */) { return true; @@ -17869,15 +17811,6 @@ function isPartOfTypeNode(node) { function isPartOfTypeExpressionWithTypeArguments(node) { return isJSDocImplementsTag(node.parent) || isJSDocAugmentsTag(node.parent) || isHeritageClause(node.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(node); } -function isChildOfNodeWithKind(node, kind) { - while (node) { - if (node.kind === kind) { - return true; - } - node = node.parent; - } - return false; -} function forEachReturnStatement(body, visitor) { return traverse(body); function traverse(node) { @@ -18214,9 +18147,6 @@ function getImmediatelyInvokedFunctionExpression(func) { } } } -function isSuperOrSuperProperty(node) { - return node.kind === 108 /* SuperKeyword */ || isSuperProperty(node); -} function isSuperProperty(node) { const kind = node.kind; return (kind === 211 /* PropertyAccessExpression */ || kind === 212 /* ElementAccessExpression */) && node.expression.kind === 108 /* SuperKeyword */; @@ -18490,9 +18420,6 @@ function isFullSourceFile(sourceFile) { function isSourceFileJS(file) { return isInJSFile(file); } -function isSourceFileNotJS(file) { - return !isInJSFile(file); -} function isInJSFile(node) { return !!node && !!(node.flags & 524288 /* JavaScriptFile */); } @@ -18794,6 +18721,23 @@ function isFunctionSymbol(symbol) { const decl = symbol.valueDeclaration; return decl.kind === 262 /* FunctionDeclaration */ || isVariableDeclaration(decl) && decl.initializer && isFunctionLike(decl.initializer); } +function canHaveModuleSpecifier(node) { + switch (node == null ? void 0 : node.kind) { + case 260 /* VariableDeclaration */: + case 208 /* BindingElement */: + case 272 /* ImportDeclaration */: + case 278 /* ExportDeclaration */: + case 271 /* ImportEqualsDeclaration */: + case 273 /* ImportClause */: + case 280 /* NamespaceExport */: + case 274 /* NamespaceImport */: + case 281 /* ExportSpecifier */: + case 276 /* ImportSpecifier */: + case 205 /* ImportType */: + return true; + } + return false; +} function tryGetModuleSpecifierFromDeclaration(node) { var _a, _b; switch (node.kind) { @@ -19275,7 +19219,7 @@ function skipTypeParentheses(node) { return node; } function skipParentheses(node, excludeJSDocTypeAssertions) { - const flags = excludeJSDocTypeAssertions ? 1 /* Parentheses */ | 16 /* ExcludeJSDocTypeAssertion */ : 1 /* Parentheses */; + const flags = excludeJSDocTypeAssertions ? 1 /* Parentheses */ | -2147483648 /* ExcludeJSDocTypeAssertion */ : 1 /* Parentheses */; return skipOuterExpressions(node, flags); } function isDeleteTarget(node) { @@ -19348,12 +19292,6 @@ function isIdentifierName(node) { } return false; } -function isAliasSymbolDeclaration(node) { - if (node.kind === 271 /* ImportEqualsDeclaration */ || node.kind === 270 /* NamespaceExportDeclaration */ || node.kind === 273 /* ImportClause */ && !!node.name || node.kind === 274 /* NamespaceImport */ || node.kind === 280 /* NamespaceExport */ || node.kind === 276 /* ImportSpecifier */ || node.kind === 281 /* ExportSpecifier */ || node.kind === 277 /* ExportAssignment */ && exportAssignmentIsAlias(node)) { - return true; - } - return isInJSFile(node) && (isBinaryExpression(node) && getAssignmentDeclarationKind(node) === 2 /* ModuleExports */ && exportAssignmentIsAlias(node) || isPropertyAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === 64 /* EqualsToken */ && isAliasableExpression(node.parent.right)); -} function getAliasDeclarationFromName(node) { switch (node.parent.kind) { case 273 /* ImportClause */: @@ -19447,17 +19385,10 @@ function isContextualKeyword(token) { function isNonContextualKeyword(token) { return isKeyword(token) && !isContextualKeyword(token); } -function isFutureReservedKeyword(token) { - return 119 /* FirstFutureReservedWord */ <= token && token <= 127 /* LastFutureReservedWord */; -} function isStringANonContextualKeyword(name) { const token = stringToToken(name); return token !== void 0 && isNonContextualKeyword(token); } -function isStringAKeyword(name) { - const token = stringToToken(name); - return token !== void 0 && isKeyword(token); -} function isIdentifierANonContextualKeyword(node) { const originalKeywordKind = identifierToKeywordKind(node); return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind); @@ -19531,6 +19462,7 @@ function getPropertyNameForPropertyNameNode(name) { case 11 /* StringLiteral */: case 15 /* NoSubstitutionTemplateLiteral */: case 9 /* NumericLiteral */: + case 10 /* BigIntLiteral */: return escapeLeadingUnderscores(name.text); case 167 /* ComputedPropertyName */: const nameExpression = name.expression; @@ -19566,9 +19498,6 @@ function getTextOfIdentifierOrLiteral(node) { function getEscapedTextOfIdentifierOrLiteral(node) { return isMemberName(node) ? node.escapedText : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text); } -function getPropertyNameForUniqueESSymbol(symbol) { - return `__@${getSymbolId(symbol)}@${symbol.escapedName}`; -} function getSymbolNameForPrivateIdentifier(containingClassSymbol, description3) { return `__#${getSymbolId(containingClassSymbol)}@${description3}`; } @@ -19578,9 +19507,6 @@ function isKnownSymbol(symbol) { function isPrivateIdentifierSymbol(symbol) { return startsWith(symbol.escapedName, "__#"); } -function isESSymbolIdentifier(node) { - return node.kind === 80 /* Identifier */ && node.escapedText === "Symbol"; -} function isProtoSetter(node) { return isIdentifier(node) ? idText(node) === "__proto__" : isStringLiteral(node) && node.text === "__proto__"; } @@ -19670,9 +19596,6 @@ function nodeStartsNewLexicalEnvironment(node) { function nodeIsSynthesized(range) { return positionIsSynthesized(range.pos) || positionIsSynthesized(range.end); } -function getOriginalSourceFile(sourceFile) { - return getParseTreeNode(sourceFile, isSourceFile) || sourceFile; -} var Associativity = /* @__PURE__ */ ((Associativity2) => { Associativity2[Associativity2["Left"] = 0] = "Left"; Associativity2[Associativity2["Right"] = 1] = "Right"; @@ -19975,9 +19898,9 @@ function containsInvalidEscapeFlag(node) { function hasInvalidEscape(template) { return template && !!(isNoSubstitutionTemplateLiteral(template) ? containsInvalidEscapeFlag(template) : containsInvalidEscapeFlag(template.head) || some(template.templateSpans, (span) => containsInvalidEscapeFlag(span.literal))); } -var doubleQuoteEscapedCharsRegExp = /[\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; -var singleQuoteEscapedCharsRegExp = /[\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; -var backtickQuoteEscapedCharsRegExp = /\r\n|[\\`\u0000-\u001f\t\v\f\b\r\u2028\u2029\u0085]/g; +var doubleQuoteEscapedCharsRegExp = /[\\"\u0000-\u001f\u2028\u2029\u0085]/g; +var singleQuoteEscapedCharsRegExp = /[\\'\u0000-\u001f\u2028\u2029\u0085]/g; +var backtickQuoteEscapedCharsRegExp = /\r\n|[\\`\u0000-\u001f\u2028\u2029\u0085]/g; var escapedCharsMap = new Map(Object.entries({ " ": "\\t", "\v": "\\v", @@ -20280,11 +20203,11 @@ function getOwnEmitOutputFilePath(fileName, host, extension) { return emitOutputFilePathWithoutExtension + extension; } function getDeclarationEmitOutputFilePath(fileName, host) { - return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host.getCurrentDirectory(), host.getCommonSourceDirectory(), (f) => host.getCanonicalFileName(f)); + return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host); } -function getDeclarationEmitOutputFilePathWorker(fileName, options, currentDirectory, commonSourceDirectory, getCanonicalFileName) { +function getDeclarationEmitOutputFilePathWorker(fileName, options, host) { const outputDir = options.declarationDir || options.outDir; - const path = outputDir ? getSourceFilePathInNewDirWorker(fileName, outputDir, currentDirectory, commonSourceDirectory, getCanonicalFileName) : fileName; + const path = outputDir ? getSourceFilePathInNewDirWorker(fileName, outputDir, host.getCurrentDirectory(), host.getCommonSourceDirectory(), (f) => host.getCanonicalFileName(f)) : fileName; const declarationExtension = getDeclarationEmitExtensionForPath(path); return removeFileExtension(path) + declarationExtension; } @@ -20832,9 +20755,6 @@ function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node) { function isAssignmentExpression(node, excludeCompoundAssignment) { return isBinaryExpression(node) && (excludeCompoundAssignment ? node.operatorToken.kind === 64 /* EqualsToken */ : isAssignmentOperator(node.operatorToken.kind)) && isLeftHandSideExpression(node.left); } -function isLeftHandSideOfAssignment(node) { - return isAssignmentExpression(node.parent) && node.parent.left === node; -} function isDestructuringAssignment(node) { if (isAssignmentExpression( node, @@ -21088,9 +21008,6 @@ function moveRangePastModifiers(node) { const lastModifier = canHaveModifiers(node) ? lastOrUndefined(node.modifiers) : void 0; return lastModifier && !positionIsSynthesized(lastModifier.end) ? moveRangePos(node, lastModifier.end) : moveRangePastDecorators(node); } -function isCollapsedRange(range) { - return range.pos === range.end; -} function createTokenRange(pos, token) { return createRange(pos, pos + tokenToString(token).length); } @@ -21332,9 +21249,6 @@ function getClassLikeDeclarationOfSymbol(symbol) { function getObjectFlags(type) { return type.flags & 3899393 /* ObjectFlagsType */ ? type.objectFlags : 0; } -function forSomeAncestorDirectory(directory, callback) { - return !!forEachAncestorDirectory(directory, (d) => callback(d) ? true : void 0); -} function isUMDExportSymbol(symbol) { return !!symbol && !!symbol.declarations && !!symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]); } @@ -21534,7 +21448,7 @@ function setObjectAllocator(alloc) { forEach(objectAllocatorPatchers, (fn) => fn(objectAllocator)); } function formatStringFromArgs(text, args) { - return text.replace(/{(\d+)}/g, (_match, index) => "" + Debug.checkDefined(args[+index])); + return text.replace(/\{(\d+)\}/g, (_match, index) => "" + Debug.checkDefined(args[+index])); } var localizedDiagnosticMessages; function setLocalizedDiagnosticMessages(messages) { @@ -21808,8 +21722,8 @@ function walkTreeForJSXTags(node) { function isFileModuleFromUsingJSXTag(file) { return !file.isDeclarationFile ? walkTreeForJSXTags(file) : void 0; } -function isFileForcedToBeModuleByFormat(file) { - return (file.impliedNodeFormat === 99 /* ESNext */ || fileExtensionIsOneOf(file.fileName, [".cjs" /* Cjs */, ".cts" /* Cts */, ".mjs" /* Mjs */, ".mts" /* Mts */])) && !file.isDeclarationFile ? true : void 0; +function isFileForcedToBeModuleByFormat(file, options) { + return (getImpliedNodeFormatForEmitWorker(file, options) === 99 /* ESNext */ || fileExtensionIsOneOf(file.fileName, [".cjs" /* Cjs */, ".cts" /* Cts */, ".mjs" /* Mjs */, ".mts" /* Mts */])) && !file.isDeclarationFile ? true : void 0; } function getSetExternalModuleIndicator(options) { switch (getEmitModuleDetectionKind(options)) { @@ -21828,10 +21742,14 @@ function getSetExternalModuleIndicator(options) { } checks.push(isFileForcedToBeModuleByFormat); const combined = or(...checks); - const callback = (file) => void (file.externalModuleIndicator = combined(file)); + const callback = (file) => void (file.externalModuleIndicator = combined(file, options)); return callback; } } +function importSyntaxAffectsModuleResolution(options) { + const moduleResolution = getEmitModuleResolutionKind(options); + return 3 /* Node16 */ <= moduleResolution && moduleResolution <= 99 /* NodeNext */ || getResolvePackageJsonExports(options) || getResolvePackageJsonImports(options); +} function createComputedCompilerOptions(options) { return options; } @@ -22030,6 +21948,12 @@ var computedOptions = createComputedCompilerOptions({ return getStrictOptionValue(compilerOptions, "strictPropertyInitialization"); } }, + strictBuiltinIteratorReturn: { + dependencies: ["strict"], + computeValue: (compilerOptions) => { + return getStrictOptionValue(compilerOptions, "strictBuiltinIteratorReturn"); + } + }, alwaysStrict: { dependencies: ["strict"], computeValue: (compilerOptions) => { @@ -22108,7 +22032,12 @@ function getJSXTransformEnabled(options) { function getJSXImplicitImportBase(compilerOptions, file) { const jsxImportSourcePragmas = file == null ? void 0 : file.pragmas.get("jsximportsource"); const jsxImportSourcePragma = isArray(jsxImportSourcePragmas) ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1] : jsxImportSourcePragmas; - return compilerOptions.jsx === 4 /* ReactJSX */ || compilerOptions.jsx === 5 /* ReactJSXDev */ || compilerOptions.jsxImportSource || jsxImportSourcePragma ? (jsxImportSourcePragma == null ? void 0 : jsxImportSourcePragma.arguments.factory) || compilerOptions.jsxImportSource || "react" : void 0; + const jsxRuntimePragmas = file == null ? void 0 : file.pragmas.get("jsxruntime"); + const jsxRuntimePragma = isArray(jsxRuntimePragmas) ? jsxRuntimePragmas[jsxRuntimePragmas.length - 1] : jsxRuntimePragmas; + if ((jsxRuntimePragma == null ? void 0 : jsxRuntimePragma.arguments.factory) === "classic") { + return void 0; + } + return compilerOptions.jsx === 4 /* ReactJSX */ || compilerOptions.jsx === 5 /* ReactJSXDev */ || compilerOptions.jsxImportSource || jsxImportSourcePragma || (jsxRuntimePragma == null ? void 0 : jsxRuntimePragma.arguments.factory) === "automatic" ? (jsxImportSourcePragma == null ? void 0 : jsxImportSourcePragma.arguments.factory) || compilerOptions.jsxImportSource || "react" : void 0; } function getJSXRuntimeImport(base, options) { return base ? `${base}/${options.jsx === 5 /* ReactJSXDev */ ? "jsx-dev-runtime" : "jsx-runtime"}` : void 0; @@ -22352,7 +22281,7 @@ function matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNa if (visited.has(canonicalPath)) return; visited.set(canonicalPath, true); const { files, directories } = getFileSystemEntries(path2); - for (const current of sort(files, compareStringsCaseSensitive)) { + for (const current of toSorted(files, compareStringsCaseSensitive)) { const name = combinePaths(path2, current); const absoluteName = combinePaths(absolutePath, current); if (extensions && !fileExtensionIsOneOf(name, extensions)) continue; @@ -22372,7 +22301,7 @@ function matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNa return; } } - for (const current of sort(directories, compareStringsCaseSensitive)) { + for (const current of toSorted(directories, compareStringsCaseSensitive)) { const name = combinePaths(path2, current); const absoluteName = combinePaths(absolutePath, current); if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) && (!excludeRegex || !excludeRegex.test(absoluteName))) { @@ -22468,6 +22397,9 @@ function hasJSFileExtension(fileName) { function hasTSFileExtension(fileName) { return some(supportedTSExtensionsFlat, (extension) => fileExtensionIs(fileName, extension)); } +function hasImplementationTSFileExtension(fileName) { + return some(supportedTSImplementationExtensions, (extension) => fileExtensionIs(fileName, extension)) && !isDeclarationFileName(fileName); +} var ModuleSpecifierEnding = /* @__PURE__ */ ((ModuleSpecifierEnding2) => { ModuleSpecifierEnding2[ModuleSpecifierEnding2["Minimal"] = 0] = "Minimal"; ModuleSpecifierEnding2[ModuleSpecifierEnding2["Index"] = 1] = "Index"; @@ -22675,9 +22607,27 @@ function rangeOfTypeParameters(sourceFile, typeParameters) { return { pos, end }; } function skipTypeChecking(sourceFile, options, host) { - return options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib || options.noCheck || host.isSourceOfProjectReferenceRedirect(sourceFile.fileName) || !canIncludeBindAndCheckDiagnsotics(sourceFile, options); + return skipTypeCheckingWorker( + sourceFile, + options, + host, + /*ignoreNoCheck*/ + false + ); } -function canIncludeBindAndCheckDiagnsotics(sourceFile, options) { +function skipTypeCheckingIgnoringNoCheck(sourceFile, options, host) { + return skipTypeCheckingWorker( + sourceFile, + options, + host, + /*ignoreNoCheck*/ + true + ); +} +function skipTypeCheckingWorker(sourceFile, options, host, ignoreNoCheck) { + return options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib || !ignoreNoCheck && options.noCheck || host.isSourceOfProjectReferenceRedirect(sourceFile.fileName) || !canIncludeBindAndCheckDiagnostics(sourceFile, options); +} +function canIncludeBindAndCheckDiagnostics(sourceFile, options) { if (!!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false) return false; if (sourceFile.scriptKind === 3 /* TS */ || sourceFile.scriptKind === 4 /* TSX */ || sourceFile.scriptKind === 5 /* External */) return true; const isJs = sourceFile.scriptKind === 1 /* JS */ || sourceFile.scriptKind === 2 /* JSX */; @@ -22851,14 +22801,6 @@ function setParent(child, parent2) { } return child; } -function setEachParent(children, parent2) { - if (children) { - for (const child of children) { - setParent(child, parent2); - } - } - return children; -} function setParentRecursive(rootNode, incremental) { if (!rootNode) return rootNode; forEachChildRecursively(rootNode, isJSDocNode(rootNode) ? bindParentToChildIgnoringJSDoc : bindParentToChild); @@ -23002,7 +22944,7 @@ function isFunctionExpressionOrArrowFunction(node) { return node.kind === 218 /* FunctionExpression */ || node.kind === 219 /* ArrowFunction */; } function escapeSnippetText(text) { - return text.replace(/\$/gm, () => "\\$"); + return text.replace(/\$/g, () => "\\$"); } function isNumericLiteralName(name) { return (+name).toString() === name; @@ -23061,10 +23003,6 @@ function getNodeModulePathParts(fullPath) { fileNameIndex = partStart; return state > 1 /* NodeModules */ ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : void 0; } -function getParameterTypeNode(parameter) { - var _a; - return parameter.kind === 341 /* JSDocParameterTag */ ? (_a = parameter.typeExpression) == null ? void 0 : _a.type : parameter.type; -} function isTypeDeclaration(node) { switch (node.kind) { case 168 /* TypeParameter */: @@ -23185,6 +23123,105 @@ function replaceFirstStar(s, replacement) { function getNameFromImportAttribute(node) { return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text); } +function isSourceElement(node) { + switch (node.kind) { + case 168 /* TypeParameter */: + case 169 /* Parameter */: + case 172 /* PropertyDeclaration */: + case 171 /* PropertySignature */: + case 185 /* ConstructorType */: + case 184 /* FunctionType */: + case 179 /* CallSignature */: + case 180 /* ConstructSignature */: + case 181 /* IndexSignature */: + case 174 /* MethodDeclaration */: + case 173 /* MethodSignature */: + case 175 /* ClassStaticBlockDeclaration */: + case 176 /* Constructor */: + case 177 /* GetAccessor */: + case 178 /* SetAccessor */: + case 183 /* TypeReference */: + case 182 /* TypePredicate */: + case 186 /* TypeQuery */: + case 187 /* TypeLiteral */: + case 188 /* ArrayType */: + case 189 /* TupleType */: + case 192 /* UnionType */: + case 193 /* IntersectionType */: + case 196 /* ParenthesizedType */: + case 190 /* OptionalType */: + case 191 /* RestType */: + case 197 /* ThisType */: + case 198 /* TypeOperator */: + case 194 /* ConditionalType */: + case 195 /* InferType */: + case 203 /* TemplateLiteralType */: + case 205 /* ImportType */: + case 202 /* NamedTupleMember */: + case 328 /* JSDocAugmentsTag */: + case 329 /* JSDocImplementsTag */: + case 346 /* JSDocTypedefTag */: + case 338 /* JSDocCallbackTag */: + case 340 /* JSDocEnumTag */: + case 345 /* JSDocTemplateTag */: + case 344 /* JSDocTypeTag */: + case 324 /* JSDocLink */: + case 325 /* JSDocLinkCode */: + case 326 /* JSDocLinkPlain */: + case 341 /* JSDocParameterTag */: + case 348 /* JSDocPropertyTag */: + case 317 /* JSDocFunctionType */: + case 315 /* JSDocNonNullableType */: + case 314 /* JSDocNullableType */: + case 312 /* JSDocAllType */: + case 313 /* JSDocUnknownType */: + case 322 /* JSDocTypeLiteral */: + case 318 /* JSDocVariadicType */: + case 309 /* JSDocTypeExpression */: + case 333 /* JSDocPublicTag */: + case 335 /* JSDocProtectedTag */: + case 334 /* JSDocPrivateTag */: + case 350 /* JSDocSatisfiesTag */: + case 343 /* JSDocThisTag */: + case 199 /* IndexedAccessType */: + case 200 /* MappedType */: + case 262 /* FunctionDeclaration */: + case 241 /* Block */: + case 268 /* ModuleBlock */: + case 243 /* VariableStatement */: + case 244 /* ExpressionStatement */: + case 245 /* IfStatement */: + case 246 /* DoStatement */: + case 247 /* WhileStatement */: + case 248 /* ForStatement */: + case 249 /* ForInStatement */: + case 250 /* ForOfStatement */: + case 251 /* ContinueStatement */: + case 252 /* BreakStatement */: + case 253 /* ReturnStatement */: + case 254 /* WithStatement */: + case 255 /* SwitchStatement */: + case 256 /* LabeledStatement */: + case 257 /* ThrowStatement */: + case 258 /* TryStatement */: + case 260 /* VariableDeclaration */: + case 208 /* BindingElement */: + case 263 /* ClassDeclaration */: + case 264 /* InterfaceDeclaration */: + case 265 /* TypeAliasDeclaration */: + case 266 /* EnumDeclaration */: + case 267 /* ModuleDeclaration */: + case 272 /* ImportDeclaration */: + case 271 /* ImportEqualsDeclaration */: + case 278 /* ExportDeclaration */: + case 277 /* ExportAssignment */: + case 242 /* EmptyStatement */: + case 259 /* DebuggerStatement */: + case 282 /* MissingDeclaration */: + return true; + } + return false; +} function evaluatorResult(value, isSyntacticallyString = false, resolvedOtherFiles = false, hasExternalReferences = false) { return { value, isSyntacticallyString, resolvedOtherFiles, hasExternalReferences }; } @@ -23743,6 +23780,10 @@ function hasInferredType(node) { return false; } } +function isSideEffectImport(node) { + const ancestor = findAncestor(node, isImportDeclaration); + return !!ancestor && !ancestor.importClause; +} // src/compiler/factory/baseNodeFactory.ts function createBaseNodeFactory() { @@ -25519,7 +25560,11 @@ function createNodeFactory(flags, baseFactory2) { node.modifiers = asNodeArray(modifiers); node.parameters = createNodeArray(parameters); node.body = body; - node.transformFlags = propagateChildrenFlags(node.modifiers) | propagateChildrenFlags(node.parameters) | propagateChildFlags(node.body) & ~67108864 /* ContainsPossibleTopLevelAwait */ | 1024 /* ContainsES2015 */; + if (!node.body) { + node.transformFlags = 1 /* ContainsTypeScript */; + } else { + node.transformFlags = propagateChildrenFlags(node.modifiers) | propagateChildrenFlags(node.parameters) | propagateChildFlags(node.body) & ~67108864 /* ContainsPossibleTopLevelAwait */ | 1024 /* ContainsES2015 */; + } node.typeParameters = void 0; node.type = void 0; node.typeArguments = void 0; @@ -27859,7 +27904,7 @@ function createNodeFactory(flags, baseFactory2) { } function createSyntaxList3(children) { const node = createBaseNode(352 /* SyntaxList */); - setNodeChildren(node, children); + node._children = children; return node; } function createNotEmittedStatement(original) { @@ -28145,6 +28190,8 @@ function createNodeFactory(flags, baseFactory2) { return updateSatisfiesExpression(outerExpression, expression, outerExpression.type); case 235 /* NonNullExpression */: return updateNonNullExpression(outerExpression, expression); + case 233 /* ExpressionWithTypeArguments */: + return updateExpressionWithTypeArguments(outerExpression, expression, outerExpression.typeArguments); case 354 /* PartiallyEmittedExpression */: return updatePartiallyEmittedExpression(outerExpression, expression); } @@ -28152,7 +28199,7 @@ function createNodeFactory(flags, baseFactory2) { function isIgnorableParen(node) { return isParenthesizedExpression(node) && nodeIsSynthesized(node) && nodeIsSynthesized(getSourceMapRange(node)) && nodeIsSynthesized(getCommentRange(node)) && !some(getSyntheticLeadingComments(node)) && !some(getSyntheticTrailingComments(node)); } - function restoreOuterExpressions(outerExpression, innerExpression, kinds = 15 /* All */) { + function restoreOuterExpressions(outerExpression, innerExpression, kinds = 31 /* All */) { if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression( outerExpression, @@ -28198,7 +28245,7 @@ function createNodeFactory(flags, baseFactory2) { } } function createCallBinding(expression, recordTempVariable, languageVersion, cacheIdentifiers = false) { - const callee = skipOuterExpressions(expression, 15 /* All */); + const callee = skipOuterExpressions(expression, 31 /* All */); let thisArg; let target; if (isSuperProperty(callee)) { @@ -29686,7 +29733,7 @@ var asyncGeneratorHelper = { var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } @@ -29868,8 +29915,8 @@ var generatorHelper = { priority: 6, text: ` var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); @@ -30032,17 +30079,22 @@ var disposeResourcesHelper = { env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; env.hasError = true; } + var r, s = 0; function next() { - while (env.stack.length) { - var rec = env.stack.pop(); + while (r = env.stack.pop()) { try { - var result = rec.dispose && rec.dispose.call(rec.value); - if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; } catch (e) { fail(e); } } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); if (env.hasError) throw env.error; } return next(); @@ -30543,6 +30595,9 @@ function isNamedExports(node) { function isExportSpecifier(node) { return node.kind === 281 /* ExportSpecifier */; } +function isModuleExportName(node) { + return node.kind === 80 /* Identifier */ || node.kind === 11 /* StringLiteral */; +} function isMissingDeclaration(node) { return node.kind === 282 /* MissingDeclaration */; } @@ -30752,17 +30807,43 @@ function isSyntaxList(n) { } // src/compiler/factory/nodeChildren.ts -var nodeChildren = /* @__PURE__ */ new WeakMap(); -function getNodeChildren(node) { - if (!isNodeKind(node.kind)) return emptyArray; - return nodeChildren.get(node); +var sourceFileToNodeChildren = /* @__PURE__ */ new WeakMap(); +function getNodeChildren(node, sourceFile) { + var _a; + const kind = node.kind; + if (!isNodeKind(kind)) { + return emptyArray; + } + if (kind === 352 /* SyntaxList */) { + return node._children; + } + return (_a = sourceFileToNodeChildren.get(sourceFile)) == null ? void 0 : _a.get(node); } -function setNodeChildren(node, children) { - nodeChildren.set(node, children); +function setNodeChildren(node, sourceFile, children) { + if (node.kind === 352 /* SyntaxList */) { + Debug.fail("Should not need to re-set the children of a SyntaxList."); + } + let map2 = sourceFileToNodeChildren.get(sourceFile); + if (map2 === void 0) { + map2 = /* @__PURE__ */ new WeakMap(); + sourceFileToNodeChildren.set(sourceFile, map2); + } + map2.set(node, children); return children; } -function unsetNodeChildren(node) { - nodeChildren.delete(node); +function unsetNodeChildren(node, origSourceFile) { + var _a; + if (node.kind === 352 /* SyntaxList */) { + Debug.fail("Did not expect to unset the children of a SyntaxList."); + } + (_a = sourceFileToNodeChildren.get(origSourceFile)) == null ? void 0 : _a.delete(node); +} +function transferSourceFileChildren(sourceFile, targetSourceFile) { + const map2 = sourceFileToNodeChildren.get(sourceFile); + if (map2 !== void 0) { + sourceFileToNodeChildren.delete(sourceFile); + sourceFileToNodeChildren.set(targetSourceFile, map2); + } } // src/compiler/factory/utilities.ts @@ -30901,17 +30982,6 @@ function createForOfBindingStatement(factory2, node, boundValue) { ); } } -function insertLeadingStatement(factory2, dest, source) { - if (isBlock(dest)) { - return factory2.updateBlock(dest, setTextRange(factory2.createNodeArray([source, ...dest.statements]), dest.statements)); - } else { - return factory2.createBlock( - factory2.createNodeArray([dest, source]), - /*multiLine*/ - true - ); - } -} function createExpressionFromEntityName(factory2, node) { if (isQualifiedName(node)) { const left = createExpressionFromEntityName(factory2, node.left); @@ -31143,18 +31213,19 @@ function getJSDocTypeAssertionType(node) { Debug.assertIsDefined(type); return type; } -function isOuterExpression(node, kinds = 15 /* All */) { +function isOuterExpression(node, kinds = 31 /* All */) { switch (node.kind) { case 217 /* ParenthesizedExpression */: - if (kinds & 16 /* ExcludeJSDocTypeAssertion */ && isJSDocTypeAssertion(node)) { + if (kinds & -2147483648 /* ExcludeJSDocTypeAssertion */ && isJSDocTypeAssertion(node)) { return false; } return (kinds & 1 /* Parentheses */) !== 0; case 216 /* TypeAssertionExpression */: case 234 /* AsExpression */: - case 233 /* ExpressionWithTypeArguments */: case 238 /* SatisfiesExpression */: return (kinds & 2 /* TypeAssertions */) !== 0; + case 233 /* ExpressionWithTypeArguments */: + return (kinds & 16 /* ExpressionsWithTypeArguments */) !== 0; case 235 /* NonNullExpression */: return (kinds & 4 /* NonNullAssertions */) !== 0; case 354 /* PartiallyEmittedExpression */: @@ -31162,13 +31233,13 @@ function isOuterExpression(node, kinds = 15 /* All */) { } return false; } -function skipOuterExpressions(node, kinds = 15 /* All */) { +function skipOuterExpressions(node, kinds = 31 /* All */) { while (isOuterExpression(node, kinds)) { node = node.expression; } return node; } -function walkUpOuterExpressions(node, kinds = 15 /* All */) { +function walkUpOuterExpressions(node, kinds = 31 /* All */) { let parent2 = node.parent; while (isOuterExpression(parent2, kinds)) { parent2 = parent2.parent; @@ -31176,9 +31247,6 @@ function walkUpOuterExpressions(node, kinds = 15 /* All */) { } return parent2; } -function skipAssertions(node) { - return skipOuterExpressions(node, 6 /* Assertions */); -} function startOnNewLine(node) { return setStartsOnNewLine( node, @@ -31200,7 +31268,7 @@ function createExternalHelpersImportDeclarationIfNeeded(nodeFactory, helperFacto if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { let namedBindings; const moduleKind = getEmitModuleKind(compilerOptions); - if (moduleKind >= 5 /* ES2015 */ && moduleKind <= 99 /* ESNext */ || sourceFile.impliedNodeFormat === 99 /* ESNext */) { + if (moduleKind >= 5 /* ES2015 */ && moduleKind <= 99 /* ESNext */ || getImpliedNodeFormatForEmitWorker(sourceFile, compilerOptions) === 99 /* ESNext */) { const helpers = getEmitHelpers(sourceFile); if (helpers) { const helperNames = []; @@ -31265,8 +31333,7 @@ function getOrCreateExternalHelpersModuleNameIfNeeded(factory2, node, compilerOp if (externalHelpersModuleName) { return externalHelpersModuleName; } - const moduleKind = getEmitModuleKind(compilerOptions); - let create = (hasExportStarsToExportValues || getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault) && moduleKind !== 4 /* System */ && (moduleKind < 5 /* ES2015 */ || node.impliedNodeFormat === 1 /* CommonJS */); + let create = (hasExportStarsToExportValues || getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault) && getEmitModuleFormatOfFileWorker(node, compilerOptions) < 4 /* System */; if (!create) { const helpers = getEmitHelpers(node); if (helpers) { @@ -31289,6 +31356,9 @@ function getLocalNameForExternalImport(factory2, node, sourceFile) { const namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node) && !isExportNamespaceAsDefaultDeclaration(node)) { const name = namespaceDeclaration.name; + if (name.kind === 11 /* StringLiteral */) { + return factory2.getGeneratedNameForNode(node); + } return isGeneratedIdentifier(name) ? name : factory2.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); } if (node.kind === 272 /* ImportDeclaration */ && node.importClause) { @@ -31481,10 +31551,6 @@ function isQuestionOrPlusOrMinusToken(node) { function isModuleName(node) { return isIdentifier(node) || isStringLiteral(node); } -function isLiteralTypeLikeExpression(node) { - const kind = node.kind; - return kind === 106 /* NullKeyword */ || kind === 112 /* TrueKeyword */ || kind === 97 /* FalseKeyword */ || isLiteralExpression(node) || isPrefixUnaryExpression(node); -} function isExponentiationOperator(kind) { return kind === 43 /* AsteriskAsteriskToken */; } @@ -31670,10 +31736,6 @@ function isExportOrDefaultModifier(node) { const kind = node.kind; return isExportOrDefaultKeywordKind(kind); } -function isNonExportDefaultModifier(node) { - const kind = node.kind; - return isModifierKind(kind) && !isExportOrDefaultKeywordKind(kind); -} function elideNodes(factory2, nodes) { if (nodes === void 0) return void 0; if (nodes.length === 0) return nodes; @@ -32449,7 +32511,7 @@ function setExternalModuleIndicator(sourceFile) { sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile); } function createSourceFile(fileName, sourceText, languageVersionOrOptions, setParentNodes = false, scriptKind) { - var _a, _b, _c, _d; + var _a, _b; (_a = tracing) == null ? void 0 : _a.push( tracing.Phase.Parse, "createSourceFile", @@ -32459,7 +32521,6 @@ function createSourceFile(fileName, sourceText, languageVersionOrOptions, setPar ); mark("beforeParse"); let result; - (_b = perfLogger) == null ? void 0 : _b.logStartParseSourceFile(fileName); const { languageVersion, setExternalModuleIndicator: overrideSetExternalModuleIndicator, @@ -32495,10 +32556,9 @@ function createSourceFile(fileName, sourceText, languageVersionOrOptions, setPar jsDocParsingMode ); } - (_c = perfLogger) == null ? void 0 : _c.logStopParseSourceFile(); mark("afterParse"); measure("Parse", "beforeParse", "afterParse"); - (_d = tracing) == null ? void 0 : _d.pop(); + (_b = tracing) == null ? void 0 : _b.pop(); return result; } function parseIsolatedEntityName(text, languageVersion) { @@ -33438,7 +33498,7 @@ var Parser; function createIdentifier(isIdentifier3, diagnosticMessage, privateIdentifierDiagnosticMessage) { if (isIdentifier3) { identifierCount++; - const pos = getNodePos(); + const pos = scanner2.hasPrecedingJSDocLeadingAsterisks() ? scanner2.getTokenStart() : getNodePos(); const originalKeywordKind = token(); const text = internIdentifier(scanner2.getTokenValue()); const hasExtendedUnicodeEscape = scanner2.hasExtendedUnicodeEscape(); @@ -33486,13 +33546,13 @@ var Parser; return createIdentifier(tokenIsIdentifierOrKeyword(token())); } function isLiteralPropertyName() { - return tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */; + return tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */ || token() === 10 /* BigIntLiteral */; } function isImportAttributeName2() { return tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */; } function parsePropertyNameWorker(allowComputedPropertyNames) { - if (token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */) { + if (token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */ || token() === 10 /* BigIntLiteral */) { const node = parseLiteralNode(); node.text = internIdentifier(node.text); return node; @@ -33651,6 +33711,9 @@ var Parser; if (token() === 161 /* FromKeyword */ && lookAhead(nextTokenIsStringLiteral)) { return false; } + if (token() === 11 /* StringLiteral */) { + return true; + } return tokenIsIdentifierOrKeyword(token()); case 13 /* JsxAttributes */: return tokenIsIdentifierOrKeyword(token()) || token() === 19 /* OpenBraceToken */; @@ -37716,7 +37779,7 @@ var Parser; if (isIndexSignature()) { return parseIndexSignatureDeclaration(pos, hasJSDoc, modifiers); } - if (tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */ || token() === 42 /* AsteriskToken */ || token() === 23 /* OpenBracketToken */) { + if (tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */ || token() === 9 /* NumericLiteral */ || token() === 10 /* BigIntLiteral */ || token() === 42 /* AsteriskToken */ || token() === 23 /* OpenBracketToken */) { const isAmbient = some(modifiers, isDeclareModifier); if (isAmbient) { for (const m of modifiers) { @@ -38099,6 +38162,12 @@ var Parser; const name = parseIdentifier(); return finishNode(factory2.createNamespaceImport(name), pos); } + function canParseModuleExportName() { + return tokenIsIdentifierOrKeyword(token()) || token() === 11 /* StringLiteral */; + } + function parseModuleExportName(parseName) { + return token() === 11 /* StringLiteral */ ? parseLiteralNode() : parseName(); + } function parseNamedImportsOrExports(kind) { const pos = getNodePos(); const node = kind === 275 /* NamedImports */ ? factory2.createNamedImports(parseBracketedList(23 /* ImportOrExportSpecifiers */, parseImportSpecifier, 19 /* OpenBraceToken */, 20 /* CloseBraceToken */)) : factory2.createNamedExports(parseBracketedList(23 /* ImportOrExportSpecifiers */, parseExportSpecifier, 19 /* OpenBraceToken */, 20 /* CloseBraceToken */)); @@ -38119,42 +38188,51 @@ var Parser; let isTypeOnly = false; let propertyName; let canParseAsKeyword = true; - let name = parseIdentifierName(); - if (name.escapedText === "type") { + let name = parseModuleExportName(parseIdentifierName); + if (name.kind === 80 /* Identifier */ && name.escapedText === "type") { if (token() === 130 /* AsKeyword */) { const firstAs = parseIdentifierName(); if (token() === 130 /* AsKeyword */) { const secondAs = parseIdentifierName(); - if (tokenIsIdentifierOrKeyword(token())) { + if (canParseModuleExportName()) { isTypeOnly = true; propertyName = firstAs; - name = parseNameWithKeywordCheck(); + name = parseModuleExportName(parseNameWithKeywordCheck); canParseAsKeyword = false; } else { propertyName = name; name = secondAs; canParseAsKeyword = false; } - } else if (tokenIsIdentifierOrKeyword(token())) { + } else if (canParseModuleExportName()) { propertyName = name; canParseAsKeyword = false; - name = parseNameWithKeywordCheck(); + name = parseModuleExportName(parseNameWithKeywordCheck); } else { isTypeOnly = true; name = firstAs; } - } else if (tokenIsIdentifierOrKeyword(token())) { + } else if (canParseModuleExportName()) { isTypeOnly = true; - name = parseNameWithKeywordCheck(); + name = parseModuleExportName(parseNameWithKeywordCheck); } } if (canParseAsKeyword && token() === 130 /* AsKeyword */) { propertyName = name; parseExpected(130 /* AsKeyword */); - name = parseNameWithKeywordCheck(); + name = parseModuleExportName(parseNameWithKeywordCheck); } - if (kind === 276 /* ImportSpecifier */ && checkIdentifierIsKeyword) { - parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected); + if (kind === 276 /* ImportSpecifier */) { + if (name.kind !== 80 /* Identifier */) { + parseErrorAt(skipTrivia(sourceText, name.pos), name.end, Diagnostics.Identifier_expected); + name = setTextRangePosEnd(createMissingNode( + 80 /* Identifier */, + /*reportAtCurrentPosition*/ + false + ), name.pos, name.pos); + } else if (checkIdentifierIsKeyword) { + parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected); + } } const node = kind === 276 /* ImportSpecifier */ ? factory2.createImportSpecifier(isTypeOnly, propertyName, name) : factory2.createExportSpecifier(isTypeOnly, propertyName, name); return finishNode(node, pos); @@ -38166,7 +38244,7 @@ var Parser; } } function parseNamespaceExport(pos) { - return finishNode(factory2.createNamespaceExport(parseIdentifierName()), pos); + return finishNode(factory2.createNamespaceExport(parseModuleExportName(parseIdentifierName)), pos); } function parseExportDeclaration(pos, hasJSDoc, modifiers) { const savedAwaitContext = inAwaitContext(); @@ -39374,6 +39452,7 @@ var IncrementalParser; aggressiveChecks ); result.impliedNodeFormat = sourceFile.impliedNodeFormat; + transferSourceFileChildren(sourceFile, result); return result; } IncrementalParser2.updateSourceFile = updateSourceFile2; @@ -39409,7 +39488,7 @@ var IncrementalParser; } } } - function moveElementEntirelyPastChangeRange(element, isArray2, delta, oldText, newText, aggressiveChecks) { + function moveElementEntirelyPastChangeRange(element, origSourceFile, isArray2, delta, oldText, newText, aggressiveChecks) { if (isArray2) { visitArray2(element); } else { @@ -39421,7 +39500,7 @@ var IncrementalParser; if (aggressiveChecks && shouldCheckNode(node)) { text = oldText.substring(node.pos, node.end); } - unsetNodeChildren(node); + unsetNodeChildren(node, origSourceFile); setTextRangePosEnd(node, node.pos + delta, node.end + delta); if (aggressiveChecks && shouldCheckNode(node)) { Debug.assert(text === newText.substring(node.pos, node.end)); @@ -39495,6 +39574,7 @@ var IncrementalParser; if (child.pos > changeRangeOldEnd) { moveElementEntirelyPastChangeRange( child, + sourceFile, /*isArray*/ false, delta, @@ -39507,7 +39587,7 @@ var IncrementalParser; const fullEnd = child.end; if (fullEnd >= changeStart) { markAsIntersectingIncrementalChange(child); - unsetNodeChildren(child); + unsetNodeChildren(child, sourceFile); adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); forEachChild(child, visitNode3, visitArray2); if (hasJSDocNodes(child)) { @@ -39525,6 +39605,7 @@ var IncrementalParser; if (array.pos > changeRangeOldEnd) { moveElementEntirelyPastChangeRange( array, + sourceFile, /*isArray*/ true, delta, @@ -39816,8 +39897,8 @@ function getNamedArgRegEx(name) { namedArgRegExCache.set(name, result); return result; } -var tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im; -var singleLinePragmaRegEx = /^\/\/\/?\s*@([^\s:]+)(.*)\s*$/im; +var tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/m; +var singleLinePragmaRegEx = /^\/\/\/?\s*@([^\s:]+)((?:[^\S\r\n]|:).*)?$/m; function extractPragmas(pragmas, range, text) { const tripleSlash = range.kind === 2 /* SingleLineCommentTrivia */ && tripleSlashXMLCommentStartRegEx.exec(text); if (tripleSlash) { @@ -39858,7 +39939,7 @@ function extractPragmas(pragmas, range, text) { return addPragmaForMatch(pragmas, range, 2 /* SingleLine */, singleLine); } if (range.kind === 3 /* MultiLineCommentTrivia */) { - const multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim; + const multiLinePragmaRegEx = /@(\S+)(\s+(?:\S.*)?)?$/gm; let multiLineMatch; while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { addPragmaForMatch(pragmas, range, 4 /* MultiLine */, multiLineMatch); @@ -40015,6 +40096,7 @@ var libEntries = [ ["esnext.array", "lib.esnext.array.d.ts"], ["esnext.regexp", "lib.esnext.regexp.d.ts"], ["esnext.string", "lib.esnext.string.d.ts"], + ["esnext.iterator", "lib.esnext.iterator.d.ts"], ["decorators", "lib.decorators.d.ts"], ["decorators.legacy", "lib.decorators.legacy.d.ts"] ]; @@ -40193,7 +40275,6 @@ var commonOptionsWithBuild = [ name: "generateTrace", type: "string", isFilePath: true, - isCommandLineOnly: true, paramType: Diagnostics.DIRECTORY, category: Diagnostics.Compiler_Diagnostics, description: Diagnostics.Generates_an_event_trace_and_a_list_of_types @@ -40226,7 +40307,6 @@ var commonOptionsWithBuild = [ affectsBuildInfo: true, showInSimplifiedHelpView: true, category: Diagnostics.Emit, - transpileOptionValue: void 0, defaultValueDescription: false, description: Diagnostics.Create_sourcemaps_for_d_ts_files }, @@ -40260,6 +40340,25 @@ var commonOptionsWithBuild = [ description: Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript, defaultValueDescription: false }, + { + name: "noCheck", + type: "boolean", + showInSimplifiedHelpView: false, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Disable_full_type_checking_only_critical_parse_and_emit_errors_will_be_reported, + transpileOptionValue: true, + defaultValueDescription: false + // Not setting affectsSemanticDiagnostics or affectsBuildInfo because we dont want all diagnostics to go away, its handled in builder + }, + { + name: "noEmit", + type: "boolean", + showInSimplifiedHelpView: true, + category: Diagnostics.Emit, + description: Diagnostics.Disable_emitting_files_from_a_compilation, + transpileOptionValue: void 0, + defaultValueDescription: false + }, { name: "assumeChangesOnlyAffectDirectDependencies", type: "boolean", @@ -40524,34 +40623,12 @@ var commandOptionsWithoutBuild = [ defaultValueDescription: false, description: Diagnostics.Disable_emitting_comments }, - { - name: "noCheck", - type: "boolean", - showInSimplifiedHelpView: false, - category: Diagnostics.Compiler_Diagnostics, - description: Diagnostics.Disable_full_type_checking_only_critical_parse_and_emit_errors_will_be_reported, - transpileOptionValue: true, - defaultValueDescription: false, - affectsSemanticDiagnostics: true, - affectsBuildInfo: true, - extraValidation() { - return [Diagnostics.Unknown_compiler_option_0, "noCheck"]; - } - }, - { - name: "noEmit", - type: "boolean", - showInSimplifiedHelpView: true, - category: Diagnostics.Emit, - description: Diagnostics.Disable_emitting_files_from_a_compilation, - transpileOptionValue: void 0, - defaultValueDescription: false - }, { name: "importHelpers", type: "boolean", affectsEmit: true, affectsBuildInfo: true, + affectsSourceFile: true, category: Diagnostics.Emit, description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file, defaultValueDescription: false @@ -40670,6 +40747,16 @@ var commandOptionsWithoutBuild = [ description: Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor, defaultValueDescription: Diagnostics.false_unless_strict_is_set }, + { + name: "strictBuiltinIteratorReturn", + type: "boolean", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + strictFlag: true, + category: Diagnostics.Type_Checking, + description: Diagnostics.Built_in_iterators_are_instantiated_with_a_TReturn_type_of_undefined_instead_of_any, + defaultValueDescription: Diagnostics.false_unless_strict_is_set + }, { name: "noImplicitThis", type: "boolean", @@ -40945,6 +41032,15 @@ var commandOptionsWithoutBuild = [ category: Diagnostics.Modules, description: Diagnostics.Conditions_to_set_in_addition_to_the_resolver_specific_defaults_when_resolving_imports }, + { + name: "noUncheckedSideEffectImports", + type: "boolean", + affectsSemanticDiagnostics: true, + affectsBuildInfo: true, + category: Diagnostics.Modules, + description: Diagnostics.Check_side_effect_imports, + defaultValueDescription: false + }, // Source Maps { name: "sourceRoot", @@ -41016,6 +41112,7 @@ var commandOptionsWithoutBuild = [ affectsEmit: true, affectsBuildInfo: true, affectsModuleResolution: true, + affectsSourceFile: true, category: Diagnostics.Language_and_Environment, description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk, defaultValueDescription: "react" @@ -41399,6 +41496,13 @@ var optionsForBuild = [ description: Diagnostics.Delete_the_outputs_of_all_projects, type: "boolean", defaultValueDescription: false + }, + { + name: "stopBuildOnErrors", + category: Diagnostics.Command_line_Options, + description: Diagnostics.Skip_building_downstream_projects_on_error_in_upstream_project, + type: "boolean", + defaultValueDescription: false } ]; var buildOpts = [ @@ -42081,9 +42185,7 @@ function convertToTSConfig(configParseResult, configFileName, host) { return config; } function optionMapToObject(optionMap) { - return { - ...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}) - }; + return Object.fromEntries(optionMap); } function filterSameAsDefaultInclude(specs) { if (!length(specs)) return void 0; @@ -42951,7 +43053,7 @@ function convertJsonOptionOfCustomType(opt, value, errors, valueExpression, sour function convertJsonOptionOfListType(option, values, basePath, errors, propertyAssignment, valueExpression, sourceFile) { return filter(map(values, (v, index) => convertJsonOption(option.element, v, basePath, errors, propertyAssignment, valueExpression == null ? void 0 : valueExpression.elements[index], sourceFile)), (v) => option.listPreserveFalsyValues ? true : !!v); } -var invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/; +var invalidTrailingRecursionPattern = /(?:^|\/)\*\*\/?$/; var wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/; function getFileNamesFromConfigSpecs(configFileSpecs, basePath, options, host, extraFileExtensions = emptyArray) { basePath = normalizePath(basePath); @@ -44085,7 +44187,6 @@ function resolveModuleNameFromCache(moduleName, containingFile, cache, mode) { ); } function resolveModuleName(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode) { - var _a, _b, _c; const traceEnabled = isTraceEnabled(compilerOptions, host); if (redirectedReference) { compilerOptions = redirectedReference.commandLine.options; @@ -44114,7 +44215,6 @@ function resolveModuleName(moduleName, containingFile, compilerOptions, host, ca trace(host, Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ModuleResolutionKind[moduleResolution]); } } - (_a = perfLogger) == null ? void 0 : _a.logStartResolveModule(moduleName); switch (moduleResolution) { case 3 /* Node16 */: result = node16ModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode); @@ -44134,8 +44234,6 @@ function resolveModuleName(moduleName, containingFile, compilerOptions, host, ca default: return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); } - if (result && result.resolvedModule) (_b = perfLogger) == null ? void 0 : _b.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); - (_c = perfLogger) == null ? void 0 : _c.logStopResolveModule(result && result.resolvedModule ? "" + result.resolvedModule.resolvedFileName : "null"); if (cache && !cache.isReadonly) { cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(moduleName, resolutionMode, result); if (!isExternalModuleNameRelative(moduleName)) { @@ -44842,22 +44940,16 @@ function getTemporaryModuleResolutionState(packageJsonInfoCache, host, options) resolvedPackageDirectory: false }; } -function getPackageScopeForPath(fileName, state) { - const parts = getPathComponents(fileName); - parts.pop(); - while (parts.length > 0) { - const pkg = getPackageJsonInfo( - getPathFromPathComponents(parts), +function getPackageScopeForPath(directory, state) { + return forEachAncestorDirectory( + directory, + (dir) => getPackageJsonInfo( + dir, /*onlyRecordFailures*/ false, state - ); - if (pkg) { - return pkg; - } - parts.pop(); - } - return void 0; + ) + ); } function getVersionPathsOfPackageJsonInfo(packageJsonInfo, state) { if (packageJsonInfo.contents.versionPaths === void 0) { @@ -45020,7 +45112,7 @@ function noKeyStartsWithDot(obj) { } function loadModuleFromSelfNameReference(extensions, moduleName, directory, state, cache, redirectedReference) { var _a, _b; - const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), (_b = (_a = state.host).getCurrentDirectory) == null ? void 0 : _b.call(_a)); + const directoryPath = getNormalizedAbsolutePath(directory, (_b = (_a = state.host).getCurrentDirectory) == null ? void 0 : _b.call(_a)); const scope = getPackageScopeForPath(directoryPath, state); if (!scope || !scope.contents.packageJsonContent.exports) { return void 0; @@ -45116,7 +45208,7 @@ function loadModuleFromImports(extensions, moduleName, directory, state, cache, void 0 ); } - const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), (_b = (_a = state.host).getCurrentDirectory) == null ? void 0 : _b.call(_a)); + const directoryPath = getNormalizedAbsolutePath(directory, (_b = (_a = state.host).getCurrentDirectory) == null ? void 0 : _b.call(_a)); const scope = getPackageScopeForPath(directoryPath, state); if (!scope) { if (state.traceEnabled) { @@ -45184,7 +45276,7 @@ function loadModuleFromImportsOrExports(extensions, state, cache, redirectedRefe moduleName ); } - const expandingKeys = sort(filter(getOwnKeys(lookupTable), (k) => hasOneAsterisk(k) || endsWith(k, "/")), comparePatternKeys); + const expandingKeys = toSorted(filter(getOwnKeys(lookupTable), (k) => hasOneAsterisk(k) || endsWith(k, "/")), comparePatternKeys); for (const potentialTarget of expandingKeys) { if (state.features & 16 /* ExportsPatternTrailers */ && matchesPatternWithTrailer(potentialTarget, moduleName)) { const target = lookupTable[potentialTarget]; @@ -45928,6 +46020,9 @@ function getModuleInstanceStateWorker(node, visited) { } function getModuleInstanceStateForAliasTarget(specifier, visited) { const name = specifier.propertyName || specifier.name; + if (name.kind !== 80 /* Identifier */) { + return 1 /* Instantiated */; + } let p = specifier.parent; while (p) { if (isBlock(p) || isModuleBlock(p) || isSourceFile(p)) { @@ -45980,11 +46075,8 @@ function createFlowNode(flags, node, antecedent) { } var binder = /* @__PURE__ */ createBinder(); function bindSourceFile(file, options) { - var _a, _b; mark("beforeBind"); - (_a = perfLogger) == null ? void 0 : _a.logStartBindFile("" + file.fileName); binder(file, options); - (_b = perfLogger) == null ? void 0 : _b.logStopBindFile(); mark("afterBind"); measure("Bind", "beforeBind", "afterBind"); } @@ -46184,7 +46276,7 @@ function createBinder() { } function declareSymbol(symbolTable, parent3, node, includes, excludes, isReplaceableByMethod, isComputedName) { Debug.assert(isComputedName || !hasDynamicName(node)); - const isDefaultExport = hasSyntacticModifier(node, 2048 /* Default */) || isExportSpecifier(node) && node.name.escapedText === "default"; + const isDefaultExport = hasSyntacticModifier(node, 2048 /* Default */) || isExportSpecifier(node) && moduleExportNameIsDefault(node.name); const name = isComputedName ? "__computed" /* Computed */ : isDefaultExport && parent3 ? "default" /* Default */ : getDeclarationName(node); let symbol; if (name === void 0) { @@ -47281,6 +47373,8 @@ function createBinder() { } function bindJSDocImportTag(node) { bind(node.tagName); + bind(node.moduleSpecifier); + bind(node.attributes); if (typeof node.comment !== "string") { bindEach(node.comment); } @@ -48664,21 +48758,25 @@ function createBinder() { const reportError = ( // report error on all statements except empty ones isStatementButNotDeclaration(node) && node.kind !== 242 /* EmptyStatement */ || // report error on class declarations - node.kind === 263 /* ClassDeclaration */ || // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + node.kind === 263 /* ClassDeclaration */ || // report errors on enums with preserved emit + isEnumDeclarationWithPreservedEmit(node, options) || // report error on instantiated modules node.kind === 267 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node) ); if (reportError) { currentFlow = reportedUnreachableFlow; if (!options.allowUnreachableCode) { const isError = unreachableCodeIsError(options) && !(node.flags & 33554432 /* Ambient */) && (!isVariableStatement(node) || !!(getCombinedNodeFlags(node.declarationList) & 7 /* BlockScoped */) || node.declarationList.declarations.some((d) => !!d.initializer)); - eachUnreachableRange(node, (start, end) => errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected)); + eachUnreachableRange(node, options, (start, end) => errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected)); } } } return true; } } -function eachUnreachableRange(node, cb) { +function isEnumDeclarationWithPreservedEmit(node, options) { + return node.kind === 266 /* EnumDeclaration */ && (!isEnumConst(node) || shouldPreserveConstEnums(options)); +} +function eachUnreachableRange(node, options, cb) { if (isStatement(node) && isExecutableStatement(node) && isBlock(node.parent)) { const { statements } = node.parent; const slice = sliceAfter(statements, node); @@ -48686,22 +48784,22 @@ function eachUnreachableRange(node, cb) { } else { cb(node, node); } -} -function isExecutableStatement(s) { - return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !isEnumDeclaration(s) && // `var x;` may declare a variable used above - !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & 7 /* BlockScoped */) && s.declarationList.declarations.some((d) => !d.initializer)); -} -function isPurelyTypeDeclaration(s) { - switch (s.kind) { - case 264 /* InterfaceDeclaration */: - case 265 /* TypeAliasDeclaration */: - return true; - case 267 /* ModuleDeclaration */: - return getModuleInstanceState(s) !== 1 /* Instantiated */; - case 266 /* EnumDeclaration */: - return hasSyntacticModifier(s, 4096 /* Const */); - default: - return false; + function isExecutableStatement(s) { + return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && // `var x;` may declare a variable used above + !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & 7 /* BlockScoped */) && s.declarationList.declarations.some((d) => !d.initializer)); + } + function isPurelyTypeDeclaration(s) { + switch (s.kind) { + case 264 /* InterfaceDeclaration */: + case 265 /* TypeAliasDeclaration */: + return true; + case 267 /* ModuleDeclaration */: + return getModuleInstanceState(s) !== 1 /* Instantiated */; + case 266 /* EnumDeclaration */: + return !isEnumDeclarationWithPreservedEmit(s, options); + default: + return false; + } } } function isExportsOrModuleExportsOrAlias(sourceFile, node) { @@ -48970,6 +49068,28 @@ __export(ts_moduleSpecifiers_exports, { }); // src/compiler/moduleSpecifiers.ts +var stringToRegex = memoizeOne((pattern) => { + try { + let slash = pattern.indexOf("/"); + if (slash !== 0) { + return new RegExp(pattern); + } + const lastSlash = pattern.lastIndexOf("/"); + if (slash === lastSlash) { + return new RegExp(pattern); + } + while ((slash = pattern.indexOf("/", slash + 1)) !== lastSlash) { + if (pattern[slash - 1] !== "\\") { + return new RegExp(pattern); + } + } + const flags = pattern.substring(lastSlash + 1).replace(/[^iu]/g, ""); + pattern = pattern.substring(1, lastSlash); + return new RegExp(pattern, flags); + } catch { + return void 0; + } +}); var RelativePreference = /* @__PURE__ */ ((RelativePreference2) => { RelativePreference2[RelativePreference2["Relative"] = 0] = "Relative"; RelativePreference2[RelativePreference2["NonRelative"] = 1] = "NonRelative"; @@ -48977,13 +49097,16 @@ var RelativePreference = /* @__PURE__ */ ((RelativePreference2) => { RelativePreference2[RelativePreference2["ExternalNonRelative"] = 3] = "ExternalNonRelative"; return RelativePreference2; })(RelativePreference || {}); -function getModuleSpecifierPreferences({ importModuleSpecifierPreference, importModuleSpecifierEnding }, compilerOptions, importingSourceFile, oldImportSpecifier) { +function getModuleSpecifierPreferences({ importModuleSpecifierPreference, importModuleSpecifierEnding, autoImportSpecifierExcludeRegexes }, host, compilerOptions, importingSourceFile, oldImportSpecifier) { const filePreferredEnding = getPreferredEnding(); return { + excludeRegexes: autoImportSpecifierExcludeRegexes, relativePreference: oldImportSpecifier !== void 0 ? isExternalModuleNameRelative(oldImportSpecifier) ? 0 /* Relative */ : 1 /* NonRelative */ : importModuleSpecifierPreference === "relative" ? 0 /* Relative */ : importModuleSpecifierPreference === "non-relative" ? 1 /* NonRelative */ : importModuleSpecifierPreference === "project-relative" ? 3 /* ExternalNonRelative */ : 2 /* Shortest */, getAllowedEndingsInPreferredOrder: (syntaxImpliedNodeFormat) => { - const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile.impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding; - if ((syntaxImpliedNodeFormat ?? importingSourceFile.impliedNodeFormat) === 99 /* ESNext */) { + const impliedNodeFormat = getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions); + const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding; + const moduleResolution = getEmitModuleResolutionKind(compilerOptions); + if ((syntaxImpliedNodeFormat ?? impliedNodeFormat) === 99 /* ESNext */ && 3 /* Node16 */ <= moduleResolution && moduleResolution <= 99 /* NodeNext */) { if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) { return [3 /* TsExtension */, 2 /* JsExtension */]; } @@ -49014,19 +49137,19 @@ function getModuleSpecifierPreferences({ importModuleSpecifierPreference, import } return getModuleSpecifierEndingPreference( importModuleSpecifierEnding, - resolutionMode ?? importingSourceFile.impliedNodeFormat, + resolutionMode ?? getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), compilerOptions, isFullSourceFile(importingSourceFile) ? importingSourceFile : void 0 ); } } function updateModuleSpecifier(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, oldImportSpecifier, options = {}) { - const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options); + const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options); if (res === oldImportSpecifier) return void 0; return res; } function getModuleSpecifier(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, options = {}) { - return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile), {}, options); + return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName2, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile), {}, options); } function getNodeModulesPackageName(compilerOptions, importingSourceFile, nodeModulesFileName, host, preferences, options = {}) { const info = getInfo(importingSourceFile.fileName, host); @@ -49056,7 +49179,7 @@ function getModuleSpecifierWorker(compilerOptions, importingSourceFile, importin /*packageNameOnly*/ void 0, options.overrideImportMode - )) || getLocalModuleSpecifier(toFileName2, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences); + )) || getLocalModuleSpecifier(toFileName2, info, compilerOptions, host, options.overrideImportMode || getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), preferences); } function tryGetModuleSpecifiersFromCache(moduleSymbol, importingSourceFile, host, userPreferences, options = {}) { const result = tryGetModuleSpecifiersFromCacheWorker( @@ -49094,7 +49217,13 @@ function getModuleSpecifiers(moduleSymbol, checker, compilerOptions, importingSo function getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, importingSourceFile, host, userPreferences, options = {}, forAutoImport) { let computedWithoutCache = false; const ambient = tryGetModuleNameFromAmbientModule(moduleSymbol, checker); - if (ambient) return { kind: "ambient", moduleSpecifiers: [ambient], computedWithoutCache }; + if (ambient) { + return { + kind: "ambient", + moduleSpecifiers: !(forAutoImport && isExcludedByRegex(ambient, userPreferences.autoImportSpecifierExcludeRegexes)) ? [ambient] : emptyArray, + computedWithoutCache + }; + } let [kind, specifiers, moduleSourceFile, modulePaths, cache] = tryGetModuleSpecifiersFromCacheWorker( moduleSymbol, importingSourceFile, @@ -49118,7 +49247,7 @@ function getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions cache == null ? void 0 : cache.set(importingSourceFile.path, moduleSourceFile.path, userPreferences, options, result.kind, modulePaths, result.moduleSpecifiers); return result; } -function getLocalModuleSpecifierBetweenFileNames(importingFile, targetFileName, compilerOptions, host, options = {}) { +function getLocalModuleSpecifierBetweenFileNames(importingFile, targetFileName, compilerOptions, host, preferences, options = {}) { const info = getInfo(importingFile.fileName, host); const importMode = options.overrideImportMode ?? importingFile.impliedNodeFormat; return getLocalModuleSpecifier( @@ -49127,17 +49256,21 @@ function getLocalModuleSpecifierBetweenFileNames(importingFile, targetFileName, compilerOptions, host, importMode, - getModuleSpecifierPreferences({}, compilerOptions, importingFile) + getModuleSpecifierPreferences(preferences, host, compilerOptions, importingFile) ); } function computeModuleSpecifiers(modulePaths, compilerOptions, importingSourceFile, host, userPreferences, options = {}, forAutoImport) { const info = getInfo(importingSourceFile.fileName, host); - const preferences = getModuleSpecifierPreferences(userPreferences, compilerOptions, importingSourceFile); + const preferences = getModuleSpecifierPreferences(userPreferences, host, compilerOptions, importingSourceFile); const existingSpecifier = isFullSourceFile(importingSourceFile) && forEach(modulePaths, (modulePath) => forEach( host.getFileIncludeReasons().get(toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)), (reason) => { if (reason.kind !== 3 /* Import */ || reason.file !== importingSourceFile.path) return void 0; - if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index, compilerOptions)) return void 0; + const existingMode = host.getModeForResolutionAtIndex(importingSourceFile, reason.index); + const targetMode = options.overrideImportMode ?? host.getDefaultResolutionModeForFile(importingSourceFile); + if (existingMode !== targetMode && existingMode !== void 0 && targetMode !== void 0) { + return void 0; + } const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text; return preferences.relativePreference !== 1 /* NonRelative */ || !pathIsRelative(specifier) ? specifier : void 0; } @@ -49162,9 +49295,11 @@ function computeModuleSpecifiers(modulePaths, compilerOptions, importingSourceFi void 0, options.overrideImportMode ) : void 0; - nodeModulesSpecifiers = append(nodeModulesSpecifiers, specifier); - if (specifier && modulePath.isRedirect) { - return { kind: "node_modules", moduleSpecifiers: nodeModulesSpecifiers, computedWithoutCache: true }; + if (specifier && !(forAutoImport && isExcludedByRegex(specifier, preferences.excludeRegexes))) { + nodeModulesSpecifiers = append(nodeModulesSpecifiers, specifier); + if (modulePath.isRedirect) { + return { kind: "node_modules", moduleSpecifiers: nodeModulesSpecifiers, computedWithoutCache: true }; + } } if (!specifier) { const local = getLocalModuleSpecifier( @@ -49177,7 +49312,7 @@ function computeModuleSpecifiers(modulePaths, compilerOptions, importingSourceFi /*pathsOnly*/ modulePath.isRedirect ); - if (!local) { + if (!local || forAutoImport && isExcludedByRegex(local, preferences.excludeRegexes)) { continue; } if (modulePath.isRedirect) { @@ -49193,7 +49328,13 @@ function computeModuleSpecifiers(modulePaths, compilerOptions, importingSourceFi } } } - return (pathsSpecifiers == null ? void 0 : pathsSpecifiers.length) ? { kind: "paths", moduleSpecifiers: pathsSpecifiers, computedWithoutCache: true } : (redirectPathsSpecifiers == null ? void 0 : redirectPathsSpecifiers.length) ? { kind: "redirect", moduleSpecifiers: redirectPathsSpecifiers, computedWithoutCache: true } : (nodeModulesSpecifiers == null ? void 0 : nodeModulesSpecifiers.length) ? { kind: "node_modules", moduleSpecifiers: nodeModulesSpecifiers, computedWithoutCache: true } : { kind: "relative", moduleSpecifiers: Debug.checkDefined(relativeSpecifiers), computedWithoutCache: true }; + return (pathsSpecifiers == null ? void 0 : pathsSpecifiers.length) ? { kind: "paths", moduleSpecifiers: pathsSpecifiers, computedWithoutCache: true } : (redirectPathsSpecifiers == null ? void 0 : redirectPathsSpecifiers.length) ? { kind: "redirect", moduleSpecifiers: redirectPathsSpecifiers, computedWithoutCache: true } : (nodeModulesSpecifiers == null ? void 0 : nodeModulesSpecifiers.length) ? { kind: "node_modules", moduleSpecifiers: nodeModulesSpecifiers, computedWithoutCache: true } : { kind: "relative", moduleSpecifiers: relativeSpecifiers ?? emptyArray, computedWithoutCache: true }; +} +function isExcludedByRegex(moduleSpecifier, excludeRegexes) { + return some(excludeRegexes, (pattern) => { + var _a; + return !!((_a = stringToRegex(pattern)) == null ? void 0 : _a.test(moduleSpecifier)); + }); } function getInfo(importingSourceFileName, host) { importingSourceFileName = getNormalizedAbsolutePath(importingSourceFileName, host.getCurrentDirectory()); @@ -49206,7 +49347,7 @@ function getInfo(importingSourceFileName, host) { canonicalSourceDirectory: getCanonicalFileName(sourceDirectory) }; } -function getLocalModuleSpecifier(moduleFileName, info, compilerOptions, host, importMode, { getAllowedEndingsInPreferredOrder: getAllowedEndingsInPrefererredOrder, relativePreference }, pathsOnly) { +function getLocalModuleSpecifier(moduleFileName, info, compilerOptions, host, importMode, { getAllowedEndingsInPreferredOrder: getAllowedEndingsInPrefererredOrder, relativePreference, excludeRegexes }, pathsOnly) { const { baseUrl, paths, rootDirs } = compilerOptions; if (pathsOnly && !paths) { return void 0; @@ -49222,7 +49363,14 @@ function getLocalModuleSpecifier(moduleFileName, info, compilerOptions, host, im if (!relativeToBaseUrl) { return pathsOnly ? void 0 : relativePath; } - const fromPackageJsonImports = pathsOnly ? void 0 : tryGetModuleNameFromPackageJsonImports(moduleFileName, sourceDirectory, compilerOptions, host, importMode); + const fromPackageJsonImports = pathsOnly ? void 0 : tryGetModuleNameFromPackageJsonImports( + moduleFileName, + sourceDirectory, + compilerOptions, + host, + importMode, + prefersTsExtension(allowedEndings) + ); const fromPaths = pathsOnly || fromPackageJsonImports === void 0 ? paths && tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions) : void 0; if (pathsOnly) { return fromPaths; @@ -49231,6 +49379,14 @@ function getLocalModuleSpecifier(moduleFileName, info, compilerOptions, host, im if (!maybeNonRelative) { return relativePath; } + const relativeIsExcluded = isExcludedByRegex(relativePath, excludeRegexes); + const nonRelativeIsExcluded = isExcludedByRegex(maybeNonRelative, excludeRegexes); + if (!relativeIsExcluded && nonRelativeIsExcluded) { + return relativePath; + } + if (relativeIsExcluded && !nonRelativeIsExcluded) { + return maybeNonRelative; + } if (relativePreference === 1 /* NonRelative */ && !pathIsRelative(maybeNonRelative)) { return maybeNonRelative; } @@ -49345,7 +49501,7 @@ function getAllModulePathsWorker(info, importedFileName, host, compilerOptions, if (cache && links && host.readFile && !pathContainsNodeModules(info.importingSourceFileName)) { Debug.type(host); const state = getTemporaryModuleResolutionState(cache.getPackageJsonInfoCache(), host, {}); - const packageJson = getPackageScopeForPath(info.importingSourceFileName, state); + const packageJson = getPackageScopeForPath(getDirectoryPath(info.importingSourceFileName), state); if (packageJson) { const toResolve = getAllRuntimeDependencies(packageJson.contents.packageJsonContent); for (const depName of toResolve || emptyArray) { @@ -49470,7 +49626,7 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, hos return ending !== 0 /* Minimal */ || value === processEnding(relativeToBaseUrl, [ending], compilerOptions, host); } } -function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, exports2, conditions, mode, isImports) { +function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, exports2, conditions, mode, isImports, preferTsExtension) { if (typeof exports2 === "string") { const ignoreCase = !hostUsesCaseSensitiveFileNames(host); const getCommonSourceDirectory2 = () => host.getCommonSourceDirectory(); @@ -49482,6 +49638,7 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac void 0 ); const extensionSwappedTarget = hasTSFileExtension(targetFilePath) ? removeFileExtension(targetFilePath) + tryGetJSExtensionForFile(targetFilePath, options) : void 0; + const canTryTsExtension = preferTsExtension && hasImplementationTSFileExtension(targetFilePath); switch (mode) { case 0 /* Exact */: if (extensionSwappedTarget && comparePaths(extensionSwappedTarget, pathOrPattern, ignoreCase) === 0 /* EqualTo */ || comparePaths(targetFilePath, pathOrPattern, ignoreCase) === 0 /* EqualTo */ || outputFile && comparePaths(outputFile, pathOrPattern, ignoreCase) === 0 /* EqualTo */ || declarationFile && comparePaths(declarationFile, pathOrPattern, ignoreCase) === 0 /* EqualTo */) { @@ -49489,6 +49646,19 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac } break; case 1 /* Directory */: + if (canTryTsExtension && containsPath(targetFilePath, pathOrPattern, ignoreCase)) { + const fragment = getRelativePathFromDirectory( + pathOrPattern, + targetFilePath, + /*ignoreCase*/ + false + ); + return { moduleFileToTry: getNormalizedAbsolutePath( + combinePaths(combinePaths(packageName, exports2), fragment), + /*currentDirectory*/ + void 0 + ) }; + } if (extensionSwappedTarget && containsPath(pathOrPattern, extensionSwappedTarget, ignoreCase)) { const fragment = getRelativePathFromDirectory( pathOrPattern, @@ -49502,7 +49672,7 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac void 0 ) }; } - if (containsPath(pathOrPattern, targetFilePath, ignoreCase)) { + if (!canTryTsExtension && containsPath(pathOrPattern, targetFilePath, ignoreCase)) { const fragment = getRelativePathFromDirectory( pathOrPattern, targetFilePath, @@ -49525,12 +49695,12 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac return { moduleFileToTry: combinePaths(packageName, fragment) }; } if (declarationFile && containsPath(pathOrPattern, declarationFile, ignoreCase)) { - const fragment = getRelativePathFromDirectory( + const fragment = changeFullExtension(getRelativePathFromDirectory( pathOrPattern, declarationFile, /*ignoreCase*/ false - ); + ), getJSExtensionForFile(declarationFile, options)); return { moduleFileToTry: combinePaths(packageName, fragment) }; } break; @@ -49538,11 +49708,15 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac const starPos = pathOrPattern.indexOf("*"); const leadingSlice = pathOrPattern.slice(0, starPos); const trailingSlice = pathOrPattern.slice(starPos + 1); + if (canTryTsExtension && startsWith(targetFilePath, leadingSlice, ignoreCase) && endsWith(targetFilePath, trailingSlice, ignoreCase)) { + const starReplacement = targetFilePath.slice(leadingSlice.length, targetFilePath.length - trailingSlice.length); + return { moduleFileToTry: replaceFirstStar(packageName, starReplacement) }; + } if (extensionSwappedTarget && startsWith(extensionSwappedTarget, leadingSlice, ignoreCase) && endsWith(extensionSwappedTarget, trailingSlice, ignoreCase)) { const starReplacement = extensionSwappedTarget.slice(leadingSlice.length, extensionSwappedTarget.length - trailingSlice.length); return { moduleFileToTry: replaceFirstStar(packageName, starReplacement) }; } - if (startsWith(targetFilePath, leadingSlice, ignoreCase) && endsWith(targetFilePath, trailingSlice, ignoreCase)) { + if (!canTryTsExtension && startsWith(targetFilePath, leadingSlice, ignoreCase) && endsWith(targetFilePath, trailingSlice, ignoreCase)) { const starReplacement = targetFilePath.slice(leadingSlice.length, targetFilePath.length - trailingSlice.length); return { moduleFileToTry: replaceFirstStar(packageName, starReplacement) }; } @@ -49552,17 +49726,19 @@ function tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, pac } if (declarationFile && startsWith(declarationFile, leadingSlice, ignoreCase) && endsWith(declarationFile, trailingSlice, ignoreCase)) { const starReplacement = declarationFile.slice(leadingSlice.length, declarationFile.length - trailingSlice.length); - return { moduleFileToTry: replaceFirstStar(packageName, starReplacement) }; + const substituted = replaceFirstStar(packageName, starReplacement); + const jsExtension = tryGetJSExtensionForFile(declarationFile, options); + return jsExtension ? { moduleFileToTry: changeFullExtension(substituted, jsExtension) } : void 0; } break; } } else if (Array.isArray(exports2)) { - return forEach(exports2, (e) => tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, e, conditions, mode, isImports)); + return forEach(exports2, (e) => tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, e, conditions, mode, isImports, preferTsExtension)); } else if (typeof exports2 === "object" && exports2 !== null) { for (const key of getOwnKeys(exports2)) { if (key === "default" || conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(conditions, key)) { const subTarget = exports2[key]; - const result = tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, subTarget, conditions, mode, isImports); + const result = tryGetModuleNameFromExportsOrImports(options, host, targetFilePath, packageDirectory, packageName, subTarget, conditions, mode, isImports, preferTsExtension); if (result) { return result; } @@ -49590,6 +49766,8 @@ function tryGetModuleNameFromExports(options, host, targetFilePath, packageDirec conditions, mode, /*isImports*/ + false, + /*preferTsExtension*/ false ); }); @@ -49604,10 +49782,12 @@ function tryGetModuleNameFromExports(options, host, targetFilePath, packageDirec conditions, 0 /* Exact */, /*isImports*/ + false, + /*preferTsExtension*/ false ); } -function tryGetModuleNameFromPackageJsonImports(moduleFileName, sourceDirectory, options, host, importMode) { +function tryGetModuleNameFromPackageJsonImports(moduleFileName, sourceDirectory, options, host, importMode, preferTsExtension) { var _a, _b, _c; if (!host.readFile || !getResolvePackageJsonImports(options)) { return void 0; @@ -49640,7 +49820,8 @@ function tryGetModuleNameFromPackageJsonImports(moduleFileName, sourceDirectory, conditions, mode, /*isImports*/ - true + true, + preferTsExtension ); })) == null ? void 0 : _c.moduleFileToTry; } @@ -49667,7 +49848,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }, { getCanonicalFileNa if (!parts) { return void 0; } - const preferences = getModuleSpecifierPreferences(userPreferences, options, importingSourceFile); + const preferences = getModuleSpecifierPreferences(userPreferences, host, options, importingSourceFile); const allowedEndings = preferences.getAllowedEndingsInPreferredOrder(); let moduleSpecifier = path; let isPackageRootPath = false; @@ -49717,12 +49898,20 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }, { getCanonicalFileNa const cachedPackageJson = (_b = (_a = host.getPackageJsonInfoCache) == null ? void 0 : _a.call(host)) == null ? void 0 : _b.getPackageJsonInfo(packageJsonPath); if (isPackageJsonInfo(cachedPackageJson) || cachedPackageJson === void 0 && host.fileExists(packageJsonPath)) { const packageJsonContent = (cachedPackageJson == null ? void 0 : cachedPackageJson.contents.packageJsonContent) || tryParseJson(host.readFile(packageJsonPath)); - const importMode = overrideMode || importingSourceFile.impliedNodeFormat; + const importMode = overrideMode || getDefaultResolutionModeForFile(importingSourceFile, host, options); if (getResolvePackageJsonExports(options)) { const nodeModulesDirectoryName2 = packageRootPath.substring(parts.topLevelPackageNameIndex + 1); const packageName2 = getPackageNameFromTypesPackageName(nodeModulesDirectoryName2); const conditions = getConditions(options, importMode); - const fromExports = (packageJsonContent == null ? void 0 : packageJsonContent.exports) ? tryGetModuleNameFromExports(options, host, path, packageRootPath, packageName2, packageJsonContent.exports, conditions) : void 0; + const fromExports = (packageJsonContent == null ? void 0 : packageJsonContent.exports) ? tryGetModuleNameFromExports( + options, + host, + path, + packageRootPath, + packageName2, + packageJsonContent.exports, + conditions + ) : void 0; if (fromExports) { return { ...fromExports, verbatimFromExports: true }; } @@ -49867,6 +50056,13 @@ function getRelativePathIfInSameVolume(path, directoryPath, getCanonicalFileName function isPathRelativeToParent(path) { return startsWith(path, ".."); } +function getDefaultResolutionModeForFile(file, host, compilerOptions) { + return isFullSourceFile(file) ? host.getDefaultResolutionModeForFile(file) : getDefaultResolutionModeForFileWorker(file, compilerOptions); +} +function prefersTsExtension(allowedEndings) { + const tsPriority = allowedEndings.indexOf(3 /* TsExtension */); + return tsPriority > -1 && tsPriority < allowedEndings.indexOf(2 /* JsExtension */); +} // src/compiler/checker.ts var ambientModuleSymbolRegex = /^".+"$/; @@ -50048,10 +50244,12 @@ function createTypeChecker(host) { var strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); var strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply"); var strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization"); + var strictBuiltinIteratorReturn = getStrictOptionValue(compilerOptions, "strictBuiltinIteratorReturn"); var noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); var noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); var useUnknownInCatchVariables = getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables"); var exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes; + var noUncheckedSideEffectImports = !!compilerOptions.noUncheckedSideEffectImports; var checkBinaryExpression = createCheckBinaryExpression(); var emitResolver = createResolver(); var nodeBuilder = createNodeBuilder(); @@ -50063,7 +50261,8 @@ function createTypeChecker(host) { isUndefinedIdentifierExpression(node) { Debug.assert(isExpressionNode(node)); return getSymbolAtLocation(node) === undefinedSymbol; - } + }, + isDefinitelyReferenceToGlobalSymbolObject }); var evaluate = createEvaluator({ evaluateElementAccessExpression, @@ -50080,13 +50279,36 @@ function createTypeChecker(host) { const denoContext = deno_exports.createDenoForkContext({ globals: denoGlobals, nodeGlobals, - mergeSymbol, - ambientModuleSymbolRegex + mergeSymbol }); const nodeGlobalThisSymbol = createSymbol(1536 /* Module */, "globalThis", 8 /* Readonly */); nodeGlobalThisSymbol.exports = denoContext.combinedGlobals; nodeGlobalThisSymbol.declarations = []; nodeGlobals.set(nodeGlobalThisSymbol.escapedName, nodeGlobalThisSymbol); + nodeGlobals.set( + "onmessage", + createSymbol(1536 /* Module */, "onmessage", 8 /* Readonly */) + ); + nodeGlobals.set( + "onabort", + createSymbol(1536 /* Module */, "onabort", 8 /* Readonly */) + ); + nodeGlobals.set( + "ReportingObserver", + createSymbol(1536 /* Module */, "ReportingObserver", 8 /* Readonly */) + ); + nodeGlobals.set( + "PerformanceObserver", + createSymbol(1536 /* Module */, "PerformanceObserver", 8 /* Readonly */) + ); + nodeGlobals.set( + "PerformanceObserverEntryList", + createSymbol(1536 /* Module */, "PerformanceObserverEntryList", 8 /* Readonly */) + ); + nodeGlobals.set( + "PerformanceResourceTiming", + createSymbol(1536 /* Module */, "PerformanceResourceTiming", 8 /* Readonly */) + ); var argumentsSymbol = createSymbol(4 /* Property */, "arguments"); var requireSymbol = createSymbol(4 /* Property */, "require"); var isolatedModulesLikeFlagName = compilerOptions.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"; @@ -50195,6 +50417,7 @@ function createTypeChecker(host) { getNonOptionalType: removeOptionalTypeMarker, getTypeArguments, typeToTypeNode: nodeBuilder.typeToTypeNode, + typePredicateToTypePredicateNode: nodeBuilder.typePredicateToTypePredicateNode, indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration, signatureToSignatureDeclaration: nodeBuilder.signatureToSignatureDeclaration, symbolToEntityName: nodeBuilder.symbolToEntityName, @@ -50360,13 +50583,6 @@ function createTypeChecker(host) { /*withAugmentations*/ true ), - tryFindAmbientModuleWithoutAugmentations: (moduleName) => { - return tryFindAmbientModule( - moduleName, - /*withAugmentations*/ - false - ); - }, getApparentType, getUnionType, isTypeAssignableTo, @@ -50380,6 +50596,7 @@ function createTypeChecker(host) { getNumberType: () => numberType, getNumberLiteralType, getBigIntType: () => bigintType, + getBigIntLiteralType, createPromiseType, createArrayType, getElementTypeOfArrayType, @@ -50400,13 +50617,13 @@ function createTypeChecker(host) { /*reportErrors*/ false ), - getAsyncIterableType: () => { + getAnyAsyncIterableType: () => { const type = getGlobalAsyncIterableType( /*reportErrors*/ false ); if (type === emptyGenericType) return void 0; - return type; + return createTypeReference(type, [anyType, anyType, anyType]); }, isSymbolAccessible, isArrayType, @@ -50878,8 +51095,6 @@ function createTypeChecker(host) { } }; var anyIterationTypes = createIterationTypes(anyType, anyType, anyType); - var anyIterationTypesExceptNext = createIterationTypes(anyType, anyType, unknownType); - var defaultIterationTypes = createIterationTypes(neverType, anyType, undefinedType); var asyncIterationTypesResolver = { iterableCacheKey: "iterationTypesOfAsyncIterable", iteratorCacheKey: "iterationTypesOfAsyncIterator", @@ -50887,7 +51102,9 @@ function createTypeChecker(host) { getGlobalIteratorType: getGlobalAsyncIteratorType, getGlobalIterableType: getGlobalAsyncIterableType, getGlobalIterableIteratorType: getGlobalAsyncIterableIteratorType, + getGlobalIteratorObjectType: getGlobalAsyncIteratorObjectType, getGlobalGeneratorType: getGlobalAsyncGeneratorType, + getGlobalBuiltinIteratorTypes: getGlobalBuiltinAsyncIteratorTypes, resolveIterationType: (type, errorNode) => getAwaitedType(type, errorNode, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member), mustHaveANextMethodDiagnostic: Diagnostics.An_async_iterator_must_have_a_next_method, mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method, @@ -50900,7 +51117,9 @@ function createTypeChecker(host) { getGlobalIteratorType, getGlobalIterableType, getGlobalIterableIteratorType, + getGlobalIteratorObjectType, getGlobalGeneratorType, + getGlobalBuiltinIteratorTypes, resolveIterationType: (type, _errorNode) => type, mustHaveANextMethodDiagnostic: Diagnostics.An_iterator_must_have_a_next_method, mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_iterator_must_be_a_method, @@ -50908,6 +51127,7 @@ function createTypeChecker(host) { }; var amalgamatedDuplicates; var reverseMappedCache = /* @__PURE__ */ new Map(); + var reverseHomomorphicMappedCache = /* @__PURE__ */ new Map(); var ambientModulesCache; var nodeAmbientModulesCache; var patternAmbientModules; @@ -50938,12 +51158,16 @@ function createTypeChecker(host) { var deferredGlobalIterableType; var deferredGlobalIteratorType; var deferredGlobalIterableIteratorType; + var deferredGlobalIteratorObjectType; var deferredGlobalGeneratorType; var deferredGlobalIteratorYieldResultType; var deferredGlobalIteratorReturnResultType; var deferredGlobalAsyncIterableType; var deferredGlobalAsyncIteratorType; var deferredGlobalAsyncIterableIteratorType; + var deferredGlobalBuiltinIteratorTypes; + var deferredGlobalBuiltinAsyncIteratorTypes; + var deferredGlobalAsyncIteratorObjectType; var deferredGlobalAsyncGeneratorType; var deferredGlobalTemplateStringsArrayType; var deferredGlobalImportMetaType; @@ -50979,6 +51203,7 @@ function createTypeChecker(host) { var contextualTypes = []; var contextualIsCache = []; var contextualTypeCount = 0; + var contextualBindingPatterns = []; var inferenceContextNodes = []; var inferenceContexts = []; var inferenceContextCount = 0; @@ -51036,6 +51261,23 @@ function createTypeChecker(host) { ]; initializeTypeChecker(); return checker; + function isDefinitelyReferenceToGlobalSymbolObject(node) { + if (!isPropertyAccessExpression(node)) return false; + if (!isIdentifier(node.name)) return false; + if (!isPropertyAccessExpression(node.expression) && !isIdentifier(node.expression)) return false; + if (isIdentifier(node.expression)) { + return idText(node.expression) === "Symbol" && getResolvedSymbol(node.expression) === (getGlobalSymbol( + "Symbol", + 111551 /* Value */ | 1048576 /* ExportValue */, + /*diagnostic*/ + void 0 + ) || unknownSymbol); + } + if (!isIdentifier(node.expression.expression)) return false; + if (idText(node.expression.name) !== "Symbol" || idText(node.expression.expression) !== "globalThis") return false; + const resolvedSymbol = getResolvedSymbol(node.expression.expression); + return resolvedSymbol === denoGlobalThisSymbol || resolvedSymbol === nodeGlobalThisSymbol; + } function getCachedType(key) { return key ? cachedTypes.get(key) : void 0; } @@ -51281,7 +51523,7 @@ function createTypeChecker(host) { } if (source.exports) { if (!target.exports) target.exports = createSymbolTable(); - mergeSymbolTable(target.exports, source.exports, unidirectional); + mergeSymbolTable(target.exports, source.exports, unidirectional, target); } if (!unidirectional) { recordMergedSymbol(target, source); @@ -51361,10 +51603,14 @@ function createTypeChecker(host) { mergeSymbolTable(combined, second); return combined; } - function mergeSymbolTable(target, source, unidirectional = false) { + function mergeSymbolTable(target, source, unidirectional = false, mergedParent) { source.forEach((sourceSymbol, id) => { const targetSymbol = target.get(id); - target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol)); + const merged = targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol); + if (mergedParent && targetSymbol) { + merged.parent = mergedParent; + } + target.set(id, merged); }); } function mergeModuleAugmentation(moduleName) { @@ -51382,6 +51628,8 @@ function createTypeChecker(host) { moduleName, moduleName, moduleNotFoundError, + /*ignoreErrors*/ + false, /*isForAugmentation*/ true ); @@ -52022,9 +52270,9 @@ function createTypeChecker(host) { } } function getDeclarationOfAliasSymbol(symbol) { - return symbol.declarations && findLast(symbol.declarations, isAliasSymbolDeclaration2); + return symbol.declarations && findLast(symbol.declarations, isAliasSymbolDeclaration); } - function isAliasSymbolDeclaration2(node) { + function isAliasSymbolDeclaration(node) { return node.kind === 271 /* ImportEqualsDeclaration */ || node.kind === 270 /* NamespaceExportDeclaration */ || node.kind === 273 /* ImportClause */ && !!node.name || node.kind === 274 /* NamespaceImport */ || node.kind === 280 /* NamespaceExport */ || node.kind === 276 /* ImportSpecifier */ || node.kind === 281 /* ExportSpecifier */ || node.kind === 277 /* ExportAssignment */ && exportAssignmentIsAlias(node) || isBinaryExpression(node) && getAssignmentDeclarationKind(node) === 2 /* ModuleExports */ && exportAssignmentIsAlias(node) || isAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === 64 /* EqualsToken */ && isAliasableOrJsExpression(node.parent.right) || node.kind === 304 /* ShorthandPropertyAssignment */ || node.kind === 303 /* PropertyAssignment */ && isAliasableOrJsExpression(node.initializer) || node.kind === 260 /* VariableDeclaration */ && isVariableDeclarationInitializedToBareOrAccessedRequire(node) || node.kind === 208 /* BindingElement */ && isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent); } function isAliasableOrJsExpression(e) { @@ -52068,7 +52316,7 @@ function createTypeChecker(host) { const isExport = typeOnlyDeclaration.kind === 281 /* ExportSpecifier */ || typeOnlyDeclaration.kind === 278 /* ExportDeclaration */; const message = isExport ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type : Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type; const relatedMessage = isExport ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here; - const name = typeOnlyDeclaration.kind === 278 /* ExportDeclaration */ ? "*" : unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); + const name = typeOnlyDeclaration.kind === 278 /* ExportDeclaration */ ? "*" : moduleExportNameTextUnescaped(typeOnlyDeclaration.name); addRelatedInfo(error2(node.moduleReference, message), createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)); } } @@ -52093,22 +52341,25 @@ function createTypeChecker(host) { function isSyntacticDefault(node) { return isExportAssignment(node) && !node.isExportEquals || hasSyntacticModifier(node, 2048 /* Default */) || isExportSpecifier(node) || isNamespaceExport(node); } - function getUsageModeForExpression(usage) { - return isStringLiteralLike(usage) ? host.getModeForUsageLocation(getSourceFileOfNode(usage), usage) : void 0; + function getEmitSyntaxForModuleSpecifierExpression(usage) { + return isStringLiteralLike(usage) ? host.getEmitSyntaxForUsageLocation(getSourceFileOfNode(usage), usage) : void 0; } function isESMFormatImportImportingCommonjsFormatFile(usageMode, targetMode) { return usageMode === 99 /* ESNext */ && targetMode === 1 /* CommonJS */; } - function isOnlyImportedAsDefault(usage) { - const usageMode = getUsageModeForExpression(usage); - return usageMode === 99 /* ESNext */ && endsWith(usage.text, ".json" /* Json */); + function isOnlyImportableAsDefault(usage) { + if (100 /* Node16 */ <= moduleKind && moduleKind <= 199 /* NodeNext */) { + const usageMode = getEmitSyntaxForModuleSpecifierExpression(usage); + return usageMode === 99 /* ESNext */ && endsWith(usage.text, ".json" /* Json */); + } + return false; } function canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, usage) { - const usageMode = file && getUsageModeForExpression(usage); - if (file && usageMode !== void 0 && file.impliedNodeFormat === 1 /* CommonJS */) { - const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat); - if (result) { - return result; + const usageMode = file && getEmitSyntaxForModuleSpecifierExpression(usage); + if (file && usageMode !== void 0) { + const targetMode = host.getImpliedNodeFormatForEmit(file); + if (usageMode === 99 /* ESNext */ && targetMode === 1 /* CommonJS */ && 100 /* Node16 */ <= moduleKind && moduleKind <= 199 /* NodeNext */) { + return true; } } if (!allowSyntheticDefaultImports) { @@ -52167,7 +52418,7 @@ function createTypeChecker(host) { if (!specifier) { return exportDefaultSymbol; } - const hasDefaultOnly = isOnlyImportedAsDefault(specifier); + const hasDefaultOnly = isOnlyImportableAsDefault(specifier); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol) && !allowSyntheticDefaultImports) { @@ -52306,12 +52557,12 @@ function createTypeChecker(host) { if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports); return result; } - function getExportOfModule(symbol, name, specifier, dontResolveAlias) { + function getExportOfModule(symbol, nameText, specifier, dontResolveAlias) { var _a; if (symbol.flags & 1536 /* Module */) { - const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText); + const exportSymbol = getExportsOfSymbol(symbol).get(nameText); const resolved = resolveSymbol(exportSymbol, dontResolveAlias); - const exportStarDeclaration = (_a = getSymbolLinks(symbol).typeOnlyExportStarMap) == null ? void 0 : _a.get(name.escapedText); + const exportStarDeclaration = (_a = getSymbolLinks(symbol).typeOnlyExportStarMap) == null ? void 0 : _a.get(nameText); markSymbolOfAliasDeclarationIfTypeOnly( specifier, exportSymbol, @@ -52319,7 +52570,7 @@ function createTypeChecker(host) { /*overwriteEmpty*/ false, exportStarDeclaration, - name.escapedText + nameText ); return resolved; } @@ -52337,10 +52588,11 @@ function createTypeChecker(host) { const moduleSpecifier = getExternalModuleRequireArgument(node) || node.moduleSpecifier; const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier); const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name; - if (!isIdentifier(name)) { + if (!isIdentifier(name) && name.kind !== 11 /* StringLiteral */) { return void 0; } - const suppressInteropError = name.escapedText === "default" /* Default */ && allowSyntheticDefaultImports; + const nameText = moduleExportNameTextEscaped(name); + const suppressInteropError = nameText === "default" /* Default */ && allowSyntheticDefaultImports; const targetSymbol = resolveESModuleSymbol( moduleSymbol, moduleSpecifier, @@ -52349,7 +52601,7 @@ function createTypeChecker(host) { suppressInteropError ); if (targetSymbol) { - if (name.escapedText) { + if (nameText || name.kind === 11 /* StringLiteral */) { if (isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } @@ -52357,18 +52609,18 @@ function createTypeChecker(host) { if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" /* ExportEquals */)) { symbolFromVariable = getPropertyOfType( getTypeOfSymbol(targetSymbol), - name.escapedText, + nameText, /*skipObjectFunctionPropertyAugment*/ true ); } else { - symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText); + symbolFromVariable = getPropertyOfVariable(targetSymbol, nameText); } symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias); - let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias); - if (symbolFromModule === void 0 && name.escapedText === "default" /* Default */) { + let symbolFromModule = getExportOfModule(targetSymbol, nameText, specifier, dontResolveAlias); + if (symbolFromModule === void 0 && nameText === "default" /* Default */) { const file = (_a = moduleSymbol.declarations) == null ? void 0 : _a.find(isSourceFile); - if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { + if (isOnlyImportableAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } } @@ -52384,7 +52636,7 @@ function createTypeChecker(host) { var _a; const moduleName = getFullyQualifiedName(moduleSymbol, node); const declarationName = declarationNameToString(name); - const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol); + const suggestion = isIdentifier(name) ? getSuggestedSymbolForNonexistentModule(name, targetSymbol) : void 0; if (suggestion !== void 0) { const suggestionName = symbolToString(suggestion); const diagnostic = error2(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName); @@ -52406,7 +52658,7 @@ function createTypeChecker(host) { } function reportNonExportedMember(node, name, declarationName, moduleSymbol, moduleName) { var _a, _b; - const localSymbol = (_b = (_a = tryCast(moduleSymbol.valueDeclaration, canHaveLocals)) == null ? void 0 : _a.locals) == null ? void 0 : _b.get(name.escapedText); + const localSymbol = (_b = (_a = tryCast(moduleSymbol.valueDeclaration, canHaveLocals)) == null ? void 0 : _a.locals) == null ? void 0 : _b.get(moduleExportNameTextEscaped(name)); const exports2 = moduleSymbol.exports; if (localSymbol) { const exportedEqualsSymbol = exports2 == null ? void 0 : exports2.get("export=" /* ExportEquals */); @@ -52438,7 +52690,7 @@ function createTypeChecker(host) { } } function getTargetOfImportSpecifier(node, dontResolveAlias) { - if (isImportSpecifier(node) && idText(node.propertyName || node.name) === "default" /* Default */) { + if (isImportSpecifier(node) && moduleExportNameIsDefault(node.propertyName || node.name)) { const specifier = getModuleSpecifierForImportOrExport(node); const moduleSymbol = specifier && resolveExternalModuleName(node, specifier); if (moduleSymbol) { @@ -52482,19 +52734,23 @@ function createTypeChecker(host) { } } function getTargetOfExportSpecifier(node, meaning, dontResolveAlias) { - if (idText(node.propertyName || node.name) === "default" /* Default */) { + const name = node.propertyName || node.name; + if (moduleExportNameIsDefault(name)) { const specifier = getModuleSpecifierForImportOrExport(node); const moduleSymbol = specifier && resolveExternalModuleName(node, specifier); if (moduleSymbol) { return getTargetofModuleDefault(moduleSymbol, node, !!dontResolveAlias); } } - const resolved = node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : resolveEntityName( - node.propertyName || node.name, - meaning, - /*ignoreErrors*/ - false, - dontResolveAlias + const resolved = node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : name.kind === 11 /* StringLiteral */ ? void 0 : ( + // Skip for invalid syntax like this: export { "x" } + resolveEntityName( + name, + meaning, + /*ignoreErrors*/ + false, + dontResolveAlias + ) ); markSymbolOfAliasDeclarationIfTypeOnly( node, @@ -52942,10 +53198,10 @@ function createTypeChecker(host) { function resolveExternalModuleName(location, moduleReferenceExpression, ignoreErrors) { const isClassic = getEmitModuleResolutionKind(compilerOptions) === 1 /* Classic */; const errorMessage = isClassic ? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; - return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? void 0 : errorMessage); + return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? void 0 : errorMessage, ignoreErrors); } - function resolveExternalModuleNameWorker(location, moduleReferenceExpression, moduleNotFoundError, isForAugmentation = false) { - return isStringLiteralLike(moduleReferenceExpression) ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation) : void 0; + function resolveExternalModuleNameWorker(location, moduleReferenceExpression, moduleNotFoundError, ignoreErrors = false, isForAugmentation = false) { + return isStringLiteralLike(moduleReferenceExpression) ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, !ignoreErrors ? moduleReferenceExpression : void 0, isForAugmentation) : void 0; } function resolveExternalModule(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation = false) { var _a; @@ -52968,7 +53224,7 @@ function createTypeChecker(host) { } function resolveExternalModuleInner(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation = false) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k; - if (startsWith(moduleReference, "@types/")) { + if (errorNode && startsWith(moduleReference, "@types/")) { const diag2 = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1; const withoutAtTypePrefix = removePrefix(moduleReference, "@types/"); error2(errorNode, diag2, withoutAtTypePrefix, moduleReference); @@ -52987,10 +53243,10 @@ function createTypeChecker(host) { /*requireStringLiteralLikeArgument*/ true ) ? location.initializer.arguments[0] : void 0) || ((_c = findAncestor(location, isImportCall)) == null ? void 0 : _c.arguments[0]) || ((_d = findAncestor(location, isImportDeclaration)) == null ? void 0 : _d.moduleSpecifier) || ((_e = findAncestor(location, isExternalModuleImportEqualsDeclaration)) == null ? void 0 : _e.moduleReference.expression) || ((_f = findAncestor(location, isExportDeclaration)) == null ? void 0 : _f.moduleSpecifier); - const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) : host.getDefaultResolutionModeForFile(currentSourceFile); const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); const resolvedModule = (_g = host.getResolvedModule(currentSourceFile, moduleReference, mode)) == null ? void 0 : _g.resolvedModule; - const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); + const resolutionDiagnostic = errorNode && resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); const sourceFile = resolvedModule && (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (resolutionDiagnostic) { @@ -52998,7 +53254,7 @@ function createTypeChecker(host) { } if (resolvedModule.resolvedUsingTsExtension && isDeclarationFileName(moduleReference)) { const importOrExport = ((_h = findAncestor(location, isImportDeclaration)) == null ? void 0 : _h.importClause) || findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); - if (importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) { + if (errorNode && importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) { error2( errorNode, Diagnostics.A_declaration_file_cannot_be_imported_without_import_type_Did_you_mean_to_import_an_implementation_file_0_instead, @@ -53007,13 +53263,13 @@ function createTypeChecker(host) { } } else if (resolvedModule.resolvedUsingTsExtension && !shouldAllowImportingTsExtension(compilerOptions, currentSourceFile.fileName)) { const importOrExport = ((_i = findAncestor(location, isImportDeclaration)) == null ? void 0 : _i.importClause) || findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); - if (!((importOrExport == null ? void 0 : importOrExport.isTypeOnly) || findAncestor(location, isImportTypeNode))) { + if (errorNode && !((importOrExport == null ? void 0 : importOrExport.isTypeOnly) || findAncestor(location, isImportTypeNode))) { const tsExtension = Debug.checkDefined(tryExtractTSExtension(moduleReference)); error2(errorNode, Diagnostics.An_import_path_can_only_end_with_a_0_extension_when_allowImportingTsExtensions_is_enabled, tsExtension); } } if (sourceFile.symbol) { - if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) { + if (errorNode && resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) { errorOnImplicitAnyModule( /*isError*/ false, @@ -53024,9 +53280,9 @@ function createTypeChecker(host) { moduleReference ); } - if (moduleResolutionKind === 3 /* Node16 */ || moduleResolutionKind === 99 /* NodeNext */) { + if (errorNode && (moduleResolutionKind === 3 /* Node16 */ || moduleResolutionKind === 99 /* NodeNext */)) { const isSyncImport = currentSourceFile.impliedNodeFormat === 1 /* CommonJS */ && !findAncestor(location, isImportCall) || !!findAncestor(location, isImportEqualsDeclaration); - const overrideHost = findAncestor(location, (l) => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)); + const overrideHost = findAncestor(location, (l) => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l) || isJSDocImportTag(l)); if (isSyncImport && sourceFile.impliedNodeFormat === 99 /* ESNext */ && !hasResolutionModeOverride(overrideHost)) { if (findAncestor(location, isImportEqualsDeclaration)) { error2(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference); @@ -53034,41 +53290,7 @@ function createTypeChecker(host) { let diagnosticDetails; const ext = tryGetExtensionFromPath2(currentSourceFile.fileName); if (ext === ".ts" /* Ts */ || ext === ".js" /* Js */ || ext === ".tsx" /* Tsx */ || ext === ".jsx" /* Jsx */) { - const scope = currentSourceFile.packageJsonScope; - const targetExt = ext === ".ts" /* Ts */ ? ".mts" /* Mts */ : ext === ".js" /* Js */ ? ".mjs" /* Mjs */ : void 0; - if (scope && !scope.contents.packageJsonContent.type) { - if (targetExt) { - diagnosticDetails = chainDiagnosticMessages( - /*details*/ - void 0, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, - targetExt, - combinePaths(scope.packageDirectory, "package.json") - ); - } else { - diagnosticDetails = chainDiagnosticMessages( - /*details*/ - void 0, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, - combinePaths(scope.packageDirectory, "package.json") - ); - } - } else { - if (targetExt) { - diagnosticDetails = chainDiagnosticMessages( - /*details*/ - void 0, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, - targetExt - ); - } else { - diagnosticDetails = chainDiagnosticMessages( - /*details*/ - void 0, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module - ); - } - } + diagnosticDetails = createModeMismatchDetails(currentSourceFile); } diagnostics.add(createDiagnosticForNodeFromMessageChain( getSourceFileOfNode(errorNode), @@ -53084,7 +53306,7 @@ function createTypeChecker(host) { } return getMergedSymbol(sourceFile.symbol); } - if (moduleNotFoundError) { + if (errorNode && moduleNotFoundError && !isSideEffectImport(errorNode)) { error2(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return void 0; @@ -53099,6 +53321,9 @@ function createTypeChecker(host) { return getMergedSymbol(pattern.symbol); } } + if (!errorNode) { + return void 0; + } if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === void 0 || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { const diag2 = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; @@ -53166,6 +53391,9 @@ function createTypeChecker(host) { } } function errorOnImplicitAnyModule(isError, errorNode, sourceFile, mode, { packageId, resolvedFileName }, moduleReference) { + if (isSideEffectImport(errorNode)) { + return; + } let errorInfo; if (!isExternalModuleNameRelative(moduleReference) && packageId) { errorInfo = createModuleNotFoundChain(sourceFile, host, moduleReference, mode, packageId.name); @@ -53231,7 +53459,7 @@ function createTypeChecker(host) { return cloneTypeAsModuleType(symbol, defaultOnlyType, referenceParent); } const targetFile = (_a = moduleSymbol == null ? void 0 : moduleSymbol.declarations) == null ? void 0 : _a.find(isSourceFile); - const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getUsageModeForExpression(reference), targetFile.impliedNodeFormat); + const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getEmitSyntaxForModuleSpecifierExpression(reference), host.getImpliedNodeFormatForEmit(targetFile)); if (getESModuleInterop(compilerOptions) || isEsmCjsRef) { let sigs = getSignaturesOfStructuredType(type, 0 /* Call */); if (!sigs || !sigs.length) { @@ -54110,6 +54338,7 @@ function createTypeChecker(host) { } function symbolToString(symbol, enclosingDeclaration, meaning, flags = 4 /* AllowAnyNodeKind */, writer) { let nodeFlags = 70221824 /* IgnoreErrors */; + let internalNodeFlags = 0 /* None */; if (flags & 2 /* UseOnlyExternalAliasing */) { nodeFlags |= 128 /* UseOnlyExternalAliasing */; } @@ -54120,15 +54349,15 @@ function createTypeChecker(host) { nodeFlags |= 16384 /* UseAliasDefinedOutsideCurrentScope */; } if (flags & 32 /* DoNotIncludeSymbolChain */) { - nodeFlags |= 134217728 /* DoNotIncludeSymbolChain */; + internalNodeFlags |= 4 /* DoNotIncludeSymbolChain */; } if (flags & 16 /* WriteComputedProps */) { - nodeFlags |= 1073741824 /* WriteComputedProps */; + internalNodeFlags |= 1 /* WriteComputedProps */; } const builder = flags & 4 /* AllowAnyNodeKind */ ? nodeBuilder.symbolToNode : nodeBuilder.symbolToEntityName; return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer2) { - const entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); + const entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags, internalNodeFlags); const printer = (enclosingDeclaration == null ? void 0 : enclosingDeclaration.kind) === 307 /* SourceFile */ ? createPrinterWithRemoveCommentsNeverAsciiEscape() : createPrinterWithRemoveComments(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode( @@ -54165,7 +54394,13 @@ function createTypeChecker(host) { } function typeToString(type, enclosingDeclaration, flags = 1048576 /* AllowUniqueESSymbolType */ | 16384 /* UseAliasDefinedOutsideCurrentScope */, writer = createTextWriter("")) { const noTruncation = compilerOptions.noErrorTruncation || flags & 1 /* NoTruncation */; - const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* IgnoreErrors */ | (noTruncation ? 1 /* NoTruncation */ : 0)); + const typeNode = nodeBuilder.typeToTypeNode( + type, + enclosingDeclaration, + toNodeBuilderFlags(flags) | 70221824 /* IgnoreErrors */ | (noTruncation ? 1 /* NoTruncation */ : 0 /* None */), + /*internalFlags*/ + void 0 + ); if (typeNode === void 0) return Debug.fail("should always get typenode"); const printer = type !== unresolvedType ? createPrinterWithRemoveComments() : createPrinterWithDefaults(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); @@ -54214,31 +54449,31 @@ function createTypeChecker(host) { } function createNodeBuilder() { return { - typeToTypeNode: (type, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => typeToTypeNodeHelper(type, context)), - typePredicateToTypePredicateNode: (typePredicate, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => typePredicateToTypePredicateNodeHelper(typePredicate, context)), - expressionOrTypeToTypeNode: (expr, type, addUndefined, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => expressionOrTypeToTypeNode(context, expr, type, addUndefined)), - serializeTypeForDeclaration: (declaration, type, symbol, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => serializeTypeForDeclaration(context, declaration, type, symbol)), - serializeReturnTypeForSignature: (signature, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => serializeReturnTypeForSignature(context, signature)), - indexInfoToIndexSignatureDeclaration: (indexInfo, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => indexInfoToIndexSignatureDeclarationHelper( + typeToTypeNode: (type, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => typeToTypeNodeHelper(type, context)), + typePredicateToTypePredicateNode: (typePredicate, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => typePredicateToTypePredicateNodeHelper(typePredicate, context)), + expressionOrTypeToTypeNode: (expr, type, addUndefined, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => expressionOrTypeToTypeNode(context, expr, type, addUndefined)), + serializeTypeForDeclaration: (declaration, type, symbol, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => serializeTypeForDeclaration(context, declaration, type, symbol)), + serializeReturnTypeForSignature: (signature, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => serializeReturnTypeForSignature(context, signature)), + indexInfoToIndexSignatureDeclaration: (indexInfo, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => indexInfoToIndexSignatureDeclarationHelper( indexInfo, context, /*typeNode*/ void 0 )), - signatureToSignatureDeclaration: (signature, kind, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => signatureToSignatureDeclarationHelper(signature, kind, context)), - symbolToEntityName: (symbol, meaning, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => symbolToName( + signatureToSignatureDeclaration: (signature, kind, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => signatureToSignatureDeclarationHelper(signature, kind, context)), + symbolToEntityName: (symbol, meaning, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => symbolToName( symbol, context, meaning, /*expectsIdentifier*/ false )), - symbolToExpression: (symbol, meaning, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => symbolToExpression(symbol, context, meaning)), - symbolToTypeParameterDeclarations: (symbol, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => typeParametersToTypeParameterDeclarations(symbol, context)), - symbolToParameterDeclaration: (symbol, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => symbolToParameterDeclaration(symbol, context)), - typeParameterToDeclaration: (parameter, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => typeParameterToDeclaration(parameter, context)), - symbolTableToDeclarationStatements: (symbolTable, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => symbolTableToDeclarationStatements(symbolTable, context)), - symbolToNode: (symbol, meaning, enclosingDeclaration, flags, tracker) => withContext2(enclosingDeclaration, flags, tracker, (context) => symbolToNode(symbol, context, meaning)) + symbolToExpression: (symbol, meaning, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => symbolToExpression(symbol, context, meaning)), + symbolToTypeParameterDeclarations: (symbol, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => typeParametersToTypeParameterDeclarations(symbol, context)), + symbolToParameterDeclaration: (symbol, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => symbolToParameterDeclaration(symbol, context)), + typeParameterToDeclaration: (parameter, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => typeParameterToDeclaration(parameter, context)), + symbolTableToDeclarationStatements: (symbolTable, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => symbolTableToDeclarationStatements(symbolTable, context)), + symbolToNode: (symbol, meaning, enclosingDeclaration, flags, internalFlags, tracker) => withContext2(enclosingDeclaration, flags, internalFlags, tracker, (context) => symbolToNode(symbol, context, meaning)) }; function getTypeFromTypeNode2(context, node, noMappedTypes) { const type = getTypeFromTypeNodeWithoutContext(node); @@ -54254,19 +54489,26 @@ function createTypeChecker(host) { if (!location) { return range; } - if (!context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(getOriginalNode(location))) { - return setOriginalNode(range, location); + let original = range.original; + while (original && original !== location) { + original = original.original; } - return setTextRange(setOriginalNode(range, location), location); + if (!original) { + setOriginalNode(range, location); + } + if (context.enclosingFile && context.enclosingFile === getSourceFileOfNode(getOriginalNode(location))) { + return setTextRange(range, location); + } + return range; } function expressionOrTypeToTypeNode(context, expr, type, addUndefined) { - const oldFlags = context.flags; - if (expr && !(context.flags & -2147483648 /* NoSyntacticPrinter */)) { + const restoreFlags = saveRestoreFlags(context); + if (expr && !(context.internalFlags & 2 /* NoSyntacticPrinter */)) { syntacticNodeBuilder.serializeTypeOfExpression(expr, context, addUndefined); } - context.flags |= -2147483648 /* NoSyntacticPrinter */; + context.internalFlags |= 2 /* NoSyntacticPrinter */; const result = expressionOrTypeToTypeNodeHelper(context, expr, type, addUndefined); - context.flags = oldFlags; + restoreFlags(); return result; } function expressionOrTypeToTypeNodeHelper(context, expr, type, addUndefined) { @@ -54287,11 +54529,11 @@ function createTypeChecker(host) { function tryReuseExistingTypeNode(context, typeNode, type, host2, addUndefined) { const originalType = type; if (addUndefined) { - type = getOptionalType(type); + type = getOptionalType(type, !isParameter(host2)); } const clone2 = tryReuseExistingNonParameterTypeNode(context, typeNode, type, host2); if (clone2) { - if (addUndefined && !someType(getTypeFromTypeNode2(context, typeNode), (t) => !!(t.flags & 32768 /* Undefined */))) { + if (addUndefined && containsNonMissingUndefinedType(type) && !someType(getTypeFromTypeNode2(context, typeNode), (t) => !!(t.flags & 32768 /* Undefined */))) { return factory.createUnionTypeNode([clone2, factory.createKeywordTypeNode(157 /* UndefinedKeyword */)]); } return clone2; @@ -54319,7 +54561,7 @@ function createTypeChecker(host) { return void 0; } function symbolToNode(symbol, context, meaning) { - if (context.flags & 1073741824 /* WriteComputedProps */) { + if (context.internalFlags & 1 /* WriteComputedProps */) { if (symbol.valueDeclaration) { const name = getNameOfDeclaration(symbol.valueDeclaration); if (name && isComputedPropertyName(name)) return name; @@ -54332,12 +54574,13 @@ function createTypeChecker(host) { } return symbolToExpression(symbol, context, meaning); } - function withContext2(enclosingDeclaration, flags, tracker, cb) { - const moduleResolverHost = (tracker == null ? void 0 : tracker.trackSymbol) ? tracker.moduleResolverHost : flags & 134217728 /* DoNotIncludeSymbolChain */ ? createBasicNodeBuilderModuleSpecifierResolutionHost(host) : void 0; + function withContext2(enclosingDeclaration, flags, internalFlags, tracker, cb) { + const moduleResolverHost = (tracker == null ? void 0 : tracker.trackSymbol) ? tracker.moduleResolverHost : (internalFlags || 0 /* None */) & 4 /* DoNotIncludeSymbolChain */ ? createBasicNodeBuilderModuleSpecifierResolutionHost(host) : void 0; const context = { enclosingDeclaration, enclosingFile: enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration), flags: flags || 0 /* None */, + internalFlags: internalFlags || 0 /* None */, tracker: void 0, encounteredError: false, reportedDiagnostic: false, @@ -54367,14 +54610,23 @@ function createTypeChecker(host) { } return context.encounteredError ? void 0 : resultingNode; } + function saveRestoreFlags(context) { + const flags = context.flags; + const internalFlags = context.internalFlags; + return restore; + function restore() { + context.flags = flags; + context.internalFlags = internalFlags; + } + } function checkTruncationLength(context) { if (context.truncating) return context.truncating; return context.truncating = context.approximateLength > (context.flags & 1 /* NoTruncation */ ? noTruncationMaximumTruncationLength : defaultMaximumTruncationLength); } function typeToTypeNodeHelper(type, context) { - const savedFlags = context.flags; + const restoreFlags = saveRestoreFlags(context); const typeNode = typeToTypeNodeWorker(type, context); - context.flags = savedFlags; + restoreFlags(); return typeNode; } function typeToTypeNodeWorker(type, context) { @@ -54828,7 +55080,7 @@ function createTypeChecker(host) { context.symbolDepth = /* @__PURE__ */ new Map(); } const links = context.enclosingDeclaration && getNodeLinks(context.enclosingDeclaration); - const key = `${getTypeId(type2)}|${context.flags}`; + const key = `${getTypeId(type2)}|${context.flags}|${context.internalFlags}`; if (links) { links.serializedTypes || (links.serializedTypes = /* @__PURE__ */ new Map()); } @@ -54934,10 +55186,10 @@ function createTypeChecker(host) { } return typeToTypeNodeHelper(getIntersectionType(types), context); } - const savedFlags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags |= 4194304 /* InObjectTypeLiteral */; const members = createTypeNodesFromResolvedType(resolved); - context.flags = savedFlags; + restoreFlags(); const typeLiteralNode = factory.createTypeLiteralNode(members); context.approximateLength += 2; setEmitFlags(typeLiteralNode, context.flags & 1024 /* MultilineObjectLiterals */ ? 0 : 1 /* SingleLine */); @@ -55000,23 +55252,51 @@ function createTypeChecker(host) { } while (i < length2 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent2); if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) { const typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); - const flags2 = context.flags; + const restoreFlags2 = saveRestoreFlags(context); context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; const ref = symbolToTypeNode(parent2, context, 788968 /* Type */, typeArgumentSlice); - context.flags = flags2; + restoreFlags2(); resultType = !resultType ? ref : appendReferenceToType(resultType, ref); } } } let typeArgumentNodes; if (typeArguments.length > 0) { - const typeParameterCount = (type2.target.typeParameters || emptyArray).length; + let typeParameterCount = 0; + if (type2.target.typeParameters) { + typeParameterCount = Math.min(type2.target.typeParameters.length, typeArguments.length); + if (isReferenceToType2(type2, getGlobalIterableType( + /*reportErrors*/ + false + )) || isReferenceToType2(type2, getGlobalIterableIteratorType( + /*reportErrors*/ + false + )) || isReferenceToType2(type2, getGlobalAsyncIterableType( + /*reportErrors*/ + false + )) || isReferenceToType2(type2, getGlobalAsyncIterableIteratorType( + /*reportErrors*/ + false + ))) { + if (!type2.node || !isTypeReferenceNode(type2.node) || !type2.node.typeArguments || type2.node.typeArguments.length < typeParameterCount) { + while (typeParameterCount > 0) { + const typeArgument = typeArguments[typeParameterCount - 1]; + const typeParameter = type2.target.typeParameters[typeParameterCount - 1]; + const defaultType = getDefaultFromTypeParameter(typeParameter); + if (!defaultType || !isTypeIdenticalTo(typeArgument, defaultType)) { + break; + } + typeParameterCount--; + } + } + } + } typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context); } - const flags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; const finalRef = symbolToTypeNode(type2.symbol, context, 788968 /* Type */, typeArgumentNodes); - context.flags = flags; + restoreFlags(); return !resultType ? finalRef : appendReferenceToType(resultType, finalRef); } } @@ -55151,7 +55431,21 @@ function createTypeChecker(host) { } function shouldUsePlaceholderForProperty(propertySymbol, context) { var _a; - return !!(getCheckFlags(propertySymbol) & 8192 /* ReverseMapped */) && (contains(context.reverseMappedStack, propertySymbol) || ((_a = context.reverseMappedStack) == null ? void 0 : _a[0]) && !(getObjectFlags(last(context.reverseMappedStack).links.propertyType) & 16 /* Anonymous */)); + const depth = 3; + return !!(getCheckFlags(propertySymbol) & 8192 /* ReverseMapped */) && (contains(context.reverseMappedStack, propertySymbol) || ((_a = context.reverseMappedStack) == null ? void 0 : _a[0]) && !(getObjectFlags(last(context.reverseMappedStack).links.propertyType) & 16 /* Anonymous */) || isDeeplyNestedReverseMappedTypeProperty()); + function isDeeplyNestedReverseMappedTypeProperty() { + var _a2; + if ((((_a2 = context.reverseMappedStack) == null ? void 0 : _a2.length) ?? 0) < depth) { + return false; + } + for (let i = 0; i < depth; i++) { + const prop = context.reverseMappedStack[context.reverseMappedStack.length - 1 - i]; + if (prop.links.mappedType.symbol !== propertySymbol.links.mappedType.symbol) { + return false; + } + } + return true; + } } function addPropertyToElementList(propertySymbol, context, typeElements) { var _a; @@ -55314,7 +55608,7 @@ function createTypeChecker(host) { } } if (seenNames) { - const saveContextFlags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags |= 64 /* UseFullyQualifiedType */; seenNames.forEach((types2) => { if (!arrayIsHomogeneous(types2, ([a], [b]) => typesAreSameReference(a, b))) { @@ -55323,7 +55617,7 @@ function createTypeChecker(host) { } } }); - context.flags = saveContextFlags; + restoreFlags(); } return result; } @@ -55375,19 +55669,19 @@ function createTypeChecker(host) { } else { typeParameters = signature.typeParameters && signature.typeParameters.map((parameter) => typeParameterToDeclaration(parameter, context)); } - const flags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags &= ~256 /* SuppressAnyReturnType */; const parameters = (some(expandedParams, (p) => p !== expandedParams[expandedParams.length - 1] && !!(getCheckFlags(p) & 32768 /* RestParameter */)) ? signature.parameters : expandedParams).map((parameter) => symbolToParameterDeclaration(parameter, context, kind === 176 /* Constructor */)); const thisParameter = context.flags & 33554432 /* OmitThisParameter */ ? void 0 : tryGetThisParameterDeclaration(signature, context); if (thisParameter) { parameters.unshift(thisParameter); } - context.flags = flags; + restoreFlags(); const returnTypeNode = serializeReturnTypeForSignature(context, signature); let modifiers = options == null ? void 0 : options.modifiers; if (kind === 185 /* ConstructorType */ && signature.flags & 4 /* Abstract */) { - const flags2 = modifiersToFlags(modifiers); - modifiers = factory.createModifiersFromModifierFlags(flags2 | 64 /* Abstract */); + const flags = modifiersToFlags(modifiers); + modifiers = factory.createModifiersFromModifierFlags(flags | 64 /* Abstract */); } const node = kind === 179 /* CallSignature */ ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) : kind === 180 /* ConstructSignature */ ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) : kind === 173 /* MethodSignature */ ? factory.createMethodSignature(modifiers, (options == null ? void 0 : options.name) ?? factory.createIdentifier(""), options == null ? void 0 : options.questionToken, typeParameters, parameters, returnTypeNode) : kind === 174 /* MethodDeclaration */ ? factory.createMethodDeclaration( modifiers, @@ -55607,13 +55901,13 @@ function createTypeChecker(host) { } } function typeParameterToDeclarationWithConstraint(type, context, constraintNode) { - const savedContextFlags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; const modifiers = factory.createModifiersFromModifierFlags(getTypeParameterModifiers(type)); const name = typeParameterToName(type, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); - context.flags = savedContextFlags; + restoreFlags(); return factory.createTypeParameterDeclaration(modifiers, name, constraintNode, defaultParameterNode); } function typeToTypeNodeHelperWithPossibleReusableTypeNode(type, typeNode, context) { @@ -55717,7 +56011,7 @@ function createTypeChecker(host) { function lookupSymbolChainWorker(symbol, context, meaning, yieldModuleSymbol) { let chain; const isTypeParameter = symbol.flags & 262144 /* TypeParameter */; - if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64 /* UseFullyQualifiedType */) && !(context.flags & 134217728 /* DoNotIncludeSymbolChain */)) { + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64 /* UseFullyQualifiedType */) && !(context.internalFlags & 4 /* DoNotIncludeSymbolChain */)) { chain = Debug.checkDefined(getSymbolChain( symbol, meaning, @@ -55853,8 +56147,10 @@ function createTypeChecker(host) { } return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)).fileName; } + const enclosingDeclaration = getOriginalNode(context.enclosingDeclaration); + const originalModuleSpecifier = canHaveModuleSpecifier(enclosingDeclaration) ? tryGetModuleSpecifierFromDeclaration(enclosingDeclaration) : void 0; const contextFile = context.enclosingFile; - const resolutionMode = overrideImportMode || (contextFile == null ? void 0 : contextFile.impliedNodeFormat); + const resolutionMode = overrideImportMode || originalModuleSpecifier && host.getModeForUsageLocation(contextFile, originalModuleSpecifier) || contextFile && host.getDefaultResolutionModeForFile(contextFile); const cacheKey = createModeAwareCacheKey(contextFile.path, resolutionMode); const links = getSymbolLinks(symbol); let specifier = links.specifierCache && links.specifierCache.get(cacheKey); @@ -55896,14 +56192,6 @@ function createTypeChecker(host) { if (getEmitModuleResolutionKind(compilerOptions) === 3 /* Node16 */ || getEmitModuleResolutionKind(compilerOptions) === 99 /* NodeNext */) { if ((targetFile == null ? void 0 : targetFile.impliedNodeFormat) === 99 /* ESNext */ && targetFile.impliedNodeFormat !== (contextFile == null ? void 0 : contextFile.impliedNodeFormat)) { specifier = getSpecifierForModuleSymbol(chain[0], context, 99 /* ESNext */); - attributes = factory.createImportAttributes( - factory.createNodeArray([ - factory.createImportAttribute( - factory.createStringLiteral("resolution-mode"), - factory.createStringLiteral("import") - ) - ]) - ); } } if (!specifier) { @@ -56238,21 +56526,22 @@ function createTypeChecker(host) { return enclosingDeclaration; } function serializeTypeForDeclaration(context, declaration, type, symbol) { - var _a; - const addUndefined = declaration && (isParameter(declaration) || isJSDocParameterTag(declaration)) && requiresAddingImplicitUndefined(declaration); + var _a, _b; + const addUndefinedForParameter = declaration && (isParameter(declaration) || isJSDocParameterTag(declaration)) && requiresAddingImplicitUndefined(declaration, context.enclosingDeclaration); const enclosingDeclaration = context.enclosingDeclaration; - const oldFlags = context.flags; - if (declaration && hasInferredType(declaration) && !(context.flags & -2147483648 /* NoSyntacticPrinter */)) { + const restoreFlags = saveRestoreFlags(context); + if (declaration && hasInferredType(declaration) && !(context.internalFlags & 2 /* NoSyntacticPrinter */)) { syntacticNodeBuilder.serializeTypeOfDeclaration(declaration, context); } - context.flags |= -2147483648 /* NoSyntacticPrinter */; - if (enclosingDeclaration && (!isErrorType(type) || context.flags & 1 /* AllowUnresolvedNames */)) { + context.internalFlags |= 2 /* NoSyntacticPrinter */; + if (enclosingDeclaration && (!isErrorType(type) || context.internalFlags & 8 /* AllowUnresolvedNames */)) { const declWithExistingAnnotation = declaration && getNonlocalEffectiveTypeAnnotationNode(declaration) ? declaration : getDeclarationWithTypeAnnotation(symbol); if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) { const existing = getNonlocalEffectiveTypeAnnotationNode(declWithExistingAnnotation); + const addUndefined = addUndefinedForParameter || !!(symbol.flags & 4 /* Property */ && symbol.flags & 16777216 /* Optional */ && isOptionalDeclaration(declWithExistingAnnotation) && ((_a = symbol.links) == null ? void 0 : _a.mappedType) && containsNonMissingUndefinedType(type)); const result2 = !isTypePredicateNode(existing) && tryReuseExistingTypeNode(context, existing, type, declWithExistingAnnotation, addUndefined); if (result2) { - context.flags = oldFlags; + restoreFlags(); return result2; } } @@ -56260,10 +56549,10 @@ function createTypeChecker(host) { if (type.flags & 8192 /* UniqueESSymbol */ && type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, (d) => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration)))) { context.flags |= 1048576 /* AllowUniqueESSymbolType */; } - const decl = declaration ?? symbol.valueDeclaration ?? ((_a = symbol.declarations) == null ? void 0 : _a[0]); + const decl = declaration ?? symbol.valueDeclaration ?? ((_b = symbol.declarations) == null ? void 0 : _b[0]); const expr = decl && isDeclarationWithPossibleInnerTypeNodeReuse(decl) ? getPossibleTypeNodeReuseExpression(decl) : void 0; - const result = expressionOrTypeToTypeNode(context, expr, type, addUndefined); - context.flags = oldFlags; + const result = expressionOrTypeToTypeNode(context, expr, type, addUndefinedForParameter); + restoreFlags(); return result; } function typeNodeIsEquivalentToType(annotatedDeclaration, type, typeFromTypeNode) { @@ -56277,29 +56566,29 @@ function createTypeChecker(host) { } function serializeReturnTypeForSignature(context, signature) { const suppressAny = context.flags & 256 /* SuppressAnyReturnType */; - const flags = context.flags; + const restoreFlags = saveRestoreFlags(context); if (suppressAny) context.flags &= ~256 /* SuppressAnyReturnType */; let returnTypeNode; const returnType = getReturnTypeOfSignature(signature); if (returnType && !(suppressAny && isTypeAny(returnType))) { - if (signature.declaration && !(context.flags & -2147483648 /* NoSyntacticPrinter */)) { + if (signature.declaration && !(context.internalFlags & 2 /* NoSyntacticPrinter */)) { syntacticNodeBuilder.serializeReturnTypeForSignature(signature.declaration, context); } - context.flags |= -2147483648 /* NoSyntacticPrinter */; + context.internalFlags |= 2 /* NoSyntacticPrinter */; returnTypeNode = serializeReturnTypeForSignatureWorker(context, signature); } else if (!suppressAny) { returnTypeNode = factory.createKeywordTypeNode(133 /* AnyKeyword */); } - context.flags = flags; + restoreFlags(); return returnTypeNode; } function serializeReturnTypeForSignatureWorker(context, signature) { const typePredicate = getTypePredicateOfSignature(signature); const type = getReturnTypeOfSignature(signature); - if (context.enclosingDeclaration && (!isErrorType(type) || context.flags & 1 /* AllowUnresolvedNames */) && signature.declaration && !nodeIsSynthesized(signature.declaration)) { - const annotation = signature.declaration && getNonlocalEffectiveReturnTypeAnnotationNode(signature.declaration); - if (annotation && getTypeFromTypeNode2(context, annotation) === type) { - const result = tryReuseExistingTypeNodeHelper(context, annotation); + if (context.enclosingDeclaration && (!isErrorType(type) || context.internalFlags & 8 /* AllowUnresolvedNames */) && signature.declaration && !nodeIsSynthesized(signature.declaration)) { + const annotation = getNonlocalEffectiveReturnTypeAnnotationNode(signature.declaration); + if (annotation) { + const result = tryReuseExistingTypeNode(context, annotation, type, context.enclosingDeclaration); if (result) { return result; } @@ -56370,6 +56659,8 @@ function createTypeChecker(host) { } introducesError = true; return { introducesError, node, sym }; + } else { + sym = symAtLocation; } } if (sym) { @@ -56793,7 +57084,10 @@ function createTypeChecker(host) { ); } if (isNamedDeclaration(node) && node.name.kind === 167 /* ComputedPropertyName */ && !isLateBindableName(node.name)) { - if (!(context.flags & 1 /* AllowUnresolvedNames */ && hasDynamicName(node) && isEntityNameExpression(node.name.expression) && checkComputedPropertyName(node.name).flags & 1 /* Any */)) { + if (!hasDynamicName(node)) { + return visitEachChild2(node, visitExistingNodeTreeSymbols); + } + if (!(context.internalFlags & 8 /* AllowUnresolvedNames */ && isEntityNameExpression(node.name.expression) && checkComputedPropertyName(node.name).flags & 1 /* Any */)) { return void 0; } } @@ -56923,7 +57217,7 @@ function createTypeChecker(host) { if (result) { if (result.pos !== -1 || result.end !== -1) { if (result === nodes) { - result = factory.createNodeArray(nodes, nodes.hasTrailingComma); + result = factory.createNodeArray(nodes.slice(), nodes.hasTrailingComma); } setTextRangePosEnd(result, -1, -1); } @@ -57144,9 +57438,10 @@ function createTypeChecker(host) { if (index >= 0) { const exportDecl = statements[index]; const replacements = mapDefined(exportDecl.exportClause.elements, (e) => { - if (!e.propertyName) { + if (!e.propertyName && e.name.kind !== 11 /* StringLiteral */) { + const name = e.name; const indices = indicesOf(statements); - const associatedIndices = filter(indices, (i) => nodeHasName(statements[i], e.name)); + const associatedIndices = filter(indices, (i) => nodeHasName(statements[i], name)); if (length(associatedIndices) && every(associatedIndices, (i) => canHaveExportModifier(statements[i]))) { for (const index2 of associatedIndices) { statements[index2] = addExportModifier(statements[index2]); @@ -57444,7 +57739,7 @@ function createTypeChecker(host) { const typeParamDecls = map(typeParams, (p) => typeParameterToDeclaration(p, context)); const jsdocAliasDecl = (_a2 = symbol.declarations) == null ? void 0 : _a2.find(isJSDocTypeAlias); const commentText = getTextOfJSDocComment(jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : void 0); - const oldFlags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags |= 8388608 /* InTypeAlias */; const oldEnclosingDecl = context.enclosingDeclaration; context.enclosingDeclaration = jsdocAliasDecl; @@ -57468,7 +57763,7 @@ function createTypeChecker(host) { ), modifierFlags ); - context.flags = oldFlags; + restoreFlags(); context.enclosingDeclaration = oldEnclosingDecl; } function serializeInterface(symbol, symbolName2, modifierFlags) { @@ -57780,7 +58075,7 @@ function createTypeChecker(host) { function getSomeTargetNameFromDeclarations(declarations) { return firstDefined(declarations, (d) => { if (isImportSpecifier(d) || isExportSpecifier(d)) { - return idText(d.propertyName || d.name); + return moduleExportNameTextUnescaped(d.propertyName || d.name); } if (isBinaryExpression(d) || isExportAssignment(d)) { const expression = isExportAssignment(d) ? d.expression : d.right; @@ -57788,7 +58083,7 @@ function createTypeChecker(host) { return idText(expression.name); } } - if (isAliasSymbolDeclaration2(d)) { + if (isAliasSymbolDeclaration(d)) { const name = getNameOfDeclaration(d); if (name && isIdentifier(name)) { return idText(name); @@ -57798,7 +58093,7 @@ function createTypeChecker(host) { }); } function serializeAsAlias(symbol, localName, modifierFlags) { - var _a2, _b, _c, _d, _e, _f; + var _a2, _b, _c, _d, _e; const node = getDeclarationOfAliasSymbol(symbol); if (!node) return Debug.fail(); const target = getMergedSymbol(getTargetOfAliasDeclaration( @@ -57996,8 +58291,11 @@ function createTypeChecker(host) { } case 281 /* ExportSpecifier */: const specifier = node.parent.parent.moduleSpecifier; - if (specifier && ((_f = node.propertyName) == null ? void 0 : _f.escapedText) === "default" /* Default */) { - verbatimTargetName = "default" /* Default */; + if (specifier) { + const propertyName = node.propertyName; + if (propertyName && moduleExportNameIsDefault(propertyName)) { + verbatimTargetName = "default" /* Default */; + } } serializeExportSpecifier( unescapeLeadingUnderscores(symbol.escapedName), @@ -58474,10 +58772,10 @@ function createTypeChecker(host) { } function getNameCandidateWorker(symbol, localName) { if (localName === "default" /* Default */ || localName === "__class" /* Class */ || localName === "__function" /* Function */) { - const flags = context.flags; + const restoreFlags = saveRestoreFlags(context); context.flags |= 16777216 /* InInitialEntityName */; const nameCandidate = getNameOfSymbolAsWritten(symbol, context); - context.flags = flags; + restoreFlags(); localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? stripQuotes(nameCandidate) : nameCandidate; } if (localName === "default" /* Default */) { @@ -58485,7 +58783,7 @@ function createTypeChecker(host) { } else if (localName === "export=" /* ExportEquals */) { localName = "_exports"; } - localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_"); + localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-z0-9]/gi, "_"); return localName; } function getInternalSymbolName(symbol, localName) { @@ -58710,7 +59008,7 @@ function createTypeChecker(host) { } function collectLinkedAliases(node, setVisibility) { let exportSymbol; - if (node.parent && node.parent.kind === 277 /* ExportAssignment */) { + if (node.kind !== 11 /* StringLiteral */ && node.parent && node.parent.kind === 277 /* ExportAssignment */) { exportSymbol = resolveName( node, node, @@ -58995,6 +59293,7 @@ function createTypeChecker(host) { } else if (strictNullChecks && pattern.parent.initializer && !hasTypeFacts(getTypeOfInitializer(pattern.parent.initializer), 65536 /* EQUndefined */)) { parentType = getTypeWithFacts(parentType, 524288 /* NEUndefined */); } + const accessFlags = 32 /* ExpressionPosition */ | (noTupleBoundsCheck || hasDefaultValue(declaration) ? 16 /* AllowMissing */ : 0); let type; if (pattern.kind === 206 /* ObjectBindingPattern */) { if (declaration.dotDotDotToken) { @@ -59013,7 +59312,7 @@ function createTypeChecker(host) { } else { const name = declaration.propertyName || declaration.name; const indexType = getLiteralTypeFromPropertyName(name); - const declaredType = getIndexedAccessType(parentType, indexType, 32 /* ExpressionPosition */, name); + const declaredType = getIndexedAccessType(parentType, indexType, accessFlags, name); type = getFlowTypeOfDestructuring(declaration, declaredType); } } else { @@ -59024,7 +59323,6 @@ function createTypeChecker(host) { type = everyType(baseConstraint, isTupleType) ? mapType(baseConstraint, (t) => sliceTupleType(t, index)) : createArrayType(elementType); } else if (isArrayLikeType(parentType)) { const indexType = getNumberLiteralType(index); - const accessFlags = 32 /* ExpressionPosition */ | (noTupleBoundsCheck || hasDefaultValue(declaration) ? 16 /* NoTupleBoundsCheck */ : 0); const declaredType = getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.name) || errorType; type = getFlowTypeOfDestructuring(declaration, declaredType); } else { @@ -59510,7 +59808,7 @@ function createTypeChecker(host) { /*reportErrors*/ false ) : unknownType; - return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, reportErrors2 ? 0 /* Normal */ : 1 /* Contextual */, contextualType))); + return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, 0 /* Normal */, contextualType))); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors2); @@ -59581,7 +59879,10 @@ function createTypeChecker(host) { return result; } function getTypeFromBindingPattern(pattern, includePatternInType = false, reportErrors2 = false) { - return pattern.kind === 206 /* ObjectBindingPattern */ ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors2) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors2); + if (includePatternInType) contextualBindingPatterns.push(pattern); + const result = pattern.kind === 206 /* ObjectBindingPattern */ ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors2) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors2); + if (includePatternInType) contextualBindingPatterns.pop(); + return result; } function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors2) { return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration( @@ -59662,18 +59963,18 @@ function createTypeChecker(host) { } return false; } - function getTypeOfVariableOrParameterOrProperty(symbol, checkMode) { + function getTypeOfVariableOrParameterOrProperty(symbol) { const links = getSymbolLinks(symbol); if (!links.type) { - const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol, checkMode); - if (!links.type && !isParameterOfContextSensitiveSignature(symbol) && !checkMode) { + const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol); + if (!links.type && !isParameterOfContextSensitiveSignature(symbol)) { links.type = type; } return type; } return links.type; } - function getTypeOfVariableOrParameterOrPropertyWorker(symbol, checkMode) { + function getTypeOfVariableOrParameterOrPropertyWorker(symbol) { if (symbol.flags & 4194304 /* Prototype */) { return getTypeOfPrototypeProperty(symbol); } @@ -59708,9 +60009,6 @@ function createTypeChecker(host) { if (symbol.flags & 512 /* ValueModule */ && !(symbol.flags & 67108864 /* Assignment */)) { return getTypeOfFuncClassEnumModule(symbol); } - if (isBindingElement(declaration) && checkMode === 1 /* Contextual */) { - return errorType; - } return reportCircularityError(symbol); } let type; @@ -59748,9 +60046,6 @@ function createTypeChecker(host) { if (symbol.flags & 512 /* ValueModule */ && !(symbol.flags & 67108864 /* Assignment */)) { return getTypeOfFuncClassEnumModule(symbol); } - if (isBindingElement(declaration) && checkMode === 1 /* Contextual */) { - return type; - } return reportCircularityError(symbol); } return type; @@ -59979,7 +60274,7 @@ function createTypeChecker(host) { } return getTypeOfSymbol(symbol); } - function getTypeOfSymbol(symbol, checkMode) { + function getTypeOfSymbol(symbol) { const checkFlags = getCheckFlags(symbol); if (checkFlags & 65536 /* DeferredType */) { return getTypeOfSymbolWithDeferredType(symbol); @@ -59994,7 +60289,7 @@ function createTypeChecker(host) { return getTypeOfReverseMappedSymbol(symbol); } if (symbol.flags & (3 /* Variable */ | 4 /* Property */)) { - return getTypeOfVariableOrParameterOrProperty(symbol, checkMode); + return getTypeOfVariableOrParameterOrProperty(symbol); } if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) { return getTypeOfFuncClassEnumModule(symbol); @@ -60013,6 +60308,17 @@ function createTypeChecker(host) { function getNonMissingTypeOfSymbol(symbol) { return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & 16777216 /* Optional */)); } + function isReferenceToSomeType(type, targets) { + if (type === void 0 || (getObjectFlags(type) & 4 /* Reference */) === 0) { + return false; + } + for (const target of targets) { + if (type.target === target) { + return true; + } + } + return false; + } function isReferenceToType2(type, target) { return type !== void 0 && target !== void 0 && (getObjectFlags(type) & 4 /* Reference */) !== 0 && type.target === target; } @@ -60052,7 +60358,8 @@ function createTypeChecker(host) { if (!node) { return void 0; } - switch (node.kind) { + const kind = node.kind; + switch (kind) { case 263 /* ClassDeclaration */: case 231 /* ClassExpression */: case 264 /* InterfaceDeclaration */: @@ -60074,13 +60381,19 @@ function createTypeChecker(host) { case 200 /* MappedType */: case 194 /* ConditionalType */: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); - if (node.kind === 200 /* MappedType */) { + if ((kind === 218 /* FunctionExpression */ || kind === 219 /* ArrowFunction */ || isObjectLiteralMethod(node)) && isContextSensitive(node)) { + const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfDeclaration(node)), 0 /* Call */)); + if (signature && signature.typeParameters) { + return [...outerTypeParameters || emptyArray, ...signature.typeParameters]; + } + } + if (kind === 200 /* MappedType */) { return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(node.typeParameter))); - } else if (node.kind === 194 /* ConditionalType */) { + } else if (kind === 194 /* ConditionalType */) { return concatenate(outerTypeParameters, getInferTypeParameters(node)); } const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node)); - const thisType = includeThisTypes && (node.kind === 263 /* ClassDeclaration */ || node.kind === 231 /* ClassExpression */ || node.kind === 264 /* InterfaceDeclaration */ || isJSConstructor(node)) && getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node)).thisType; + const thisType = includeThisTypes && (kind === 263 /* ClassDeclaration */ || kind === 231 /* ClassExpression */ || kind === 264 /* InterfaceDeclaration */ || isJSConstructor(node)) && getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node)).thisType; return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } case 341 /* JSDocParameterTag */: @@ -60434,6 +60747,9 @@ function createTypeChecker(host) { links.instantiations = /* @__PURE__ */ new Map(); links.instantiations.set(getTypeListId(typeParameters), type); } + if (type === intrinsicMarkerType && symbol.escapedName === "BuiltinIteratorReturn") { + type = getBuiltinIteratorReturnType(); + } } else { type = errorType; if (declaration.kind === 340 /* JSDocEnumTag */) { @@ -60898,18 +61214,18 @@ function createTypeChecker(host) { function getExpandedParameters(sig, skipUnionExpanding) { if (signatureHasRestParameter(sig)) { const restIndex = sig.parameters.length - 1; - const restName = sig.parameters[restIndex].escapedName; - const restType = getTypeOfSymbol(sig.parameters[restIndex]); + const restSymbol = sig.parameters[restIndex]; + const restType = getTypeOfSymbol(restSymbol); if (isTupleType(restType)) { - return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName)]; + return [expandSignatureParametersWithTupleMembers(restType, restIndex, restSymbol)]; } else if (!skipUnionExpanding && restType.flags & 1048576 /* Union */ && every(restType.types, isTupleType)) { - return map(restType.types, (t) => expandSignatureParametersWithTupleMembers(t, restIndex, restName)); + return map(restType.types, (t) => expandSignatureParametersWithTupleMembers(t, restIndex, restSymbol)); } } return [sig.parameters]; - function expandSignatureParametersWithTupleMembers(restType, restIndex, restName) { + function expandSignatureParametersWithTupleMembers(restType, restIndex, restSymbol) { const elementTypes = getTypeArguments(restType); - const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName); + const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restSymbol); const restParams = map(elementTypes, (t, i) => { const name = associatedNames && associatedNames[i] ? associatedNames[i] : getParameterNameAtPosition(sig, restIndex + i, restType); const flags = restType.target.elementFlags[i]; @@ -60920,19 +61236,29 @@ function createTypeChecker(host) { }); return concatenate(sig.parameters.slice(0, restIndex), restParams); } - function getUniqAssociatedNamesFromTupleType(type, restName) { - const associatedNamesMap = /* @__PURE__ */ new Map(); - return map(type.target.labeledElementDeclarations, (labeledElement, i) => { - const name = getTupleElementLabel(labeledElement, i, restName); - const prevCounter = associatedNamesMap.get(name); - if (prevCounter === void 0) { - associatedNamesMap.set(name, 1); - return name; - } else { - associatedNamesMap.set(name, prevCounter + 1); - return `${name}_${prevCounter}`; + function getUniqAssociatedNamesFromTupleType(type, restSymbol) { + const names = map(type.target.labeledElementDeclarations, (labeledElement, i) => getTupleElementLabel(labeledElement, i, type.target.elementFlags[i], restSymbol)); + if (names) { + const duplicates = []; + const uniqueNames = /* @__PURE__ */ new Set(); + for (let i = 0; i < names.length; i++) { + const name = names[i]; + if (!tryAddToSet(uniqueNames, name)) { + duplicates.push(i); + } } - }); + const counters = /* @__PURE__ */ new Map(); + for (const i of duplicates) { + let counter = counters.get(names[i]) ?? 1; + let name; + while (!tryAddToSet(uniqueNames, name = `${names[i]}_${counter}`)) { + counter++; + } + names[i] = name; + counters.set(names[i], counter + 1); + } + } + return names; } } function getDefaultConstructSignatures(classType) { @@ -62879,8 +63205,11 @@ function createTypeChecker(host) { true ); } + function getTypeParametersForMapper(signature) { + return sameMap(signature.typeParameters, (tp) => tp.mapper ? instantiateType(tp, tp.mapper) : tp); + } function createSignatureTypeMapper(signature, typeArguments) { - return createTypeMapper(signature.typeParameters, typeArguments); + return createTypeMapper(getTypeParametersForMapper(signature), typeArguments); } function getErasedSignature(signature) { return signature.typeParameters ? signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) : signature; @@ -63141,14 +63470,14 @@ function createTypeChecker(host) { var _a, _b; if (!type.resolvedTypeArguments) { if (!pushTypeResolution(type, 5 /* ResolvedTypeArguments */)) { - return ((_a = type.target.localTypeParameters) == null ? void 0 : _a.map(() => errorType)) || emptyArray; + return concatenate(type.target.outerTypeParameters, (_a = type.target.localTypeParameters) == null ? void 0 : _a.map(() => errorType)) || emptyArray; } const node = type.node; const typeArguments = !node ? emptyArray : node.kind === 183 /* TypeReference */ ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments2(node, type.target.localTypeParameters)) : node.kind === 188 /* ArrayType */ ? [getTypeFromTypeNode(node.elementType)] : map(node.elements, getTypeFromTypeNode); if (popTypeResolution()) { type.resolvedTypeArguments ?? (type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments); } else { - type.resolvedTypeArguments ?? (type.resolvedTypeArguments = ((_b = type.target.localTypeParameters) == null ? void 0 : _b.map(() => errorType)) || emptyArray); + type.resolvedTypeArguments ?? (type.resolvedTypeArguments = concatenate(type.target.outerTypeParameters, ((_b = type.target.localTypeParameters) == null ? void 0 : _b.map(() => errorType)) || emptyArray)); error2( type.node || currentNode, type.target.symbol ? Diagnostics.Type_arguments_for_0_circularly_reference_themselves : Diagnostics.Tuple_type_arguments_circularly_reference_themselves, @@ -63599,6 +63928,18 @@ function createTypeChecker(host) { const symbol = getGlobalTypeSymbol(name, reportErrors2); return symbol || reportErrors2 ? getTypeOfGlobalSymbol(symbol, arity) : void 0; } + function getGlobalBuiltinTypes(typeNames, arity) { + let types; + for (const typeName of typeNames) { + types = append(types, getGlobalType( + typeName, + arity, + /*reportErrors*/ + false + )); + } + return types ?? emptyArray; + } function getGlobalTypedPropertyDescriptorType() { return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType( "TypedPropertyDescriptor", @@ -63701,7 +64042,7 @@ function createTypeChecker(host) { return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType( "AsyncIterable", /*arity*/ - 1, + 3, reportErrors2 )) || emptyGenericType; } @@ -63717,7 +64058,18 @@ function createTypeChecker(host) { return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType( "AsyncIterableIterator", /*arity*/ - 1, + 3, + reportErrors2 + )) || emptyGenericType; + } + function getGlobalBuiltinAsyncIteratorTypes() { + return deferredGlobalBuiltinAsyncIteratorTypes ?? (deferredGlobalBuiltinAsyncIteratorTypes = getGlobalBuiltinTypes(["ReadableStreamAsyncIterator"], 1)); + } + function getGlobalAsyncIteratorObjectType(reportErrors2) { + return deferredGlobalAsyncIteratorObjectType || (deferredGlobalAsyncIteratorObjectType = getGlobalType( + "AsyncIteratorObject", + /*arity*/ + 3, reportErrors2 )) || emptyGenericType; } @@ -63733,7 +64085,7 @@ function createTypeChecker(host) { return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType( "Iterable", /*arity*/ - 1, + 3, reportErrors2 )) || emptyGenericType; } @@ -63749,7 +64101,21 @@ function createTypeChecker(host) { return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType( "IterableIterator", /*arity*/ - 1, + 3, + reportErrors2 + )) || emptyGenericType; + } + function getBuiltinIteratorReturnType() { + return strictBuiltinIteratorReturn ? undefinedType : anyType; + } + function getGlobalBuiltinIteratorTypes() { + return deferredGlobalBuiltinIteratorTypes ?? (deferredGlobalBuiltinIteratorTypes = getGlobalBuiltinTypes(["ArrayIterator", "MapIterator", "SetIterator", "StringIterator"], 1)); + } + function getGlobalIteratorObjectType(reportErrors2) { + return deferredGlobalIteratorObjectType || (deferredGlobalIteratorObjectType = getGlobalType( + "IteratorObject", + /*arity*/ + 3, reportErrors2 )) || emptyGenericType; } @@ -63931,7 +64297,7 @@ function createTypeChecker(host) { return createTypeFromGenericGlobalType(getGlobalIterableType( /*reportErrors*/ true - ), [iteratedType]); + ), [iteratedType, voidType, undefinedType]); } function createArrayType(elementType, readonly) { return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]); @@ -64595,6 +64961,12 @@ function createTypeChecker(host) { function eachUnionContains(unionTypes2, type) { for (const u of unionTypes2) { if (!containsType(u.types, type)) { + if (type === missingType) { + return containsType(u.types, undefinedType); + } + if (type === undefinedType) { + return containsType(u.types, missingType); + } const primitive = type.flags & 128 /* StringLiteral */ ? stringType : type.flags & (32 /* Enum */ | 256 /* NumberLiteral */) ? numberType : type.flags & 2048 /* BigIntLiteral */ ? bigintType : type.flags & 8192 /* UniqueESSymbol */ ? esSymbolType : void 0; if (!primitive || !containsType(u.types, primitive)) { return false; @@ -64651,6 +65023,13 @@ function createTypeChecker(host) { for (const t of u.types) { if (insertType(checked, t)) { if (eachUnionContains(unionTypes2, t)) { + if (t === undefinedType && result.length && result[0] === missingType) { + continue; + } + if (t === missingType && result.length && result[0] === undefinedType) { + result[0] = missingType; + continue; + } insertType(result, t); } } @@ -64735,7 +65114,7 @@ function createTypeChecker(host) { } else if (every(typeSet, (t) => !!(t.flags & 1048576 /* Union */ && (t.types[0].flags & 65536 /* Null */ || t.types[1].flags & 65536 /* Null */)))) { removeFromEach(typeSet, 65536 /* Null */); result = getUnionType([getIntersectionType(typeSet, flags), nullType], 1 /* Literal */, aliasSymbol, aliasTypeArguments); - } else if (typeSet.length >= 4) { + } else if (typeSet.length >= 3 && types.length > 2) { const middle = Math.floor(typeSet.length / 2); result = getIntersectionType([getIntersectionType(typeSet.slice(0, middle), flags), getIntersectionType(typeSet.slice(middle), flags)], flags, aliasSymbol, aliasTypeArguments); } else { @@ -65131,7 +65510,7 @@ function createTypeChecker(host) { } if (everyType(objectType, isTupleType) && isNumericLiteralName(propName)) { const index = +propName; - if (accessNode && everyType(objectType, (t) => !t.target.hasRestElement) && !(accessFlags & 16 /* NoTupleBoundsCheck */)) { + if (accessNode && everyType(objectType, (t) => !(t.target.combinedFlags & 12 /* Variable */)) && !(accessFlags & 16 /* AllowMissing */)) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (isTupleType(objectType)) { if (index < 0) { @@ -65272,17 +65651,21 @@ function createTypeChecker(host) { return void 0; } } + if (accessFlags & 16 /* AllowMissing */ && isObjectLiteralType2(objectType)) { + return undefinedType; + } if (isJSLiteralType(objectType)) { return anyType; } if (accessNode) { const indexNode = getIndexNodeForAccessExpression(accessNode); - if (indexType.flags & (128 /* StringLiteral */ | 256 /* NumberLiteral */)) { + if (indexNode.kind !== 10 /* BigIntLiteral */ && indexType.flags & (128 /* StringLiteral */ | 256 /* NumberLiteral */)) { error2(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + indexType.value, typeToString(objectType)); } else if (indexType.flags & (4 /* String */ | 8 /* Number */)) { error2(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); } else { - error2(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); + const typeString = indexNode.kind === 10 /* BigIntLiteral */ ? "bigint" : typeToString(indexType); + error2(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeString); } } if (isTypeAny(indexType)) { @@ -67525,6 +67908,10 @@ function createTypeChecker(host) { function containsUndefinedType(type) { return !!((type.flags & 1048576 /* Union */ ? type.types[0] : type).flags & 32768 /* Undefined */); } + function containsNonMissingUndefinedType(type) { + const candidate = type.flags & 1048576 /* Union */ ? type.types[0] : type; + return !!(candidate.flags & 32768 /* Undefined */) && candidate !== missingType; + } function isStringIndexSignatureOnlyType(type) { return type.flags & 524288 /* Object */ && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) || type.flags & 3145728 /* UnionOrIntersection */ && every(type.types, isStringIndexSignatureOnlyType) || false; } @@ -67539,7 +67926,7 @@ function createTypeChecker(host) { } const id = getSymbolId(sourceSymbol) + "," + getSymbolId(targetSymbol); const entry = enumRelation.get(id); - if (entry !== void 0 && !(!(entry & 4 /* Reported */) && entry & 2 /* Failed */ && errorReporter)) { + if (entry !== void 0 && !(entry & 2 /* Failed */ && errorReporter)) { return !!(entry & 1 /* Succeeded */); } const targetEnumType = getTypeOfSymbol(targetSymbol); @@ -67554,10 +67941,8 @@ function createTypeChecker(host) { void 0, 64 /* UseFullyQualifiedType */ )); - enumRelation.set(id, 2 /* Failed */ | 4 /* Reported */); - } else { - enumRelation.set(id, 2 /* Failed */); } + enumRelation.set(id, 2 /* Failed */); return false; } const sourceValue = getEnumMemberValue(getDeclarationOfKind(sourceProperty, 306 /* EnumMember */)).value; @@ -67566,26 +67951,22 @@ function createTypeChecker(host) { const sourceIsString = typeof sourceValue === "string"; const targetIsString = typeof targetValue === "string"; if (sourceValue !== void 0 && targetValue !== void 0) { - if (!errorReporter) { - enumRelation.set(id, 2 /* Failed */); - } else { + if (errorReporter) { const escapedSource = sourceIsString ? `"${escapeString(sourceValue)}"` : sourceValue; const escapedTarget = targetIsString ? `"${escapeString(targetValue)}"` : targetValue; errorReporter(Diagnostics.Each_declaration_of_0_1_differs_in_its_value_where_2_was_expected_but_3_was_given, symbolName(targetSymbol), symbolName(targetProperty), escapedTarget, escapedSource); - enumRelation.set(id, 2 /* Failed */ | 4 /* Reported */); } + enumRelation.set(id, 2 /* Failed */); return false; } if (sourceIsString || targetIsString) { - if (!errorReporter) { - enumRelation.set(id, 2 /* Failed */); - } else { + if (errorReporter) { const knownStringValue = sourceValue ?? targetValue; Debug.assert(typeof knownStringValue === "string"); const escapedValue = `"${escapeString(knownStringValue)}"`; errorReporter(Diagnostics.One_value_of_0_1_is_the_string_2_and_the_other_is_assumed_to_be_an_unknown_numeric_value, symbolName(targetSymbol), symbolName(targetProperty), escapedValue); - enumRelation.set(id, 2 /* Failed */ | 4 /* Reported */); } + enumRelation.set(id, 2 /* Failed */); return false; } } @@ -67743,7 +68124,7 @@ function createTypeChecker(host) { /*ignoreConstraints*/ false ); - relation.set(id, 4 /* Reported */ | 2 /* Failed */); + relation.set(id, 2 /* Failed */ | (relationCount <= 0 ? 32 /* ComplexityOverflow */ : 64 /* StackDepthOverflow */)); (_a = tracing) == null ? void 0 : _a.instant(tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth: sourceDepth, targetDepth }); const message = relationCount <= 0 ? Diagnostics.Excessive_complexity_comparing_types_0_and_1 : Diagnostics.Excessive_stack_depth_comparing_types_0_and_1; const diag2 = error2(errorNode || currentNode, message, typeToString(source), typeToString(target)); @@ -68596,7 +68977,7 @@ function createTypeChecker(host) { ); const entry = relation.get(id); if (entry !== void 0) { - if (reportErrors2 && entry & 2 /* Failed */ && !(entry & 4 /* Reported */)) { + if (reportErrors2 && entry & 2 /* Failed */ && !(entry & 96 /* Overflow */)) { } else { if (outofbandVarianceMarkerHandler) { const saved = entry & 24 /* ReportsMask */; @@ -68607,6 +68988,11 @@ function createTypeChecker(host) { instantiateType(source2, reportUnreliableMapper); } } + if (reportErrors2 && entry & 96 /* Overflow */) { + const message = entry & 32 /* ComplexityOverflow */ ? Diagnostics.Excessive_complexity_comparing_types_0_and_1 : Diagnostics.Excessive_stack_depth_comparing_types_0_and_1; + reportError(message, typeToString(source2), typeToString(target2)); + overrideNextErrorInfo++; + } return entry & 1 /* Succeeded */ ? -1 /* True */ : 0 /* False */; } } @@ -68704,7 +69090,7 @@ function createTypeChecker(host) { } } } else { - relation.set(id, (reportErrors2 ? 4 /* Reported */ : 0) | 2 /* Failed */ | propagatingVarianceFlags); + relation.set(id, 2 /* Failed */ | propagatingVarianceFlags); relationCount--; resetMaybeStack( /*markAllAsSucceeded*/ @@ -69597,7 +69983,7 @@ function createTypeChecker(host) { const sourceArity = getTypeReferenceArity(source2); const targetArity = getTypeReferenceArity(target2); const sourceRestFlag = isTupleType(source2) ? source2.target.combinedFlags & 4 /* Rest */ : 4 /* Rest */; - const targetRestFlag = target2.target.combinedFlags & 4 /* Rest */; + const targetHasRestElement = !!(target2.target.combinedFlags & 12 /* Variable */); const sourceMinLength = isTupleType(source2) ? source2.target.minLength : 0; const targetMinLength = target2.target.minLength; if (!sourceRestFlag && sourceArity < targetMinLength) { @@ -69606,13 +69992,13 @@ function createTypeChecker(host) { } return 0 /* False */; } - if (!targetRestFlag && targetArity < sourceMinLength) { + if (!targetHasRestElement && targetArity < sourceMinLength) { if (reportErrors2) { reportError(Diagnostics.Source_has_0_element_s_but_target_allows_only_1, sourceMinLength, targetArity); } return 0 /* False */; } - if (!targetRestFlag && (sourceRestFlag || targetArity < sourceArity)) { + if (!targetHasRestElement && (sourceRestFlag || targetArity < sourceArity)) { if (reportErrors2) { if (sourceMinLength < targetMinLength) { reportError(Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength); @@ -69626,7 +70012,6 @@ function createTypeChecker(host) { const targetTypeArguments = getTypeArguments(target2); const targetStartCount = getStartElementCount(target2.target, 11 /* NonRest */); const targetEndCount = getEndElementCount(target2.target, 11 /* NonRest */); - const targetHasRestElement = target2.target.hasRestElement; let canExcludeDiscriminants = !!excludedProperties; for (let sourcePosition = 0; sourcePosition < sourceArity; sourcePosition++) { const sourceFlags = isTupleType(source2) ? source2.target.elementFlags[sourcePosition] : 4 /* Rest */; @@ -70086,7 +70471,7 @@ function createTypeChecker(host) { for (let i = 0; i < types.length; i++) { if (include[i]) { const targetType = getTypeOfPropertyOrIndexSignatureOfType(types[i], propertyName); - if (targetType && related(getDiscriminatingType(), targetType)) { + if (targetType && someType(getDiscriminatingType(), (t) => !!related(t, targetType))) { matched = true; } else { include[i] = 3 /* Maybe */; @@ -70866,6 +71251,7 @@ function createTypeChecker(host) { return type; } function reportWideningErrorsInType(type) { + var _a; let errorReported = false; if (getObjectFlags(type) & 65536 /* ContainsWideningType */) { if (type.flags & 1048576 /* Union */) { @@ -70873,27 +71259,28 @@ function createTypeChecker(host) { errorReported = true; } else { for (const t of type.types) { - if (reportWideningErrorsInType(t)) { - errorReported = true; - } + errorReported || (errorReported = reportWideningErrorsInType(t)); } } - } - if (isArrayOrTupleType(type)) { + } else if (isArrayOrTupleType(type)) { for (const t of getTypeArguments(type)) { - if (reportWideningErrorsInType(t)) { - errorReported = true; - } + errorReported || (errorReported = reportWideningErrorsInType(t)); } - } - if (isObjectLiteralType2(type)) { + } else if (isObjectLiteralType2(type)) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); if (getObjectFlags(t) & 65536 /* ContainsWideningType */) { - if (!reportWideningErrorsInType(t)) { - error2(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + errorReported = reportWideningErrorsInType(t); + if (!errorReported) { + const valueDeclaration = (_a = p.declarations) == null ? void 0 : _a.find((d) => { + var _a2; + return ((_a2 = d.symbol.valueDeclaration) == null ? void 0 : _a2.parent) === type.symbol.valueDeclaration; + }); + if (valueDeclaration) { + error2(valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + errorReported = true; + } } - errorReported = true; } } } @@ -71173,11 +71560,11 @@ function createTypeChecker(host) { } function inferTypeForHomomorphicMappedType(source, target, constraint) { const cacheKey = source.id + "," + target.id + "," + constraint.id; - if (reverseMappedCache.has(cacheKey)) { - return reverseMappedCache.get(cacheKey); + if (reverseHomomorphicMappedCache.has(cacheKey)) { + return reverseHomomorphicMappedCache.get(cacheKey); } const type = createReverseMappedType(source, target, constraint); - reverseMappedCache.set(cacheKey, type); + reverseHomomorphicMappedCache.set(cacheKey, type); return type; } function isPartiallyInferableType(type) { @@ -71272,7 +71659,7 @@ function createTypeChecker(host) { return firstOrUndefinedIterator(getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties)); } function tupleTypesDefinitelyUnrelated(source, target) { - return !(target.target.combinedFlags & 8 /* Variadic */) && target.target.minLength > source.target.minLength || !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength); + return !(target.target.combinedFlags & 8 /* Variadic */) && target.target.minLength > source.target.minLength || !(target.target.combinedFlags & 12 /* Variable */) && (!!(source.target.combinedFlags & 12 /* Variable */) || target.target.fixedLength < source.target.fixedLength); } function typesDefinitelyUnrelated(source, target) { return isTupleType(source) && isTupleType(target) ? tupleTypesDefinitelyUnrelated(source, target) : !!getUnmatchedProperty( @@ -71361,7 +71748,7 @@ function createTypeChecker(host) { return false; } function inferTypesFromTemplateLiteralType(source, target) { - return source.flags & 128 /* StringLiteral */ ? inferFromLiteralPartsToTemplateLiteral([source.value], emptyArray, target) : source.flags & 134217728 /* TemplateLiteral */ ? arraysEqual(source.texts, target.texts) ? map(source.types, (s, i) => { + return source.flags & 128 /* StringLiteral */ ? inferFromLiteralPartsToTemplateLiteral([source.value], emptyArray, target) : source.flags & 134217728 /* TemplateLiteral */ ? arrayIsEqualTo(source.texts, target.texts) ? map(source.types, (s, i) => { return isTypeAssignableTo(getBaseConstraintOrType(s), getBaseConstraintOrType(target.types[i])) ? s : getStringLikeTypeForType(s); }) : inferFromLiteralPartsToTemplateLiteral(source.texts, source.types, target) : void 0; } @@ -71890,7 +72277,7 @@ function createTypeChecker(host) { return; } const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, 3 /* Fixed */) : 0, target.target.hasRestElement ? getEndElementCount(target.target, 3 /* Fixed */) : 0); + const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, 3 /* Fixed */) : 0, target.target.combinedFlags & 12 /* Variable */ ? getEndElementCount(target.target, 3 /* Fixed */) : 0); for (let i = 0; i < startLength; i++) { inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); } @@ -71911,7 +72298,7 @@ function createTypeChecker(host) { } else if (elementFlags[startLength] & 8 /* Variadic */ && elementFlags[startLength + 1] & 4 /* Rest */) { const param = (_a = getInferenceInfoForType(elementTypes[startLength])) == null ? void 0 : _a.typeParameter; const constraint = param && getBaseConstraintOfType(param); - if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { + if (constraint && isTupleType(constraint) && !(constraint.target.combinedFlags & 12 /* Variable */)) { const impliedArity = constraint.target.fixedLength; inferFromTypes(sliceTupleType(source, startLength, sourceArity - (startLength + impliedArity)), elementTypes[startLength]); inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength + impliedArity, endLength), elementTypes[startLength + 1]); @@ -71919,7 +72306,7 @@ function createTypeChecker(host) { } else if (elementFlags[startLength] & 4 /* Rest */ && elementFlags[startLength + 1] & 8 /* Variadic */) { const param = (_b = getInferenceInfoForType(elementTypes[startLength + 1])) == null ? void 0 : _b.typeParameter; const constraint = param && getBaseConstraintOfType(param); - if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { + if (constraint && isTupleType(constraint) && !(constraint.target.combinedFlags & 12 /* Variable */)) { const impliedArity = constraint.target.fixedLength; const endIndex = sourceArity - getEndElementCount(target.target, 3 /* Fixed */); const startIndex = endIndex - impliedArity; @@ -72071,7 +72458,7 @@ function createTypeChecker(host) { const inferredCovariantType = inference.candidates ? getCovariantInference(inference, context.signature) : void 0; const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) : void 0; if (inferredCovariantType || inferredContravariantType) { - const preferCovariantType = inferredCovariantType && (!inferredContravariantType || !(inferredCovariantType.flags & 131072 /* Never */) && some(inference.contraCandidates, (t) => isTypeSubtypeOf(inferredCovariantType, t)) && every(context.inferences, (other) => other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter || every(other.candidates, (t) => isTypeSubtypeOf(t, inferredCovariantType)))); + const preferCovariantType = inferredCovariantType && (!inferredContravariantType || !(inferredCovariantType.flags & (131072 /* Never */ | 1 /* Any */)) && some(inference.contraCandidates, (t) => isTypeAssignableTo(inferredCovariantType, t)) && every(context.inferences, (other) => other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter || every(other.candidates, (t) => isTypeAssignableTo(t, inferredCovariantType)))); inferredType = preferCovariantType ? inferredCovariantType : inferredContravariantType; fallbackType = preferCovariantType ? inferredContravariantType : inferredCovariantType; } else if (context.flags & 1 /* NoDefault */) { @@ -72458,6 +72845,9 @@ function createTypeChecker(host) { return isTypeAssignableTo(assignedType, reducedType) ? reducedType : declaredType; } function isFunctionObjectType(type) { + if (getObjectFlags(type) & 256 /* EvolvingArray */) { + return false; + } const resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || resolved.members.get("bind") && isTypeSubtypeOf(type, globalFunctionType)); } @@ -73525,7 +73915,7 @@ function createTypeChecker(host) { return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType))); } const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction)); - if (result !== declaredType && result.flags & declaredType.flags & 1048576 /* Union */ && arraysEqual(result.types, declaredType.types)) { + if (result !== declaredType && result.flags & declaredType.flags & 1048576 /* Union */ && arrayIsEqualTo(result.types, declaredType.types)) { return declaredType; } return result; @@ -74285,9 +74675,10 @@ function createTypeChecker(host) { return; case 281 /* ExportSpecifier */: const exportDeclaration = node.parent.parent; - if (!node.isTypeOnly && !exportDeclaration.isTypeOnly && !exportDeclaration.moduleSpecifier) { + const name = node.propertyName || node.name; + if (!node.isTypeOnly && !exportDeclaration.isTypeOnly && !exportDeclaration.moduleSpecifier && name.kind !== 11 /* StringLiteral */) { const symbol = resolveEntityName( - node.propertyName || node.name, + name, 111551 /* Value */, /*ignoreErrors*/ true, @@ -74405,7 +74796,7 @@ function createTypeChecker(host) { if (!canCollectSymbolAliasAccessabilityData) { return; } - if (location.flags & 33554432 /* Ambient */) { + if (location.flags & 33554432 /* Ambient */ && !isPropertySignature(location) && !isPropertyDeclaration(location)) { return; } switch (hint) { @@ -74581,6 +74972,9 @@ function createTypeChecker(host) { function markExportSpecifierAliasReferenced(location) { if (!location.parent.parent.moduleSpecifier && !location.isTypeOnly && !location.parent.parent.isTypeOnly) { const exportedName = location.propertyName || location.name; + if (exportedName.kind === 11 /* StringLiteral */) { + return; + } const symbol = resolveName( exportedName, exportedName.escapedText, @@ -74595,7 +74989,7 @@ function createTypeChecker(host) { const target = symbol && (symbol.flags & 2097152 /* Alias */ ? resolveAlias(symbol) : symbol); if (!target || getSymbolFlags(target) & 111551 /* Value */) { markExportAsReferenced(location); - markIdentifierAliasReferenced(location.propertyName || location.name); + markIdentifierAliasReferenced(exportedName); } } return; @@ -74711,7 +75105,7 @@ function createTypeChecker(host) { markAliasSymbolAsReferenced(rootSymbol); } else if (forDecoratorMetadata && getIsolatedModules(compilerOptions) && getEmitModuleKind(compilerOptions) >= 5 /* ES2015 */ && !symbolIsValue(rootSymbol) && !some(rootSymbol.declarations, isTypeOnlyImportOrExportDeclaration)) { const diag2 = error2(typeName, Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled); - const aliasDeclaration = find(rootSymbol.declarations || emptyArray, isAliasSymbolDeclaration2); + const aliasDeclaration = find(rootSymbol.declarations || emptyArray, isAliasSymbolDeclaration); if (aliasDeclaration) { addRelatedInfo(diag2, createDiagnosticForNode(aliasDeclaration, Diagnostics._0_was_imported_here, idText(rootName))); } @@ -74735,9 +75129,9 @@ function createTypeChecker(host) { ); } } - function getNarrowedTypeOfSymbol(symbol, location, checkMode) { + function getNarrowedTypeOfSymbol(symbol, location) { var _a; - const type = getTypeOfSymbol(symbol, checkMode); + const type = getTypeOfSymbol(symbol); const declaration = symbol.valueDeclaration; if (declaration) { if (isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) { @@ -74876,7 +75270,10 @@ function createTypeChecker(host) { } const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); let declaration = localOrExportSymbol.valueDeclaration; - let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node, checkMode); + if (declaration && declaration.kind === 208 /* BindingElement */ && contains(contextualBindingPatterns, declaration.parent) && findAncestor(node, (parent2) => parent2 === declaration.parent)) { + return nonInferrableAnyType; + } + let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node); const assignmentKind = getAssignmentTargetKind(node); if (assignmentKind) { if (!(localOrExportSymbol.flags & 3 /* Variable */) && !(isInJSFile(node) && localOrExportSymbol.flags & 512 /* ValueModule */)) { @@ -75831,7 +76228,7 @@ function createTypeChecker(host) { type, (t) => { var _a; - if (isGenericMappedType(t) && !t.declaration.nameType) { + if (isGenericMappedType(t) && getMappedTypeNameTypeKind(t) !== 2 /* Remapping */) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); @@ -75929,7 +76326,7 @@ function createTypeChecker(host) { return removeMissingType(getTypeArguments(t)[index], !!(t.target.elementFlags[index] && 2 /* Optional */)); } const offset = length2 !== void 0 && (lastSpreadIndex === void 0 || index > lastSpreadIndex) ? length2 - index : 0; - const fixedEndLength = offset > 0 && t.target.hasRestElement ? getEndElementCount(t.target, 3 /* Fixed */) : 0; + const fixedEndLength = offset > 0 && t.target.combinedFlags & 12 /* Variable */ ? getEndElementCount(t.target, 3 /* Fixed */) : 0; if (offset > 0 && offset <= fixedEndLength) { return getTypeArguments(t)[getTypeReferenceArity(t) - offset]; } @@ -76572,7 +76969,7 @@ function createTypeChecker(host) { return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type; } function hasDefaultValue(node) { - return node.kind === 208 /* BindingElement */ && !!node.initializer || node.kind === 226 /* BinaryExpression */ && node.operatorToken.kind === 64 /* EqualsToken */; + return node.kind === 208 /* BindingElement */ && !!node.initializer || node.kind === 303 /* PropertyAssignment */ && hasDefaultValue(node.initializer) || node.kind === 304 /* ShorthandPropertyAssignment */ && !!node.objectAssignmentInitializer || node.kind === 226 /* BinaryExpression */ && node.operatorToken.kind === 64 /* EqualsToken */; } function isSpreadIntoCallOrNew(node) { const parent2 = walkUpParenthesizedExpressions(node.parent); @@ -76741,7 +77138,6 @@ function createTypeChecker(host) { return links.immediateTarget; } function checkObjectLiteral(node, checkMode = 0 /* Normal */) { - var _a; const inDestructuringPattern = isAssignmentTarget(node); checkGrammarObjectLiteralExpression(node, inDestructuringPattern); const allPropertiesTable = strictNullChecks ? createSymbolTable() : void 0; @@ -76796,11 +77192,8 @@ function createTypeChecker(host) { if (nameType) { prop.links.nameType = nameType; } - if (inDestructuringPattern) { - const isOptional = memberDecl.kind === 303 /* PropertyAssignment */ && hasDefaultValue(memberDecl.initializer) || memberDecl.kind === 304 /* ShorthandPropertyAssignment */ && memberDecl.objectAssignmentInitializer; - if (isOptional) { - prop.flags |= 16777216 /* Optional */; - } + if (inDestructuringPattern && hasDefaultValue(memberDecl)) { + prop.flags |= 16777216 /* Optional */; } else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & 512 /* ObjectLiteralPatternWithComputedProperties */)) { const impliedProp = getPropertyOfType(contextualType, member.escapedName); if (impliedProp) { @@ -76875,21 +77268,6 @@ function createTypeChecker(host) { propertiesArray.push(member); } popContextualType(); - if (contextualTypeHasPattern) { - const rootPatternParent = findAncestor(contextualType.pattern.parent, (n) => n.kind === 260 /* VariableDeclaration */ || n.kind === 226 /* BinaryExpression */ || n.kind === 169 /* Parameter */); - const spreadOrOutsideRootObject = findAncestor(node, (n) => n === rootPatternParent || n.kind === 305 /* SpreadAssignment */); - if (spreadOrOutsideRootObject.kind !== 305 /* SpreadAssignment */) { - for (const prop of getPropertiesOfType(contextualType)) { - if (!propertiesTable.get(prop.escapedName) && !getPropertyOfType(spread, prop.escapedName)) { - if (!(prop.flags & 16777216 /* Optional */)) { - error2(prop.valueDeclaration || ((_a = tryCast(prop, isTransientSymbol)) == null ? void 0 : _a.links.bindingElement), Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); - } - propertiesTable.set(prop.escapedName, prop); - propertiesArray.push(prop); - } - } - } - } if (isErrorType(spread)) { return errorType; } @@ -77412,7 +77790,7 @@ function createTypeChecker(host) { checkGrammarJsxElement(node); } checkJsxPreconditions(node); - markLinkedReferences(node, 4 /* Jsx */); + markJsxAliasReferenced(node); if (isNodeOpeningLikeElement) { const jsxOpeningLikeNode = node; const sig = getResolvedSignature(jsxOpeningLikeNode); @@ -77565,8 +77943,21 @@ function createTypeChecker(host) { function getEnclosingClassFromThisParameter(node) { const thisParameter = getThisParameterFromNodeContext(node); let thisType = (thisParameter == null ? void 0 : thisParameter.type) && getTypeFromTypeNode(thisParameter.type); - if (thisType && thisType.flags & 262144 /* TypeParameter */) { - thisType = getConstraintOfTypeParameter(thisType); + if (thisType) { + if (thisType.flags & 262144 /* TypeParameter */) { + thisType = getConstraintOfTypeParameter(thisType); + } + } else { + const thisContainer = getThisContainer( + node, + /*includeArrowFunctions*/ + false, + /*includeClassComputedPropertyName*/ + false + ); + if (isFunctionLike(thisContainer)) { + thisType = getContextualThisParameterType(thisContainer); + } } if (thisType && getObjectFlags(thisType) & (3 /* ClassOrInterface */ | 4 /* Reference */)) { return getTargetType(thisType); @@ -78085,7 +78476,7 @@ function createTypeChecker(host) { addErrorOrSuggestion(!isUncheckedJS || errorInfo.code !== Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, resultDiagnostic); } function containerSeemsToBeEmptyDomElement(containingType) { - return compilerOptions.lib && !compilerOptions.lib.includes("dom") && everyContainedType(containingType, (type) => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) && isEmptyObjectType(containingType); + return compilerOptions.lib && !compilerOptions.lib.includes("dom") && everyContainedType(containingType, (type) => type.symbol && /^(?:EventTarget|Node|(?:HTML[a-zA-Z]*)?Element)$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) && isEmptyObjectType(containingType); } function typeHasStaticProperty(propName, containingType) { const prop = containingType.symbol && getPropertyOfType(getTypeOfSymbol(containingType.symbol), propName); @@ -78526,7 +78917,7 @@ function createTypeChecker(host) { return void 0; } function instantiateSignatureInContextOf(signature, contextualSignature, inferenceContext, compareTypes) { - const context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); + const context = createInferenceContext(getTypeParametersForMapper(signature), signature, 0 /* None */, compareTypes); const restType = getEffectiveRestType(contextualSignature); const mapper = inferenceContext && (restType && restType.flags & 262144 /* TypeParameter */ ? inferenceContext.nonFixingMapper : inferenceContext.mapper); const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; @@ -80346,7 +80737,7 @@ function createTypeChecker(host) { return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); } function getTypeWithSyntheticDefaultOnly(type, symbol, originalSymbol, moduleSpecifier) { - const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier); + const hasDefaultOnly = isOnlyImportableAsDefault(moduleSpecifier); if (hasDefaultOnly && type && !isErrorType(type)) { const synthType = type; if (!synthType.defaultOnlyType) { @@ -80672,14 +81063,45 @@ function createTypeChecker(host) { !!declaration && (hasInitializer(declaration) || isOptionalDeclaration(declaration)) ); } - function getTupleElementLabel(d, index, restParameterName = "arg") { + function getTupleElementLabelFromBindingElement(node, index, elementFlags) { + switch (node.name.kind) { + case 80 /* Identifier */: { + const name = node.name.escapedText; + if (node.dotDotDotToken) { + return elementFlags & 12 /* Variable */ ? name : `${name}_${index}`; + } else { + return elementFlags & 3 /* Fixed */ ? name : `${name}_n`; + } + } + case 207 /* ArrayBindingPattern */: { + if (node.dotDotDotToken) { + const elements = node.name.elements; + const lastElement = tryCast(lastOrUndefined(elements), isBindingElement); + const elementCount = elements.length - ((lastElement == null ? void 0 : lastElement.dotDotDotToken) ? 1 : 0); + if (index < elementCount) { + const element = elements[index]; + if (isBindingElement(element)) { + return getTupleElementLabelFromBindingElement(element, index, elementFlags); + } + } else if (lastElement == null ? void 0 : lastElement.dotDotDotToken) { + return getTupleElementLabelFromBindingElement(lastElement, index - elementCount, elementFlags); + } + } + break; + } + } + return `arg_${index}`; + } + function getTupleElementLabel(d, index = 0, elementFlags = 3 /* Fixed */, restSymbol) { if (!d) { - return `${restParameterName}_${index}`; + const restParameter = tryCast(restSymbol == null ? void 0 : restSymbol.valueDeclaration, isParameter); + return restParameter ? getTupleElementLabelFromBindingElement(restParameter, index, elementFlags) : `${(restSymbol == null ? void 0 : restSymbol.escapedName) ?? "arg"}_${index}`; } Debug.assert(isIdentifier(d.name)); return d.name.escapedText; } function getParameterNameAtPosition(signature, pos, overrideRestType) { + var _a; const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); if (pos < paramCount) { return signature.parameters[pos].escapedName; @@ -80687,9 +81109,11 @@ function createTypeChecker(host) { const restParameter = signature.parameters[paramCount] || unknownSymbol; const restType = overrideRestType || getTypeOfSymbol(restParameter); if (isTupleType(restType)) { - const associatedNames = restType.target.labeledElementDeclarations; + const tupleType = restType.target; const index = pos - paramCount; - return getTupleElementLabel(associatedNames == null ? void 0 : associatedNames[index], index, restParameter.escapedName); + const associatedName = (_a = tupleType.labeledElementDeclarations) == null ? void 0 : _a[index]; + const elementFlags = tupleType.elementFlags[index]; + return getTupleElementLabel(associatedName, index, elementFlags, restParameter); } return restParameter.escapedName; } @@ -80762,7 +81186,7 @@ function createTypeChecker(host) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[paramCount]); const index = pos - paramCount; - if (!isTupleType(restType) || restType.target.hasRestElement || index < restType.target.fixedLength) { + if (!isTupleType(restType) || restType.target.combinedFlags & 12 /* Variable */ || index < restType.target.fixedLength) { return getIndexedAccessType(restType, getNumberLiteralType(index)); } } @@ -80800,7 +81224,7 @@ function createTypeChecker(host) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[length2 - 1]); if (isTupleType(restType)) { - return length2 + restType.target.fixedLength - (restType.target.hasRestElement ? 0 : 1); + return length2 + restType.target.fixedLength - (restType.target.combinedFlags & 12 /* Variable */ ? 0 : 1); } } return length2; @@ -80843,7 +81267,7 @@ function createTypeChecker(host) { function hasEffectiveRestParameter(signature) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); - return !isTupleType(restType) || restType.target.hasRestElement; + return !isTupleType(restType) || !!(restType.target.combinedFlags & 12 /* Variable */); } return false; } @@ -80853,7 +81277,7 @@ function createTypeChecker(host) { if (!isTupleType(restType)) { return isTypeAny(restType) ? anyArrayType : restType; } - if (restType.target.hasRestElement) { + if (restType.target.combinedFlags & 12 /* Variable */) { return sliceTupleType(restType, restType.target.fixedLength); } } @@ -81367,30 +81791,15 @@ function createTypeChecker(host) { /*errorNode*/ void 0 ) || unknownType; - nextType = resolver.resolveIterationType( - nextType, - /*errorNode*/ - void 0 - ) || unknownType; if (globalGeneratorType === emptyGenericType) { - const globalType = resolver.getGlobalIterableIteratorType( + const globalIterableIteratorType = resolver.getGlobalIterableIteratorType( /*reportErrors*/ false ); - const iterationTypes = globalType !== emptyGenericType ? getIterationTypesOfGlobalIterableType(globalType, resolver) : void 0; - const iterableIteratorReturnType = iterationTypes ? iterationTypes.returnType : anyType; - const iterableIteratorNextType = iterationTypes ? iterationTypes.nextType : undefinedType; - if (isTypeAssignableTo(returnType, iterableIteratorReturnType) && isTypeAssignableTo(iterableIteratorNextType, nextType)) { - if (globalType !== emptyGenericType) { - return createTypeFromGenericGlobalType(globalType, [yieldType]); - } - resolver.getGlobalIterableIteratorType( - /*reportErrors*/ - true - ); - return emptyObjectType; + if (globalIterableIteratorType !== emptyGenericType) { + return createTypeFromGenericGlobalType(globalIterableIteratorType, [yieldType, returnType, nextType]); } - resolver.getGlobalGeneratorType( + resolver.getGlobalIterableIteratorType( /*reportErrors*/ true ); @@ -82170,7 +82579,7 @@ function createTypeChecker(host) { ); } } - const elementType = getIndexedAccessType(objectLiteralType, exprType, 32 /* ExpressionPosition */, name); + const elementType = getIndexedAccessType(objectLiteralType, exprType, 32 /* ExpressionPosition */ | (hasDefaultValue(property) ? 16 /* AllowMissing */ : 0), name); const type = getFlowTypeOfDestructuring(property, elementType); return checkDestructuringAssignment(property.kind === 304 /* ShorthandPropertyAssignment */ ? property : property.initializer, type); } else if (property.kind === 305 /* SpreadAssignment */) { @@ -82219,7 +82628,7 @@ function createTypeChecker(host) { if (element.kind !== 230 /* SpreadElement */) { const indexType = getNumberLiteralType(elementIndex); if (isArrayLikeType(sourceType)) { - const accessFlags = 32 /* ExpressionPosition */ | (hasDefaultValue(element) ? 16 /* NoTupleBoundsCheck */ : 0); + const accessFlags = 32 /* ExpressionPosition */ | (hasDefaultValue(element) ? 16 /* AllowMissing */ : 0); const elementType2 = getIndexedAccessTypeOrUndefined(sourceType, indexType, accessFlags, createSyntheticExpression(element, indexType)) || errorType; const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType2, 524288 /* NEUndefined */) : elementType2; const type = getFlowTypeOfDestructuring(element, assignedType); @@ -82369,7 +82778,7 @@ function createTypeChecker(host) { setLastResult(state, checkExpression(node.right, checkMode)); return state; } - checkGrammarNullishCoalesceWithLogicalExpression(node); + checkNullishCoalesceOperands(node); const operator = node.operatorToken.kind; if (operator === 64 /* EqualsToken */ && (node.left.kind === 210 /* ObjectLiteralExpression */ || node.left.kind === 209 /* ArrayLiteralExpression */)) { state.skip = true; @@ -82402,7 +82811,9 @@ function createTypeChecker(host) { if (operator === 56 /* AmpersandAmpersandToken */ || isIfStatement(parent2)) { checkTestingKnownTruthyCallableOrAwaitableOrEnumMemberType(node.left, leftType, isIfStatement(parent2) ? parent2.thenStatement : void 0); } - checkTruthinessOfType(leftType, node.left); + if (isBinaryLogicalOperator(operator)) { + checkTruthinessOfType(leftType, node.left); + } } } } @@ -82459,7 +82870,7 @@ function createTypeChecker(host) { state.typeStack[state.stackIndex + 1] = type; } } - function checkGrammarNullishCoalesceWithLogicalExpression(node) { + function checkNullishCoalesceOperands(node) { const { left, operatorToken, right } = node; if (operatorToken.kind === 61 /* QuestionQuestionToken */) { if (isBinaryExpression(left) && (left.operatorToken.kind === 57 /* BarBarToken */ || left.operatorToken.kind === 56 /* AmpersandAmpersandToken */)) { @@ -82468,15 +82879,63 @@ function createTypeChecker(host) { if (isBinaryExpression(right) && (right.operatorToken.kind === 57 /* BarBarToken */ || right.operatorToken.kind === 56 /* AmpersandAmpersandToken */)) { grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); } + const leftTarget = skipOuterExpressions(left, 31 /* All */); + const nullishSemantics = getSyntacticNullishnessSemantics(leftTarget); + if (nullishSemantics !== 3 /* Sometimes */) { + if (node.parent.kind === 226 /* BinaryExpression */) { + error2(leftTarget, Diagnostics.This_binary_expression_is_never_nullish_Are_you_missing_parentheses); + } else { + if (nullishSemantics === 1 /* Always */) { + error2(leftTarget, Diagnostics.This_expression_is_always_nullish); + } else { + error2(leftTarget, Diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish); + } + } + } } } + function getSyntacticNullishnessSemantics(node) { + node = skipOuterExpressions(node); + switch (node.kind) { + case 223 /* AwaitExpression */: + case 213 /* CallExpression */: + case 212 /* ElementAccessExpression */: + case 214 /* NewExpression */: + case 211 /* PropertyAccessExpression */: + case 229 /* YieldExpression */: + case 110 /* ThisKeyword */: + return 3 /* Sometimes */; + case 226 /* BinaryExpression */: + switch (node.operatorToken.kind) { + case 64 /* EqualsToken */: + case 61 /* QuestionQuestionToken */: + case 78 /* QuestionQuestionEqualsToken */: + case 57 /* BarBarToken */: + case 76 /* BarBarEqualsToken */: + case 56 /* AmpersandAmpersandToken */: + case 77 /* AmpersandAmpersandEqualsToken */: + return 3 /* Sometimes */; + } + return 2 /* Never */; + case 227 /* ConditionalExpression */: + return getSyntacticNullishnessSemantics(node.whenTrue) | getSyntacticNullishnessSemantics(node.whenFalse); + case 106 /* NullKeyword */: + return 1 /* Always */; + case 80 /* Identifier */: + if (getResolvedSymbol(node) === undefinedSymbol) { + return 1 /* Always */; + } + return 3 /* Sometimes */; + } + return 2 /* Never */; + } function checkBinaryLikeExpression(left, operatorToken, right, checkMode, errorNode) { const operator = operatorToken.kind; if (operator === 64 /* EqualsToken */ && (left.kind === 210 /* ObjectLiteralExpression */ || left.kind === 209 /* ArrayLiteralExpression */)) { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === 110 /* ThisKeyword */); } let leftType; - if (isLogicalOrCoalescingBinaryOperator(operator)) { + if (isBinaryLogicalOperator(operator)) { leftType = checkTruthinessExpression(left, checkMode); } else { leftType = checkExpression(left, checkMode); @@ -82556,6 +83015,29 @@ function createTypeChecker(host) { } if (leftOk && rightOk) { checkAssignmentOperator(resultType2); + switch (operator) { + case 48 /* LessThanLessThanToken */: + case 71 /* LessThanLessThanEqualsToken */: + case 49 /* GreaterThanGreaterThanToken */: + case 72 /* GreaterThanGreaterThanEqualsToken */: + case 50 /* GreaterThanGreaterThanGreaterThanToken */: + case 73 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + const rhsEval = evaluate(right); + if (typeof rhsEval.value === "number" && Math.abs(rhsEval.value) >= 32) { + errorOrSuggestion( + isEnumMember(walkUpParenthesizedExpressions(right.parent.parent)), + // elevate from suggestion to error within an enum member + errorNode || operatorToken, + Diagnostics.This_operation_can_be_simplified_This_shift_is_identical_to_0_1_2, + getTextOfNode(left), + tokenToString(operator), + rhsEval.value % 32 + ); + } + break; + default: + break; + } } return resultType2; } @@ -82914,9 +83396,8 @@ function createTypeChecker(host) { const iterationTypes = returnType && getIterationTypesOfGeneratorFunctionReturnType(returnType, isAsync); const signatureYieldType = iterationTypes && iterationTypes.yieldType || anyType; const signatureNextType = iterationTypes && iterationTypes.nextType || anyType; - const resolvedSignatureNextType = isAsync ? getAwaitedType(signatureNextType) || anyType : signatureNextType; const yieldExpressionType = node.expression ? checkExpression(node.expression) : undefinedWideningType; - const yieldedType = getYieldedTypeOfYieldExpression(node, yieldExpressionType, resolvedSignatureNextType, isAsync); + const yieldedType = getYieldedTypeOfYieldExpression(node, yieldExpressionType, signatureNextType, isAsync); if (returnType && yieldedType) { checkTypeAssignableToAndOptionallyElaborate(yieldedType, signatureYieldType, node.expression || node, node.expression); } @@ -83058,9 +83539,56 @@ function createTypeChecker(host) { void 0, checkMode || 0 /* Normal */ ) : checkExpressionCached(initializer, checkMode)); - return isParameter(declaration) && declaration.name.kind === 207 /* ArrayBindingPattern */ && isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ? padTupleType(type, declaration.name) : type; + if (isParameter(isBindingElement(declaration) ? walkUpBindingElementsAndPatterns(declaration) : declaration)) { + if (declaration.name.kind === 206 /* ObjectBindingPattern */ && isObjectLiteralType2(type)) { + return padObjectLiteralType(type, declaration.name); + } + if (declaration.name.kind === 207 /* ArrayBindingPattern */ && isTupleType(type)) { + return padTupleType(type, declaration.name); + } + } + return type; + } + function padObjectLiteralType(type, pattern) { + let missingElements; + for (const e of pattern.elements) { + if (e.initializer) { + const name = getPropertyNameFromBindingElement(e); + if (name && !getPropertyOfType(type, name)) { + missingElements = append(missingElements, e); + } + } + } + if (!missingElements) { + return type; + } + const members = createSymbolTable(); + for (const prop of getPropertiesOfObjectType(type)) { + members.set(prop.escapedName, prop); + } + for (const e of missingElements) { + const symbol = createSymbol(4 /* Property */ | 16777216 /* Optional */, getPropertyNameFromBindingElement(e)); + symbol.links.type = getTypeFromBindingElement( + e, + /*includePatternInType*/ + false, + /*reportErrors*/ + false + ); + members.set(symbol.escapedName, symbol); + } + const result = createAnonymousType(type.symbol, members, emptyArray, emptyArray, getIndexInfosOfType(type)); + result.objectFlags = type.objectFlags; + return result; + } + function getPropertyNameFromBindingElement(e) { + const exprType = getLiteralTypeFromPropertyName(e.propertyName || e.name); + return isTypeUsableAsPropertyName(exprType) ? getPropertyNameFromType(exprType) : void 0; } function padTupleType(type, pattern) { + if (type.target.combinedFlags & 12 /* Variable */ || getTypeReferenceArity(type) >= pattern.elements.length) { + return type; + } const patternElements = pattern.elements; const elementTypes = getElementTypes(type).slice(); const elementFlags = type.target.elementFlags.slice(); @@ -83369,7 +83897,17 @@ function createTypeChecker(host) { if (!ok) { error2(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); } - if (getIsolatedModules(compilerOptions)) { + if (compilerOptions.isolatedModules || compilerOptions.verbatimModuleSyntax && ok && !resolveName( + node, + getFirstIdentifier(node), + 2097152 /* Alias */, + /*nameNotFoundMessage*/ + void 0, + /*isUse*/ + false, + /*excludeGlobals*/ + true + )) { Debug.assert(!!(type.symbol.flags & 128 /* ConstEnum */)); const constEnumDeclaration = type.symbol.valueDeclaration; const redirect = host.getRedirectReferenceForResolutionFromSourceOfProject(getSourceFileOfNode(constEnumDeclaration).resolvedPath); @@ -83593,9 +84131,7 @@ function createTypeChecker(host) { } checkSourceElement(node.type); const { parameterName } = node; - if (typePredicate.kind === 0 /* This */ || typePredicate.kind === 2 /* AssertsThis */) { - getTypeFromThisTypeNode(parameterName); - } else { + if (typePredicate.kind !== 0 /* This */ && typePredicate.kind !== 2 /* AssertsThis */) { if (typePredicate.parameterIndex >= 0) { if (signatureHasRestParameter(signature) && typePredicate.parameterIndex === signature.parameters.length - 1) { error2(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); @@ -84330,16 +84866,20 @@ function createTypeChecker(host) { const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { const canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck2); - forEach(overloads, (o) => { - const deviation = getEffectiveDeclarationFlags(o, flagsToCheck2) ^ canonicalFlags; - if (deviation & 32 /* Export */) { - error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); - } else if (deviation & 128 /* Ambient */) { - error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); - } else if (deviation & (2 /* Private */ | 4 /* Protected */)) { - error2(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); - } else if (deviation & 64 /* Abstract */) { - error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); + group(overloads, (o) => getSourceFileOfNode(o).fileName).forEach((overloadsInFile) => { + const canonicalFlagsForFile = getEffectiveDeclarationFlags(getCanonicalOverload(overloadsInFile, implementation), flagsToCheck2); + for (const o of overloadsInFile) { + const deviation = getEffectiveDeclarationFlags(o, flagsToCheck2) ^ canonicalFlags; + const deviationInFile = getEffectiveDeclarationFlags(o, flagsToCheck2) ^ canonicalFlagsForFile; + if (deviationInFile & 32 /* Export */) { + error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); + } else if (deviationInFile & 128 /* Ambient */) { + error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); + } else if (deviation & (2 /* Private */ | 4 /* Protected */)) { + error2(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); + } else if (deviation & 64 /* Abstract */) { + error2(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); + } } }); } @@ -85474,7 +86014,7 @@ function createTypeChecker(host) { if (!wrappingDeclaration.type) { addRelatedInfo( diagnostic, - createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName)) + createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 0, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName)) ); } diagnostics.add(diagnostic); @@ -85573,7 +86113,7 @@ function createTypeChecker(host) { }); } function checkCollisionWithRequireExportsInGeneratedCode(node, name) { - if (moduleKind >= 5 /* ES2015 */ && !(moduleKind >= 100 /* Node16 */ && getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) >= 5 /* ES2015 */) { return; } if (!name || !needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { @@ -85783,6 +86323,9 @@ function createTypeChecker(host) { checkAliasSymbol(node); return; } + if (node.name.kind === 10 /* BigIntLiteral */) { + error2(node.name, Diagnostics.A_bigint_literal_cannot_be_used_as_a_property_name); + } const type = convertAutoToAny(getTypeOfSymbol(symbol)); if (node === symbol.valueDeclaration) { const initializer = hasOnlyExpressionInitializer(node) && getEffectiveInitializer(node); @@ -85810,7 +86353,7 @@ function createTypeChecker(host) { ); if (globalAsyncDisposableType !== emptyObjectType && globalDisposableType !== emptyObjectType) { const optionalDisposableType = getUnionType([globalAsyncDisposableType, globalDisposableType, nullType, undefinedType]); - checkTypeAssignableTo(initializerType, optionalDisposableType, initializer, Diagnostics.The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined); + checkTypeAssignableTo(widenTypeForVariableLikeDeclaration(initializerType, node), optionalDisposableType, initializer, Diagnostics.The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined); } } else if (blockScopeKind === 4 /* Using */) { const globalDisposableType = getGlobalDisposableType( @@ -85819,7 +86362,7 @@ function createTypeChecker(host) { ); if (globalDisposableType !== emptyObjectType) { const optionalDisposableType = getUnionType([globalDisposableType, nullType, undefinedType]); - checkTypeAssignableTo(initializerType, optionalDisposableType, initializer, Diagnostics.The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined); + checkTypeAssignableTo(widenTypeForVariableLikeDeclaration(initializerType, node), optionalDisposableType, initializer, Diagnostics.The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined); } } } @@ -85937,7 +86480,7 @@ function createTypeChecker(host) { bothHelper(location, body2); return; } - const type = location === condExpr2 ? condType : checkTruthinessExpression(location); + const type = location === condExpr2 ? condType : checkExpression(location); if (type.flags & 1024 /* EnumLiteral */ && isPropertyAccessExpression(location) && (getNodeLinks(location.expression).resolvedSymbol ?? unknownSymbol).flags & 384 /* Enum */) { error2(location, Diagnostics.This_condition_will_always_return_0, !!type.value ? "true" : "false"); return; @@ -86032,9 +86575,51 @@ function createTypeChecker(host) { function checkTruthinessOfType(type, node) { if (type.flags & 16384 /* Void */) { error2(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness); + } else { + const semantics = getSyntacticTruthySemantics(node); + if (semantics !== 3 /* Sometimes */) { + error2( + node, + semantics === 1 /* Always */ ? Diagnostics.This_kind_of_expression_is_always_truthy : Diagnostics.This_kind_of_expression_is_always_falsy + ); + } } return type; } + function getSyntacticTruthySemantics(node) { + node = skipOuterExpressions(node); + switch (node.kind) { + case 9 /* NumericLiteral */: + if (node.text === "0" || node.text === "1") { + return 3 /* Sometimes */; + } + return 1 /* Always */; + case 209 /* ArrayLiteralExpression */: + case 219 /* ArrowFunction */: + case 10 /* BigIntLiteral */: + case 231 /* ClassExpression */: + case 218 /* FunctionExpression */: + case 284 /* JsxElement */: + case 285 /* JsxSelfClosingElement */: + case 210 /* ObjectLiteralExpression */: + case 14 /* RegularExpressionLiteral */: + return 1 /* Always */; + case 222 /* VoidExpression */: + case 106 /* NullKeyword */: + return 2 /* Never */; + case 15 /* NoSubstitutionTemplateLiteral */: + case 11 /* StringLiteral */: + return !!node.text ? 1 /* Always */ : 2 /* Never */; + case 227 /* ConditionalExpression */: + return getSyntacticTruthySemantics(node.whenTrue) | getSyntacticTruthySemantics(node.whenFalse); + case 80 /* Identifier */: + if (getResolvedSymbol(node) === undefinedSymbol) { + return 2 /* Never */; + } + return 3 /* Sometimes */; + } + return 3 /* Sometimes */; + } function checkTruthinessExpression(node, checkMode) { return checkTruthinessOfType(checkExpression(node, checkMode), node); } @@ -86417,30 +87002,21 @@ function createTypeChecker(host) { function getIterationTypesOfIterableCached(type, resolver) { return getCachedIterationTypes(type, resolver.iterableCacheKey); } - function getIterationTypesOfGlobalIterableType(globalType, resolver) { - const globalIterationTypes = getIterationTypesOfIterableCached(globalType, resolver) || getIterationTypesOfIterableSlow( - globalType, - resolver, - /*errorNode*/ - void 0, - /*errorOutputContainer*/ - void 0, - /*noCache*/ - false - ); - return globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes; - } function getIterationTypesOfIterableFast(type, resolver) { - let globalType; - if (isReferenceToType2(type, globalType = resolver.getGlobalIterableType( + if (isReferenceToType2(type, resolver.getGlobalIterableType( /*reportErrors*/ false - )) || isReferenceToType2(type, globalType = resolver.getGlobalIterableIteratorType( + )) || isReferenceToType2(type, resolver.getGlobalIteratorObjectType( + /*reportErrors*/ + false + )) || isReferenceToType2(type, resolver.getGlobalIterableIteratorType( + /*reportErrors*/ + false + )) || isReferenceToType2(type, resolver.getGlobalGeneratorType( /*reportErrors*/ false ))) { - const [yieldType] = getTypeArguments(type); - const { returnType, nextType } = getIterationTypesOfGlobalIterableType(globalType, resolver); + const [yieldType, returnType, nextType] = getTypeArguments(type); return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType( yieldType, /*errorNode*/ @@ -86451,11 +87027,10 @@ function createTypeChecker(host) { void 0 ) || returnType, nextType)); } - if (isReferenceToType2(type, resolver.getGlobalGeneratorType( - /*reportErrors*/ - false - ))) { - const [yieldType, returnType, nextType] = getTypeArguments(type); + if (isReferenceToSomeType(type, resolver.getGlobalBuiltinIteratorTypes())) { + const [yieldType] = getTypeArguments(type); + const returnType = getBuiltinIteratorReturnType(); + const nextType = unknownType; return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType( yieldType, /*errorNode*/ @@ -86496,10 +87071,10 @@ function createTypeChecker(host) { !!getAwaitedTypeOfPromise(type) || !allowAsyncIterables && isForOfStatement(errorNode.parent) && errorNode.parent.expression === errorNode && getGlobalAsyncIterableType( /*reportErrors*/ false - ) !== emptyGenericType && isTypeAssignableTo(type, getGlobalAsyncIterableType( + ) !== emptyGenericType && isTypeAssignableTo(type, createTypeFromGenericGlobalType(getGlobalAsyncIterableType( /*reportErrors*/ false - )) + ), [anyType, anyType, anyType])) ); return errorAndMaybeSuggestAwait(errorNode, suggestAwait, message, typeToString(type)); } @@ -86529,26 +87104,13 @@ function createTypeChecker(host) { return getCachedIterationTypes(type, resolver.iteratorCacheKey); } function getIterationTypesOfIteratorFast(type, resolver) { - const globalType = resolver.getGlobalIterableIteratorType( + if (isReferenceToType2(type, resolver.getGlobalIterableIteratorType( /*reportErrors*/ false - ); - if (isReferenceToType2(type, globalType)) { - const [yieldType] = getTypeArguments(type); - const globalIterationTypes = getIterationTypesOfIteratorCached(globalType, resolver) || getIterationTypesOfIteratorSlow( - globalType, - resolver, - /*errorNode*/ - void 0, - /*errorOutputContainer*/ - void 0, - /*noCache*/ - false - ); - const { returnType, nextType } = globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes; - return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); - } - if (isReferenceToType2(type, resolver.getGlobalIteratorType( + )) || isReferenceToType2(type, resolver.getGlobalIteratorType( + /*reportErrors*/ + false + )) || isReferenceToType2(type, resolver.getGlobalIteratorObjectType( /*reportErrors*/ false )) || isReferenceToType2(type, resolver.getGlobalGeneratorType( @@ -86558,6 +87120,12 @@ function createTypeChecker(host) { const [yieldType, returnType, nextType] = getTypeArguments(type); return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); } + if (isReferenceToSomeType(type, resolver.getGlobalBuiltinIteratorTypes())) { + const [yieldType] = getTypeArguments(type); + const returnType = getBuiltinIteratorReturnType(); + const nextType = unknownType; + return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); + } } function isIteratorResult(type, kind) { const doneType = getTypeOfPropertyOfType(type, "done") || falseType; @@ -86625,7 +87193,7 @@ function createTypeChecker(host) { } const methodType = method && !(methodName === "next" && method.flags & 16777216 /* Optional */) ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), 2097152 /* NEUndefinedOrNull */) : void 0; if (isTypeAny(methodType)) { - return methodName === "next" ? anyIterationTypes : anyIterationTypesExceptNext; + return anyIterationTypes; } const methodSignatures = methodType ? getSignaturesOfType(methodType, 0 /* Call */) : emptyArray; if (methodSignatures.length === 0) { @@ -86994,7 +87562,7 @@ function createTypeChecker(host) { } } function checkClassNameCollisionWithObject(name) { - if (languageVersion >= 1 /* ES5 */ && name.escapedText === "Object" && (moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(name).impliedNodeFormat === 1 /* CommonJS */)) { + if (languageVersion >= 1 /* ES5 */ && name.escapedText === "Object" && host.getEmitModuleFormatOfFile(getSourceFileOfNode(name)) < 5 /* ES2015 */) { error2(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ModuleKind[moduleKind]); } } @@ -87373,23 +87941,22 @@ function createTypeChecker(host) { hasAbstractModifier(member), isStatic(member), memberIsParameterProperty, - symbolName(declaredProp), + declaredProp, reportErrors2 ? member : void 0 ); } - function checkMemberForOverrideModifier(node, staticType, baseStaticType, baseWithThis, type, typeWithThis, memberHasOverrideModifier, memberHasAbstractModifier, memberIsStatic, memberIsParameterProperty, memberName, errorNode) { + function checkMemberForOverrideModifier(node, staticType, baseStaticType, baseWithThis, type, typeWithThis, memberHasOverrideModifier, memberHasAbstractModifier, memberIsStatic, memberIsParameterProperty, member, errorNode) { const isJs = isInJSFile(node); const nodeInAmbientContext = !!(node.flags & 33554432 /* Ambient */); if (baseWithThis && (memberHasOverrideModifier || compilerOptions.noImplicitOverride)) { - const memberEscapedName = escapeLeadingUnderscores(memberName); const thisType = memberIsStatic ? staticType : typeWithThis; const baseType = memberIsStatic ? baseStaticType : baseWithThis; - const prop = getPropertyOfType(thisType, memberEscapedName); - const baseProp = getPropertyOfType(baseType, memberEscapedName); + const prop = getPropertyOfType(thisType, member.escapedName); + const baseProp = getPropertyOfType(baseType, member.escapedName); const baseClassName = typeToString(baseWithThis); if (prop && !baseProp && memberHasOverrideModifier) { if (errorNode) { - const suggestion = getSuggestedSymbolForNonexistentClassMember(memberName, baseType); + const suggestion = getSuggestedSymbolForNonexistentClassMember(symbolName(member), baseType); suggestion ? error2( errorNode, isJs ? Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 : Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, @@ -87506,7 +88073,7 @@ function createTypeChecker(host) { isStatic(member), /*memberIsParameterProperty*/ false, - symbolName(memberSymbol) + memberSymbol ); } function getTargetSymbol(s) { @@ -87764,7 +88331,9 @@ function createTypeChecker(host) { checkExportsOnMergedDeclarations(node); checkTypeParameters(node.typeParameters); if (node.type.kind === 141 /* IntrinsicKeyword */) { - if (!intrinsicTypeKinds.has(node.name.escapedText) || length(node.typeParameters) !== 1) { + const typeParameterCount = length(node.typeParameters); + const valid = typeParameterCount === 0 ? node.name.escapedText === "BuiltinIteratorReturn" : typeParameterCount === 1 && intrinsicTypeKinds.has(node.name.escapedText); + if (!valid) { error2(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); } } else { @@ -88054,6 +88623,14 @@ function createTypeChecker(host) { } if (isIdentifier(node.name)) { checkCollisionsForDeclarationName(node, node.name); + if (!(node.flags & (32 /* Namespace */ | 2048 /* GlobalAugmentation */))) { + const sourceFile = getSourceFileOfNode(node); + const pos = getNonModifierTokenPosOfNode(node); + const span = getSpanOfTokenAtPosition(sourceFile, pos); + suggestionDiagnostics.add( + createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead) + ); + } } checkExportsOnMergedDeclarations(node); const symbol = getSymbolOfDeclaration(node); @@ -88075,7 +88652,7 @@ function createTypeChecker(host) { getNodeLinks(node).flags |= 2048 /* LexicalModuleMergesWithClass */; } } - if (compilerOptions.verbatimModuleSyntax && node.parent.kind === 307 /* SourceFile */ && (moduleKind === 1 /* CommonJS */ || node.parent.impliedNodeFormat === 1 /* CommonJS */)) { + if (compilerOptions.verbatimModuleSyntax && node.parent.kind === 307 /* SourceFile */ && host.getEmitModuleFormatOfFile(node.parent) === 1 /* CommonJS */) { const exportModifier = (_b = node.modifiers) == null ? void 0 : _b.find((m) => m.kind === 95 /* ExportKeyword */); if (exportModifier) { error2(exportModifier, Diagnostics.A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); @@ -88118,6 +88695,7 @@ function createTypeChecker(host) { grammarErrorOnFirstToken(node, Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); break; case 271 /* ImportEqualsDeclaration */: + if (isInternalModuleImportEqualsDeclaration(node)) break; case 272 /* ImportDeclaration */: grammarErrorOnFirstToken(node, Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); break; @@ -88197,6 +88775,16 @@ function createTypeChecker(host) { } return true; } + function checkModuleExportName(name, allowStringLiteral = true) { + if (name === void 0 || name.kind !== 11 /* StringLiteral */) { + return; + } + if (!allowStringLiteral) { + grammarErrorOnNode(name, Diagnostics.Identifier_expected); + } else if (moduleKind === 5 /* ES2015 */ || moduleKind === 6 /* ES2020 */) { + grammarErrorOnNode(name, Diagnostics.String_literal_import_and_export_names_are_not_supported_when_the_module_flag_is_set_to_es2015_or_es2020); + } + } function checkAliasSymbol(node) { var _a, _b, _c, _d; let symbol = getSymbolOfDeclaration(node); @@ -88208,7 +88796,7 @@ function createTypeChecker(host) { Debug.assert(node.kind !== 280 /* NamespaceExport */); if (node.kind === 281 /* ExportSpecifier */) { const diag2 = error2(errorNode, Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files); - const alreadyExportedSymbol = (_b = (_a = getSourceFileOfNode(node).symbol) == null ? void 0 : _a.exports) == null ? void 0 : _b.get((node.propertyName || node.name).escapedText); + const alreadyExportedSymbol = (_b = (_a = getSourceFileOfNode(node).symbol) == null ? void 0 : _a.exports) == null ? void 0 : _b.get(moduleExportNameTextEscaped(node.propertyName || node.name)); if (alreadyExportedSymbol === target) { const exportingDeclaration = (_c = alreadyExportedSymbol.declarations) == null ? void 0 : _c.find(isJSDocNode); if (exportingDeclaration) { @@ -88263,7 +88851,7 @@ function createTypeChecker(host) { if (compilerOptions.verbatimModuleSyntax) { Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name"); const message = compilerOptions.verbatimModuleSyntax && isInternalModuleImportEqualsDeclaration(node) ? Diagnostics.An_import_alias_cannot_resolve_to_a_type_or_type_only_declaration_when_verbatimModuleSyntax_is_enabled : isType ? Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled; - const name = idText(node.kind === 276 /* ImportSpecifier */ ? node.propertyName || node.name : node.name); + const name = moduleExportNameTextUnescaped(node.kind === 276 /* ImportSpecifier */ ? node.propertyName || node.name : node.name); addTypeOnlyDeclarationRelatedInfo( error2(node, message, name), isType ? void 0 : typeOnlyAlias, @@ -88277,7 +88865,7 @@ function createTypeChecker(host) { } case 281 /* ExportSpecifier */: { if (compilerOptions.verbatimModuleSyntax || getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node)) { - const name = idText(node.propertyName || node.name); + const name = moduleExportNameTextUnescaped(node.propertyName || node.name); const diagnostic = isType ? error2(node, Diagnostics.Re_exporting_a_type_when_0_is_enabled_requires_using_export_type, isolatedModulesLikeFlagName) : error2(node, Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_1_is_enabled, name, isolatedModulesLikeFlagName); addTypeOnlyDeclarationRelatedInfo(diagnostic, isType ? void 0 : typeOnlyAlias, name); break; @@ -88285,8 +88873,17 @@ function createTypeChecker(host) { } } } - if (compilerOptions.verbatimModuleSyntax && node.kind !== 271 /* ImportEqualsDeclaration */ && !isInJSFile(node) && (moduleKind === 1 /* CommonJS */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */)) { + if (compilerOptions.verbatimModuleSyntax && node.kind !== 271 /* ImportEqualsDeclaration */ && !isInJSFile(node) && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === 1 /* CommonJS */) { error2(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + } else if (moduleKind === 200 /* Preserve */ && node.kind !== 271 /* ImportEqualsDeclaration */ && node.kind !== 260 /* VariableDeclaration */ && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === 1 /* CommonJS */) { + error2(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve); + } + if (compilerOptions.verbatimModuleSyntax && !isTypeOnlyImportOrExportDeclaration(node) && !(node.flags & 33554432 /* Ambient */) && targetFlags & 128 /* ConstEnum */) { + const constEnumDeclaration = target.valueDeclaration; + const redirect = host.getRedirectReferenceForResolutionFromSourceOfProject(getSourceFileOfNode(constEnumDeclaration).resolvedPath); + if (constEnumDeclaration.flags & 33554432 /* Ambient */ && (!redirect || !shouldPreserveConstEnums(redirect.commandLine.options))) { + error2(node, Diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, isolatedModulesLikeFlagName); + } } } if (isImportSpecifier(node)) { @@ -88325,8 +88922,11 @@ function createTypeChecker(host) { function checkImportBinding(node) { checkCollisionsForDeclarationName(node, node.name); checkAliasSymbol(node); - if (node.kind === 276 /* ImportSpecifier */ && idText(node.propertyName || node.name) === "default" && getESModuleInterop(compilerOptions) && moduleKind !== 4 /* System */ && (moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */)) { - checkExternalEmitHelpers(node, 131072 /* ImportDefault */); + if (node.kind === 276 /* ImportSpecifier */) { + checkModuleExportName(node.propertyName); + if (moduleExportNameIsDefault(node.propertyName || node.name) && getESModuleInterop(compilerOptions) && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < 4 /* System */) { + checkExternalEmitHelpers(node, 131072 /* ImportDefault */); + } } } function checkImportAttributes(declaration) { @@ -88346,7 +88946,7 @@ function createTypeChecker(host) { if (validForTypeAttributes && override) { return; } - const mode = moduleKind === 199 /* NodeNext */ && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier); + const mode = moduleKind === 199 /* NodeNext */ && declaration.moduleSpecifier && getEmitSyntaxForModuleSpecifierExpression(declaration.moduleSpecifier); if (mode !== 99 /* ESNext */ && moduleKind !== 99 /* ESNext */ && moduleKind !== 200 /* Preserve */) { const message = isImportAttributes2 ? moduleKind === 199 /* NodeNext */ ? Diagnostics.Import_attributes_are_not_allowed_on_statements_that_compile_to_CommonJS_require_calls : Diagnostics.Import_attributes_are_only_supported_when_the_module_option_is_set_to_esnext_nodenext_or_preserve : moduleKind === 199 /* NodeNext */ ? Diagnostics.Import_assertions_are_not_allowed_on_statements_that_compile_to_CommonJS_require_calls : Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_nodenext_or_preserve; return grammarErrorOnNode(node, message); @@ -88379,7 +88979,7 @@ function createTypeChecker(host) { if (importClause.namedBindings) { if (importClause.namedBindings.kind === 274 /* NamespaceImport */) { checkImportBinding(importClause.namedBindings); - if (moduleKind !== 4 /* System */ && (moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */) && getESModuleInterop(compilerOptions)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < 4 /* System */ && getESModuleInterop(compilerOptions)) { checkExternalEmitHelpers(node, 65536 /* ImportStar */); } } else { @@ -88389,6 +88989,8 @@ function createTypeChecker(host) { } } } + } else if (noUncheckedSideEffectImports && !importClause) { + void resolveExternalModuleName(node, node.moduleSpecifier); } } checkImportAttributes(node); @@ -88419,7 +89021,7 @@ function createTypeChecker(host) { grammarErrorOnNode(node, Diagnostics.An_import_alias_cannot_use_import_type); } } else { - if (moduleKind >= 5 /* ES2015 */ && moduleKind !== 200 /* Preserve */ && getSourceFileOfNode(node).impliedNodeFormat === void 0 && !node.isTypeOnly && !(node.flags & 33554432 /* Ambient */)) { + if (5 /* ES2015 */ <= moduleKind && moduleKind <= 99 /* ESNext */ && !node.isTypeOnly && !(node.flags & 33554432 /* Ambient */)) { grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } } @@ -88447,8 +89049,9 @@ function createTypeChecker(host) { error2(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } else if (node.exportClause) { checkAliasSymbol(node.exportClause); + checkModuleExportName(node.exportClause.name); } - if (moduleKind !== 4 /* System */ && (moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < 4 /* System */) { if (node.exportClause) { if (getESModuleInterop(compilerOptions)) { checkExternalEmitHelpers(node, 65536 /* ImportStar */); @@ -88477,6 +89080,9 @@ function createTypeChecker(host) { } function checkExportSpecifier(node) { checkAliasSymbol(node); + const hasModuleSpecifier = node.parent.parent.moduleSpecifier !== void 0; + checkModuleExportName(node.propertyName, hasModuleSpecifier); + checkModuleExportName(node.name); if (getEmitDeclarations(compilerOptions)) { collectLinkedAliases( node.propertyName || node.name, @@ -88484,8 +89090,11 @@ function createTypeChecker(host) { true ); } - if (!node.parent.parent.moduleSpecifier) { + if (!hasModuleSpecifier) { const exportedName = node.propertyName || node.name; + if (exportedName.kind === 11 /* StringLiteral */) { + return; + } const symbol = resolveName( exportedName, exportedName.escapedText, @@ -88501,7 +89110,7 @@ function createTypeChecker(host) { markLinkedReferences(node, 7 /* ExportSpecifier */); } } else { - if (getESModuleInterop(compilerOptions) && moduleKind !== 4 /* System */ && (moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */) && idText(node.propertyName || node.name) === "default") { + if (getESModuleInterop(compilerOptions) && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < 4 /* System */ && moduleExportNameIsDefault(node.propertyName || node.name)) { checkExternalEmitHelpers(node, 131072 /* ImportDefault */); } } @@ -88527,7 +89136,7 @@ function createTypeChecker(host) { if (typeAnnotationNode) { checkTypeAssignableTo(checkExpressionCached(node.expression), getTypeFromTypeNode(typeAnnotationNode), node.expression); } - const isIllegalExportDefaultInCJS = !node.isExportEquals && !(node.flags & 33554432 /* Ambient */) && compilerOptions.verbatimModuleSyntax && (moduleKind === 1 /* CommonJS */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */); + const isIllegalExportDefaultInCJS = !node.isExportEquals && !(node.flags & 33554432 /* Ambient */) && compilerOptions.verbatimModuleSyntax && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === 1 /* CommonJS */; if (node.expression.kind === 80 /* Identifier */) { const id = node.expression; const sym = getExportSymbolOfValueSymbolIfExported(resolveEntityName( @@ -88607,9 +89216,7 @@ function createTypeChecker(host) { grammarErrorOnNode(node.expression, Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); } if (node.isExportEquals) { - if (moduleKind >= 5 /* ES2015 */ && moduleKind !== 200 /* Preserve */ && // deno: temporarily disable this one until Deno 2.0 (https://github.com/microsoft/TypeScript/pull/52109) - /* (node.flags & NodeFlags.Ambient && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.ESNext) || */ - (!(node.flags & 33554432 /* Ambient */) && getSourceFileOfNode(node).impliedNodeFormat !== 1 /* CommonJS */)) { + if (moduleKind >= 5 /* ES2015 */ && moduleKind !== 200 /* Preserve */ && (node.flags & 33554432 /* Ambient */ && host.getImpliedNodeFormatForEmit(getSourceFileOfNode(node)) === 99 /* ESNext */ || !(node.flags & 33554432 /* Ambient */) && host.getImpliedNodeFormatForEmit(getSourceFileOfNode(node)) !== 1 /* CommonJS */)) { grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); } else if (moduleKind === 4 /* System */ && !(node.flags & 33554432 /* Ambient */)) { grammarErrorOnNode(node, Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); @@ -88670,6 +89277,9 @@ function createTypeChecker(host) { } } function checkSourceElementWorker(node) { + if (getNodeCheckFlags(node) & 8388608 /* PartiallyTypeChecked */) { + return; + } if (canHaveJSDoc(node)) { forEach(node.jsDoc, ({ comment, tags }) => { checkJSDocCommentWorker(comment); @@ -89013,19 +89623,21 @@ function createTypeChecker(host) { currentNode = saveCurrentNode; (_b = tracing) == null ? void 0 : _b.pop(); } - function checkSourceFile(node) { + function checkSourceFile(node, nodesToCheck) { var _a, _b; (_a = tracing) == null ? void 0 : _a.push( tracing.Phase.Check, - "checkSourceFile", + nodesToCheck ? "checkSourceFileNodes" : "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true ); - mark("beforeCheck"); - checkSourceFileWorker(node); - mark("afterCheck"); - measure("Check", "beforeCheck", "afterCheck"); + const beforeMark = nodesToCheck ? "beforeCheckNodes" : "beforeCheck"; + const afterMark = nodesToCheck ? "afterCheckNodes" : "afterCheck"; + mark(beforeMark); + nodesToCheck ? checkSourceFileNodesWorker(node, nodesToCheck) : checkSourceFileWorker(node); + mark(afterMark); + measure("Check", beforeMark, afterMark); (_b = tracing) == null ? void 0 : _b.pop(); } function unusedIsError(kind, isAmbient) { @@ -89056,6 +89668,13 @@ function createTypeChecker(host) { clear(potentialWeakMapSetCollisions); clear(potentialReflectCollisions); clear(potentialUnusedRenamedBindingElementsInTypes); + if (links.flags & 8388608 /* PartiallyTypeChecked */) { + potentialThisCollisions = links.potentialThisCollisions; + potentialNewTargetCollisions = links.potentialNewTargetCollisions; + potentialWeakMapSetCollisions = links.potentialWeakMapSetCollisions; + potentialReflectCollisions = links.potentialReflectCollisions; + potentialUnusedRenamedBindingElementsInTypes = links.potentialUnusedRenamedBindingElementsInTypes; + } forEach(node.statements, checkSourceElement); checkSourceElement(node.endOfFileToken); checkDeferredNodes(node); @@ -89096,10 +89715,38 @@ function createTypeChecker(host) { links.flags |= 1 /* TypeChecked */; } } - function getDiagnostics2(sourceFile, ct) { + function checkSourceFileNodesWorker(file, nodes) { + const links = getNodeLinks(file); + if (!(links.flags & 1 /* TypeChecked */)) { + if (skipTypeChecking(file, compilerOptions, host)) { + return; + } + checkGrammarSourceFile(file); + clear(potentialThisCollisions); + clear(potentialNewTargetCollisions); + clear(potentialWeakMapSetCollisions); + clear(potentialReflectCollisions); + clear(potentialUnusedRenamedBindingElementsInTypes); + forEach(nodes, checkSourceElement); + checkDeferredNodes(file); + (links.potentialThisCollisions || (links.potentialThisCollisions = [])).push(...potentialThisCollisions); + (links.potentialNewTargetCollisions || (links.potentialNewTargetCollisions = [])).push(...potentialNewTargetCollisions); + (links.potentialWeakMapSetCollisions || (links.potentialWeakMapSetCollisions = [])).push(...potentialWeakMapSetCollisions); + (links.potentialReflectCollisions || (links.potentialReflectCollisions = [])).push(...potentialReflectCollisions); + (links.potentialUnusedRenamedBindingElementsInTypes || (links.potentialUnusedRenamedBindingElementsInTypes = [])).push( + ...potentialUnusedRenamedBindingElementsInTypes + ); + links.flags |= 8388608 /* PartiallyTypeChecked */; + for (const node of nodes) { + const nodeLinks2 = getNodeLinks(node); + nodeLinks2.flags |= 8388608 /* PartiallyTypeChecked */; + } + } + } + function getDiagnostics2(sourceFile, ct, nodesToCheck) { try { cancellationToken = ct; - return getDiagnosticsWorker(sourceFile); + return getDiagnosticsWorker(sourceFile, nodesToCheck); } finally { cancellationToken = void 0; } @@ -89110,20 +89757,23 @@ function createTypeChecker(host) { } deferredDiagnosticsCallbacks = []; } - function checkSourceFileWithEagerDiagnostics(sourceFile) { + function checkSourceFileWithEagerDiagnostics(sourceFile, nodesToCheck) { ensurePendingDiagnosticWorkComplete(); const oldAddLazyDiagnostics = addLazyDiagnostic; addLazyDiagnostic = (cb) => cb(); - checkSourceFile(sourceFile); + checkSourceFile(sourceFile, nodesToCheck); addLazyDiagnostic = oldAddLazyDiagnostics; } - function getDiagnosticsWorker(sourceFile) { + function getDiagnosticsWorker(sourceFile, nodesToCheck) { if (sourceFile) { ensurePendingDiagnosticWorkComplete(); const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length; - checkSourceFileWithEagerDiagnostics(sourceFile); + checkSourceFileWithEagerDiagnostics(sourceFile, nodesToCheck); const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName); + if (nodesToCheck) { + return semanticDiagnostics; + } const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics); @@ -89133,7 +89783,7 @@ function createTypeChecker(host) { } return semanticDiagnostics; } - forEach(host.getSourceFiles(), checkSourceFileWithEagerDiagnostics); + forEach(host.getSourceFiles(), (file) => checkSourceFileWithEagerDiagnostics(file)); return diagnostics.getDiagnostics(); } function getGlobalDiagnostics() { @@ -89661,7 +90311,11 @@ function createTypeChecker(host) { } function getExportSpecifierLocalTargetSymbol(node) { if (isExportSpecifier(node)) { - return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : resolveEntityName(node.propertyName || node.name, 111551 /* Value */ | 788968 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); + const name = node.propertyName || node.name; + return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : name.kind === 11 /* StringLiteral */ ? void 0 : ( + // Skip for invalid syntax like this: export { "x" } + resolveEntityName(name, 111551 /* Value */ | 788968 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */) + ); } else { return resolveEntityName(node, 111551 /* Value */ | 788968 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); } @@ -90007,7 +90661,7 @@ function createTypeChecker(host) { } function isReferencedAliasDeclaration(node, checkChildren) { Debug.assert(canCollectSymbolAliasAccessabilityData); - if (isAliasSymbolDeclaration2(node)) { + if (isAliasSymbolDeclaration(node)) { const symbol = getSymbolOfDeclaration(node); const links = symbol && getSymbolLinks(symbol); if (links == null ? void 0 : links.referenced) { @@ -90043,11 +90697,17 @@ function createTypeChecker(host) { const type = getTypeFromTypeNode(typeNode); return containsUndefinedType(type); } - function requiresAddingImplicitUndefined(parameter) { - return (isRequiredInitializedParameter(parameter) || isOptionalUninitializedParameterProperty(parameter)) && !declaredParameterTypeContainsUndefined(parameter); + function requiresAddingImplicitUndefined(parameter, enclosingDeclaration) { + return (isRequiredInitializedParameter(parameter, enclosingDeclaration) || isOptionalUninitializedParameterProperty(parameter)) && !declaredParameterTypeContainsUndefined(parameter); } - function isRequiredInitializedParameter(parameter) { - return !!strictNullChecks && !isOptionalParameter(parameter) && !isJSDocParameterTag(parameter) && !!parameter.initializer && !hasSyntacticModifier(parameter, 31 /* ParameterPropertyModifier */); + function isRequiredInitializedParameter(parameter, enclosingDeclaration) { + if (!strictNullChecks || isOptionalParameter(parameter) || isJSDocParameterTag(parameter) || !parameter.initializer) { + return false; + } + if (hasSyntacticModifier(parameter, 31 /* ParameterPropertyModifier */)) { + return !!enclosingDeclaration && isFunctionLikeDeclaration(enclosingDeclaration); + } + return true; } function isOptionalUninitializedParameterProperty(parameter) { return strictNullChecks && isOptionalParameter(parameter) && (isJSDocParameterTag(parameter) || !parameter.initializer) && hasSyntacticModifier(parameter, 31 /* ParameterPropertyModifier */); @@ -90094,7 +90754,7 @@ function createTypeChecker(host) { return !!(getNodeCheckFlags(node) & flag); } function calculateNodeCheckFlagWorker(node, flag) { - if (!compilerOptions.noCheck && canIncludeBindAndCheckDiagnsotics(getSourceFileOfNode(node), compilerOptions)) { + if (!compilerOptions.noCheck && canIncludeBindAndCheckDiagnostics(getSourceFileOfNode(node), compilerOptions)) { return; } const links = getNodeLinks(node); @@ -90156,17 +90816,19 @@ function createTypeChecker(host) { function checkChildIdentifiers(node2) { forEachNodeRecursively(node2, checkIdentifiers); } + function isExpressionNodeOrShorthandPropertyAssignmentName(node2) { + return isExpressionNode(node2) || isShorthandPropertyAssignment(node2.parent) && (node2.parent.objectAssignmentInitializer ?? node2.parent.name) === node2; + } function checkSingleIdentifier(node2) { const nodeLinks2 = getNodeLinks(node2); - nodeLinks2.calculatedFlags |= 536870912 /* ConstructorReference */ | 16384 /* CapturedBlockScopedBinding */ | 32768 /* BlockScopedBindingInLoop */; - if (isIdentifier(node2) && isExpressionNode(node2) && !(isPropertyAccessExpression(node2.parent) && node2.parent.name === node2)) { - const s = getSymbolAtLocation( - node2, - /*ignoreErrors*/ - true - ); - if (s && s !== unknownSymbol) { - checkIdentifierCalculateNodeCheckFlags(node2, s); + nodeLinks2.calculatedFlags |= 536870912 /* ConstructorReference */; + if (isIdentifier(node2)) { + nodeLinks2.calculatedFlags |= 32768 /* BlockScopedBindingInLoop */ | 16384 /* CapturedBlockScopedBinding */; + if (isExpressionNodeOrShorthandPropertyAssignmentName(node2) && !(isPropertyAccessExpression(node2.parent) && node2.parent.name === node2)) { + const s = getResolvedSymbol(node2); + if (s && s !== unknownSymbol) { + checkIdentifierCalculateNodeCheckFlags(node2, s); + } } } } @@ -90319,14 +90981,14 @@ function createTypeChecker(host) { return 11 /* ObjectType */; } } - function createTypeOfDeclaration(declarationIn, enclosingDeclaration, flags, tracker) { + function createTypeOfDeclaration(declarationIn, enclosingDeclaration, flags, internalFlags, tracker) { const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { return factory.createToken(133 /* AnyKeyword */); } const symbol = getSymbolOfDeclaration(declaration); const type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */)) ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; - return nodeBuilder.serializeTypeForDeclaration(declaration, type, symbol, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); + return nodeBuilder.serializeTypeForDeclaration(declaration, type, symbol, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, internalFlags, tracker); } function isDeclarationWithPossibleInnerTypeNodeReuse(declaration) { return isFunctionLike(declaration) || isExportAssignment(declaration) || isVariableLike(declaration); @@ -90369,14 +91031,14 @@ function createTypeChecker(host) { } return candidateExpr; } - function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn, enclosingDeclaration, flags, tracker) { + function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn, enclosingDeclaration, flags, internalFlags, tracker) { const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike); if (!signatureDeclaration) { return factory.createToken(133 /* AnyKeyword */); } - return nodeBuilder.serializeReturnTypeForSignature(getSignatureFromDeclaration(signatureDeclaration), enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); + return nodeBuilder.serializeReturnTypeForSignature(getSignatureFromDeclaration(signatureDeclaration), enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, internalFlags, tracker); } - function createTypeOfExpression(exprIn, enclosingDeclaration, flags, tracker) { + function createTypeOfExpression(exprIn, enclosingDeclaration, flags, internalFlags, tracker) { const expr = getParseTreeNode(exprIn, isExpression); if (!expr) { return factory.createToken(133 /* AnyKeyword */); @@ -90389,6 +91051,7 @@ function createTypeChecker(host) { void 0, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, + internalFlags, tracker ); } @@ -90494,6 +91157,8 @@ function createTypeChecker(host) { enclosing, /*flags*/ void 0, + /*internalFlags*/ + void 0, tracker ) : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse(); if (enumResult) return enumResult; @@ -90622,17 +91287,18 @@ function createTypeChecker(host) { const parseDecl = getParseTreeNode(decl); return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl); }, - getDeclarationStatementsForSourceFile: (node, flags, tracker) => { + getDeclarationStatementsForSourceFile: (node, flags, internalFlags, tracker) => { const n = getParseTreeNode(node); Debug.assert(n && n.kind === 307 /* SourceFile */, "Non-sourcefile node passed into getDeclarationsForSourceFile"); const sym = getSymbolOfDeclaration(node); if (!sym) { - return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker); + return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, internalFlags, tracker); } resolveExternalModuleSymbol(sym); - return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker); + return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, internalFlags, tracker); }, - isImportRequiredByAugmentation + isImportRequiredByAugmentation, + isDefinitelyReferenceToGlobalSymbolObject }; function isImportRequiredByAugmentation(node) { const file = getSourceFileOfNode(node); @@ -91113,7 +91779,7 @@ function createTypeChecker(host) { break; case 95 /* ExportKeyword */: if (compilerOptions.verbatimModuleSyntax && !(node.flags & 33554432 /* Ambient */) && node.kind !== 265 /* TypeAliasDeclaration */ && node.kind !== 264 /* InterfaceDeclaration */ && // ModuleDeclaration needs to be checked that it is uninstantiated later - node.kind !== 267 /* ModuleDeclaration */ && node.parent.kind === 307 /* SourceFile */ && (moduleKind === 1 /* CommonJS */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */)) { + node.kind !== 267 /* ModuleDeclaration */ && node.parent.kind === 307 /* SourceFile */ && host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === 1 /* CommonJS */) { return grammarErrorOnNode(modifier, Diagnostics.A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); } if (flags & 32 /* Export */) { @@ -91620,6 +92286,13 @@ function createTypeChecker(host) { if (name.kind === 9 /* NumericLiteral */) { checkGrammarNumericLiteral(name); } + if (name.kind === 10 /* BigIntLiteral */) { + addErrorOrSuggestion( + /*isError*/ + true, + createDiagnosticForNode(name, Diagnostics.A_bigint_literal_cannot_be_used_as_a_property_name) + ); + } currentKind = 4 /* PropertyAssignment */; break; case 174 /* MethodDeclaration */: @@ -91716,6 +92389,7 @@ function createTypeChecker(host) { } case 7 /* ES2022 */: case 99 /* ESNext */: + case 200 /* Preserve */: case 4 /* System */: if (languageVersion >= 4 /* ES2017 */) { break; @@ -92022,7 +92696,7 @@ function createTypeChecker(host) { const message = node.initializer ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions : !node.type ? Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations : Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context; return grammarErrorOnNode(node.exclamationToken, message); } - if ((moduleKind < 5 /* ES2015 */ || getSourceFileOfNode(node).impliedNodeFormat === 1 /* CommonJS */) && moduleKind !== 4 /* System */ && !(node.parent.parent.flags & 33554432 /* Ambient */) && hasSyntacticModifier(node.parent.parent, 32 /* Export */)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < 4 /* System */ && !(node.parent.parent.flags & 33554432 /* Ambient */) && hasSyntacticModifier(node.parent.parent, 32 /* Export */)) { checkESModuleMarker(node.name); } return !!blockScopeKind && checkGrammarNameInLetOrConstDeclarations(node.name); @@ -92290,8 +92964,8 @@ function createTypeChecker(host) { return false; } function getAmbientModules(sourceFile) { - const isNode2 = denoContext.hasNodeSourceFile(sourceFile); - if (isNode2) { + const isNode = denoContext.hasNodeSourceFile(sourceFile); + if (isNode) { if (!nodeAmbientModulesCache) { nodeAmbientModulesCache = getAmbientModules2(denoContext.combinedGlobals); } @@ -92343,11 +93017,11 @@ function createTypeChecker(host) { return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); } const nodeArguments = node.arguments; - if (moduleKind !== 99 /* ESNext */ && moduleKind !== 199 /* NodeNext */ && moduleKind !== 100 /* Node16 */) { + if (moduleKind !== 99 /* ESNext */ && moduleKind !== 199 /* NodeNext */ && moduleKind !== 100 /* Node16 */ && moduleKind !== 200 /* Preserve */) { checkGrammarForDisallowedTrailingComma(nodeArguments); if (nodeArguments.length > 1) { const importAttributesArgument = nodeArguments[1]; - return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext); + return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_nodenext_or_preserve); } } if (nodeArguments.length === 0 || nodeArguments.length > 2) { @@ -92486,7 +93160,7 @@ function isDeclarationNameOrImportPropertyName(name) { switch (name.parent.kind) { case 276 /* ImportSpecifier */: case 281 /* ExportSpecifier */: - return isIdentifier(name); + return isIdentifier(name) || name.kind === 11 /* StringLiteral */; default: return isDeclarationName(name); } @@ -92535,7 +93209,9 @@ function createBasicNodeBuilderModuleSpecifierResolutionHost(host) { isSourceOfProjectReferenceRedirect: (fileName) => host.isSourceOfProjectReferenceRedirect(fileName), fileExists: (fileName) => host.fileExists(fileName), getFileIncludeReasons: () => host.getFileIncludeReasons(), - readFile: host.readFile ? (fileName) => host.readFile(fileName) : void 0 + readFile: host.readFile ? (fileName) => host.readFile(fileName) : void 0, + getDefaultResolutionModeForFile: (file) => host.getDefaultResolutionModeForFile(file), + getModeForResolutionAtIndex: (file, index) => host.getModeForResolutionAtIndex(file, index) }; } var SymbolTrackerImpl = class _SymbolTrackerImpl { @@ -93729,7 +94405,7 @@ var visitEachChildTable = { return context.factory.updateImportSpecifier( node, node.isTypeOnly, - nodeVisitor(node.propertyName, visitor, isIdentifier), + nodeVisitor(node.propertyName, visitor, isModuleExportName), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)) ); }, @@ -93760,8 +94436,8 @@ var visitEachChildTable = { return context.factory.updateExportSpecifier( node, node.isTypeOnly, - nodeVisitor(node.propertyName, visitor, isIdentifier), - Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)) + nodeVisitor(node.propertyName, visitor, isModuleExportName), + Debug.checkDefined(nodeVisitor(node.name, visitor, isModuleExportName)) ); }, // Module references @@ -94477,7 +95153,7 @@ function containsDefaultReference(node) { return some(node.elements, isNamedDefaultReference); } function isNamedDefaultReference(e) { - return e.propertyName !== void 0 ? e.propertyName.escapedText === "default" /* Default */ : e.name.escapedText === "default" /* Default */; + return moduleExportNameIsDefault(e.propertyName || e.name); } function chainBundle(context, transformSourceFile) { return transformSourceFileOrBundle; @@ -94553,9 +95229,10 @@ function collectExternalModuleInfo(context, sourceFile) { hasImportDefault || (hasImportDefault = containsDefaultReference(node.exportClause)); } else { const name = node.exportClause.name; - if (!uniqueExports.get(idText(name))) { + const nameText = moduleExportNameTextUnescaped(name); + if (!uniqueExports.get(nameText)) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(idText(name), true); + uniqueExports.set(nameText, true); exportedNames = append(exportedNames, name); } hasImportStar = true; @@ -94613,26 +95290,29 @@ function collectExternalModuleInfo(context, sourceFile) { return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, exportedFunctions, externalHelpersImportDeclaration }; function addExportedNamesForExportDeclaration(node) { for (const specifier of cast(node.exportClause, isNamedExports).elements) { - if (!uniqueExports.get(idText(specifier.name))) { + const specifierNameText = moduleExportNameTextUnescaped(specifier.name); + if (!uniqueExports.get(specifierNameText)) { const name = specifier.propertyName || specifier.name; - if (!node.moduleSpecifier) { - exportSpecifiers.add(name, specifier); - } - const decl = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); - if (decl) { - if (decl.kind === 262 /* FunctionDeclaration */) { - addExportedFunctionDeclaration(decl, specifier.name, specifier.name.escapedText === "default" /* Default */); - continue; + if (name.kind !== 11 /* StringLiteral */) { + if (!node.moduleSpecifier) { + exportSpecifiers.add(name, specifier); + } + const decl = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); + if (decl) { + if (decl.kind === 262 /* FunctionDeclaration */) { + addExportedFunctionDeclaration(decl, specifier.name, moduleExportNameIsDefault(specifier.name)); + continue; + } + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name); } - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name); } - uniqueExports.set(idText(specifier.name), true); + uniqueExports.set(specifierNameText, true); exportedNames = append(exportedNames, specifier.name); } } } function addExportedFunctionDeclaration(node, name, isDefault) { - exportedFunctions.add(node); + exportedFunctions.add(getOriginalNode(node, isFunctionDeclaration)); if (isDefault) { if (!hasExportDefault) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name ?? context.factory.getDeclarationName(node)); @@ -94640,9 +95320,10 @@ function collectExternalModuleInfo(context, sourceFile) { } } else { name ?? (name = node.name); - if (!uniqueExports.get(idText(name))) { + const nameText = moduleExportNameTextUnescaped(name); + if (!uniqueExports.get(nameText)) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(idText(name), true); + uniqueExports.set(nameText, true); } } } @@ -95358,7 +96039,7 @@ function createDestructuringPropertyAccess(flattenContext, value, propertyName) propertyName ); return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression); - } else if (isStringOrNumericLiteralLike(propertyName)) { + } else if (isStringOrNumericLiteralLike(propertyName) || isBigIntLiteral(propertyName)) { const argumentExpression = factory2.cloneNode(propertyName); return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression); } else { @@ -95783,7 +96464,6 @@ function transformTypeScript(context) { let currentNamespaceContainerName; let currentLexicalScope; let currentScopeFirstDeclarationsOfName; - let currentClassHasParameterProperties; let enabledSubstitutions; let applicableSubstitutions; return transformSourceFileOrBundle; @@ -95811,14 +96491,12 @@ function transformTypeScript(context) { function saveStateAndInvoke(node, f) { const savedCurrentScope = currentLexicalScope; const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; - const savedCurrentClassHasParameterProperties = currentClassHasParameterProperties; onBeforeVisitNode(node); const visited = f(node); if (currentLexicalScope !== savedCurrentScope) { currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; } currentLexicalScope = savedCurrentScope; - currentClassHasParameterProperties = savedCurrentClassHasParameterProperties; return visited; } function onBeforeVisitNode(node) { @@ -96451,7 +97129,7 @@ function transformTypeScript(context) { } function visitPropertyNameOfClassElement(member) { const name = member.name; - if (isComputedPropertyName(name) && (!hasStaticModifier(member) && currentClassHasParameterProperties || hasDecorators(member) && legacyDecorators)) { + if (legacyDecorators && isComputedPropertyName(name) && hasDecorators(member)) { const expression = visitNode(name.expression, visitor, isExpression); Debug.assert(expression); const innerExpression = skipPartiallyEmittedExpressions(expression); @@ -96826,7 +97504,7 @@ function transformTypeScript(context) { return updated; } function visitParenthesizedExpression(node) { - const innerExpression = skipOuterExpressions(node.expression, ~6 /* Assertions */); + const innerExpression = skipOuterExpressions(node.expression, ~(6 /* Assertions */ | 16 /* ExpressionsWithTypeArguments */)); if (isAssertionExpression(innerExpression) || isSatisfiesExpression(innerExpression)) { const expression = visitNode(node.expression, visitor, isExpression); Debug.assert(expression); @@ -97632,8 +98310,6 @@ function transformClassFields(context) { return node; } switch (node.kind) { - case 129 /* AccessorKeyword */: - return Debug.fail("Use `modifierVisitor` instead."); case 263 /* ClassDeclaration */: return visitClassDeclaration(node); case 231 /* ClassExpression */: @@ -99046,6 +99722,7 @@ function transformClassFields(context) { addRange(statementsOut, visitNodes2(statementsIn, visitor, isStatement, statementOffset)); } function transformConstructorBody(node, constructor, isDerivedClass) { + var _a; const instanceProperties = getProperties( node, /*requireInitializer*/ @@ -99139,12 +99816,12 @@ function transformClassFields(context) { setTextRange( factory2.createNodeArray(statements), /*location*/ - constructor ? constructor.body.statements : node.members + ((_a = constructor == null ? void 0 : constructor.body) == null ? void 0 : _a.statements) ?? node.members ), multiLine ), /*location*/ - constructor ? constructor.body : void 0 + constructor == null ? void 0 : constructor.body ); } function addPropertyOrClassStaticBlockStatements(statements, properties, receiver) { @@ -106148,7 +106825,7 @@ function transformJsx(context) { const name = node.name; if (isIdentifier(name)) { const text = idText(name); - return /^[A-Za-z_]\w*$/.test(text) ? name : factory2.createStringLiteral(text); + return /^[A-Z_]\w*$/i.test(text) ? name : factory2.createStringLiteral(text); } return factory2.createStringLiteral(idText(name.namespace) + ":" + idText(name.name)); } @@ -108272,7 +108949,7 @@ function transformES2015(context) { statement, /*outermostLabeledStatement*/ node - ) : factory2.restoreEnclosingLabel(Debug.checkDefined(visitNode(statement, visitor, isStatement, factory2.liftToBlock)), node, convertedLoopState && resetLabel); + ) : factory2.restoreEnclosingLabel(visitNode(statement, visitor, isStatement, factory2.liftToBlock) ?? setTextRange(factory2.createEmptyStatement(), statement), node, convertedLoopState && resetLabel); } function visitIterationStatement(node, outermostLabeledStatement) { switch (node.kind) { @@ -111929,7 +112606,7 @@ function transformModule(context) { factory2.createExpressionStatement( reduceLeft( currentModuleInfo.exportedNames.slice(i, i + chunkSize), - (prev, nextId) => factory2.createAssignment(factory2.createPropertyAccessExpression(factory2.createIdentifier("exports"), factory2.createIdentifier(idText(nextId))), prev), + (prev, nextId) => nextId.kind === 11 /* StringLiteral */ ? factory2.createAssignment(factory2.createElementAccessExpression(factory2.createIdentifier("exports"), factory2.createStringLiteral(nextId.text)), prev) : factory2.createAssignment(factory2.createPropertyAccessExpression(factory2.createIdentifier("exports"), factory2.createIdentifier(idText(nextId))), prev), factory2.createVoidZero() ) ) @@ -112252,7 +112929,10 @@ function transformModule(context) { append(statements, createUnderscoreUnderscoreESModule()); } if (some(currentModuleInfo.exportedNames)) { - append(statements, factory2.createExpressionStatement(reduceLeft(currentModuleInfo.exportedNames, (prev, nextId) => factory2.createAssignment(factory2.createPropertyAccessExpression(factory2.createIdentifier("exports"), factory2.createIdentifier(idText(nextId))), prev), factory2.createVoidZero()))); + append( + statements, + factory2.createExpressionStatement(reduceLeft(currentModuleInfo.exportedNames, (prev, nextId) => nextId.kind === 11 /* StringLiteral */ ? factory2.createAssignment(factory2.createElementAccessExpression(factory2.createIdentifier("exports"), factory2.createStringLiteral(nextId.text)), prev) : factory2.createAssignment(factory2.createPropertyAccessExpression(factory2.createIdentifier("exports"), factory2.createIdentifier(idText(nextId))), prev), factory2.createVoidZero())) + ); } for (const f of currentModuleInfo.exportedFunctions) { appendExportsOfHoistedDeclaration(statements, f); @@ -112382,7 +113062,7 @@ function transformModule(context) { case 354 /* PartiallyEmittedExpression */: return visitPartiallyEmittedExpression(node, valueIsDiscarded); case 213 /* CallExpression */: - if (isImportCall(node) && currentSourceFile.impliedNodeFormat === void 0) { + if (isImportCall(node) && host.shouldTransformImportCall(currentSourceFile)) { return visitImportCallExpression(node); } break; @@ -112575,7 +113255,7 @@ function transformModule(context) { return factory2.updateLabeledStatement( node, node.label, - Debug.checkDefined(visitNode(node.statement, topLevelNestedVisitor, isStatement, factory2.liftToBlock)) + visitNode(node.statement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ?? setTextRange(factory2.createEmptyStatement(), node.statement) ); } function visitWithStatement(node) { @@ -112589,7 +113269,7 @@ function transformModule(context) { return factory2.updateIfStatement( node, visitNode(node.expression, visitor, isExpression), - Debug.checkDefined(visitNode(node.thenStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock)), + visitNode(node.thenStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ?? factory2.createBlock([]), visitNode(node.elseStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ); } @@ -113123,17 +113803,16 @@ function transformModule(context) { ); } for (const specifier of node.exportClause.elements) { - const exportNeedsImportDefault = !!getESModuleInterop(compilerOptions) && !(getInternalEmitFlags(node) & 2 /* NeverApplyImportHelper */) && idText(specifier.propertyName || specifier.name) === "default"; - const exportedValue = factory2.createPropertyAccessExpression( - exportNeedsImportDefault ? emitHelpers().createImportDefaultHelper(generatedName) : generatedName, - specifier.propertyName || specifier.name - ); + const specifierName = specifier.propertyName || specifier.name; + const exportNeedsImportDefault = !!getESModuleInterop(compilerOptions) && !(getInternalEmitFlags(node) & 2 /* NeverApplyImportHelper */) && moduleExportNameIsDefault(specifierName); + const target = exportNeedsImportDefault ? emitHelpers().createImportDefaultHelper(generatedName) : generatedName; + const exportedValue = specifierName.kind === 11 /* StringLiteral */ ? factory2.createElementAccessExpression(target, specifierName) : factory2.createPropertyAccessExpression(target, specifierName); statements.push( setOriginalNode( setTextRange( factory2.createExpressionStatement( createExportExpression( - factory2.getExportName(specifier), + specifier.name.kind === 11 /* StringLiteral */ ? factory2.cloneNode(specifier.name) : factory2.getExportName(specifier), exportedValue, /*location*/ void 0, @@ -113158,7 +113837,7 @@ function transformModule(context) { factory2.cloneNode(node.exportClause.name), getHelperExpressionForExport( node, - moduleKind !== 2 /* AMD */ ? createRequireCall2(node) : isExportNamespaceAsDefaultDeclaration(node) ? generatedName : factory2.createIdentifier(idText(node.exportClause.name)) + moduleKind !== 2 /* AMD */ ? createRequireCall2(node) : isExportNamespaceAsDefaultDeclaration(node) ? generatedName : node.exportClause.name.kind === 11 /* StringLiteral */ ? generatedName : factory2.createIdentifier(idText(node.exportClause.name)) ) ) ), @@ -113488,10 +114167,13 @@ function transformModule(context) { return statements; } function appendExportStatement(statements, seen, exportName, expression, location, allowComments, liveBinding) { - if (!seen.has(exportName)) { + if (exportName.kind !== 11 /* StringLiteral */) { + if (seen.has(exportName)) { + return statements; + } seen.set(exportName, true); - statements = append(statements, createExportStatement(exportName, expression, location, allowComments, liveBinding)); } + statements = append(statements, createExportStatement(exportName, expression, location, allowComments, liveBinding)); return statements; } function createUnderscoreUnderscoreESModule() { @@ -113561,7 +114243,10 @@ function transformModule(context) { ]) ] ) : factory2.createAssignment( - factory2.createPropertyAccessExpression( + name.kind === 11 /* StringLiteral */ ? factory2.createElementAccessExpression( + factory2.createIdentifier("exports"), + factory2.cloneNode(name) + ) : factory2.createPropertyAccessExpression( factory2.createIdentifier("exports"), factory2.cloneNode(name) ), @@ -113697,11 +114382,9 @@ function transformModule(context) { ); } else if (isImportSpecifier(importDeclaration)) { const name = importDeclaration.propertyName || importDeclaration.name; + const target = factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration); return setTextRange( - factory2.createPropertyAccessExpression( - factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration), - factory2.cloneNode(name) - ), + name.kind === 11 /* StringLiteral */ ? factory2.createElementAccessExpression(target, factory2.cloneNode(name)) : factory2.createPropertyAccessExpression(target, factory2.cloneNode(name)), /*location*/ node ); @@ -113989,7 +114672,7 @@ function transformSystemModule(context) { const exportedNames = []; if (moduleInfo.exportedNames) { for (const exportedLocalName of moduleInfo.exportedNames) { - if (exportedLocalName.escapedText === "default") { + if (moduleExportNameIsDefault(exportedLocalName)) { continue; } exportedNames.push( @@ -114167,10 +114850,10 @@ function transformSystemModule(context) { for (const e of entry.exportClause.elements) { properties.push( factory2.createPropertyAssignment( - factory2.createStringLiteral(idText(e.name)), + factory2.createStringLiteral(moduleExportNameTextUnescaped(e.name)), factory2.createElementAccessExpression( parameterName, - factory2.createStringLiteral(idText(e.propertyName || e.name)) + factory2.createStringLiteral(moduleExportNameTextUnescaped(e.propertyName || e.name)) ) ) ); @@ -114197,7 +114880,7 @@ function transformSystemModule(context) { /*typeArguments*/ void 0, [ - factory2.createStringLiteral(idText(entry.exportClause.name)), + factory2.createStringLiteral(moduleExportNameTextUnescaped(entry.exportClause.name)), parameterName ] ) @@ -114537,7 +115220,7 @@ function transformSystemModule(context) { const exportSpecifiers = moduleInfo.exportSpecifiers.get(name); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { - if (exportSpecifier.name.escapedText !== excludeName) { + if (moduleExportNameTextUnescaped(exportSpecifier.name) !== excludeName) { statements = appendExportStatement(statements, exportSpecifier.name, name); } } @@ -114689,7 +115372,7 @@ function transformSystemModule(context) { return factory2.updateLabeledStatement( node, node.label, - Debug.checkDefined(visitNode(node.statement, topLevelNestedVisitor, isStatement, factory2.liftToBlock)) + visitNode(node.statement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ?? factory2.createExpressionStatement(factory2.createIdentifier("")) ); } function visitWithStatement(node) { @@ -114703,7 +115386,7 @@ function transformSystemModule(context) { return factory2.updateIfStatement( node, visitNode(node.expression, visitor, isExpression), - Debug.checkDefined(visitNode(node.thenStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock)), + visitNode(node.thenStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ?? factory2.createBlock([]), visitNode(node.elseStatement, topLevelNestedVisitor, isStatement, factory2.liftToBlock) ); } @@ -114958,13 +115641,12 @@ function transformSystemModule(context) { node ); } else if (isImportSpecifier(importDeclaration)) { + const importedName = importDeclaration.propertyName || importDeclaration.name; + const target = factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration); return setTextRange( factory2.createPropertyAssignment( factory2.cloneNode(name), - factory2.createPropertyAccessExpression( - factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration), - factory2.cloneNode(importDeclaration.propertyName || importDeclaration.name) - ) + importedName.kind === 11 /* StringLiteral */ ? factory2.createElementAccessExpression(target, factory2.cloneNode(importedName)) : factory2.createPropertyAccessExpression(target, factory2.cloneNode(importedName)) ), /*location*/ node @@ -115007,11 +115689,10 @@ function transformSystemModule(context) { node ); } else if (isImportSpecifier(importDeclaration)) { + const importedName = importDeclaration.propertyName || importDeclaration.name; + const target = factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration); return setTextRange( - factory2.createPropertyAccessExpression( - factory2.getGeneratedNameForNode(((_b = (_a = importDeclaration.parent) == null ? void 0 : _a.parent) == null ? void 0 : _b.parent) || importDeclaration), - factory2.cloneNode(importDeclaration.propertyName || importDeclaration.name) - ), + importedName.kind === 11 /* StringLiteral */ ? factory2.createElementAccessExpression(target, factory2.cloneNode(importedName)) : factory2.createPropertyAccessExpression(target, factory2.cloneNode(importedName)), /*location*/ node ); @@ -115377,8 +116058,8 @@ function transformECMAScriptModule(context) { } } -// src/compiler/transformers/module/node.ts -function transformNodeModule(context) { +// src/compiler/transformers/module/impliedNodeFormatDependent.ts +function transformImpliedNodeFormatDependentModule(context) { const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; const esmTransform = transformECMAScriptModule(context); @@ -115389,6 +116070,7 @@ function transformNodeModule(context) { const cjsTransform = transformModule(context); const cjsOnSubstituteNode = context.onSubstituteNode; const cjsOnEmitNode = context.onEmitNode; + const getEmitModuleFormatOfFile2 = (file) => context.getEmitHost().getEmitModuleFormatOfFile(file); context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; context.enableSubstitution(307 /* SourceFile */); @@ -115403,7 +116085,7 @@ function transformNodeModule(context) { if (!currentSourceFile) { return previousOnSubstituteNode(hint, node); } - if (currentSourceFile.impliedNodeFormat === 99 /* ESNext */) { + if (getEmitModuleFormatOfFile2(currentSourceFile) >= 5 /* ES2015 */) { return esmOnSubstituteNode(hint, node); } return cjsOnSubstituteNode(hint, node); @@ -115416,13 +116098,13 @@ function transformNodeModule(context) { if (!currentSourceFile) { return previousOnEmitNode(hint, node, emitCallback); } - if (currentSourceFile.impliedNodeFormat === 99 /* ESNext */) { + if (getEmitModuleFormatOfFile2(currentSourceFile) >= 5 /* ES2015 */) { return esmOnEmitNode(hint, node, emitCallback); } return cjsOnEmitNode(hint, node, emitCallback); } function getModuleTransformForFile(file) { - return file.impliedNodeFormat === 99 /* ESNext */ ? esmTransform : cjsTransform; + return getEmitModuleFormatOfFile2(file) >= 5 /* ES2015 */ ? esmTransform : cjsTransform; } function transformSourceFile(node) { if (node.isDeclarationFile) { @@ -115844,7 +116526,11 @@ function createGetIsolatedDeclarationErrors(resolver) { if (isSetAccessor(node.parent)) { return createAccessorTypeError(node.parent); } - const addUndefined = resolver.requiresAddingImplicitUndefined(node); + const addUndefined = resolver.requiresAddingImplicitUndefined( + node, + /*enclosingDeclaration*/ + void 0 + ); if (!addUndefined && node.initializer) { return createExpressionError(node.initializer); } @@ -115899,19 +116585,19 @@ function createGetIsolatedDeclarationErrors(resolver) { function getDeclarationDiagnostics(host, resolver, file) { const compilerOptions = host.getCompilerOptions(); const files = filter(getSourceFilesToEmit(host, file), isSourceFileNotJson); - const result = transformNodes( + return contains(files, file) ? transformNodes( resolver, host, factory, compilerOptions, - file ? contains(files, file) ? [file] : emptyArray : files, + [file], [transformDeclarations], /*allowDtsFiles*/ false - ); - return result.diagnostics; + ).diagnostics : void 0; } -var declarationEmitNodeBuilderFlags = 1024 /* MultilineObjectLiterals */ | 2048 /* WriteClassExpressionAsTypeLiteral */ | 4096 /* UseTypeOfFunction */ | 8 /* UseStructuralFallback */ | 524288 /* AllowEmptyTuple */ | 1 /* AllowUnresolvedNames */ | 4 /* GenerateNamesForShadowedTypeParams */ | 1 /* NoTruncation */; +var declarationEmitNodeBuilderFlags = 1024 /* MultilineObjectLiterals */ | 2048 /* WriteClassExpressionAsTypeLiteral */ | 4096 /* UseTypeOfFunction */ | 8 /* UseStructuralFallback */ | 524288 /* AllowEmptyTuple */ | 4 /* GenerateNamesForShadowedTypeParams */ | 1 /* NoTruncation */; +var declarationEmitInternalNodeBuilderFlags = 8 /* AllowUnresolvedNames */; function transformDeclarations(context) { const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context"); let getSymbolAccessibilityDiagnostic = throwDiagnostic; @@ -115963,6 +116649,7 @@ function transformDeclarations(context) { } function reportInferenceFallback(node) { if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return; + if (getSourceFileOfNode(node) !== currentSourceFile) return; if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) { reportExpandoFunctionErrors(node); } else { @@ -116007,7 +116694,10 @@ function transformDeclarations(context) { function reportPrivateInBaseOfClassExpression(propertyName) { if (errorNameNode || errorFallbackNode) { context.addDiagnostic( - createDiagnosticForNode(errorNameNode || errorFallbackNode, Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName) + addRelatedInfo( + createDiagnosticForNode(errorNameNode || errorFallbackNode, Diagnostics.Property_0_of_exported_anonymous_class_type_may_not_be_private_or_protected, propertyName), + ...isVariableDeclaration((errorNameNode || errorFallbackNode).parent) ? [createDiagnosticForNode(errorNameNode || errorFallbackNode, Diagnostics.Add_a_type_annotation_to_the_variable_0, errorDeclarationNameWithFallback())] : [] + ) ); } } @@ -116063,7 +116753,7 @@ function transformDeclarations(context) { diagnosticMessage: s.errorModuleName ? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit : Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit, errorNode: s.errorNode || sourceFile }; - const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker); + const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker); getSymbolAccessibilityDiagnostic = oldDiag; return result; } @@ -116316,7 +117006,7 @@ function transformDeclarations(context) { if (shouldPrintWithInitializer(node)) { return; } - const shouldAddImplicitUndefined = node.kind === 169 /* Parameter */ && resolver.requiresAddingImplicitUndefined(node); + const shouldAddImplicitUndefined = node.kind === 169 /* Parameter */ && resolver.requiresAddingImplicitUndefined(node, enclosingDeclaration); if (type && !shouldAddImplicitUndefined) { return visitNode(type, visitDeclarationSubtree, isTypeNode); } @@ -116333,7 +117023,7 @@ function transformDeclarations(context) { case 172 /* PropertyDeclaration */: case 208 /* BindingElement */: case 260 /* VariableDeclaration */: - typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker); + typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker); break; case 262 /* FunctionDeclaration */: case 180 /* ConstructSignature */: @@ -116341,7 +117031,7 @@ function transformDeclarations(context) { case 174 /* MethodDeclaration */: case 177 /* GetAccessor */: case 179 /* CallSignature */: - typeNode = resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker); + typeNode = resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker); break; default: Debug.assertNever(node); @@ -116601,15 +117291,17 @@ function transformDeclarations(context) { if (isDeclarationAndNotVisible(input)) return; if (hasDynamicName(input)) { if (isolatedDeclarations) { - if (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent)) { - context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations)); - return; - } else if ( - // Type declarations just need to double-check that the input computed name is an entity name expression - (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent)) && !isEntityNameExpression(input.name.expression) - ) { - context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations)); - return; + if (!resolver.isDefinitelyReferenceToGlobalSymbolObject(input.name.expression)) { + if (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent)) { + context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations)); + return; + } else if ( + // Type declarations just need to double-check that the input computed name is an entity name expression + (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent)) && !isEntityNameExpression(input.name.expression) + ) { + context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations)); + return; + } } } else if (!resolver.isLateBound(getParseTreeNode(input)) || !isEntityNameExpression(input.name.expression)) { return; @@ -116940,7 +117632,7 @@ function transformDeclarations(context) { newId, /*exclamationToken*/ void 0, - resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), + resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker), /*initializer*/ void 0 ); @@ -117066,7 +117758,7 @@ function transformDeclarations(context) { return void 0; } getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); - const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags | -2147483648 /* NoSyntacticPrinter */, symbolTracker); + const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags | 2 /* NoSyntacticPrinter */, symbolTracker); getSymbolAccessibilityDiagnostic = oldDiag; const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr); const name = isNonContextualKeywordName ? factory2.getGeneratedNameForNode(p.valueDeclaration) : factory2.createIdentifier(nameStr); @@ -117269,7 +117961,7 @@ function transformDeclarations(context) { newId, /*exclamationToken*/ void 0, - resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), + resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker), /*initializer*/ void 0 ); @@ -117542,17 +118234,18 @@ function isProcessedComponent(node) { // src/compiler/transformer.ts function getModuleTransformer(moduleKind) { switch (moduleKind) { + case 200 /* Preserve */: + return transformECMAScriptModule; case 99 /* ESNext */: case 7 /* ES2022 */: case 6 /* ES2020 */: case 5 /* ES2015 */: - case 200 /* Preserve */: - return transformECMAScriptModule; - case 4 /* System */: - return transformSystemModule; case 100 /* Node16 */: case 199 /* NodeNext */: - return transformNodeModule; + case 1 /* CommonJS */: + return transformImpliedNodeFormatDependentModule; + case 4 /* System */: + return transformSystemModule; default: return transformModule; } @@ -117976,16 +118669,16 @@ function isBuildInfoFile(file) { function forEachEmittedFile(host, action, sourceFilesOrTargetSourceFile, forceDtsEmit = false, onlyBuildInfo, includeBuildInfo) { const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); const options = host.getCompilerOptions(); - if (options.outFile) { - if (sourceFiles.length) { - const bundle = factory.createBundle(sourceFiles); - const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle); - if (result) { - return result; + if (!onlyBuildInfo) { + if (options.outFile) { + if (sourceFiles.length) { + const bundle = factory.createBundle(sourceFiles); + const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle); + if (result) { + return result; + } } - } - } else { - if (!onlyBuildInfo) { + } else { for (const sourceFile of sourceFiles) { const result = action(getOutputPathsFor(sourceFile, host, forceDtsEmit), sourceFile); if (result) { @@ -117993,19 +118686,19 @@ function forEachEmittedFile(host, action, sourceFilesOrTargetSourceFile, forceDt } } } - if (includeBuildInfo) { - const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); - if (buildInfoPath) return action( - { buildInfoPath }, - /*sourceFileOrBundle*/ - void 0 - ); - } + } + if (includeBuildInfo) { + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); + if (buildInfoPath) return action( + { buildInfoPath }, + /*sourceFileOrBundle*/ + void 0 + ); } } function getTsBuildInfoEmitOutputFilePath(options) { const configFile = options.configFilePath; - if (!isIncrementalCompilation(options)) return void 0; + if (!canEmitTsBuildInfo(options)) return void 0; if (options.tsBuildInfoFile) return options.tsBuildInfoFile; const outPath = options.outFile; let buildInfoExtensionLess; @@ -118023,14 +118716,16 @@ function getTsBuildInfoEmitOutputFilePath(options) { } return buildInfoExtensionLess + ".tsbuildinfo" /* TsBuildInfo */; } +function canEmitTsBuildInfo(options) { + return isIncrementalCompilation(options) || !!options.tscBuild; +} function getOutputPathsForBundle(options, forceDtsPaths) { const outPath = options.outFile; const jsFilePath = options.emitDeclarationOnly ? void 0 : outPath; const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options); const declarationFilePath = forceDtsPaths || getEmitDeclarations(options) ? removeFileExtension(outPath) + ".d.ts" /* Dts */ : void 0; const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : void 0; - const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); - return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }; + return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; } function getOutputPathsFor(sourceFile, host, forceDtsPaths) { const options = host.getCompilerOptions(); @@ -118044,7 +118739,7 @@ function getOutputPathsFor(sourceFile, host, forceDtsPaths) { const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? void 0 : getSourceMapFilePath(jsFilePath, options); const declarationFilePath = forceDtsPaths || getEmitDeclarations(options) && !isJsonFile ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : void 0; const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : void 0; - return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: void 0 }; + return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; } } function getSourceMapFilePath(jsFilePath, options) { @@ -118093,7 +118788,7 @@ function createAddOutput() { } } function getSingleOutputFileNames(configFile, addOutput) { - const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle( + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle( configFile.options, /*forceDtsPaths*/ false @@ -118102,7 +118797,6 @@ function getSingleOutputFileNames(configFile, addOutput) { addOutput(sourceMapFilePath); addOutput(declarationFilePath); addOutput(declarationMapPath); - addOutput(buildInfoPath); } function getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput, getCommonSourceDirectory2) { if (isDeclarationFileName(inputFileName)) return; @@ -118153,8 +118847,8 @@ function getAllProjectOutputs(configFile, ignoreCase) { for (const inputFileName of configFile.fileNames) { getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput, getCommonSourceDirectory2); } - addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options)); } + addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options)); return getOutputs(); } function getOutputFileNames(commandLine, inputFileName, ignoreCase) { @@ -118194,7 +118888,7 @@ function getFirstProjectOutput(configFile, ignoreCase) { function emitResolverSkipsTypeChecking(emitOnly, forceDtsEmit) { return !!forceDtsEmit && !!emitOnly; } -function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, declarationTransformers }, emitOnly, onlyBuildInfo, forceDtsEmit) { +function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, declarationTransformers }, emitOnly, onlyBuildInfo, forceDtsEmit, skipBuildInfo) { var compilerOptions = host.getCompilerOptions(); var sourceMapDataList = compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions) ? [] : void 0; var emittedFilesList = compilerOptions.listEmittedFiles ? [] : void 0; @@ -118210,7 +118904,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit), forceDtsEmit, onlyBuildInfo, - !targetSourceFile + !targetSourceFile && !skipBuildInfo ); exit(); return { @@ -118232,15 +118926,12 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla (_f = tracing) == null ? void 0 : _f.pop(); } function emitBuildInfo(buildInfoPath) { - if (!buildInfoPath || targetSourceFile || emitSkipped) return; + if (!buildInfoPath || targetSourceFile) return; if (host.isEmitBlocked(buildInfoPath)) { emitSkipped = true; return; } - const buildInfo = host.getBuildInfo() || createBuildInfo( - /*program*/ - void 0 - ); + const buildInfo = host.getBuildInfo() || { version }; writeFile( host, emitterDiagnostics, @@ -118264,7 +118955,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla } (isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : filter(sourceFileOrBundle.sourceFiles, isSourceFileNotJson)).forEach( (sourceFile) => { - if (compilerOptions.noCheck || !canIncludeBindAndCheckDiagnsotics(sourceFile, compilerOptions)) markLinkedReferences(sourceFile); + if (compilerOptions.noCheck || !canIncludeBindAndCheckDiagnostics(sourceFile, compilerOptions)) markLinkedReferences(sourceFile); } ); const transform2 = transformNodes( @@ -118282,6 +118973,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla newLine: compilerOptions.newLine, noEmitHelpers: compilerOptions.noEmitHelpers, module: getEmitModuleKind(compilerOptions), + moduleResolution: getEmitModuleResolutionKind(compilerOptions), target: getEmitScriptTarget(compilerOptions), sourceMap: compilerOptions.sourceMap, inlineSourceMap: compilerOptions.inlineSourceMap, @@ -118316,7 +119008,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson); const inputListOrBundle = compilerOptions.outFile ? [factory.createBundle(filesForEmit)] : filesForEmit; filesForEmit.forEach((sourceFile) => { - if (emitOnly && !getEmitDeclarations(compilerOptions) || compilerOptions.noCheck || emitResolverSkipsTypeChecking(emitOnly, forceDtsEmit) || !canIncludeBindAndCheckDiagnsotics(sourceFile, compilerOptions)) { + if (emitOnly && !getEmitDeclarations(compilerOptions) || compilerOptions.noCheck || emitResolverSkipsTypeChecking(emitOnly, forceDtsEmit) || !canIncludeBindAndCheckDiagnostics(sourceFile, compilerOptions)) { collectLinkedAliases(sourceFile); } }); @@ -118344,8 +119036,9 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla newLine: compilerOptions.newLine, noEmitHelpers: true, module: compilerOptions.module, + moduleResolution: compilerOptions.moduleResolution, target: compilerOptions.target, - sourceMap: !forceDtsEmit && compilerOptions.declarationMap, + sourceMap: emitOnly !== 2 /* BuilderSignature */ && compilerOptions.declarationMap, inlineSourceMap: compilerOptions.inlineSourceMap, extendedDiagnostics: compilerOptions.extendedDiagnostics, onlyPrintJsDocStyle: true, @@ -118359,7 +119052,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla isEmitNotificationEnabled: declarationTransform.isEmitNotificationEnabled, substituteNode: declarationTransform.substituteNode }); - printSourceFileOrBundle( + const dtsWritten = printSourceFileOrBundle( declarationFilePath, declarationMapPath, declarationTransform, @@ -118373,7 +119066,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla } ); if (emittedFilesList) { - emittedFilesList.push(declarationFilePath); + if (dtsWritten) emittedFilesList.push(declarationFilePath); if (declarationMapPath) { emittedFilesList.push(declarationMapPath); } @@ -118402,6 +119095,7 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla forEachChild(node, collectLinkedAliases); } function markLinkedReferences(file) { + if (isSourceFileJS(file)) return; forEachChildRecursively(file, (n) => { if (isImportEqualsDeclaration(n) && !(getSyntacticModifierFlags(n) & 32 /* Export */)) return "skip"; if (isImportDeclaration(n)) return "skip"; @@ -118464,8 +119158,10 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla writer.writeLine(); } const text = writer.getText(); - writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos, diagnostics: transform2.diagnostics }); + const data = { sourceMapUrlPos, diagnostics: transform2.diagnostics }; + writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, data); writer.clear(); + return !data.skippedDtsWrite; } function shouldEmitSourceMaps(mapOptions, sourceFileOrBundle) { return (mapOptions.sourceMap || mapOptions.inlineSourceMap) && (sourceFileOrBundle.kind !== 307 /* SourceFile */ || !fileExtensionIs(sourceFileOrBundle.fileName, ".json" /* Json */)); @@ -118521,9 +119217,6 @@ function emitFiles(resolver, host, targetSourceFile, { scriptTransformers, decla return encodeURI(sourceMapFile); } } -function createBuildInfo(program) { - return { program, version }; -} function getBuildInfoText(buildInfo) { return JSON.stringify(buildInfo); } @@ -118568,7 +119261,8 @@ var notImplementedResolver = { getJsxFragmentFactoryEntity: notImplemented, isBindingCapturedByNode: notImplemented, getDeclarationStatementsForSourceFile: notImplemented, - isImportRequiredByAugmentation: notImplemented + isImportRequiredByAugmentation: notImplemented, + isDefinitelyReferenceToGlobalSymbolObject: notImplemented }; var createPrinterWithDefaults = /* @__PURE__ */ memoize(() => createPrinter({})); var createPrinterWithRemoveComments = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true })); @@ -119385,7 +120079,7 @@ function createPrinter(printerOptions = {}, handlers = {}) { } function getSortedEmitHelpers(node) { const helpers = getEmitHelpers(node); - return helpers && stableSort(helpers, compareEmitHelpers); + return helpers && toSorted(helpers, compareEmitHelpers); } function emitNumericOrBigIntLiteral(node) { emitLiteral( @@ -119395,7 +120089,13 @@ function createPrinter(printerOptions = {}, handlers = {}) { ); } function emitLiteral(node, jsxAttributeEscape) { - const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape, jsxAttributeEscape); + const text = getLiteralTextOfNode( + node, + /*sourceFile*/ + void 0, + printerOptions.neverAsciiEscape, + jsxAttributeEscape + ); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) && (node.kind === 11 /* StringLiteral */ || isTemplateLiteralKind(node.kind))) { writeLiteral(text); } else { @@ -119876,6 +120576,8 @@ function createPrinter(printerOptions = {}, handlers = {}) { if (isNumericLiteral(expression)) { const text = getLiteralTextOfNode( expression, + /*sourceFile*/ + void 0, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ @@ -121097,7 +121799,7 @@ function createPrinter(printerOptions = {}, handlers = {}) { if (node.comment) { const text = getTextOfJSDocComment(node.comment); if (text) { - const lines = text.split(/\r\n?|\n/g); + const lines = text.split(/\r\n?|\n/); for (const line of lines) { writeLine(); writeSpace(); @@ -121524,7 +122226,7 @@ function createPrinter(printerOptions = {}, handlers = {}) { if (isFunctionLike(parentNode) && parentNode.typeArguments) { return emitTypeArguments(parentNode, parentNode.typeArguments); } - emitList(parentNode, typeParameters, 53776 /* TypeParameters */); + emitList(parentNode, typeParameters, 53776 /* TypeParameters */ | (isArrowFunction(parentNode) ? 64 /* AllowTrailingComma */ : 0 /* None */)); } function emitParameters(parentNode, parameters) { emitList(parentNode, parameters, 2576 /* Parameters */); @@ -121792,7 +122494,7 @@ function createPrinter(printerOptions = {}, handlers = {}) { } } function writeLines(text) { - const lines = text.split(/\r\n?|\n/g); + const lines = text.split(/\r\n?|\n/); const indentation = guessIndentation(lines); for (const lineText of lines) { const line = indentation ? lineText.slice(indentation) : lineText; @@ -122017,18 +122719,18 @@ function createPrinter(printerOptions = {}, handlers = {}) { } return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia); } - function getLiteralTextOfNode(node, neverAsciiEscape, jsxAttributeEscape) { + function getLiteralTextOfNode(node, sourceFile = currentSourceFile, neverAsciiEscape, jsxAttributeEscape) { if (node.kind === 11 /* StringLiteral */ && node.textSourceNode) { const textSourceNode = node.textSourceNode; if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) { const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode2(textSourceNode); return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` : neverAsciiEscape || getEmitFlags(node) & 16777216 /* NoAsciiEscaping */ ? `"${escapeString(text)}"` : `"${escapeNonAsciiString(text)}"`; } else { - return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape); + return getLiteralTextOfNode(textSourceNode, getSourceFileOfNode(textSourceNode), neverAsciiEscape, jsxAttributeEscape); } } const flags = (neverAsciiEscape ? 1 /* NeverAsciiEscape */ : 0) | (jsxAttributeEscape ? 2 /* JsxAttributeEscape */ : 0) | (printerOptions.terminateUnterminatedLiterals ? 4 /* TerminateUnterminatedLiterals */ : 0) | (printerOptions.target && printerOptions.target >= 8 /* ES2021 */ ? 8 /* AllowNumericSeparator */ : 0); - return getLiteralText(node, currentSourceFile, flags); + return getLiteralText(node, sourceFile, flags); } function pushNameGenerationScope(node) { privateNameTempFlagsStack.push(privateNameTempFlags); @@ -123029,7 +123731,7 @@ function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensi } try { return createCachedFileSystemEntries(rootDir, rootDirPath); - } catch (_e) { + } catch { Debug.assert(!cachedReadDirectoryResult.has(ensureTrailingDirectorySeparator(rootDirPath))); return void 0; } @@ -123118,6 +123820,12 @@ function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensi function realpath(s) { return host.realpath ? host.realpath(s) : s; } + function clearFirstAncestorEntry(fileOrDirectoryPath) { + forEachAncestorDirectory( + getDirectoryPath(fileOrDirectoryPath), + (ancestor) => cachedReadDirectoryResult.delete(ensureTrailingDirectorySeparator(ancestor)) ? true : void 0 + ); + } function addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath) { const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath); if (existingResult !== void 0) { @@ -123126,6 +123834,7 @@ function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensi } const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrDirectoryPath); if (!parentResult) { + clearFirstAncestorEntry(fileOrDirectoryPath); return void 0; } if (!host.directoryExists) { @@ -123151,6 +123860,8 @@ function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensi const parentResult = getCachedFileSystemEntriesForBaseDir(filePath); if (parentResult) { updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === 0 /* Created */); + } else { + clearFirstAncestorEntry(filePath); } } function updateFilesOfFileSystemEntry(parentResult, baseName, fileExists2) { @@ -123309,7 +124020,7 @@ function isIgnoredFileFromWildCardWatching({ } return false; function hasSourceFile(file) { - return realProgram ? !!realProgram.getSourceFileByPath(file) : builderProgram ? builderProgram.getState().fileInfos.has(file) : !!find(program, (rootFile) => toPath3(rootFile) === file); + return realProgram ? !!realProgram.getSourceFileByPath(file) : builderProgram ? builderProgram.state.fileInfos.has(file) : !!find(program, (rootFile) => toPath3(rootFile) === file); } function isSupportedScriptKind() { if (!getScriptKind2) return false; @@ -123330,9 +124041,6 @@ function isIgnoredFileFromWildCardWatching({ } } } -function isBuilderProgram(program) { - return !!program.getState; -} function isEmittedFileOfProgram(program, file) { if (!program) { return false; @@ -123857,8 +124565,7 @@ function getModeForUsageLocation(file, usage, compilerOptions) { return getModeForUsageLocationWorker(file, usage, compilerOptions); } function getModeForUsageLocationWorker(file, usage, compilerOptions) { - var _a; - if (isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent)) { + if (isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent) || isJSDocImportTag(usage.parent)) { const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage.parent); if (isTypeOnly) { const override = getResolutionModeOverride(usage.parent.attributes); @@ -123873,19 +124580,28 @@ function getModeForUsageLocationWorker(file, usage, compilerOptions) { return override; } } - if (compilerOptions && getEmitModuleKind(compilerOptions) === 200 /* Preserve */) { - return usage.parent.parent && isImportEqualsDeclaration(usage.parent.parent) || isRequireCall( - usage.parent, - /*requireStringLiteralLikeArgument*/ - false - ) ? 1 /* CommonJS */ : 99 /* ESNext */; + if (compilerOptions && importSyntaxAffectsModuleResolution(compilerOptions)) { + return getEmitSyntaxForUsageLocationWorker(file, usage, compilerOptions); } - if (file.impliedNodeFormat === void 0) return void 0; - if (file.impliedNodeFormat !== 99 /* ESNext */) { - return isImportCall(walkUpParenthesizedExpressions(usage.parent)) ? 99 /* ESNext */ : 1 /* CommonJS */; +} +function getEmitSyntaxForUsageLocationWorker(file, usage, compilerOptions) { + var _a; + if (!compilerOptions) { + return void 0; } const exprParentParent = (_a = walkUpParenthesizedExpressions(usage.parent)) == null ? void 0 : _a.parent; - return exprParentParent && isImportEqualsDeclaration(exprParentParent) ? 1 /* CommonJS */ : 99 /* ESNext */; + if (exprParentParent && isImportEqualsDeclaration(exprParentParent) || isRequireCall( + usage.parent, + /*requireStringLiteralLikeArgument*/ + false + )) { + return 1 /* CommonJS */; + } + if (isImportCall(walkUpParenthesizedExpressions(usage.parent))) { + return shouldTransformImportCallWorker(file, compilerOptions) ? 1 /* CommonJS */ : 99 /* ESNext */; + } + const fileEmitMode = getEmitModuleFormatOfFileWorker(file, compilerOptions); + return fileEmitMode === 1 /* CommonJS */ ? 1 /* CommonJS */ : emitModuleKindIsNonNodeESM(fileEmitMode) || fileEmitMode === 200 /* Preserve */ ? 99 /* ESNext */ : void 0; } function getResolutionModeOverride(node, grammarErrorOnNode) { if (!node) return void 0; @@ -123942,7 +124658,7 @@ function getTypeReferenceResolutionName(entry) { } var typeReferenceResolutionNameAndModeGetter = { getName: getTypeReferenceResolutionName, - getMode: (entry, file) => getModeForFileReference(entry, file == null ? void 0 : file.impliedNodeFormat) + getMode: (entry, file, compilerOptions) => getModeForFileReference(entry, file && getDefaultResolutionModeForFileWorker(file, compilerOptions)) }; function createTypeReferenceResolutionLoader(containingFile, redirectedReference, options, host, cache) { return { @@ -124116,19 +124832,15 @@ function getImpliedNodeFormatForFile(fileName, packageJsonInfoCache, host, optio return typeof result === "object" ? result.impliedNodeFormat : result; } function getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options) { - switch (getEmitModuleResolutionKind(options)) { - case 3 /* Node16 */: - case 99 /* NodeNext */: - return fileExtensionIsOneOf(fileName, [".d.mts" /* Dmts */, ".mts" /* Mts */, ".mjs" /* Mjs */]) ? 99 /* ESNext */ : fileExtensionIsOneOf(fileName, [".d.cts" /* Dcts */, ".cts" /* Cts */, ".cjs" /* Cjs */]) ? 1 /* CommonJS */ : fileExtensionIsOneOf(fileName, [".d.ts" /* Dts */, ".ts" /* Ts */, ".tsx" /* Tsx */, ".js" /* Js */, ".jsx" /* Jsx */]) ? lookupFromPackageJson() : void 0; - default: - return void 0; - } + const moduleResolution = getEmitModuleResolutionKind(options); + const shouldLookupFromPackageJson = 3 /* Node16 */ <= moduleResolution && moduleResolution <= 99 /* NodeNext */ || pathContainsNodeModules(fileName); + return fileExtensionIsOneOf(fileName, [".d.mts" /* Dmts */, ".mts" /* Mts */, ".mjs" /* Mjs */]) ? 99 /* ESNext */ : fileExtensionIsOneOf(fileName, [".d.cts" /* Dcts */, ".cts" /* Cts */, ".cjs" /* Cjs */]) ? 1 /* CommonJS */ : shouldLookupFromPackageJson && fileExtensionIsOneOf(fileName, [".d.ts" /* Dts */, ".ts" /* Ts */, ".tsx" /* Tsx */, ".js" /* Js */, ".jsx" /* Jsx */]) ? lookupFromPackageJson() : void 0; function lookupFromPackageJson() { const state = getTemporaryModuleResolutionState(packageJsonInfoCache, host, options); const packageJsonLocations = []; state.failedLookupLocations = packageJsonLocations; state.affectingLocations = packageJsonLocations; - const packageJsonScope = getPackageScopeForPath(fileName, state); + const packageJsonScope = getPackageScopeForPath(getDirectoryPath(fileName), state); const impliedNodeFormat = (packageJsonScope == null ? void 0 : packageJsonScope.contents.packageJsonContent.type) === "module" ? 99 /* ESNext */ : 1 /* CommonJS */; return { impliedNodeFormat, packageJsonLocations, packageJsonScope }; } @@ -124264,13 +124976,12 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config let commonSourceDirectory; let typeChecker; let classifiableNames; - const ambientModuleNameToUnmodifiedFileName = /* @__PURE__ */ new Map(); let fileReasons = createMultiMap(); let filesWithReferencesProcessed; let fileReasonsToChain; let reasonToRelatedInfo; - const cachedBindAndCheckDiagnosticsForFile = {}; - const cachedDeclarationDiagnosticsForFile = {}; + let cachedBindAndCheckDiagnosticsForFile; + let cachedDeclarationDiagnosticsForFile; let fileProcessingDiagnostics; let automaticTypeDirectiveNames; let automaticTypeDirectiveResolutions; @@ -124502,7 +125213,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config }); } } - files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); + files = toSorted(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); processingDefaultLibFiles = void 0; processingOtherFiles = void 0; filesWithReferencesProcessed = void 0; @@ -124513,7 +125224,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config const newFile = getSourceFileByPath(oldSourceFile.resolvedPath); if (shouldCreateNewSourceFile || !newFile || newFile.impliedNodeFormat !== oldSourceFile.impliedNodeFormat || // old file wasn't redirect but new file is oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path) { - host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path)); + host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path), newFile); } } if (!host.getParsedCommandLine) { @@ -124523,7 +125234,9 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config resolvedProjectReference.sourceFile, oldProgram.getCompilerOptions(), /*hasSourceFileByPath*/ - false + false, + /*newSourceFileByResolvedPath*/ + void 0 ); } }); @@ -124581,6 +125294,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config isSourceFileFromExternalLibrary, isSourceFileDefaultLibrary, getModeForUsageLocation: getModeForUsageLocation2, + getEmitSyntaxForUsageLocation, getModeForResolutionAtIndex: getModeForResolutionAtIndex2, getSourceFileFromReference, getLibFileFromReference, @@ -124609,6 +125323,11 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config forEachResolvedProjectReference: forEachResolvedProjectReference2, isSourceOfProjectReferenceRedirect, getRedirectReferenceForResolutionFromSourceOfProject, + getCompilerOptionsForFile, + getDefaultResolutionModeForFile: getDefaultResolutionModeForFile2, + getEmitModuleFormatOfFile: getEmitModuleFormatOfFile2, + getImpliedNodeFormatForEmit: getImpliedNodeFormatForEmit2, + shouldTransformImportCall, emitBuildInfo, fileExists, readFile, @@ -124740,12 +125459,18 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } function resolveModuleNamesWorker(moduleNames, containingFile, reusedNames) { var _a2, _b2; - if (!moduleNames.length) return emptyArray; const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); const redirectedReference = getRedirectReferenceForResolution(containingFile); (_a2 = tracing) == null ? void 0 : _a2.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); mark("beforeResolveModule"); - const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, redirectedReference, options, containingFile, reusedNames); + const result = actualResolveModuleNamesWorker( + moduleNames, + containingFileName, + redirectedReference, + options, + containingFile, + reusedNames + ); mark("afterResolveModule"); measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); (_b2 = tracing) == null ? void 0 : _b2.pop(); @@ -124753,13 +125478,19 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, reusedNames) { var _a2, _b2; - if (!typeDirectiveNames.length) return []; const containingSourceFile = !isString(containingFile) ? containingFile : void 0; const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; const redirectedReference = containingSourceFile && getRedirectReferenceForResolution(containingSourceFile); (_a2 = tracing) == null ? void 0 : _a2.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName }); mark("beforeResolveTypeReference"); - const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, options, containingSourceFile, reusedNames); + const result = actualResolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames, + containingFileName, + redirectedReference, + options, + containingSourceFile, + reusedNames + ); mark("afterResolveTypeReference"); measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); (_b2 = tracing) == null ? void 0 : _b2.pop(); @@ -124829,144 +125560,108 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } return classifiableNames; } - function resolveModuleNamesReusingOldState(moduleNames, file) { - if (structureIsReused === 0 /* Not */ && !file.ambientModuleNames.length) { - return resolveModuleNamesWorker( - moduleNames, - file, - /*reusedNames*/ - void 0 - ); - } - let unknownModuleNames; - let result; - let reusedNames; - const predictedToResolveToAmbientModuleMarker = emptyResolution; - const oldSourceFile = oldProgram && oldProgram.getSourceFile(file.fileName); - for (let i = 0; i < moduleNames.length; i++) { - const moduleName = moduleNames[i]; - if (file === oldSourceFile && !hasInvalidatedResolutions(file.path)) { - const oldResolution = oldProgram == null ? void 0 : oldProgram.getResolvedModule(file, moduleName.text, getModeForUsageLocation2(file, moduleName)); - if (oldResolution == null ? void 0 : oldResolution.resolvedModule) { - if (isTraceEnabled(options, host)) { - trace( - host, - oldResolution.resolvedModule.packageId ? Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, - moduleName.text, - getNormalizedAbsolutePath(file.originalFileName, currentDirectory), - oldResolution.resolvedModule.resolvedFileName, - oldResolution.resolvedModule.packageId && packageIdToString(oldResolution.resolvedModule.packageId) - ); - } - (result ?? (result = new Array(moduleNames.length)))[i] = oldResolution; - (reusedNames ?? (reusedNames = [])).push(moduleName); - continue; - } - } - let resolvesToAmbientModuleInNonModifiedFile = false; - if (contains(file.ambientModuleNames, moduleName.text)) { - resolvesToAmbientModuleInNonModifiedFile = true; - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); - } - } else { - resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName); - } - if (resolvesToAmbientModuleInNonModifiedFile) { - (result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; - } else { - (unknownModuleNames ?? (unknownModuleNames = [])).push(moduleName); - } - } - const resolutions = unknownModuleNames && unknownModuleNames.length ? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames) : emptyArray; - if (!result) { - Debug.assert(resolutions.length === moduleNames.length); - return resolutions; - } - let j = 0; - for (let i = 0; i < result.length; i++) { - if (!result[i]) { - result[i] = resolutions[j]; - j++; - } - } - Debug.assert(j === resolutions.length); - return result; - function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName) { - var _a2; - const resolutionToFile = (_a2 = oldProgram == null ? void 0 : oldProgram.getResolvedModule(file, moduleName.text, getModeForUsageLocation2(file, moduleName))) == null ? void 0 : _a2.resolvedModule; - const resolvedFile = resolutionToFile && oldProgram.getSourceFile(resolutionToFile.resolvedFileName); - if (resolutionToFile && resolvedFile) { - return false; - } - const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text); - if (!unmodifiedFile) { - return false; - } - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile); - } - return true; - } + function resolveModuleNamesReusingOldState(moduleNames, containingFile) { + return resolveNamesReusingOldState({ + entries: moduleNames, + containingFile, + containingSourceFile: containingFile, + redirectedReference: getRedirectReferenceForResolution(containingFile), + nameAndModeGetter: moduleResolutionNameAndModeGetter, + resolutionWorker: resolveModuleNamesWorker, + getResolutionFromOldProgram: (name, mode) => oldProgram == null ? void 0 : oldProgram.getResolvedModule(containingFile, name, mode), + getResolved: getResolvedModuleFromResolution, + canReuseResolutionsInFile: () => containingFile === (oldProgram == null ? void 0 : oldProgram.getSourceFile(containingFile.fileName)) && !hasInvalidatedResolutions(containingFile.path), + resolveToOwnAmbientModule: true + }); } function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames, containingFile) { - var _a2; - if (structureIsReused === 0 /* Not */) { - return resolveTypeReferenceDirectiveNamesWorker( - typeDirectiveNames, + const containingSourceFile = !isString(containingFile) ? containingFile : void 0; + return resolveNamesReusingOldState({ + entries: typeDirectiveNames, + containingFile, + containingSourceFile, + redirectedReference: containingSourceFile && getRedirectReferenceForResolution(containingSourceFile), + nameAndModeGetter: typeReferenceResolutionNameAndModeGetter, + resolutionWorker: resolveTypeReferenceDirectiveNamesWorker, + getResolutionFromOldProgram: (name, mode) => { + var _a2; + return containingSourceFile ? oldProgram == null ? void 0 : oldProgram.getResolvedTypeReferenceDirective(containingSourceFile, name, mode) : (_a2 = oldProgram == null ? void 0 : oldProgram.getAutomaticTypeDirectiveResolutions()) == null ? void 0 : _a2.get(name, mode); + }, + getResolved: getResolvedTypeReferenceDirectiveFromResolution, + canReuseResolutionsInFile: () => containingSourceFile ? containingSourceFile === (oldProgram == null ? void 0 : oldProgram.getSourceFile(containingSourceFile.fileName)) && !hasInvalidatedResolutions(containingSourceFile.path) : !hasInvalidatedResolutions(toPath3(containingFile)) + }); + } + function resolveNamesReusingOldState({ + entries, + containingFile, + containingSourceFile, + redirectedReference, + nameAndModeGetter, + resolutionWorker, + getResolutionFromOldProgram, + getResolved, + canReuseResolutionsInFile, + resolveToOwnAmbientModule + }) { + if (!entries.length) return emptyArray; + if (structureIsReused === 0 /* Not */ && (!resolveToOwnAmbientModule || !containingSourceFile.ambientModuleNames.length)) { + return resolutionWorker( + entries, containingFile, /*reusedNames*/ void 0 ); } - let unknownTypeReferenceDirectiveNames; + let unknownEntries; + let unknownEntryIndices; let result; let reusedNames; - const containingSourceFile = !isString(containingFile) ? containingFile : void 0; - const oldSourceFile = !isString(containingFile) ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : void 0; - const canReuseResolutions = !isString(containingFile) ? containingFile === oldSourceFile && !hasInvalidatedResolutions(containingFile.path) : !hasInvalidatedResolutions(toPath3(containingFile)); - for (let i = 0; i < typeDirectiveNames.length; i++) { - const entry = typeDirectiveNames[i]; - if (canReuseResolutions) { - const typeDirectiveName = getTypeReferenceResolutionName(entry); - const mode = getModeForFileReference(entry, containingSourceFile == null ? void 0 : containingSourceFile.impliedNodeFormat); - const oldResolution = !isString(containingFile) ? oldProgram == null ? void 0 : oldProgram.getResolvedTypeReferenceDirective(containingFile, typeDirectiveName, mode) : (_a2 = oldProgram == null ? void 0 : oldProgram.getAutomaticTypeDirectiveResolutions()) == null ? void 0 : _a2.get(typeDirectiveName, mode); - if (oldResolution == null ? void 0 : oldResolution.resolvedTypeReferenceDirective) { + const reuseResolutions = canReuseResolutionsInFile(); + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + if (reuseResolutions) { + const name = nameAndModeGetter.getName(entry); + const mode = nameAndModeGetter.getMode(entry, containingSourceFile, (redirectedReference == null ? void 0 : redirectedReference.commandLine.options) ?? options); + const oldResolution = getResolutionFromOldProgram(name, mode); + const oldResolved = oldResolution && getResolved(oldResolution); + if (oldResolved) { if (isTraceEnabled(options, host)) { trace( host, - oldResolution.resolvedTypeReferenceDirective.packageId ? Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2, - typeDirectiveName, - !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile, - oldResolution.resolvedTypeReferenceDirective.resolvedFileName, - oldResolution.resolvedTypeReferenceDirective.packageId && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId) + resolutionWorker === resolveModuleNamesWorker ? oldResolved.packageId ? Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : oldResolved.packageId ? Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2, + name, + containingSourceFile ? getNormalizedAbsolutePath(containingSourceFile.originalFileName, currentDirectory) : containingFile, + oldResolved.resolvedFileName, + oldResolved.packageId && packageIdToString(oldResolved.packageId) ); } - (result ?? (result = new Array(typeDirectiveNames.length)))[i] = oldResolution; + (result ?? (result = new Array(entries.length)))[i] = oldResolution; (reusedNames ?? (reusedNames = [])).push(entry); continue; } } - (unknownTypeReferenceDirectiveNames ?? (unknownTypeReferenceDirectiveNames = [])).push(entry); - } - if (!unknownTypeReferenceDirectiveNames) return result || emptyArray; - const resolutions = resolveTypeReferenceDirectiveNamesWorker( - unknownTypeReferenceDirectiveNames, - containingFile, - reusedNames - ); - if (!result) { - Debug.assert(resolutions.length === typeDirectiveNames.length); - return resolutions; - } - let j = 0; - for (let i = 0; i < result.length; i++) { - if (!result[i]) { - result[i] = resolutions[j]; - j++; + if (resolveToOwnAmbientModule) { + const name = nameAndModeGetter.getName(entry); + if (contains(containingSourceFile.ambientModuleNames, name)) { + if (isTraceEnabled(options, host)) { + trace( + host, + Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, + name, + getNormalizedAbsolutePath(containingSourceFile.originalFileName, currentDirectory) + ); + } + (result ?? (result = new Array(entries.length)))[i] = emptyResolution; + continue; + } } + (unknownEntries ?? (unknownEntries = [])).push(entry); + (unknownEntryIndices ?? (unknownEntryIndices = [])).push(i); } - Debug.assert(j === resolutions.length); + if (!unknownEntries) return result; + const resolutions = resolutionWorker(unknownEntries, containingFile, reusedNames); + if (!result) return resolutions; + resolutions.forEach((resolution, index) => result[unknownEntryIndices[index]] = resolution); return result; } function canReuseProjectReferences() { @@ -125095,10 +125790,6 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } else if (hasInvalidatedResolutions(oldSourceFile.path)) { structureIsReused = 1 /* SafeModules */; modifiedSourceFiles.push(newSourceFile); - } else { - for (const moduleName of oldSourceFile.ambientModuleNames) { - ambientModuleNameToUnmodifiedFileName.set(moduleName, oldSourceFile.fileName); - } } newSourceFiles.push(newSourceFile); } @@ -125191,6 +125882,10 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config getSymlinkCache, writeFile: writeFileCallback || writeFile2, isEmitBlocked, + shouldTransformImportCall, + getEmitModuleFormatOfFile: getEmitModuleFormatOfFile2, + getDefaultResolutionModeForFile: getDefaultResolutionModeForFile2, + getModeForResolutionAtIndex: getModeForResolutionAtIndex2, readFile: (f) => host.readFile(f), fileExists: (f) => { const path = toPath3(f); @@ -125217,7 +125912,6 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } function emitBuildInfo(writeFileCallback) { var _a2, _b2; - Debug.assert(!options.outFile); (_a2 = tracing) == null ? void 0 : _a2.push( tracing.Phase.Emit, "emitBuildInfo", @@ -125259,20 +125953,23 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config if (file.hasNoDefaultLib) { return true; } - if (!options.noLib) { + if (options.noLib) { return false; } const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } else { - return some(options.lib, (libFileName) => equalityComparer(file.fileName, resolvedLibReferences.get(libFileName).actual)); + return some(options.lib, (libFileName) => { + const resolvedLib = resolvedLibReferences.get(libFileName); + return !!resolvedLib && equalityComparer(file.fileName, resolvedLib.actual); + }); } } function getTypeChecker() { return typeChecker || (typeChecker = createTypeChecker(program)); } - function emit(sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit) { + function emit(sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit, skipBuildInfo) { var _a2, _b2; (_a2 = tracing) == null ? void 0 : _a2.push( tracing.Phase.Emit, @@ -125281,14 +125978,25 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config /*separateBeginAndEnd*/ true ); - const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit)); + const result = runWithCancellationToken( + () => emitWorker( + program, + sourceFile, + writeFileCallback, + cancellationToken, + emitOnly, + transformers, + forceDtsEmit, + skipBuildInfo + ) + ); (_b2 = tracing) == null ? void 0 : _b2.pop(); return result; } function isEmitBlocked(emitFileName) { return hasEmitBlockingDiagnostics.has(toPath3(emitFileName)); } - function emitWorker(program2, sourceFile, writeFileCallback, cancellationToken, emitOnly, customTransformers, forceDtsEmit) { + function emitWorker(program2, sourceFile, writeFileCallback, cancellationToken, emitOnly, customTransformers, forceDtsEmit, skipBuildInfo) { if (!forceDtsEmit) { const result = handleNoEmitOptions(program2, sourceFile, writeFileCallback, cancellationToken); if (result) return result; @@ -125310,7 +126018,8 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config emitOnly, /*onlyBuildInfo*/ false, - forceDtsEmit + forceDtsEmit, + skipBuildInfo ) ); mark("afterEmit"); @@ -125337,15 +126046,23 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config function getSyntacticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); } - function getSemanticDiagnostics(sourceFile, cancellationToken) { - return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); + function getSemanticDiagnostics(sourceFile, cancellationToken, nodesToCheck) { + return getDiagnosticsHelper( + sourceFile, + (sourceFile2, cancellationToken2) => getSemanticDiagnosticsForFile(sourceFile2, cancellationToken2, nodesToCheck), + cancellationToken + ); } function getCachedSemanticDiagnostics(sourceFile) { - var _a2; - return sourceFile ? (_a2 = cachedBindAndCheckDiagnosticsForFile.perFile) == null ? void 0 : _a2.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + return cachedBindAndCheckDiagnosticsForFile == null ? void 0 : cachedBindAndCheckDiagnosticsForFile.get(sourceFile.path); } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { - return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); + return getBindAndCheckDiagnosticsForFile( + sourceFile, + cancellationToken, + /*nodesToCheck*/ + void 0 + ); } function getProgramDiagnostics(sourceFile) { var _a2; @@ -125359,12 +126076,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config return getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, programDiagnosticsInFile).diagnostics; } function getDeclarationDiagnostics2(sourceFile, cancellationToken) { - const options2 = program.getCompilerOptions(); - if (!sourceFile || options2.outFile) { - return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); - } else { - return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); - } + return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); } function getSyntacticDiagnosticsForFile(sourceFile) { if (isSourceFileJS(sourceFile)) { @@ -125385,16 +126097,26 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config throw e; } } - function getSemanticDiagnosticsForFile(sourceFile, cancellationToken) { + function getSemanticDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck) { return concatenate( - filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken), options), + filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck), options), getProgramDiagnostics(sourceFile) ); } - function getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken) { - return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedBindAndCheckDiagnosticsForFile, getBindAndCheckDiagnosticsForFileNoCache); + function getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck) { + if (nodesToCheck) { + return getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken, nodesToCheck); + } + let result = cachedBindAndCheckDiagnosticsForFile == null ? void 0 : cachedBindAndCheckDiagnosticsForFile.get(sourceFile.path); + if (!result) { + (cachedBindAndCheckDiagnosticsForFile ?? (cachedBindAndCheckDiagnosticsForFile = /* @__PURE__ */ new Map())).set( + sourceFile.path, + result = getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken) + ); + } + return result; } - function getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken) { + function getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken, nodesToCheck) { return runWithCancellationToken(() => { if (skipTypeChecking(sourceFile, options, program)) { return emptyArray; @@ -125402,24 +126124,34 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config const typeChecker2 = getTypeChecker(); Debug.assert(!!sourceFile.bindDiagnostics); const isJs = sourceFile.scriptKind === 1 /* JS */ || sourceFile.scriptKind === 2 /* JSX */; - const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); + const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); let bindDiagnostics = sourceFile.bindDiagnostics; - let checkDiagnostics = typeChecker2.getDiagnostics(sourceFile, cancellationToken); + let checkDiagnostics = typeChecker2.getDiagnostics(sourceFile, cancellationToken, nodesToCheck); if (isPlainJs) { bindDiagnostics = filter(bindDiagnostics, (d) => plainJSErrors.has(d.code)); checkDiagnostics = filter(checkDiagnostics, (d) => plainJSErrors.has(d.code)); } - return getMergedBindAndCheckDiagnostics(sourceFile, !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : void 0); + return getMergedBindAndCheckDiagnostics( + sourceFile, + !isPlainJs, + !!nodesToCheck, + bindDiagnostics, + checkDiagnostics, + isCheckJs ? sourceFile.jsDocDiagnostics : void 0 + ); }); } - function getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics, ...allDiagnostics) { + function getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics, partialCheck, ...allDiagnostics) { var _a2; const flatDiagnostics = flatten(allDiagnostics); if (!includeBindAndCheckDiagnostics || !((_a2 = sourceFile.commentDirectives) == null ? void 0 : _a2.length)) { return flatDiagnostics; } const { diagnostics, directives } = getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, flatDiagnostics); + if (partialCheck) { + return diagnostics; + } for (const errorExpectation of directives.getUnusedExpectations()) { diagnostics.push(createDiagnosticForRange(sourceFile, errorExpectation.range, Diagnostics.Unused_ts_expect_error_directive)); } @@ -125447,7 +126179,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config return line; } const lineText = file.text.slice(lineStarts[line], lineStarts[line + 1]).trim(); - if (lineText !== "" && !/^(\s*)\/\/(.*)$/.test(lineText)) { + if (lineText !== "" && !/^\s*\/\/.*$/.test(lineText)) { return -1; } line--; @@ -125670,7 +126402,14 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config }); } function getDeclarationDiagnosticsWorker(sourceFile, cancellationToken) { - return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache); + let result = cachedDeclarationDiagnosticsForFile == null ? void 0 : cachedDeclarationDiagnosticsForFile.get(sourceFile.path); + if (!result) { + (cachedDeclarationDiagnosticsForFile ?? (cachedDeclarationDiagnosticsForFile = /* @__PURE__ */ new Map())).set( + sourceFile.path, + result = getDeclarationDiagnosticsForFileNoCache(sourceFile, cancellationToken) + ); + } + return result; } function getDeclarationDiagnosticsForFileNoCache(sourceFile, cancellationToken) { return runWithCancellationToken(() => { @@ -125678,22 +126417,8 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config return getDeclarationDiagnostics(getEmitHost(noop), resolver, sourceFile) || emptyArray; }); } - function getAndCacheDiagnostics(sourceFile, cancellationToken, cache, getDiagnostics2) { - var _a2; - const cachedResult = sourceFile ? (_a2 = cache.perFile) == null ? void 0 : _a2.get(sourceFile.path) : cache.allDiagnostics; - if (cachedResult) { - return cachedResult; - } - const result = getDiagnostics2(sourceFile, cancellationToken); - if (sourceFile) { - (cache.perFile || (cache.perFile = /* @__PURE__ */ new Map())).set(sourceFile.path, result); - } else { - cache.allDiagnostics = result; - } - return result; - } function getDeclarationDiagnosticsForFile(sourceFile, cancellationToken) { - return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + return sourceFile.isDeclarationFile ? emptyArray : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } function getOptionsDiagnostics() { return sortAndDeduplicateDiagnostics(concatenate( @@ -126240,10 +126965,14 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config const resolvedTypeReferenceDirective = resolutions[index]; const fileName = ref.fileName; resolutionsInFile.set(fileName, getModeForFileReference(ref, file.impliedNodeFormat), resolvedTypeReferenceDirective); - const mode = ref.resolutionMode || file.impliedNodeFormat; + const mode = ref.resolutionMode || getDefaultResolutionModeForFile2(file); processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: 5 /* TypeReferenceDirective */, file: file.path, index }); } } + function getCompilerOptionsForFile(file) { + var _a2; + return ((_a2 = getRedirectReferenceForResolution(file)) == null ? void 0 : _a2.commandLine.options) || options; + } function processTypeReferenceDirective(typeReferenceDirective, mode, resolution, reason) { var _a2, _b2; (_a2 = tracing) == null ? void 0 : _a2.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolution.resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : void 0 }); @@ -126344,13 +127073,12 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config return host.getCanonicalFileName(fileName); } function processImportedModules(file) { - var _a2; collectExternalModuleReferences(file); if (file.imports.length || file.moduleAugmentations.length) { const moduleNames = getModuleNames(file); const resolutions = (resolvedModulesProcessing == null ? void 0 : resolvedModulesProcessing.get(file.path)) || resolveModuleNamesReusingOldState(moduleNames, file); Debug.assert(resolutions.length === moduleNames.length); - const optionsForFile = ((_a2 = getRedirectReferenceForResolution(file)) == null ? void 0 : _a2.commandLine.options) || options; + const optionsForFile = getCompilerOptionsForFile(file); const resolutionsInFile = createModeAwareCache(); (resolvedModules ?? (resolvedModules = /* @__PURE__ */ new Map())).set(file.path, resolutionsInFile); for (let index = 0; index < moduleNames.length; index++) { @@ -126515,8 +127243,8 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } const outputFile = options.outFile; if (options.tsBuildInfoFile) { - if (!isIncrementalCompilation(options)) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite"); + if (!canEmitTsBuildInfo(options)) { + createDiagnosticForOptionName(Diagnostics.Option_tsBuildInfoFile_cannot_be_specified_without_specifying_option_incremental_or_composite_or_if_not_running_tsc_b, "tsBuildInfoFile"); } } else if (options.incremental && !outputFile && !options.configFilePath) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified)); @@ -126641,7 +127369,8 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config if (options.outDir || // there is --outDir specified options.rootDir || // there is --rootDir specified options.sourceRoot || // there is --sourceRoot specified - options.mapRoot) { + options.mapRoot || // there is --mapRoot specified + getEmitDeclarations(options) && options.declarationDir) { const dir = getCommonSourceDirectory2(); if (options.outDir && dir === "" && files.some((file) => getRootLength(file.fileName) > 1)) { createDiagnosticForOptionName(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); @@ -126654,14 +127383,6 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config if (!getEmitDeclarations(options)) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); } - if (options.noEmit) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); - } - } - if (options.noCheck) { - if (options.noEmit) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noCheck", "noEmit"); - } } if (options.emitDecoratorMetadata && !options.experimentalDecorators) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"); @@ -126773,7 +127494,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } return Version.zero; } - function checkDeprecations(deprecatedIn, stopsWorkingIn, removedIn, createDiagnostic, fn) { + function checkDeprecations(deprecatedIn, removedIn, createDiagnostic, fn) { const deprecatedInVersion = new Version(deprecatedIn); const removedInVersion = new Version(removedIn); const typescriptVersion = new Version(typeScriptVersion3 || versionMajorMinor); @@ -126790,9 +127511,9 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config } } else { if (value === void 0) { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_is_deprecated_and_will_stop_functioning_in_TypeScript_1_Specify_compilerOption_ignoreDeprecations_Colon_2_to_silence_this_error, name, stopsWorkingIn, deprecatedIn); + createDiagnostic(name, value, useInstead, Diagnostics.Option_0_is_deprecated_and_will_stop_functioning_in_TypeScript_1_Specify_compilerOption_ignoreDeprecations_Colon_2_to_silence_this_error, name, removedIn, deprecatedIn); } else { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_1_is_deprecated_and_will_stop_functioning_in_TypeScript_2_Specify_compilerOption_ignoreDeprecations_Colon_3_to_silence_this_error, name, value, stopsWorkingIn, deprecatedIn); + createDiagnostic(name, value, useInstead, Diagnostics.Option_0_1_is_deprecated_and_will_stop_functioning_in_TypeScript_2_Specify_compilerOption_ignoreDeprecations_Colon_3_to_silence_this_error, name, value, removedIn, deprecatedIn); } } }); @@ -126828,7 +127549,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config ); } } - checkDeprecations("5.0", "5.5", "6.0", createDiagnostic, (createDeprecatedDiagnostic) => { + checkDeprecations("5.0", "5.5", createDiagnostic, (createDeprecatedDiagnostic) => { if (options.target === 0 /* ES3 */) { createDeprecatedDiagnostic("target", "ES3"); } @@ -126880,7 +127601,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config function createDiagnostic(_name, _value, _useInstead, message, ...args) { createDiagnosticForReference(parentFile, index, message, ...args); } - checkDeprecations("5.0", "5.5", "6.0", createDiagnostic, (createDeprecatedDiagnostic) => { + checkDeprecations("5.0", "5.5", createDiagnostic, (createDeprecatedDiagnostic) => { if (ref.prepend) { createDeprecatedDiagnostic("prepend"); } @@ -126906,7 +127627,7 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config redirectInfo = cachedChain.redirectInfo; } else { reasons == null ? void 0 : reasons.forEach(processReason); - redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file); + redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file, getCompilerOptionsForFile(file)); } if (fileProcessingReason) processReason(fileProcessingReason); const processedExtraReason = (seenReasons == null ? void 0 : seenReasons.size) !== (reasons == null ? void 0 : reasons.length); @@ -127264,13 +127985,53 @@ function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _config return symlinks; } function getModeForUsageLocation2(file, usage) { - var _a2; - const optionsForFile = ((_a2 = getRedirectReferenceForResolution(file)) == null ? void 0 : _a2.commandLine.options) || options; - return getModeForUsageLocationWorker(file, usage, optionsForFile); + return getModeForUsageLocationWorker(file, usage, getCompilerOptionsForFile(file)); + } + function getEmitSyntaxForUsageLocation(file, usage) { + return getEmitSyntaxForUsageLocationWorker(file, usage, getCompilerOptionsForFile(file)); } function getModeForResolutionAtIndex2(file, index) { return getModeForUsageLocation2(file, getModuleNameStringLiteralAt(file, index)); } + function getDefaultResolutionModeForFile2(sourceFile) { + return getDefaultResolutionModeForFileWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + function getImpliedNodeFormatForEmit2(sourceFile) { + return getImpliedNodeFormatForEmitWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + function getEmitModuleFormatOfFile2(sourceFile) { + return getEmitModuleFormatOfFileWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + function shouldTransformImportCall(sourceFile) { + return shouldTransformImportCallWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } +} +function shouldTransformImportCallWorker(sourceFile, options) { + const moduleKind = getEmitModuleKind(options); + if (100 /* Node16 */ <= moduleKind && moduleKind <= 199 /* NodeNext */ || moduleKind === 200 /* Preserve */) { + return false; + } + return getEmitModuleFormatOfFileWorker(sourceFile, options) < 5 /* ES2015 */; +} +function getEmitModuleFormatOfFileWorker(sourceFile, options) { + return getImpliedNodeFormatForEmitWorker(sourceFile, options) ?? getEmitModuleKind(options); +} +function getImpliedNodeFormatForEmitWorker(sourceFile, options) { + var _a, _b; + const moduleKind = getEmitModuleKind(options); + if (100 /* Node16 */ <= moduleKind && moduleKind <= 199 /* NodeNext */) { + return sourceFile.impliedNodeFormat; + } + if (sourceFile.impliedNodeFormat === 1 /* CommonJS */ && (((_a = sourceFile.packageJsonScope) == null ? void 0 : _a.contents.packageJsonContent.type) === "commonjs" || fileExtensionIsOneOf(sourceFile.fileName, [".cjs" /* Cjs */, ".cts" /* Cts */]))) { + return 1 /* CommonJS */; + } + if (sourceFile.impliedNodeFormat === 99 /* ESNext */ && (((_b = sourceFile.packageJsonScope) == null ? void 0 : _b.contents.packageJsonContent.type) === "module" || fileExtensionIsOneOf(sourceFile.fileName, [".mjs" /* Mjs */, ".mts" /* Mts */]))) { + return 99 /* ESNext */; + } + return void 0; +} +function getDefaultResolutionModeForFileWorker(sourceFile, options) { + return importSyntaxAffectsModuleResolution(options) ? getImpliedNodeFormatForEmitWorker(sourceFile, options) : void 0; } function updateHostForUseSourceOfProjectReferenceRedirect(host) { let setOfDeclarationDirectories; @@ -127398,8 +128159,7 @@ var emitSkippedWithNoDiagnostics = { diagnostics: emptyArray, sourceMaps: void 0 function handleNoEmitOptions(program, sourceFile, writeFile2, cancellationToken) { const options = program.getCompilerOptions(); if (options.noEmit) { - program.getSemanticDiagnostics(sourceFile, cancellationToken); - return sourceFile || options.outFile ? emitSkippedWithNoDiagnostics : program.emitBuildInfo(writeFile2, cancellationToken); + return sourceFile ? emitSkippedWithNoDiagnostics : program.emitBuildInfo(writeFile2, cancellationToken); } if (!options.noEmitOnError) return void 0; let diagnostics = [ @@ -127417,7 +128177,7 @@ function handleNoEmitOptions(program, sourceFile, writeFile2, cancellationToken) } if (!diagnostics.length) return void 0; let emittedFiles; - if (!sourceFile && !options.outFile) { + if (!sourceFile) { const emitResult = program.emitBuildInfo(writeFile2, cancellationToken); if (emitResult.diagnostics) diagnostics = [...diagnostics, ...emitResult.diagnostics]; emittedFiles = emitResult.emittedFiles; @@ -127740,8 +128500,7 @@ var BuilderState; ); }, cancellationToken, - /*emitOnly*/ - true, + 2 /* BuilderSignature */, /*customTransformers*/ void 0, /*forceDtsEmit*/ @@ -127883,20 +128642,30 @@ var BuilderFileEmit = /* @__PURE__ */ ((BuilderFileEmit2) => { BuilderFileEmit2[BuilderFileEmit2["Js"] = 1] = "Js"; BuilderFileEmit2[BuilderFileEmit2["JsMap"] = 2] = "JsMap"; BuilderFileEmit2[BuilderFileEmit2["JsInlineMap"] = 4] = "JsInlineMap"; - BuilderFileEmit2[BuilderFileEmit2["Dts"] = 8] = "Dts"; - BuilderFileEmit2[BuilderFileEmit2["DtsMap"] = 16] = "DtsMap"; + BuilderFileEmit2[BuilderFileEmit2["DtsErrors"] = 8] = "DtsErrors"; + BuilderFileEmit2[BuilderFileEmit2["DtsEmit"] = 16] = "DtsEmit"; + BuilderFileEmit2[BuilderFileEmit2["DtsMap"] = 32] = "DtsMap"; + BuilderFileEmit2[BuilderFileEmit2["Dts"] = 24] = "Dts"; BuilderFileEmit2[BuilderFileEmit2["AllJs"] = 7] = "AllJs"; - BuilderFileEmit2[BuilderFileEmit2["AllDts"] = 24] = "AllDts"; - BuilderFileEmit2[BuilderFileEmit2["All"] = 31] = "All"; + BuilderFileEmit2[BuilderFileEmit2["AllDtsEmit"] = 48] = "AllDtsEmit"; + BuilderFileEmit2[BuilderFileEmit2["AllDts"] = 56] = "AllDts"; + BuilderFileEmit2[BuilderFileEmit2["All"] = 63] = "All"; return BuilderFileEmit2; })(BuilderFileEmit || {}); +function isBuilderProgramStateWithDefinedProgram(state) { + return state.program !== void 0; +} +function toBuilderProgramStateWithDefinedProgram(state) { + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); + return state; +} function getBuilderFileEmit(options) { let result = 1 /* Js */; if (options.sourceMap) result = result | 2 /* JsMap */; if (options.inlineSourceMap) result = result | 4 /* JsInlineMap */; - if (getEmitDeclarations(options)) result = result | 8 /* Dts */; - if (options.declarationMap) result = result | 16 /* DtsMap */; - if (options.emitDeclarationOnly) result = result & 24 /* AllDts */; + if (getEmitDeclarations(options)) result = result | 24 /* Dts */; + if (options.declarationMap) result = result | 32 /* DtsMap */; + if (options.emitDeclarationOnly) result = result & 56 /* AllDts */; return result; } function getPendingEmitKind(optionsOrEmitKind, oldOptionsOrEmitKind) { @@ -127907,7 +128676,8 @@ function getPendingEmitKind(optionsOrEmitKind, oldOptionsOrEmitKind) { const diff = oldEmitKind ^ emitKind; let result = 0 /* None */; if (diff & 7 /* AllJs */) result = emitKind & 7 /* AllJs */; - if (diff & 24 /* AllDts */) result = result | emitKind & 24 /* AllDts */; + if (diff & 8 /* DtsErrors */) result = result | emitKind & 8 /* DtsErrors */; + if (diff & 48 /* AllDtsEmit */) result = result | emitKind & 48 /* AllDtsEmit */; return result; } function hasSameKeys(map1, map2) { @@ -127925,17 +128695,18 @@ function createBuilderProgramState(newProgram, oldState) { const compilerOptions = newProgram.getCompilerOptions(); state.compilerOptions = compilerOptions; const outFilePath = compilerOptions.outFile; - if (!outFilePath) { - state.semanticDiagnosticsPerFile = /* @__PURE__ */ new Map(); - } else if (compilerOptions.composite && (oldState == null ? void 0 : oldState.outSignature) && outFilePath === oldState.compilerOptions.outFile) { + state.semanticDiagnosticsPerFile = /* @__PURE__ */ new Map(); + if (outFilePath && compilerOptions.composite && (oldState == null ? void 0 : oldState.outSignature) && outFilePath === oldState.compilerOptions.outFile) { state.outSignature = oldState.outSignature && getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldState.outSignature); } state.changedFilesSet = /* @__PURE__ */ new Set(); state.latestChangedDtsFile = compilerOptions.composite ? oldState == null ? void 0 : oldState.latestChangedDtsFile : void 0; + state.checkPending = state.compilerOptions.noCheck ? true : void 0; const useOldState = BuilderState.canReuseOldState(state.referencedMap, oldState); const oldCompilerOptions = useOldState ? oldState.compilerOptions : void 0; - const canCopySemanticDiagnostics = useOldState && oldState.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile && !compilerOptionsAffectSemanticDiagnostics(compilerOptions, oldCompilerOptions); + let canCopySemanticDiagnostics = useOldState && !compilerOptionsAffectSemanticDiagnostics(compilerOptions, oldCompilerOptions); const canCopyEmitSignatures = compilerOptions.composite && (oldState == null ? void 0 : oldState.emitSignatures) && !outFilePath && !compilerOptionsAffectDeclarationPath(compilerOptions, oldState.compilerOptions); + let canCopyEmitDiagnostics = true; if (useOldState) { (_a = oldState.changedFilesSet) == null ? void 0 : _a.forEach((value) => state.changedFilesSet.add(value)); if (!outFilePath && ((_b = oldState.affectedFilesPendingEmit) == null ? void 0 : _b.size)) { @@ -127943,8 +128714,13 @@ function createBuilderProgramState(newProgram, oldState) { state.seenAffectedFiles = /* @__PURE__ */ new Set(); } state.programEmitPending = oldState.programEmitPending; + if (outFilePath && state.changedFilesSet.size) { + canCopySemanticDiagnostics = false; + canCopyEmitDiagnostics = false; + } + state.hasErrorsFromOldState = oldState.hasErrors; } else { - state.buildInfoEmitPending = true; + state.buildInfoEmitPending = isIncrementalCompilation(compilerOptions); } const referencedMap = state.referencedMap; const oldReferencedMap = useOldState ? oldState.referencedMap : void 0; @@ -127960,10 +128736,10 @@ function createBuilderProgramState(newProgram, oldState) { oldInfo.impliedFormat !== info.impliedFormat || // Referenced files changed !hasSameKeys(newReferences = referencedMap && referencedMap.getValues(sourceFilePath), oldReferencedMap && oldReferencedMap.getValues(sourceFilePath)) || // Referenced file was deleted in the new program newReferences && forEachKey(newReferences, (path) => !state.fileInfos.has(path) && oldState.fileInfos.has(path))) { - addFileToChangeSet(state, sourceFilePath); + addFileToChangeSet(sourceFilePath); } else { const sourceFile = newProgram.getSourceFileByPath(sourceFilePath); - const emitDiagnostics = (_a2 = oldState.emitDiagnosticsPerFile) == null ? void 0 : _a2.get(sourceFilePath); + const emitDiagnostics = canCopyEmitDiagnostics ? (_a2 = oldState.emitDiagnosticsPerFile) == null ? void 0 : _a2.get(sourceFilePath) : void 0; if (emitDiagnostics) { (state.emitDiagnosticsPerFile ?? (state.emitDiagnosticsPerFile = /* @__PURE__ */ new Map())).set( sourceFilePath, @@ -127992,16 +128768,16 @@ function createBuilderProgramState(newProgram, oldState) { }); if (useOldState && forEachEntry(oldState.fileInfos, (info, sourceFilePath) => { if (state.fileInfos.has(sourceFilePath)) return false; - if (outFilePath || info.affectsGlobalScope) return true; + if (info.affectsGlobalScope) return true; state.buildInfoEmitPending = true; - return false; + return !!outFilePath; })) { BuilderState.getAllFilesExcludingDefaultLibraryFile( state, newProgram, /*firstSourceFile*/ void 0 - ).forEach((file) => addFileToChangeSet(state, file.resolvedPath)); + ).forEach((file) => addFileToChangeSet(file.resolvedPath)); } else if (oldCompilerOptions) { const pendingEmitKind = compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions) ? getBuilderFileEmit(compilerOptions) : getPendingEmitKind(compilerOptions, oldCompilerOptions); if (pendingEmitKind !== 0 /* None */) { @@ -128017,18 +128793,26 @@ function createBuilderProgramState(newProgram, oldState) { }); Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size); state.seenAffectedFiles = state.seenAffectedFiles || /* @__PURE__ */ new Set(); - state.buildInfoEmitPending = true; - } else { + } else if (!state.changedFilesSet.size) { state.programEmitPending = state.programEmitPending ? state.programEmitPending | pendingEmitKind : pendingEmitKind; } + state.buildInfoEmitPending = true; } } + if (useOldState && state.semanticDiagnosticsPerFile.size !== state.fileInfos.size && oldState.checkPending !== state.checkPending) state.buildInfoEmitPending = true; return state; -} -function addFileToChangeSet(state, path) { - state.changedFilesSet.add(path); - state.buildInfoEmitPending = true; - state.programEmitPending = void 0; + function addFileToChangeSet(path) { + state.changedFilesSet.add(path); + if (outFilePath) { + canCopySemanticDiagnostics = false; + canCopyEmitDiagnostics = false; + state.semanticDiagnosticsFromOldState = void 0; + state.semanticDiagnosticsPerFile.clear(); + state.emitDiagnosticsPerFile = void 0; + } + state.buildInfoEmitPending = true; + state.programEmitPending = void 0; + } } function getEmitSignatureFromOldSignature(options, oldOptions, oldEmitSignature) { return !!options.declarationMap === !!oldOptions.declarationMap ? ( @@ -128052,7 +128836,12 @@ function repopulateDiagnostics(diagnostics, newProgram) { } function convertOrRepopulateDiagnosticMessageChain(chain, sourceFile, newProgram, repopulateInfo) { const info = repopulateInfo(chain); - if (info) { + if (info === true) { + return { + ...createModeMismatchDetails(sourceFile), + next: convertOrRepopulateDiagnosticMessageChainArray(chain.next, sourceFile, newProgram, repopulateInfo) + }; + } else if (info) { return { ...createModuleNotFoundChain(sourceFile, newProgram, info.moduleReference, info.mode, info.packageName || info.moduleReference), next: convertOrRepopulateDiagnosticMessageChainArray(chain.next, sourceFile, newProgram, repopulateInfo) @@ -128095,34 +128884,6 @@ function releaseCache(state) { BuilderState.releaseCache(state); state.program = void 0; } -function backupBuilderProgramEmitState(state) { - const outFilePath = state.compilerOptions.outFile; - Debug.assert(!state.changedFilesSet.size || outFilePath); - return { - affectedFilesPendingEmit: state.affectedFilesPendingEmit && new Map(state.affectedFilesPendingEmit), - seenEmittedFiles: state.seenEmittedFiles && new Map(state.seenEmittedFiles), - programEmitPending: state.programEmitPending, - emitSignatures: state.emitSignatures && new Map(state.emitSignatures), - outSignature: state.outSignature, - latestChangedDtsFile: state.latestChangedDtsFile, - hasChangedEmitSignature: state.hasChangedEmitSignature, - changedFilesSet: outFilePath ? new Set(state.changedFilesSet) : void 0, - buildInfoEmitPending: state.buildInfoEmitPending, - emitDiagnosticsPerFile: state.emitDiagnosticsPerFile && new Map(state.emitDiagnosticsPerFile) - }; -} -function restoreBuilderProgramEmitState(state, savedEmitState) { - state.affectedFilesPendingEmit = savedEmitState.affectedFilesPendingEmit; - state.seenEmittedFiles = savedEmitState.seenEmittedFiles; - state.programEmitPending = savedEmitState.programEmitPending; - state.emitSignatures = savedEmitState.emitSignatures; - state.outSignature = savedEmitState.outSignature; - state.latestChangedDtsFile = savedEmitState.latestChangedDtsFile; - state.hasChangedEmitSignature = savedEmitState.hasChangedEmitSignature; - state.buildInfoEmitPending = savedEmitState.buildInfoEmitPending; - state.emitDiagnosticsPerFile = savedEmitState.emitDiagnosticsPerFile; - if (savedEmitState.changedFilesSet) state.changedFilesSet = savedEmitState.changedFilesSet; -} function assertSourceFileOkWithoutNextAffectedCall(state, sourceFile) { Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.resolvedPath)); } @@ -128137,7 +128898,11 @@ function getNextAffectedFile(state, cancellationToken, host) { const affectedFile = affectedFiles[affectedFilesIndex]; if (!seenAffectedFiles.has(affectedFile.resolvedPath)) { state.affectedFilesIndex = affectedFilesIndex; - addToAffectedFilesPendingEmit(state, affectedFile.resolvedPath, getBuilderFileEmit(state.compilerOptions)); + addToAffectedFilesPendingEmit( + state, + affectedFile.resolvedPath, + getBuilderFileEmit(state.compilerOptions) + ); handleDtsMayChangeOfAffectedFile( state, affectedFile, @@ -128157,15 +128922,11 @@ function getNextAffectedFile(state, cancellationToken, host) { if (nextKey.done) { return void 0; } - const program = Debug.checkDefined(state.program); - const compilerOptions = program.getCompilerOptions(); - if (compilerOptions.outFile) { - Debug.assert(!state.semanticDiagnosticsPerFile); - return program; - } + const compilerOptions = state.program.getCompilerOptions(); + if (compilerOptions.outFile) return state.program; state.affectedFiles = BuilderState.getFilesAffectedByWithOldState( state, - program, + state.program, nextKey.value, cancellationToken, host @@ -128175,17 +128936,34 @@ function getNextAffectedFile(state, cancellationToken, host) { if (!state.seenAffectedFiles) state.seenAffectedFiles = /* @__PURE__ */ new Set(); } } -function clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles) { - var _a; - if (!((_a = state.affectedFilesPendingEmit) == null ? void 0 : _a.size)) return; - if (!emitOnlyDtsFiles) return state.affectedFilesPendingEmit = void 0; - state.affectedFilesPendingEmit.forEach((emitKind, path) => { - const pending = emitKind & 7 /* AllJs */; +function clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles, isForDtsErrors) { + var _a, _b; + if (!((_a = state.affectedFilesPendingEmit) == null ? void 0 : _a.size) && !state.programEmitPending) return; + if (!emitOnlyDtsFiles && !isForDtsErrors) { + state.affectedFilesPendingEmit = void 0; + state.programEmitPending = void 0; + } + (_b = state.affectedFilesPendingEmit) == null ? void 0 : _b.forEach((emitKind, path) => { + const pending = !isForDtsErrors ? emitKind & 7 /* AllJs */ : emitKind & (7 /* AllJs */ | 48 /* AllDtsEmit */); if (!pending) state.affectedFilesPendingEmit.delete(path); else state.affectedFilesPendingEmit.set(path, pending); }); + if (state.programEmitPending) { + const pending = !isForDtsErrors ? state.programEmitPending & 7 /* AllJs */ : state.programEmitPending & (7 /* AllJs */ | 48 /* AllDtsEmit */); + if (!pending) state.programEmitPending = void 0; + else state.programEmitPending = pending; + } } -function getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles) { +function getPendingEmitKindWithSeen(optionsOrEmitKind, seenOldOptionsOrEmitKind, emitOnlyDtsFiles, isForDtsErrors) { + let pendingKind = getPendingEmitKind(optionsOrEmitKind, seenOldOptionsOrEmitKind); + if (emitOnlyDtsFiles) pendingKind = pendingKind & 56 /* AllDts */; + if (isForDtsErrors) pendingKind = pendingKind & 8 /* DtsErrors */; + return pendingKind; +} +function getBuilderFileEmitAllDts(isForDtsErrors) { + return !isForDtsErrors ? 56 /* AllDts */ : 8 /* DtsErrors */; +} +function getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles, isForDtsErrors) { var _a; if (!((_a = state.affectedFilesPendingEmit) == null ? void 0 : _a.size)) return void 0; return forEachEntry(state.affectedFilesPendingEmit, (emitKind, path) => { @@ -128196,12 +128974,16 @@ function getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles) { return void 0; } const seenKind = (_a2 = state.seenEmittedFiles) == null ? void 0 : _a2.get(affectedFile.resolvedPath); - let pendingKind = getPendingEmitKind(emitKind, seenKind); - if (emitOnlyDtsFiles) pendingKind = pendingKind & 24 /* AllDts */; + const pendingKind = getPendingEmitKindWithSeen( + emitKind, + seenKind, + emitOnlyDtsFiles, + isForDtsErrors + ); if (pendingKind) return { affectedFile, emitKind: pendingKind }; }); } -function getNextPendingEmitDiagnosticsFile(state) { +function getNextPendingEmitDiagnosticsFile(state, isForDtsErrors) { var _a; if (!((_a = state.emitDiagnosticsPerFile) == null ? void 0 : _a.size)) return void 0; return forEachEntry(state.emitDiagnosticsPerFile, (diagnostics, path) => { @@ -128212,15 +128994,14 @@ function getNextPendingEmitDiagnosticsFile(state) { return void 0; } const seenKind = ((_a2 = state.seenEmittedFiles) == null ? void 0 : _a2.get(affectedFile.resolvedPath)) || 0 /* None */; - if (!(seenKind & 24 /* AllDts */)) return { affectedFile, diagnostics, seenKind }; + if (!(seenKind & getBuilderFileEmitAllDts(isForDtsErrors))) return { affectedFile, diagnostics, seenKind }; }); } function removeDiagnosticsOfLibraryFiles(state) { if (!state.cleanedDiagnosticsOfLibFiles) { state.cleanedDiagnosticsOfLibFiles = true; - const program = Debug.checkDefined(state.program); - const options = program.getCompilerOptions(); - forEach(program.getSourceFiles(), (f) => program.isSourceFileDefaultLibrary(f) && !skipTypeChecking(f, options, program) && removeSemanticDiagnosticsOf(state, f.resolvedPath)); + const options = state.program.getCompilerOptions(); + forEach(state.program.getSourceFiles(), (f) => state.program.isSourceFileDefaultLibrary(f) && !skipTypeCheckingIgnoringNoCheck(f, options, state.program) && removeSemanticDiagnosticsOf(state, f.resolvedPath)); } } function handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, host) { @@ -128229,7 +129010,7 @@ function handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken removeDiagnosticsOfLibraryFiles(state); BuilderState.updateShapeSignature( state, - Debug.checkDefined(state.program), + state.program, affectedFile, cancellationToken, host @@ -128247,12 +129028,11 @@ function handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken function handleDtsMayChangeOf(state, path, invalidateJsFiles, cancellationToken, host) { removeSemanticDiagnosticsOf(state, path); if (!state.changedFilesSet.has(path)) { - const program = Debug.checkDefined(state.program); - const sourceFile = program.getSourceFileByPath(path); + const sourceFile = state.program.getSourceFileByPath(path); if (sourceFile) { BuilderState.updateShapeSignature( state, - program, + state.program, sourceFile, cancellationToken, host, @@ -128260,9 +129040,17 @@ function handleDtsMayChangeOf(state, path, invalidateJsFiles, cancellationToken, true ); if (invalidateJsFiles) { - addToAffectedFilesPendingEmit(state, path, getBuilderFileEmit(state.compilerOptions)); + addToAffectedFilesPendingEmit( + state, + path, + getBuilderFileEmit(state.compilerOptions) + ); } else if (getEmitDeclarations(state.compilerOptions)) { - addToAffectedFilesPendingEmit(state, path, state.compilerOptions.declarationMap ? 24 /* AllDts */ : 8 /* Dts */); + addToAffectedFilesPendingEmit( + state, + path, + state.compilerOptions.declarationMap ? 56 /* AllDts */ : 24 /* Dts */ + ); } } } @@ -128329,7 +129117,7 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile(state, affectedFile host ); if (isChangedSignature(state, currentPath)) { - const currentSourceFile = Debug.checkDefined(state.program).getSourceFileByPath(currentPath); + const currentSourceFile = state.program.getSourceFileByPath(currentPath); queue.push(...BuilderState.getReferencedByPaths(state, currentSourceFile.resolvedPath)); } } @@ -128375,38 +129163,79 @@ function handleDtsMayChangeOfFileAndExportsOfFile(state, filePath, invalidateJsF ); return void 0; } -function getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken) { +function getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken, semanticDiagnosticsPerFile) { + if (state.compilerOptions.noCheck) return emptyArray; return concatenate( - getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken), - Debug.checkDefined(state.program).getProgramDiagnostics(sourceFile) + getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken, semanticDiagnosticsPerFile), + state.program.getProgramDiagnostics(sourceFile) ); } -function getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken) { +function getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken, semanticDiagnosticsPerFile) { + semanticDiagnosticsPerFile ?? (semanticDiagnosticsPerFile = state.semanticDiagnosticsPerFile); const path = sourceFile.resolvedPath; - if (state.semanticDiagnosticsPerFile) { - const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); - if (cachedDiagnostics) { - return filterSemanticDiagnostics(cachedDiagnostics, state.compilerOptions); - } - } - const diagnostics = Debug.checkDefined(state.program).getBindAndCheckDiagnostics(sourceFile, cancellationToken); - if (state.semanticDiagnosticsPerFile) { - state.semanticDiagnosticsPerFile.set(path, diagnostics); + const cachedDiagnostics = semanticDiagnosticsPerFile.get(path); + if (cachedDiagnostics) { + return filterSemanticDiagnostics(cachedDiagnostics, state.compilerOptions); } + const diagnostics = state.program.getBindAndCheckDiagnostics(sourceFile, cancellationToken); + semanticDiagnosticsPerFile.set(path, diagnostics); + state.buildInfoEmitPending = true; return filterSemanticDiagnostics(diagnostics, state.compilerOptions); } -function isProgramBundleEmitBuildInfo(info) { +function isIncrementalBundleEmitBuildInfo(info) { var _a; return !!((_a = info.options) == null ? void 0 : _a.outFile); } +function isIncrementalBuildInfo(info) { + return !!info.fileNames; +} +function isNonIncrementalBuildInfo(info) { + return !isIncrementalBuildInfo(info) && !!info.root; +} +function ensureHasErrorsForState(state) { + if (state.hasErrors !== void 0) return; + if (isIncrementalCompilation(state.compilerOptions)) { + state.hasErrors = !some(state.program.getSourceFiles(), (f) => { + var _a, _b; + const bindAndCheckDiagnostics = state.semanticDiagnosticsPerFile.get(f.resolvedPath); + return bindAndCheckDiagnostics === void 0 || // Missing semantic diagnostics in cache will be encoded in buildInfo + !!bindAndCheckDiagnostics.length || // cached semantic diagnostics will be encoded in buildInfo + !!((_b = (_a = state.emitDiagnosticsPerFile) == null ? void 0 : _a.get(f.resolvedPath)) == null ? void 0 : _b.length); + }) && (hasSyntaxOrGlobalErrors(state) || some(state.program.getSourceFiles(), (f) => !!state.program.getProgramDiagnostics(f).length)); + } else { + state.hasErrors = some(state.program.getSourceFiles(), (f) => { + var _a, _b; + const bindAndCheckDiagnostics = state.semanticDiagnosticsPerFile.get(f.resolvedPath); + return !!(bindAndCheckDiagnostics == null ? void 0 : bindAndCheckDiagnostics.length) || // If has semantic diagnostics + !!((_b = (_a = state.emitDiagnosticsPerFile) == null ? void 0 : _a.get(f.resolvedPath)) == null ? void 0 : _b.length); + }) || hasSyntaxOrGlobalErrors(state); + } +} +function hasSyntaxOrGlobalErrors(state) { + return !!state.program.getConfigFileParsingDiagnostics().length || !!state.program.getSyntacticDiagnostics().length || !!state.program.getOptionsDiagnostics().length || !!state.program.getGlobalDiagnostics().length; +} +function getBuildInfoEmitPending(state) { + ensureHasErrorsForState(state); + return state.buildInfoEmitPending ?? (state.buildInfoEmitPending = !!state.hasErrorsFromOldState !== !!state.hasErrors); +} function getBuildInfo2(state) { var _a, _b; - const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory(); + const currentDirectory = state.program.getCurrentDirectory(); const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions), currentDirectory)); const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : void 0; const fileNames = []; const fileNameToFileId = /* @__PURE__ */ new Map(); const rootFileNames = new Set(state.program.getRootFileNames().map((f) => toPath(f, currentDirectory, state.program.getCanonicalFileName))); + ensureHasErrorsForState(state); + if (!isIncrementalCompilation(state.compilerOptions)) { + const buildInfo2 = { + root: arrayFrom(rootFileNames, (r) => relativeToBuildInfo(r)), + errors: state.hasErrors ? true : void 0, + checkPending: state.checkPending, + version + }; + return buildInfo2; + } const root = []; if (state.compilerOptions.outFile) { const fileInfos2 = arrayFrom(state.fileInfos.entries(), ([key, value]) => { @@ -128414,12 +129243,15 @@ function getBuildInfo2(state) { tryAddRoot(key, fileId); return value.impliedFormat ? { version: value.version, impliedFormat: value.impliedFormat, signature: void 0, affectsGlobalScope: void 0 } : value.version; }); - const program2 = { + const buildInfo2 = { fileNames, fileInfos: fileInfos2, root, resolvedRoot: toResolvedRoot(), - options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions), + options: toIncrementalBuildInfoCompilerOptions(state.compilerOptions), + semanticDiagnosticsPerFile: !state.changedFilesSet.size ? toIncrementalBuildInfoDiagnostics() : void 0, + emitDiagnosticsPerFile: toIncrementalBuildInfoEmitDiagnostics(), + changeFileSet: toChangeFileSet(), outSignature: state.outSignature, latestChangedDtsFile, pendingEmit: !state.programEmitPending ? void 0 : ( @@ -128428,10 +129260,13 @@ function getBuildInfo2(state) { // Pending emit is same as deteremined by compilerOptions state.programEmitPending ) - ) + ), // Actual value + errors: state.hasErrors ? true : void 0, + checkPending: state.checkPending, + version }; - return createBuildInfo(program2); + return buildInfo2; } let fileIdsList; let fileNamesToFileIdListId; @@ -128486,7 +129321,7 @@ function getBuildInfo2(state) { toFileIdListId(state.referencedMap.getValues(key)) ]); } - const semanticDiagnosticsPerFile = convertToProgramBuildInfoDiagnostics(); + const semanticDiagnosticsPerFile = toIncrementalBuildInfoDiagnostics(); let affectedFilesPendingEmit; if ((_b = state.affectedFilesPendingEmit) == null ? void 0 : _b.size) { const fullEmitForOptions = getBuilderFileEmit(state.compilerOptions); @@ -128500,7 +129335,7 @@ function getBuildInfo2(state) { affectedFilesPendingEmit, pendingEmit === fullEmitForOptions ? fileId : ( // Pending full emit per options - pendingEmit === 8 /* Dts */ ? [fileId] : ( + pendingEmit === 24 /* Dts */ ? [fileId] : ( // Pending on Dts only [fileId, pendingEmit] ) @@ -128510,29 +129345,25 @@ function getBuildInfo2(state) { } } } - let changeFileSet; - if (state.changedFilesSet.size) { - for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { - changeFileSet = append(changeFileSet, toFileId(path)); - } - } - const emitDiagnosticsPerFile = convertToProgramBuildInfoEmitDiagnostics(); - const program = { + const buildInfo = { fileNames, + fileIdsList, fileInfos, root, resolvedRoot: toResolvedRoot(), - options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions), - fileIdsList, + options: toIncrementalBuildInfoCompilerOptions(state.compilerOptions), referencedMap, semanticDiagnosticsPerFile, - emitDiagnosticsPerFile, + emitDiagnosticsPerFile: toIncrementalBuildInfoEmitDiagnostics(), + changeFileSet: toChangeFileSet(), affectedFilesPendingEmit, - changeFileSet, emitSignatures, - latestChangedDtsFile + latestChangedDtsFile, + errors: state.hasErrors ? true : void 0, + checkPending: state.checkPending, + version }; - return createBuildInfo(program); + return buildInfo; function relativeToBuildInfoEnsuringAbsolutePath(path) { return relativeToBuildInfo(getNormalizedAbsolutePath(path, currentDirectory)); } @@ -128580,13 +129411,13 @@ function getBuildInfo2(state) { }); return result; } - function convertToProgramBuildInfoCompilerOptions(options) { + function toIncrementalBuildInfoCompilerOptions(options) { let result; const { optionsNameMap } = getOptionsNameMap(); for (const name of getOwnKeys(options).sort(compareStringsCaseSensitive)) { const optionInfo = optionsNameMap.get(name.toLowerCase()); if (optionInfo == null ? void 0 : optionInfo.affectsBuildInfo) { - (result || (result = {}))[name] = convertToReusableCompilerOptionValue( + (result || (result = {}))[name] = toReusableCompilerOptionValue( optionInfo, options[name] ); @@ -128594,7 +129425,7 @@ function getBuildInfo2(state) { } return result; } - function convertToReusableCompilerOptionValue(option, value) { + function toReusableCompilerOptionValue(option, value) { if (option) { Debug.assert(option.type !== "listOrElement"); if (option.type === "list") { @@ -128608,23 +129439,22 @@ function getBuildInfo2(state) { } return value; } - function convertToProgramBuildInfoDiagnostics() { + function toIncrementalBuildInfoDiagnostics() { let result; state.fileInfos.forEach((_value, key) => { - var _a2; - const value = (_a2 = state.semanticDiagnosticsPerFile) == null ? void 0 : _a2.get(key); + const value = state.semanticDiagnosticsPerFile.get(key); if (!value) { if (!state.changedFilesSet.has(key)) result = append(result, toFileId(key)); } else if (value.length) { result = append(result, [ toFileId(key), - convertToReusableDiagnostics(value, key) + toReusableDiagnostic(value, key) ]); } }); return result; } - function convertToProgramBuildInfoEmitDiagnostics() { + function toIncrementalBuildInfoEmitDiagnostics() { var _a2; let result; if (!((_a2 = state.emitDiagnosticsPerFile) == null ? void 0 : _a2.size)) return result; @@ -128632,55 +129462,64 @@ function getBuildInfo2(state) { const value = state.emitDiagnosticsPerFile.get(key); result = append(result, [ toFileId(key), - convertToReusableDiagnostics(value, key) + toReusableDiagnostic(value, key) ]); } return result; } - function convertToReusableDiagnostics(diagnostics, diagnosticFilePath) { + function toReusableDiagnostic(diagnostics, diagnosticFilePath) { Debug.assert(!!diagnostics.length); return diagnostics.map((diagnostic) => { - const result = convertToReusableDiagnosticRelatedInformation(diagnostic, diagnosticFilePath); + const result = toReusableDiagnosticRelatedInformation(diagnostic, diagnosticFilePath); result.reportsUnnecessary = diagnostic.reportsUnnecessary; result.reportDeprecated = diagnostic.reportsDeprecated; result.source = diagnostic.source; result.skippedOn = diagnostic.skippedOn; const { relatedInformation } = diagnostic; - result.relatedInformation = relatedInformation ? relatedInformation.length ? relatedInformation.map((r) => convertToReusableDiagnosticRelatedInformation(r, diagnosticFilePath)) : [] : void 0; + result.relatedInformation = relatedInformation ? relatedInformation.length ? relatedInformation.map((r) => toReusableDiagnosticRelatedInformation(r, diagnosticFilePath)) : [] : void 0; return result; }); } - function convertToReusableDiagnosticRelatedInformation(diagnostic, diagnosticFilePath) { + function toReusableDiagnosticRelatedInformation(diagnostic, diagnosticFilePath) { const { file } = diagnostic; return { ...diagnostic, file: file ? file.resolvedPath === diagnosticFilePath ? void 0 : relativeToBuildInfo(file.resolvedPath) : false, - messageText: isString(diagnostic.messageText) ? diagnostic.messageText : convertToReusableDiagnosticMessageChain(diagnostic.messageText) + messageText: isString(diagnostic.messageText) ? diagnostic.messageText : toReusableDiagnosticMessageChain(diagnostic.messageText) }; } - function convertToReusableDiagnosticMessageChain(chain) { + function toReusableDiagnosticMessageChain(chain) { if (chain.repopulateInfo) { return { info: chain.repopulateInfo(), - next: convertToReusableDiagnosticMessageChainArray(chain.next) + next: toReusableDiagnosticMessageChainArray(chain.next) }; } - const next = convertToReusableDiagnosticMessageChainArray(chain.next); + const next = toReusableDiagnosticMessageChainArray(chain.next); return next === chain.next ? chain : { ...chain, next }; } - function convertToReusableDiagnosticMessageChainArray(array) { + function toReusableDiagnosticMessageChainArray(array) { if (!array) return array; return forEach(array, (chain, index) => { - const reusable = convertToReusableDiagnosticMessageChain(chain); + const reusable = toReusableDiagnosticMessageChain(chain); if (chain === reusable) return void 0; const result = index > 0 ? array.slice(0, index - 1) : []; result.push(reusable); for (let i = index + 1; i < array.length; i++) { - result.push(convertToReusableDiagnosticMessageChain(array[i])); + result.push(toReusableDiagnosticMessageChain(array[i])); } return result; }) || array; } + function toChangeFileSet() { + let changeFileSet; + if (state.changedFilesSet.size) { + for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { + changeFileSet = append(changeFileSet, toFileId(path)); + } + } + return changeFileSet; + } } var BuilderProgramKind = /* @__PURE__ */ ((BuilderProgramKind2) => { BuilderProgramKind2[BuilderProgramKind2["SemanticDiagnosticsBuilderProgram"] = 0] = "SemanticDiagnosticsBuilderProgram"; @@ -128744,25 +129583,27 @@ function computeSignature(text, host, data) { return (host.createHash ?? generateDjb2Hash)(getTextHandlingSourceMapForSignature(text, data)); } function createBuilderProgram(kind, { newProgram, host, oldProgram, configFileParsingDiagnostics }) { - let oldState = oldProgram && oldProgram.getState(); + let oldState = oldProgram && oldProgram.state; if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) { newProgram = void 0; oldState = void 0; return oldProgram; } const state = createBuilderProgramState(newProgram, oldState); - newProgram.getBuildInfo = () => getBuildInfo2(state); + newProgram.getBuildInfo = () => getBuildInfo2(toBuilderProgramStateWithDefinedProgram(state)); newProgram = void 0; oldProgram = void 0; oldState = void 0; - const getState = () => state; - const builderProgram = createRedirectedBuilderProgram(getState, configFileParsingDiagnostics); - builderProgram.getState = getState; - builderProgram.saveEmitState = () => backupBuilderProgramEmitState(state); - builderProgram.restoreEmitState = (saved) => restoreBuilderProgramEmitState(state, saved); + const builderProgram = createRedirectedBuilderProgram(state, configFileParsingDiagnostics); + builderProgram.state = state; builderProgram.hasChangedEmitSignature = () => !!state.hasChangedEmitSignature; - builderProgram.getAllDependencies = (sourceFile) => BuilderState.getAllDependencies(state, Debug.checkDefined(state.program), sourceFile); + builderProgram.getAllDependencies = (sourceFile) => BuilderState.getAllDependencies( + state, + Debug.checkDefined(state.program), + sourceFile + ); builderProgram.getSemanticDiagnostics = getSemanticDiagnostics; + builderProgram.getDeclarationDiagnostics = getDeclarationDiagnostics2; builderProgram.emit = emit; builderProgram.releaseProgram = () => releaseCache(state); if (kind === 0 /* SemanticDiagnosticsBuilderProgram */) { @@ -128776,76 +129617,145 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa } return builderProgram; function emitBuildInfo(writeFile2, cancellationToken) { - if (state.buildInfoEmitPending) { - const result = Debug.checkDefined(state.program).emitBuildInfo(writeFile2 || maybeBind(host, host.writeFile), cancellationToken); + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); + if (getBuildInfoEmitPending(state)) { + const result = state.program.emitBuildInfo( + writeFile2 || maybeBind(host, host.writeFile), + cancellationToken + ); state.buildInfoEmitPending = false; return result; } return emitSkippedWithNoDiagnostics; } - function emitNextAffectedFile(writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers) { - var _a, _b, _c; + function emitNextAffectedFileOrDtsErrors(writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers, isForDtsErrors) { + var _a, _b, _c, _d; + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); let affected = getNextAffectedFile(state, cancellationToken, host); const programEmitKind = getBuilderFileEmit(state.compilerOptions); - let emitKind = emitOnlyDtsFiles ? programEmitKind & 24 /* AllDts */ : programEmitKind; + let emitKind = !isForDtsErrors ? emitOnlyDtsFiles ? programEmitKind & 56 /* AllDts */ : programEmitKind : 8 /* DtsErrors */; if (!affected) { if (!state.compilerOptions.outFile) { - const pendingAffectedFile = getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles); - if (!pendingAffectedFile) { - const pendingForDiagnostics = getNextPendingEmitDiagnosticsFile(state); + const pendingAffectedFile = getNextAffectedFilePendingEmit( + state, + emitOnlyDtsFiles, + isForDtsErrors + ); + if (pendingAffectedFile) { + ({ affectedFile: affected, emitKind } = pendingAffectedFile); + } else { + const pendingForDiagnostics = getNextPendingEmitDiagnosticsFile( + state, + isForDtsErrors + ); if (pendingForDiagnostics) { - (state.seenEmittedFiles ?? (state.seenEmittedFiles = /* @__PURE__ */ new Map())).set(pendingForDiagnostics.affectedFile.resolvedPath, pendingForDiagnostics.seenKind | 24 /* AllDts */); + (state.seenEmittedFiles ?? (state.seenEmittedFiles = /* @__PURE__ */ new Map())).set( + pendingForDiagnostics.affectedFile.resolvedPath, + pendingForDiagnostics.seenKind | getBuilderFileEmitAllDts(isForDtsErrors) + ); return { result: { emitSkipped: true, diagnostics: pendingForDiagnostics.diagnostics }, affected: pendingForDiagnostics.affectedFile }; } - if (!state.buildInfoEmitPending) return void 0; - const affected2 = state.program; - const result2 = affected2.emitBuildInfo(writeFile2 || maybeBind(host, host.writeFile), cancellationToken); - state.buildInfoEmitPending = false; - return { result: result2, affected: affected2 }; } - ({ affectedFile: affected, emitKind } = pendingAffectedFile); } else { - if (!state.programEmitPending) return void 0; - emitKind = state.programEmitPending; - if (emitOnlyDtsFiles) emitKind = emitKind & 24 /* AllDts */; - if (!emitKind) return void 0; - affected = state.program; + if (state.programEmitPending) { + emitKind = getPendingEmitKindWithSeen( + state.programEmitPending, + state.seenProgramEmit, + emitOnlyDtsFiles, + isForDtsErrors + ); + if (emitKind) affected = state.program; + } + if (!affected && ((_a = state.emitDiagnosticsPerFile) == null ? void 0 : _a.size)) { + const seenKind = state.seenProgramEmit || 0 /* None */; + if (!(seenKind & getBuilderFileEmitAllDts(isForDtsErrors))) { + state.seenProgramEmit = getBuilderFileEmitAllDts(isForDtsErrors) | seenKind; + const diagnostics = []; + state.emitDiagnosticsPerFile.forEach((d) => addRange(diagnostics, d)); + return { + result: { emitSkipped: true, diagnostics }, + affected: state.program + }; + } + } + } + if (!affected) { + if (isForDtsErrors || !getBuildInfoEmitPending(state)) return void 0; + const affected2 = state.program; + const result2 = affected2.emitBuildInfo( + writeFile2 || maybeBind(host, host.writeFile), + cancellationToken + ); + state.buildInfoEmitPending = false; + return { result: result2, affected: affected2 }; } } let emitOnly; if (emitKind & 7 /* AllJs */) emitOnly = 0 /* Js */; - if (emitKind & 24 /* AllDts */) emitOnly = emitOnly === void 0 ? 1 /* Dts */ : void 0; - if (affected === state.program) { - state.programEmitPending = state.changedFilesSet.size ? getPendingEmitKind(programEmitKind, emitKind) : state.programEmitPending ? getPendingEmitKind(state.programEmitPending, emitKind) : void 0; - } - const result = state.program.emit( + if (emitKind & 56 /* AllDts */) emitOnly = emitOnly === void 0 ? 1 /* Dts */ : void 0; + const result = !isForDtsErrors ? state.program.emit( affected === state.program ? void 0 : affected, getWriteFileCallback(writeFile2, customTransformers), cancellationToken, emitOnly, - customTransformers - ); + customTransformers, + /*forceDtsEmit*/ + void 0, + /*skipBuildInfo*/ + true + ) : { + emitSkipped: true, + diagnostics: state.program.getDeclarationDiagnostics( + affected === state.program ? void 0 : affected, + cancellationToken + ) + }; if (affected !== state.program) { const affectedSourceFile = affected; state.seenAffectedFiles.add(affectedSourceFile.resolvedPath); if (state.affectedFilesIndex !== void 0) state.affectedFilesIndex++; state.buildInfoEmitPending = true; - const existing = ((_a = state.seenEmittedFiles) == null ? void 0 : _a.get(affectedSourceFile.resolvedPath)) || 0 /* None */; + const existing = ((_b = state.seenEmittedFiles) == null ? void 0 : _b.get(affectedSourceFile.resolvedPath)) || 0 /* None */; (state.seenEmittedFiles ?? (state.seenEmittedFiles = /* @__PURE__ */ new Map())).set(affectedSourceFile.resolvedPath, emitKind | existing); - const existingPending = ((_b = state.affectedFilesPendingEmit) == null ? void 0 : _b.get(affectedSourceFile.resolvedPath)) || programEmitKind; + const existingPending = ((_c = state.affectedFilesPendingEmit) == null ? void 0 : _c.get(affectedSourceFile.resolvedPath)) || programEmitKind; const pendingKind = getPendingEmitKind(existingPending, emitKind | existing); if (pendingKind) (state.affectedFilesPendingEmit ?? (state.affectedFilesPendingEmit = /* @__PURE__ */ new Map())).set(affectedSourceFile.resolvedPath, pendingKind); - else (_c = state.affectedFilesPendingEmit) == null ? void 0 : _c.delete(affectedSourceFile.resolvedPath); + else (_d = state.affectedFilesPendingEmit) == null ? void 0 : _d.delete(affectedSourceFile.resolvedPath); if (result.diagnostics.length) (state.emitDiagnosticsPerFile ?? (state.emitDiagnosticsPerFile = /* @__PURE__ */ new Map())).set(affectedSourceFile.resolvedPath, result.diagnostics); } else { state.changedFilesSet.clear(); + state.programEmitPending = state.changedFilesSet.size ? getPendingEmitKind(programEmitKind, emitKind) : state.programEmitPending ? getPendingEmitKind(state.programEmitPending, emitKind) : void 0; + state.seenProgramEmit = emitKind | (state.seenProgramEmit || 0 /* None */); + setEmitDiagnosticsPerFile(result.diagnostics); + state.buildInfoEmitPending = true; } return { result, affected }; } + function setEmitDiagnosticsPerFile(diagnostics) { + let emitDiagnosticsPerFile; + diagnostics.forEach((d) => { + if (!d.file) return; + let diagnostics2 = emitDiagnosticsPerFile == null ? void 0 : emitDiagnosticsPerFile.get(d.file.resolvedPath); + if (!diagnostics2) (emitDiagnosticsPerFile ?? (emitDiagnosticsPerFile = /* @__PURE__ */ new Map())).set(d.file.resolvedPath, diagnostics2 = []); + diagnostics2.push(d); + }); + if (emitDiagnosticsPerFile) state.emitDiagnosticsPerFile = emitDiagnosticsPerFile; + } + function emitNextAffectedFile(writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers) { + return emitNextAffectedFileOrDtsErrors( + writeFile2, + cancellationToken, + emitOnlyDtsFiles, + customTransformers, + /*isForDtsErrors*/ + false + ); + } function getWriteFileCallback(writeFile2, customTransformers) { + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); if (!getEmitDeclarations(state.compilerOptions)) return writeFile2 || maybeBind(host, host.writeFile); return (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => { var _a, _b, _c; @@ -128880,7 +129790,7 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa if (state.compilerOptions.composite) { const filePath = sourceFiles[0].resolvedPath; emitSignature = handleNewSignature((_c = state.emitSignatures) == null ? void 0 : _c.get(filePath), emitSignature); - if (!emitSignature) return; + if (!emitSignature) return data.skippedDtsWrite = true; (state.emitSignatures ?? (state.emitSignatures = /* @__PURE__ */ new Map())).set(filePath, emitSignature); } } else if (state.compilerOptions.composite) { @@ -128889,7 +129799,7 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa /*newSignature*/ void 0 ); - if (!newSignature) return; + if (!newSignature) return data.skippedDtsWrite = true; state.outSignature = newSignature; } } @@ -128912,6 +129822,7 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa }; } function emit(targetSourceFile, writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers) { + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); if (kind === 1 /* EmitAndSemanticDiagnosticsBuilderProgram */) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); } @@ -128924,7 +129835,12 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa let diagnostics; let emittedFiles = []; let affectedEmitResult; - while (affectedEmitResult = emitNextAffectedFile(writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + while (affectedEmitResult = emitNextAffectedFile( + writeFile2, + cancellationToken, + emitOnlyDtsFiles, + customTransformers + )) { emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles); @@ -128937,23 +129853,82 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa sourceMaps }; } else { - clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles); + clearAffectedFilesPendingEmit( + state, + emitOnlyDtsFiles, + /*isForDtsErrors*/ + false + ); } } - return Debug.checkDefined(state.program).emit( + const emitResult = state.program.emit( targetSourceFile, getWriteFileCallback(writeFile2, customTransformers), cancellationToken, emitOnlyDtsFiles, customTransformers ); + handleNonEmitBuilderWithEmitOrDtsErrors( + targetSourceFile, + emitOnlyDtsFiles, + /*isForDtsErrors*/ + false, + emitResult.diagnostics + ); + return emitResult; + } + function handleNonEmitBuilderWithEmitOrDtsErrors(targetSourceFile, emitOnlyDtsFiles, isForDtsErrors, diagnostics) { + if (!targetSourceFile && kind !== 1 /* EmitAndSemanticDiagnosticsBuilderProgram */) { + clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles, isForDtsErrors); + setEmitDiagnosticsPerFile(diagnostics); + } + } + function getDeclarationDiagnostics2(sourceFile, cancellationToken) { + var _a; + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); + if (kind === 1 /* EmitAndSemanticDiagnosticsBuilderProgram */) { + assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); + let affectedEmitResult; + let diagnostics; + while (affectedEmitResult = emitNextAffectedFileOrDtsErrors( + /*writeFile*/ + void 0, + cancellationToken, + /*emitOnlyDtsFiles*/ + void 0, + /*customTransformers*/ + void 0, + /*isForDtsErrors*/ + true + )) { + if (!sourceFile) diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); + } + return (!sourceFile ? diagnostics : (_a = state.emitDiagnosticsPerFile) == null ? void 0 : _a.get(sourceFile.resolvedPath)) || emptyArray; + } else { + const result = state.program.getDeclarationDiagnostics(sourceFile, cancellationToken); + handleNonEmitBuilderWithEmitOrDtsErrors( + sourceFile, + /*emitOnlyDtsFiles*/ + void 0, + /*isForDtsErrors*/ + true, + result + ); + return result; + } } function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken, ignoreSourceFile) { + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); while (true) { const affected = getNextAffectedFile(state, cancellationToken, host); let result; - if (!affected) return void 0; - else if (affected !== state.program) { + if (!affected) { + if (state.checkPending && !state.compilerOptions.noCheck) { + state.checkPending = void 0; + state.buildInfoEmitPending = true; + } + return void 0; + } else if (affected !== state.program) { const affectedSourceFile = affected; if (!ignoreSourceFile || !ignoreSourceFile(affectedSourceFile)) { result = getSemanticDiagnosticsOfFile(state, affectedSourceFile, cancellationToken); @@ -128963,33 +129938,48 @@ function createBuilderProgram(kind, { newProgram, host, oldProgram, configFilePa state.buildInfoEmitPending = true; if (!result) continue; } else { - result = state.program.getSemanticDiagnostics( - /*sourceFile*/ - void 0, - cancellationToken + let diagnostics; + const semanticDiagnosticsPerFile = /* @__PURE__ */ new Map(); + state.program.getSourceFiles().forEach( + (sourceFile) => diagnostics = addRange( + diagnostics, + getSemanticDiagnosticsOfFile( + state, + sourceFile, + cancellationToken, + semanticDiagnosticsPerFile + ) + ) ); + state.semanticDiagnosticsPerFile = semanticDiagnosticsPerFile; + result = diagnostics || emptyArray; state.changedFilesSet.clear(); state.programEmitPending = getBuilderFileEmit(state.compilerOptions); + if (!state.compilerOptions.noCheck) state.checkPending = void 0; + state.buildInfoEmitPending = true; } return { result, affected }; } } function getSemanticDiagnostics(sourceFile, cancellationToken) { + Debug.assert(isBuilderProgramStateWithDefinedProgram(state)); assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); - const compilerOptions = Debug.checkDefined(state.program).getCompilerOptions(); - if (compilerOptions.outFile) { - Debug.assert(!state.semanticDiagnosticsPerFile); - return Debug.checkDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken); - } if (sourceFile) { return getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken); } - while (getSemanticDiagnosticsOfNextAffectedFile(cancellationToken)) { + while (true) { + const affectedResult = getSemanticDiagnosticsOfNextAffectedFile(cancellationToken); + if (!affectedResult) break; + if (affectedResult.affected === state.program) return affectedResult.result; } let diagnostics; - for (const sourceFile2 of Debug.checkDefined(state.program).getSourceFiles()) { + for (const sourceFile2 of state.program.getSourceFiles()) { diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile2, cancellationToken)); } + if (state.checkPending && !state.compilerOptions.noCheck) { + state.checkPending = void 0; + state.buildInfoEmitPending = true; + } return diagnostics || emptyArray; } } @@ -129003,44 +129993,49 @@ function toBuilderStateFileInfoForMultiEmit(fileInfo) { return isString(fileInfo) ? { version: fileInfo, signature: fileInfo, affectsGlobalScope: void 0, impliedFormat: void 0 } : isString(fileInfo.signature) ? fileInfo : { version: fileInfo.version, signature: fileInfo.signature === false ? void 0 : fileInfo.version, affectsGlobalScope: fileInfo.affectsGlobalScope, impliedFormat: fileInfo.impliedFormat }; } function toBuilderFileEmit(value, fullEmitForOptions) { - return isNumber(value) ? fullEmitForOptions : value[1] || 8 /* Dts */; + return isNumber(value) ? fullEmitForOptions : value[1] || 24 /* Dts */; } function toProgramEmitPending(value, options) { return !value ? getBuilderFileEmit(options || {}) : value; } -function createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, host) { +function createBuilderProgramUsingIncrementalBuildInfo(buildInfo, buildInfoPath, host) { var _a, _b, _c, _d; - const program = buildInfo.program; const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); let state; - const filePaths = (_a = program.fileNames) == null ? void 0 : _a.map(toPathInBuildInfoDirectory); + const filePaths = (_a = buildInfo.fileNames) == null ? void 0 : _a.map(toPathInBuildInfoDirectory); let filePathsSetList; - const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) : void 0; - if (isProgramBundleEmitBuildInfo(program)) { - const fileInfos = /* @__PURE__ */ new Map(); - program.fileInfos.forEach((fileInfo, index) => { + const latestChangedDtsFile = buildInfo.latestChangedDtsFile ? toAbsolutePath(buildInfo.latestChangedDtsFile) : void 0; + const fileInfos = /* @__PURE__ */ new Map(); + const changedFilesSet = new Set(map(buildInfo.changeFileSet, toFilePath)); + if (isIncrementalBundleEmitBuildInfo(buildInfo)) { + buildInfo.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1); fileInfos.set(path, isString(fileInfo) ? { version: fileInfo, signature: void 0, affectsGlobalScope: void 0, impliedFormat: void 0 } : fileInfo); }); state = { fileInfos, - compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, + compilerOptions: buildInfo.options ? convertToOptionsWithAbsolutePaths(buildInfo.options, toAbsolutePath) : {}, + semanticDiagnosticsPerFile: toPerFileSemanticDiagnostics(buildInfo.semanticDiagnosticsPerFile), + emitDiagnosticsPerFile: toPerFileEmitDiagnostics(buildInfo.emitDiagnosticsPerFile), + hasReusableDiagnostic: true, + changedFilesSet, latestChangedDtsFile, - outSignature: program.outSignature, - programEmitPending: program.pendingEmit === void 0 ? void 0 : toProgramEmitPending(program.pendingEmit, program.options) + outSignature: buildInfo.outSignature, + programEmitPending: buildInfo.pendingEmit === void 0 ? void 0 : toProgramEmitPending(buildInfo.pendingEmit, buildInfo.options), + hasErrors: buildInfo.errors, + checkPending: buildInfo.checkPending }; } else { - filePathsSetList = (_b = program.fileIdsList) == null ? void 0 : _b.map((fileIds) => new Set(fileIds.map(toFilePath))); - const fileInfos = /* @__PURE__ */ new Map(); - const emitSignatures = ((_c = program.options) == null ? void 0 : _c.composite) && !program.options.outFile ? /* @__PURE__ */ new Map() : void 0; - program.fileInfos.forEach((fileInfo, index) => { + filePathsSetList = (_b = buildInfo.fileIdsList) == null ? void 0 : _b.map((fileIds) => new Set(fileIds.map(toFilePath))); + const emitSignatures = ((_c = buildInfo.options) == null ? void 0 : _c.composite) && !buildInfo.options.outFile ? /* @__PURE__ */ new Map() : void 0; + buildInfo.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1); const stateFileInfo = toBuilderStateFileInfoForMultiEmit(fileInfo); fileInfos.set(path, stateFileInfo); if (emitSignatures && stateFileInfo.signature) emitSignatures.set(path, stateFileInfo.signature); }); - (_d = program.emitSignatures) == null ? void 0 : _d.forEach((value) => { + (_d = buildInfo.emitSignatures) == null ? void 0 : _d.forEach((value) => { if (isNumber(value)) emitSignatures.delete(toFilePath(value)); else { const key = toFilePath(value[0]); @@ -129053,25 +130048,24 @@ function createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, hos ); } }); - const changedFilesSet = new Set(map(program.changeFileSet, toFilePath)); - const fullEmitForOptions = program.affectedFilesPendingEmit ? getBuilderFileEmit(program.options || {}) : void 0; + const fullEmitForOptions = buildInfo.affectedFilesPendingEmit ? getBuilderFileEmit(buildInfo.options || {}) : void 0; state = { fileInfos, - compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, - referencedMap: toManyToManyPathMap(program.referencedMap, program.options ?? {}), - semanticDiagnosticsPerFile: toPerFileSemanticDiagnostics(program.semanticDiagnosticsPerFile, fileInfos, changedFilesSet), - emitDiagnosticsPerFile: toPerFileEmitDiagnostics(program.emitDiagnosticsPerFile), + compilerOptions: buildInfo.options ? convertToOptionsWithAbsolutePaths(buildInfo.options, toAbsolutePath) : {}, + referencedMap: toManyToManyPathMap(buildInfo.referencedMap, buildInfo.options ?? {}), + semanticDiagnosticsPerFile: toPerFileSemanticDiagnostics(buildInfo.semanticDiagnosticsPerFile), + emitDiagnosticsPerFile: toPerFileEmitDiagnostics(buildInfo.emitDiagnosticsPerFile), hasReusableDiagnostic: true, - affectedFilesPendingEmit: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, (value) => toFilePath(isNumber(value) ? value : value[0]), (value) => toBuilderFileEmit(value, fullEmitForOptions)), changedFilesSet, + affectedFilesPendingEmit: buildInfo.affectedFilesPendingEmit && arrayToMap(buildInfo.affectedFilesPendingEmit, (value) => toFilePath(isNumber(value) ? value : value[0]), (value) => toBuilderFileEmit(value, fullEmitForOptions)), latestChangedDtsFile, - emitSignatures: (emitSignatures == null ? void 0 : emitSignatures.size) ? emitSignatures : void 0 + emitSignatures: (emitSignatures == null ? void 0 : emitSignatures.size) ? emitSignatures : void 0, + hasErrors: buildInfo.errors, + checkPending: buildInfo.checkPending }; } return { - getState: () => state, - saveEmitState: noop, - restoreEmitState: noop, + state, getProgram: notImplemented, getProgramOrUndefined: returnUndefined, releaseProgram: noop, @@ -129111,7 +130105,7 @@ function createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, hos referenceMap.forEach(([fileId, fileIdListId]) => map2.set(toFilePath(fileId), toFilePathsSet(fileIdListId))); return map2; } - function toPerFileSemanticDiagnostics(diagnostics, fileInfos, changedFilesSet) { + function toPerFileSemanticDiagnostics(diagnostics) { const semanticDiagnostics = new Map( mapDefinedIterator( fileInfos.keys(), @@ -129122,7 +130116,7 @@ function createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, hos if (isNumber(value)) semanticDiagnostics.delete(toFilePath(value)); else semanticDiagnostics.set(toFilePath(value[0]), value[1]); }); - return semanticDiagnostics.size ? semanticDiagnostics : void 0; + return semanticDiagnostics; } function toPerFileEmitDiagnostics(diagnostics) { return diagnostics && arrayToMap(diagnostics, (value) => toFilePath(value[0]), (value) => value[1]); @@ -129163,15 +130157,19 @@ function getBuildInfoFileVersionMap(program, buildInfoPath, host) { } } } -function createRedirectedBuilderProgram(getState, configFileParsingDiagnostics) { +function getNonIncrementalBuildInfoRoots(buildInfo, buildInfoPath, host) { + if (!isNonIncrementalBuildInfo(buildInfo)) return void 0; + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + return buildInfo.root.map((r) => toPath(r, buildInfoDirectory, getCanonicalFileName)); +} +function createRedirectedBuilderProgram(state, configFileParsingDiagnostics) { return { - getState: notImplemented, - saveEmitState: noop, - restoreEmitState: noop, + state: void 0, getProgram, - getProgramOrUndefined: () => getState().program, - releaseProgram: () => getState().program = void 0, - getCompilerOptions: () => getState().compilerOptions, + getProgramOrUndefined: () => state.program, + releaseProgram: () => state.program = void 0, + getCompilerOptions: () => state.compilerOptions, getSourceFile: (fileName) => getProgram().getSourceFile(fileName), getSourceFiles: () => getProgram().getSourceFiles(), getOptionsDiagnostics: (cancellationToken) => getProgram().getOptionsDiagnostics(cancellationToken), @@ -129187,20 +130185,50 @@ function createRedirectedBuilderProgram(getState, configFileParsingDiagnostics) close: noop }; function getProgram() { - return Debug.checkDefined(getState().program); + return Debug.checkDefined(state.program); } } // src/compiler/builderPublic.ts function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences) { - return createBuilderProgram(0 /* SemanticDiagnosticsBuilderProgram */, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); + return createBuilderProgram( + 0 /* SemanticDiagnosticsBuilderProgram */, + getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences + ) + ); } function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences) { - return createBuilderProgram(1 /* EmitAndSemanticDiagnosticsBuilderProgram */, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); + return createBuilderProgram( + 1 /* EmitAndSemanticDiagnosticsBuilderProgram */, + getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences + ) + ); } function createAbstractBuilder(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences) { - const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences); - return createRedirectedBuilderProgram(() => ({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }), newConfigFileParsingDiagnostics); + const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences + ); + return createRedirectedBuilderProgram( + { program: newProgram, compilerOptions: newProgram.getCompilerOptions() }, + newConfigFileParsingDiagnostics + ); } // src/compiler/resolutionCache.ts @@ -129213,9 +130241,9 @@ function removeIgnoredPath(path) { function perceivedOsRootLengthForWatching(pathComponents2, length2) { if (length2 <= 1) return 1; let indexAfterOsRoot = 1; - let isDosStyle = pathComponents2[0].search(/[a-zA-Z]:/) === 0; + let isDosStyle = pathComponents2[0].search(/[a-z]:/i) === 0; if (pathComponents2[0] !== directorySeparator && !isDosStyle && // Non dos style paths - pathComponents2[1].search(/[a-zA-Z]\$$/) === 0) { + pathComponents2[1].search(/[a-z]\$$/i) === 0) { if (length2 === 2) return 2; indexAfterOsRoot = 2; isDosStyle = true; @@ -129250,7 +130278,7 @@ function canWatchAffectedPackageJsonOrNodeModulesOfAtTypes(fileOrDirPath) { function canWatchAffectingLocation(filePath) { return canWatchAffectedPackageJsonOrNodeModulesOfAtTypes(filePath); } -function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, rootDir, rootPath, rootPathComponents, getCurrentDirectory) { +function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, rootDir, rootPath, rootPathComponents, getCurrentDirectory, preferNonRecursiveWatch) { const failedLookupPathComponents = getPathComponents(failedLookupLocationPath); failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory()); const failedLookupComponents = getPathComponents(failedLookupLocation); @@ -129282,10 +130310,11 @@ function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLoo perceivedOsRootLength, nodeModulesIndex, rootPathComponents, - lastNodeModulesIndex + lastNodeModulesIndex, + preferNonRecursiveWatch ); } -function getDirectoryToWatchFromFailedLookupLocationDirectory(dirComponents, dirPathComponents, dirPathComponentsLength, perceivedOsRootLength, nodeModulesIndex, rootPathComponents, lastNodeModulesIndex) { +function getDirectoryToWatchFromFailedLookupLocationDirectory(dirComponents, dirPathComponents, dirPathComponentsLength, perceivedOsRootLength, nodeModulesIndex, rootPathComponents, lastNodeModulesIndex, preferNonRecursiveWatch) { if (nodeModulesIndex !== -1) { return getDirectoryOfFailedLookupWatch( dirComponents, @@ -129296,11 +130325,13 @@ function getDirectoryToWatchFromFailedLookupLocationDirectory(dirComponents, dir } let nonRecursive = true; let length2 = dirPathComponentsLength; - for (let i = 0; i < dirPathComponentsLength; i++) { - if (dirPathComponents[i] !== rootPathComponents[i]) { - nonRecursive = false; - length2 = Math.max(i + 1, perceivedOsRootLength + 1); - break; + if (!preferNonRecursiveWatch) { + for (let i = 0; i < dirPathComponentsLength; i++) { + if (dirPathComponents[i] !== rootPathComponents[i]) { + nonRecursive = false; + length2 = Math.max(i + 1, perceivedOsRootLength + 1); + break; + } } } return getDirectoryOfFailedLookupWatch( @@ -129328,7 +130359,7 @@ function getDirectoryOfFailedLookupWatch(dirComponents, dirPathComponents, lengt packageDirPath: packageDirLength !== void 0 ? getPathFromPathComponents(dirPathComponents, packageDirLength) : void 0 }; } -function getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot, typeRootPath, rootPath, rootPathComponents, getCurrentDirectory, filterCustomPath) { +function getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot, typeRootPath, rootPath, rootPathComponents, getCurrentDirectory, preferNonRecursiveWatch, filterCustomPath) { const typeRootPathComponents = getPathComponents(typeRootPath); if (isInDirectoryPath(rootPathComponents, typeRootPathComponents)) { return rootPath; @@ -129341,7 +130372,8 @@ function getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot, typeRootP perceivedOsRootLengthForWatching(typeRootPathComponents, typeRootPathComponents.length), typeRootPathComponents.indexOf("node_modules"), rootPathComponents, - typeRootPathComponents.lastIndexOf("node_modules") + typeRootPathComponents.lastIndexOf("node_modules"), + preferNonRecursiveWatch ); return toWatch && filterCustomPath(toWatch.dirPath) ? toWatch.dirPath : void 0; } @@ -129349,9 +130381,6 @@ function getRootDirectoryOfResolutionCache(rootDirForResolution, getCurrentDirec const normalized = getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory()); return !isDiskPathRoot(normalized) ? removeTrailingDirectorySeparator(normalized) : normalized; } -function getRootPathSplitLength(rootPath) { - return rootPath.split(directorySeparator).length - (hasTrailingDirectorySeparator(rootPath) ? 1 : 0); -} function getModuleResolutionHost(resolutionHost) { var _a; return ((_a = resolutionHost.getCompilerHost) == null ? void 0 : _a.call(resolutionHost)) || resolutionHost; @@ -129400,7 +130429,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW let filesWithChangedSetOfUnresolvedImports; let filesWithInvalidatedResolutions; let filesWithInvalidatedNonRelativeUnresolvedImports; - const nonRelativeExternalModuleResolutions = createMultiMap(); + const nonRelativeExternalModuleResolutions = /* @__PURE__ */ new Set(); const resolutionsWithFailedLookups = /* @__PURE__ */ new Set(); const resolutionsWithOnlyAffectingLocations = /* @__PURE__ */ new Set(); const resolvedFileToResolution = /* @__PURE__ */ new Map(); @@ -129481,12 +130510,6 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW clear: clear2, onChangesAffectModuleResolution }; - function getResolvedModule(resolution) { - return resolution.resolvedModule; - } - function getResolvedTypeReferenceDirective(resolution) { - return resolution.resolvedTypeReferenceDirective; - } function clear2() { clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf); clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf); @@ -129557,8 +130580,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW moduleResolutionCache.clearAllExceptPackageJsonInfoCache(); typeReferenceDirectiveResolutionCache.clearAllExceptPackageJsonInfoCache(); libraryResolutionCache.clearAllExceptPackageJsonInfoCache(); - nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions); - nonRelativeExternalModuleResolutions.clear(); + watchFailedLookupLocationOfNonRelativeModuleResolutions(); isSymlinkCache.clear(); } function cleanupLibResolutionWatching(newProgram) { @@ -129568,7 +130590,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW stopWatchFailedLookupLocationOfResolution( resolution, resolutionHost.toPath(getInferredLibraryNameResolveFrom(resolutionHost.getCompilationSettings(), getCurrentDirectory(), libFileName)), - getResolvedModule + getResolvedModuleFromResolution ); resolvedLibraries.delete(libFileName); } @@ -129577,13 +130599,12 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW function finishCachingPerDirectoryResolution(newProgram, oldProgram) { filesWithInvalidatedNonRelativeUnresolvedImports = void 0; allModuleAndTypeResolutionsAreInvalidated = false; - nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions); - nonRelativeExternalModuleResolutions.clear(); + watchFailedLookupLocationOfNonRelativeModuleResolutions(); if (newProgram !== oldProgram) { cleanupLibResolutionWatching(newProgram); newProgram == null ? void 0 : newProgram.getSourceFiles().forEach((newFile) => { var _a; - const expected = isExternalOrCommonJsModule(newFile) ? ((_a = newFile.packageJsonLocations) == null ? void 0 : _a.length) ?? 0 : 0; + const expected = ((_a = newFile.packageJsonLocations) == null ? void 0 : _a.length) ?? 0; const existing = impliedFormatPackageJsons.get(newFile.resolvedPath) ?? emptyArray; for (let i = existing.length; i < expected; i++) { createFileWatcherOfAffectingLocation( @@ -129748,7 +130769,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW getModuleResolutionHost(resolutionHost), typeReferenceDirectiveResolutionCache ), - getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective, + getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution, shouldRetryResolution: (resolution) => resolution.resolvedTypeReferenceDirective === void 0, deferWatchingNonRelativeResolution: false }); @@ -129769,7 +130790,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW resolutionHost, moduleResolutionCache ), - getResolutionWithResolvedFileName: getResolvedModule, + getResolutionWithResolvedFileName: getResolvedModuleFromResolution, shouldRetryResolution: (resolution) => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), logChanges: logChangesWhenResolvingModule, deferWatchingNonRelativeResolution: true @@ -129787,17 +130808,17 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW libraryName, resolution, path, - getResolvedModule, + getResolvedModuleFromResolution, /*deferWatchingNonRelativeResolution*/ false ); resolvedLibraries.set(libFileName, resolution); if (existingResolution) { - stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule); + stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModuleFromResolution); } } else { if (isTraceEnabled(options, host)) { - const resolved = getResolvedModule(resolution); + const resolved = getResolvedModuleFromResolution(resolution); trace( host, (resolved == null ? void 0 : resolved.resolvedFileName) ? resolved.packageId ? Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved, @@ -129836,27 +130857,20 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW return endsWith(dirPath, "/node_modules/@types"); } function watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, filePath, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution) { - var _a; - if (resolution.refCount) { - resolution.refCount++; - Debug.assertIsDefined(resolution.files); - } else { - resolution.refCount = 1; - Debug.assert(!((_a = resolution.files) == null ? void 0 : _a.size)); - if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) { - watchFailedLookupLocationOfResolution(resolution); - } else { - nonRelativeExternalModuleResolutions.add(name, resolution); - } - const resolved = getResolutionWithResolvedFileName(resolution); - if (resolved && resolved.resolvedFileName) { - const key = resolutionHost.toPath(resolved.resolvedFileName); - let resolutions = resolvedFileToResolution.get(key); - if (!resolutions) resolvedFileToResolution.set(key, resolutions = /* @__PURE__ */ new Set()); - resolutions.add(resolution); - } - } (resolution.files ?? (resolution.files = /* @__PURE__ */ new Set())).add(filePath); + if (resolution.files.size !== 1) return; + if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) { + watchFailedLookupLocationOfResolution(resolution); + } else { + nonRelativeExternalModuleResolutions.add(resolution); + } + const resolved = getResolutionWithResolvedFileName(resolution); + if (resolved && resolved.resolvedFileName) { + const key = resolutionHost.toPath(resolved.resolvedFileName); + let resolutions = resolvedFileToResolution.get(key); + if (!resolutions) resolvedFileToResolution.set(key, resolutions = /* @__PURE__ */ new Set()); + resolutions.add(resolution); + } } function watchFailedLookupLocation(failedLookupLocation, setAtRoot) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); @@ -129866,7 +130880,8 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW rootDir, rootPath, rootPathComponents, - getCurrentDirectory + getCurrentDirectory, + resolutionHost.preferNonRecursiveWatch ); if (toWatch) { const { dir, dirPath, nonRecursive, packageDir, packageDirPath } = toWatch; @@ -129881,7 +130896,8 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW return setAtRoot; } function watchFailedLookupLocationOfResolution(resolution) { - Debug.assert(!!resolution.refCount); + var _a; + Debug.assert(!!((_a = resolution.files) == null ? void 0 : _a.size)); const { failedLookupLocations, affectingLocations, alternateResult } = resolution; if (!(failedLookupLocations == null ? void 0 : failedLookupLocations.length) && !(affectingLocations == null ? void 0 : affectingLocations.length) && !alternateResult) return; if ((failedLookupLocations == null ? void 0 : failedLookupLocations.length) || alternateResult) resolutionsWithFailedLookups.add(resolution); @@ -129907,7 +130923,8 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW watchAffectingLocationsOfResolution(resolution, !(failedLookupLocations == null ? void 0 : failedLookupLocations.length) && !alternateResult); } function watchAffectingLocationsOfResolution(resolution, addToResolutionsWithOnlyAffectingLocations) { - Debug.assert(!!resolution.refCount); + var _a; + Debug.assert(!!((_a = resolution.files) == null ? void 0 : _a.size)); const { affectingLocations } = resolution; if (!(affectingLocations == null ? void 0 : affectingLocations.length)) return; if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution); @@ -129981,17 +130998,9 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW (_a = watcher == null ? void 0 : watcher.symlinks) == null ? void 0 : _a.forEach((path2) => invalidateAffectingFileWatcher(path2, packageJsonMap)); packageJsonMap == null ? void 0 : packageJsonMap.delete(resolutionHost.toPath(path)); } - function watchFailedLookupLocationOfNonRelativeModuleResolutions(resolutions, name) { - const program = resolutionHost.getCurrentProgram(); - if (!program || !program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(name)) { - resolutions.forEach(watchFailedLookupLocationOfResolution); - } else { - resolutions.forEach((resolution) => watchAffectingLocationsOfResolution( - resolution, - /*addToResolutionsWithOnlyAffectingLocations*/ - true - )); - } + function watchFailedLookupLocationOfNonRelativeModuleResolutions() { + nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfResolution); + nonRelativeExternalModuleResolutions.clear(); } function createDirectoryWatcherForPackageDir(dir, dirPath, packageDir, packageDirPath, nonRecursive) { Debug.assert(!nonRecursive); @@ -130011,11 +131020,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW ); } else if (packageDirWatcher.isSymlink !== isSymlink) { packageDirWatcher.dirPathToWatcher.forEach((watcher) => { - removeDirectoryWatcher( - packageDirWatcher.isSymlink ? packageDirPath : dirPath, - /*syncDirWatcherRemove*/ - false - ); + removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath); watcher.watcher = createDirPathToWatcher(); }); packageDirWatcher.isSymlink = isSymlink; @@ -130055,7 +131060,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW } return dirWatcher; } - function stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot, syncDirWatcherRemove) { + function stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); const toWatch = getDirectoryToWatchFailedLookupLocation( failedLookupLocation, @@ -130063,7 +131068,8 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW rootDir, rootPath, rootPathComponents, - getCurrentDirectory + getCurrentDirectory, + resolutionHost.preferNonRecursiveWatch ); if (toWatch) { const { dirPath, packageDirPath } = toWatch; @@ -130074,7 +131080,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW const forDirPath = packageDirWatcher.dirPathToWatcher.get(dirPath); forDirPath.refCount--; if (forDirPath.refCount === 0) { - removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath, syncDirWatcherRemove); + removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath); packageDirWatcher.dirPathToWatcher.delete(dirPath); if (packageDirWatcher.isSymlink) { const refCount = dirPathToSymlinkPackageRefCount.get(dirPath) - 1; @@ -130084,20 +131090,17 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW dirPathToSymlinkPackageRefCount.set(dirPath, refCount); } } - if (syncDirWatcherRemove) closePackageDirWatcher(packageDirWatcher, packageDirPath); } } else { - removeDirectoryWatcher(dirPath, syncDirWatcherRemove); + removeDirectoryWatcher(dirPath); } } return removeAtRoot; } - function stopWatchFailedLookupLocationOfResolution(resolution, filePath, getResolutionWithResolvedFileName, syncDirWatcherRemove) { + function stopWatchFailedLookupLocationOfResolution(resolution, filePath, getResolutionWithResolvedFileName) { Debug.checkDefined(resolution.files).delete(filePath); - resolution.refCount--; - if (resolution.refCount) { - return; - } + if (resolution.files.size) return; + resolution.files = void 0; const resolved = getResolutionWithResolvedFileName(resolution); if (resolved && resolved.resolvedFileName) { const key = resolutionHost.toPath(resolved.resolvedFileName); @@ -130109,11 +131112,11 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW let removeAtRoot = false; if (failedLookupLocations) { for (const failedLookupLocation of failedLookupLocations) { - removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot, syncDirWatcherRemove); + removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot); } } - if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot, syncDirWatcherRemove); - if (removeAtRoot) removeDirectoryWatcher(rootPath, syncDirWatcherRemove); + if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot); + if (removeAtRoot) removeDirectoryWatcher(rootPath); } else if (affectingLocations == null ? void 0 : affectingLocations.length) { resolutionsWithOnlyAffectingLocations.delete(resolution); } @@ -130121,14 +131124,12 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW for (const affectingLocation of affectingLocations) { const watcher = fileWatchesOfAffectingLocations.get(affectingLocation); watcher.resolutions--; - if (syncDirWatcherRemove) closeFileWatcherOfAffectingLocation(watcher, affectingLocation); } } } - function removeDirectoryWatcher(dirPath, syncDirWatcherRemove) { + function removeDirectoryWatcher(dirPath) { const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); dirWatcher.refCount--; - if (syncDirWatcherRemove) closeDirectoryWatchesOfFailedLookup(dirWatcher, dirPath); } function createDirectoryWatcher(directory, dirPath, nonRecursive) { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, (fileOrDirectory) => { @@ -130139,15 +131140,14 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath); }, nonRecursive ? 0 /* None */ : 1 /* Recursive */); } - function removeResolutionsOfFileFromCache(cache, filePath, getResolutionWithResolvedFileName, syncDirWatcherRemove) { + function removeResolutionsOfFileFromCache(cache, filePath, getResolutionWithResolvedFileName) { const resolutions = cache.get(filePath); if (resolutions) { resolutions.forEach( (resolution) => stopWatchFailedLookupLocationOfResolution( resolution, filePath, - getResolutionWithResolvedFileName, - syncDirWatcherRemove + getResolutionWithResolvedFileName ) ); cache.delete(filePath); @@ -130161,9 +131161,9 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW if (!resolvedProjectReference) return; resolvedProjectReference.commandLine.fileNames.forEach((f) => removeResolutionsOfFile(resolutionHost.toPath(f))); } - function removeResolutionsOfFile(filePath, syncDirWatcherRemove) { - removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModule, syncDirWatcherRemove); - removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective, syncDirWatcherRemove); + function removeResolutionsOfFile(filePath) { + removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModuleFromResolution); + removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirectiveFromResolution); } function invalidateResolutions(resolutions, canInvalidate) { if (!resolutions) return false; @@ -130293,6 +131293,7 @@ function createResolutionCache(resolutionHost, rootDirForResolution, logChangesW rootPath, rootPathComponents, getCurrentDirectory, + resolutionHost.preferNonRecursiveWatch, (dirPath2) => directoryWatchesOfFailedLookups.has(dirPath2) || dirPathToSymlinkPackageRefCount.has(dirPath2) ); if (dirPath) { @@ -130458,7 +131459,7 @@ function createTabularErrorsDisplay(filesInError, host) { if (distinctFiles.length === 0) return ""; const numberLength = (num) => Math.log(num) * Math.LOG10E + 1; const fileToErrorCount = distinctFiles.map((file) => [file, countWhere(filesInError, (fileInError) => fileInError.fileName === file.fileName)]); - const maxErrors = fileToErrorCount.reduce((acc, value) => Math.max(acc, value[1] || 0), 0); + const maxErrors = maxBy(fileToErrorCount, 0, (value) => value[1]); const headerRow = Diagnostics.Errors_Files.message; const leftColumnHeadingLength = headerRow.split(" ")[0].length; const leftPaddingGoal = Math.max(leftColumnHeadingLength, numberLength(maxErrors)); @@ -130475,13 +131476,13 @@ function createTabularErrorsDisplay(filesInError, host) { }); return tabularData; } -function isBuilderProgram2(program) { - return !!program.getState; +function isBuilderProgram(program) { + return !!program.state; } function listFiles(program, write) { const options = program.getCompilerOptions(); if (options.explainFiles) { - explainFiles(isBuilderProgram2(program) ? program.getProgram() : program, write); + explainFiles(isBuilderProgram(program) ? program.getProgram() : program, write); } else if (options.listFiles || options.listFilesOnly) { forEach(program.getSourceFiles(), (file) => { write(file.fileName); @@ -130495,10 +131496,10 @@ function explainFiles(program, write) { for (const file of program.getSourceFiles()) { write(`${toFileName(file, relativeFileName)}`); (_a = reasons.get(file.path)) == null ? void 0 : _a.forEach((reason) => write(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`)); - (_b = explainIfFileIsRedirectAndImpliedFormat(file, relativeFileName)) == null ? void 0 : _b.forEach((d) => write(` ${d.messageText}`)); + (_b = explainIfFileIsRedirectAndImpliedFormat(file, program.getCompilerOptionsForFile(file), relativeFileName)) == null ? void 0 : _b.forEach((d) => write(` ${d.messageText}`)); } } -function explainIfFileIsRedirectAndImpliedFormat(file, fileNameConvertor) { +function explainIfFileIsRedirectAndImpliedFormat(file, options, fileNameConvertor) { var _a; let result; if (file.path !== file.resolvedPath) { @@ -130518,7 +131519,7 @@ function explainIfFileIsRedirectAndImpliedFormat(file, fileNameConvertor) { )); } if (isExternalOrCommonJsModule(file)) { - switch (file.impliedNodeFormat) { + switch (getImpliedNodeFormatForEmitWorker(file, options)) { case 99 /* ESNext */: if (file.packageJsonScope) { (result ?? (result = [])).push(chainDiagnosticMessages( @@ -130686,7 +131687,7 @@ function toFileName(file, fileNameConvertor) { return fileNameConvertor ? fileNameConvertor(fileName) : fileName; } function emitFilesAndReportErrors(program, reportDiagnostic, write, reportSummary, writeFile2, cancellationToken, emitOnlyDtsFiles, customTransformers) { - const isListFilesOnly = !!program.getCompilerOptions().listFilesOnly; + const options = program.getCompilerOptions(); const allDiagnostics = program.getConfigFileParsingDiagnostics().slice(); const configFileParsingDiagnosticsLength = allDiagnostics.length; addRange(allDiagnostics, program.getSyntacticDiagnostics( @@ -130696,7 +131697,7 @@ function emitFilesAndReportErrors(program, reportDiagnostic, write, reportSummar )); if (allDiagnostics.length === configFileParsingDiagnosticsLength) { addRange(allDiagnostics, program.getOptionsDiagnostics(cancellationToken)); - if (!isListFilesOnly) { + if (!options.listFilesOnly) { addRange(allDiagnostics, program.getGlobalDiagnostics(cancellationToken)); if (allDiagnostics.length === configFileParsingDiagnosticsLength) { addRange(allDiagnostics, program.getSemanticDiagnostics( @@ -130705,9 +131706,16 @@ function emitFilesAndReportErrors(program, reportDiagnostic, write, reportSummar cancellationToken )); } + if (options.noEmit && getEmitDeclarations(options) && allDiagnostics.length === configFileParsingDiagnosticsLength) { + addRange(allDiagnostics, program.getDeclarationDiagnostics( + /*sourceFile*/ + void 0, + cancellationToken + )); + } } } - const emitResult = isListFilesOnly ? { emitSkipped: true, diagnostics: emptyArray } : program.emit( + const emitResult = options.listFilesOnly ? { emitSkipped: true, diagnostics: emptyArray } : program.emit( /*targetSourceFile*/ void 0, writeFile2, @@ -130715,13 +131723,12 @@ function emitFilesAndReportErrors(program, reportDiagnostic, write, reportSummar emitOnlyDtsFiles, customTransformers ); - const { emittedFiles, diagnostics: emitDiagnostics } = emitResult; - addRange(allDiagnostics, emitDiagnostics); + addRange(allDiagnostics, emitResult.diagnostics); const diagnostics = sortAndDeduplicateDiagnostics(allDiagnostics); diagnostics.forEach(reportDiagnostic); if (write) { const currentDir = program.getCurrentDirectory(); - forEach(emittedFiles, (file) => { + forEach(emitResult.emittedFiles, (file) => { const filepath = getNormalizedAbsolutePath(file, currentDir); write(`TSFILE: ${filepath}`); }); @@ -130762,7 +131769,8 @@ function createWatchHost(system = sys, reportWatchStatus2) { watchFile: maybeBind(system, system.watchFile) || returnNoopFileWatcher, watchDirectory: maybeBind(system, system.watchDirectory) || returnNoopFileWatcher, setTimeout: maybeBind(system, system.setTimeout) || noop, - clearTimeout: maybeBind(system, system.clearTimeout) || noop + clearTimeout: maybeBind(system, system.clearTimeout) || noop, + preferNonRecursiveWatch: system.preferNonRecursiveWatch }; } var WatchType = { @@ -130981,8 +131989,8 @@ function readBuilderProgram(compilerOptions, host) { if (!content) return void 0; buildInfo = getBuildInfo(buildInfoPath, content); } - if (!buildInfo || buildInfo.version !== version || !buildInfo.program) return void 0; - return createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, host); + if (!buildInfo || buildInfo.version !== version || !isIncrementalBuildInfo(buildInfo)) return void 0; + return createBuilderProgramUsingIncrementalBuildInfo(buildInfo, buildInfoPath, host); } function createIncrementalCompilerHost(options, system = sys) { const host = createCompilerHostWorker( @@ -131093,6 +132101,7 @@ function createWatchProgram(host) { compilerHost.toPath = toPath3; compilerHost.getCompilationSettings = () => compilerOptions; compilerHost.useSourceOfProjectReferenceRedirect = maybeBind(host, host.useSourceOfProjectReferenceRedirect); + compilerHost.preferNonRecursiveWatch = host.preferNonRecursiveWatch; compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.FailedLookupLocations); compilerHost.watchAffectingFileLocation = (file, cb) => watchFile2(file, cb, 2e3 /* High */, watchOptions, WatchType.AffectingFileLocation); compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.TypeRoots); @@ -131404,22 +132413,17 @@ function createWatchProgram(host) { updateProgram(); } function updateProgram() { - var _a, _b, _c, _d; switch (updateLevel) { case 1 /* RootNamesAndUpdate */: - (_a = perfLogger) == null ? void 0 : _a.logStartUpdateProgram("PartialConfigReload"); reloadFileNamesFromConfigFile(); break; case 2 /* Full */: - (_b = perfLogger) == null ? void 0 : _b.logStartUpdateProgram("FullConfigReload"); reloadConfigFile(); break; default: - (_c = perfLogger) == null ? void 0 : _c.logStartUpdateProgram("SynchronizeProgram"); synchronizeProgram(); break; } - (_d = perfLogger) == null ? void 0 : _d.logStopUpdateProgram("Done"); return getCurrentBuilderProgram(); } function reloadFileNamesFromConfigFile() { @@ -131701,16 +132705,17 @@ var UpToDateStatusType = /* @__PURE__ */ ((UpToDateStatusType2) => { UpToDateStatusType2[UpToDateStatusType2["ErrorReadingFile"] = 4] = "ErrorReadingFile"; UpToDateStatusType2[UpToDateStatusType2["OutOfDateWithSelf"] = 5] = "OutOfDateWithSelf"; UpToDateStatusType2[UpToDateStatusType2["OutOfDateWithUpstream"] = 6] = "OutOfDateWithUpstream"; - UpToDateStatusType2[UpToDateStatusType2["OutOfDateBuildInfo"] = 7] = "OutOfDateBuildInfo"; - UpToDateStatusType2[UpToDateStatusType2["OutOfDateOptions"] = 8] = "OutOfDateOptions"; - UpToDateStatusType2[UpToDateStatusType2["OutOfDateRoots"] = 9] = "OutOfDateRoots"; - UpToDateStatusType2[UpToDateStatusType2["UpstreamOutOfDate"] = 10] = "UpstreamOutOfDate"; - UpToDateStatusType2[UpToDateStatusType2["UpstreamBlocked"] = 11] = "UpstreamBlocked"; - UpToDateStatusType2[UpToDateStatusType2["ComputingUpstream"] = 12] = "ComputingUpstream"; - UpToDateStatusType2[UpToDateStatusType2["TsVersionOutputOfDate"] = 13] = "TsVersionOutputOfDate"; - UpToDateStatusType2[UpToDateStatusType2["UpToDateWithInputFileText"] = 14] = "UpToDateWithInputFileText"; - UpToDateStatusType2[UpToDateStatusType2["ContainerOnly"] = 15] = "ContainerOnly"; - UpToDateStatusType2[UpToDateStatusType2["ForceBuild"] = 16] = "ForceBuild"; + UpToDateStatusType2[UpToDateStatusType2["OutOfDateBuildInfoWithPendingEmit"] = 7] = "OutOfDateBuildInfoWithPendingEmit"; + UpToDateStatusType2[UpToDateStatusType2["OutOfDateBuildInfoWithErrors"] = 8] = "OutOfDateBuildInfoWithErrors"; + UpToDateStatusType2[UpToDateStatusType2["OutOfDateOptions"] = 9] = "OutOfDateOptions"; + UpToDateStatusType2[UpToDateStatusType2["OutOfDateRoots"] = 10] = "OutOfDateRoots"; + UpToDateStatusType2[UpToDateStatusType2["UpstreamOutOfDate"] = 11] = "UpstreamOutOfDate"; + UpToDateStatusType2[UpToDateStatusType2["UpstreamBlocked"] = 12] = "UpstreamBlocked"; + UpToDateStatusType2[UpToDateStatusType2["ComputingUpstream"] = 13] = "ComputingUpstream"; + UpToDateStatusType2[UpToDateStatusType2["TsVersionOutputOfDate"] = 14] = "TsVersionOutputOfDate"; + UpToDateStatusType2[UpToDateStatusType2["UpToDateWithInputFileText"] = 15] = "UpToDateWithInputFileText"; + UpToDateStatusType2[UpToDateStatusType2["ContainerOnly"] = 16] = "ContainerOnly"; + UpToDateStatusType2[UpToDateStatusType2["ForceBuild"] = 17] = "ForceBuild"; return UpToDateStatusType2; })(UpToDateStatusType || {}); function resolveConfigFileProjectName(project) { @@ -131722,7 +132727,6 @@ function resolveConfigFileProjectName(project) { // src/compiler/tsbuildPublic.ts var minimumDate = /* @__PURE__ */ new Date(-864e13); -var maximumDate = /* @__PURE__ */ new Date(864e13); function getOrCreateValueFromConfigFileMap(configFileMap, resolved, createT) { const existingValue = configFileMap.get(resolved); let newValue; @@ -131777,6 +132781,7 @@ function getCompilerOptionsOfBuildOptions(buildOptions) { commonOptionsWithBuild.forEach((option) => { if (hasProperty(buildOptions, option.name)) result[option.name] = buildOptions[option.name]; }); + result.tscBuild = true; return result; } function createSolutionBuilder(host, rootNames, defaultOptions) { @@ -132180,7 +133185,7 @@ function createUpdateOutputFileStampsProject(state, project, projectPath, config } }; } -function createBuildOrUpdateInvalidedProject(state, project, projectPath, projectIndex, config, buildOrder) { +function createBuildOrUpdateInvalidedProject(state, project, projectPath, projectIndex, config, status, buildOrder) { let step = 0 /* CreateProgram */; let program; let buildResult; @@ -132231,17 +133236,13 @@ function createBuildOrUpdateInvalidedProject(state, project, projectPath, projec } ); } - executeSteps(2 /* SemanticDiagnostics */, cancellationToken); - if (step === 4 /* EmitBuildInfo */) { - return emitBuildInfo(writeFile2, cancellationToken); - } - if (step !== 3 /* Emit */) return void 0; + executeSteps(0 /* CreateProgram */, cancellationToken); return emit(writeFile2, cancellationToken, customTransformers); }, done }; function done(cancellationToken, writeFile2, customTransformers) { - executeSteps(6 /* Done */, cancellationToken, writeFile2, customTransformers); + executeSteps(3 /* Done */, cancellationToken, writeFile2, customTransformers); mark("SolutionBuilder::Projects built"); return doneInvalidatedProject(state, projectPath); } @@ -132258,14 +133259,14 @@ function createBuildOrUpdateInvalidedProject(state, project, projectPath, projec if (state.options.dry) { reportStatus(state, Diagnostics.A_non_dry_build_would_build_project_0, project); buildResult = 1 /* Success */; - step = 5 /* QueueReferencingProjects */; + step = 2 /* QueueReferencingProjects */; return; } if (state.options.verbose) reportStatus(state, Diagnostics.Building_project_0, project); if (config.fileNames.length === 0) { reportAndStoreErrors(state, projectPath, getConfigFileParsingDiagnostics(config)); buildResult = 0 /* None */; - step = 5 /* QueueReferencingProjects */; + step = 2 /* QueueReferencingProjects */; return; } const { host, compilerHost } = state; @@ -132293,185 +133294,97 @@ function createBuildOrUpdateInvalidedProject(state, project, projectPath, projec } step++; } - function handleDiagnostics(diagnostics, errorFlags, errorType) { - if (diagnostics.length) { - ({ buildResult, step } = buildErrors( - state, - projectPath, - program, - config, - diagnostics, - errorFlags, - errorType - )); - } else { - step++; - } - } - function getSyntaxDiagnostics(cancellationToken) { - Debug.assertIsDefined(program); - handleDiagnostics( - [ - ...program.getConfigFileParsingDiagnostics(), - ...program.getOptionsDiagnostics(cancellationToken), - ...program.getGlobalDiagnostics(cancellationToken), - ...program.getSyntacticDiagnostics( - /*sourceFile*/ - void 0, - cancellationToken - ) - ], - 8 /* SyntaxErrors */, - "Syntactic" - ); - } - function getSemanticDiagnostics(cancellationToken) { - handleDiagnostics( - Debug.checkDefined(program).getSemanticDiagnostics( - /*sourceFile*/ - void 0, - cancellationToken - ), - 16 /* TypeErrors */, - "Semantic" - ); - } function emit(writeFileCallback, cancellationToken, customTransformers) { var _a, _b, _c; Debug.assertIsDefined(program); - Debug.assert(step === 3 /* Emit */); - const saved = program.saveEmitState(); - let declDiagnostics; - const reportDeclarationDiagnostics = (d) => (declDiagnostics || (declDiagnostics = [])).push(d); - const outputFiles = []; - const { emitResult } = emitFilesAndReportErrors( - program, - reportDeclarationDiagnostics, - /*write*/ - void 0, - /*reportSummary*/ - void 0, - (name, text, writeByteOrderMark, _onError, _sourceFiles, data) => outputFiles.push({ name, text, writeByteOrderMark, data }), - cancellationToken, - /*emitOnlyDtsFiles*/ - false, - customTransformers || ((_b = (_a = state.host).getCustomTransformers) == null ? void 0 : _b.call(_a, project)) - ); - if (declDiagnostics) { - program.restoreEmitState(saved); - ({ buildResult, step } = buildErrors( - state, - projectPath, - program, - config, - declDiagnostics, - 32 /* DeclarationEmitErrors */, - "Declaration file" - )); - return { - emitSkipped: true, - diagnostics: emitResult.diagnostics - }; - } + Debug.assert(step === 1 /* Emit */); const { host, compilerHost } = state; - const resultFlags = ((_c = program.hasChangedEmitSignature) == null ? void 0 : _c.call(program)) ? 0 /* None */ : 2 /* DeclarationOutputUnchanged */; - const emitterDiagnostics = createDiagnosticCollection(); const emittedOutputs = /* @__PURE__ */ new Map(); const options = program.getCompilerOptions(); const isIncremental = isIncrementalCompilation(options); let outputTimeStampMap; let now; - outputFiles.forEach(({ name, text, writeByteOrderMark, data }) => { - const path = toPath2(state, name); - emittedOutputs.set(toPath2(state, name), name); - if (data == null ? void 0 : data.buildInfo) setBuildInfo(state, data.buildInfo, projectPath, options, resultFlags); - const modifiedTime = (data == null ? void 0 : data.differsOnlyInMap) ? getModifiedTime(state.host, name) : void 0; - writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark); - if (data == null ? void 0 : data.differsOnlyInMap) state.host.setModifiedTime(name, modifiedTime); - else if (!isIncremental && state.watch) { - (outputTimeStampMap || (outputTimeStampMap = getOutputTimeStampMap(state, projectPath))).set(path, now || (now = getCurrentTime(state.host))); - } - }); - finishEmit( - emitterDiagnostics, - emittedOutputs, - outputFiles.length ? outputFiles[0].name : getFirstProjectOutput(config, !host.useCaseSensitiveFileNames()), - resultFlags + const { emitResult, diagnostics } = emitFilesAndReportErrors( + program, + (d) => host.reportDiagnostic(d), + state.write, + /*reportSummary*/ + void 0, + (name, text, writeByteOrderMark, onError, sourceFiles, data) => { + var _a2; + const path = toPath2(state, name); + emittedOutputs.set(toPath2(state, name), name); + if (data == null ? void 0 : data.buildInfo) { + now || (now = getCurrentTime(state.host)); + const isChangedSignature2 = (_a2 = program.hasChangedEmitSignature) == null ? void 0 : _a2.call(program); + const existing = getBuildInfoCacheEntry(state, name, projectPath); + if (existing) { + existing.buildInfo = data.buildInfo; + existing.modifiedTime = now; + if (isChangedSignature2) existing.latestChangedDtsTime = now; + } else { + state.buildInfoCache.set(projectPath, { + path: toPath2(state, name), + buildInfo: data.buildInfo, + modifiedTime: now, + latestChangedDtsTime: isChangedSignature2 ? now : void 0 + }); + } + } + const modifiedTime = (data == null ? void 0 : data.differsOnlyInMap) ? getModifiedTime(state.host, name) : void 0; + (writeFileCallback || compilerHost.writeFile)( + name, + text, + writeByteOrderMark, + onError, + sourceFiles, + data + ); + if (data == null ? void 0 : data.differsOnlyInMap) state.host.setModifiedTime(name, modifiedTime); + else if (!isIncremental && state.watch) { + (outputTimeStampMap || (outputTimeStampMap = getOutputTimeStampMap(state, projectPath))).set(path, now || (now = getCurrentTime(state.host))); + } + }, + cancellationToken, + /*emitOnlyDtsFiles*/ + void 0, + customTransformers || ((_b = (_a = state.host).getCustomTransformers) == null ? void 0 : _b.call(_a, project)) ); - return emitResult; - } - function emitBuildInfo(writeFileCallback, cancellationToken) { - Debug.assertIsDefined(program); - Debug.assert(step === 4 /* EmitBuildInfo */); - const emitResult = program.emitBuildInfo((name, text, writeByteOrderMark, onError, sourceFiles, data) => { - if (data == null ? void 0 : data.buildInfo) setBuildInfo(state, data.buildInfo, projectPath, program.getCompilerOptions(), 2 /* DeclarationOutputUnchanged */); - if (writeFileCallback) writeFileCallback(name, text, writeByteOrderMark, onError, sourceFiles, data); - else state.compilerHost.writeFile(name, text, writeByteOrderMark, onError, sourceFiles, data); - }, cancellationToken); - if (emitResult.diagnostics.length) { - reportErrors(state, emitResult.diagnostics); - state.diagnostics.set(projectPath, [...state.diagnostics.get(projectPath), ...emitResult.diagnostics]); - buildResult = 64 /* EmitErrors */ & buildResult; + if ((!options.noEmitOnError || !diagnostics.length) && (emittedOutputs.size || status.type !== 8 /* OutOfDateBuildInfoWithErrors */)) { + updateOutputTimestampsWorker(state, config, projectPath, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs); } - if (emitResult.emittedFiles && state.write) { - emitResult.emittedFiles.forEach((name) => listEmittedFile(state, config, name)); + state.projectErrorsReported.set(projectPath, true); + buildResult = ((_c = program.hasChangedEmitSignature) == null ? void 0 : _c.call(program)) ? 0 /* None */ : 2 /* DeclarationOutputUnchanged */; + if (!diagnostics.length) { + state.diagnostics.delete(projectPath); + state.projectStatus.set(projectPath, { + type: 1 /* UpToDate */, + oldestOutputFileName: firstOrUndefinedIterator(emittedOutputs.values()) ?? getFirstProjectOutput(config, !host.useCaseSensitiveFileNames()) + }); + } else { + state.diagnostics.set(projectPath, diagnostics); + state.projectStatus.set(projectPath, { type: 0 /* Unbuildable */, reason: `it had errors` }); + buildResult |= 4 /* AnyErrors */; } afterProgramDone(state, program); - step = 5 /* QueueReferencingProjects */; + step = 2 /* QueueReferencingProjects */; return emitResult; } - function finishEmit(emitterDiagnostics, emittedOutputs, oldestOutputFileName, resultFlags) { - const emitDiagnostics = emitterDiagnostics.getDiagnostics(); - if (emitDiagnostics.length) { - ({ buildResult, step } = buildErrors( - state, - projectPath, - program, - config, - emitDiagnostics, - 64 /* EmitErrors */, - "Emit" - )); - return emitDiagnostics; - } - if (state.write) { - emittedOutputs.forEach((name) => listEmittedFile(state, config, name)); - } - updateOutputTimestampsWorker(state, config, projectPath, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs); - state.diagnostics.delete(projectPath); - state.projectStatus.set(projectPath, { - type: 1 /* UpToDate */, - oldestOutputFileName - }); - afterProgramDone(state, program); - step = 5 /* QueueReferencingProjects */; - buildResult = resultFlags; - return emitDiagnostics; - } function executeSteps(till, cancellationToken, writeFile2, customTransformers) { - while (step <= till && step < 6 /* Done */) { + while (step <= till && step < 3 /* Done */) { const currentStep = step; switch (step) { case 0 /* CreateProgram */: createProgram2(); break; - case 1 /* SyntaxDiagnostics */: - getSyntaxDiagnostics(cancellationToken); - break; - case 2 /* SemanticDiagnostics */: - getSemanticDiagnostics(cancellationToken); - break; - case 3 /* Emit */: + case 1 /* Emit */: emit(writeFile2, cancellationToken, customTransformers); break; - case 4 /* EmitBuildInfo */: - emitBuildInfo(writeFile2, cancellationToken); - break; - case 5 /* QueueReferencingProjects */: + case 2 /* QueueReferencingProjects */: queueReferencingProjects(state, project, projectPath, projectIndex, config, buildOrder, Debug.checkDefined(buildResult)); step++; break; - case 6 /* Done */: + case 3 /* Done */: default: assertType(step); } @@ -132521,7 +133434,7 @@ function getNextInvalidatedProjectCreateInfo(state, buildOrder, reportQueue) { } continue; } - if (status.type === 2 /* UpToDateWithUpstreamTypes */ || status.type === 14 /* UpToDateWithInputFileText */) { + if (status.type === 2 /* UpToDateWithUpstreamTypes */ || status.type === 15 /* UpToDateWithInputFileText */) { reportAndStoreErrors(state, projectPath, getConfigFileParsingDiagnostics(config)); return { kind: 1 /* UpdateOutputFileStamps */, @@ -132533,7 +133446,7 @@ function getNextInvalidatedProjectCreateInfo(state, buildOrder, reportQueue) { }; } } - if (status.type === 11 /* UpstreamBlocked */) { + if (status.type === 12 /* UpstreamBlocked */) { verboseReportProjectStatus(state, project, status); reportAndStoreErrors(state, projectPath, getConfigFileParsingDiagnostics(config)); projectPendingBuild.delete(projectPath); @@ -132547,7 +133460,7 @@ function getNextInvalidatedProjectCreateInfo(state, buildOrder, reportQueue) { } continue; } - if (status.type === 15 /* ContainerOnly */) { + if (status.type === 16 /* ContainerOnly */) { verboseReportProjectStatus(state, project, status); reportAndStoreErrors(state, projectPath, getConfigFileParsingDiagnostics(config)); projectPendingBuild.delete(projectPath); @@ -132572,6 +133485,7 @@ function createInvalidatedProjectWithInfo(state, info, buildOrder) { info.projectPath, info.projectIndex, info.config, + info.status, buildOrder ) : createUpdateOutputFileStampsProject( state, @@ -132586,11 +133500,6 @@ function getNextInvalidatedProject(state, buildOrder, reportQueue) { if (!info) return info; return createInvalidatedProjectWithInfo(state, info, buildOrder); } -function listEmittedFile({ write }, proj, file) { - if (write && proj.options.listEmittedFiles) { - write(`TSFILE: ${file}`); - } -} function getOldProgram({ options, builderPrograms, compilerHost }, proj, parsed) { if (options.force) return void 0; const value = builderPrograms.get(proj); @@ -132599,7 +133508,6 @@ function getOldProgram({ options, builderPrograms, compilerHost }, proj, parsed) } function afterProgramDone(state, program) { if (program) { - if (state.write) listFiles(program, state.write); if (state.host.afterProgramEmitAndDiagnostics) { state.host.afterProgramEmitAndDiagnostics(program); } @@ -132607,14 +133515,6 @@ function afterProgramDone(state, program) { } state.projectCompilerOptions = state.baseCompilerOptions; } -function buildErrors(state, resolvedPath, program, config, diagnostics, buildResult, errorType) { - const canEmitBuildInfo = program && !program.getCompilerOptions().outFile; - reportAndStoreErrors(state, resolvedPath, diagnostics); - state.projectStatus.set(resolvedPath, { type: 0 /* Unbuildable */, reason: `${errorType} errors` }); - if (canEmitBuildInfo) return { buildResult, step: 4 /* EmitBuildInfo */ }; - afterProgramDone(state, program); - return { buildResult, step: 5 /* QueueReferencingProjects */ }; -} function isFileWatcherWithModifiedTime(value) { return !!value.watcher; } @@ -132672,23 +133572,6 @@ function getOutputTimeStampMap(state, resolvedConfigFilePath) { if (!result) state.outputTimeStamps.set(resolvedConfigFilePath, result = /* @__PURE__ */ new Map()); return result; } -function setBuildInfo(state, buildInfo, resolvedConfigPath, options, resultFlags) { - const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); - const existing = getBuildInfoCacheEntry(state, buildInfoPath, resolvedConfigPath); - const modifiedTime = getCurrentTime(state.host); - if (existing) { - existing.buildInfo = buildInfo; - existing.modifiedTime = modifiedTime; - if (!(resultFlags & 2 /* DeclarationOutputUnchanged */)) existing.latestChangedDtsTime = modifiedTime; - } else { - state.buildInfoCache.set(resolvedConfigPath, { - path: toPath2(state, buildInfoPath), - buildInfo, - modifiedTime, - latestChangedDtsTime: resultFlags & 2 /* DeclarationOutputUnchanged */ ? void 0 : modifiedTime - }); - } -} function getBuildInfoCacheEntry(state, buildInfoPath, resolvedConfigPath) { const path = toPath2(state, buildInfoPath); const existing = state.buildInfoCache.get(resolvedConfigPath); @@ -132716,99 +133599,107 @@ function checkConfigFileUpToDateStatus(state, configFile, oldestOutputFileTime, } } function getUpToDateStatusWorker(state, project, resolvedPath) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e; if (!project.fileNames.length && !canJsonReportNoInputFiles(project.raw)) { return { - type: 15 /* ContainerOnly */ + type: 16 /* ContainerOnly */ }; } let referenceStatuses; const force = !!state.options.force; if (project.projectReferences) { - state.projectStatus.set(resolvedPath, { type: 12 /* ComputingUpstream */ }); + state.projectStatus.set(resolvedPath, { type: 13 /* ComputingUpstream */ }); for (const ref of project.projectReferences) { const resolvedRef = resolveProjectReferencePath(ref); const resolvedRefPath = toResolvedConfigFilePath(state, resolvedRef); const resolvedConfig = parseConfigFile(state, resolvedRef, resolvedRefPath); const refStatus = getUpToDateStatus(state, resolvedConfig, resolvedRefPath); - if (refStatus.type === 12 /* ComputingUpstream */ || refStatus.type === 15 /* ContainerOnly */) { + if (refStatus.type === 13 /* ComputingUpstream */ || refStatus.type === 16 /* ContainerOnly */) { continue; } - if (refStatus.type === 0 /* Unbuildable */ || refStatus.type === 11 /* UpstreamBlocked */) { + if (state.options.stopBuildOnErrors && (refStatus.type === 0 /* Unbuildable */ || refStatus.type === 12 /* UpstreamBlocked */)) { return { - type: 11 /* UpstreamBlocked */, + type: 12 /* UpstreamBlocked */, upstreamProjectName: ref.path, - upstreamProjectBlocked: refStatus.type === 11 /* UpstreamBlocked */ - }; - } - if (refStatus.type !== 1 /* UpToDate */) { - return { - type: 10 /* UpstreamOutOfDate */, - upstreamProjectName: ref.path + upstreamProjectBlocked: refStatus.type === 12 /* UpstreamBlocked */ }; } if (!force) (referenceStatuses || (referenceStatuses = [])).push({ ref, refStatus, resolvedRefPath, resolvedConfig }); } } - if (force) return { type: 16 /* ForceBuild */ }; + if (force) return { type: 17 /* ForceBuild */ }; const { host } = state; const buildInfoPath = getTsBuildInfoEmitOutputFilePath(project.options); - let oldestOutputFileName; - let oldestOutputFileTime = maximumDate; - let buildInfoTime; - let buildInfoProgram; - let buildInfoVersionMap; - if (buildInfoPath) { - const buildInfoCacheEntry2 = getBuildInfoCacheEntry(state, buildInfoPath, resolvedPath); - buildInfoTime = (buildInfoCacheEntry2 == null ? void 0 : buildInfoCacheEntry2.modifiedTime) || getModifiedTime(host, buildInfoPath); - if (buildInfoTime === missingFileModifiedTime) { - if (!buildInfoCacheEntry2) { - state.buildInfoCache.set(resolvedPath, { - path: toPath2(state, buildInfoPath), - buildInfo: false, - modifiedTime: buildInfoTime - }); - } - return { - type: 3 /* OutputMissing */, - missingOutputFileName: buildInfoPath - }; + const isIncremental = isIncrementalCompilation(project.options); + let buildInfoCacheEntry = getBuildInfoCacheEntry(state, buildInfoPath, resolvedPath); + const buildInfoTime = (buildInfoCacheEntry == null ? void 0 : buildInfoCacheEntry.modifiedTime) || getModifiedTime(host, buildInfoPath); + if (buildInfoTime === missingFileModifiedTime) { + if (!buildInfoCacheEntry) { + state.buildInfoCache.set(resolvedPath, { + path: toPath2(state, buildInfoPath), + buildInfo: false, + modifiedTime: buildInfoTime + }); } - const buildInfo = getBuildInfo3(state, buildInfoPath, resolvedPath, buildInfoTime); - if (!buildInfo) { - return { - type: 4 /* ErrorReadingFile */, - fileName: buildInfoPath - }; - } - if (buildInfo.program && buildInfo.version !== version) { - return { - type: 13 /* TsVersionOutputOfDate */, - version: buildInfo.version - }; - } - if (buildInfo.program) { - if (((_a = buildInfo.program.changeFileSet) == null ? void 0 : _a.length) || (!project.options.noEmit ? ((_b = buildInfo.program.affectedFilesPendingEmit) == null ? void 0 : _b.length) || ((_c = buildInfo.program.emitDiagnosticsPerFile) == null ? void 0 : _c.length) : (_d = buildInfo.program.semanticDiagnosticsPerFile) == null ? void 0 : _d.length)) { - return { - type: 7 /* OutOfDateBuildInfo */, - buildInfoFile: buildInfoPath - }; - } - if (!project.options.noEmit && getPendingEmitKind(project.options, buildInfo.program.options || {})) { - return { - type: 8 /* OutOfDateOptions */, - buildInfoFile: buildInfoPath - }; - } - buildInfoProgram = buildInfo.program; - } - oldestOutputFileTime = buildInfoTime; - oldestOutputFileName = buildInfoPath; + return { + type: 3 /* OutputMissing */, + missingOutputFileName: buildInfoPath + }; } + const buildInfo = getBuildInfo3(state, buildInfoPath, resolvedPath, buildInfoTime); + if (!buildInfo) { + return { + type: 4 /* ErrorReadingFile */, + fileName: buildInfoPath + }; + } + const incrementalBuildInfo = isIncremental && isIncrementalBuildInfo(buildInfo) ? buildInfo : void 0; + if ((incrementalBuildInfo || !isIncremental) && buildInfo.version !== version) { + return { + type: 14 /* TsVersionOutputOfDate */, + version: buildInfo.version + }; + } + if (!project.options.noCheck && (buildInfo.errors || // TODO: syntax errors???? + buildInfo.checkPending)) { + return { + type: 8 /* OutOfDateBuildInfoWithErrors */, + buildInfoFile: buildInfoPath + }; + } + if (incrementalBuildInfo) { + if (!project.options.noCheck && (((_a = incrementalBuildInfo.changeFileSet) == null ? void 0 : _a.length) || ((_b = incrementalBuildInfo.semanticDiagnosticsPerFile) == null ? void 0 : _b.length) || getEmitDeclarations(project.options) && ((_c = incrementalBuildInfo.emitDiagnosticsPerFile) == null ? void 0 : _c.length))) { + return { + type: 8 /* OutOfDateBuildInfoWithErrors */, + buildInfoFile: buildInfoPath + }; + } + if (!project.options.noEmit && (((_d = incrementalBuildInfo.changeFileSet) == null ? void 0 : _d.length) || ((_e = incrementalBuildInfo.affectedFilesPendingEmit) == null ? void 0 : _e.length) || incrementalBuildInfo.pendingEmit !== void 0)) { + return { + type: 7 /* OutOfDateBuildInfoWithPendingEmit */, + buildInfoFile: buildInfoPath + }; + } + if ((!project.options.noEmit || project.options.noEmit && getEmitDeclarations(project.options)) && getPendingEmitKindWithSeen( + project.options, + incrementalBuildInfo.options || {}, + /*emitOnlyDtsFiles*/ + void 0, + !!project.options.noEmit + )) { + return { + type: 9 /* OutOfDateOptions */, + buildInfoFile: buildInfoPath + }; + } + } + let oldestOutputFileTime = buildInfoTime; + let oldestOutputFileName = buildInfoPath; let newestInputFileName = void 0; let newestInputFileTime = minimumDate; let pseudoInputUpToDate = false; const seenRoots = /* @__PURE__ */ new Set(); + let buildInfoVersionMap; for (const inputFile of project.fileNames) { const inputTime = getModifiedTime2(state, inputFile); if (inputTime === missingFileModifiedTime) { @@ -132817,12 +133708,12 @@ function getUpToDateStatusWorker(state, project, resolvedPath) { reason: `${inputFile} does not exist` }; } - const inputPath = buildInfoProgram ? toPath2(state, inputFile) : void 0; - if (buildInfoTime && buildInfoTime < inputTime) { + const inputPath = toPath2(state, inputFile); + if (buildInfoTime < inputTime) { let version2; let currentVersion; - if (buildInfoProgram) { - if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath, host); + if (incrementalBuildInfo) { + if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(incrementalBuildInfo, buildInfoPath, host); const resolvedInputPath = buildInfoVersionMap.roots.get(inputPath); version2 = buildInfoVersionMap.fileInfos.get(resolvedInputPath ?? inputPath); const text = version2 ? state.readFileWithCache(resolvedInputPath ?? inputFile) : void 0; @@ -132841,27 +133732,34 @@ function getUpToDateStatusWorker(state, project, resolvedPath) { newestInputFileName = inputFile; newestInputFileTime = inputTime; } - if (buildInfoProgram) seenRoots.add(inputPath); + seenRoots.add(inputPath); } - if (buildInfoProgram) { - if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath, host); - const existingRoot = forEachEntry( + let existingRoot; + if (incrementalBuildInfo) { + if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(incrementalBuildInfo, buildInfoPath, host); + existingRoot = forEachEntry( buildInfoVersionMap.roots, // File was root file when project was built but its not any more (_resolved, existingRoot2) => !seenRoots.has(existingRoot2) ? existingRoot2 : void 0 ); - if (existingRoot) { - return { - type: 9 /* OutOfDateRoots */, - buildInfoFile: buildInfoPath, - inputFile: existingRoot - }; - } + } else { + existingRoot = forEach( + getNonIncrementalBuildInfoRoots(buildInfo, buildInfoPath, host), + (root) => !seenRoots.has(root) ? root : void 0 + ); } - if (!buildInfoPath) { + if (existingRoot) { + return { + type: 10 /* OutOfDateRoots */, + buildInfoFile: buildInfoPath, + inputFile: existingRoot + }; + } + if (!isIncremental) { const outputs = getAllProjectOutputs(project, !host.useCaseSensitiveFileNames()); const outputTimeStampMap = getOutputTimeStampMap(state, resolvedPath); for (const output of outputs) { + if (output === buildInfoPath) continue; const path = toPath2(state, output); let outputTime = outputTimeStampMap == null ? void 0 : outputTimeStampMap.get(path); if (!outputTime) { @@ -132887,14 +133785,13 @@ function getUpToDateStatusWorker(state, project, resolvedPath) { } } } - const buildInfoCacheEntry = state.buildInfoCache.get(resolvedPath); let pseudoUpToDate = false; if (referenceStatuses) { for (const { ref, refStatus, resolvedConfig, resolvedRefPath } of referenceStatuses) { if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) { continue; } - if (buildInfoCacheEntry && hasSameBuildInfo(state, buildInfoCacheEntry, resolvedRefPath)) { + if (hasSameBuildInfo(state, buildInfoCacheEntry ?? (buildInfoCacheEntry = state.buildInfoCache.get(resolvedPath)), resolvedRefPath)) { return { type: 6 /* OutOfDateWithUpstream */, outOfDateOutputFileName: buildInfoPath, @@ -132925,7 +133822,7 @@ function getUpToDateStatusWorker(state, project, resolvedPath) { ); if (dependentPackageFileStatus) return dependentPackageFileStatus; return { - type: pseudoUpToDate ? 2 /* UpToDateWithUpstreamTypes */ : pseudoInputUpToDate ? 14 /* UpToDateWithInputFileText */ : 1 /* UpToDate */, + type: pseudoUpToDate ? 2 /* UpToDateWithUpstreamTypes */ : pseudoInputUpToDate ? 15 /* UpToDateWithInputFileText */ : 1 /* UpToDate */, newestInputFileTime, newestInputFileName, oldestOutputFileName @@ -132937,7 +133834,7 @@ function hasSameBuildInfo(state, buildInfoCacheEntry, resolvedRefPath) { } function getUpToDateStatus(state, project, resolvedPath) { if (project === void 0) { - return { type: 0 /* Unbuildable */, reason: "File deleted mid-build" }; + return { type: 0 /* Unbuildable */, reason: "config file deleted mid-build" }; } const prior = state.projectStatus.get(resolvedPath); if (prior !== void 0) { @@ -132954,7 +133851,8 @@ function updateOutputTimestampsWorker(state, proj, projectPath, verboseMessage, if (proj.options.noEmit) return; let now; const buildInfoPath = getTsBuildInfoEmitOutputFilePath(proj.options); - if (buildInfoPath) { + const isIncremental = isIncrementalCompilation(proj.options); + if (buildInfoPath && isIncremental) { if (!(skipOutputs == null ? void 0 : skipOutputs.has(toPath2(state, buildInfoPath)))) { if (!!state.options.verbose) reportStatus(state, verboseMessage, proj.options.configFilePath); state.host.setModifiedTime(buildInfoPath, now = getCurrentTime(state.host)); @@ -132977,7 +133875,8 @@ function updateOutputTimestampsWorker(state, proj, projectPath, verboseMessage, reportStatus(state, verboseMessage, proj.options.configFilePath); } host.setModifiedTime(file, now || (now = getCurrentTime(state.host))); - if (outputTimeStampMap) { + if (file === buildInfoPath) getBuildInfoCacheEntry(state, buildInfoPath, projectPath).modifiedTime = now; + else if (outputTimeStampMap) { outputTimeStampMap.set(path, now); modifiedOutputs.add(path); } @@ -132991,7 +133890,7 @@ function getLatestChangedDtsTime(state, options, resolvedConfigPath) { if (!options.composite) return void 0; const entry = Debug.checkDefined(state.buildInfoCache.get(resolvedConfigPath)); if (entry.latestChangedDtsTime !== void 0) return entry.latestChangedDtsTime || void 0; - const latestChangedDtsTime = entry.buildInfo && entry.buildInfo.program && entry.buildInfo.program.latestChangedDtsFile ? state.host.getModifiedTime(getNormalizedAbsolutePath(entry.buildInfo.program.latestChangedDtsFile, getDirectoryPath(entry.path))) : void 0; + const latestChangedDtsTime = entry.buildInfo && isIncrementalBuildInfo(entry.buildInfo) && entry.buildInfo.latestChangedDtsFile ? state.host.getModifiedTime(getNormalizedAbsolutePath(entry.buildInfo.latestChangedDtsFile, getDirectoryPath(entry.path))) : void 0; entry.latestChangedDtsTime = latestChangedDtsTime || false; return latestChangedDtsTime; } @@ -133006,7 +133905,7 @@ function updateOutputTimestamps(state, proj, resolvedPath) { }); } function queueReferencingProjects(state, project, projectPath, projectIndex, config, buildOrder, buildResult) { - if (buildResult & 124 /* AnyErrors */) return; + if (state.options.stopBuildOnErrors && buildResult & 4 /* AnyErrors */) return; if (!config.options.composite) return; for (let index = projectIndex + 1; index < buildOrder.length; index++) { const nextProject = buildOrder[index]; @@ -133025,7 +133924,7 @@ function queueReferencingProjects(state, project, projectPath, projectIndex, con status.type = 2 /* UpToDateWithUpstreamTypes */; break; } - case 14 /* UpToDateWithInputFileText */: + case 15 /* UpToDateWithInputFileText */: case 2 /* UpToDateWithUpstreamTypes */: if (!(buildResult & 2 /* DeclarationOutputUnchanged */)) { state.projectStatus.set(nextProjectPath, { @@ -133035,7 +133934,7 @@ function queueReferencingProjects(state, project, projectPath, projectIndex, con }); } break; - case 11 /* UpstreamBlocked */: + case 12 /* UpstreamBlocked */: if (toResolvedConfigFilePath(state, resolveProjectName(state, status.upstreamProjectName)) === projectPath) { clearProjectStatus(state, nextProjectPath); } @@ -133454,21 +134353,28 @@ function reportUpToDateStatus(state, configFileName, status) { relName(state, configFileName), relName(state, status.fileName) ); - case 7 /* OutOfDateBuildInfo */: + case 7 /* OutOfDateBuildInfoWithPendingEmit */: return reportStatus( state, Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_some_of_the_changes_were_not_emitted, relName(state, configFileName), relName(state, status.buildInfoFile) ); - case 8 /* OutOfDateOptions */: + case 8 /* OutOfDateBuildInfoWithErrors */: + return reportStatus( + state, + Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors, + relName(state, configFileName), + relName(state, status.buildInfoFile) + ); + case 9 /* OutOfDateOptions */: return reportStatus( state, Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_there_is_change_in_compilerOptions, relName(state, configFileName), relName(state, status.buildInfoFile) ); - case 9 /* OutOfDateRoots */: + case 10 /* OutOfDateRoots */: return reportStatus( state, Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_file_2_was_root_file_of_compilation_but_not_any_more, @@ -133493,20 +134399,20 @@ function reportUpToDateStatus(state, configFileName, status) { Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, relName(state, configFileName) ); - case 14 /* UpToDateWithInputFileText */: + case 15 /* UpToDateWithInputFileText */: return reportStatus( state, Diagnostics.Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_files, relName(state, configFileName) ); - case 10 /* UpstreamOutOfDate */: + case 11 /* UpstreamOutOfDate */: return reportStatus( state, Diagnostics.Project_0_is_out_of_date_because_its_dependency_1_is_out_of_date, relName(state, configFileName), relName(state, status.upstreamProjectName) ); - case 11 /* UpstreamBlocked */: + case 12 /* UpstreamBlocked */: return reportStatus( state, status.upstreamProjectBlocked ? Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_was_not_built : Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, @@ -133516,11 +134422,11 @@ function reportUpToDateStatus(state, configFileName, status) { case 0 /* Unbuildable */: return reportStatus( state, - Diagnostics.Failed_to_parse_file_0_Colon_1, + Diagnostics.Project_0_is_out_of_date_because_1, relName(state, configFileName), status.reason ); - case 13 /* TsVersionOutputOfDate */: + case 14 /* TsVersionOutputOfDate */: return reportStatus( state, Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, @@ -133528,14 +134434,14 @@ function reportUpToDateStatus(state, configFileName, status) { status.version, version ); - case 16 /* ForceBuild */: + case 17 /* ForceBuild */: return reportStatus( state, Diagnostics.Project_0_is_being_forcibly_rebuilt, relName(state, configFileName) ); - case 15 /* ContainerOnly */: - case 12 /* ComputingUpstream */: + case 16 /* ContainerOnly */: + case 13 /* ComputingUpstream */: break; default: assertType(status); @@ -133607,7 +134513,7 @@ function shouldBePretty(sys2, options) { return options.pretty; } function getOptionsForHelp(commandLine) { - return !!commandLine.options.all ? sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : filter(optionDeclarations.slice(), (v) => !!v.showInSimplifiedHelpView); + return !!commandLine.options.all ? toSorted(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : filter(optionDeclarations.slice(), (v) => !!v.showInSimplifiedHelpView); } function printVersion(sys2) { sys2.write(getDiagnosticText(Diagnostics.Version_0, version) + sys2.newLine); @@ -134780,7 +135686,7 @@ function createSyntacticTypeNodeBuilder(options, resolver) { return typeFromAccessor(parent2, context); } const declaredType = getEffectiveTypeAnnotationNode(node); - const addUndefined = resolver.requiresAddingImplicitUndefined(node); + const addUndefined = resolver.requiresAddingImplicitUndefined(node, context.enclosingDeclaration); let resultType; if (declaredType) { resultType = serializeExistingTypeAnnotation(declaredType, addUndefined); @@ -134961,7 +135867,7 @@ function createSyntacticTypeNodeBuilder(options, resolver) { expression, /*includeBigInt*/ false - )) { + ) && !resolver.isDefinitelyReferenceToGlobalSymbolObject(expression)) { context.tracker.reportInferenceFallback(prop.name); result = false; } @@ -135088,7 +135994,6 @@ __export(ts_JsTyping_exports, { nodeCoreModuleList: () => nodeCoreModuleList, nodeCoreModules: () => nodeCoreModules, nonRelativeModuleNameForTypingCache: () => nonRelativeModuleNameForTypingCache, - prefixedNodeCoreModuleList: () => prefixedNodeCoreModuleList, renderPackageNameValidationFailure: () => renderPackageNameValidationFailure, validatePackageName: () => validatePackageName }); @@ -137186,7 +138091,9 @@ function createModuleSpecifierResolutionHost(program, host) { isSourceOfProjectReferenceRedirect: (fileName) => program.isSourceOfProjectReferenceRedirect(fileName), getNearestAncestorDirectoryWithPackageJson: maybeBind(host, host.getNearestAncestorDirectoryWithPackageJson), getFileIncludeReasons: () => program.getFileIncludeReasons(), - getCommonSourceDirectory: () => program.getCommonSourceDirectory() + getCommonSourceDirectory: () => program.getCommonSourceDirectory(), + getDefaultResolutionModeForFile: (file) => program.getDefaultResolutionModeForFile(file), + getModeForResolutionAtIndex: (file, index) => program.getModeForResolutionAtIndex(file, index) }; } function getModuleSpecifierResolverHost(program, host) { @@ -137285,7 +138192,7 @@ function insertImports(changes, sourceFile, imports, blankLineBetween, preferenc const importKindPredicate = decl.kind === 243 /* VariableStatement */ ? isRequireVariableStatement : isAnyImportSyntax; const existingImportStatements = filter(sourceFile.statements, importKindPredicate); const { comparer, isSorted } = ts_OrganizeImports_exports.getOrganizeImportsStringComparerWithDetection(existingImportStatements, preferences); - const sortedNewImports = isArray(imports) ? stableSort(imports, (a, b) => ts_OrganizeImports_exports.compareImportsOrRequireStatements(a, b, comparer)) : [imports]; + const sortedNewImports = isArray(imports) ? toSorted(imports, (a, b) => ts_OrganizeImports_exports.compareImportsOrRequireStatements(a, b, comparer)) : [imports]; if (!(existingImportStatements == null ? void 0 : existingImportStatements.length)) { if (isFullSourceFile(sourceFile)) { changes.insertNodesAtTopOfFile(sourceFile, sortedNewImports, blankLineBetween); @@ -137648,13 +138555,6 @@ function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, f ); }); } -function nodeToDisplayParts(node, enclosingDeclaration) { - const file = enclosingDeclaration.getSourceFile(); - return mapToDisplayParts((writer) => { - const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); - printer.writeNode(4 /* Unspecified */, node, file, writer); - }); -} function isImportOrExportSpecifierName(location) { return !!location.parent && isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location; } @@ -137895,7 +138795,7 @@ function getTypeNodeIfAccessible(type, enclosingScope, program, host) { const checker = program.getTypeChecker(); let typeIsAccessible = true; const notAccessible = () => typeIsAccessible = false; - const res = checker.typeToTypeNode(type, enclosingScope, 1 /* NoTruncation */, { + const res = checker.typeToTypeNode(type, enclosingScope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */, { trackSymbol: (symbol, declaration, meaning) => { typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible( symbol, @@ -138124,7 +139024,7 @@ function createPackageJsonImportFilter(fromFile, preferences, host) { let sourceFileCache; return { allowsImportingAmbientModule, - allowsImportingSourceFile, + getSourceFileInfo, allowsImportingSpecifier }; function moduleSpecifierIsCoveredByPackageJson(specifier) { @@ -138163,9 +139063,9 @@ function createPackageJsonImportFilter(fromFile, preferences, host) { ambientModuleCache.set(moduleSymbol, result); return result; } - function allowsImportingSourceFile(sourceFile, moduleSpecifierResolutionHost) { + function getSourceFileInfo(sourceFile, moduleSpecifierResolutionHost) { if (!packageJsons.length) { - return true; + return { importable: true, packageName: void 0 }; } if (!sourceFileCache) { sourceFileCache = /* @__PURE__ */ new Map(); @@ -138175,12 +139075,14 @@ function createPackageJsonImportFilter(fromFile, preferences, host) { return cached; } } - const moduleSpecifier = getNodeModulesPackageNameFromFileName(sourceFile.fileName, moduleSpecifierResolutionHost); - if (!moduleSpecifier) { - sourceFileCache.set(sourceFile, true); - return true; + const packageName = getNodeModulesPackageNameFromFileName(sourceFile.fileName, moduleSpecifierResolutionHost); + if (!packageName) { + const result2 = { importable: true, packageName }; + sourceFileCache.set(sourceFile, result2); + return result2; } - const result = moduleSpecifierIsCoveredByPackageJson(moduleSpecifier); + const importable = moduleSpecifierIsCoveredByPackageJson(packageName); + const result = { importable, packageName }; sourceFileCache.set(sourceFile, result); return result; } @@ -138290,36 +139192,12 @@ function mapOneOrMany(valueOrArray, f, resultSelector = identity) { function firstOrOnly(valueOrArray) { return isArray(valueOrArray) ? first(valueOrArray) : valueOrArray; } -function getNamesForExportedSymbol(symbol, scriptTarget) { - if (needsNameFromDeclaration(symbol)) { - const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol); - if (fromDeclaration) return fromDeclaration; - const fileNameCase = moduleSymbolToValidIdentifier( - getSymbolParentOrFail(symbol), - scriptTarget, - /*forceCapitalize*/ - false - ); - const capitalized = moduleSymbolToValidIdentifier( - getSymbolParentOrFail(symbol), - scriptTarget, - /*forceCapitalize*/ - true - ); - if (fileNameCase === capitalized) return fileNameCase; - return [fileNameCase, capitalized]; - } - return symbol.name; -} function getNameForExportedSymbol(symbol, scriptTarget, preferCapitalized) { - if (needsNameFromDeclaration(symbol)) { + if (symbol.escapedName === "export=" /* ExportEquals */ || symbol.escapedName === "default" /* Default */) { return getDefaultLikeExportNameFromDeclaration(symbol) || moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, !!preferCapitalized); } return symbol.name; } -function needsNameFromDeclaration(symbol) { - return !(symbol.flags & 33554432 /* Transient */) && (symbol.escapedName === "export=" /* ExportEquals */ || symbol.escapedName === "default" /* Default */); -} function getDefaultLikeExportNameFromDeclaration(symbol) { return firstDefined(symbol.declarations, (d) => { var _a, _b, _c; @@ -138387,16 +139265,6 @@ function stringContainsAt(haystack, needle, startIndex) { function startsWithUnderscore(name) { return name.charCodeAt(0) === 95 /* _ */; } -function isGlobalDeclaration(declaration) { - return !isNonGlobalDeclaration(declaration); -} -function isNonGlobalDeclaration(declaration) { - const sourceFile = declaration.getSourceFile(); - if (!sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) { - return false; - } - return isInJSFile(declaration) || !findAncestor(declaration, (d) => isModuleDeclaration(d) && isGlobalScopeAugmentation(d)); -} function isDeprecatedDeclaration(decl) { return !!(getCombinedNodeFlagsAlwaysIncludeJSDoc(decl) & 65536 /* Deprecated */); } @@ -138492,9 +139360,13 @@ function fileShouldUseJavaScriptRequire(file, program, host, preferRequire) { if (!hasJSFileExtension(fileName)) { return false; } - const compilerOptions = program.getCompilerOptions(); + const compilerOptions = typeof file === "string" ? program.getCompilerOptions() : program.getCompilerOptionsForFile(file); const moduleKind = getEmitModuleKind(compilerOptions); - const impliedNodeFormat = typeof file === "string" ? getImpliedNodeFormatForFile(toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), (_a = program.getPackageJsonInfoCache) == null ? void 0 : _a.call(program), host, compilerOptions) : file.impliedNodeFormat; + const sourceFileLike = typeof file === "string" ? { + fileName: file, + impliedNodeFormat: getImpliedNodeFormatForFile(toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), (_a = program.getPackageJsonInfoCache) == null ? void 0 : _a.call(program), host, compilerOptions) + } : file; + const impliedNodeFormat = getImpliedNodeFormatForEmitWorker(sourceFileLike, compilerOptions); if (impliedNodeFormat === 99 /* ESNext */) { return false; } @@ -138606,6 +139478,7 @@ function createCacheableExportInfoMap(host) { const namedSymbol = isDefault && getLocalSymbolForExportDefault(symbol) || symbol; const names = exportKind === 0 /* Named */ || isExternalModuleSymbol(namedSymbol) ? unescapeLeadingUnderscores(symbolTableKey) : getNamesForExportedSymbol( namedSymbol, + checker, /*scriptTarget*/ void 0 ); @@ -138755,7 +139628,7 @@ function isImportableFile(program, from, to, preferences, packageJsonFilter, mod if (from === to) return false; const cachedResult = moduleSpecifierCache == null ? void 0 : moduleSpecifierCache.get(from.path, to.path, preferences, {}); if ((cachedResult == null ? void 0 : cachedResult.isBlockedByPackageJsonDependencies) !== void 0) { - return !cachedResult.isBlockedByPackageJsonDependencies; + return !cachedResult.isBlockedByPackageJsonDependencies || !!cachedResult.packageName && fileContainsPackageImport(from, cachedResult.packageName); } const getCanonicalFileName = hostGetCanonicalFileName(moduleSpecifierResolutionHost); const globalTypingsCache = (_a = moduleSpecifierResolutionHost.getGlobalTypingsCacheLocation) == null ? void 0 : _a.call(moduleSpecifierResolutionHost); @@ -138771,12 +139644,15 @@ function isImportableFile(program, from, to, preferences, packageJsonFilter, mod } ); if (packageJsonFilter) { - const isAutoImportable = hasImportablePath && packageJsonFilter.allowsImportingSourceFile(to, moduleSpecifierResolutionHost); - moduleSpecifierCache == null ? void 0 : moduleSpecifierCache.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, !isAutoImportable); - return isAutoImportable; + const importInfo = hasImportablePath ? packageJsonFilter.getSourceFileInfo(to, moduleSpecifierResolutionHost) : void 0; + moduleSpecifierCache == null ? void 0 : moduleSpecifierCache.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, importInfo == null ? void 0 : importInfo.packageName, !(importInfo == null ? void 0 : importInfo.importable)); + return !!(importInfo == null ? void 0 : importInfo.importable) || !!(importInfo == null ? void 0 : importInfo.packageName) && fileContainsPackageImport(from, importInfo.packageName); } return hasImportablePath; } +function fileContainsPackageImport(sourceFile, packageName) { + return sourceFile.imports && sourceFile.imports.some((i) => i.text === packageName || i.text.startsWith(packageName + "/")); +} function isImportablePath(fromPath, toPath3, getCanonicalFileName, globalCachePath) { const toNodeModules = forEachAncestorDirectory(toPath3, (ancestor) => getBaseFileName(ancestor) === "node_modules" ? ancestor : void 0); const toNodeModulesParent = toNodeModules && getDirectoryPath(getCanonicalFileName(toNodeModules)); @@ -138785,10 +139661,7 @@ function isImportablePath(fromPath, toPath3, getCanonicalFileName, globalCachePa function forEachExternalModuleToImportFrom(program, host, preferences, useAutoImportProvider, cb) { var _a, _b; const useCaseSensitiveFileNames2 = hostUsesCaseSensitiveFileNames(host); - const excludePatterns = preferences.autoImportFileExcludePatterns && mapDefined(preferences.autoImportFileExcludePatterns, (spec) => { - const pattern = getSubPatternFromSpec(spec, "", "exclude"); - return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames2) : void 0; - }); + const excludePatterns = preferences.autoImportFileExcludePatterns && getIsExcludedPatterns(preferences, useCaseSensitiveFileNames2); forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), excludePatterns, host, (module2, file) => cb( module2, file, @@ -138821,25 +139694,17 @@ function forEachExternalModuleToImportFrom(program, host, preferences, useAutoIm (_b = host.log) == null ? void 0 : _b.call(host, `forEachExternalModuleToImportFrom autoImportProvider: ${timestamp() - start}`); } } -function forEachExternalModule(checker, allSourceFiles, excludePatterns, host, cb) { - var _a, _b; - const realpathsWithSymlinks = (_a = host.getSymlinkCache) == null ? void 0 : _a.call(host).getSymlinkedDirectoriesByRealpath(); - const isExcluded = excludePatterns && (({ fileName, path }) => { - if (excludePatterns.some((p) => p.test(fileName))) return true; - if ((realpathsWithSymlinks == null ? void 0 : realpathsWithSymlinks.size) && pathContainsNodeModules(fileName)) { - let dir = getDirectoryPath(fileName); - return forEachAncestorDirectory(getDirectoryPath(path), (dirPath) => { - const symlinks = realpathsWithSymlinks.get(ensureTrailingDirectorySeparator(dirPath)); - if (symlinks) { - return symlinks.some((s) => excludePatterns.some((p) => p.test(fileName.replace(dir, s)))); - } - dir = getDirectoryPath(dir); - }) ?? false; - } - return false; +function getIsExcludedPatterns(preferences, useCaseSensitiveFileNames2) { + return mapDefined(preferences.autoImportFileExcludePatterns, (spec) => { + const pattern = getSubPatternFromSpec(spec, "", "exclude"); + return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames2) : void 0; }); +} +function forEachExternalModule(checker, allSourceFiles, excludePatterns, host, cb) { + var _a; + const isExcluded = excludePatterns && getIsExcluded(excludePatterns, host); for (const ambient of checker.getAmbientModules()) { - if (!ambient.name.includes("*") && !(excludePatterns && ((_b = ambient.declarations) == null ? void 0 : _b.every((d) => isExcluded(d.getSourceFile()))))) { + if (!ambient.name.includes("*") && !(excludePatterns && ((_a = ambient.declarations) == null ? void 0 : _a.every((d) => isExcluded(d.getSourceFile()))))) { cb( ambient, /*sourceFile*/ @@ -138853,6 +139718,28 @@ function forEachExternalModule(checker, allSourceFiles, excludePatterns, host, c } } } +function getIsExcluded(excludePatterns, host) { + var _a; + const realpathsWithSymlinks = (_a = host.getSymlinkCache) == null ? void 0 : _a.call(host).getSymlinkedDirectoriesByRealpath(); + return ({ fileName, path }) => { + if (excludePatterns.some((p) => p.test(fileName))) return true; + if ((realpathsWithSymlinks == null ? void 0 : realpathsWithSymlinks.size) && pathContainsNodeModules(fileName)) { + let dir = getDirectoryPath(fileName); + return forEachAncestorDirectory(getDirectoryPath(path), (dirPath) => { + const symlinks = realpathsWithSymlinks.get(ensureTrailingDirectorySeparator(dirPath)); + if (symlinks) { + return symlinks.some((s) => excludePatterns.some((p) => p.test(fileName.replace(dir, s)))); + } + dir = getDirectoryPath(dir); + }) ?? false; + } + return false; + }; +} +function getIsFileExcluded(host, preferences) { + if (!preferences.autoImportFileExcludePatterns) return () => false; + return getIsExcluded(getIsExcludedPatterns(preferences, hostUsesCaseSensitiveFileNames(host)), host); +} function getExportInfoMap(importingFile, host, program, preferences, cancellationToken) { var _a, _b, _c, _d, _e; const start = timestamp(); @@ -138930,9 +139817,18 @@ function getDefaultLikeExportInfo(moduleSymbol, checker) { function isImportableSymbol(symbol, checker) { return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) && !isPrivateIdentifierSymbol(symbol); } -function forEachNameOfDefaultExport(defaultExport, checker, compilerOptions, preferCapitalizedNames, cb) { +function getNamesForExportedSymbol(defaultExport, checker, scriptTarget) { + let names; + forEachNameOfDefaultExport(defaultExport, checker, scriptTarget, (name, capitalizedName) => { + names = capitalizedName ? [name, capitalizedName] : name; + return true; + }); + return Debug.checkDefined(names); +} +function forEachNameOfDefaultExport(defaultExport, checker, scriptTarget, cb) { let chain; let current = defaultExport; + const seen = /* @__PURE__ */ new Map(); while (current) { const fromDeclaration = getDefaultLikeExportNameFromDeclaration(current); if (fromDeclaration) { @@ -138944,11 +139840,25 @@ function forEachNameOfDefaultExport(defaultExport, checker, compilerOptions, pre if (final) return final; } chain = append(chain, current); + if (!addToSeen(seen, current)) break; current = current.flags & 2097152 /* Alias */ ? checker.getImmediateAliasedSymbol(current) : void 0; } for (const symbol of chain ?? emptyArray) { if (symbol.parent && isExternalModuleSymbol(symbol.parent)) { - const final = cb(moduleSymbolToValidIdentifier(symbol.parent, getEmitScriptTarget(compilerOptions), preferCapitalizedNames)); + const final = cb( + moduleSymbolToValidIdentifier( + symbol.parent, + scriptTarget, + /*forceCapitalize*/ + false + ), + moduleSymbolToValidIdentifier( + symbol.parent, + scriptTarget, + /*forceCapitalize*/ + true + ) + ); if (final) return final; } } @@ -139614,8 +140524,8 @@ function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) } } function tryClassifyTripleSlashComment(start, width) { - const tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/im; - const attributeRegex = /(\s)(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/img; + const tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/m; + const attributeRegex = /(\s)(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/g; const text = sourceFile.text.substr(start, width); const match = tripleSlashXMLCommentRegEx.exec(text); if (!match) { @@ -140046,10 +140956,8 @@ var DocumentHighlights; return [...nodes, container]; } return nodes; - case 210 /* ObjectLiteralExpression */: - return void 0; default: - Debug.assertNever(container, "Invalid container kind."); + return void 0; } } function pushKeywordIf(keywordList, token, ...expected) { @@ -141330,7 +142238,7 @@ function preProcessFile(sourceText, readImportFiles = true, detectJavaScriptImpo } // src/services/sourcemaps.ts -var base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+/=]+)$)?/; +var base64UrlRegExp = /^data:(?:application\/json;charset=[uU][tT][fF]-8;base64,([A-Za-z0-9+/=]+)$)?/; function getSourceMapper(host) { const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const currentDirectory = host.getCurrentDirectory(); @@ -141382,7 +142290,7 @@ function getSourceMapper(host) { } const options = program.getCompilerOptions(); const outPath = options.outFile; - const declarationPath = outPath ? removeFileExtension(outPath) + ".d.ts" /* Dts */ : getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName); + const declarationPath = outPath ? removeFileExtension(outPath) + ".d.ts" /* Dts */ : getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), program); if (declarationPath === void 0) return void 0; const newLoc = getDocumentPositionMapper2(declarationPath, info.fileName).getGeneratedPosition(info); return newLoc === info ? void 0 : newLoc; @@ -141474,7 +142382,7 @@ function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) { program.getSemanticDiagnostics(sourceFile, cancellationToken); const diags = []; const checker = program.getTypeChecker(); - const isCommonJSFile = sourceFile.impliedNodeFormat === 1 /* CommonJS */ || fileExtensionIsOneOf(sourceFile.fileName, [".cts" /* Cts */, ".cjs" /* Cjs */]); + const isCommonJSFile = program.getImpliedNodeFormatForEmit(sourceFile) === 1 /* CommonJS */ || fileExtensionIsOneOf(sourceFile.fileName, [".cts" /* Cts */, ".cjs" /* Cjs */]); if (!isCommonJSFile && sourceFile.commonJsModuleIndicator && (programContainsEsModules(program) || compilerOptionsIndicateEsModules(program.getCompilerOptions())) && containsTopLevelCommonjs(sourceFile)) { diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_module)); } @@ -141495,7 +142403,8 @@ function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) { } addRange(diags, sourceFile.bindSuggestionDiagnostics); addRange(diags, program.getSuggestionDiagnostics(sourceFile, cancellationToken)); - return diags.sort((d1, d2) => d1.start - d2.start); + diags.sort((d1, d2) => d1.start - d2.start); + return diags; function check(node) { if (isJsFile) { if (canBeConvertedToClass(node, checker)) { @@ -141741,6 +142650,7 @@ function transpileWorker(input, transpileOptions, declaration) { options.isolatedDeclarations = true; } else { options.declaration = false; + options.declarationMap = false; } const newLine = getNewLineCharacter(options); const compilerHost = { @@ -141936,7 +142846,8 @@ function getContainers(declaration) { } container = getContainerNode(container); } - return containers.reverse(); + containers.reverse(); + return containers; } function compareNavigateToItems(i1, i2) { return compareValues(i1.matchKind, i2.matchKind) || compareStringsCaseSensitiveUI(i1.name, i2.name); @@ -142716,13 +143627,12 @@ function isFunctionOrClassExpression(node) { } function cleanText(text) { text = text.length > maxLength ? text.substring(0, maxLength) + "..." : text; - return text.replace(/\\?(\r?\n|\r|\u2028|\u2029)/g, ""); + return text.replace(/\\?(?:\r?\n|[\r\u2028\u2029])/g, ""); } // src/services/_namespaces/ts.refactor.ts var ts_refactor_exports = {}; __export(ts_refactor_exports, { - addExportToChanges: () => addExportToChanges, addExportsInOldFile: () => addExportsInOldFile, addImportsForMovedSymbols: () => addImportsForMovedSymbols, addNewFileToTsconfig: () => addNewFileToTsconfig, @@ -142734,13 +143644,8 @@ __export(ts_refactor_exports, { convertStringOrTemplateLiteral: () => ts_refactor_convertStringOrTemplateLiteral_exports, convertToOptionalChainExpression: () => ts_refactor_convertToOptionalChainExpression_exports, createNewFileName: () => createNewFileName, - deleteMovedStatements: () => deleteMovedStatements, - deleteUnusedImports: () => deleteUnusedImports, - deleteUnusedOldImports: () => deleteUnusedOldImports, doChangeNamedToNamespaceOrDefault: () => doChangeNamedToNamespaceOrDefault, extractSymbol: () => ts_refactor_extractSymbol_exports, - filterImport: () => filterImport, - forEachImportInStatement: () => forEachImportInStatement, generateGetAccessorAndSetAccessor: () => ts_refactor_generateGetAccessorAndSetAccessor_exports, getApplicableRefactors: () => getApplicableRefactors, getEditsForRefactor: () => getEditsForRefactor, @@ -142748,16 +143653,11 @@ __export(ts_refactor_exports, { getIdentifierForNode: () => getIdentifierForNode, getNewStatementsAndRemoveFromOldFile: () => getNewStatementsAndRemoveFromOldFile, getStatementsToMove: () => getStatementsToMove, - getTopLevelDeclarationStatement: () => getTopLevelDeclarationStatement, getUsageInfo: () => getUsageInfo, inferFunctionReturnType: () => ts_refactor_inferFunctionReturnType_exports, isRefactorErrorInfo: () => isRefactorErrorInfo, - isTopLevelDeclaration: () => isTopLevelDeclaration, - moduleSpecifierFromImport: () => moduleSpecifierFromImport, - nameOfTopLevelDeclaration: () => nameOfTopLevelDeclaration, refactorKindBeginsWith: () => refactorKindBeginsWith, - registerRefactor: () => registerRefactor, - updateImportsInOtherFiles: () => updateImportsInOtherFiles + registerRefactor: () => registerRefactor }); // src/services/refactorProvider.ts @@ -143191,9 +144091,9 @@ function doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, toConve const namespaceImportName = namespaceNameConflicts ? getUniqueName(preferredName, sourceFile) : preferredName; const neededNamedImports = /* @__PURE__ */ new Set(); for (const element of toConvert.elements) { - const propertyName = (element.propertyName || element.name).text; + const propertyName = element.propertyName || element.name; ts_FindAllReferences_exports.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, (id) => { - const access = factory.createPropertyAccessExpression(factory.createIdentifier(namespaceImportName), propertyName); + const access = propertyName.kind === 11 /* StringLiteral */ ? factory.createElementAccessExpression(factory.createIdentifier(namespaceImportName), factory.cloneNode(propertyName)) : factory.createPropertyAccessExpression(factory.createIdentifier(namespaceImportName), factory.cloneNode(propertyName)); if (isShorthandPropertyAssignment(id.parent)) { changes.replaceNode(sourceFile, id.parent, factory.createPropertyAssignment(id.text, access)); } else if (isExportSpecifier(id.parent)) { @@ -143209,7 +144109,7 @@ function doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, toConve shouldUseDefault ? factory.createIdentifier(namespaceImportName) : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName)) ); if (neededNamedImports.size && isImportDeclaration(importDecl)) { - const newNamedImports = arrayFrom(neededNamedImports.values(), (element) => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); + const newNamedImports = arrayFrom(neededNamedImports.values(), (element) => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.cloneNode(element.propertyName), factory.cloneNode(element.name))); changes.insertNodeAfter(sourceFile, toConvert.parent.parent, createImport( importDecl, /*defaultImportName*/ @@ -143760,7 +144660,7 @@ function updateImportsInOtherFiles(changes, program, host, oldFile, movedSymbols deleteUnusedImports(sourceFile, importNode, changes, shouldMove); const pathToTargetFileWithExtension = resolvePath(getDirectoryPath(getNormalizedAbsolutePath(oldFile.fileName, program.getCurrentDirectory())), targetFileName); if (getStringComparer(!program.useCaseSensitiveFileNames())(pathToTargetFileWithExtension, sourceFile.fileName) === 0 /* EqualTo */) return; - const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host)); + const newModuleSpecifier = ts_moduleSpecifiers_exports.getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host)); const newImportDeclaration = filterImport(importNode, makeStringLiteral(newModuleSpecifier, quotePreference), shouldMove); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); const ns = getNamespaceLikeImport(importNode); @@ -144171,7 +145071,7 @@ function isPureImport(node) { return false; } } -function getUsageInfo(oldFile, toMove, checker, existingTargetLocals = /* @__PURE__ */ new Set()) { +function getUsageInfo(oldFile, toMove, checker, existingTargetLocals = /* @__PURE__ */ new Set(), enclosingRange) { var _a; const movedSymbols = /* @__PURE__ */ new Set(); const oldImportsNeededByTargetFile = /* @__PURE__ */ new Map(); @@ -144187,7 +145087,7 @@ function getUsageInfo(oldFile, toMove, checker, existingTargetLocals = /* @__PUR } const unusedImportsFromOldFile = /* @__PURE__ */ new Set(); for (const statement of toMove) { - forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => { + forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => { if (!symbol.declarations || isGlobalType(checker, symbol)) { return; } @@ -144217,7 +145117,7 @@ function getUsageInfo(oldFile, toMove, checker, existingTargetLocals = /* @__PUR if (jsxNamespaceSymbol && !!(statement.transformFlags & 2 /* ContainsJsx */)) { unusedImportsFromOldFile.delete(jsxNamespaceSymbol); } - forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => { + forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => { if (movedSymbols.has(symbol)) oldFileImportsFromTargetFile.set(symbol, isValidTypeOnlyUseSite); unusedImportsFromOldFile.delete(symbol); }); @@ -144259,9 +145159,12 @@ function makeUniqueFilename(proposedFilename, extension, inDirectory, host) { function inferNewFileName(importsFromNewFile, movedSymbols) { return forEachKey(importsFromNewFile, symbolNameNoDefault) || forEachKey(movedSymbols, symbolNameNoDefault) || "newFile"; } -function forEachReference(node, checker, onReference) { +function forEachReference(node, checker, enclosingRange, onReference) { node.forEachChild(function cb(node2) { if (isIdentifier(node2) && !isDeclarationName(node2)) { + if (enclosingRange && !rangeContainsRange(enclosingRange, node2)) { + return; + } const sym = checker.getSymbolAtLocation(node2); if (sym) onReference(sym, isValidTypeOnlyAliasUseSite(node2)); } else { @@ -144424,12 +145327,18 @@ function getExistingLocals(sourceFile, statements, checker) { } } for (const statement of statements) { - forEachReference(statement, checker, (s) => { - const symbol = skipAlias(s, checker); - if (symbol.valueDeclaration && getSourceFileOfNode(symbol.valueDeclaration).path === sourceFile.path) { - existingLocals.add(symbol); + forEachReference( + statement, + checker, + /*enclosingRange*/ + void 0, + (s) => { + const symbol = skipAlias(s, checker); + if (symbol.valueDeclaration && getSourceFileOfNode(symbol.valueDeclaration).path === sourceFile.path) { + existingLocals.add(symbol); + } } - }); + ); } return existingLocals; } @@ -144521,7 +145430,12 @@ registerRefactor(refactorName4, { const { references, declaration, replacement } = info; const edits = ts_textChanges_exports.ChangeTracker.with(context, (tracker) => { for (const node of references) { - tracker.replaceNode(file, node, getReplacementExpression(node, replacement)); + const closestStringIdentifierParent = isStringLiteral(replacement) && isIdentifier(node) && walkUpParenthesizedExpressions(node.parent); + if (closestStringIdentifierParent && isTemplateSpan(closestStringIdentifierParent) && !isTaggedTemplateExpression(closestStringIdentifierParent.parent.parent)) { + replaceTemplateStringVariableWithLiteral(tracker, file, closestStringIdentifierParent, replacement); + } else { + tracker.replaceNode(file, node, getReplacementExpression(node, replacement)); + } } tracker.delete(file, declaration); }); @@ -144610,6 +145524,19 @@ function getReplacementExpression(reference, replacement) { } return replacement; } +function replaceTemplateStringVariableWithLiteral(tracker, sourceFile, reference, replacement) { + const templateExpression = reference.parent; + const index = templateExpression.templateSpans.indexOf(reference); + const prevNode = index === 0 ? templateExpression.head : templateExpression.templateSpans[index - 1]; + tracker.replaceRangeWithText( + sourceFile, + { + pos: prevNode.getEnd() - 2, + end: reference.literal.getStart() + 1 + }, + replacement.text.replace(/\\/g, "\\\\").replace(/`/g, "\\`") + ); +} // src/services/refactors/moveToNewFile.ts var refactorName5 = "Move to a new file"; @@ -146818,7 +147745,7 @@ function extractFunctionInScope(node, scope, { usages: usagesInScope, typeParame if (!isJS) { let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); type = checker.getBaseTypeOfLiteralType(type); - typeNode = ts_codefix_exports.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, 1 /* NoTruncation */); + typeNode = ts_codefix_exports.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); } const paramDecl = factory.createParameterDeclaration( /*modifiers*/ @@ -146838,8 +147765,8 @@ function extractFunctionInScope(node, scope, { usages: usagesInScope, typeParame callArguments.push(factory.createIdentifier(name)); }); const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values(), (type) => ({ type, declaration: getFirstDeclarationBeforePosition(type, context.startPosition) })); - const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); - const typeParameters = sortedTypeParametersAndDeclarations.length === 0 ? void 0 : mapDefined(sortedTypeParametersAndDeclarations, ({ declaration }) => declaration); + typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); + const typeParameters = typeParametersAndDeclarations.length === 0 ? void 0 : mapDefined(typeParametersAndDeclarations, ({ declaration }) => declaration); const callTypeArguments = typeParameters !== void 0 ? typeParameters.map((decl) => factory.createTypeReferenceNode( decl.name, /*typeArguments*/ @@ -146847,7 +147774,7 @@ function extractFunctionInScope(node, scope, { usages: usagesInScope, typeParame )) : void 0; if (isExpression(node) && !isJS) { const contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */); + returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); } const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & 1 /* HasReturn */)); suppressLeadingAndTrailingTrivia(body); @@ -146887,7 +147814,8 @@ function extractFunctionInScope(node, scope, { usages: usagesInScope, typeParame checker.typeToTypeNode( checker.getTypeAtLocation(range.thisNode), scope, - 1 /* NoTruncation */ + 1 /* NoTruncation */, + 8 /* AllowUnresolvedNames */ ), /*initializer*/ void 0 @@ -146984,7 +147912,8 @@ function extractFunctionInScope(node, scope, { usages: usagesInScope, typeParame const variableType = checker.typeToTypeNode( checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, - 1 /* NoTruncation */ + 1 /* NoTruncation */, + 8 /* AllowUnresolvedNames */ ); typeElements.push(factory.createPropertySignature( /*modifiers*/ @@ -147115,7 +148044,7 @@ function extractConstantInScope(node, scope, { substitutions }, rangeFacts, cont const file = scope.getSourceFile(); const localNameText = getIdentifierForNode(node, scope, checker, file); const isJS = isInJSFile(scope); - let variableType = isJS || !checker.isContextSensitive(node) ? void 0 : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */); + let variableType = isJS || !checker.isContextSensitive(node) ? void 0 : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); let initializer = transformConstantInitializer(skipParentheses(node), substitutions); ({ variableType, initializer } = transformFunctionInitializerAndType(variableType, initializer)); suppressLeadingAndTrailingTrivia(initializer); @@ -147240,13 +148169,13 @@ function extractConstantInScope(node, scope, { substitutions }, rangeFacts, cont } else { const paramType = checker.getTypeAtLocation(p); if (paramType === checker.getAnyType()) hasAny = true; - parameters.push(factory.updateParameterDeclaration(p, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, 1 /* NoTruncation */), p.initializer)); + parameters.push(factory.updateParameterDeclaration(p, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */), p.initializer)); } } if (hasAny) return { variableType: variableType2, initializer: initializer2 }; variableType2 = void 0; if (isArrowFunction(initializer2)) { - initializer2 = factory.updateArrowFunction(initializer2, canHaveModifiers(node) ? getModifiers(node) : void 0, initializer2.typeParameters, parameters, initializer2.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NoTruncation */), initializer2.equalsGreaterThanToken, initializer2.body); + initializer2 = factory.updateArrowFunction(initializer2, canHaveModifiers(node) ? getModifiers(node) : void 0, initializer2.typeParameters, parameters, initializer2.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */), initializer2.equalsGreaterThanToken, initializer2.body); } else { if (functionSignature && !!functionSignature.thisParameter) { const firstParameter = firstOrUndefined(parameters); @@ -147263,7 +148192,7 @@ function extractConstantInScope(node, scope, { substitutions }, rangeFacts, cont "this", /*questionToken*/ void 0, - checker.typeToTypeNode(thisType, scope, 1 /* NoTruncation */) + checker.typeToTypeNode(thisType, scope, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */) ) ); } @@ -147872,11 +148801,31 @@ function getInfo4(context) { return { error: getLocaleSpecificMessage(Diagnostics.Return_type_must_be_inferred_from_a_function) }; } const typeChecker = context.program.getTypeChecker(); - const returnType = tryGetReturnType(typeChecker, declaration); + let returnType; + if (typeChecker.isImplementationOfOverload(declaration)) { + const signatures = typeChecker.getTypeAtLocation(declaration).getCallSignatures(); + if (signatures.length > 1) { + returnType = typeChecker.getUnionType(mapDefined(signatures, (s) => s.getReturnType())); + } + } + if (!returnType) { + const signature = typeChecker.getSignatureFromDeclaration(declaration); + if (signature) { + const typePredicate = typeChecker.getTypePredicateOfSignature(signature); + if (typePredicate && typePredicate.type) { + const typePredicateTypeNode = typeChecker.typePredicateToTypePredicateNode(typePredicate, declaration, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); + if (typePredicateTypeNode) { + return { declaration, returnTypeNode: typePredicateTypeNode }; + } + } else { + returnType = typeChecker.getReturnTypeOfSignature(signature); + } + } + } if (!returnType) { return { error: getLocaleSpecificMessage(Diagnostics.Could_not_determine_function_return_type) }; } - const returnTypeNode = typeChecker.typeToTypeNode(returnType, declaration, 1 /* NoTruncation */); + const returnTypeNode = typeChecker.typeToTypeNode(returnType, declaration, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); if (returnTypeNode) { return { declaration, returnTypeNode }; } @@ -147892,18 +148841,6 @@ function isConvertibleDeclaration(node) { return false; } } -function tryGetReturnType(typeChecker, node) { - if (typeChecker.isImplementationOfOverload(node)) { - const signatures = typeChecker.getTypeAtLocation(node).getCallSignatures(); - if (signatures.length > 1) { - return typeChecker.getUnionType(mapDefined(signatures, (s) => s.getReturnType())); - } - } - const signature = typeChecker.getSignatureFromDeclaration(node); - if (signature) { - return typeChecker.getReturnTypeOfSignature(signature); - } -} // src/services/classifier2020.ts var TokenEncodingConsts = /* @__PURE__ */ ((TokenEncodingConsts2) => { @@ -148201,9 +149138,9 @@ var NodeObject = class { getChildAt(index, sourceFile) { return this.getChildren(sourceFile)[index]; } - getChildren(sourceFile) { + getChildren(sourceFile = getSourceFileOfNode(this)) { this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine"); - return getNodeChildren(this) ?? setNodeChildren(this, createChildren(this, sourceFile)); + return getNodeChildren(this, sourceFile) ?? setNodeChildren(this, sourceFile, createChildren(this, sourceFile)); } getFirstToken(sourceFile) { this.assertHasRealPosition(); @@ -148284,7 +149221,7 @@ function createSyntaxList(nodes, parent2) { pos = node.end; } addSyntheticNodes(children, pos, nodes.end, parent2); - setNodeChildren(list, children); + list._children = children; return list; } var TokenOrIdentifierObject = class { @@ -149223,13 +150160,18 @@ function createLanguageService(host, documentRegistry = createDocumentRegistry(h if (host.getParsedCommandLine) { (_a3 = host.onReleaseParsedCommandLine) == null ? void 0 : _a3.call(host, configFileName, oldResolvedRef, oldOptions); } else if (oldResolvedRef) { - onReleaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions); + releaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions); } } - function onReleaseOldSourceFile(oldSourceFile, oldOptions) { + function releaseOldSourceFile(oldSourceFile, oldOptions) { const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat); } + function onReleaseOldSourceFile(oldSourceFile, oldOptions, hasSourceFileByPath, newSourceFileByResolvedPath) { + var _a3; + releaseOldSourceFile(oldSourceFile, oldOptions); + (_a3 = host.onReleaseOldSourceFile) == null ? void 0 : _a3.call(host, oldSourceFile, oldOptions, hasSourceFileByPath, newSourceFileByResolvedPath); + } function getOrCreateSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) { return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile); } @@ -149340,6 +150282,108 @@ function createLanguageService(host, documentRegistry = createDocumentRegistry(h const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return [...semanticDiagnostics, ...declarationDiagnostics]; } + function getRegionSemanticDiagnostics(fileName, ranges) { + synchronizeHostData(); + const sourceFile = getValidSourceFile(fileName); + const options = program.getCompilerOptions(); + if (skipTypeChecking(sourceFile, options, program) || !canIncludeBindAndCheckDiagnostics(sourceFile, options) || program.getCachedSemanticDiagnostics(sourceFile)) { + return void 0; + } + const nodes = getNodesForRanges(sourceFile, ranges); + if (!nodes) { + return void 0; + } + const checkedSpans = normalizeSpans(nodes.map((node) => createTextSpanFromBounds(node.getFullStart(), node.getEnd()))); + const semanticDiagnostics = program.getSemanticDiagnostics(sourceFile, cancellationToken, nodes); + return { + diagnostics: semanticDiagnostics.slice(), + spans: checkedSpans + }; + } + function getNodesForRanges(file, ranges) { + const nodes = []; + const spans = normalizeSpans(ranges.map((range) => createTextSpanFromRange(range))); + for (const span of spans) { + const nodesForSpan = getNodesForSpan(file, span); + if (!nodesForSpan) { + return void 0; + } + nodes.push(...nodesForSpan); + } + if (!nodes.length) { + return void 0; + } + return nodes; + } + function getNodesForSpan(file, span) { + if (textSpanContainsTextRange(span, file)) { + return void 0; + } + const endToken = findTokenOnLeftOfPosition(file, textSpanEnd(span)) || file; + const enclosingNode = findAncestor(endToken, (node) => textRangeContainsTextSpan(node, span)); + const nodes = []; + chooseOverlappingNodes(span, enclosingNode, nodes); + if (file.end === span.start + span.length) { + nodes.push(file.endOfFileToken); + } + if (some(nodes, isSourceFile)) { + return void 0; + } + return nodes; + } + function chooseOverlappingNodes(span, node, result) { + if (!nodeOverlapsWithSpan(node, span)) { + return false; + } + if (textSpanContainsTextRange(span, node)) { + addSourceElement(node, result); + return true; + } + if (isBlockLike(node)) { + return chooseOverlappingBlockLike(span, node, result); + } + if (isClassLike(node)) { + return chooseOverlappingClassLike(span, node, result); + } + addSourceElement(node, result); + return true; + } + function nodeOverlapsWithSpan(node, span) { + const spanEnd = span.start + span.length; + return node.pos < spanEnd && node.end > span.start; + } + function addSourceElement(node, result) { + while (node.parent && !isSourceElement(node)) { + node = node.parent; + } + result.push(node); + } + function chooseOverlappingBlockLike(span, node, result) { + const childResult = []; + const stmts = node.statements.filter((stmt) => chooseOverlappingNodes(span, stmt, childResult)); + if (stmts.length === node.statements.length) { + addSourceElement(node, result); + return true; + } + result.push(...childResult); + return false; + } + function chooseOverlappingClassLike(span, node, result) { + var _a2, _b, _c; + const overlaps = (n) => textRangeIntersectsWithTextSpan(n, span); + if (((_a2 = node.modifiers) == null ? void 0 : _a2.some(overlaps)) || node.name && overlaps(node.name) || ((_b = node.typeParameters) == null ? void 0 : _b.some(overlaps)) || ((_c = node.heritageClauses) == null ? void 0 : _c.some(overlaps))) { + addSourceElement(node, result); + return true; + } + const childResult = []; + const members = node.members.filter((member) => chooseOverlappingNodes(span, member, childResult)); + if (members.length === node.members.length) { + addSourceElement(node, result); + return true; + } + result.push(...childResult); + return false; + } function getSuggestionDiagnostics(fileName) { synchronizeHostData(); return computeSuggestionDiagnostics(getValidSourceFile(fileName), program, cancellationToken); @@ -149694,6 +150738,7 @@ function createLanguageService(host, documentRegistry = createDocumentRegistry(h synchronizeHostData(); Debug.assert(args.type === "file"); const sourceFile = getValidSourceFile(args.fileName); + if (containsParseError(sourceFile)) return emptyArray; const formatContext = ts_formatting_exports.getFormatContext(formatOptions, host); const mode = args.mode ?? (args.skipDestructiveCodeActions ? "SortAndCombine" /* SortAndCombine */ : "All" /* All */); return ts_OrganizeImports_exports.organizeImports(sourceFile, formatContext, host, program, preferences, mode); @@ -150036,7 +151081,7 @@ function createLanguageService(host, documentRegistry = createDocumentRegistry(h return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); } function getTodoCommentsRegExp() { - const singleLineCommentStart = /(?:\/\/+\s*)/.source; + const singleLineCommentStart = /(?:\/{2,}\s*)/.source; const multiLineCommentStart = /(?:\/\*+\s*)/.source; const anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source; const preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; @@ -150154,6 +151199,7 @@ function createLanguageService(host, documentRegistry = createDocumentRegistry(h cleanupSemanticCache, getSyntacticDiagnostics, getSemanticDiagnostics, + getRegionSemanticDiagnostics, getSuggestionDiagnostics, getCompilerOptionsDiagnostics, getSyntacticClassifications: getSyntacticClassifications2, @@ -151316,19 +152362,16 @@ __export(ts_codefix_exports, { createFileTextChanges: () => createFileTextChanges, createImportAdder: () => createImportAdder, createImportSpecifierResolver: () => createImportSpecifierResolver, - createJsonPropertyAssignment: () => createJsonPropertyAssignment, createMissingMemberNodes: () => createMissingMemberNodes, createSignatureDeclarationFromCallExpression: () => createSignatureDeclarationFromCallExpression, createSignatureDeclarationFromSignature: () => createSignatureDeclarationFromSignature, createStubbedBody: () => createStubbedBody, eachDiagnostic: () => eachDiagnostic, findAncestorMatchingSpan: () => findAncestorMatchingSpan, - findJsonProperty: () => findJsonProperty, generateAccessorFromProperty: () => generateAccessorFromProperty, getAccessorConvertiblePropertyAtPosition: () => getAccessorConvertiblePropertyAtPosition, getAllFixes: () => getAllFixes, getAllSupers: () => getAllSupers, - getArgumentTypesAndTypeParameters: () => getArgumentTypesAndTypeParameters, getFixes: () => getFixes, getImportCompletionAction: () => getImportCompletionAction, getImportKind: () => getImportKind, @@ -151343,6 +152386,7 @@ __export(ts_codefix_exports, { setJsonCompilerOptionValue: () => setJsonCompilerOptionValue, setJsonCompilerOptionValues: () => setJsonCompilerOptionValues, tryGetAutoImportableReferenceFromTypeNode: () => tryGetAutoImportableReferenceFromTypeNode, + typePredicateToAutoImportableTypeNode: () => typePredicateToAutoImportableTypeNode, typeToAutoImportableTypeNode: () => typeToAutoImportableTypeNode }); @@ -151729,7 +152773,7 @@ function isInsideAwaitableBody(node) { function makeChange3(changeTracker, errorCode, sourceFile, checker, insertionSite, fixedDeclarations) { if (isForOfStatement(insertionSite.parent) && !insertionSite.parent.awaitModifier) { const exprType = checker.getTypeAtLocation(insertionSite); - const asyncIter = checker.getAsyncIterableType(); + const asyncIter = checker.getAnyAsyncIterableType(); if (asyncIter && checker.isTypeAssignableTo(exprType, asyncIter)) { const forOf = insertionSite.parent; changeTracker.replaceNode(sourceFile, forOf, factory.updateForOfStatement(forOf, factory.createToken(135 /* AwaitKeyword */), forOf.initializer, forOf.expression, forOf.statement)); @@ -154086,7 +155130,7 @@ function getLeftAndRightSiblings(typedefNode) { function findEndOfTextBetween(jsDocComment, from, to) { const comment = jsDocComment.getText().substring(from - jsDocComment.getStart(), to - jsDocComment.getStart()); for (let i = comment.length; i > 0; i--) { - if (!/[*/\s]/g.test(comment.substring(i - 1, i))) { + if (!/[*/\s]/.test(comment.substring(i - 1, i))) { return from + i; } } @@ -154293,6 +155337,8 @@ function addMissingDeclarations(context, implementedTypeNode, sourceFile, classD classDeclaration, /*flags*/ void 0, + /*internalFlags*/ + void 0, getNoopSymbolTrackerWithResolver(context) )); } @@ -154412,7 +155458,7 @@ function createImportAdderWorker(sourceFile, program, useAutoImportProvider, pre addImport(first(info)); } function addImportFromExportedSymbol(exportedSymbol, isValidTypeOnlyUseSite, referenceImport) { - var _a; + var _a, _b; const moduleSymbol = Debug.checkDefined(exportedSymbol.parent); const symbolName2 = getNameForExportedSymbol(exportedSymbol, getEmitScriptTarget(compilerOptions)); const checker = program.getTypeChecker(); @@ -154429,10 +155475,14 @@ function createImportAdderWorker(sourceFile, program, useAutoImportProvider, pre preferences, cancellationToken ); + if (!exportInfo) { + Debug.assert((_a = preferences.autoImportFileExcludePatterns) == null ? void 0 : _a.length); + return; + } const useRequire = shouldUseRequire(sourceFile, program); let fix = getImportFixForSymbol( sourceFile, - Debug.checkDefined(exportInfo), + exportInfo, program, /*position*/ void 0, @@ -154442,7 +155492,7 @@ function createImportAdderWorker(sourceFile, program, useAutoImportProvider, pre preferences ); if (fix) { - const localName = ((_a = tryCast(referenceImport == null ? void 0 : referenceImport.name, isIdentifier)) == null ? void 0 : _a.text) ?? symbolName2; + const localName = ((_b = tryCast(referenceImport == null ? void 0 : referenceImport.name, isIdentifier)) == null ? void 0 : _b.text) ?? symbolName2; if (referenceImport && isTypeOnlyImportDeclaration(referenceImport) && (fix.kind === 3 /* AddNew */ || fix.kind === 2 /* AddToExisting */) && fix.addAsTypeOnly === 1 /* Allowed */) { fix = { ...fix, addAsTypeOnly: 2 /* Required */ }; } @@ -154479,9 +155529,10 @@ function createImportAdderWorker(sourceFile, program, useAutoImportProvider, pre sourceFile, exportingFileName, compilerOptions, - createModuleSpecifierResolutionHost(program, host) + createModuleSpecifierResolutionHost(program, host), + preferences ); - const importKind = getImportKind(futureExportingSourceFile, exportKind, compilerOptions); + const importKind = getImportKind(futureExportingSourceFile, exportKind, program); const addAsTypeOnly = getAddAsTypeOnly( isImportUsageValidAsTypeOnly, /*isForNewImportDeclaration*/ @@ -154821,7 +155872,7 @@ function createImportAdderWorker(sourceFile, program, useAutoImportProvider, pre } function createImportSpecifierResolver(importingFile, program, host, preferences) { const packageJsonImportFilter = createPackageJsonImportFilter(importingFile, preferences, host); - const importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + const importMap = createExistingImportMap(importingFile, program); return { getModuleSpecifierForBestExportInfo }; function getModuleSpecifierForBestExportInfo(exportInfo, position, isValidTypeOnlyUseSite, fromCacheOnly) { const { fixes, computedWithoutCacheCount } = getImportFixes( @@ -154891,8 +155942,12 @@ function codeFixActionToCodeAction({ description: description3, changes, command } function getAllExportInfoForSymbol(importingFile, symbol, symbolName2, moduleSymbol, preferCapitalized, program, host, preferences, cancellationToken) { const getChecker = createGetChecker(program, host); + const isFileExcluded = preferences.autoImportFileExcludePatterns && getIsFileExcluded(host, preferences); + const mergedModuleSymbol = program.getTypeChecker().getMergedSymbol(moduleSymbol); + const moduleSourceFile = isFileExcluded && mergedModuleSymbol.declarations && getDeclarationOfKind(mergedModuleSymbol, 307 /* SourceFile */); + const moduleSymbolExcluded = moduleSourceFile && isFileExcluded(moduleSourceFile); return getExportInfoMap(importingFile, host, program, preferences, cancellationToken).search(importingFile.path, preferCapitalized, (name) => name === symbolName2, (info) => { - if (skipAlias(info[0].symbol, getChecker(info[0].isFromPackageJson)) === symbol && info.some((i) => i.moduleSymbol === moduleSymbol || i.symbol.parent === moduleSymbol)) { + if (getChecker(info[0].isFromPackageJson).getMergedSymbol(skipAlias(info[0].symbol, getChecker(info[0].isFromPackageJson))) === symbol && (moduleSymbolExcluded || info.some((i) => i.moduleSymbol === moduleSymbol || i.symbol.parent === moduleSymbol))) { return info; } }); @@ -154924,7 +155979,7 @@ function getSingleExportInfoForSymbol(symbol, symbolName2, moduleSymbol, program } } } -function getImportFixes(exportInfos, usagePosition, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap = isFullSourceFile(sourceFile) ? createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()) : void 0, fromCacheOnly) { +function getImportFixes(exportInfos, usagePosition, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap = isFullSourceFile(sourceFile) ? createExistingImportMap(sourceFile, program) : void 0, fromCacheOnly) { const checker = program.getTypeChecker(); const existingImports = importMap ? flatMap(exportInfos, importMap.getImportsForExportInfo) : emptyArray; const useNamespace = usagePosition !== void 0 && tryUseExistingNamespaceImport(existingImports, usagePosition); @@ -155039,7 +156094,8 @@ function tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker }; } } -function createExistingImportMap(checker, importingFile, compilerOptions) { +function createExistingImportMap(importingFile, program) { + const checker = program.getTypeChecker(); let importMap; for (const moduleSpecifier of importingFile.imports) { const i = importFromModuleSpecifier(moduleSpecifier); @@ -155060,7 +156116,7 @@ function createExistingImportMap(checker, importingFile, compilerOptions) { const matchingDeclarations = importMap == null ? void 0 : importMap.get(getSymbolId(moduleSymbol)); if (!matchingDeclarations) return emptyArray; if (isSourceFileJS(importingFile) && !(targetFlags & 111551 /* Value */) && !every(matchingDeclarations, isJSDocImportTag)) return emptyArray; - const importKind = getImportKind(importingFile, exportKind, compilerOptions); + const importKind = getImportKind(importingFile, exportKind, program); return matchingDeclarations.map((declaration) => ({ declaration, importKind, symbol, targetFlags })); } }; @@ -155075,8 +156131,8 @@ function shouldUseRequire(sourceFile, program) { if (compilerOptions.configFile) { return getEmitModuleKind(compilerOptions) < 5 /* ES2015 */; } - if (sourceFile.impliedNodeFormat === 1 /* CommonJS */) return true; - if (sourceFile.impliedNodeFormat === 99 /* ESNext */) return false; + if (getImpliedNodeFormatForEmit(sourceFile, program) === 1 /* CommonJS */) return true; + if (getImpliedNodeFormatForEmit(sourceFile, program) === 99 /* ESNext */) return false; for (const otherFile of program.getSourceFiles()) { if (otherFile === sourceFile || !isSourceFileJS(otherFile) || program.isSourceFileFromExternalLibrary(otherFile)) continue; if (otherFile.commonJsModuleIndicator && !otherFile.externalModuleIndicator) return true; @@ -155128,20 +156184,13 @@ function getNewImportFixes(program, sourceFile, usagePosition, isValidTypeOnlyUs if (!importedSymbolHasValueMeaning && isJs && usagePosition !== void 0) { return { kind: 1 /* JsdocTypeImport */, moduleSpecifierKind, moduleSpecifier, usagePosition, exportInfo: exportInfo2, isReExport: i > 0 }; } - const importKind = getImportKind(sourceFile, exportInfo2.exportKind, compilerOptions); + const importKind = getImportKind(sourceFile, exportInfo2.exportKind, program); let qualification; if (usagePosition !== void 0 && importKind === 3 /* CommonJS */ && exportInfo2.exportKind === 0 /* Named */) { const exportEquals = checker.resolveExternalModuleSymbol(exportInfo2.moduleSymbol); let namespacePrefix; if (exportEquals !== exportInfo2.moduleSymbol) { - namespacePrefix = forEachNameOfDefaultExport( - exportEquals, - checker, - compilerOptions, - /*preferCapitalizedNames*/ - false, - identity - ); + namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, getEmitScriptTarget(compilerOptions), identity); } namespacePrefix || (namespacePrefix = moduleSymbolToValidIdentifier( exportInfo2.moduleSymbol, @@ -155205,7 +156254,7 @@ function getFixInfos(context, errorCode, pos, useAutoImportProvider) { } function sortFixInfo(fixes, sourceFile, program, packageJsonImportFilter, host, preferences) { const _toPath = (fileName) => toPath(fileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)); - return sort(fixes, (a, b) => compareBooleans(!!a.isJsxNamespaceFix, !!b.isJsxNamespaceFix) || compareValues(a.fix.kind, b.fix.kind) || compareModuleSpecifiers(a.fix, b.fix, sourceFile, program, preferences, packageJsonImportFilter.allowsImportingSpecifier, _toPath)); + return toSorted(fixes, (a, b) => compareBooleans(!!a.isJsxNamespaceFix, !!b.isJsxNamespaceFix) || compareValues(a.fix.kind, b.fix.kind) || compareModuleSpecifiers(a.fix, b.fix, sourceFile, program, preferences, packageJsonImportFilter.allowsImportingSpecifier, _toPath)); } function getFixInfosWithoutDiagnostic(context, symbolToken, useAutoImportProvider) { const info = getFixesInfoForNonUMDImport(context, symbolToken, useAutoImportProvider); @@ -155314,8 +156363,8 @@ function getUmdSymbol(token, checker) { } return void 0; } -function getImportKind(importingFile, exportKind, compilerOptions, forceImportKeyword) { - if (compilerOptions.verbatimModuleSyntax && (getEmitModuleKind(compilerOptions) === 1 /* CommonJS */ || importingFile.impliedNodeFormat === 1 /* CommonJS */)) { +function getImportKind(importingFile, exportKind, program, forceImportKeyword) { + if (program.getCompilerOptions().verbatimModuleSyntax && getEmitModuleFormatOfFile(importingFile, program) === 1 /* CommonJS */) { return 3 /* CommonJS */; } switch (exportKind) { @@ -155324,18 +156373,18 @@ function getImportKind(importingFile, exportKind, compilerOptions, forceImportKe case 1 /* Default */: return 1 /* Default */; case 2 /* ExportEquals */: - return getExportEqualsImportKind(importingFile, compilerOptions, !!forceImportKeyword); + return getExportEqualsImportKind(importingFile, program.getCompilerOptions(), !!forceImportKeyword); case 3 /* UMD */: - return getUmdImportKind(importingFile, compilerOptions, !!forceImportKeyword); + return getUmdImportKind(importingFile, program, !!forceImportKeyword); default: return Debug.assertNever(exportKind); } } -function getUmdImportKind(importingFile, compilerOptions, forceImportKeyword) { - if (getAllowSyntheticDefaultImports(compilerOptions)) { +function getUmdImportKind(importingFile, program, forceImportKeyword) { + if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) { return 1 /* Default */; } - const moduleKind = getEmitModuleKind(compilerOptions); + const moduleKind = getEmitModuleKind(program.getCompilerOptions()); switch (moduleKind) { case 2 /* AMD */: case 1 /* CommonJS */: @@ -155354,7 +156403,7 @@ function getUmdImportKind(importingFile, compilerOptions, forceImportKeyword) { return 2 /* Namespace */; case 100 /* Node16 */: case 199 /* NodeNext */: - return importingFile.impliedNodeFormat === 99 /* ESNext */ ? 2 /* Namespace */ : 3 /* CommonJS */; + return getImpliedNodeFormatForEmit(importingFile, program) === 99 /* ESNext */ ? 2 /* Namespace */ : 3 /* CommonJS */; default: return Debug.assertNever(moduleKind, `Unexpected moduleKind ${moduleKind}`); } @@ -155427,7 +156476,7 @@ function getExportInfos(symbolName2, isJsxTagName, currentTokenMeaning, cancella }); function addSymbol(moduleSymbol, toFile, exportedSymbol, exportKind, program2, isFromPackageJson) { const moduleSpecifierResolutionHost = getModuleSpecifierResolutionHost(isFromPackageJson); - if (toFile && isImportableFile(program2, fromFile, toFile, preferences, packageJsonFilter, moduleSpecifierResolutionHost, moduleSpecifierCache) || !toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost)) { + if (toFile && isImportableFile(program2, fromFile, toFile, preferences, packageJsonFilter, moduleSpecifierResolutionHost, moduleSpecifierCache) || (!toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost) || fileContainsPackageImport(fromFile, stripQuotes(moduleSymbol.name)))) { const checker = program2.getTypeChecker(); originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { symbol: exportedSymbol, moduleSymbol, moduleFileName: toFile == null ? void 0 : toFile.fileName, exportKind, targetFlags: skipAlias(exportedSymbol, checker).flags, isFromPackageJson }); } @@ -155437,7 +156486,7 @@ function getExportInfos(symbolName2, isJsxTagName, currentTokenMeaning, cancella cancellationToken.throwIfCancellationRequested(); const compilerOptions = program2.getCompilerOptions(); const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker); - if (defaultInfo && symbolFlagsHaveMeaning(checker.getSymbolFlags(defaultInfo.symbol), currentTokenMeaning) && forEachNameOfDefaultExport(defaultInfo.symbol, checker, compilerOptions, isJsxTagName, (name) => name === symbolName2)) { + if (defaultInfo && symbolFlagsHaveMeaning(checker.getSymbolFlags(defaultInfo.symbol), currentTokenMeaning) && forEachNameOfDefaultExport(defaultInfo.symbol, checker, getEmitScriptTarget(compilerOptions), (name, capitalizedName) => (isJsxTagName ? capitalizedName ?? name : name) === symbolName2)) { addSymbol(moduleSymbol, sourceFile, defaultInfo.symbol, defaultInfo.exportKind, program2, isFromPackageJson); } const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName2, moduleSymbol); @@ -155651,7 +156700,7 @@ function doAddExistingFix(changes, sourceFile, clause, defaultImport, namedImpor } if (namedImports.length) { const { specifierComparer, isSorted } = ts_OrganizeImports_exports.getNamedImportSpecifierComparerWithDetection(clause.parent, preferences, sourceFile); - const newSpecifiers = stableSort( + const newSpecifiers = toSorted( namedImports.map( (namedImport) => factory.createImportSpecifier( (!clause.isTypeOnly || promoteFromTypeOnly2) && shouldUseTypeOnly(namedImport, preferences), @@ -155668,7 +156717,7 @@ function doAddExistingFix(changes, sourceFile, clause, defaultImport, namedImpor clause.namedBindings, factory.updateNamedImports( clause.namedBindings, - stableSort([...existingSpecifiers.filter((s) => !removeExistingImportSpecifiers.has(s)), ...newSpecifiers], specifierComparer) + toSorted([...existingSpecifiers.filter((s) => !removeExistingImportSpecifiers.has(s)), ...newSpecifiers], specifierComparer) ) ); } else if ((existingSpecifiers == null ? void 0 : existingSpecifiers.length) && isSorted !== false) { @@ -155838,6 +156887,12 @@ function createConstEqualsRequireDeclaration(name, quotedModuleSpecifier) { function symbolFlagsHaveMeaning(flags, meaning) { return meaning === 7 /* All */ ? true : meaning & 1 /* Value */ ? !!(flags & 111551 /* Value */) : meaning & 2 /* Type */ ? !!(flags & 788968 /* Type */) : meaning & 4 /* Namespace */ ? !!(flags & 1920 /* Namespace */) : false; } +function getImpliedNodeFormatForEmit(file, program) { + return isFullSourceFile(file) ? program.getImpliedNodeFormatForEmit(file) : getImpliedNodeFormatForEmitWorker(file, program.getCompilerOptions()); +} +function getEmitModuleFormatOfFile(file, program) { + return isFullSourceFile(file) ? program.getEmitModuleFormatOfFile(file) : getEmitModuleFormatOfFileWorker(file, program.getCompilerOptions()); +} // src/services/codefixes/fixAddMissingConstraint.ts var fixId17 = "addMissingConstraint"; @@ -155916,6 +156971,8 @@ function addMissingConstraint(changes, program, preferences, host, sourceFile, i scriptTarget, /*flags*/ void 0, + /*internalFlags*/ + void 0, tracker ); if (typeNode) { @@ -156923,7 +157980,7 @@ function getInfo10(sourceFile, tokenPos, errorCode, checker, program) { const moduleDeclaration = find(symbol.declarations, isModuleDeclaration); const moduleDeclarationSourceFile = moduleDeclaration == null ? void 0 : moduleDeclaration.getSourceFile(); if (moduleDeclaration && moduleDeclarationSourceFile && !isSourceFileFromLibrary(program, moduleDeclarationSourceFile)) { - return { kind: 2 /* Function */, token, call: parent2.parent, sourceFile, modifierFlags: 32 /* Export */, parentDeclaration: moduleDeclaration }; + return { kind: 2 /* Function */, token, call: parent2.parent, sourceFile: moduleDeclarationSourceFile, modifierFlags: 32 /* Export */, parentDeclaration: moduleDeclaration }; } const moduleSourceFile = find(symbol.declarations, isSourceFile); if (sourceFile.commonJsModuleIndicator) return void 0; @@ -157023,14 +158080,15 @@ function getTypeNode2(checker, node, token) { const binaryExpression = token.parent.parent; const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); - typeNode = checker.typeToTypeNode(widenedType, node, 1 /* NoTruncation */); + typeNode = checker.typeToTypeNode(widenedType, node, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */); } else { const contextualType = checker.getContextualType(token.parent); typeNode = contextualType ? checker.typeToTypeNode( contextualType, /*enclosingDeclaration*/ void 0, - 1 /* NoTruncation */ + 1 /* NoTruncation */, + 8 /* AllowUnresolvedNames */ ) : void 0; } return typeNode || factory.createKeywordTypeNode(133 /* AnyKeyword */); @@ -157352,7 +158410,9 @@ function createPropertyNameFromSymbol(symbol, target, quotePreference, checker) 111551 /* Value */, /*enclosingDeclaration*/ void 0, - 1073741824 /* WriteComputedProps */ + /*flags*/ + void 0, + 1 /* WriteComputedProps */ ); if (prop && isComputedPropertyName(prop)) return prop; } @@ -157525,7 +158585,7 @@ function tryGetName2(node) { } } function typeToTypeNode(checker, type, enclosingDeclaration) { - return checker.typeToTypeNode(checker.getWidenedType(type), enclosingDeclaration, 1 /* NoTruncation */) ?? factory.createKeywordTypeNode(159 /* UnknownKeyword */); + return checker.typeToTypeNode(checker.getWidenedType(type), enclosingDeclaration, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */) ?? factory.createKeywordTypeNode(159 /* UnknownKeyword */); } function doChange19(changes, program, preferences, host, declarations, newParameters) { const scriptTarget = getEmitScriptTarget(program.getCompilerOptions()); @@ -158828,7 +159888,8 @@ var canHaveTypeAnnotation = /* @__PURE__ */ new Set([ 206 /* ObjectBindingPattern */, 207 /* ArrayBindingPattern */ ]); -var declarationEmitNodeBuilderFlags2 = 1024 /* MultilineObjectLiterals */ | 2048 /* WriteClassExpressionAsTypeLiteral */ | 4096 /* UseTypeOfFunction */ | 8 /* UseStructuralFallback */ | 524288 /* AllowEmptyTuple */ | 4 /* GenerateNamesForShadowedTypeParams */ | 1 /* NoTruncation */ | 1073741824 /* WriteComputedProps */; +var declarationEmitNodeBuilderFlags2 = 1024 /* MultilineObjectLiterals */ | 2048 /* WriteClassExpressionAsTypeLiteral */ | 4096 /* UseTypeOfFunction */ | 8 /* UseStructuralFallback */ | 524288 /* AllowEmptyTuple */ | 4 /* GenerateNamesForShadowedTypeParams */ | 1 /* NoTruncation */; +var declarationEmitInternalNodeBuilderFlags2 = 1 /* WriteComputedProps */; registerCodeFix({ errorCodes: errorCodes47, fixIds: [fixId36], @@ -159421,7 +160482,25 @@ function withContext(context, typePrintMode, cb) { if (typePrintMode === 1 /* Relative */) { return relativeType(node); } - let type = isValueSignatureDeclaration(node) ? tryGetReturnType2(node) : typeChecker.getTypeAtLocation(node); + let type; + if (isValueSignatureDeclaration(node)) { + const signature = typeChecker.getSignatureFromDeclaration(node); + if (signature) { + const typePredicate = typeChecker.getTypePredicateOfSignature(signature); + if (typePredicate) { + if (!typePredicate.type) { + return emptyInferenceResult; + } + return { + typeNode: typePredicateToTypeNode(typePredicate, findAncestor(node, isDeclaration) ?? sourceFile, getFlags(typePredicate.type)), + mutatedTarget: false + }; + } + type = typeChecker.getReturnTypeOfSignature(signature); + } + } else { + type = typeChecker.getTypeAtLocation(node); + } if (!type) { return emptyInferenceResult; } @@ -159435,14 +160514,17 @@ function withContext(context, typePrintMode, cb) { } type = widenedType; } - if (isParameter(node) && typeChecker.requiresAddingImplicitUndefined(node)) { + const enclosingDeclaration = findAncestor(node, isDeclaration) ?? sourceFile; + if (isParameter(node) && typeChecker.requiresAddingImplicitUndefined(node, enclosingDeclaration)) { type = typeChecker.getUnionType([typeChecker.getUndefinedType(), type], 0 /* None */); } - const flags = (isVariableDeclaration(node) || isPropertyDeclaration(node) && hasSyntacticModifier(node, 256 /* Static */ | 8 /* Readonly */)) && type.flags & 8192 /* UniqueESSymbol */ ? 1048576 /* AllowUniqueESSymbolType */ : 0 /* None */; return { - typeNode: typeToTypeNode2(type, findAncestor(node, isDeclaration) ?? sourceFile, flags), + typeNode: typeToTypeNode2(type, enclosingDeclaration, getFlags(type)), mutatedTarget: false }; + function getFlags(type2) { + return (isVariableDeclaration(node) || isPropertyDeclaration(node) && hasSyntacticModifier(node, 256 /* Static */ | 8 /* Readonly */)) && type2.flags & 8192 /* UniqueESSymbol */ ? 1048576 /* AllowUniqueESSymbolType */ : 0 /* None */; + } } function createTypeOfFromEntityNameExpression(node) { return factory.createTypeQueryNode(getSynthesizedDeepClone(node)); @@ -159594,7 +160676,7 @@ function withContext(context, typePrintMode, cb) { } function typeToTypeNode2(type, enclosingDeclaration, flags = 0 /* None */) { let isTruncated = false; - const result2 = typeToAutoImportableTypeNode(typeChecker, importAdder, type, enclosingDeclaration, scriptTarget, declarationEmitNodeBuilderFlags2 | flags, { + const result2 = typeToAutoImportableTypeNode(typeChecker, importAdder, type, enclosingDeclaration, scriptTarget, declarationEmitNodeBuilderFlags2 | flags, declarationEmitInternalNodeBuilderFlags2, { moduleResolverHost: program, trackSymbol() { return true; @@ -159605,11 +160687,18 @@ function withContext(context, typePrintMode, cb) { }); return isTruncated ? factory.createKeywordTypeNode(133 /* AnyKeyword */) : result2; } - function tryGetReturnType2(node) { - const signature = typeChecker.getSignatureFromDeclaration(node); - if (signature) { - return typeChecker.getReturnTypeOfSignature(signature); - } + function typePredicateToTypeNode(typePredicate, enclosingDeclaration, flags = 0 /* None */) { + let isTruncated = false; + const result2 = typePredicateToAutoImportableTypeNode(typeChecker, importAdder, typePredicate, enclosingDeclaration, scriptTarget, declarationEmitNodeBuilderFlags2 | flags, declarationEmitInternalNodeBuilderFlags2, { + moduleResolverHost: program, + trackSymbol() { + return true; + }, + reportTruncationError() { + isTruncated = true; + } + }); + return isTruncated ? factory.createKeywordTypeNode(133 /* AnyKeyword */) : result2; } function addTypeToVariableLike(decl) { const { typeNode } = inferType(decl); @@ -160927,7 +162016,7 @@ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, sourceFile, con case 172 /* PropertyDeclaration */: let flags = 1 /* NoTruncation */; flags |= quotePreference === 0 /* Single */ ? 268435456 /* UseSingleQuotesForStringLiteralType */ : 0; - let typeNode = checker.typeToTypeNode(type, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)); + let typeNode = checker.typeToTypeNode(type, enclosingDeclaration, flags, 8 /* AllowUnresolvedNames */, getNoopSymbolTrackerWithResolver(context)); if (importAdder) { const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference) { @@ -160952,6 +162041,8 @@ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, sourceFile, con enclosingDeclaration, /*flags*/ void 0, + /*internalFlags*/ + void 0, getNoopSymbolTrackerWithResolver(context) ); const allAccessors = getAllAccessorDeclarations(declarations, declaration); @@ -161007,6 +162098,9 @@ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, sourceFile, con break; } for (const signature of signatures) { + if (signature.declaration && signature.declaration.flags & 33554432 /* Ambient */) { + continue; + } outputMethod(quotePreference, signature, modifiers, createName(declarationName)); } if (!ambient) { @@ -161081,7 +162175,7 @@ function createSignatureDeclarationFromSignature(kind, context, quotePreference, const scriptTarget = getEmitScriptTarget(program.getCompilerOptions()); const isJs = isInJSFile(enclosingDeclaration); const flags = 1 /* NoTruncation */ | 256 /* SuppressAnyReturnType */ | 524288 /* AllowEmptyTuple */ | (quotePreference === 0 /* Single */ ? 268435456 /* UseSingleQuotesForStringLiteralType */ : 0 /* None */); - const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)); + const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, 8 /* AllowUnresolvedNames */, getNoopSymbolTrackerWithResolver(context)); if (!signatureDeclaration) { return void 0; } @@ -161182,6 +162276,7 @@ function createSignatureDeclarationFromCallExpression(kind, context, importAdder contextNode, scriptTarget, 1 /* NoTruncation */, + 8 /* AllowUnresolvedNames */, tracker ); const modifiers = modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : void 0; @@ -161200,6 +162295,8 @@ function createSignatureDeclarationFromCallExpression(kind, context, importAdder contextNode, /*flags*/ void 0, + /*internalFlags*/ + void 0, tracker ); switch (kind) { @@ -161269,8 +162366,8 @@ function createTypeParametersForArguments(checker, argumentTypeParameters, typeA function createTypeParameterName(index) { return 84 /* T */ + index <= 90 /* Z */ ? String.fromCharCode(84 /* T */ + index) : `T${index}`; } -function typeToAutoImportableTypeNode(checker, importAdder, type, contextNode, scriptTarget, flags, tracker) { - let typeNode = checker.typeToTypeNode(type, contextNode, flags, tracker); +function typeToAutoImportableTypeNode(checker, importAdder, type, contextNode, scriptTarget, flags, internalFlags, tracker) { + let typeNode = checker.typeToTypeNode(type, contextNode, flags, internalFlags, tracker); if (typeNode && isImportTypeNode(typeNode)) { const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference) { @@ -161280,13 +162377,24 @@ function typeToAutoImportableTypeNode(checker, importAdder, type, contextNode, s } return getSynthesizedDeepClone(typeNode); } +function typePredicateToAutoImportableTypeNode(checker, importAdder, typePredicate, contextNode, scriptTarget, flags, internalFlags, tracker) { + let typePredicateNode = checker.typePredicateToTypePredicateNode(typePredicate, contextNode, flags, internalFlags, tracker); + if ((typePredicateNode == null ? void 0 : typePredicateNode.type) && isImportTypeNode(typePredicateNode.type)) { + const importableReference = tryGetAutoImportableReferenceFromTypeNode(typePredicateNode.type, scriptTarget); + if (importableReference) { + importSymbols(importAdder, importableReference.symbols); + typePredicateNode = factory.updateTypePredicateNode(typePredicateNode, typePredicateNode.assertsModifier, typePredicateNode.parameterName, importableReference.typeNode); + } + } + return getSynthesizedDeepClone(typePredicateNode); +} function typeContainsTypeParameter(type) { if (type.isUnionOrIntersection()) { return type.types.some(typeContainsTypeParameter); } return type.flags & 262144 /* TypeParameter */; } -function getArgumentTypesAndTypeParameters(checker, importAdder, instanceTypes, contextNode, scriptTarget, flags, tracker) { +function getArgumentTypesAndTypeParameters(checker, importAdder, instanceTypes, contextNode, scriptTarget, flags, internalFlags, tracker) { const argumentTypeNodes = []; const argumentTypeParameters = /* @__PURE__ */ new Map(); for (let i = 0; i < instanceTypes.length; i += 1) { @@ -161298,13 +162406,13 @@ function getArgumentTypesAndTypeParameters(checker, importAdder, instanceTypes, continue; } const widenedInstanceType = checker.getBaseTypeOfLiteralType(instanceType); - const argumentTypeNode = typeToAutoImportableTypeNode(checker, importAdder, widenedInstanceType, contextNode, scriptTarget, flags, tracker); + const argumentTypeNode = typeToAutoImportableTypeNode(checker, importAdder, widenedInstanceType, contextNode, scriptTarget, flags, internalFlags, tracker); if (!argumentTypeNode) { continue; } argumentTypeNodes.push(argumentTypeNode); const argumentTypeParameter = getFirstTypeParameterName(instanceType); - const instanceTypeConstraint = instanceType.isTypeParameter() && instanceType.constraint && !isAnonymousObjectConstraintType(instanceType.constraint) ? typeToAutoImportableTypeNode(checker, importAdder, instanceType.constraint, contextNode, scriptTarget, flags, tracker) : void 0; + const instanceTypeConstraint = instanceType.isTypeParameter() && instanceType.constraint && !isAnonymousObjectConstraintType(instanceType.constraint) ? typeToAutoImportableTypeNode(checker, importAdder, instanceType.constraint, contextNode, scriptTarget, flags, internalFlags, tracker) : void 0; if (argumentTypeParameter) { argumentTypeParameters.set(argumentTypeParameter, { argumentType: instanceType, constraint: instanceTypeConstraint }); } @@ -161404,7 +162512,7 @@ function createMethodImplementingSignatures(checker, context, enclosingDeclarati function getReturnTypeFromSignatures(signatures, checker, context, enclosingDeclaration) { if (length(signatures)) { const type = checker.getUnionType(map(signatures, checker.getReturnTypeOfSignature)); - return checker.typeToTypeNode(type, enclosingDeclaration, 1 /* NoTruncation */, getNoopSymbolTrackerWithResolver(context)); + return checker.typeToTypeNode(type, enclosingDeclaration, 1 /* NoTruncation */, 8 /* AllowUnresolvedNames */, getNoopSymbolTrackerWithResolver(context)); } } function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType, quotePreference, body) { @@ -161492,6 +162600,14 @@ function tryGetAutoImportableReferenceFromTypeNode(importTypeNode, scriptTarget) function visit(node) { if (isLiteralImportTypeNode(node) && node.qualifier) { const firstIdentifier = getFirstIdentifier(node.qualifier); + if (!firstIdentifier.symbol) { + return visitEachChild( + node, + visit, + /*context*/ + void 0 + ); + } const name = getNameForExportedSymbol(firstIdentifier.symbol, scriptTarget); const qualifier = name !== firstIdentifier.text ? replaceFirstIdentifierOfEntityName(node.qualifier, factory.createIdentifier(name)) : node.qualifier; symbols = append(symbols, firstIdentifier.symbol); @@ -161994,7 +163110,7 @@ var errorCodes54 = [Diagnostics.require_call_may_be_converted_to_an_import.code] registerCodeFix({ errorCodes: errorCodes54, getCodeActions(context) { - const info = getInfo18(context.sourceFile, context.program, context.span.start); + const info = getInfo18(context.sourceFile, context.program, context.span.start, context.preferences); if (!info) { return void 0; } @@ -162003,14 +163119,14 @@ registerCodeFix({ }, fixIds: [fixId42], getAllCodeActions: (context) => codeFixAll(context, errorCodes54, (changes, diag2) => { - const info = getInfo18(diag2.file, context.program, diag2.start); + const info = getInfo18(diag2.file, context.program, diag2.start, context.preferences); if (info) { doChange35(changes, context.sourceFile, info); } }) }); function doChange35(changes, sourceFile, info) { - const { allowSyntheticDefaults, defaultImportName, namedImports, statement, required } = info; + const { allowSyntheticDefaults, defaultImportName, namedImports, statement, moduleSpecifier } = info; changes.replaceNode( sourceFile, statement, @@ -162020,7 +163136,7 @@ function doChange35(changes, sourceFile, info) { /*isTypeOnly*/ false, defaultImportName, - factory.createExternalModuleReference(required) + factory.createExternalModuleReference(moduleSpecifier) ) : factory.createImportDeclaration( /*modifiers*/ void 0, @@ -162030,13 +163146,13 @@ function doChange35(changes, sourceFile, info) { defaultImportName, namedImports ), - required, + moduleSpecifier, /*attributes*/ void 0 ) ); } -function getInfo18(sourceFile, program, pos) { +function getInfo18(sourceFile, program, pos, preferences) { const { parent: parent2 } = getTokenAtPosition(sourceFile, pos); if (!isRequireCall( parent2, @@ -162046,15 +163162,17 @@ function getInfo18(sourceFile, program, pos) { Debug.failBadSyntaxKind(parent2); } const decl = cast(parent2.parent, isVariableDeclaration); + const quotePreference = getQuotePreference(sourceFile, preferences); const defaultImportName = tryCast(decl.name, isIdentifier); const namedImports = isObjectBindingPattern(decl.name) ? tryCreateNamedImportsFromObjectBindingPattern(decl.name) : void 0; if (defaultImportName || namedImports) { + const moduleSpecifier = first(parent2.arguments); return { allowSyntheticDefaults: getAllowSyntheticDefaultImports(program.getCompilerOptions()), defaultImportName, namedImports, statement: cast(decl.parent.parent, isVariableStatement), - required: first(parent2.arguments) + moduleSpecifier: isNoSubstitutionTemplateLiteral(moduleSpecifier) ? factory.createStringLiteral(moduleSpecifier.text, quotePreference === 0 /* Single */) : moduleSpecifier }; } } @@ -162588,6 +163706,7 @@ __export(ts_Completions_exports, { getCompletionEntryDetails: () => getCompletionEntryDetails, getCompletionEntrySymbol: () => getCompletionEntrySymbol, getCompletionsAtPosition: () => getCompletionsAtPosition, + getDefaultCommitCharacters: () => getDefaultCommitCharacters, getPropertiesForObjectExpression: () => getPropertiesForObjectExpression, moduleSpecifierResolutionCacheAttemptLimit: () => moduleSpecifierResolutionCacheAttemptLimit, moduleSpecifierResolutionLimit: () => moduleSpecifierResolutionLimit @@ -162679,9 +163798,9 @@ function originIsComputedPropertyName(origin) { return !!(origin && origin.kind & 512 /* ComputedPropertyName */); } function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { - var _a, _b, _c; + var _a, _b, _c, _d; const start = timestamp(); - const needsFullResolution = isForImportStatementCompletion || moduleResolutionSupportsPackageJsonExportsAndImports(getEmitModuleResolutionKind(program.getCompilerOptions())); + const needsFullResolution = isForImportStatementCompletion || getResolvePackageJsonExports(program.getCompilerOptions()) || ((_a = preferences.autoImportSpecifierExcludeRegexes) == null ? void 0 : _a.length); let skippedAny = false; let ambientCount = 0; let resolvedCount = 0; @@ -162694,9 +163813,9 @@ function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, resolvedBeyondLimit: () => resolvedCount > moduleSpecifierResolutionLimit }); const hitRateMessage = cacheAttemptCount ? ` (${(resolvedFromCacheCount / cacheAttemptCount * 100).toFixed(1)}% hit rate)` : ""; - (_a = host.log) == null ? void 0 : _a.call(host, `${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`); - (_b = host.log) == null ? void 0 : _b.call(host, `${logPrefix}: response is ${skippedAny ? "incomplete" : "complete"}`); - (_c = host.log) == null ? void 0 : _c.call(host, `${logPrefix}: ${timestamp() - start}`); + (_b = host.log) == null ? void 0 : _b.call(host, `${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`); + (_c = host.log) == null ? void 0 : _c.call(host, `${logPrefix}: response is ${skippedAny ? "incomplete" : "complete"}`); + (_d = host.log) == null ? void 0 : _d.call(host, `${logPrefix}: ${timestamp() - start}`); return result; function tryResolve(exportInfo, isFromAmbientModule) { if (isFromAmbientModule) { @@ -162720,6 +163839,12 @@ function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, return result2 || (needsFullResolution ? "failed" : "skipped"); } } +function getDefaultCommitCharacters(isNewIdentifierLocation) { + if (isNewIdentifierLocation) { + return []; + } + return [".", ",", ";"]; +} function getCompletionsAtPosition(host, program, log, sourceFile, position, preferences, triggerCharacter, completionKind, cancellationToken, formatContext, includeSymbol = false) { var _a; const { previousToken } = getRelevantTokens(position, sourceFile); @@ -162728,7 +163853,17 @@ function getCompletionsAtPosition(host, program, log, sourceFile, position, pref } if (triggerCharacter === " ") { if (preferences.includeCompletionsForImportStatements && preferences.includeCompletionsWithInsertText) { - return { isGlobalCompletion: true, isMemberCompletion: false, isNewIdentifierLocation: true, isIncomplete: true, entries: [] }; + return { + isGlobalCompletion: true, + isMemberCompletion: false, + isNewIdentifierLocation: true, + isIncomplete: true, + entries: [], + defaultCommitCharacters: getDefaultCommitCharacters( + /*isNewIdentifierLocation*/ + true + ) + }; } return void 0; } @@ -162882,7 +164017,16 @@ function continuePreviousIncompleteResponse(cache, file, location, program, host return previousResponse; } function jsdocCompletionInfo(entries) { - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: false, + isNewIdentifierLocation: false, + entries, + defaultCommitCharacters: getDefaultCommitCharacters( + /*isNewIdentifierLocation*/ + false + ) + }; } function getJSDocParameterCompletions(sourceFile, position, checker, options, preferences, tagNameOnly) { const currentToken = getTokenAtPosition(sourceFile, position); @@ -163110,10 +164254,12 @@ function getJSDocParamAnnotation(paramName, initializer, dotDotDotToken, isJs, i const printer = isSnippet ? createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target }) : createPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target }); setEmitFlags(typeNode, 1 /* SingleLine */); @@ -163153,7 +164299,8 @@ function specificKeywordCompletionInfo(entries, isNewIdentifierLocation) { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation, - entries: entries.slice() + entries: entries.slice(), + defaultCommitCharacters: getDefaultCommitCharacters(isNewIdentifierLocation) }; } function keywordCompletionData(keywordFilters, filterOutTsOnlyKeywords, isNewIdentifierLocation) { @@ -163311,7 +164458,8 @@ function completionInfoFromData(sourceFile, host, program, compilerOptions, log, isMemberCompletion: isMemberCompletionKind(completionKind), isNewIdentifierLocation, optionalReplacementSpan: getOptionalReplacementSpan(location), - entries + entries, + defaultCommitCharacters: getDefaultCommitCharacters(isNewIdentifierLocation) }; } function isCheckedFile(sourceFile, compilerOptions) { @@ -163369,6 +164517,7 @@ function getExhaustiveCaseSnippets(caseBlock, sourceFile, preferences, options, const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, newLine: getNewLineKind(newLineChar) }); @@ -163476,7 +164625,17 @@ function getJsxClosingTagCompletion(location, sourceFile) { kindModifiers: void 0, sortText: SortText.LocationPriority }; - return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, optionalReplacementSpan: replacementSpan, entries: [entry] }; + return { + isGlobalCompletion: false, + isMemberCompletion: true, + isNewIdentifierLocation: false, + optionalReplacementSpan: replacementSpan, + entries: [entry], + defaultCommitCharacters: getDefaultCommitCharacters( + /*isNewIdentifierLocation*/ + false + ) + }; } return; } @@ -163493,7 +164652,8 @@ function getJSCompletionEntries(sourceFile, position, uniqueNames, target, entri kind: "warning" /* warning */, kindModifiers: "", sortText: SortText.JavascriptIdentifiers, - isFromUncheckedFile: true + isFromUncheckedFile: true, + commitCharacters: [] }, compareCompletionEntries); } }); @@ -163502,7 +164662,13 @@ function completionNameForLiteral(sourceFile, preferences, literal) { return typeof literal === "object" ? pseudoBigIntToString(literal) + "n" : isString(literal) ? quote(sourceFile, preferences, literal) : JSON.stringify(literal); } function createCompletionEntryForLiteral(sourceFile, preferences, literal) { - return { name: completionNameForLiteral(sourceFile, preferences, literal), kind: "string" /* string */, kindModifiers: "" /* none */, sortText: SortText.LocationPriority }; + return { + name: completionNameForLiteral(sourceFile, preferences, literal), + kind: "string" /* string */, + kindModifiers: "" /* none */, + sortText: SortText.LocationPriority, + commitCharacters: [] + }; } function createCompletionEntry(symbol, sortText, replacementToken, contextToken, location, position, sourceFile, host, program, name, needsConvertPropertyAccess, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, importStatementCompletion, useSemicolons, options, preferences, completionKind, formatContext, isJsxIdentifierExpected, isRightOfOpenTag, includeSymbol) { var _a, _b; @@ -163555,7 +164721,7 @@ function createCompletionEntry(symbol, sortText, replacementToken, contextToken, if (originIsResolvedExport(origin)) { sourceDisplay = [textPart(origin.moduleSpecifier)]; if (importStatementCompletion) { - ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, options, preferences)); + ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, program, preferences)); isSnippet = preferences.includeCompletionsWithSnippetText ? true : void 0; } } @@ -163625,15 +164791,25 @@ function createCompletionEntry(symbol, sortText, replacementToken, contextToken, hasAction = !importStatementCompletion; } const parentNamedImportOrExport = findAncestor(location, isNamedImportsOrExports); - if ((parentNamedImportOrExport == null ? void 0 : parentNamedImportOrExport.kind) === 275 /* NamedImports */) { - const possibleToken = stringToToken(name); - if (parentNamedImportOrExport && possibleToken && (possibleToken === 135 /* AwaitKeyword */ || isNonContextualKeyword(possibleToken))) { - insertText = `${name} as ${name}_`; + if (parentNamedImportOrExport) { + const languageVersion = getEmitScriptTarget(host.getCompilationSettings()); + if (!isIdentifierText(name, languageVersion)) { + insertText = JSON.stringify(name); + if (parentNamedImportOrExport.kind === 275 /* NamedImports */) { + insertText += " as " + generateIdentifierForArbitraryString(name, languageVersion); + } + } else if (parentNamedImportOrExport.kind === 275 /* NamedImports */) { + const possibleToken = stringToToken(name); + if (possibleToken && (possibleToken === 135 /* AwaitKeyword */ || isNonContextualKeyword(possibleToken))) { + insertText = `${name} as ${name}_`; + } } } + const kind = ts_SymbolDisplay_exports.getSymbolKind(typeChecker, symbol, location); + const commitCharacters = kind === "warning" /* warning */ || kind === "string" /* string */ ? [] : void 0; return { name, - kind: ts_SymbolDisplay_exports.getSymbolKind(typeChecker, symbol, location), + kind, kindModifiers: ts_SymbolDisplay_exports.getSymbolModifiers(typeChecker, symbol), sortText, source, @@ -163648,9 +164824,27 @@ function createCompletionEntry(symbol, sortText, replacementToken, contextToken, isPackageJsonImport: originIsPackageJsonImport(origin) || void 0, isImportStatementCompletion: !!importStatementCompletion || void 0, data, + commitCharacters, ...includeSymbol ? { symbol } : void 0 }; } +function generateIdentifierForArbitraryString(text, languageVersion) { + let needsUnderscore = false; + let identifier = ""; + let ch; + for (let i = 0; i < text.length; i += ch !== void 0 && ch >= 65536 ? 2 : 1) { + ch = text.codePointAt(i); + if (ch !== void 0 && (i === 0 ? isIdentifierStart(ch, languageVersion) : isIdentifierPart(ch, languageVersion))) { + if (needsUnderscore) identifier += "_"; + identifier += String.fromCodePoint(ch); + needsUnderscore = false; + } else { + needsUnderscore = true; + } + } + if (needsUnderscore) identifier += "_"; + return identifier || "_"; +} function isClassLikeMemberCompletion(symbol, location, sourceFile) { if (isInJSFile(location)) { return false; @@ -163671,6 +164865,7 @@ function getEntryForMemberCompletion(host, program, options, preferences, name, const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: false, newLine: getNewLineKind(getNewLineOrDefaultFromHost(host, formatContext == null ? void 0 : formatContext.options)) @@ -163821,6 +165016,7 @@ function getEntryForObjectLiteralMethodCompletion(symbol, name, enclosingDeclara const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: false, newLine: getNewLineKind(getNewLineOrDefaultFromHost(host, formatContext == null ? void 0 : formatContext.options)) @@ -163841,6 +165037,7 @@ function getEntryForObjectLiteralMethodCompletion(symbol, name, enclosingDeclara const signaturePrinter = createPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: true }); @@ -163890,7 +165087,14 @@ function createObjectLiteralMethod(symbol, enclosingDeclaration, sourceFile, pro if (signatures.length !== 1) { return void 0; } - const typeNode = checker.typeToTypeNode(effectiveType, enclosingDeclaration, builderFlags, ts_codefix_exports.getNoopSymbolTrackerWithResolver({ program, host })); + const typeNode = checker.typeToTypeNode( + effectiveType, + enclosingDeclaration, + builderFlags, + /*internalFlags*/ + void 0, + ts_codefix_exports.getNoopSymbolTrackerWithResolver({ program, host }) + ); if (!typeNode || !isFunctionTypeNode(typeNode)) { return void 0; } @@ -164010,7 +165214,7 @@ function createSnippetPrinter(printerOptions) { { ...formatContext, options: formatOptions } ); }); - const allChanges = escapes ? stableSort(concatenate(changes, escapes), (a, b) => compareTextSpans(a.span, b.span)) : changes; + const allChanges = escapes ? toSorted(concatenate(changes, escapes), (a, b) => compareTextSpans(a.span, b.span)) : changes; return ts_textChanges_exports.applyChanges(syntheticFile.text, allChanges); } function printNode(hint, node, sourceFile) { @@ -164046,7 +165250,7 @@ function createSnippetPrinter(printerOptions) { 0, { ...formatContext, options: formatOptions } ); - const allChanges = escapes ? stableSort(concatenate(changes, escapes), (a, b) => compareTextSpans(a.span, b.span)) : changes; + const allChanges = escapes ? toSorted(concatenate(changes, escapes), (a, b) => compareTextSpans(a.span, b.span)) : changes; return ts_textChanges_exports.applyChanges(syntheticFile.text, allChanges); } } @@ -164102,7 +165306,7 @@ function completionEntryDataToSymbolOriginInfo(data, completionName, moduleSymbo }; return unresolvedOrigin; } -function getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, options, preferences) { +function getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, program, preferences) { const replacementSpan = importStatementCompletion.replacementSpan; const quotedModuleSpecifier = escapeSnippetText(quote(sourceFile, preferences, origin.moduleSpecifier)); const exportKind = origin.isDefaultExport ? 1 /* Default */ : origin.exportName === "export=" /* ExportEquals */ ? 2 /* ExportEquals */ : 0 /* Named */; @@ -164110,7 +165314,7 @@ function getInsertTextAndReplacementSpanForImportCompletion(name, importStatemen const importKind = ts_codefix_exports.getImportKind( sourceFile, exportKind, - options, + program, /*forceImportKeyword*/ true ); @@ -164258,7 +165462,16 @@ function getCompletionEntriesFromSymbols(symbols, entries, replacementToken, con function getLabelCompletionAtPosition(node) { const entries = getLabelStatementCompletions(node); if (entries.length) { - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: false, + isNewIdentifierLocation: false, + entries, + defaultCommitCharacters: getDefaultCommitCharacters( + /*isNewIdentifierLocation*/ + false + ) + }; } } function getLabelStatementCompletions(node) { @@ -165237,7 +166450,7 @@ function getCompletionData(program, log, sourceFile, compilerOptions, position, if (ts_JsTyping_exports.nodeCoreModules.has(moduleName) && startsWith(moduleName, "node:") !== shouldUseUriStyleNodeCoreModules(sourceFile, program)) { return false; } - return packageJsonFilter ? packageJsonFilter.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson)) : true; + return ((packageJsonFilter == null ? void 0 : packageJsonFilter.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson))) ?? true) || fileContainsPackageImport(sourceFile, moduleName); } return isImportableFile( info.isFromPackageJson ? packageJsonAutoImportProvider : program, @@ -165479,7 +166692,7 @@ function getCompletionData(program, log, sourceFile, compilerOptions, position, completionKind = 3 /* MemberLike */; isNewIdentifierLocation = false; const exports2 = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); - const existing = new Set(namedImportsOrExports.elements.filter((n) => !isCurrentlyEditingNode(n)).map((n) => (n.propertyName || n.name).escapedText)); + const existing = new Set(namedImportsOrExports.elements.filter((n) => !isCurrentlyEditingNode(n)).map((n) => moduleExportNameTextEscaped(n.propertyName || n.name))); const uniques = exports2.filter((e) => e.escapedName !== "default" /* Default */ && !existing.has(e.escapedName)); symbols = concatenate(symbols, uniques); if (!uniques.length) { @@ -165970,6 +167183,9 @@ function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, js if (isIdentifierText(name, target, jsxIdentifierExpected ? 1 /* JSX */ : 0 /* Standard */) || symbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { return validNameResult; } + if (symbol.flags & 2097152 /* Alias */) { + return { name, needsConvertPropertyAccess: true }; + } switch (kind) { case 3 /* MemberLike */: return originIsComputedPropertyName(origin) ? { name: origin.symbolName, needsConvertPropertyAccess: false } : void 0; @@ -166111,7 +167327,13 @@ function getJsDocTagAtPosition(node, position) { } function getPropertiesForObjectExpression(contextualType, completionsType, obj, checker) { const hasCompletionsType = completionsType && completionsType !== contextualType; - const type = hasCompletionsType && !(completionsType.flags & 3 /* AnyOrUnknown */) ? checker.getUnionType([contextualType, completionsType]) : contextualType; + const promiseFilteredContextualType = checker.getUnionType( + filter( + contextualType.flags & 1048576 /* Union */ ? contextualType.types : [contextualType], + (t) => !checker.getPromisedTypeOfPromise(t) + ) + ); + const type = hasCompletionsType && !(completionsType.flags & 3 /* AnyOrUnknown */) ? checker.getUnionType([promiseFilteredContextualType, completionsType]) : promiseFilteredContextualType; const properties = getApparentProperties(type, obj, checker); return type.isClass() && containsNonPublicProperties(properties) ? [] : hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties; function hasDeclarationOtherThanSelf(member) { @@ -166486,7 +167708,7 @@ function createNameAndKindSet() { } function getStringLiteralCompletions(sourceFile, position, contextToken, options, host, program, log, preferences, includeSymbol) { if (isInReferenceComment(sourceFile, position)) { - const entries = getTripleSlashReferenceCompletion(sourceFile, position, options, host); + const entries = getTripleSlashReferenceCompletion(sourceFile, position, program, host); return entries && convertPathCompletions(entries); } if (isInString(sourceFile, position, contextToken)) { @@ -166544,7 +167766,14 @@ function convertStringLiteralCompletions(completion, contextToken, sourceFile, h void 0, includeSymbol ); - return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, optionalReplacementSpan, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: true, + isNewIdentifierLocation: completion.hasIndexSignature, + optionalReplacementSpan, + entries, + defaultCommitCharacters: getDefaultCommitCharacters(completion.hasIndexSignature) + }; } case 2 /* Types */: { const quoteChar = contextToken.kind === 15 /* NoSubstitutionTemplateLiteral */ ? 96 /* backtick */ : startsWith(getTextOfNode(contextToken), "'") ? 39 /* singleQuote */ : 34 /* doubleQuote */; @@ -166553,9 +167782,17 @@ function convertStringLiteralCompletions(completion, contextToken, sourceFile, h kindModifiers: "" /* none */, kind: "string" /* string */, sortText: SortText.LocationPriority, - replacementSpan: getReplacementSpanForContextToken(contextToken, position) + replacementSpan: getReplacementSpanForContextToken(contextToken, position), + commitCharacters: [] })); - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, optionalReplacementSpan, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: false, + isNewIdentifierLocation: completion.isNewIdentifier, + optionalReplacementSpan, + entries, + defaultCommitCharacters: getDefaultCommitCharacters(completion.isNewIdentifier) + }; } default: return Debug.assertNever(completion); @@ -166586,7 +167823,13 @@ function convertPathCompletions(pathCompletions) { const isGlobalCompletion = false; const isNewIdentifierLocation = true; const entries = pathCompletions.map(({ name, kind, span, extension }) => ({ name, kind, kindModifiers: kindModifiersFromExtension(extension), sortText: SortText.LocationPriority, replacementSpan: span })); - return { isGlobalCompletion, isMemberCompletion: false, isNewIdentifierLocation, entries }; + return { + isGlobalCompletion, + isMemberCompletion: false, + isNewIdentifierLocation, + entries, + defaultCommitCharacters: getDefaultCommitCharacters(isNewIdentifierLocation) + }; } function kindModifiersFromExtension(extension) { switch (extension) { @@ -166665,6 +167908,21 @@ function getStringLiteralCompletionEntries(sourceFile, node, position, program, } const literals = contextualTypes.types.filter((literal) => !tracker.hasValue(literal.value)); return { kind: 2 /* Types */, types: literals, isNewIdentifier: false }; + case 276 /* ImportSpecifier */: + case 281 /* ExportSpecifier */: + const specifier = parent2; + if (specifier.propertyName && node !== specifier.propertyName) { + return; + } + const namedImportsOrExports = specifier.parent; + const { moduleSpecifier } = namedImportsOrExports.kind === 275 /* NamedImports */ ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; + if (!moduleSpecifier) return; + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); + if (!moduleSpecifierSymbol) return; + const exports2 = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); + const existing = new Set(namedImportsOrExports.elements.map((n) => moduleExportNameTextEscaped(n.propertyName || n.name))); + const uniques = exports2.filter((e) => e.escapedName !== "default" /* Default */ && !existing.has(e.escapedName)); + return { kind: 1 /* Properties */, symbols: uniques, hasIndexSignature: false }; default: return fromContextualType() || fromContextualType(0 /* None */); } @@ -166794,7 +168052,7 @@ function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, prog const compilerOptions = program.getCompilerOptions(); const typeChecker = program.getTypeChecker(); const extensionOptions = getExtensionOptions(compilerOptions, 1 /* ModuleSpecifier */, sourceFile, typeChecker, preferences, mode); - return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && !compilerOptions.paths && (isRootedDiskPath(literalValue) || isUrl(literalValue)) ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, extensionOptions) : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, compilerOptions, host, extensionOptions, typeChecker); + return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && !compilerOptions.paths && (isRootedDiskPath(literalValue) || isUrl(literalValue)) ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, program, host, scriptPath, extensionOptions) : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, program, host, extensionOptions); } function getExtensionOptions(compilerOptions, referenceKind, importingSourceFile, typeChecker, preferences, resolutionMode) { return { @@ -166805,14 +168063,15 @@ function getExtensionOptions(compilerOptions, referenceKind, importingSourceFile resolutionMode }; } -function getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, extensionOptions) { +function getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, program, host, scriptPath, extensionOptions) { + const compilerOptions = program.getCompilerOptions(); if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, - compilerOptions, + program, host, scriptPath ); @@ -166821,6 +168080,7 @@ function getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, c literalValue, scriptDirectory, extensionOptions, + program, host, /*moduleSpecifierIsRelative*/ true, @@ -166847,7 +168107,8 @@ function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ign compareStringsCaseSensitive ); } -function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptDirectory, extensionOptions, compilerOptions, host, exclude) { +function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptDirectory, extensionOptions, program, host, exclude) { + const compilerOptions = program.getCompilerOptions(); const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); @@ -166856,6 +168117,7 @@ function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment fragment, baseDirectory, extensionOptions, + program, host, /*moduleSpecifierIsRelative*/ true, @@ -166864,7 +168126,7 @@ function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment (itemA, itemB) => itemA.name === itemB.name && itemA.kind === itemB.kind && itemA.extension === itemB.extension ); } -function getCompletionEntriesForDirectoryFragment(fragment, scriptDirectory, extensionOptions, host, moduleSpecifierIsRelative, exclude, result = createNameAndKindSet()) { +function getCompletionEntriesForDirectoryFragment(fragment, scriptDirectory, extensionOptions, program, host, moduleSpecifierIsRelative, exclude, result = createNameAndKindSet()) { var _a; if (fragment === void 0) { fragment = ""; @@ -166889,7 +168151,7 @@ function getCompletionEntriesForDirectoryFragment(fragment, scriptDirectory, ext if (versionPaths) { const packageDirectory = getDirectoryPath(packageJsonPath); const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length); - if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) { + if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, program, host, versionPaths)) { return result; } } @@ -166915,7 +168177,7 @@ function getCompletionEntriesForDirectoryFragment(fragment, scriptDirectory, ext } const { name, extension } = getFilenameWithExtensionOption( getBaseFileName(filePath), - host.getCompilationSettings(), + program, extensionOptions, /*isExportsWildcard*/ false @@ -166934,7 +168196,7 @@ function getCompletionEntriesForDirectoryFragment(fragment, scriptDirectory, ext } return result; } -function getFilenameWithExtensionOption(name, compilerOptions, extensionOptions, isExportsWildcard) { +function getFilenameWithExtensionOption(name, program, extensionOptions, isExportsWildcard) { const nonJsResult = ts_moduleSpecifiers_exports.tryGetRealFileNameForNonJsDeclarationFileName(name); if (nonJsResult) { return { name: nonJsResult, extension: tryGetExtensionFromPath2(nonJsResult) }; @@ -166942,9 +168204,10 @@ function getFilenameWithExtensionOption(name, compilerOptions, extensionOptions, if (extensionOptions.referenceKind === 0 /* Filename */) { return { name, extension: tryGetExtensionFromPath2(name) }; } - let allowedEndings = getModuleSpecifierPreferences( + let allowedEndings = ts_moduleSpecifiers_exports.getModuleSpecifierPreferences( { importModuleSpecifierEnding: extensionOptions.endingPreference }, - compilerOptions, + program, + program.getCompilerOptions(), extensionOptions.importingSourceFile ).getAllowedEndingsInPreferredOrder(extensionOptions.resolutionMode); if (isExportsWildcard) { @@ -166954,16 +168217,16 @@ function getFilenameWithExtensionOption(name, compilerOptions, extensionOptions, if (fileExtensionIsOneOf(name, supportedTSImplementationExtensions)) { return { name, extension: tryGetExtensionFromPath2(name) }; } - const outputExtension2 = ts_moduleSpecifiers_exports.tryGetJSExtensionForFile(name, compilerOptions); + const outputExtension2 = ts_moduleSpecifiers_exports.tryGetJSExtensionForFile(name, program.getCompilerOptions()); return outputExtension2 ? { name: changeExtension(name, outputExtension2), extension: outputExtension2 } : { name, extension: tryGetExtensionFromPath2(name) }; } if (!isExportsWildcard && (allowedEndings[0] === 0 /* Minimal */ || allowedEndings[0] === 1 /* Index */) && fileExtensionIsOneOf(name, [".js" /* Js */, ".jsx" /* Jsx */, ".ts" /* Ts */, ".tsx" /* Tsx */, ".d.ts" /* Dts */])) { return { name: removeFileExtension(name), extension: tryGetExtensionFromPath2(name) }; } - const outputExtension = ts_moduleSpecifiers_exports.tryGetJSExtensionForFile(name, compilerOptions); + const outputExtension = ts_moduleSpecifiers_exports.tryGetJSExtensionForFile(name, program.getCompilerOptions()); return outputExtension ? { name: changeExtension(name, outputExtension), extension: outputExtension } : { name, extension: tryGetExtensionFromPath2(name) }; } -function addCompletionEntriesFromPaths(result, fragment, baseDirectory, extensionOptions, host, paths) { +function addCompletionEntriesFromPaths(result, fragment, baseDirectory, extensionOptions, program, host, paths) { const getPatternsForKey = (key) => paths[key]; const comparePaths2 = (a, b) => { const patternA = tryParsePattern(a); @@ -166979,13 +168242,14 @@ function addCompletionEntriesFromPaths(result, fragment, baseDirectory, extensio fragment, baseDirectory, extensionOptions, + program, host, getOwnKeys(paths), getPatternsForKey, comparePaths2 ); } -function addCompletionEntriesFromPathsOrExports(result, isExports, fragment, baseDirectory, extensionOptions, host, keys, getPatternsForKey, comparePaths2) { +function addCompletionEntriesFromPathsOrExports(result, isExports, fragment, baseDirectory, extensionOptions, program, host, keys, getPatternsForKey, comparePaths2) { let pathResults = []; let matchedPath; for (const key of keys) { @@ -167004,7 +168268,7 @@ function addCompletionEntriesFromPathsOrExports(result, isExports, fragment, bas if (typeof pathPattern === "string" || matchedPath === void 0 || comparePaths2(key, matchedPath) !== 1 /* GreaterThan */) { pathResults.push({ matchedPattern: isMatch, - results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, isExports && isMatch, host).map(({ name, kind, extension }) => nameAndKind(name, kind, extension)) + results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, isExports && isMatch, program, host).map(({ name, kind, extension }) => nameAndKind(name, kind, extension)) }); } } @@ -167012,7 +168276,9 @@ function addCompletionEntriesFromPathsOrExports(result, isExports, fragment, bas pathResults.forEach((pathResult) => pathResult.results.forEach((r) => result.add(r))); return matchedPath !== void 0; } -function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, compilerOptions, host, extensionOptions, typeChecker) { +function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, program, host, extensionOptions) { + const typeChecker = program.getTypeChecker(); + const compilerOptions = program.getCompilerOptions(); const { baseUrl, paths } = compilerOptions; const result = createNameAndKindSet(); const moduleResolution = getEmitModuleResolutionKind(compilerOptions); @@ -167022,6 +168288,7 @@ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, c fragment, absolute, extensionOptions, + program, host, /*moduleSpecifierIsRelative*/ false, @@ -167032,7 +168299,7 @@ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, c } if (paths) { const absolute = getPathsBasePath(compilerOptions, host); - addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, host, paths); + addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, program, host, paths); } const fragmentDirectory = getFragmentDirectory(fragment); for (const ambientName of getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker)) { @@ -167043,7 +168310,7 @@ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, c void 0 )); } - getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); + getCompletionEntriesFromTypings(host, program, scriptPath, fragmentDirectory, extensionOptions, result); if (moduleResolutionUsesNodeModules(moduleResolution)) { let foundGlobal = false; if (fragmentDirectory === void 0) { @@ -167068,6 +168335,7 @@ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, c fragment, nodeModules, extensionOptions, + program, host, /*moduleSpecifierIsRelative*/ false, @@ -167112,6 +168380,7 @@ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, mode, c fragmentSubpath, packageDirectory, extensionOptions, + program, host, keys, (key) => singleElementArray(getPatternFromFirstMatchingCondition(exports2[key], conditions)), @@ -167144,7 +168413,7 @@ function getPatternFromFirstMatchingCondition(target, conditions) { function getFragmentDirectory(fragment) { return containsSlash(fragment) ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : void 0; } -function getCompletionsForPathMapping(path, patterns, fragment, packageDirectory, extensionOptions, isExportsWildcard, host) { +function getCompletionsForPathMapping(path, patterns, fragment, packageDirectory, extensionOptions, isExportsWildcard, program, host) { if (!endsWith(path, "*")) { return !path.includes("*") ? justPathMappingName(path, "script" /* scriptElement */) : emptyArray; } @@ -167154,15 +168423,15 @@ function getCompletionsForPathMapping(path, patterns, fragment, packageDirectory const starIsFullPathComponent = path[path.length - 2] === "/"; return starIsFullPathComponent ? justPathMappingName(pathPrefix, "directory" /* directory */) : flatMap(patterns, (pattern) => { var _a; - return (_a = getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, isExportsWildcard, host)) == null ? void 0 : _a.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest })); + return (_a = getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, isExportsWildcard, program, host)) == null ? void 0 : _a.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest })); }); } - return flatMap(patterns, (pattern) => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, host)); + return flatMap(patterns, (pattern) => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, program, host)); function justPathMappingName(name, kind) { return startsWith(name, fragment) ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: void 0 }] : emptyArray; } } -function getModulesForPathsPattern(fragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, host) { +function getModulesForPathsPattern(fragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, program, host) { if (!host.readDirectory) { return void 0; } @@ -167195,7 +168464,7 @@ function getModulesForPathsPattern(fragment, packageDirectory, pattern, extensio if (containsSlash(trimmedWithPattern)) { return directoryResult(getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); } - const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, host.getCompilationSettings(), extensionOptions, isExportsWildcard); + const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, program, extensionOptions, isExportsWildcard); return nameAndKind(name, "script" /* scriptElement */, extension); } }); @@ -167223,7 +168492,8 @@ function getAmbientModuleCompletions(fragment, fragmentDirectory, checker) { } return nonRelativeModuleNames; } -function getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host) { +function getTripleSlashReferenceCompletion(sourceFile, position, program, host) { + const compilerOptions = program.getCompilerOptions(); const token = getTokenAtPosition(sourceFile, position); const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); const range = commentRanges && find(commentRanges, (commentRange) => position >= commentRange.pos && position <= commentRange.end); @@ -167241,14 +168511,16 @@ function getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions toComplete, scriptPath, getExtensionOptions(compilerOptions, 0 /* Filename */, sourceFile), + program, host, /*moduleSpecifierIsRelative*/ true, sourceFile.path - ) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, 1 /* ModuleSpecifier */, sourceFile)) : Debug.fail(); + ) : kind === "types" ? getCompletionEntriesFromTypings(host, program, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, 1 /* ModuleSpecifier */, sourceFile)) : Debug.fail(); return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); } -function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result = createNameAndKindSet()) { +function getCompletionEntriesFromTypings(host, program, scriptPath, fragmentDirectory, extensionOptions, result = createNameAndKindSet()) { + const options = program.getCompilerOptions(); const seen = /* @__PURE__ */ new Map(); const typeRoots = tryAndIgnoreErrors(() => getEffectiveTypeRoots(options, host)) || emptyArray; for (const root of typeRoots) { @@ -167282,6 +168554,7 @@ function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDire remainingFragment, baseDirectory, extensionOptions, + program, host, /*moduleSpecifierIsRelative*/ false, @@ -167352,11 +168625,9 @@ __export(ts_FindAllReferences_exports, { getImplementationsAtPosition: () => getImplementationsAtPosition, getImportOrExportSymbol: () => getImportOrExportSymbol, getReferenceEntriesForNode: () => getReferenceEntriesForNode, - getTextSpanOfEntry: () => getTextSpanOfEntry, isContextWithStartAndEndNode: () => isContextWithStartAndEndNode, isDeclarationOfSymbol: () => isDeclarationOfSymbol, isWriteAccessForReference: () => isWriteAccessForReference, - nodeEntry: () => nodeEntry, toContextSpan: () => toContextSpan, toHighlightSpan: () => toHighlightSpan, toReferenceEntry: () => toReferenceEntry, @@ -167620,12 +168891,12 @@ function getSearchesFromDirectImports(directImports, exportSymbol, exportKind, c } for (const element of namedBindings.elements) { const { name, propertyName } = element; - if (!isNameMatch((propertyName || name).escapedText)) { + if (!isNameMatch(moduleExportNameTextEscaped(propertyName || name))) { continue; } if (propertyName) { singleReferences.push(propertyName); - if (!isForRename || name.escapedText === exportSymbol.escapedName) { + if (!isForRename || moduleExportNameTextEscaped(name) === exportSymbol.escapedName) { addSearch(name, checker.getSymbolAtLocation(name)); } } else { @@ -167883,7 +169154,7 @@ function getContainingModuleSymbol(importer, checker) { return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node) { - if (node.kind === 213 /* CallExpression */) { + if (node.kind === 213 /* CallExpression */ || node.kind === 351 /* JSDocImportTag */) { return node.getSourceFile(); } const { parent: parent2 } = node; @@ -168883,8 +170154,8 @@ var Core; function shouldAddSingleReference(singleRef, state) { if (!hasMatchingMeaning(singleRef, state)) return false; if (state.options.use !== 2 /* Rename */) return true; - if (!isIdentifier(singleRef)) return false; - return !(isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === "default" /* Default */); + if (!isIdentifier(singleRef) && !isImportOrExportSpecifier(singleRef.parent)) return false; + return !(isImportOrExportSpecifier(singleRef.parent) && moduleExportNameIsDefault(singleRef)); } function searchForImportedSymbol(symbol, state) { if (!symbol.declarations) return; @@ -169046,7 +170317,7 @@ var Core; case 15 /* NoSubstitutionTemplateLiteral */: case 11 /* StringLiteral */: { const str = node; - return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node) && str.text.length === searchSymbolName.length; + return str.text.length === searchSymbolName.length && (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node || isImportOrExportSpecifier(node.parent)); } case 9 /* NumericLiteral */: return isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length; @@ -169112,7 +170383,7 @@ var Core; return; } if (isExportSpecifier(parent2)) { - Debug.assert(referenceLocation.kind === 80 /* Identifier */); + Debug.assert(referenceLocation.kind === 80 /* Identifier */ || referenceLocation.kind === 11 /* StringLiteral */); getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent2, search, state, addReferencesHere); return; } @@ -169162,7 +170433,7 @@ var Core; return; } if (!propertyName) { - if (!(state.options.use === 2 /* Rename */ && name.escapedText === "default" /* Default */)) { + if (!(state.options.use === 2 /* Rename */ && moduleExportNameIsDefault(name))) { addRef(); } } else if (referenceLocation === propertyName) { @@ -169178,7 +170449,7 @@ var Core; } } if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) { - const isDefaultExport = referenceLocation.escapedText === "default" || exportSpecifier.name.escapedText === "default"; + const isDefaultExport = moduleExportNameIsDefault(referenceLocation) || moduleExportNameIsDefault(exportSpecifier.name); const exportKind = isDefaultExport ? 1 /* Default */ : 0 /* Named */; const exportSymbol = Debug.checkDefined(exportSpecifier.symbol); const exportInfo = getExportInfo(exportSymbol, exportKind, state.checker); @@ -169778,7 +171049,6 @@ var Core; var ts_GoToDefinition_exports = {}; __export(ts_GoToDefinition_exports, { createDefinitionInfo: () => createDefinitionInfo, - findReferenceInPosition: () => findReferenceInPosition, getDefinitionAndBoundSpan: () => getDefinitionAndBoundSpan, getDefinitionAtPosition: () => getDefinitionAtPosition, getReferenceAtPosition: () => getReferenceAtPosition, @@ -169893,12 +171163,13 @@ function getDefinitionAtPosition(program, sourceFile, position, searchOtherFiles const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); if (calledDeclaration && !(isJsxOpeningLikeElement(node.parent) && isJsxConstructorLike(calledDeclaration))) { const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration, failedAliasResolution); + let declarationFilter = (d) => d !== calledDeclaration; if (typeChecker.getRootSymbols(symbol).some((s) => symbolMatchesSignature(s, calledDeclaration))) { - return [sigInfo]; - } else { - const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) || emptyArray; - return node.kind === 108 /* SuperKeyword */ ? [sigInfo, ...defs] : [...defs, sigInfo]; + if (!isConstructorDeclaration(calledDeclaration)) return [sigInfo]; + declarationFilter = (d) => d !== calledDeclaration && (isClassDeclaration(d) || isClassExpression(d)); } + const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, declarationFilter) || emptyArray; + return node.kind === 108 /* SuperKeyword */ ? [sigInfo, ...defs] : [...defs, sigInfo]; } if (node.parent.kind === 304 /* ShorthandPropertyAssignment */) { const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); @@ -170135,7 +171406,7 @@ function getSymbol(node, checker, stopAtAlias) { return { symbol, failedAliasResolution }; } function shouldSkipAlias(node, declaration) { - if (node.kind !== 80 /* Identifier */) { + if (node.kind !== 80 /* Identifier */ && (node.kind !== 11 /* StringLiteral */ || !isImportOrExportSpecifier(node.parent))) { return false; } if (node.parent === declaration) { @@ -170155,9 +171426,9 @@ function isExpandoDeclaration(node) { }); return !!containingAssignment && getAssignmentDeclarationKind(containingAssignment) === 5 /* Property */; } -function getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, excludeDeclaration) { - const filteredDeclarations = filter(symbol.declarations, (d) => d !== excludeDeclaration); - const signatureDefinition = getConstructSignatureDefinition() || getCallSignatureDefinition(); +function getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, declarationFilter) { + const filteredDeclarations = declarationFilter !== void 0 ? filter(symbol.declarations, declarationFilter) : symbol.declarations; + const signatureDefinition = !declarationFilter && (getConstructSignatureDefinition() || getCallSignatureDefinition()); if (signatureDefinition) { return signatureDefinition; } @@ -170563,6 +171834,14 @@ function provideInlayHints(context) { if (!signature) { return; } + const typePredicate = checker.getTypePredicateOfSignature(signature); + if (typePredicate == null ? void 0 : typePredicate.type) { + const hintParts2 = typePredicateToInlayHintParts(typePredicate); + if (hintParts2) { + addTypeHints(hintParts2, getTypeAnnotationPosition(decl)); + return; + } + } const returnType = checker.getReturnTypeOfSignature(signature); if (isModuleReferenceType(returnType)) { return; @@ -170631,6 +171910,26 @@ function provideInlayHints(context) { ); }); } + function printTypePredicateInSingleLine(typePredicate) { + const flags = 70221824 /* IgnoreErrors */ | 1048576 /* AllowUniqueESSymbolType */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; + const printer = createPrinterWithRemoveComments(); + return usingSingleLineStringWriter((writer) => { + const typePredicateNode = checker.typePredicateToTypePredicateNode( + typePredicate, + /*enclosingDeclaration*/ + void 0, + flags + ); + Debug.assertIsDefined(typePredicateNode, "should always get typePredicateNode"); + printer.writeNode( + 4 /* Unspecified */, + typePredicateNode, + /*sourceFile*/ + file, + writer + ); + }); + } function typeToInlayHintParts(type) { if (!shouldUseInteractiveInlayHints(preferences)) { return printTypeInSingleLine(type); @@ -170642,29 +171941,46 @@ function provideInlayHints(context) { void 0, flags ); + Debug.assertIsDefined(typeNode, "should always get typeNode"); + return getInlayHintDisplayParts(typeNode); + } + function typePredicateToInlayHintParts(typePredicate) { + if (!shouldUseInteractiveInlayHints(preferences)) { + return printTypePredicateInSingleLine(typePredicate); + } + const flags = 70221824 /* IgnoreErrors */ | 1048576 /* AllowUniqueESSymbolType */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; + const typeNode = checker.typePredicateToTypePredicateNode( + typePredicate, + /*enclosingDeclaration*/ + void 0, + flags + ); Debug.assertIsDefined(typeNode, "should always get typenode"); + return getInlayHintDisplayParts(typeNode); + } + function getInlayHintDisplayParts(node) { const parts = []; - visitForDisplayParts(typeNode); + visitForDisplayParts(node); return parts; - function visitForDisplayParts(node) { + function visitForDisplayParts(node2) { var _a, _b; - if (!node) { + if (!node2) { return; } - const tokenString = tokenToString(node.kind); + const tokenString = tokenToString(node2.kind); if (tokenString) { parts.push({ text: tokenString }); return; } - if (isLiteralExpression(node)) { - parts.push({ text: getLiteralText2(node) }); + if (isLiteralExpression(node2)) { + parts.push({ text: getLiteralText2(node2) }); return; } - switch (node.kind) { + switch (node2.kind) { case 80 /* Identifier */: - Debug.assertNode(node, isIdentifier); - const identifierText = idText(node); - const name = node.symbol && node.symbol.declarations && node.symbol.declarations.length && getNameOfDeclaration(node.symbol.declarations[0]); + Debug.assertNode(node2, isIdentifier); + const identifierText = idText(node2); + const name = node2.symbol && node2.symbol.declarations && node2.symbol.declarations.length && getNameOfDeclaration(node2.symbol.declarations[0]); if (name) { parts.push(getNodeDisplayPart(identifierText, name)); } else { @@ -170672,331 +171988,331 @@ function provideInlayHints(context) { } break; case 166 /* QualifiedName */: - Debug.assertNode(node, isQualifiedName); - visitForDisplayParts(node.left); + Debug.assertNode(node2, isQualifiedName); + visitForDisplayParts(node2.left); parts.push({ text: "." }); - visitForDisplayParts(node.right); + visitForDisplayParts(node2.right); break; case 182 /* TypePredicate */: - Debug.assertNode(node, isTypePredicateNode); - if (node.assertsModifier) { + Debug.assertNode(node2, isTypePredicateNode); + if (node2.assertsModifier) { parts.push({ text: "asserts " }); } - visitForDisplayParts(node.parameterName); - if (node.type) { + visitForDisplayParts(node2.parameterName); + if (node2.type) { parts.push({ text: " is " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 183 /* TypeReference */: - Debug.assertNode(node, isTypeReferenceNode); - visitForDisplayParts(node.typeName); - if (node.typeArguments) { + Debug.assertNode(node2, isTypeReferenceNode); + visitForDisplayParts(node2.typeName); + if (node2.typeArguments) { parts.push({ text: "<" }); - visitDisplayPartList(node.typeArguments, ", "); + visitDisplayPartList(node2.typeArguments, ", "); parts.push({ text: ">" }); } break; case 168 /* TypeParameter */: - Debug.assertNode(node, isTypeParameterDeclaration); - if (node.modifiers) { - visitDisplayPartList(node.modifiers, " "); + Debug.assertNode(node2, isTypeParameterDeclaration); + if (node2.modifiers) { + visitDisplayPartList(node2.modifiers, " "); } - visitForDisplayParts(node.name); - if (node.constraint) { + visitForDisplayParts(node2.name); + if (node2.constraint) { parts.push({ text: " extends " }); - visitForDisplayParts(node.constraint); + visitForDisplayParts(node2.constraint); } - if (node.default) { + if (node2.default) { parts.push({ text: " = " }); - visitForDisplayParts(node.default); + visitForDisplayParts(node2.default); } break; case 169 /* Parameter */: - Debug.assertNode(node, isParameter); - if (node.modifiers) { - visitDisplayPartList(node.modifiers, " "); + Debug.assertNode(node2, isParameter); + if (node2.modifiers) { + visitDisplayPartList(node2.modifiers, " "); } - if (node.dotDotDotToken) { + if (node2.dotDotDotToken) { parts.push({ text: "..." }); } - visitForDisplayParts(node.name); - if (node.questionToken) { + visitForDisplayParts(node2.name); + if (node2.questionToken) { parts.push({ text: "?" }); } - if (node.type) { + if (node2.type) { parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 185 /* ConstructorType */: - Debug.assertNode(node, isConstructorTypeNode); + Debug.assertNode(node2, isConstructorTypeNode); parts.push({ text: "new " }); - visitParametersAndTypeParameters(node); + visitParametersAndTypeParameters(node2); parts.push({ text: " => " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); break; case 186 /* TypeQuery */: - Debug.assertNode(node, isTypeQueryNode); + Debug.assertNode(node2, isTypeQueryNode); parts.push({ text: "typeof " }); - visitForDisplayParts(node.exprName); - if (node.typeArguments) { + visitForDisplayParts(node2.exprName); + if (node2.typeArguments) { parts.push({ text: "<" }); - visitDisplayPartList(node.typeArguments, ", "); + visitDisplayPartList(node2.typeArguments, ", "); parts.push({ text: ">" }); } break; case 187 /* TypeLiteral */: - Debug.assertNode(node, isTypeLiteralNode); + Debug.assertNode(node2, isTypeLiteralNode); parts.push({ text: "{" }); - if (node.members.length) { + if (node2.members.length) { parts.push({ text: " " }); - visitDisplayPartList(node.members, "; "); + visitDisplayPartList(node2.members, "; "); parts.push({ text: " " }); } parts.push({ text: "}" }); break; case 188 /* ArrayType */: - Debug.assertNode(node, isArrayTypeNode); - visitForDisplayParts(node.elementType); + Debug.assertNode(node2, isArrayTypeNode); + visitForDisplayParts(node2.elementType); parts.push({ text: "[]" }); break; case 189 /* TupleType */: - Debug.assertNode(node, isTupleTypeNode); + Debug.assertNode(node2, isTupleTypeNode); parts.push({ text: "[" }); - visitDisplayPartList(node.elements, ", "); + visitDisplayPartList(node2.elements, ", "); parts.push({ text: "]" }); break; case 202 /* NamedTupleMember */: - Debug.assertNode(node, isNamedTupleMember); - if (node.dotDotDotToken) { + Debug.assertNode(node2, isNamedTupleMember); + if (node2.dotDotDotToken) { parts.push({ text: "..." }); } - visitForDisplayParts(node.name); - if (node.questionToken) { + visitForDisplayParts(node2.name); + if (node2.questionToken) { parts.push({ text: "?" }); } parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); break; case 190 /* OptionalType */: - Debug.assertNode(node, isOptionalTypeNode); - visitForDisplayParts(node.type); + Debug.assertNode(node2, isOptionalTypeNode); + visitForDisplayParts(node2.type); parts.push({ text: "?" }); break; case 191 /* RestType */: - Debug.assertNode(node, isRestTypeNode); + Debug.assertNode(node2, isRestTypeNode); parts.push({ text: "..." }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); break; case 192 /* UnionType */: - Debug.assertNode(node, isUnionTypeNode); - visitDisplayPartList(node.types, " | "); + Debug.assertNode(node2, isUnionTypeNode); + visitDisplayPartList(node2.types, " | "); break; case 193 /* IntersectionType */: - Debug.assertNode(node, isIntersectionTypeNode); - visitDisplayPartList(node.types, " & "); + Debug.assertNode(node2, isIntersectionTypeNode); + visitDisplayPartList(node2.types, " & "); break; case 194 /* ConditionalType */: - Debug.assertNode(node, isConditionalTypeNode); - visitForDisplayParts(node.checkType); + Debug.assertNode(node2, isConditionalTypeNode); + visitForDisplayParts(node2.checkType); parts.push({ text: " extends " }); - visitForDisplayParts(node.extendsType); + visitForDisplayParts(node2.extendsType); parts.push({ text: " ? " }); - visitForDisplayParts(node.trueType); + visitForDisplayParts(node2.trueType); parts.push({ text: " : " }); - visitForDisplayParts(node.falseType); + visitForDisplayParts(node2.falseType); break; case 195 /* InferType */: - Debug.assertNode(node, isInferTypeNode); + Debug.assertNode(node2, isInferTypeNode); parts.push({ text: "infer " }); - visitForDisplayParts(node.typeParameter); + visitForDisplayParts(node2.typeParameter); break; case 196 /* ParenthesizedType */: - Debug.assertNode(node, isParenthesizedTypeNode); + Debug.assertNode(node2, isParenthesizedTypeNode); parts.push({ text: "(" }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); parts.push({ text: ")" }); break; case 198 /* TypeOperator */: - Debug.assertNode(node, isTypeOperatorNode); - parts.push({ text: `${tokenToString(node.operator)} ` }); - visitForDisplayParts(node.type); + Debug.assertNode(node2, isTypeOperatorNode); + parts.push({ text: `${tokenToString(node2.operator)} ` }); + visitForDisplayParts(node2.type); break; case 199 /* IndexedAccessType */: - Debug.assertNode(node, isIndexedAccessTypeNode); - visitForDisplayParts(node.objectType); + Debug.assertNode(node2, isIndexedAccessTypeNode); + visitForDisplayParts(node2.objectType); parts.push({ text: "[" }); - visitForDisplayParts(node.indexType); + visitForDisplayParts(node2.indexType); parts.push({ text: "]" }); break; case 200 /* MappedType */: - Debug.assertNode(node, isMappedTypeNode); + Debug.assertNode(node2, isMappedTypeNode); parts.push({ text: "{ " }); - if (node.readonlyToken) { - if (node.readonlyToken.kind === 40 /* PlusToken */) { + if (node2.readonlyToken) { + if (node2.readonlyToken.kind === 40 /* PlusToken */) { parts.push({ text: "+" }); - } else if (node.readonlyToken.kind === 41 /* MinusToken */) { + } else if (node2.readonlyToken.kind === 41 /* MinusToken */) { parts.push({ text: "-" }); } parts.push({ text: "readonly " }); } parts.push({ text: "[" }); - visitForDisplayParts(node.typeParameter); - if (node.nameType) { + visitForDisplayParts(node2.typeParameter); + if (node2.nameType) { parts.push({ text: " as " }); - visitForDisplayParts(node.nameType); + visitForDisplayParts(node2.nameType); } parts.push({ text: "]" }); - if (node.questionToken) { - if (node.questionToken.kind === 40 /* PlusToken */) { + if (node2.questionToken) { + if (node2.questionToken.kind === 40 /* PlusToken */) { parts.push({ text: "+" }); - } else if (node.questionToken.kind === 41 /* MinusToken */) { + } else if (node2.questionToken.kind === 41 /* MinusToken */) { parts.push({ text: "-" }); } parts.push({ text: "?" }); } parts.push({ text: ": " }); - if (node.type) { - visitForDisplayParts(node.type); + if (node2.type) { + visitForDisplayParts(node2.type); } parts.push({ text: "; }" }); break; case 201 /* LiteralType */: - Debug.assertNode(node, isLiteralTypeNode); - visitForDisplayParts(node.literal); + Debug.assertNode(node2, isLiteralTypeNode); + visitForDisplayParts(node2.literal); break; case 184 /* FunctionType */: - Debug.assertNode(node, isFunctionTypeNode); - visitParametersAndTypeParameters(node); + Debug.assertNode(node2, isFunctionTypeNode); + visitParametersAndTypeParameters(node2); parts.push({ text: " => " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); break; case 205 /* ImportType */: - Debug.assertNode(node, isImportTypeNode); - if (node.isTypeOf) { + Debug.assertNode(node2, isImportTypeNode); + if (node2.isTypeOf) { parts.push({ text: "typeof " }); } parts.push({ text: "import(" }); - visitForDisplayParts(node.argument); - if (node.assertions) { + visitForDisplayParts(node2.argument); + if (node2.assertions) { parts.push({ text: ", { assert: " }); - visitDisplayPartList(node.assertions.assertClause.elements, ", "); + visitDisplayPartList(node2.assertions.assertClause.elements, ", "); parts.push({ text: " }" }); } parts.push({ text: ")" }); - if (node.qualifier) { + if (node2.qualifier) { parts.push({ text: "." }); - visitForDisplayParts(node.qualifier); + visitForDisplayParts(node2.qualifier); } - if (node.typeArguments) { + if (node2.typeArguments) { parts.push({ text: "<" }); - visitDisplayPartList(node.typeArguments, ", "); + visitDisplayPartList(node2.typeArguments, ", "); parts.push({ text: ">" }); } break; case 171 /* PropertySignature */: - Debug.assertNode(node, isPropertySignature); - if ((_a = node.modifiers) == null ? void 0 : _a.length) { - visitDisplayPartList(node.modifiers, " "); + Debug.assertNode(node2, isPropertySignature); + if ((_a = node2.modifiers) == null ? void 0 : _a.length) { + visitDisplayPartList(node2.modifiers, " "); parts.push({ text: " " }); } - visitForDisplayParts(node.name); - if (node.questionToken) { + visitForDisplayParts(node2.name); + if (node2.questionToken) { parts.push({ text: "?" }); } - if (node.type) { + if (node2.type) { parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 181 /* IndexSignature */: - Debug.assertNode(node, isIndexSignatureDeclaration); + Debug.assertNode(node2, isIndexSignatureDeclaration); parts.push({ text: "[" }); - visitDisplayPartList(node.parameters, ", "); + visitDisplayPartList(node2.parameters, ", "); parts.push({ text: "]" }); - if (node.type) { + if (node2.type) { parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 173 /* MethodSignature */: - Debug.assertNode(node, isMethodSignature); - if ((_b = node.modifiers) == null ? void 0 : _b.length) { - visitDisplayPartList(node.modifiers, " "); + Debug.assertNode(node2, isMethodSignature); + if ((_b = node2.modifiers) == null ? void 0 : _b.length) { + visitDisplayPartList(node2.modifiers, " "); parts.push({ text: " " }); } - visitForDisplayParts(node.name); - if (node.questionToken) { + visitForDisplayParts(node2.name); + if (node2.questionToken) { parts.push({ text: "?" }); } - visitParametersAndTypeParameters(node); - if (node.type) { + visitParametersAndTypeParameters(node2); + if (node2.type) { parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 179 /* CallSignature */: - Debug.assertNode(node, isCallSignatureDeclaration); - visitParametersAndTypeParameters(node); - if (node.type) { + Debug.assertNode(node2, isCallSignatureDeclaration); + visitParametersAndTypeParameters(node2); + if (node2.type) { parts.push({ text: ": " }); - visitForDisplayParts(node.type); + visitForDisplayParts(node2.type); } break; case 207 /* ArrayBindingPattern */: - Debug.assertNode(node, isArrayBindingPattern); + Debug.assertNode(node2, isArrayBindingPattern); parts.push({ text: "[" }); - visitDisplayPartList(node.elements, ", "); + visitDisplayPartList(node2.elements, ", "); parts.push({ text: "]" }); break; case 206 /* ObjectBindingPattern */: - Debug.assertNode(node, isObjectBindingPattern); + Debug.assertNode(node2, isObjectBindingPattern); parts.push({ text: "{" }); - if (node.elements.length) { + if (node2.elements.length) { parts.push({ text: " " }); - visitDisplayPartList(node.elements, ", "); + visitDisplayPartList(node2.elements, ", "); parts.push({ text: " " }); } parts.push({ text: "}" }); break; case 208 /* BindingElement */: - Debug.assertNode(node, isBindingElement); - visitForDisplayParts(node.name); + Debug.assertNode(node2, isBindingElement); + visitForDisplayParts(node2.name); break; case 224 /* PrefixUnaryExpression */: - Debug.assertNode(node, isPrefixUnaryExpression); - parts.push({ text: tokenToString(node.operator) }); - visitForDisplayParts(node.operand); + Debug.assertNode(node2, isPrefixUnaryExpression); + parts.push({ text: tokenToString(node2.operator) }); + visitForDisplayParts(node2.operand); break; case 203 /* TemplateLiteralType */: - Debug.assertNode(node, isTemplateLiteralTypeNode); - visitForDisplayParts(node.head); - node.templateSpans.forEach(visitForDisplayParts); + Debug.assertNode(node2, isTemplateLiteralTypeNode); + visitForDisplayParts(node2.head); + node2.templateSpans.forEach(visitForDisplayParts); break; case 16 /* TemplateHead */: - Debug.assertNode(node, isTemplateHead); - parts.push({ text: getLiteralText2(node) }); + Debug.assertNode(node2, isTemplateHead); + parts.push({ text: getLiteralText2(node2) }); break; case 204 /* TemplateLiteralTypeSpan */: - Debug.assertNode(node, isTemplateLiteralTypeSpan); - visitForDisplayParts(node.type); - visitForDisplayParts(node.literal); + Debug.assertNode(node2, isTemplateLiteralTypeSpan); + visitForDisplayParts(node2.type); + visitForDisplayParts(node2.literal); break; case 17 /* TemplateMiddle */: - Debug.assertNode(node, isTemplateMiddle); - parts.push({ text: getLiteralText2(node) }); + Debug.assertNode(node2, isTemplateMiddle); + parts.push({ text: getLiteralText2(node2) }); break; case 18 /* TemplateTail */: - Debug.assertNode(node, isTemplateTail); - parts.push({ text: getLiteralText2(node) }); + Debug.assertNode(node2, isTemplateTail); + parts.push({ text: getLiteralText2(node2) }); break; case 197 /* ThisType */: - Debug.assertNode(node, isThisTypeNode); + Debug.assertNode(node2, isThisTypeNode); parts.push({ text: "this" }); break; default: - Debug.failBadSyntaxKind(node); + Debug.failBadSyntaxKind(node2); } } function visitParametersAndTypeParameters(signatureDeclaration) { @@ -171010,22 +172326,22 @@ function provideInlayHints(context) { parts.push({ text: ")" }); } function visitDisplayPartList(nodes, separator) { - nodes.forEach((node, index) => { + nodes.forEach((node2, index) => { if (index > 0) { parts.push({ text: separator }); } - visitForDisplayParts(node); + visitForDisplayParts(node2); }); } - function getLiteralText2(node) { - switch (node.kind) { + function getLiteralText2(node2) { + switch (node2.kind) { case 11 /* StringLiteral */: - return quotePreference === 0 /* Single */ ? `'${escapeString(node.text, 39 /* singleQuote */)}'` : `"${escapeString(node.text, 34 /* doubleQuote */)}"`; + return quotePreference === 0 /* Single */ ? `'${escapeString(node2.text, 39 /* singleQuote */)}'` : `"${escapeString(node2.text, 34 /* doubleQuote */)}"`; case 16 /* TemplateHead */: case 17 /* TemplateMiddle */: case 18 /* TemplateTail */: { - const rawText = node.rawText ?? escapeTemplateSubstitution(escapeString(node.text, 96 /* backtick */)); - switch (node.kind) { + const rawText = node2.rawText ?? escapeTemplateSubstitution(escapeString(node2.text, 96 /* backtick */)); + switch (node2.kind) { case 16 /* TemplateHead */: return "`" + rawText + "${"; case 17 /* TemplateMiddle */: @@ -171035,7 +172351,7 @@ function provideInlayHints(context) { } } } - return node.text; + return node2.text; } } function isUndefined(name) { @@ -171181,7 +172497,7 @@ function getJsDocCommentsFromDeclarations(declarations, checker) { return flatten(intersperse(parts, [lineBreakPart()])); } function isIdenticalListOfDisplayParts(parts1, parts2) { - return arraysEqual(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text); + return arrayIsEqualTo(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text); } function getCommentHavingNodes(declaration) { switch (declaration.kind) { @@ -171544,9 +172860,10 @@ ${content} parsedNodes.push({ sourceFile: sourceFile2, body: bod }); } } - const { body } = parsedNodes.sort( + parsedNodes.sort( (a, b) => a.sourceFile.parseDiagnostics.length - b.sourceFile.parseDiagnostics.length - )[0]; + ); + const { body } = parsedNodes[0]; return body; } function placeNodeGroup(originalFile, changeTracker, changes, focusLocations) { @@ -171695,7 +173012,6 @@ var ts_OrganizeImports_exports = {}; __export(ts_OrganizeImports_exports, { compareImportsOrRequireStatements: () => compareImportsOrRequireStatements, compareModuleSpecifiers: () => compareModuleSpecifiers2, - getDetectionLists: () => getDetectionLists, getImportDeclarationInsertionIndex: () => getImportDeclarationInsertionIndex, getImportSpecifierInsertionIndex: () => getImportSpecifierInsertionIndex, getNamedImportSpecifierComparerWithDetection: () => getNamedImportSpecifierComparerWithDetection, @@ -171751,7 +173067,7 @@ function organizeImports(sourceFile, formatContext, host, program, preferences, } setEmitFlags(oldImportDecls[0], 1024 /* NoLeadingComments */); const oldImportGroups = shouldCombine ? group(oldImportDecls, (importDecl) => getExternalModuleName2(importDecl.moduleSpecifier)) : [oldImportDecls]; - const sortedImportGroups = shouldSort ? stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiersWorker(group1[0].moduleSpecifier, group2[0].moduleSpecifier, comparer.moduleSpecifierComparer ?? defaultComparer)) : oldImportGroups; + const sortedImportGroups = shouldSort ? toSorted(oldImportGroups, (group1, group2) => compareModuleSpecifiersWorker(group1[0].moduleSpecifier, group2[0].moduleSpecifier, comparer.moduleSpecifierComparer ?? defaultComparer)) : oldImportGroups; const newImportDecls = flatMap(sortedImportGroups, (importGroup) => getExternalModuleName2(importGroup[0].moduleSpecifier) || importGroup[0].moduleSpecifier === void 0 ? coalesce(importGroup) : importGroup); if (newImportDecls.length === 0) { changeTracker.deleteNodes( @@ -171786,7 +173102,7 @@ function organizeImports(sourceFile, formatContext, host, program, preferences, const processImportsOfSameModuleSpecifier = (importGroup) => { if (shouldRemove) importGroup = removeUnusedImports(importGroup, sourceFile, program); if (shouldCombine) importGroup = coalesceImportsWorker(importGroup, detectedModuleCaseComparer, specifierComparer, sourceFile); - if (shouldSort) importGroup = stableSort(importGroup, (s1, s2) => compareImportsOrRequireStatements(s1, s2, detectedModuleCaseComparer)); + if (shouldSort) importGroup = toSorted(importGroup, (s1, s2) => compareImportsOrRequireStatements(s1, s2, detectedModuleCaseComparer)); return importGroup; }; organizeDeclsWorker(oldImportDecls, processImportsOfSameModuleSpecifier); @@ -171962,7 +173278,7 @@ function coalesceImportsWorker(importGroup, comparer, specifierComparer, sourceF const importGroupsByAttributes = groupBy(importGroup, (decl) => { if (decl.attributes) { let attrs = decl.attributes.token + " "; - for (const x of sort(decl.attributes.elements, (x2, y) => compareStringsCaseSensitive(x2.name.text, y.name.text))) { + for (const x of toSorted(decl.attributes.elements, (x2, y) => compareStringsCaseSensitive(x2.name.text, y.name.text))) { attrs += x.name.text + ":"; attrs += isStringLiteralLike(x.value) ? `"${x.value.text}"` : x.value.getText() + " "; } @@ -171987,7 +173303,7 @@ function coalesceImportsWorker(importGroup, comparer, specifierComparer, sourceF ); continue; } - const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) => comparer(i1.importClause.namedBindings.name.text, i2.importClause.namedBindings.name.text)); + const sortedNamespaceImports = toSorted(namespaceImports, (i1, i2) => comparer(i1.importClause.namedBindings.name.text, i2.importClause.namedBindings.name.text)); for (const namespaceImport of sortedNamespaceImports) { coalescedImports.push( updateImportDeclarationAndClause( @@ -172022,7 +173338,7 @@ function coalesceImportsWorker(importGroup, comparer, specifierComparer, sourceF } newImportSpecifiers.push(...getNewImportSpecifiers(namedImports)); const sortedImportSpecifiers = factory.createNodeArray( - stableSort(newImportSpecifiers, specifierComparer), + toSorted(newImportSpecifiers, specifierComparer), firstNamedImport == null ? void 0 : firstNamedImport.importClause.namedBindings.elements.hasTrailingComma ); const newNamedImports = sortedImportSpecifiers.length === 0 ? newDefaultImport ? void 0 : factory.createNamedImports(emptyArray) : firstNamedImport ? factory.updateNamedImports(firstNamedImport.importClause.namedBindings, sortedImportSpecifiers) : factory.createNamedImports(sortedImportSpecifiers); @@ -172070,7 +173386,7 @@ function coalesceExportsWorker(exportGroup, specifierComparer) { } const newExportSpecifiers = []; newExportSpecifiers.push(...flatMap(exportGroup2, (i) => i.exportClause && isNamedExports(i.exportClause) ? i.exportClause.elements : emptyArray)); - const sortedExportSpecifiers = stableSort(newExportSpecifiers, specifierComparer); + const sortedExportSpecifiers = toSorted(newExportSpecifiers, specifierComparer); const exportDecl = exportGroup2[0]; coalescedExports.push( factory.updateExportDeclaration( @@ -172148,7 +173464,7 @@ function hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier) { return isString(moduleSpecifierText) && some(sourceFile.moduleAugmentations, (moduleName) => isStringLiteral(moduleName) && moduleName.text === moduleSpecifierText); } function getNewImportSpecifiers(namedImports) { - return flatMap(namedImports, (namedImport) => map(tryGetNamedBindingElements(namedImport), (importSpecifier) => importSpecifier.name && importSpecifier.propertyName && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText ? factory.updateImportSpecifier( + return flatMap(namedImports, (namedImport) => map(tryGetNamedBindingElements(namedImport), (importSpecifier) => importSpecifier.name && importSpecifier.propertyName && moduleExportNameTextEscaped(importSpecifier.name) === moduleExportNameTextEscaped(importSpecifier.propertyName) ? factory.updateImportSpecifier( importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ @@ -172358,7 +173674,8 @@ function collectElements(sourceFile, cancellationToken) { const res = []; addNodeOutliningSpans(sourceFile, cancellationToken, res); addRegionOutliningSpans(sourceFile, res); - return res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); + res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); + return res; } function addNodeOutliningSpans(sourceFile, cancellationToken, out) { let depthRemaining = 40; @@ -172424,11 +173741,11 @@ function addRegionOutliningSpans(sourceFile, out) { for (const currentLineStart of lineStarts) { const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart); const lineText = sourceFile.text.substring(currentLineStart, lineEnd); - const result = isRegionDelimiter(lineText); + const result = parseRegionDelimiter(lineText); if (!result || isInComment(sourceFile, currentLineStart)) { continue; } - if (!result[1]) { + if (result.isStart) { const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); regions.push(createOutliningSpan( span, @@ -172436,7 +173753,7 @@ function addRegionOutliningSpans(sourceFile, out) { span, /*autoCollapse*/ false, - result[2] || "#region" + result.name || "#region" )); } else { const region = regions.pop(); @@ -172448,14 +173765,18 @@ function addRegionOutliningSpans(sourceFile, out) { } } } -var regionDelimiterRegExp = /^#(end)?region(?:\s+(.*))?(?:\r)?$/; -function isRegionDelimiter(lineText) { +var regionDelimiterRegExp = /^#(end)?region(.*)\r?$/; +function parseRegionDelimiter(lineText) { lineText = lineText.trimStart(); if (!startsWith(lineText, "//")) { return null; } lineText = lineText.slice(2).trim(); - return regionDelimiterRegExp.exec(lineText); + const result = regionDelimiterRegExp.exec(lineText); + if (result) { + return { isStart: !result[1], name: result[2].trim() }; + } + return void 0; } function addOutliningForLeadingCommentsForPos(pos, sourceFile, cancellationToken, out) { const comments = getLeadingCommentRanges(sourceFile.text, pos); @@ -172469,7 +173790,7 @@ function addOutliningForLeadingCommentsForPos(pos, sourceFile, cancellationToken switch (kind) { case 2 /* SingleLineCommentTrivia */: const commentText = sourceText.slice(pos2, end); - if (isRegionDelimiter(commentText)) { + if (parseRegionDelimiter(commentText)) { combineAndAddMultipleSingleLineComments(); singleLineCommentCount = 0; break; @@ -173001,9 +174322,6 @@ function getArgumentOrParameterListInfo(node, position, sourceFile, checker) { if (!info) return void 0; const { list, argumentIndex } = info; const argumentCount = getArgumentCount(checker, list); - if (argumentIndex !== 0) { - Debug.assertLessThan(argumentIndex, argumentCount); - } const argumentsSpan = getApplicableSpanForArguments(list, sourceFile); return { list, argumentIndex, argumentCount, argumentsSpan }; } @@ -173276,9 +174594,6 @@ function createSignatureHelpItems(candidates, resolvedSignature, { isTypeParamet void 0 ) : emptyArray; const items = map(candidates, (candidateSignature) => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile)); - if (argumentIndex !== 0) { - Debug.assertLessThan(argumentIndex, argumentCount); - } let selectedItemIndex = 0; let itemsSeen = 0; for (let i = 0; i < items.length; i++) { @@ -175092,7 +176407,7 @@ var changesToText; function getTextChangesFromChanges(changes, newLineCharacter, formatContext, validate) { return mapDefined(group(changes, (c) => c.sourceFile.path), (changesInFile) => { const sourceFile = changesInFile[0].sourceFile; - const normalized = stableSort(changesInFile, (a, b) => a.range.pos - b.range.pos || a.range.end - b.range.end); + const normalized = toSorted(changesInFile, (a, b) => a.range.pos - b.range.pos || a.range.end - b.range.end); for (let i = 0; i < normalized.length - 1; i++) { Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`); } @@ -178340,16 +179655,17 @@ function pasteEditsProvider(targetFile, pastedText, pasteLocations, copiedFrom, function pasteEdits(targetFile, pastedText, pasteLocations, copiedFrom, host, preferences, formatContext, cancellationToken, changes) { let actualPastedText; if (pastedText.length !== pasteLocations.length) { - actualPastedText = pastedText.length === 1 ? pastedText : [pastedText.join("\n")]; + actualPastedText = pastedText.length === 1 ? pastedText[0] : pastedText.join(getNewLineOrDefaultFromHost(formatContext.host, formatContext.options)); } const statements = []; let newText = targetFile.text; for (let i = pasteLocations.length - 1; i >= 0; i--) { const { pos, end } = pasteLocations[i]; - newText = actualPastedText ? newText.slice(0, pos) + actualPastedText[0] + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); + newText = actualPastedText ? newText.slice(0, pos) + actualPastedText + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); } + let importAdder; Debug.checkDefined(host.runWithTemporaryFileUpdate).call(host, targetFile.fileName, newText, (updatedProgram, originalProgram, updatedFile) => { - const importAdder = ts_codefix_exports.createImportAdder(updatedFile, updatedProgram, preferences, host); + importAdder = ts_codefix_exports.createImportAdder(updatedFile, updatedProgram, preferences, host); if (copiedFrom == null ? void 0 : copiedFrom.range) { Debug.assert(copiedFrom.range.length === pastedText.length); copiedFrom.range.forEach((copy) => { @@ -178362,7 +179678,7 @@ function pasteEdits(targetFile, pastedText, pasteLocations, copiedFrom, host, pr } statements.push(...statementsInSourceFile.slice(startNodeIndex, endNodeIndex === -1 ? statementsInSourceFile.length : endNodeIndex + 1)); }); - const usage = getUsageInfo(copiedFrom.file, statements, originalProgram.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram.getTypeChecker())); + const usage = getUsageInfo(copiedFrom.file, statements, originalProgram.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram.getTypeChecker()), { pos: copiedFrom.range[0].pos, end: copiedFrom.range[copiedFrom.range.length - 1].end }); Debug.assertIsDefined(originalProgram); const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFile.fileName, originalProgram, host, !!copiedFrom.file.commonJsModuleIndicator); addExportsInOldFile(copiedFrom.file, usage.targetFileImportsFromOldFile, changes, useEsModuleSyntax); @@ -178376,31 +179692,49 @@ function pasteEdits(targetFile, pastedText, pasteLocations, copiedFrom, host, pr preferences, formatContext }; - forEachChild(updatedFile, function cb(node) { - if (isIdentifier(node) && !(originalProgram == null ? void 0 : originalProgram.getTypeChecker().resolveName( - node.text, - node, - -1 /* All */, - /*excludeGlobals*/ - false - ))) { - importAdder.addImportForUnresolvedIdentifier( - context, + let offset = 0; + pasteLocations.forEach((location, i) => { + const oldTextLength = location.end - location.pos; + const textToBePasted = actualPastedText ?? pastedText[i]; + const startPos = location.pos + offset; + const endPos = startPos + textToBePasted.length; + const range = { pos: startPos, end: endPos }; + offset += textToBePasted.length - oldTextLength; + const enclosingNode = findAncestor( + getTokenAtPosition(context.sourceFile, range.pos), + (ancestorNode) => rangeContainsRange(ancestorNode, range) + ); + if (!enclosingNode) return; + forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { + const isImportCandidate = isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && !(updatedProgram == null ? void 0 : updatedProgram.getTypeChecker().resolveName( + node.text, node, - /*useAutoImportProvider*/ - true - ); - } - node.forEachChild(cb); + -1 /* All */, + /*excludeGlobals*/ + false + )); + if (isImportCandidate) { + return importAdder.addImportForUnresolvedIdentifier( + context, + node, + /*useAutoImportProvider*/ + true + ); + } + node.forEachChild(importUnresolvedIdentifiers); + }); }); } importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences)); }); + if (!importAdder.hasFixes()) { + return; + } pasteLocations.forEach((paste, i) => { changes.replaceRangeWithText( targetFile, { pos: paste.pos, end: paste.end }, - actualPastedText ? actualPastedText[0] : pastedText[i] + actualPastedText ?? pastedText[i] ); }); } @@ -178458,7 +179792,6 @@ __export(ts_exports2, { GoToDefinition: () => ts_GoToDefinition_exports, HighlightSpanKind: () => HighlightSpanKind, IdentifierNameMap: () => IdentifierNameMap, - IdentifierNameMultiMap: () => IdentifierNameMultiMap, ImportKind: () => ImportKind, ImportsNotUsedAsValues: () => ImportsNotUsedAsValues, IndentStyle: () => IndentStyle, @@ -178469,6 +179802,7 @@ __export(ts_exports2, { InlayHintKind: () => InlayHintKind2, InlayHints: () => ts_InlayHints_exports, InternalEmitFlags: () => InternalEmitFlags, + InternalNodeBuilderFlags: () => InternalNodeBuilderFlags, InternalSymbolName: () => InternalSymbolName, IntersectionFlags: () => IntersectionFlags, InvalidatedProjectKind: () => InvalidatedProjectKind, @@ -178515,6 +179849,7 @@ __export(ts_exports2, { PollingInterval: () => PollingInterval, PollingWatchKind: () => PollingWatchKind, PragmaKindFlags: () => PragmaKindFlags, + PredicateSemantics: () => PredicateSemantics, PrivateIdentifierKind: () => PrivateIdentifierKind, ProcessLevel: () => ProcessLevel, ProgramUpdateLevel: () => ProgramUpdateLevel, @@ -178545,7 +179880,6 @@ __export(ts_exports2, { SymbolFlags: () => SymbolFlags, SymbolFormatFlags: () => SymbolFormatFlags, SyntaxKind: () => SyntaxKind, - SyntheticSymbolKind: () => SyntheticSymbolKind, Ternary: () => Ternary, ThrottledCancellationToken: () => ThrottledCancellationToken, TokenClass: () => TokenClass, @@ -178568,7 +179902,6 @@ __export(ts_exports2, { WatchLogLevel: () => WatchLogLevel, WatchType: () => WatchType, accessPrivateIdentifier: () => accessPrivateIdentifier, - addDisposableResourceHelper: () => addDisposableResourceHelper, addEmitFlags: () => addEmitFlags, addEmitHelper: () => addEmitHelper, addEmitHelpers: () => addEmitHelpers, @@ -178591,23 +179924,15 @@ __export(ts_exports2, { arrayFrom: () => arrayFrom, arrayIsEqualTo: () => arrayIsEqualTo, arrayIsHomogeneous: () => arrayIsHomogeneous, - arrayIsSorted: () => arrayIsSorted, arrayOf: () => arrayOf, arrayReverseIterator: () => arrayReverseIterator, arrayToMap: () => arrayToMap, arrayToMultiMap: () => arrayToMultiMap, arrayToNumericMap: () => arrayToNumericMap, - arraysEqual: () => arraysEqual, assertType: () => assertType, assign: () => assign, - assignHelper: () => assignHelper, - asyncDelegator: () => asyncDelegator, - asyncGeneratorHelper: () => asyncGeneratorHelper, asyncSuperHelper: () => asyncSuperHelper, - asyncValues: () => asyncValues, attachFileToDiagnostics: () => attachFileToDiagnostics, - awaitHelper: () => awaitHelper, - awaiterHelper: () => awaiterHelper, base64decode: () => base64decode, base64encode: () => base64encode, binarySearch: () => binarySearch, @@ -178620,6 +179945,7 @@ __export(ts_exports2, { buildOverload: () => buildOverload, bundlerModuleNameResolver: () => bundlerModuleNameResolver, canBeConvertedToAsync: () => canBeConvertedToAsync, + canEmitTsBuildInfo: () => canEmitTsBuildInfo, canHaveDecorators: () => canHaveDecorators, canHaveExportModifier: () => canHaveExportModifier, canHaveFlowNode: () => canHaveFlowNode, @@ -178630,8 +179956,9 @@ __export(ts_exports2, { canHaveJSDoc: () => canHaveJSDoc, canHaveLocals: () => canHaveLocals, canHaveModifiers: () => canHaveModifiers, + canHaveModuleSpecifier: () => canHaveModuleSpecifier, canHaveSymbol: () => canHaveSymbol, - canIncludeBindAndCheckDiagnsotics: () => canIncludeBindAndCheckDiagnsotics, + canIncludeBindAndCheckDiagnostics: () => canIncludeBindAndCheckDiagnostics, canJsonReportNoInputFiles: () => canJsonReportNoInputFiles, canProduceDiagnostics: () => canProduceDiagnostics, canUsePropertyAccess: () => canUsePropertyAccess, @@ -178648,16 +179975,13 @@ __export(ts_exports2, { changeFullExtension: () => changeFullExtension, changesAffectModuleResolution: () => changesAffectModuleResolution, changesAffectingProgramStructure: () => changesAffectingProgramStructure, - characterToRegularExpressionFlag: () => characterToRegularExpressionFlag, + characterCodeToRegularExpressionFlag: () => characterCodeToRegularExpressionFlag, childIsDecorated: () => childIsDecorated, classElementOrClassElementParameterIsDecorated: () => classElementOrClassElementParameterIsDecorated, classHasClassThisAssignment: () => classHasClassThisAssignment, classHasDeclaredOrExplicitlyAssignedName: () => classHasDeclaredOrExplicitlyAssignedName, classHasExplicitlyAssignedName: () => classHasExplicitlyAssignedName, classOrConstructorParameterIsDecorated: () => classOrConstructorParameterIsDecorated, - classPrivateFieldGetHelper: () => classPrivateFieldGetHelper, - classPrivateFieldInHelper: () => classPrivateFieldInHelper, - classPrivateFieldSetHelper: () => classPrivateFieldSetHelper, classicNameResolver: () => classicNameResolver, classifier: () => ts_classifier_exports, cleanExtendedConfigCache: () => cleanExtendedConfigCache, @@ -178665,7 +179989,6 @@ __export(ts_exports2, { clearMap: () => clearMap, clearSharedExtendedConfigFileWatcher: () => clearSharedExtendedConfigFileWatcher, climbPastPropertyAccess: () => climbPastPropertyAccess, - climbPastPropertyOrElementAccess: () => climbPastPropertyOrElementAccess, clone: () => clone, cloneCompilerOptions: () => cloneCompilerOptions, closeFileWatcher: () => closeFileWatcher, @@ -178678,12 +180001,10 @@ __export(ts_exports2, { commandLineOptionOfCustomType: () => commandLineOptionOfCustomType, commentPragmas: () => commentPragmas, commonOptionsWithBuild: () => commonOptionsWithBuild, - commonPackageFolders: () => commonPackageFolders, compact: () => compact, compareBooleans: () => compareBooleans, compareDataObjects: () => compareDataObjects, compareDiagnostics: () => compareDiagnostics, - compareDiagnosticsSkipRelatedInformation: () => compareDiagnosticsSkipRelatedInformation, compareEmitHelpers: () => compareEmitHelpers, compareNumberOfDirectorySeparators: () => compareNumberOfDirectorySeparators, comparePaths: () => comparePaths, @@ -178697,26 +180018,21 @@ __export(ts_exports2, { compareStringsCaseSensitiveUI: () => compareStringsCaseSensitiveUI, compareTextSpans: () => compareTextSpans, compareValues: () => compareValues, - compileOnSaveCommandLineOption: () => compileOnSaveCommandLineOption, compilerOptionsAffectDeclarationPath: () => compilerOptionsAffectDeclarationPath, compilerOptionsAffectEmit: () => compilerOptionsAffectEmit, compilerOptionsAffectSemanticDiagnostics: () => compilerOptionsAffectSemanticDiagnostics, compilerOptionsDidYouMeanDiagnostics: () => compilerOptionsDidYouMeanDiagnostics, compilerOptionsIndicateEsModules: () => compilerOptionsIndicateEsModules, - compose: () => compose, computeCommonSourceDirectoryOfFilenames: () => computeCommonSourceDirectoryOfFilenames, computeLineAndCharacterOfPosition: () => computeLineAndCharacterOfPosition, computeLineOfPosition: () => computeLineOfPosition, computeLineStarts: () => computeLineStarts, computePositionOfLineAndCharacter: () => computePositionOfLineAndCharacter, - computeSignature: () => computeSignature, computeSignatureWithDiagnostics: () => computeSignatureWithDiagnostics, computeSuggestionDiagnostics: () => computeSuggestionDiagnostics, computedOptions: () => computedOptions, concatenate: () => concatenate, concatenateDiagnosticMessageChains: () => concatenateDiagnosticMessageChains, - configDirTemplateSubstitutionOptions: () => configDirTemplateSubstitutionOptions, - configDirTemplateSubstitutionWatchOptions: () => configDirTemplateSubstitutionWatchOptions, consumesNodeCoreModules: () => consumesNodeCoreModules, contains: () => contains, containsIgnoredPath: () => containsIgnoredPath, @@ -178747,16 +180063,11 @@ __export(ts_exports2, { createAccessorPropertySetRedirector: () => createAccessorPropertySetRedirector, createBaseNodeFactory: () => createBaseNodeFactory, createBinaryExpressionTrampoline: () => createBinaryExpressionTrampoline, - createBindingHelper: () => createBindingHelper, - createBuildInfo: () => createBuildInfo, createBuilderProgram: () => createBuilderProgram, - createBuilderProgramUsingProgramBuildInfo: () => createBuilderProgramUsingProgramBuildInfo, + createBuilderProgramUsingIncrementalBuildInfo: () => createBuilderProgramUsingIncrementalBuildInfo, createBuilderStatusReporter: () => createBuilderStatusReporter, - createCacheWithRedirects: () => createCacheWithRedirects, createCacheableExportInfoMap: () => createCacheableExportInfoMap, createCachedDirectoryStructureHost: () => createCachedDirectoryStructureHost, - createClassNamedEvaluationHelperBlock: () => createClassNamedEvaluationHelperBlock, - createClassThisAssignmentBlock: () => createClassThisAssignmentBlock, createClassifier: () => createClassifier, createCommentDirectivesMap: () => createCommentDirectivesMap, createCompilerDiagnostic: () => createCompilerDiagnostic, @@ -178808,6 +180119,7 @@ __export(ts_exports2, { createMemberAccessForPropertyName: () => createMemberAccessForPropertyName, createModeAwareCache: () => createModeAwareCache, createModeAwareCacheKey: () => createModeAwareCacheKey, + createModeMismatchDetails: () => createModeMismatchDetails, createModuleNotFoundChain: () => createModuleNotFoundChain, createModuleResolutionCache: () => createModuleResolutionCache, createModuleResolutionLoader: () => createModuleResolutionLoader, @@ -178878,9 +180190,7 @@ __export(ts_exports2, { declarationNameToString: () => declarationNameToString, decodeMappings: () => decodeMappings, decodedTextSpanIntersectsWith: () => decodedTextSpanIntersectsWith, - decorateHelper: () => decorateHelper, deduplicate: () => deduplicate, - defaultIncludeSpec: () => defaultIncludeSpec, defaultInitCompilerOptions: () => defaultInitCompilerOptions, defaultMaximumTruncationLength: () => defaultMaximumTruncationLength, deno: () => deno_exports, @@ -178892,27 +180202,22 @@ __export(ts_exports2, { displayPart: () => displayPart, displayPartsToString: () => displayPartsToString, disposeEmitNodes: () => disposeEmitNodes, - disposeResourcesHelper: () => disposeResourcesHelper, documentSpansEqual: () => documentSpansEqual, dumpTracingLegend: () => dumpTracingLegend, elementAt: () => elementAt, elideNodes: () => elideNodes, - emitComments: () => emitComments, emitDetachedComments: () => emitDetachedComments, emitFiles: () => emitFiles, emitFilesAndReportErrors: () => emitFilesAndReportErrors, emitFilesAndReportErrorsAndGetExitStatus: () => emitFilesAndReportErrorsAndGetExitStatus, emitModuleKindIsNonNodeESM: () => emitModuleKindIsNonNodeESM, emitNewLineBeforeLeadingCommentOfPosition: () => emitNewLineBeforeLeadingCommentOfPosition, - emitNewLineBeforeLeadingComments: () => emitNewLineBeforeLeadingComments, - emitNewLineBeforeLeadingCommentsOfPosition: () => emitNewLineBeforeLeadingCommentsOfPosition, emitResolverSkipsTypeChecking: () => emitResolverSkipsTypeChecking, emitSkippedWithNoDiagnostics: () => emitSkippedWithNoDiagnostics, emptyArray: () => emptyArray, emptyFileSystemEntries: () => emptyFileSystemEntries, emptyMap: () => emptyMap, emptyOptions: () => emptyOptions, - emptySet: () => emptySet, endsWith: () => endsWith, ensurePathIsNonModuleName: () => ensurePathIsNonModuleName, ensureScriptKind: () => ensureScriptKind, @@ -178923,7 +180228,6 @@ __export(ts_exports2, { equateStringsCaseInsensitive: () => equateStringsCaseInsensitive, equateStringsCaseSensitive: () => equateStringsCaseSensitive, equateValues: () => equateValues, - esDecorateHelper: () => esDecorateHelper, escapeJsxAttributeString: () => escapeJsxAttributeString, escapeLeadingUnderscores: () => escapeLeadingUnderscores, escapeNonAsciiString: () => escapeNonAsciiString, @@ -178937,15 +180241,14 @@ __export(ts_exports2, { explainFiles: () => explainFiles, explainIfFileIsRedirectAndImpliedFormat: () => explainIfFileIsRedirectAndImpliedFormat, exportAssignmentIsAlias: () => exportAssignmentIsAlias, - exportStarHelper: () => exportStarHelper, expressionResultIsUnused: () => expressionResultIsUnused, extend: () => extend, - extendsHelper: () => extendsHelper, extensionFromPath: () => extensionFromPath, extensionIsTS: () => extensionIsTS, extensionsNotSupportingExtensionlessResolution: () => extensionsNotSupportingExtensionlessResolution, externalHelpersModuleNameText: () => externalHelpersModuleNameText, factory: () => factory, + fileContainsPackageImport: () => fileContainsPackageImport, fileExtensionIs: () => fileExtensionIs, fileExtensionIsOneOf: () => fileExtensionIsOneOf, fileIncludeReasonToDiagnostics: () => fileIncludeReasonToDiagnostics, @@ -178967,7 +180270,6 @@ __export(ts_exports2, { findLast: () => findLast, findLastIndex: () => findLastIndex, findListItemInfo: () => findListItemInfo, - findMap: () => findMap, findModifier: () => findModifier, findNextToken: () => findNextToken, findPackageJson: () => findPackageJson, @@ -179015,7 +180317,6 @@ __export(ts_exports2, { forEachTsConfigPropArray: () => forEachTsConfigPropArray, forEachUnique: () => forEachUnique, forEachYieldExpression: () => forEachYieldExpression, - forSomeAncestorDirectory: () => forSomeAncestorDirectory, formatColorAndReset: () => formatColorAndReset, formatDiagnostic: () => formatDiagnostic, formatDiagnostics: () => formatDiagnostics, @@ -179026,11 +180327,8 @@ __export(ts_exports2, { formatMessage: () => formatMessage, formatStringFromArgs: () => formatStringFromArgs, formatting: () => ts_formatting_exports, - fullTripleSlashAMDReferencePathRegEx: () => fullTripleSlashAMDReferencePathRegEx, - fullTripleSlashReferencePathRegEx: () => fullTripleSlashReferencePathRegEx, generateDjb2Hash: () => generateDjb2Hash, generateTSConfig: () => generateTSConfig, - generatorHelper: () => generatorHelper, getAdjustedReferenceLocation: () => getAdjustedReferenceLocation, getAdjustedRenameLocation: () => getAdjustedRenameLocation, getAliasDeclarationFromName: () => getAliasDeclarationFromName, @@ -179049,7 +180347,6 @@ __export(ts_exports2, { getAreDeclarationMapsEnabled: () => getAreDeclarationMapsEnabled, getAssignedExpandoInitializer: () => getAssignedExpandoInitializer, getAssignedName: () => getAssignedName, - getAssignedNameOfIdentifier: () => getAssignedNameOfIdentifier, getAssignmentDeclarationKind: () => getAssignmentDeclarationKind, getAssignmentDeclarationPropertyAccessKind: () => getAssignmentDeclarationPropertyAccessKind, getAssignmentTargetKind: () => getAssignmentTargetKind, @@ -179090,7 +180387,6 @@ __export(ts_exports2, { getContainingObjectLiteralElement: () => getContainingObjectLiteralElement, getContextualTypeFromParent: () => getContextualTypeFromParent, getContextualTypeFromParentOrAncestorTypeNode: () => getContextualTypeFromParentOrAncestorTypeNode, - getCurrentTime: () => getCurrentTime, getDeclarationDiagnostics: () => getDeclarationDiagnostics, getDeclarationEmitExtensionForPath: () => getDeclarationEmitExtensionForPath, getDeclarationEmitOutputFilePath: () => getDeclarationEmitOutputFilePath, @@ -179108,6 +180404,7 @@ __export(ts_exports2, { getDefaultLibFilePath: () => getDefaultLibFilePath, getDefaultLikeExportInfo: () => getDefaultLikeExportInfo, getDefaultLikeExportNameFromDeclaration: () => getDefaultLikeExportNameFromDeclaration, + getDefaultResolutionModeForFileWorker: () => getDefaultResolutionModeForFileWorker, getDiagnosticText: () => getDiagnosticText, getDiagnosticsWithinSpan: () => getDiagnosticsWithinSpan, getDirectoryPath: () => getDirectoryPath, @@ -179138,6 +180435,7 @@ __export(ts_exports2, { getEmitFlags: () => getEmitFlags, getEmitHelpers: () => getEmitHelpers, getEmitModuleDetectionKind: () => getEmitModuleDetectionKind, + getEmitModuleFormatOfFileWorker: () => getEmitModuleFormatOfFileWorker, getEmitModuleKind: () => getEmitModuleKind, getEmitModuleResolutionKind: () => getEmitModuleResolutionKind, getEmitScriptTarget: () => getEmitScriptTarget, @@ -179188,11 +180486,11 @@ __export(ts_exports2, { getIdentifierGeneratedImportReference: () => getIdentifierGeneratedImportReference, getIdentifierTypeArguments: () => getIdentifierTypeArguments, getImmediatelyInvokedFunctionExpression: () => getImmediatelyInvokedFunctionExpression, + getImpliedNodeFormatForEmitWorker: () => getImpliedNodeFormatForEmitWorker, getImpliedNodeFormatForFile: () => getImpliedNodeFormatForFile, getImpliedNodeFormatForFileWorker: () => getImpliedNodeFormatForFileWorker, getImportNeedsImportDefaultHelper: () => getImportNeedsImportDefaultHelper, getImportNeedsImportStarHelper: () => getImportNeedsImportStarHelper, - getIndentSize: () => getIndentSize, getIndentString: () => getIndentString, getInferredLibraryNameResolveFrom: () => getInferredLibraryNameResolveFrom, getInitializedVariables: () => getInitializedVariables, @@ -179201,6 +180499,7 @@ __export(ts_exports2, { getInterfaceBaseTypeNodes: () => getInterfaceBaseTypeNodes, getInternalEmitFlags: () => getInternalEmitFlags, getInvokedExpression: () => getInvokedExpression, + getIsFileExcluded: () => getIsFileExcluded, getIsolatedModules: () => getIsolatedModules, getJSDocAugmentsTag: () => getJSDocAugmentsTag, getJSDocClassTag: () => getJSDocClassTag, @@ -179229,7 +180528,6 @@ __export(ts_exports2, { getJSDocSatisfiesExpressionType: () => getJSDocSatisfiesExpressionType, getJSDocSatisfiesTag: () => getJSDocSatisfiesTag, getJSDocTags: () => getJSDocTags, - getJSDocTagsNoCache: () => getJSDocTagsNoCache, getJSDocTemplateTag: () => getJSDocTemplateTag, getJSDocThisTag: () => getJSDocThisTag, getJSDocType: () => getJSDocType, @@ -179253,7 +180551,6 @@ __export(ts_exports2, { getLineAndCharacterOfPosition: () => getLineAndCharacterOfPosition, getLineInfo: () => getLineInfo, getLineOfLocalPosition: () => getLineOfLocalPosition, - getLineOfLocalPositionFromLineMap: () => getLineOfLocalPositionFromLineMap, getLineStartPositionForPosition: () => getLineStartPositionForPosition, getLineStarts: () => getLineStarts, getLinesBetweenPositionAndNextNonWhitespaceCharacter: () => getLinesBetweenPositionAndNextNonWhitespaceCharacter, @@ -179295,7 +180592,6 @@ __export(ts_exports2, { getNameOfScriptTarget: () => getNameOfScriptTarget, getNameOrArgument: () => getNameOrArgument, getNameTable: () => getNameTable, - getNamesForExportedSymbol: () => getNamesForExportedSymbol, getNamespaceDeclarationNode: () => getNamespaceDeclarationNode, getNewLineCharacter: () => getNewLineCharacter, getNewLineKind: () => getNewLineKind, @@ -179312,49 +180608,43 @@ __export(ts_exports2, { getNonAssignmentOperatorForCompoundAssignment: () => getNonAssignmentOperatorForCompoundAssignment, getNonAugmentationDeclaration: () => getNonAugmentationDeclaration, getNonDecoratorTokenPosOfNode: () => getNonDecoratorTokenPosOfNode, + getNonIncrementalBuildInfoRoots: () => getNonIncrementalBuildInfoRoots, + getNonModifierTokenPosOfNode: () => getNonModifierTokenPosOfNode, getNormalizedAbsolutePath: () => getNormalizedAbsolutePath, getNormalizedAbsolutePathWithoutRoot: () => getNormalizedAbsolutePathWithoutRoot, getNormalizedPathComponents: () => getNormalizedPathComponents, getObjectFlags: () => getObjectFlags, - getOperator: () => getOperator, getOperatorAssociativity: () => getOperatorAssociativity, getOperatorPrecedence: () => getOperatorPrecedence, getOptionFromName: () => getOptionFromName, getOptionsForLibraryResolution: () => getOptionsForLibraryResolution, getOptionsNameMap: () => getOptionsNameMap, getOrCreateEmitNode: () => getOrCreateEmitNode, - getOrCreateExternalHelpersModuleNameIfNeeded: () => getOrCreateExternalHelpersModuleNameIfNeeded, getOrUpdate: () => getOrUpdate, getOriginalNode: () => getOriginalNode, getOriginalNodeId: () => getOriginalNodeId, - getOriginalSourceFile: () => getOriginalSourceFile, getOutputDeclarationFileName: () => getOutputDeclarationFileName, getOutputDeclarationFileNameWorker: () => getOutputDeclarationFileNameWorker, getOutputExtension: () => getOutputExtension, getOutputFileNames: () => getOutputFileNames, getOutputJSFileNameWorker: () => getOutputJSFileNameWorker, getOutputPathsFor: () => getOutputPathsFor, - getOutputPathsForBundle: () => getOutputPathsForBundle, getOwnEmitOutputFilePath: () => getOwnEmitOutputFilePath, getOwnKeys: () => getOwnKeys, getOwnValues: () => getOwnValues, - getPackageJsonInfo: () => getPackageJsonInfo, getPackageJsonTypesVersionsPaths: () => getPackageJsonTypesVersionsPaths, - getPackageJsonsVisibleToFile: () => getPackageJsonsVisibleToFile, getPackageNameFromTypesPackageName: () => getPackageNameFromTypesPackageName, getPackageScopeForPath: () => getPackageScopeForPath, getParameterSymbolFromJSDoc: () => getParameterSymbolFromJSDoc, - getParameterTypeNode: () => getParameterTypeNode, getParentNodeInSpan: () => getParentNodeInSpan, getParseTreeNode: () => getParseTreeNode, getParsedCommandLineOfConfigFile: () => getParsedCommandLineOfConfigFile, getPathComponents: () => getPathComponents, - getPathComponentsRelativeTo: () => getPathComponentsRelativeTo, getPathFromPathComponents: () => getPathFromPathComponents, getPathUpdater: () => getPathUpdater, getPathsBasePath: () => getPathsBasePath, getPatternFromSpec: () => getPatternFromSpec, - getPendingEmitKind: () => getPendingEmitKind, + getPendingEmitKindWithSeen: () => getPendingEmitKindWithSeen, getPositionOfLineAndCharacter: () => getPositionOfLineAndCharacter, getPossibleGenericSignatures: () => getPossibleGenericSignatures, getPossibleOriginalInputExtensionForExtension: () => getPossibleOriginalInputExtensionForExtension, @@ -179367,7 +180657,6 @@ __export(ts_exports2, { getPropertyArrayElementValue: () => getPropertyArrayElementValue, getPropertyAssignmentAliasLikeExpression: () => getPropertyAssignmentAliasLikeExpression, getPropertyNameForPropertyNameNode: () => getPropertyNameForPropertyNameNode, - getPropertyNameForUniqueESSymbol: () => getPropertyNameForUniqueESSymbol, getPropertyNameFromType: () => getPropertyNameFromType, getPropertyNameOfBindingOrAssignmentElement: () => getPropertyNameOfBindingOrAssignmentElement, getPropertySymbolFromBindingElement: () => getPropertySymbolFromBindingElement, @@ -179391,13 +180680,14 @@ __export(ts_exports2, { getResolvePackageJsonExports: () => getResolvePackageJsonExports, getResolvePackageJsonImports: () => getResolvePackageJsonImports, getResolvedExternalModuleName: () => getResolvedExternalModuleName, + getResolvedModuleFromResolution: () => getResolvedModuleFromResolution, + getResolvedTypeReferenceDirectiveFromResolution: () => getResolvedTypeReferenceDirectiveFromResolution, getRestIndicatorOfBindingOrAssignmentElement: () => getRestIndicatorOfBindingOrAssignmentElement, getRestParameterElementType: () => getRestParameterElementType, getRightMostAssignedExpression: () => getRightMostAssignedExpression, getRootDeclaration: () => getRootDeclaration, getRootDirectoryOfResolutionCache: () => getRootDirectoryOfResolutionCache, getRootLength: () => getRootLength, - getRootPathSplitLength: () => getRootPathSplitLength, getScriptKind: () => getScriptKind, getScriptKindFromFileName: () => getScriptKindFromFileName, getScriptTargetFeatures: () => getScriptTargetFeatures, @@ -179409,14 +180699,12 @@ __export(ts_exports2, { getSetAccessorValueParameter: () => getSetAccessorValueParameter, getSetExternalModuleIndicator: () => getSetExternalModuleIndicator, getShebang: () => getShebang, - getSingleInitializerOfVariableStatementOrPropertyDeclaration: () => getSingleInitializerOfVariableStatementOrPropertyDeclaration, getSingleVariableOfVariableStatement: () => getSingleVariableOfVariableStatement, getSnapshotText: () => getSnapshotText, getSnippetElement: () => getSnippetElement, getSourceFileOfModule: () => getSourceFileOfModule, getSourceFileOfNode: () => getSourceFileOfNode, getSourceFilePathInNewDir: () => getSourceFilePathInNewDir, - getSourceFilePathInNewDirWorker: () => getSourceFilePathInNewDirWorker, getSourceFileVersionAsHashFromText: () => getSourceFileVersionAsHashFromText, getSourceFilesToEmit: () => getSourceFilesToEmit, getSourceMapRange: () => getSourceMapRange, @@ -179439,7 +180727,6 @@ __export(ts_exports2, { getSwitchedType: () => getSwitchedType, getSymbolId: () => getSymbolId, getSymbolNameForPrivateIdentifier: () => getSymbolNameForPrivateIdentifier, - getSymbolParentOrFail: () => getSymbolParentOrFail, getSymbolTarget: () => getSymbolTarget, getSyntacticClassifications: () => getSyntacticClassifications, getSyntacticModifierFlags: () => getSyntacticModifierFlags, @@ -179470,7 +180757,6 @@ __export(ts_exports2, { getTouchingToken: () => getTouchingToken, getTrailingCommentRanges: () => getTrailingCommentRanges, getTrailingSemicolonDeferringWriter: () => getTrailingSemicolonDeferringWriter, - getTransformFlagsSubtreeExclusions: () => getTransformFlagsSubtreeExclusions, getTransformers: () => getTransformers, getTsBuildInfoEmitOutputFilePath: () => getTsBuildInfoEmitOutputFilePath, getTsConfigObjectLiteralExpression: () => getTsConfigObjectLiteralExpression, @@ -179498,7 +180784,6 @@ __export(ts_exports2, { hasAccessorModifier: () => hasAccessorModifier, hasAmbientModifier: () => hasAmbientModifier, hasChangesInResolutions: () => hasChangesInResolutions, - hasChildOfKind: () => hasChildOfKind, hasContextSensitiveParameters: () => hasContextSensitiveParameters, hasDecorators: () => hasDecorators, hasDocComment: () => hasDocComment, @@ -179507,6 +180792,7 @@ __export(ts_exports2, { hasEffectiveModifiers: () => hasEffectiveModifiers, hasEffectiveReadonlyModifier: () => hasEffectiveReadonlyModifier, hasExtension: () => hasExtension, + hasImplementationTSFileExtension: () => hasImplementationTSFileExtension, hasIndexSignature: () => hasIndexSignature, hasInferredType: () => hasInferredType, hasInitializer: () => hasInitializer, @@ -179534,7 +180820,6 @@ __export(ts_exports2, { hasType: () => hasType, hasTypeArguments: () => hasTypeArguments, hasZeroOrOneAsteriskCharacter: () => hasZeroOrOneAsteriskCharacter, - helperString: () => helperString, hostGetCanonicalFileName: () => hostGetCanonicalFileName, hostUsesCaseSensitiveFileNames: () => hostUsesCaseSensitiveFileNames, idText: () => idText, @@ -179544,9 +180829,8 @@ __export(ts_exports2, { identitySourceMapConsumer: () => identitySourceMapConsumer, ignoreSourceNewlines: () => ignoreSourceNewlines, ignoredPaths: () => ignoredPaths, - importDefaultHelper: () => importDefaultHelper, importFromModuleSpecifier: () => importFromModuleSpecifier, - importStarHelper: () => importStarHelper, + importSyntaxAffectsModuleResolution: () => importSyntaxAffectsModuleResolution, indexOfAnyCharCode: () => indexOfAnyCharCode, indexOfNode: () => indexOfNode, indicesOf: () => indicesOf, @@ -179554,7 +180838,6 @@ __export(ts_exports2, { injectClassNamedEvaluationHelperBlockIfMissing: () => injectClassNamedEvaluationHelperBlockIfMissing, injectClassThisAssignmentIfMissing: () => injectClassThisAssignmentIfMissing, insertImports: () => insertImports, - insertLeadingStatement: () => insertLeadingStatement, insertSorted: () => insertSorted, insertStatementAfterCustomPrologue: () => insertStatementAfterCustomPrologue, insertStatementAfterStandardPrologue: () => insertStatementAfterStandardPrologue, @@ -179570,11 +180853,9 @@ __export(ts_exports2, { isAccessibilityModifier: () => isAccessibilityModifier, isAccessor: () => isAccessor, isAccessorModifier: () => isAccessorModifier, - isAliasSymbolDeclaration: () => isAliasSymbolDeclaration, isAliasableExpression: () => isAliasableExpression, isAmbientModule: () => isAmbientModule, isAmbientPropertyDeclaration: () => isAmbientPropertyDeclaration, - isAnonymousFunctionDefinition: () => isAnonymousFunctionDefinition, isAnyDirectorySeparator: () => isAnyDirectorySeparator, isAnyImportOrBareOrAccessedRequire: () => isAnyImportOrBareOrAccessedRequire, isAnyImportOrReExport: () => isAnyImportOrReExport, @@ -179610,6 +180891,7 @@ __export(ts_exports2, { isAwaitKeyword: () => isAwaitKeyword, isBigIntLiteral: () => isBigIntLiteral, isBinaryExpression: () => isBinaryExpression, + isBinaryLogicalOperator: () => isBinaryLogicalOperator, isBinaryOperatorToken: () => isBinaryOperatorToken, isBindableObjectDefinePropertyCall: () => isBindableObjectDefinePropertyCall, isBindableStaticAccessExpression: () => isBindableStaticAccessExpression, @@ -179631,7 +180913,7 @@ __export(ts_exports2, { isBreakStatement: () => isBreakStatement, isBuild: () => isBuild, isBuildInfoFile: () => isBuildInfoFile, - isBuilderProgram: () => isBuilderProgram2, + isBuilderProgram: () => isBuilderProgram, isBundle: () => isBundle, isCallChain: () => isCallChain, isCallExpression: () => isCallExpression, @@ -179650,7 +180932,6 @@ __export(ts_exports2, { isCatchClauseVariableDeclaration: () => isCatchClauseVariableDeclaration, isCatchClauseVariableDeclarationOrBindingElement: () => isCatchClauseVariableDeclarationOrBindingElement, isCheckJsEnabledForFile: () => isCheckJsEnabledForFile, - isChildOfNodeWithKind: () => isChildOfNodeWithKind, isCircularBuildOrder: () => isCircularBuildOrder, isClassDeclaration: () => isClassDeclaration, isClassElement: () => isClassElement, @@ -179662,7 +180943,6 @@ __export(ts_exports2, { isClassOrTypeElement: () => isClassOrTypeElement, isClassStaticBlockDeclaration: () => isClassStaticBlockDeclaration, isClassThisAssignmentBlock: () => isClassThisAssignmentBlock, - isCollapsedRange: () => isCollapsedRange, isColonToken: () => isColonToken, isCommaExpression: () => isCommaExpression, isCommaListExpression: () => isCommaListExpression, @@ -179705,16 +180985,13 @@ __export(ts_exports2, { isDeleteTarget: () => isDeleteTarget, isDeprecatedDeclaration: () => isDeprecatedDeclaration, isDestructuringAssignment: () => isDestructuringAssignment, - isDiagnosticWithLocation: () => isDiagnosticWithLocation, isDiskPathRoot: () => isDiskPathRoot, isDoStatement: () => isDoStatement, isDocumentRegistryEntry: () => isDocumentRegistryEntry, isDotDotDotToken: () => isDotDotDotToken, isDottedName: () => isDottedName, isDynamicName: () => isDynamicName, - isESSymbolIdentifier: () => isESSymbolIdentifier, isEffectiveExternalModule: () => isEffectiveExternalModule, - isEffectiveModuleDeclaration: () => isEffectiveModuleDeclaration, isEffectiveStrictModeSourceFile: () => isEffectiveStrictModeSourceFile, isElementAccessChain: () => isElementAccessChain, isElementAccessExpression: () => isElementAccessExpression, @@ -179784,13 +181061,11 @@ __export(ts_exports2, { isFunctionOrModuleBlock: () => isFunctionOrModuleBlock, isFunctionSymbol: () => isFunctionSymbol, isFunctionTypeNode: () => isFunctionTypeNode, - isFutureReservedKeyword: () => isFutureReservedKeyword, isGeneratedIdentifier: () => isGeneratedIdentifier, isGeneratedPrivateIdentifier: () => isGeneratedPrivateIdentifier, isGetAccessor: () => isGetAccessor, isGetAccessorDeclaration: () => isGetAccessorDeclaration, isGetOrSetAccessorDeclaration: () => isGetOrSetAccessorDeclaration, - isGlobalDeclaration: () => isGlobalDeclaration, isGlobalScopeAugmentation: () => isGlobalScopeAugmentation, isGlobalSourceFile: () => isGlobalSourceFile, isGrammarError: () => isGrammarError, @@ -179838,6 +181113,8 @@ __export(ts_exports2, { isInTemplateString: () => isInTemplateString, isInTopLevelContext: () => isInTopLevelContext, isInTypeQuery: () => isInTypeQuery, + isIncrementalBuildInfo: () => isIncrementalBuildInfo, + isIncrementalBundleEmitBuildInfo: () => isIncrementalBundleEmitBuildInfo, isIncrementalCompilation: () => isIncrementalCompilation, isIndexSignatureDeclaration: () => isIndexSignatureDeclaration, isIndexedAccessTypeNode: () => isIndexedAccessTypeNode, @@ -179944,7 +181221,6 @@ __export(ts_exports2, { isLabeledStatement: () => isLabeledStatement, isLateVisibilityPaintedStatement: () => isLateVisibilityPaintedStatement, isLeftHandSideExpression: () => isLeftHandSideExpression, - isLeftHandSideOfAssignment: () => isLeftHandSideOfAssignment, isLet: () => isLet, isLineBreak: () => isLineBreak, isLiteralComputedPropertyDeclarationName: () => isLiteralComputedPropertyDeclarationName, @@ -179952,10 +181228,7 @@ __export(ts_exports2, { isLiteralExpressionOfObject: () => isLiteralExpressionOfObject, isLiteralImportTypeNode: () => isLiteralImportTypeNode, isLiteralKind: () => isLiteralKind, - isLiteralLikeAccess: () => isLiteralLikeAccess, - isLiteralLikeElementAccess: () => isLiteralLikeElementAccess, isLiteralNameOfPropertyDeclarationOrIndexAccess: () => isLiteralNameOfPropertyDeclarationOrIndexAccess, - isLiteralTypeLikeExpression: () => isLiteralTypeLikeExpression, isLiteralTypeLiteral: () => isLiteralTypeLiteral, isLiteralTypeNode: () => isLiteralTypeNode, isLocalName: () => isLocalName, @@ -179980,6 +181253,7 @@ __export(ts_exports2, { isModuleBlock: () => isModuleBlock, isModuleBody: () => isModuleBody, isModuleDeclaration: () => isModuleDeclaration, + isModuleExportName: () => isModuleExportName, isModuleExportsAccessExpression: () => isModuleExportsAccessExpression, isModuleIdentifier: () => isModuleIdentifier, isModuleName: () => isModuleName, @@ -179989,7 +181263,6 @@ __export(ts_exports2, { isModuleWithStringLiteralName: () => isModuleWithStringLiteralName, isNameOfFunctionDeclaration: () => isNameOfFunctionDeclaration, isNameOfModuleDeclaration: () => isNameOfModuleDeclaration, - isNamedClassElement: () => isNamedClassElement, isNamedDeclaration: () => isNamedDeclaration, isNamedEvaluation: () => isNamedEvaluation, isNamedEvaluationSource: () => isNamedEvaluationSource, @@ -180007,7 +181280,6 @@ __export(ts_exports2, { isNewExpression: () => isNewExpression, isNewExpressionTarget: () => isNewExpressionTarget, isNoSubstitutionTemplateLiteral: () => isNoSubstitutionTemplateLiteral, - isNode: () => isNode, isNodeArray: () => isNodeArray, isNodeArrayMultiLine: () => isNodeArrayMultiLine, isNodeDescendantOf: () => isNodeDescendantOf, @@ -180016,14 +181288,11 @@ __export(ts_exports2, { isNodeModulesDirectory: () => isNodeModulesDirectory, isNodeWithPossibleHoistedDeclaration: () => isNodeWithPossibleHoistedDeclaration, isNonContextualKeyword: () => isNonContextualKeyword, - isNonExportDefaultModifier: () => isNonExportDefaultModifier, isNonGlobalAmbientModule: () => isNonGlobalAmbientModule, - isNonGlobalDeclaration: () => isNonGlobalDeclaration, isNonNullAccess: () => isNonNullAccess, isNonNullChain: () => isNonNullChain, isNonNullExpression: () => isNonNullExpression, isNonStaticMethodOrAccessorWithPrivateName: () => isNonStaticMethodOrAccessorWithPrivateName, - isNotEmittedOrPartiallyEmittedNode: () => isNotEmittedOrPartiallyEmittedNode, isNotEmittedStatement: () => isNotEmittedStatement, isNullishCoalesce: () => isNullishCoalesce, isNumber: () => isNumber, @@ -180039,7 +181308,6 @@ __export(ts_exports2, { isObjectLiteralMethod: () => isObjectLiteralMethod, isObjectLiteralOrClassExpressionMethodOrAccessor: () => isObjectLiteralOrClassExpressionMethodOrAccessor, isObjectTypeDeclaration: () => isObjectTypeDeclaration, - isOctalDigit: () => isOctalDigit, isOmittedExpression: () => isOmittedExpression, isOptionalChain: () => isOptionalChain, isOptionalChainRoot: () => isOptionalChainRoot, @@ -180073,7 +181341,6 @@ __export(ts_exports2, { isPrivateIdentifierClassElementDeclaration: () => isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression: () => isPrivateIdentifierPropertyAccessExpression, isPrivateIdentifierSymbol: () => isPrivateIdentifierSymbol, - isProgramBundleEmitBuildInfo: () => isProgramBundleEmitBuildInfo, isProgramUptoDate: () => isProgramUptoDate, isPrologueDirective: () => isPrologueDirective, isPropertyAccessChain: () => isPropertyAccessChain, @@ -180086,7 +181353,6 @@ __export(ts_exports2, { isPropertyName: () => isPropertyName, isPropertyNameLiteral: () => isPropertyNameLiteral, isPropertySignature: () => isPropertySignature, - isProtoSetter: () => isProtoSetter, isPrototypeAccess: () => isPrototypeAccess, isPrototypePropertyAssignment: () => isPrototypePropertyAssignment, isPunctuation: () => isPunctuation, @@ -180096,7 +181362,6 @@ __export(ts_exports2, { isQuestionOrExclamationToken: () => isQuestionOrExclamationToken, isQuestionOrPlusOrMinusToken: () => isQuestionOrPlusOrMinusToken, isQuestionToken: () => isQuestionToken, - isRawSourceMap: () => isRawSourceMap, isReadonlyKeyword: () => isReadonlyKeyword, isReadonlyKeywordOrPlusOrMinusToken: () => isReadonlyKeywordOrPlusOrMinusToken, isRecognizedTripleSlashComment: () => isRecognizedTripleSlashComment, @@ -180118,24 +181383,22 @@ __export(ts_exports2, { isRootedDiskPath: () => isRootedDiskPath, isSameEntityName: () => isSameEntityName, isSatisfiesExpression: () => isSatisfiesExpression, - isScopeMarker: () => isScopeMarker, isSemicolonClassElement: () => isSemicolonClassElement, isSetAccessor: () => isSetAccessor, isSetAccessorDeclaration: () => isSetAccessorDeclaration, - isShebangTrivia: () => isShebangTrivia, isShiftOperatorOrHigher: () => isShiftOperatorOrHigher, isShorthandAmbientModuleSymbol: () => isShorthandAmbientModuleSymbol, isShorthandPropertyAssignment: () => isShorthandPropertyAssignment, + isSideEffectImport: () => isSideEffectImport, isSignedNumericLiteral: () => isSignedNumericLiteral, isSimpleCopiableExpression: () => isSimpleCopiableExpression, isSimpleInlineableExpression: () => isSimpleInlineableExpression, - isSimpleParameter: () => isSimpleParameter, isSimpleParameterList: () => isSimpleParameterList, isSingleOrDoubleQuote: () => isSingleOrDoubleQuote, + isSourceElement: () => isSourceElement, isSourceFile: () => isSourceFile, isSourceFileFromLibrary: () => isSourceFileFromLibrary, isSourceFileJS: () => isSourceFileJS, - isSourceFileNotJS: () => isSourceFileNotJS, isSourceFileNotJson: () => isSourceFileNotJson, isSourceMapping: () => isSourceMapping, isSpecialPropertyDeclaration: () => isSpecialPropertyDeclaration, @@ -180148,7 +181411,6 @@ __export(ts_exports2, { isStatic: () => isStatic, isStaticModifier: () => isStaticModifier, isString: () => isString, - isStringAKeyword: () => isStringAKeyword, isStringANonContextualKeyword: () => isStringANonContextualKeyword, isStringAndEmptyAnonymousObjectIntersection: () => isStringAndEmptyAnonymousObjectIntersection, isStringDoubleQuoted: () => isStringDoubleQuoted, @@ -180161,7 +181423,6 @@ __export(ts_exports2, { isStringTextContainingNode: () => isStringTextContainingNode, isSuperCall: () => isSuperCall, isSuperKeyword: () => isSuperKeyword, - isSuperOrSuperProperty: () => isSuperOrSuperProperty, isSuperProperty: () => isSuperProperty, isSupportedSourceFileName: () => isSupportedSourceFileName, isSwitchStatement: () => isSwitchStatement, @@ -180207,7 +181468,6 @@ __export(ts_exports2, { isTypeDeclaration: () => isTypeDeclaration, isTypeElement: () => isTypeElement, isTypeKeyword: () => isTypeKeyword, - isTypeKeywordToken: () => isTypeKeywordToken, isTypeKeywordTokenOrIdentifier: () => isTypeKeywordTokenOrIdentifier, isTypeLiteralNode: () => isTypeLiteralNode, isTypeNode: () => isTypeNode, @@ -180262,10 +181522,6 @@ __export(ts_exports2, { libMap: () => libMap, libs: () => libs, lineBreakPart: () => lineBreakPart, - linkNamePart: () => linkNamePart, - linkPart: () => linkPart, - linkTextPart: () => linkTextPart, - listFiles: () => listFiles, loadModuleFromGlobalCache: () => loadModuleFromGlobalCache, loadWithModeAwareCache: () => loadWithModeAwareCache, makeIdentifierFromModuleName: () => makeIdentifierFromModuleName, @@ -180275,7 +181531,6 @@ __export(ts_exports2, { map: () => map, mapAllOrFail: () => mapAllOrFail, mapDefined: () => mapDefined, - mapDefinedEntries: () => mapDefinedEntries, mapDefinedIterator: () => mapDefinedIterator, mapEntries: () => mapEntries, mapIterator: () => mapIterator, @@ -180285,18 +181540,19 @@ __export(ts_exports2, { matchPatternOrExact: () => matchPatternOrExact, matchedText: () => matchedText, matchesExclude: () => matchesExclude, + maxBy: () => maxBy, maybeBind: () => maybeBind, maybeSetLocalizedDiagnosticMessages: () => maybeSetLocalizedDiagnosticMessages, memoize: () => memoize, - memoizeCached: () => memoizeCached, memoizeOne: () => memoizeOne, - memoizeWeak: () => memoizeWeak, - metadataHelper: () => metadataHelper, min: () => min, minAndMax: () => minAndMax, missingFileModifiedTime: () => missingFileModifiedTime, modifierToFlag: () => modifierToFlag, modifiersToFlags: () => modifiersToFlags, + moduleExportNameIsDefault: () => moduleExportNameIsDefault, + moduleExportNameTextEscaped: () => moduleExportNameTextEscaped, + moduleExportNameTextUnescaped: () => moduleExportNameTextUnescaped, moduleOptionDeclaration: () => moduleOptionDeclaration, moduleResolutionIsEqualTo: () => moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter: () => moduleResolutionNameAndModeGetter, @@ -180336,11 +181592,11 @@ __export(ts_exports2, { nodePosToString: () => nodePosToString, nodeSeenTracker: () => nodeSeenTracker, nodeStartsNewLexicalEnvironment: () => nodeStartsNewLexicalEnvironment, - nodeToDisplayParts: () => nodeToDisplayParts, noop: () => noop, noopFileWatcher: () => noopFileWatcher, normalizePath: () => normalizePath, normalizeSlashes: () => normalizeSlashes, + normalizeSpans: () => normalizeSpans, not: () => not, notImplemented: () => notImplemented, notImplementedResolver: () => notImplementedResolver, @@ -180355,13 +181611,11 @@ __export(ts_exports2, { optionsForBuild: () => optionsForBuild, optionsForWatch: () => optionsForWatch, optionsHaveChanges: () => optionsHaveChanges, - optionsHaveModuleResolutionChanges: () => optionsHaveModuleResolutionChanges, or: () => or, orderedRemoveItem: () => orderedRemoveItem, orderedRemoveItemAt: () => orderedRemoveItemAt, packageIdToPackageName: () => packageIdToPackageName, packageIdToString: () => packageIdToString, - paramHelper: () => paramHelper, parameterIsThisKeyword: () => parameterIsThisKeyword, parameterNamePart: () => parameterNamePart, parseBaseNodeFactory: () => parseBaseNodeFactory, @@ -180392,10 +181646,8 @@ __export(ts_exports2, { pathIsBareSpecifier: () => pathIsBareSpecifier, pathIsRelative: () => pathIsRelative, patternText: () => patternText, - perfLogger: () => perfLogger, performIncrementalCompilation: () => performIncrementalCompilation, performance: () => ts_performance_exports, - plainJSErrors: () => plainJSErrors, positionBelongsToNode: () => positionBelongsToNode, positionIsASICandidate: () => positionIsASICandidate, positionIsSynthesized: () => positionIsSynthesized, @@ -180408,7 +181660,6 @@ __export(ts_exports2, { programContainsEsModules: () => programContainsEsModules, programContainsModules: () => programContainsModules, projectReferenceIsEqualTo: () => projectReferenceIsEqualTo, - propKeyHelper: () => propKeyHelper, propertyNamePart: () => propertyNamePart, pseudoBigIntToString: () => pseudoBigIntToString, punctuationPart: () => punctuationPart, @@ -180431,7 +181682,6 @@ __export(ts_exports2, { rangeStartPositionsAreOnSameLine: () => rangeStartPositionsAreOnSameLine, readBuilderProgram: () => readBuilderProgram, readConfigFile: () => readConfigFile, - readHelper: () => readHelper, readJson: () => readJson, readJsonConfigFile: () => readJsonConfigFile, readJsonOrUndefined: () => readJsonOrUndefined, @@ -180442,7 +181692,7 @@ __export(ts_exports2, { reducePathComponents: () => reducePathComponents, refactor: () => ts_refactor_exports, regExpEscape: () => regExpEscape, - regularExpressionFlagToCharacter: () => regularExpressionFlagToCharacter, + regularExpressionFlagToCharacterCode: () => regularExpressionFlagToCharacterCode, relativeComplement: () => relativeComplement, removeAllComments: () => removeAllComments, removeEmitHelper: () => removeEmitHelper, @@ -180450,7 +181700,6 @@ __export(ts_exports2, { removeFileExtension: () => removeFileExtension, removeIgnoredPath: () => removeIgnoredPath, removeMinAndVersionNumbers: () => removeMinAndVersionNumbers, - removeOptionality: () => removeOptionality, removePrefix: () => removePrefix, removeSuffix: () => removeSuffix, removeTrailingDirectorySeparator: () => removeTrailingDirectorySeparator, @@ -180469,20 +181718,16 @@ __export(ts_exports2, { resolveTripleslashReference: () => resolveTripleslashReference, resolveTypeReferenceDirective: () => resolveTypeReferenceDirective, resolvingEmptyArray: () => resolvingEmptyArray, - restHelper: () => restHelper, returnFalse: () => returnFalse, returnNoopFileWatcher: () => returnNoopFileWatcher, returnTrue: () => returnTrue, returnUndefined: () => returnUndefined, returnsPromise: () => returnsPromise, - runInitializersHelper: () => runInitializersHelper, sameFlatMap: () => sameFlatMap, sameMap: () => sameMap, sameMapping: () => sameMapping, - scanShebangTrivia: () => scanShebangTrivia, scanTokenAtPosition: () => scanTokenAtPosition, scanner: () => scanner, - screenStartingMessageCodes: () => screenStartingMessageCodes, semanticDiagnosticsOptionDeclarations: () => semanticDiagnosticsOptionDeclarations, serializeCompilerOptions: () => serializeCompilerOptions, server: () => ts_server_exports3, @@ -180490,16 +181735,13 @@ __export(ts_exports2, { setCommentRange: () => setCommentRange, setConfigFileInOptions: () => setConfigFileInOptions, setConstantValue: () => setConstantValue, - setEachParent: () => setEachParent, setEmitFlags: () => setEmitFlags, - setFunctionNameHelper: () => setFunctionNameHelper, setGetSourceFileAsHashVersioned: () => setGetSourceFileAsHashVersioned, setIdentifierAutoGenerate: () => setIdentifierAutoGenerate, setIdentifierGeneratedImportReference: () => setIdentifierGeneratedImportReference, setIdentifierTypeArguments: () => setIdentifierTypeArguments, setInternalEmitFlags: () => setInternalEmitFlags, setLocalizedDiagnosticMessages: () => setLocalizedDiagnosticMessages, - setModuleDefaultHelper: () => setModuleDefaultHelper, setNodeChildren: () => setNodeChildren, setNodeFlags: () => setNodeFlags, setObjectAllocator: () => setObjectAllocator, @@ -180528,7 +181770,6 @@ __export(ts_exports2, { shouldPreserveConstEnums: () => shouldPreserveConstEnums, shouldUseUriStyleNodeCoreModules: () => shouldUseUriStyleNodeCoreModules, showModuleSpecifier: () => showModuleSpecifier, - signatureHasLiteralTypes: () => signatureHasLiteralTypes, signatureHasRestParameter: () => signatureHasRestParameter, signatureToDisplayParts: () => signatureToDisplayParts, single: () => single, @@ -180537,18 +181778,17 @@ __export(ts_exports2, { singleOrMany: () => singleOrMany, singleOrUndefined: () => singleOrUndefined, skipAlias: () => skipAlias, - skipAssertions: () => skipAssertions, skipConstraint: () => skipConstraint, skipOuterExpressions: () => skipOuterExpressions, skipParentheses: () => skipParentheses, skipPartiallyEmittedExpressions: () => skipPartiallyEmittedExpressions, skipTrivia: () => skipTrivia, skipTypeChecking: () => skipTypeChecking, + skipTypeCheckingIgnoringNoCheck: () => skipTypeCheckingIgnoringNoCheck, skipTypeParentheses: () => skipTypeParentheses, skipWhile: () => skipWhile, sliceAfter: () => sliceAfter, some: () => some, - sort: () => sort, sortAndDeduplicate: () => sortAndDeduplicate, sortAndDeduplicateDiagnostics: () => sortAndDeduplicateDiagnostics, sourceFileAffectingCompilerOptions: () => sourceFileAffectingCompilerOptions, @@ -180557,8 +181797,6 @@ __export(ts_exports2, { sourceMapCommentRegExpDontCareLineStart: () => sourceMapCommentRegExpDontCareLineStart, spacePart: () => spacePart, spanMap: () => spanMap, - spreadArrayHelper: () => spreadArrayHelper, - stableSort: () => stableSort, startEndContainsRange: () => startEndContainsRange, startEndOverlapsWithStartEnd: () => startEndOverlapsWithStartEnd, startOnNewLine: () => startOnNewLine, @@ -180571,10 +181809,8 @@ __export(ts_exports2, { stringToToken: () => stringToToken, stripQuotes: () => stripQuotes, supportedDeclarationExtensions: () => supportedDeclarationExtensions, - supportedJSExtensions: () => supportedJSExtensions, supportedJSExtensionsFlat: () => supportedJSExtensionsFlat, supportedLocaleDirectories: () => supportedLocaleDirectories, - supportedTSExtensions: () => supportedTSExtensions, supportedTSExtensionsFlat: () => supportedTSExtensionsFlat, supportedTSImplementationExtensions: () => supportedTSImplementationExtensions, suppressLeadingAndTrailingTrivia: () => suppressLeadingAndTrailingTrivia, @@ -180583,16 +181819,12 @@ __export(ts_exports2, { symbolEscapedNameNoDefault: () => symbolEscapedNameNoDefault, symbolName: () => symbolName, symbolNameNoDefault: () => symbolNameNoDefault, - symbolPart: () => symbolPart, symbolToDisplayParts: () => symbolToDisplayParts, - syntaxMayBeASICandidate: () => syntaxMayBeASICandidate, - syntaxRequiresTrailingSemicolonOrASI: () => syntaxRequiresTrailingSemicolonOrASI, sys: () => sys, sysLog: () => sysLog, tagNamesAreEquivalent: () => tagNamesAreEquivalent, takeWhile: () => takeWhile, targetOptionDeclaration: () => targetOptionDeclaration, - templateObjectHelper: () => templateObjectHelper, testFormatSettings: () => testFormatSettings, textChangeRangeIsUnchanged: () => textChangeRangeIsUnchanged, textChangeRangeNewSpan: () => textChangeRangeNewSpan, @@ -180600,7 +181832,10 @@ __export(ts_exports2, { textOrKeywordPart: () => textOrKeywordPart, textPart: () => textPart, textRangeContainsPositionInclusive: () => textRangeContainsPositionInclusive, + textRangeContainsTextSpan: () => textRangeContainsTextSpan, + textRangeIntersectsWithTextSpan: () => textRangeIntersectsWithTextSpan, textSpanContainsPosition: () => textSpanContainsPosition, + textSpanContainsTextRange: () => textSpanContainsTextRange, textSpanContainsTextSpan: () => textSpanContainsTextSpan, textSpanEnd: () => textSpanEnd, textSpanIntersection: () => textSpanIntersection, @@ -180618,15 +181853,16 @@ __export(ts_exports2, { toBuilderStateFileInfoForMultiEmit: () => toBuilderStateFileInfoForMultiEmit, toEditorSettings: () => toEditorSettings, toFileNameLowerCase: () => toFileNameLowerCase, - toLowerCase: () => toLowerCase, toPath: () => toPath, toProgramEmitPending: () => toProgramEmitPending, + toSorted: () => toSorted, tokenIsIdentifierOrKeyword: () => tokenIsIdentifierOrKeyword, tokenIsIdentifierOrKeywordOrGreaterThan: () => tokenIsIdentifierOrKeywordOrGreaterThan, tokenToString: () => tokenToString, trace: () => trace, tracing: () => tracing, tracingEnabled: () => tracingEnabled, + transferSourceFileChildren: () => transferSourceFileChildren, transform: () => transform, transformClassFields: () => transformClassFields, transformDeclarations: () => transformDeclarations, @@ -180641,11 +181877,11 @@ __export(ts_exports2, { transformESDecorators: () => transformESDecorators, transformESNext: () => transformESNext, transformGenerators: () => transformGenerators, + transformImpliedNodeFormatDependentModule: () => transformImpliedNodeFormatDependentModule, transformJsx: () => transformJsx, transformLegacyDecorators: () => transformLegacyDecorators, transformModule: () => transformModule, transformNamedEvaluation: () => transformNamedEvaluation, - transformNodeModule: () => transformNodeModule, transformNodes: () => transformNodes, transformSystemModule: () => transformSystemModule, transformTypeScript: () => transformTypeScript, @@ -180672,7 +181908,6 @@ __export(ts_exports2, { tryGetPropertyNameOfBindingOrAssignmentElement: () => tryGetPropertyNameOfBindingOrAssignmentElement, tryGetSourceMappingURL: () => tryGetSourceMappingURL, tryGetTextOfPropertyName: () => tryGetTextOfPropertyName, - tryIOAndConsumeErrors: () => tryIOAndConsumeErrors, tryParseJson: () => tryParseJson, tryParsePattern: () => tryParsePattern, tryParsePatterns: () => tryParsePatterns, @@ -180694,7 +181929,6 @@ __export(ts_exports2, { unescapeLeadingUnderscores: () => unescapeLeadingUnderscores, unmangleScopedPackageName: () => unmangleScopedPackageName, unorderedRemoveItem: () => unorderedRemoveItem, - unorderedRemoveItemAt: () => unorderedRemoveItemAt, unreachableCodeIsError: () => unreachableCodeIsError, unsetNodeChildren: () => unsetNodeChildren, unusedLabelIsError: () => unusedLabelIsError, @@ -180707,11 +181941,9 @@ __export(ts_exports2, { updateSharedExtendedConfigFileWatcher: () => updateSharedExtendedConfigFileWatcher, updateSourceFile: () => updateSourceFile, updateWatchingWildcardDirectories: () => updateWatchingWildcardDirectories, - usesExtensionsOnImports: () => usesExtensionsOnImports, usingSingleLineStringWriter: () => usingSingleLineStringWriter, utf16EncodeAsString: () => utf16EncodeAsString, validateLocaleAndSetLanguage: () => validateLocaleAndSetLanguage, - valuesHelper: () => valuesHelper, version: () => version, versionMajorMinor: () => versionMajorMinor, visitArray: () => visitArray, @@ -180724,7 +181956,6 @@ __export(ts_exports2, { visitNodes: () => visitNodes2, visitParameterList: () => visitParameterList, walkUpBindingElementsAndPatterns: () => walkUpBindingElementsAndPatterns, - walkUpLexicalEnvironments: () => walkUpLexicalEnvironments, walkUpOuterExpressions: () => walkUpOuterExpressions, walkUpParenthesizedExpressions: () => walkUpParenthesizedExpressions, walkUpParenthesizedTypes: () => walkUpParenthesizedTypes, @@ -180877,20 +182108,19 @@ __export(ts_server_exports3, { LogLevel: () => LogLevel2, Msg: () => Msg, OpenFileInfoTelemetryEvent: () => OpenFileInfoTelemetryEvent, - Project: () => Project3, + Project: () => Project2, ProjectInfoTelemetryEvent: () => ProjectInfoTelemetryEvent, ProjectKind: () => ProjectKind, ProjectLanguageServiceStateEvent: () => ProjectLanguageServiceStateEvent, ProjectLoadingFinishEvent: () => ProjectLoadingFinishEvent, ProjectLoadingStartEvent: () => ProjectLoadingStartEvent, - ProjectService: () => ProjectService3, + ProjectService: () => ProjectService2, ProjectsUpdatedInBackgroundEvent: () => ProjectsUpdatedInBackgroundEvent, ScriptInfo: () => ScriptInfo, ScriptVersionCache: () => ScriptVersionCache, Session: () => Session3, TextStorage: () => TextStorage, ThrottledOperations: () => ThrottledOperations, - TypingsCache: () => TypingsCache, TypingsInstallerAdapter: () => TypingsInstallerAdapter, allFilesAreJsOrDts: () => allFilesAreJsOrDts, allRootFilesAreJsOrDts: () => allRootFilesAreJsOrDts, @@ -180909,7 +182139,6 @@ __export(ts_server_exports3, { createSortedArray: () => createSortedArray2, emptyArray: () => emptyArray2, findArgument: () => findArgument, - forEachResolvedProjectReferenceProject: () => forEachResolvedProjectReferenceProject, formatDiagnosticToProtocol: () => formatDiagnosticToProtocol, formatMessage: () => formatMessage2, getBaseConfigFileName: () => getBaseConfigFileName, @@ -180935,7 +182164,6 @@ __export(ts_server_exports3, { nullCancellationToken: () => nullCancellationToken, nullTypingsInstaller: () => nullTypingsInstaller, protocol: () => ts_server_protocol_exports, - removeSorted: () => removeSorted, stringifyIndented: () => stringifyIndented, toEvent: () => toEvent, toNormalizedPath: () => toNormalizedPath, @@ -181002,7 +182230,6 @@ var TypingsInstaller = class { this.missingTypingsSet = /* @__PURE__ */ new Set(); this.knownCachesSet = /* @__PURE__ */ new Set(); this.projectWatchers = /* @__PURE__ */ new Map(); - /** @internal */ this.pendingRunRequests = []; this.installRunCount = 1; this.inFlightRequestCount = 0; @@ -181477,14 +182704,11 @@ var ThrottledOperations = class _ThrottledOperations { return this.pendingTimeouts.delete(operationId); } static run(operationId, self, cb) { - var _a, _b; - (_a = perfLogger) == null ? void 0 : _a.logStartScheduledOperation(operationId); self.pendingTimeouts.delete(operationId); if (self.logger) { self.logger.info(`Running: ${operationId}`); } cb(); - (_b = perfLogger) == null ? void 0 : _b.logStopScheduledOperation(); } }; var GcTimer = class _GcTimer { @@ -181500,9 +182724,7 @@ var GcTimer = class _GcTimer { this.timerId = this.host.setTimeout(_GcTimer.run, this.delay, this); } static run(self) { - var _a, _b; self.timerId = void 0; - (_a = perfLogger) == null ? void 0 : _a.logStartScheduledOperation("GC collect"); const log = self.logger.hasLevel(2 /* requestTime */); const before = log && self.host.getMemoryUsage(); self.host.gc(); @@ -181510,26 +182732,12 @@ var GcTimer = class _GcTimer { const after = self.host.getMemoryUsage(); self.logger.perftrc(`GC::before ${before}, after ${after}`); } - (_b = perfLogger) == null ? void 0 : _b.logStopScheduledOperation(); } }; function getBaseConfigFileName(configFilePath) { const base = getBaseFileName(configFilePath); return base === "tsconfig.json" || base === "jsconfig.json" ? base : void 0; } -function removeSorted(array, remove, compare) { - if (!array || array.length === 0) { - return; - } - if (array[0] === remove) { - array.splice(0, 1); - return; - } - const removeIndex = binarySearch(array, remove, identity, compare); - if (removeIndex >= 0) { - array.splice(removeIndex, 1); - } -} // src/server/_namespaces/ts.server.protocol.ts var ts_server_protocol_exports = {}; @@ -181544,7 +182752,7 @@ __export(ts_server_protocol_exports, { NewLineKind: () => NewLineKind2, OrganizeImportsMode: () => OrganizeImportsMode, PollingWatchKind: () => PollingWatchKind2, - ScriptTarget: () => ScriptTarget10, + ScriptTarget: () => ScriptTarget11, SemicolonPreference: () => SemicolonPreference, WatchDirectoryKind: () => WatchDirectoryKind2, WatchFileKind: () => WatchFileKind2 @@ -181735,24 +182943,24 @@ var NewLineKind2 = /* @__PURE__ */ ((NewLineKind3) => { NewLineKind3["Lf"] = "Lf"; return NewLineKind3; })(NewLineKind2 || {}); -var ScriptTarget10 = /* @__PURE__ */ ((ScriptTarget11) => { - ScriptTarget11["ES3"] = "es3"; - ScriptTarget11["ES5"] = "es5"; - ScriptTarget11["ES6"] = "es6"; - ScriptTarget11["ES2015"] = "es2015"; - ScriptTarget11["ES2016"] = "es2016"; - ScriptTarget11["ES2017"] = "es2017"; - ScriptTarget11["ES2018"] = "es2018"; - ScriptTarget11["ES2019"] = "es2019"; - ScriptTarget11["ES2020"] = "es2020"; - ScriptTarget11["ES2021"] = "es2021"; - ScriptTarget11["ES2022"] = "es2022"; - ScriptTarget11["ES2023"] = "es2023"; - ScriptTarget11["ESNext"] = "esnext"; - ScriptTarget11["JSON"] = "json"; - ScriptTarget11["Latest"] = "esnext" /* ESNext */; - return ScriptTarget11; -})(ScriptTarget10 || {}); +var ScriptTarget11 = /* @__PURE__ */ ((ScriptTarget12) => { + ScriptTarget12["ES3"] = "es3"; + ScriptTarget12["ES5"] = "es5"; + ScriptTarget12["ES6"] = "es6"; + ScriptTarget12["ES2015"] = "es2015"; + ScriptTarget12["ES2016"] = "es2016"; + ScriptTarget12["ES2017"] = "es2017"; + ScriptTarget12["ES2018"] = "es2018"; + ScriptTarget12["ES2019"] = "es2019"; + ScriptTarget12["ES2020"] = "es2020"; + ScriptTarget12["ES2021"] = "es2021"; + ScriptTarget12["ES2022"] = "es2022"; + ScriptTarget12["ES2023"] = "es2023"; + ScriptTarget12["ESNext"] = "esnext"; + ScriptTarget12["JSON"] = "json"; + ScriptTarget12["Latest"] = "esnext" /* ESNext */; + return ScriptTarget12; +})(ScriptTarget11 || {}); { } @@ -182237,102 +183445,6 @@ function failIfInvalidLocation(location) { Debug.assert(location.offset > 0, `Expected offset to be non-${location.offset === 0 ? "zero" : "negative"}`); } -// src/server/typingsCache.ts -var nullTypingsInstaller = { - isKnownTypesPackageName: returnFalse, - // Should never be called because we never provide a types registry. - installPackage: notImplemented, - enqueueInstallTypingsRequest: noop, - attach: noop, - onProjectClosed: noop, - globalTypingsCacheLocation: void 0 - // TODO: GH#18217 -}; -function setIsEqualTo(arr1, arr2) { - if (arr1 === arr2) { - return true; - } - if ((arr1 || emptyArray2).length === 0 && (arr2 || emptyArray2).length === 0) { - return true; - } - const set = /* @__PURE__ */ new Map(); - let unique = 0; - for (const v of arr1) { - if (set.get(v) !== true) { - set.set(v, true); - unique++; - } - } - for (const v of arr2) { - const isSet = set.get(v); - if (isSet === void 0) { - return false; - } - if (isSet === true) { - set.set(v, false); - unique--; - } - } - return unique === 0; -} -function typeAcquisitionChanged(opt1, opt2) { - return opt1.enable !== opt2.enable || !setIsEqualTo(opt1.include, opt2.include) || !setIsEqualTo(opt1.exclude, opt2.exclude); -} -function compilerOptionsChanged(opt1, opt2) { - return getAllowJSCompilerOption(opt1) !== getAllowJSCompilerOption(opt2); -} -function unresolvedImportsChanged(imports1, imports2) { - if (imports1 === imports2) { - return false; - } - return !arrayIsEqualTo(imports1, imports2); -} -var TypingsCache = class { - constructor(installer) { - this.installer = installer; - this.perProjectCache = /* @__PURE__ */ new Map(); - } - isKnownTypesPackageName(name) { - return this.installer.isKnownTypesPackageName(name); - } - installPackage(options) { - return this.installer.installPackage(options); - } - enqueueInstallTypingsForProject(project, unresolvedImports, forceRefresh) { - const typeAcquisition = project.getTypeAcquisition(); - if (!typeAcquisition || !typeAcquisition.enable) { - return; - } - const entry = this.perProjectCache.get(project.getProjectName()); - if (forceRefresh || !entry || typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) || compilerOptionsChanged(project.getCompilationSettings(), entry.compilerOptions) || unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports)) { - this.perProjectCache.set(project.getProjectName(), { - compilerOptions: project.getCompilationSettings(), - typeAcquisition, - typings: entry ? entry.typings : emptyArray2, - unresolvedImports, - poisoned: true - }); - this.installer.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports); - } - } - updateTypingsForProject(projectName, compilerOptions, typeAcquisition, unresolvedImports, newTypings) { - const typings = sort(newTypings); - this.perProjectCache.set(projectName, { - compilerOptions, - typeAcquisition, - typings, - unresolvedImports, - poisoned: false - }); - return !typeAcquisition || !typeAcquisition.enable ? emptyArray2 : typings; - } - onProjectClosed(project) { - if (this.perProjectCache.delete(project.getProjectName())) { - this.installer.onProjectClosed(project); - } - } -}; - // src/server/project.ts var ProjectKind = /* @__PURE__ */ ((ProjectKind2) => { ProjectKind2[ProjectKind2["Inferred"] = 0] = "Inferred"; @@ -182407,7 +183519,46 @@ function hasNoTypeScriptSource(fileNames) { function isGeneratedFileWatcher(watch) { return watch.generatedFilePath !== void 0; } -var Project3 = class _Project { +function setIsEqualTo(arr1, arr2) { + if (arr1 === arr2) { + return true; + } + if ((arr1 || emptyArray2).length === 0 && (arr2 || emptyArray2).length === 0) { + return true; + } + const set = /* @__PURE__ */ new Map(); + let unique = 0; + for (const v of arr1) { + if (set.get(v) !== true) { + set.set(v, true); + unique++; + } + } + for (const v of arr2) { + const isSet = set.get(v); + if (isSet === void 0) { + return false; + } + if (isSet === true) { + set.set(v, false); + unique--; + } + } + return unique === 0; +} +function typeAcquisitionChanged(opt1, opt2) { + return opt1.enable !== opt2.enable || !setIsEqualTo(opt1.include, opt2.include) || !setIsEqualTo(opt1.exclude, opt2.exclude); +} +function compilerOptionsChanged(opt1, opt2) { + return getAllowJSCompilerOption(opt1) !== getAllowJSCompilerOption(opt2); +} +function unresolvedImportsChanged(imports1, imports2) { + if (imports1 === imports2) { + return false; + } + return !arrayIsEqualTo(imports1, imports2); +} +var Project2 = class _Project { /** @internal */ constructor(projectName, projectKind, projectService, documentRegistry, hasExplicitListOfFiles, lastFileExceededProgramSize, compilerOptions, compileOnSaveEnabled, watchOptions, directoryStructureHost, currentDirectory) { this.projectKind = projectKind; @@ -182427,9 +183578,7 @@ var Project3 = class _Project { * @internal */ this.cachedUnresolvedImportsPerFile = /* @__PURE__ */ new Map(); - /** @internal */ this.hasAddedorRemovedFiles = false; - /** @internal */ this.hasAddedOrRemovedSymlinks = false; /** * Last version that was reported. @@ -182454,7 +183603,6 @@ var Project3 = class _Project { this.dirty = false; /** @internal */ this.typingFiles = emptyArray2; - /** @internal */ this.moduleSpecifierCache = createModuleSpecifierCache(this); /** @internal */ this.createHash = maybeBind(this.projectService.host, this.projectService.host.createHash); @@ -182500,6 +183648,7 @@ var Project3 = class _Project { this.trace = (s) => host.trace(s); } this.realpath = maybeBind(host, host.realpath); + this.preferNonRecursiveWatch = this.projectService.canUseWatchEvents || host.preferNonRecursiveWatch; this.resolutionCache = createResolutionCache( this, this.currentDirectory, @@ -182573,18 +183722,15 @@ var Project3 = class _Project { return { pluginConfigEntry, resolvedModule, errorLogs }; } isKnownTypesPackageName(name) { - return this.typingsCache.isKnownTypesPackageName(name); + return this.projectService.typingsInstaller.isKnownTypesPackageName(name); } installPackage(options) { - return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }); + return this.projectService.typingsInstaller.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }); } /** @internal */ getGlobalTypingsCacheLocation() { return this.getGlobalCache(); } - get typingsCache() { - return this.projectService.typingsCache; - } /** @internal */ getSymlinkCache() { if (!this.symlinks) { @@ -182689,7 +183835,7 @@ var Project3 = class _Project { } fileExists(file) { const path = this.toPath(file); - return !this.isWatchedMissingFile(path) && this.directoryStructureHost.fileExists(file); + return !!this.projectService.getScriptInfoForPath(path) || !this.isWatchedMissingFile(path) && this.directoryStructureHost.fileExists(file); } /** @internal */ resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options, containingSourceFile, reusedNames) { @@ -182956,13 +184102,13 @@ var Project3 = class _Project { return this.projectName; } removeLocalTypingsFromTypeAcquisition(newTypeAcquisition) { - if (!newTypeAcquisition || !newTypeAcquisition.include) { + if (!newTypeAcquisition.enable || !newTypeAcquisition.include) { return newTypeAcquisition; } return { ...newTypeAcquisition, include: this.removeExistingTypings(newTypeAcquisition.include) }; } getExternalFiles(updateLevel) { - return sort(flatMap(this.plugins, (plugin) => { + return toSorted(flatMap(this.plugins, (plugin) => { if (typeof plugin.module.getExternalFiles !== "function") return; try { return plugin.module.getExternalFiles(this, updateLevel || 0 /* Update */); @@ -182987,7 +184133,8 @@ var Project3 = class _Project { } close() { var _a; - this.projectService.typingsCache.onProjectClosed(this); + if (this.typingsCache) this.projectService.typingsInstaller.onProjectClosed(this); + this.typingsCache = void 0; this.closeWatchingTypingLocations(); this.cleanupProgram(); forEach(this.externalFiles, (externalFile) => this.detachScriptInfoIfNotRoot(externalFile)); @@ -183229,6 +184376,12 @@ var Project3 = class _Project { this.hasAddedOrRemovedSymlinks = true; } /** @internal */ + onReleaseOldSourceFile(oldSourceFile, _oldOptions, hasSourceFileByPath, newSourceFileByResolvedPath) { + if (!newSourceFileByResolvedPath || oldSourceFile.resolvedPath === oldSourceFile.path && newSourceFileByResolvedPath.resolvedPath !== oldSourceFile.path) { + this.detachScriptInfoFromProject(oldSourceFile.fileName, hasSourceFileByPath); + } + } + /** @internal */ updateFromProject() { updateProjectIfDirty(this); } @@ -183237,9 +184390,8 @@ var Project3 = class _Project { * @returns: true if set of files in the project stays the same and false - otherwise. */ updateGraph() { - var _a, _b, _c, _d; + var _a, _b; (_a = tracing) == null ? void 0 : _a.push(tracing.Phase.Session, "updateGraph", { name: this.projectName, kind: ProjectKind[this.projectKind] }); - (_b = perfLogger) == null ? void 0 : _b.logStartUpdateGraph(); this.resolutionCache.startRecordingFilesWithChangedResolutions(); const hasNewProgram = this.updateGraphWorker(); const hasAddedorRemovedFiles = this.hasAddedorRemovedFiles; @@ -183253,7 +184405,7 @@ var Project3 = class _Project { if (hasNewProgram || changedFiles.length) { this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program, this.cachedUnresolvedImportsPerFile); } - this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles); + this.enqueueInstallTypingsForProject(hasAddedorRemovedFiles); } else { this.lastCachedUnresolvedImportsList = void 0; } @@ -183267,12 +184419,33 @@ var Project3 = class _Project { if (isFirstProgramLoad) { this.getPackageJsonAutoImportProvider(); } - (_c = perfLogger) == null ? void 0 : _c.logStopUpdateGraph(); - (_d = tracing) == null ? void 0 : _d.pop(); + (_b = tracing) == null ? void 0 : _b.pop(); return !hasNewProgram; } /** @internal */ - updateTypingFiles(typingFiles) { + enqueueInstallTypingsForProject(forceRefresh) { + const typeAcquisition = this.getTypeAcquisition(); + if (!typeAcquisition || !typeAcquisition.enable || this.projectService.typingsInstaller === nullTypingsInstaller) { + return; + } + const entry = this.typingsCache; + if (forceRefresh || !entry || typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) || compilerOptionsChanged(this.getCompilationSettings(), entry.compilerOptions) || unresolvedImportsChanged(this.lastCachedUnresolvedImportsList, entry.unresolvedImports)) { + this.typingsCache = { + compilerOptions: this.getCompilationSettings(), + typeAcquisition, + unresolvedImports: this.lastCachedUnresolvedImportsList + }; + this.projectService.typingsInstaller.enqueueInstallTypingsRequest(this, typeAcquisition, this.lastCachedUnresolvedImportsList); + } + } + /** @internal */ + updateTypingFiles(compilerOptions, typeAcquisition, unresolvedImports, newTypings) { + this.typingsCache = { + compilerOptions, + typeAcquisition, + unresolvedImports + }; + const typingFiles = !typeAcquisition || !typeAcquisition.enable ? emptyArray2 : toSorted(newTypings); if (enumerateInsertsAndDeletes( typingFiles, this.typingFiles, @@ -183286,12 +184459,10 @@ var Project3 = class _Project { this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); } } - /** @internal */ closeWatchingTypingLocations() { if (this.typingWatchers) clearMap(this.typingWatchers, closeFileWatcher); this.typingWatchers = void 0; } - /** @internal */ onTypingInstallerWatchInvoke() { this.typingWatchers.isInvoked = true; this.projectService.updateTypingsForProject({ projectName: this.getProjectName(), kind: ActionInvalidate }); @@ -183369,8 +184540,9 @@ var Project3 = class _Project { return this.program; } removeExistingTypings(include) { + if (!include.length) return include; const existing = getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost); - return include.filter((i) => !existing.includes(i)); + return filter(include, (i) => !existing.includes(i)); } updateGraphWorker() { var _a, _b; @@ -183394,30 +184566,6 @@ var Project3 = class _Project { let hasNewProgram = false; if (this.program && (!oldProgram || this.program !== oldProgram && this.program.structureIsReused !== 2 /* Completely */)) { hasNewProgram = true; - if (oldProgram) { - for (const f of oldProgram.getSourceFiles()) { - const newFile = this.program.getSourceFileByPath(f.resolvedPath); - if (!newFile || f.resolvedPath === f.path && newFile.resolvedPath !== f.path) { - this.detachScriptInfoFromProject( - f.fileName, - !!this.program.getSourceFileByPath(f.path), - /*syncDirWatcherRemove*/ - true - ); - } - } - oldProgram.forEachResolvedProjectReference((resolvedProjectReference) => { - if (!this.program.getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) { - this.detachScriptInfoFromProject( - resolvedProjectReference.sourceFile.fileName, - /*noRemoveResolution*/ - void 0, - /*syncDirWatcherRemove*/ - true - ); - } - }); - } this.rootFilesMap.forEach((value, path) => { var _a2; const file = this.program.getSourceFileByPath(path); @@ -183449,7 +184597,7 @@ var Project3 = class _Project { this.generatedFilesMap.forEach((watcher, source) => { const sourceFile = this.program.getSourceFileByPath(source); if (!sourceFile || sourceFile.resolvedPath !== source || !this.isValidGeneratedFileWatcher( - getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.currentDirectory, this.program.getCommonSourceDirectory(), this.getCanonicalFileName), + getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.program), watcher )) { closeFileWatcherOf(watcher); @@ -183542,12 +184690,12 @@ var Project3 = class _Project { sendPerformanceEvent(kind, durationMs) { this.projectService.sendPerformanceEvent(kind, durationMs); } - detachScriptInfoFromProject(uncheckedFileName, noRemoveResolution, syncDirWatcherRemove) { + detachScriptInfoFromProject(uncheckedFileName, noRemoveResolution) { const scriptInfoToDetach = this.projectService.getScriptInfo(uncheckedFileName); if (scriptInfoToDetach) { scriptInfoToDetach.detachFromProject(this); if (!noRemoveResolution) { - this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path, syncDirWatcherRemove); + this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path); } } } @@ -183647,7 +184795,6 @@ var Project3 = class _Project { false ); } - /** @internal */ filesToStringWorker(writeProjectFileNames, writeFileExplaination, writeFileVersionAndText) { if (this.isInitialLoadPending()) return " Files (0) InitialLoadPending\n"; if (!this.program) return " Files (0) NoProgram\n"; @@ -183981,7 +185128,6 @@ var Project3 = class _Project { (_c = tracing) == null ? void 0 : _c.pop(); } } - /** @internal */ isDefaultProjectForOpenFiles() { return !!forEachEntry( this.projectService.openFiles, @@ -184013,16 +185159,15 @@ var Project3 = class _Project { var _a, _b, _c, _d; const originalProgram = this.program; const rootSourceFile = Debug.checkDefined((_a = this.program) == null ? void 0 : _a.getSourceFile(rootFile), "Expected file to be part of program"); - const originalText = Debug.checkDefined(rootSourceFile.getText()); + const originalText = Debug.checkDefined(rootSourceFile.getFullText()); (_b = this.getScriptInfo(rootFile)) == null ? void 0 : _b.editContent(0, originalText.length, updatedText); this.updateGraph(); try { cb(this.program, originalProgram, (_c = this.program) == null ? void 0 : _c.getSourceFile(rootFile)); } finally { - (_d = this.getScriptInfo(rootFile)) == null ? void 0 : _d.editContent(0, this.program.getSourceFile(rootFile).getText().length, originalText); + (_d = this.getScriptInfo(rootFile)) == null ? void 0 : _d.editContent(0, updatedText.length, originalText); } } - /** @internal */ getCompilerOptionsForNoDtsResolutionProject() { return { ...this.getCompilerOptions(), @@ -184063,7 +185208,7 @@ function extractUnresolvedImportsFromSourceFile(program, file, ambientModules, c return unresolvedImports || emptyArray2; }); } -var InferredProject2 = class extends Project3 { +var InferredProject2 = class extends Project2 { /** @internal */ constructor(projectService, documentRegistry, compilerOptions, watchOptions, projectRootPath, currentDirectory, typeAcquisition) { super( @@ -184157,7 +185302,7 @@ var InferredProject2 = class extends Project3 { }; } }; -var AuxiliaryProject = class extends Project3 { +var AuxiliaryProject = class extends Project2 { constructor(projectService, documentRegistry, compilerOptions, currentDirectory) { super( projectService.newAuxiliaryProjectName(), @@ -184184,7 +185329,7 @@ var AuxiliaryProject = class extends Project3 { return; } }; -var _AutoImportProviderProject = class _AutoImportProviderProject extends Project3 { +var _AutoImportProviderProject = class _AutoImportProviderProject extends Project2 { /** @internal */ constructor(hostProject, initialRootNames, documentRegistry, compilerOptions) { super( @@ -184440,7 +185585,6 @@ var _AutoImportProviderProject = class _AutoImportProviderProject extends Projec return (_a = this.hostProject.getCurrentProgram()) == null ? void 0 : _a.getModuleResolutionCache(); } }; -/** @internal */ _AutoImportProviderProject.maxDependencies = 10; /** @internal */ _AutoImportProviderProject.compilerOptionsOverrides = { @@ -184452,7 +185596,7 @@ _AutoImportProviderProject.compilerOptionsOverrides = { noLib: true }; var AutoImportProviderProject = _AutoImportProviderProject; -var ConfiguredProject2 = class extends Project3 { +var ConfiguredProject2 = class extends Project2 { /** @internal */ constructor(configFileName, canonicalConfigFilePath, projectService, documentRegistry, cachedDirectoryStructureHost, pendingUpdateReason) { super( @@ -184515,7 +185659,6 @@ var ConfiguredProject2 = class extends Project3 { onReleaseParsedCommandLine(fileName) { this.releaseParsedConfig(asNormalizedPath(this.projectService.toCanonicalFileName(asNormalizedPath(normalizePath(fileName))))); } - /** @internal */ releaseParsedConfig(canonicalConfigFilePath) { this.projectService.stopWatchingWildCards(canonicalConfigFilePath, this); this.projectService.releaseParsedConfig(canonicalConfigFilePath, this); @@ -184658,7 +185801,7 @@ var ConfiguredProject2 = class extends Project3 { updateErrorForNoInputFiles(fileNames, this.getConfigFilePath(), this.getCompilerOptions().configFile.configFileSpecs, this.projectErrors, this.canConfigFileJsonReportNoInputFiles); } }; -var ExternalProject = class extends Project3 { +var ExternalProject = class extends Project2 { /** @internal */ constructor(externalProjectName, projectService, documentRegistry, compilerOptions, lastFileExceededProgramSize, compileOnSaveEnabled, projectFilePath, watchOptions) { super( @@ -184865,6 +186008,16 @@ function findProjectByName(projectName, projects) { } } } +var nullTypingsInstaller = { + isKnownTypesPackageName: returnFalse, + // Should never be called because we never provide a types registry. + installPackage: notImplemented, + enqueueInstallTypingsRequest: noop, + attach: noop, + onProjectClosed: noop, + globalTypingsCacheLocation: void 0 + // TODO: GH#18217 +}; var noopConfigFileWatcher = { close: noop }; function getConfigFileNameFromCache(info, cache) { if (!cache || isAncestorConfigFileInfo(info)) return void 0; @@ -185063,8 +186216,11 @@ function createProjectNameFactoryWithCounter(nameFactory) { function getHostWatcherMap() { return { idToCallbacks: /* @__PURE__ */ new Map(), pathToId: /* @__PURE__ */ new Map() }; } +function getCanUseWatchEvents(service, canUseWatchEvents) { + return !!canUseWatchEvents && !!service.eventHandler && !!service.session; +} function createWatchFactoryHostUsingWatchEvents(service, canUseWatchEvents) { - if (!canUseWatchEvents || !service.eventHandler || !service.session) return void 0; + if (!getCanUseWatchEvents(service, canUseWatchEvents)) return void 0; const watchedFiles = getHostWatcherMap(); const watchedDirectories = getHostWatcherMap(); const watchedDirectoriesRecursive = getHostWatcherMap(); @@ -185222,9 +186378,7 @@ var _ProjectService = class _ProjectService { this.pendingEnsureProjectForOpenFiles = false; /** Tracks projects that we have already sent telemetry for. */ this.seenProjects = /* @__PURE__ */ new Map(); - /** @internal */ this.sharedExtendedConfigFileWatchers = /* @__PURE__ */ new Map(); - /** @internal */ this.extendedConfigCache = /* @__PURE__ */ new Map(); /** @internal */ this.baseline = noop; @@ -185268,7 +186422,6 @@ var _ProjectService = class _ProjectService { this.logger.info("No types map provided; using the default"); } this.typingsInstaller.attach(this); - this.typingsCache = new TypingsCache(this.typingsInstaller); this.hostConfiguration = { formatCodeOptions: getDefaultFormatCodeSettings(this.host.newLine), preferences: emptyOptions, @@ -185288,6 +186441,7 @@ var _ProjectService = class _ProjectService { log, getDetailWatchInfo ); + this.canUseWatchEvents = getCanUseWatchEvents(this, opts.canUseWatchEvents); (_a = opts.incrementalVerifier) == null ? void 0 : _a.call(opts, this); } toPath(fileName) { @@ -185361,12 +186515,15 @@ var _ProjectService = class _ProjectService { } switch (response.kind) { case ActionSet: - project.updateTypingFiles(this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings)); + project.updateTypingFiles( + response.compilerOptions, + response.typeAcquisition, + response.unresolvedImports, + response.typings + ); return; case ActionInvalidate: - this.typingsCache.enqueueInstallTypingsForProject( - project, - project.lastCachedUnresolvedImportsList, + project.enqueueInstallTypingsForProject( /*forceRefresh*/ true ); @@ -185679,65 +186836,17 @@ var _ProjectService = class _ProjectService { } /** * This is to watch whenever files are added or removed to the wildcard directories - * - * @internal */ watchWildcardDirectory(directory, flags, configFileName, config) { let watcher = this.watchFactory.watchDirectory( directory, - (fileOrDirectory) => { - const fileOrDirectoryPath = this.toPath(fileOrDirectory); - const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); - if (getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) && (fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectory))) { - const file = this.getNormalizedAbsolutePath(fileOrDirectory); - this.logger.info(`Config: ${configFileName} Detected new package.json: ${file}`); - this.packageJsonCache.addOrUpdate(file, fileOrDirectoryPath); - this.watchPackageJsonFile(file, fileOrDirectoryPath, result); - } - const configuredProjectForConfig = this.findConfiguredProjectByProjectName(configFileName); - if (isIgnoredFileFromWildCardWatching({ - watchedDirPath: this.toPath(directory), - fileOrDirectory, - fileOrDirectoryPath, - configFileName, - extraFileExtensions: this.hostConfiguration.extraFileExtensions, - currentDirectory: this.currentDirectory, - options: config.parsedCommandLine.options, - program: (configuredProjectForConfig == null ? void 0 : configuredProjectForConfig.getCurrentProgram()) || config.parsedCommandLine.fileNames, - useCaseSensitiveFileNames: this.host.useCaseSensitiveFileNames, - writeLog: (s) => this.logger.info(s), - toPath: (s) => this.toPath(s), - getScriptKind: configuredProjectForConfig ? (fileName) => configuredProjectForConfig.getScriptKind(fileName) : void 0 - })) return; - if (config.updateLevel !== 2 /* Full */) config.updateLevel = 1 /* RootNamesAndUpdate */; - config.projects.forEach((watchWildcardDirectories, projectCanonicalPath) => { - var _a; - if (!watchWildcardDirectories) return; - const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); - if (!project) return; - if (configuredProjectForConfig !== project && this.getHostPreferences().includeCompletionsForModuleExports) { - const path = this.toPath(configFileName); - if (find((_a = project.getCurrentProgram()) == null ? void 0 : _a.getResolvedProjectReferences(), (ref) => (ref == null ? void 0 : ref.sourceFile.path) === path)) { - project.markAutoImportProviderAsDirty(); - } - } - const updateLevel = configuredProjectForConfig === project ? 1 /* RootNamesAndUpdate */ : 0 /* Update */; - if (project.pendingUpdateLevel > updateLevel) return; - if (this.openFiles.has(fileOrDirectoryPath)) { - const info = Debug.checkDefined(this.getScriptInfoForPath(fileOrDirectoryPath)); - if (info.isAttached(project)) { - const loadLevelToSet = Math.max(updateLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || 0 /* Update */); - project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet); - } else { - project.pendingUpdateLevel = updateLevel; - this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); - } - } else { - project.pendingUpdateLevel = updateLevel; - this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); - } - }); - }, + (fileOrDirectory) => this.onWildCardDirectoryWatcherInvoke( + directory, + configFileName, + config, + result, + fileOrDirectory + ), flags, this.getWatchOptionsFromProjectWatchOptions(config.parsedCommandLine.watchOptions, getDirectoryPath(configFileName)), WatchType.WildcardDirectory, @@ -185760,7 +186869,62 @@ var _ProjectService = class _ProjectService { }; return result; } - /** @internal */ + onWildCardDirectoryWatcherInvoke(directory, configFileName, config, wildCardWatcher, fileOrDirectory) { + const fileOrDirectoryPath = this.toPath(fileOrDirectory); + const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); + if (getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) && (fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectory))) { + const file = this.getNormalizedAbsolutePath(fileOrDirectory); + this.logger.info(`Config: ${configFileName} Detected new package.json: ${file}`); + this.packageJsonCache.addOrUpdate(file, fileOrDirectoryPath); + this.watchPackageJsonFile(file, fileOrDirectoryPath, wildCardWatcher); + } + if (!(fsResult == null ? void 0 : fsResult.fileExists)) { + this.sendSourceFileChange(fileOrDirectoryPath); + } + const configuredProjectForConfig = this.findConfiguredProjectByProjectName(configFileName); + if (isIgnoredFileFromWildCardWatching({ + watchedDirPath: this.toPath(directory), + fileOrDirectory, + fileOrDirectoryPath, + configFileName, + extraFileExtensions: this.hostConfiguration.extraFileExtensions, + currentDirectory: this.currentDirectory, + options: config.parsedCommandLine.options, + program: (configuredProjectForConfig == null ? void 0 : configuredProjectForConfig.getCurrentProgram()) || config.parsedCommandLine.fileNames, + useCaseSensitiveFileNames: this.host.useCaseSensitiveFileNames, + writeLog: (s) => this.logger.info(s), + toPath: (s) => this.toPath(s), + getScriptKind: configuredProjectForConfig ? (fileName) => configuredProjectForConfig.getScriptKind(fileName) : void 0 + })) return; + if (config.updateLevel !== 2 /* Full */) config.updateLevel = 1 /* RootNamesAndUpdate */; + config.projects.forEach((watchWildcardDirectories, projectCanonicalPath) => { + var _a; + if (!watchWildcardDirectories) return; + const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); + if (!project) return; + if (configuredProjectForConfig !== project && this.getHostPreferences().includeCompletionsForModuleExports) { + const path = this.toPath(configFileName); + if (find((_a = project.getCurrentProgram()) == null ? void 0 : _a.getResolvedProjectReferences(), (ref) => (ref == null ? void 0 : ref.sourceFile.path) === path)) { + project.markAutoImportProviderAsDirty(); + } + } + const updateLevel = configuredProjectForConfig === project ? 1 /* RootNamesAndUpdate */ : 0 /* Update */; + if (project.pendingUpdateLevel > updateLevel) return; + if (this.openFiles.has(fileOrDirectoryPath)) { + const info = Debug.checkDefined(this.getScriptInfoForPath(fileOrDirectoryPath)); + if (info.isAttached(project)) { + const loadLevelToSet = Math.max(updateLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || 0 /* Update */); + project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet); + } else { + project.pendingUpdateLevel = updateLevel; + this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); + } + } else { + project.pendingUpdateLevel = updateLevel; + this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); + } + }); + } delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath, loadReason) { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (!(configFileExistenceInfo == null ? void 0 : configFileExistenceInfo.config)) return false; @@ -185788,7 +186952,6 @@ var _ProjectService = class _ProjectService { }); return scheduledAnyProjectUpdate; } - /** @internal */ onConfigFileChanged(configFileName, canonicalConfigFilePath, eventKind) { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); const project = this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath); @@ -186010,7 +187173,6 @@ var _ProjectService = class _ProjectService { this.configFileExistenceInfoCache.set(canonicalConfigFilePath, { exists, openFilesImpactedByConfigFile }); return exists; } - /** @internal */ createConfigFileWatcherForParsedConfig(configFileName, canonicalConfigFilePath, forProject) { var _a, _b; const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); @@ -186351,8 +187513,6 @@ var _ProjectService = class _ProjectService { } /** * Read the config file of the project, and update the project root file names. - * - * @internal */ loadConfiguredProject(project, reason) { var _a, _b; @@ -186604,7 +187764,6 @@ var _ProjectService = class _ProjectService { project.markAsDirty(); return project.updateGraph(); } - /** @internal */ reloadFileNamesOfParsedConfig(configFileName, config) { if (config.updateLevel === void 0) return config.parsedCommandLine.fileNames; Debug.assert(config.updateLevel === 1 /* RootNamesAndUpdate */); @@ -186649,7 +187808,6 @@ var _ProjectService = class _ProjectService { true ); } - /** @internal */ clearSemanticCache(project) { project.originalConfiguredProjects = void 0; project.resolutionCache.clear(); @@ -187226,7 +188384,6 @@ Dynamic files must always be opened with service's current directory or service getWatchOptions(project) { return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions(), project.getCurrentDirectory()); } - /** @internal */ getWatchOptionsFromProjectWatchOptions(projectOptions, basePath) { const hostWatchOptions = !this.hostConfiguration.beforeSubstitution ? this.hostConfiguration.watchOptions : handleWatchOptionsConfigDirTemplateSubstitution( this.hostConfiguration.beforeSubstitution, @@ -187237,20 +188394,34 @@ Dynamic files must always be opened with service's current directory or service closeLog() { this.logger.close(); } + sendSourceFileChange(inPath) { + this.filenameToScriptInfo.forEach((info) => { + if (this.openFiles.has(info.path)) return; + if (!info.fileWatcher) return; + const eventKind = memoize( + () => this.host.fileExists(info.fileName) ? info.deferredDelete ? 0 /* Created */ : 1 /* Changed */ : 2 /* Deleted */ + ); + if (inPath) { + if (isScriptInfoWatchedFromNodeModules(info) || !info.path.startsWith(inPath)) return; + if (eventKind() === 2 /* Deleted */ && info.deferredDelete) return; + this.logger.info(`Invoking sourceFileChange on ${info.fileName}:: ${eventKind()}`); + } + this.onSourceFileChanged( + info, + eventKind() + ); + }); + } /** * This function rebuilds the project for every file opened by the client * This does not reload contents of open files from disk. But we could do that if needed */ reloadProjects() { this.logger.info("reload projects."); - this.filenameToScriptInfo.forEach((info) => { - if (this.openFiles.has(info.path)) return; - if (!info.fileWatcher) return; - this.onSourceFileChanged( - info, - this.host.fileExists(info.fileName) ? info.deferredDelete ? 0 /* Created */ : 1 /* Changed */ : 2 /* Deleted */ - ); - }); + this.sendSourceFileChange( + /*inPath*/ + void 0 + ); this.pendingProjectUpdates.forEach((_project, projectName) => { this.throttledOperations.cancel(projectName); this.pendingProjectUpdates.delete(projectName); @@ -187599,12 +188770,12 @@ Dynamic files must always be opened with service's current directory or service } /** @internal */ loadAncestorProjectTree(forProjects) { - forProjects = forProjects || mapDefinedEntries( - this.configuredProjects, - (key, project) => !project.isInitialLoadPending() ? [key, true] : void 0 - ); + forProjects ?? (forProjects = new Set( + mapDefinedIterator(this.configuredProjects.entries(), ([key, project]) => !project.isInitialLoadPending() ? key : void 0) + )); const seenProjects = /* @__PURE__ */ new Set(); - for (const project of arrayFrom(this.configuredProjects.values())) { + const currentConfiguredProjects = arrayFrom(this.configuredProjects.values()); + for (const project of currentConfiguredProjects) { if (forEachPotentialProjectReference(project, (potentialRefPath) => forProjects.has(potentialRefPath))) { updateProjectIfDirty(project); } @@ -187650,8 +188821,38 @@ Dynamic files must always be opened with service's current directory or service } this.removeOrphanScriptInfos(); } + tryInvokeWildCardDirectories(info) { + this.configFileExistenceInfoCache.forEach((configFileExistenceInfo, config) => { + var _a, _b; + if (!((_a = configFileExistenceInfo.config) == null ? void 0 : _a.parsedCommandLine) || contains( + configFileExistenceInfo.config.parsedCommandLine.fileNames, + info.fileName, + !this.host.useCaseSensitiveFileNames ? equateStringsCaseInsensitive : equateStringsCaseSensitive + )) { + return; + } + (_b = configFileExistenceInfo.config.watchedDirectories) == null ? void 0 : _b.forEach((watcher, directory) => { + if (containsPath(directory, info.fileName, !this.host.useCaseSensitiveFileNames)) { + this.logger.info(`Invoking ${config}:: wildcard for open scriptInfo:: ${info.fileName}`); + this.onWildCardDirectoryWatcherInvoke( + directory, + config, + configFileExistenceInfo.config, + watcher.watcher, + info.fileName + ); + } + }); + }); + } openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { + const existing = this.getScriptInfoForPath(normalizedPathToPath( + fileName, + projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, + this.toCanonicalFileName + )); const info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath); + if (!existing && info && !info.isDynamic) this.tryInvokeWildCardDirectories(info); const { retainProjects, ...result } = this.assignProjectToOpenedScriptInfo(info); this.cleanupProjectsAndScriptInfos( retainProjects, @@ -187798,10 +188999,16 @@ Dynamic files must always be opened with service's current directory or service } /** @internal */ applyChangesInOpenFiles(openFiles, changedFiles, closedFiles) { + let existingOpenScriptInfos; let openScriptInfos; let assignOrphanScriptInfosToInferredProject = false; if (openFiles) { for (const file of openFiles) { + (existingOpenScriptInfos ?? (existingOpenScriptInfos = [])).push(this.getScriptInfoForPath(normalizedPathToPath( + toNormalizedPath(file.fileName), + file.projectRootPath ? this.getNormalizedAbsolutePath(file.projectRootPath) : this.currentDirectory, + this.toCanonicalFileName + ))); const info = this.getOrCreateOpenScriptInfo( toNormalizedPath(file.fileName), file.content, @@ -187829,6 +189036,10 @@ Dynamic files must always be opened with service's current directory or service } } let retainProjects; + forEach( + existingOpenScriptInfos, + (existing, index) => !existing && openScriptInfos[index] && !openScriptInfos[index].isDynamic ? this.tryInvokeWildCardDirectories(openScriptInfos[index]) : void 0 + ); openScriptInfos == null ? void 0 : openScriptInfos.forEach((info) => { var _a; return (_a = this.assignProjectToOpenedScriptInfo(info).retainProjects) == null ? void 0 : _a.forEach((p) => (retainProjects ?? (retainProjects = /* @__PURE__ */ new Set())).add(p)); @@ -188071,12 +189282,12 @@ Dynamic files must always be opened with service's current directory or service return; } this.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`); - if (!pluginConfigEntry.name || isExternalModuleNameRelative(pluginConfigEntry.name) || /[\\/]\.\.?($|[\\/])/.test(pluginConfigEntry.name)) { + if (!pluginConfigEntry.name || isExternalModuleNameRelative(pluginConfigEntry.name) || /[\\/]\.\.?(?:$|[\\/])/.test(pluginConfigEntry.name)) { this.logger.info(`Skipped loading plugin ${pluginConfigEntry.name || JSON.stringify(pluginConfigEntry)} because only package name is allowed plugin name`); return; } if (this.host.importPlugin) { - const importPromise = Project3.importServicePluginAsync( + const importPromise = Project2.importServicePluginAsync( pluginConfigEntry, searchPaths, this.host, @@ -188090,7 +189301,7 @@ Dynamic files must always be opened with service's current directory or service } this.endEnablePlugin( project, - Project3.importServicePluginSync( + Project2.importServicePluginSync( pluginConfigEntry, searchPaths, this.host, @@ -188100,7 +189311,6 @@ Dynamic files must always be opened with service's current directory or service } /** * Performs the remaining steps of enabling a plugin after its module has been instantiated. - * @internal */ endEnablePlugin(project, { pluginConfigEntry, resolvedModule, errorLogs }) { var _a; @@ -188216,7 +189426,6 @@ Dynamic files must always be opened with service's current directory or service } }); } - /** @internal */ watchPackageJsonFile(file, path, project) { Debug.assert(project !== void 0); let result = (this.packageJsonFilesMap ?? (this.packageJsonFilesMap = /* @__PURE__ */ new Map())).get(path); @@ -188257,7 +189466,6 @@ Dynamic files must always be opened with service's current directory or service result.projects.add(project); (project.packageJsonWatches ?? (project.packageJsonWatches = /* @__PURE__ */ new Set())).add(result); } - /** @internal */ onPackageJsonChange(result) { result.projects.forEach((project) => { var _a; @@ -188282,7 +189490,7 @@ Dynamic files must always be opened with service's current directory or service }; /** Makes a filename safe to insert in a RegExp */ _ProjectService.filenameEscapeRegexp = /[-/\\^$*+?.()|[\]{}]/g; -var ProjectService3 = _ProjectService; +var ProjectService2 = _ProjectService; function createIncompleteCompletionsCache() { let info; return { @@ -188326,6 +189534,8 @@ function createModuleSpecifierCache(host) { kind, modulePaths, moduleSpecifiers, + /*packageName*/ + void 0, /*isBlockedByPackageJsonDependencies*/ false )); @@ -188356,16 +189566,19 @@ function createModuleSpecifierCache(host) { modulePaths, /*moduleSpecifiers*/ void 0, + /*packageName*/ + void 0, /*isBlockedByPackageJsonDependencies*/ void 0 )); } }, - setBlockedByPackageJsonDependencies(fromFileName, toFileName2, preferences, options, isBlockedByPackageJsonDependencies) { + setBlockedByPackageJsonDependencies(fromFileName, toFileName2, preferences, options, packageName, isBlockedByPackageJsonDependencies) { const cache2 = ensureCache(fromFileName, preferences, options); const info = cache2.get(toFileName2); if (info) { info.isBlockedByPackageJsonDependencies = isBlockedByPackageJsonDependencies; + info.packageName = packageName; } else { cache2.set(toFileName2, createInfo( /*kind*/ @@ -188374,6 +189587,7 @@ function createModuleSpecifierCache(host) { void 0, /*moduleSpecifiers*/ void 0, + packageName, isBlockedByPackageJsonDependencies )); } @@ -188403,8 +189617,8 @@ function createModuleSpecifierCache(host) { function key(fromFileName, preferences, options) { return `${fromFileName},${preferences.importModuleSpecifierEnding},${preferences.importModuleSpecifierPreference},${options.overrideImportMode}`; } - function createInfo(kind, modulePaths, moduleSpecifiers, isBlockedByPackageJsonDependencies) { - return { kind, modulePaths, moduleSpecifiers, isBlockedByPackageJsonDependencies }; + function createInfo(kind, modulePaths, moduleSpecifiers, packageName, isBlockedByPackageJsonDependencies) { + return { kind, modulePaths, moduleSpecifiers, packageName, isBlockedByPackageJsonDependencies }; } } @@ -188556,11 +189770,12 @@ var MultistepOperation = class { } complete() { if (this.requestId !== void 0) { - this.operationHost.sendRequestCompletedEvent(this.requestId); + this.operationHost.sendRequestCompletedEvent(this.requestId, this.performanceData); this.requestId = void 0; } this.setTimerHandle(void 0); this.setImmediateId(void 0); + this.performanceData = void 0; } immediate(actionType, action) { const requestId = this.requestId; @@ -188568,7 +189783,7 @@ var MultistepOperation = class { this.setImmediateId( this.operationHost.getServerHost().setImmediate(() => { this.immediateId = void 0; - this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action)); + this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action), this.performanceData); }, actionType) ); } @@ -188579,7 +189794,7 @@ var MultistepOperation = class { this.operationHost.getServerHost().setTimeout( () => { this.timerHandle = void 0; - this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action)); + this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action), this.performanceData); }, ms, actionType @@ -188608,6 +189823,7 @@ var MultistepOperation = class { this.operationHost.logError(e, `delayed processing of request ${this.requestId}`); } } + this.performanceData = this.operationHost.getPerformanceData(); if (stop || !this.hasPendingWork()) { this.complete(); } @@ -188961,6 +190177,9 @@ var invalidSyntacticModeCommands = [ var Session3 = class _Session { constructor(opts) { this.changeSeq = 0; + // Minimum number of lines for attempting to use region diagnostics for a file. + /** @internal */ + this.regionDiagLineCountThreshold = 500; this.handlers = new Map(Object.entries({ // TODO(jakebailey): correctly type the handlers ["status" /* Status */]: () => { @@ -189061,7 +190280,10 @@ var Session3 = class _Session { }, ["exit" /* Exit */]: () => { this.exit(); - return this.notRequired(); + return this.notRequired( + /*request*/ + void 0 + ); }, ["definition" /* Definition */]: (request) => { return this.requiredResponse(this.getDefinition( @@ -189153,7 +190375,7 @@ var Session3 = class _Session { // TODO: GH#18217 request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : void 0 ); - return this.notRequired(); + return this.notRequired(request); }, ["quickinfo" /* Quickinfo */]: (request) => { return this.requiredResponse(this.getQuickInfoWorker( @@ -189303,41 +190525,39 @@ var Session3 = class _Session { }, ["geterr" /* Geterr */]: (request) => { this.errorCheck.startNew((next) => this.getDiagnostics(next, request.arguments.delay, request.arguments.files)); - return this.notRequired(); + return this.notRequired( + /*request*/ + void 0 + ); }, ["geterrForProject" /* GeterrForProject */]: (request) => { this.errorCheck.startNew((next) => this.getDiagnosticsForProject(next, request.arguments.delay, request.arguments.file)); - return this.notRequired(); + return this.notRequired( + /*request*/ + void 0 + ); }, ["change" /* Change */]: (request) => { this.change(request.arguments); - return this.notRequired(); + return this.notRequired(request); }, ["configure" /* Configure */]: (request) => { this.projectService.setHostConfiguration(request.arguments); - this.doOutput( - /*info*/ - void 0, - "configure" /* Configure */, - request.seq, - /*success*/ - true - ); - return this.notRequired(); + return this.notRequired(request); }, ["reload" /* Reload */]: (request) => { - this.reload(request.arguments, request.seq); + this.reload(request.arguments); return this.requiredResponse({ reloadFinished: true }); }, ["saveto" /* Saveto */]: (request) => { const savetoArgs = request.arguments; this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); - return this.notRequired(); + return this.notRequired(request); }, ["close" /* Close */]: (request) => { const closeArgs = request.arguments; this.closeClientFile(closeArgs.file); - return this.notRequired(); + return this.notRequired(request); }, ["navto" /* Navto */]: (request) => { return this.requiredResponse(this.getNavigateToItems( @@ -189419,9 +190639,9 @@ var Session3 = class _Session { ["projectInfo" /* ProjectInfo */]: (request) => { return this.requiredResponse(this.getProjectInfo(request.arguments)); }, - ["reloadProjects" /* ReloadProjects */]: () => { + ["reloadProjects" /* ReloadProjects */]: (request) => { this.projectService.reloadProjects(); - return this.notRequired(); + return this.notRequired(request); }, ["jsxClosingTag" /* JsxClosingTag */]: (request) => { return this.requiredResponse(this.getJsxClosingTag(request.arguments)); @@ -189516,15 +190736,7 @@ var Session3 = class _Session { }, ["configurePlugin" /* ConfigurePlugin */]: (request) => { this.configurePlugin(request.arguments); - this.doOutput( - /*info*/ - void 0, - "configurePlugin" /* ConfigurePlugin */, - request.seq, - /*success*/ - true - ); - return this.notRequired(); + return this.notRequired(request); }, ["selectionRange" /* SelectionRange */]: (request) => { return this.requiredResponse(this.getSmartSelectionRange( @@ -189624,11 +190836,12 @@ var Session3 = class _Session { const { throttleWaitMilliseconds } = opts; this.eventHandler = this.canUseEvents ? opts.eventHandler || ((event) => this.defaultEventHandler(event)) : void 0; const multistepOperationHost = { - executeWithRequestId: (requestId, action) => this.executeWithRequestId(requestId, action), + executeWithRequestId: (requestId, action, performanceData) => this.executeWithRequestId(requestId, action, performanceData), getCurrentRequestId: () => this.currentRequestId, + getPerformanceData: () => this.performanceData, getServerHost: () => this.host, logError: (err, cmd) => this.logError(err, cmd), - sendRequestCompletedEvent: (requestId) => this.sendRequestCompletedEvent(requestId), + sendRequestCompletedEvent: (requestId, performanceData) => this.sendRequestCompletedEvent(requestId, performanceData), isCancellationRequested: () => this.cancellationToken.isCancellationRequested() }; this.errorCheck = new MultistepOperation(multistepOperationHost); @@ -189651,7 +190864,7 @@ var Session3 = class _Session { canUseWatchEvents: opts.canUseWatchEvents, incrementalVerifier: opts.incrementalVerifier }; - this.projectService = new ProjectService3(settings); + this.projectService = new ProjectService2(settings); this.projectService.setPerformanceEventHandler(this.performanceEventHandler.bind(this)); this.gcTimer = new GcTimer( this.host, @@ -189680,8 +190893,14 @@ var Session3 = class _Session { Debug.assertNever(this.projectService.serverMode); } } - sendRequestCompletedEvent(requestId) { - this.event({ request_seq: requestId }, "requestCompleted"); + sendRequestCompletedEvent(requestId, performanceData) { + this.event( + { + request_seq: requestId, + performanceData: performanceData && toProtocolPerformanceData(performanceData) + }, + "requestCompleted" + ); } addPerformanceData(key, value) { if (!this.performanceData) { @@ -189689,6 +190908,15 @@ var Session3 = class _Session { } this.performanceData[key] = (this.performanceData[key] ?? 0) + value; } + addDiagnosticsPerformanceData(file, kind, duration) { + var _a, _b; + if (!this.performanceData) { + this.performanceData = {}; + } + let fileDiagnosticDuration = (_a = this.performanceData.diagnosticsDuration) == null ? void 0 : _a.get(file); + if (!fileDiagnosticDuration) ((_b = this.performanceData).diagnosticsDuration ?? (_b.diagnosticsDuration = /* @__PURE__ */ new Map())).set(file, fileDiagnosticDuration = {}); + fileDiagnosticDuration[kind] = duration; + } performanceEventHandler(event) { switch (event.kind) { case "UpdateGraph": @@ -189831,23 +191059,21 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter this.writeMessage(msg); } writeMessage(msg) { - var _a; const msgText = formatMessage2(msg, this.logger, this.byteLength, this.host.newLine); - (_a = perfLogger) == null ? void 0 : _a.logEvent(`Response message size: ${msgText.length}`); this.host.write(msgText); } event(body, eventName) { this.send(toEvent(eventName, body)); } /** @internal */ - doOutput(info, cmdName, reqSeq, success, message) { + doOutput(info, cmdName, reqSeq, success, performanceData, message) { const res = { seq: 0, type: "response", command: cmdName, request_seq: reqSeq, success, - performanceData: this.performanceData + performanceData: performanceData && toProtocolPerformanceData(performanceData) }; if (success) { let metadata; @@ -189877,32 +191103,70 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter } semanticCheck(file, project) { var _a, _b; + const diagnosticsStartTime = timestamp(); (_a = tracing) == null ? void 0 : _a.push(tracing.Phase.Session, "semanticCheck", { file, configFilePath: project.canonicalConfigFilePath }); const diags = isDeclarationFileInJSOnlyNonConfiguredProject(project, file) ? emptyArray2 : project.getLanguageService().getSemanticDiagnostics(file).filter((d) => !!d.file); - this.sendDiagnosticsEvent(file, project, diags, "semanticDiag"); + this.sendDiagnosticsEvent(file, project, diags, "semanticDiag", diagnosticsStartTime); (_b = tracing) == null ? void 0 : _b.pop(); } syntacticCheck(file, project) { var _a, _b; + const diagnosticsStartTime = timestamp(); (_a = tracing) == null ? void 0 : _a.push(tracing.Phase.Session, "syntacticCheck", { file, configFilePath: project.canonicalConfigFilePath }); - this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag"); + this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag", diagnosticsStartTime); (_b = tracing) == null ? void 0 : _b.pop(); } suggestionCheck(file, project) { var _a, _b; + const diagnosticsStartTime = timestamp(); (_a = tracing) == null ? void 0 : _a.push(tracing.Phase.Session, "suggestionCheck", { file, configFilePath: project.canonicalConfigFilePath }); - this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag"); + this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag", diagnosticsStartTime); (_b = tracing) == null ? void 0 : _b.pop(); } - sendDiagnosticsEvent(file, project, diagnostics, kind) { + regionSemanticCheck(file, project, ranges) { + var _a, _b, _c; + const diagnosticsStartTime = timestamp(); + (_a = tracing) == null ? void 0 : _a.push(tracing.Phase.Session, "regionSemanticCheck", { file, configFilePath: project.canonicalConfigFilePath }); + let diagnosticsResult; + if (!this.shouldDoRegionCheck(file) || !(diagnosticsResult = project.getLanguageService().getRegionSemanticDiagnostics(file, ranges))) { + (_b = tracing) == null ? void 0 : _b.pop(); + return; + } + this.sendDiagnosticsEvent(file, project, diagnosticsResult.diagnostics, "regionSemanticDiag", diagnosticsStartTime, diagnosticsResult.spans); + (_c = tracing) == null ? void 0 : _c.pop(); + return; + } + // We should only do the region-based semantic check if we think it would be + // considerably faster than a whole-file semantic check. + /** @internal */ + shouldDoRegionCheck(file) { + var _a; + const lineCount = (_a = this.projectService.getScriptInfoForNormalizedPath(file)) == null ? void 0 : _a.textStorage.getLineInfo().getLineCount(); + return !!(lineCount && lineCount >= this.regionDiagLineCountThreshold); + } + sendDiagnosticsEvent(file, project, diagnostics, kind, diagnosticsStartTime, spans) { try { - this.event({ file, diagnostics: diagnostics.map((diag2) => formatDiag(file, project, diag2)) }, kind); + const scriptInfo = Debug.checkDefined(project.getScriptInfo(file)); + const duration = timestamp() - diagnosticsStartTime; + const body = { + file, + diagnostics: diagnostics.map((diag2) => formatDiag(file, project, diag2)), + spans: spans == null ? void 0 : spans.map((span) => toProtocolTextSpan(span, scriptInfo)) + }; + this.event( + body, + kind + ); + this.addDiagnosticsPerformanceData(file, kind, duration); } catch (err) { this.logError(err, kind); } } /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */ updateErrorCheck(next, checkList, ms, requireOpen = true) { + if (checkList.length === 0) { + return; + } Debug.assert(!this.suppressDiagnosticEvents); const seq = this.changeSeq; const followMs = Math.min(ms, 200); @@ -189910,20 +191174,36 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter const goNext = () => { index++; if (checkList.length > index) { - next.delay("checkOne", followMs, checkOne); + return next.delay("checkOne", followMs, checkOne); } }; + const doSemanticCheck = (fileName, project) => { + this.semanticCheck(fileName, project); + if (this.changeSeq !== seq) { + return; + } + if (this.getPreferences(fileName).disableSuggestions) { + return goNext(); + } + next.immediate("suggestionCheck", () => { + this.suggestionCheck(fileName, project); + goNext(); + }); + }; const checkOne = () => { if (this.changeSeq !== seq) { return; } + let ranges; let item = checkList[index]; if (isString(item)) { item = this.toPendingErrorCheck(item); - if (!item) { - goNext(); - return; - } + } else if ("ranges" in item) { + ranges = item.ranges; + item = this.toPendingErrorCheck(item.file); + } + if (!item) { + return goNext(); } const { fileName, project } = item; updateProjectIfDirty(project); @@ -189935,23 +191215,21 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter return; } if (project.projectService.serverMode !== 0 /* Semantic */) { - goNext(); - return; + return goNext(); } - next.immediate("semanticCheck", () => { - this.semanticCheck(fileName, project); - if (this.changeSeq !== seq) { - return; - } - if (this.getPreferences(fileName).disableSuggestions) { - goNext(); - return; - } - next.immediate("suggestionCheck", () => { - this.suggestionCheck(fileName, project); - goNext(); + if (ranges) { + return next.immediate("regionSemanticCheck", () => { + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(fileName); + if (scriptInfo) { + this.regionSemanticCheck(fileName, project, ranges.map((range) => this.getRange({ file: fileName, ...range }, scriptInfo))); + } + if (this.changeSeq !== seq) { + return; + } + next.immediate("semanticCheck", () => doSemanticCheck(fileName, project)); }); - }); + } + next.immediate("semanticCheck", () => doSemanticCheck(fileName, project)); }; if (checkList.length > index && this.changeSeq === seq) { next.delay("checkOne", ms, checkOne); @@ -190188,7 +191466,7 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex); const packageJsonCache = (_a2 = project.getModuleResolutionCache()) == null ? void 0 : _a2.getPackageJsonInfoCache(); const compilerOptions = project.getCompilationSettings(); - const packageJson = getPackageScopeForPath(getNormalizedAbsolutePath(packageDirectory + "/package.json", project.getCurrentDirectory()), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions)); + const packageJson = getPackageScopeForPath(getNormalizedAbsolutePath(packageDirectory, project.getCurrentDirectory()), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions)); if (!packageJson) return void 0; const entrypoints = getEntrypointsFromPackageJsonInfo( packageJson, @@ -190872,42 +192150,12 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter const prefix = args.prefix || ""; const entries = mapDefined(completions.entries, (entry) => { if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) { - const { - name, - kind: kind2, - kindModifiers, - sortText, - insertText, - filterText, - replacementSpan, - hasAction, - source, - sourceDisplay, - labelDetails, - isSnippet, - isRecommended, - isPackageJsonImport, - isImportStatementCompletion, - data - } = entry; - const convertedSpan = replacementSpan ? toProtocolTextSpan(replacementSpan, scriptInfo) : void 0; + const convertedSpan = entry.replacementSpan ? toProtocolTextSpan(entry.replacementSpan, scriptInfo) : void 0; return { - name, - kind: kind2, - kindModifiers, - sortText, - insertText, - filterText, + ...entry, replacementSpan: convertedSpan, - isSnippet, - hasAction: hasAction || void 0, - source, - sourceDisplay, - labelDetails, - isRecommended, - isPackageJsonImport, - isImportStatementCompletion, - data + hasAction: entry.hasAction || void 0, + symbol: void 0 }; } }); @@ -191030,12 +192278,12 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter const project = this.projectService.tryGetDefaultProjectForFile(fileName); return project && { fileName, project }; } - getDiagnostics(next, delay, fileNames) { + getDiagnostics(next, delay, fileArgs) { if (this.suppressDiagnosticEvents) { return; } - if (fileNames.length > 0) { - this.updateErrorCheck(next, fileNames, delay); + if (fileArgs.length > 0) { + this.updateErrorCheck(next, fileArgs, delay); } } change(args) { @@ -191056,22 +192304,13 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter ); } } - reload(args, reqSeq) { + reload(args) { const file = toNormalizedPath(args.file); const tempFileName = args.tmpfile === void 0 ? void 0 : toNormalizedPath(args.tmpfile); const info = this.projectService.getScriptInfoForNormalizedPath(file); if (info) { this.changeSeq++; - if (info.reloadFromFile(tempFileName)) { - this.doOutput( - /*info*/ - void 0, - "reload" /* Reload */, - reqSeq, - /*success*/ - true - ); - } + info.reloadFromFile(tempFileName); } } saveToTmp(fileName, tempFileName) { @@ -191620,11 +192859,20 @@ ${e.message}`; } exit() { } - notRequired() { - return { responseRequired: false }; + notRequired(request) { + if (request) this.doOutput( + /*info*/ + void 0, + request.command, + request.seq, + /*success*/ + true, + this.performanceData + ); + return { responseRequired: false, performanceData: this.performanceData }; } requiredResponse(response) { - return { response, responseRequired: true }; + return { response, responseRequired: true, performanceData: this.performanceData }; } addProtocolHandler(command, handler) { if (this.handlers.has(command)) { @@ -191642,18 +192890,27 @@ ${e.message}`; this.currentRequestId = void 0; this.cancellationToken.resetRequest(requestId); } - executeWithRequestId(requestId, f) { + // eslint-disable-line @typescript-eslint/unified-signatures + executeWithRequestId(requestId, f, perfomanceData) { + const currentPerformanceData = this.performanceData; try { + this.performanceData = perfomanceData; this.setCurrentRequest(requestId); return f(); } finally { this.resetCurrentRequest(requestId); + this.performanceData = currentPerformanceData; } } executeCommand(request) { const handler = this.handlers.get(request.command); if (handler) { - const response = this.executeWithRequestId(request.seq, () => handler(request)); + const response = this.executeWithRequestId( + request.seq, + () => handler(request), + /*perfomanceData*/ + void 0 + ); this.projectService.enableRequestedPlugins(); return response; } else { @@ -191665,16 +192922,18 @@ ${e.message}`; request.seq, /*success*/ false, + /*performanceData*/ + void 0, `Unrecognized JSON command: ${request.command}` ); return { responseRequired: false }; } } onMessage(message) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k; + var _a, _b, _c, _d, _e, _f, _g; this.gcTimer.scheduleCollect(); - this.performanceData = void 0; let start; + const currentPerformanceData = this.performanceData; if (this.logger.hasLevel(2 /* requestTime */)) { start = this.hrtime(); if (this.logger.hasLevel(3 /* verbose */)) { @@ -191687,16 +192946,15 @@ ${e.message}`; request = this.parseMessage(message); relevantFile = request.arguments && request.arguments.file ? request.arguments : void 0; (_a = tracing) == null ? void 0 : _a.instant(tracing.Phase.Session, "request", { seq: request.seq, command: request.command }); - (_b = perfLogger) == null ? void 0 : _b.logStartCommand("" + request.command, this.toStringMessage(message).substring(0, 100)); - (_c = tracing) == null ? void 0 : _c.push( + (_b = tracing) == null ? void 0 : _b.push( tracing.Phase.Session, "executeCommand", { seq: request.seq, command: request.command }, /*separateBeginAndEnd*/ true ); - const { response, responseRequired } = this.executeCommand(request); - (_d = tracing) == null ? void 0 : _d.pop(); + const { response, responseRequired, performanceData } = this.executeCommand(request); + (_c = tracing) == null ? void 0 : _c.pop(); if (this.logger.hasLevel(2 /* requestTime */)) { const elapsedTime = hrTimeToMilliseconds(this.hrtime(start)).toFixed(4); if (responseRequired) { @@ -191705,15 +192963,15 @@ ${e.message}`; this.logger.perftrc(`${request.seq}::${request.command}: async elapsed time (in milliseconds) ${elapsedTime}`); } } - (_e = perfLogger) == null ? void 0 : _e.logStopCommand("" + request.command, "Success"); - (_f = tracing) == null ? void 0 : _f.instant(tracing.Phase.Session, "response", { seq: request.seq, command: request.command, success: !!response }); + (_d = tracing) == null ? void 0 : _d.instant(tracing.Phase.Session, "response", { seq: request.seq, command: request.command, success: !!response }); if (response) { this.doOutput( response, request.command, request.seq, /*success*/ - true + true, + performanceData ); } else if (responseRequired) { this.doOutput( @@ -191723,26 +192981,26 @@ ${e.message}`; request.seq, /*success*/ false, + performanceData, "No content available." ); } } catch (err) { - (_g = tracing) == null ? void 0 : _g.popAll(); + (_e = tracing) == null ? void 0 : _e.popAll(); if (err instanceof OperationCanceledException) { - (_h = perfLogger) == null ? void 0 : _h.logStopCommand("" + (request && request.command), "Canceled: " + err); - (_i = tracing) == null ? void 0 : _i.instant(tracing.Phase.Session, "commandCanceled", { seq: request == null ? void 0 : request.seq, command: request == null ? void 0 : request.command }); + (_f = tracing) == null ? void 0 : _f.instant(tracing.Phase.Session, "commandCanceled", { seq: request == null ? void 0 : request.seq, command: request == null ? void 0 : request.command }); this.doOutput( { canceled: true }, request.command, request.seq, /*success*/ - true + true, + this.performanceData ); return; } this.logErrorWorker(err, this.toStringMessage(message), relevantFile); - (_j = perfLogger) == null ? void 0 : _j.logStopCommand("" + (request && request.command), "Error: " + err); - (_k = tracing) == null ? void 0 : _k.instant(tracing.Phase.Session, "commandError", { seq: request == null ? void 0 : request.seq, command: request == null ? void 0 : request.command, message: err.message }); + (_g = tracing) == null ? void 0 : _g.instant(tracing.Phase.Session, "commandError", { seq: request == null ? void 0 : request.seq, command: request == null ? void 0 : request.command, message: err.message }); this.doOutput( /*info*/ void 0, @@ -191750,8 +193008,11 @@ ${e.message}`; request ? request.seq : 0, /*success*/ false, + this.performanceData, "Error processing request. " + err.message + "\n" + err.stack ); + } finally { + this.performanceData = currentPerformanceData; } } parseMessage(message) { @@ -191773,6 +193034,10 @@ ${e.message}`; return this.projectService.getHostPreferences(); } }; +function toProtocolPerformanceData(performanceData) { + const diagnosticsDuration = performanceData.diagnosticsDuration && arrayFrom(performanceData.diagnosticsDuration, ([file, data]) => ({ ...data, file })); + return { ...performanceData, diagnosticsDuration }; +} function toProtocolTextSpan(textSpan, scriptInfo) { return { start: scriptInfo.positionToLineOffset(textSpan.start), @@ -192753,20 +194018,19 @@ __export(ts_server_exports4, { LogLevel: () => LogLevel2, Msg: () => Msg, OpenFileInfoTelemetryEvent: () => OpenFileInfoTelemetryEvent, - Project: () => Project3, + Project: () => Project2, ProjectInfoTelemetryEvent: () => ProjectInfoTelemetryEvent, ProjectKind: () => ProjectKind, ProjectLanguageServiceStateEvent: () => ProjectLanguageServiceStateEvent, ProjectLoadingFinishEvent: () => ProjectLoadingFinishEvent, ProjectLoadingStartEvent: () => ProjectLoadingStartEvent, - ProjectService: () => ProjectService3, + ProjectService: () => ProjectService2, ProjectsUpdatedInBackgroundEvent: () => ProjectsUpdatedInBackgroundEvent, ScriptInfo: () => ScriptInfo, ScriptVersionCache: () => ScriptVersionCache, Session: () => Session3, TextStorage: () => TextStorage, ThrottledOperations: () => ThrottledOperations, - TypingsCache: () => TypingsCache, TypingsInstallerAdapter: () => TypingsInstallerAdapter, allFilesAreJsOrDts: () => allFilesAreJsOrDts, allRootFilesAreJsOrDts: () => allRootFilesAreJsOrDts, @@ -192785,7 +194049,6 @@ __export(ts_server_exports4, { createSortedArray: () => createSortedArray2, emptyArray: () => emptyArray2, findArgument: () => findArgument, - forEachResolvedProjectReferenceProject: () => forEachResolvedProjectReferenceProject, formatDiagnosticToProtocol: () => formatDiagnosticToProtocol, formatMessage: () => formatMessage2, getBaseConfigFileName: () => getBaseConfigFileName, @@ -192811,7 +194074,6 @@ __export(ts_server_exports4, { nullCancellationToken: () => nullCancellationToken, nullTypingsInstaller: () => nullTypingsInstaller, protocol: () => ts_server_protocol_exports, - removeSorted: () => removeSorted, stringifyIndented: () => stringifyIndented, toEvent: () => toEvent, toNormalizedPath: () => toNormalizedPath, @@ -192889,7 +194151,6 @@ if (typeof console !== "undefined") { GoToDefinition, HighlightSpanKind, IdentifierNameMap, - IdentifierNameMultiMap, ImportKind, ImportsNotUsedAsValues, IndentStyle, @@ -192900,6 +194161,7 @@ if (typeof console !== "undefined") { InlayHintKind, InlayHints, InternalEmitFlags, + InternalNodeBuilderFlags, InternalSymbolName, IntersectionFlags, InvalidatedProjectKind, @@ -192946,6 +194208,7 @@ if (typeof console !== "undefined") { PollingInterval, PollingWatchKind, PragmaKindFlags, + PredicateSemantics, PrivateIdentifierKind, ProcessLevel, ProgramUpdateLevel, @@ -192976,7 +194239,6 @@ if (typeof console !== "undefined") { SymbolFlags, SymbolFormatFlags, SyntaxKind, - SyntheticSymbolKind, Ternary, ThrottledCancellationToken, TokenClass, @@ -192999,7 +194261,6 @@ if (typeof console !== "undefined") { WatchLogLevel, WatchType, accessPrivateIdentifier, - addDisposableResourceHelper, addEmitFlags, addEmitHelper, addEmitHelpers, @@ -193022,23 +194283,15 @@ if (typeof console !== "undefined") { arrayFrom, arrayIsEqualTo, arrayIsHomogeneous, - arrayIsSorted, arrayOf, arrayReverseIterator, arrayToMap, arrayToMultiMap, arrayToNumericMap, - arraysEqual, assertType, assign, - assignHelper, - asyncDelegator, - asyncGeneratorHelper, asyncSuperHelper, - asyncValues, attachFileToDiagnostics, - awaitHelper, - awaiterHelper, base64decode, base64encode, binarySearch, @@ -193051,6 +194304,7 @@ if (typeof console !== "undefined") { buildOverload, bundlerModuleNameResolver, canBeConvertedToAsync, + canEmitTsBuildInfo, canHaveDecorators, canHaveExportModifier, canHaveFlowNode, @@ -193061,8 +194315,9 @@ if (typeof console !== "undefined") { canHaveJSDoc, canHaveLocals, canHaveModifiers, + canHaveModuleSpecifier, canHaveSymbol, - canIncludeBindAndCheckDiagnsotics, + canIncludeBindAndCheckDiagnostics, canJsonReportNoInputFiles, canProduceDiagnostics, canUsePropertyAccess, @@ -193079,16 +194334,13 @@ if (typeof console !== "undefined") { changeFullExtension, changesAffectModuleResolution, changesAffectingProgramStructure, - characterToRegularExpressionFlag, + characterCodeToRegularExpressionFlag, childIsDecorated, classElementOrClassElementParameterIsDecorated, classHasClassThisAssignment, classHasDeclaredOrExplicitlyAssignedName, classHasExplicitlyAssignedName, classOrConstructorParameterIsDecorated, - classPrivateFieldGetHelper, - classPrivateFieldInHelper, - classPrivateFieldSetHelper, classicNameResolver, classifier, cleanExtendedConfigCache, @@ -193096,7 +194348,6 @@ if (typeof console !== "undefined") { clearMap, clearSharedExtendedConfigFileWatcher, climbPastPropertyAccess, - climbPastPropertyOrElementAccess, clone, cloneCompilerOptions, closeFileWatcher, @@ -193109,12 +194360,10 @@ if (typeof console !== "undefined") { commandLineOptionOfCustomType, commentPragmas, commonOptionsWithBuild, - commonPackageFolders, compact, compareBooleans, compareDataObjects, compareDiagnostics, - compareDiagnosticsSkipRelatedInformation, compareEmitHelpers, compareNumberOfDirectorySeparators, comparePaths, @@ -193128,26 +194377,21 @@ if (typeof console !== "undefined") { compareStringsCaseSensitiveUI, compareTextSpans, compareValues, - compileOnSaveCommandLineOption, compilerOptionsAffectDeclarationPath, compilerOptionsAffectEmit, compilerOptionsAffectSemanticDiagnostics, compilerOptionsDidYouMeanDiagnostics, compilerOptionsIndicateEsModules, - compose, computeCommonSourceDirectoryOfFilenames, computeLineAndCharacterOfPosition, computeLineOfPosition, computeLineStarts, computePositionOfLineAndCharacter, - computeSignature, computeSignatureWithDiagnostics, computeSuggestionDiagnostics, computedOptions, concatenate, concatenateDiagnosticMessageChains, - configDirTemplateSubstitutionOptions, - configDirTemplateSubstitutionWatchOptions, consumesNodeCoreModules, contains, containsIgnoredPath, @@ -193178,16 +194422,11 @@ if (typeof console !== "undefined") { createAccessorPropertySetRedirector, createBaseNodeFactory, createBinaryExpressionTrampoline, - createBindingHelper, - createBuildInfo, createBuilderProgram, - createBuilderProgramUsingProgramBuildInfo, + createBuilderProgramUsingIncrementalBuildInfo, createBuilderStatusReporter, - createCacheWithRedirects, createCacheableExportInfoMap, createCachedDirectoryStructureHost, - createClassNamedEvaluationHelperBlock, - createClassThisAssignmentBlock, createClassifier, createCommentDirectivesMap, createCompilerDiagnostic, @@ -193239,6 +194478,7 @@ if (typeof console !== "undefined") { createMemberAccessForPropertyName, createModeAwareCache, createModeAwareCacheKey, + createModeMismatchDetails, createModuleNotFoundChain, createModuleResolutionCache, createModuleResolutionLoader, @@ -193309,9 +194549,7 @@ if (typeof console !== "undefined") { declarationNameToString, decodeMappings, decodedTextSpanIntersectsWith, - decorateHelper, deduplicate, - defaultIncludeSpec, defaultInitCompilerOptions, defaultMaximumTruncationLength, deno, @@ -193323,27 +194561,22 @@ if (typeof console !== "undefined") { displayPart, displayPartsToString, disposeEmitNodes, - disposeResourcesHelper, documentSpansEqual, dumpTracingLegend, elementAt, elideNodes, - emitComments, emitDetachedComments, emitFiles, emitFilesAndReportErrors, emitFilesAndReportErrorsAndGetExitStatus, emitModuleKindIsNonNodeESM, emitNewLineBeforeLeadingCommentOfPosition, - emitNewLineBeforeLeadingComments, - emitNewLineBeforeLeadingCommentsOfPosition, emitResolverSkipsTypeChecking, emitSkippedWithNoDiagnostics, emptyArray, emptyFileSystemEntries, emptyMap, emptyOptions, - emptySet, endsWith, ensurePathIsNonModuleName, ensureScriptKind, @@ -193354,7 +194587,6 @@ if (typeof console !== "undefined") { equateStringsCaseInsensitive, equateStringsCaseSensitive, equateValues, - esDecorateHelper, escapeJsxAttributeString, escapeLeadingUnderscores, escapeNonAsciiString, @@ -193368,15 +194600,14 @@ if (typeof console !== "undefined") { explainFiles, explainIfFileIsRedirectAndImpliedFormat, exportAssignmentIsAlias, - exportStarHelper, expressionResultIsUnused, extend, - extendsHelper, extensionFromPath, extensionIsTS, extensionsNotSupportingExtensionlessResolution, externalHelpersModuleNameText, factory, + fileContainsPackageImport, fileExtensionIs, fileExtensionIsOneOf, fileIncludeReasonToDiagnostics, @@ -193398,7 +194629,6 @@ if (typeof console !== "undefined") { findLast, findLastIndex, findListItemInfo, - findMap, findModifier, findNextToken, findPackageJson, @@ -193446,7 +194676,6 @@ if (typeof console !== "undefined") { forEachTsConfigPropArray, forEachUnique, forEachYieldExpression, - forSomeAncestorDirectory, formatColorAndReset, formatDiagnostic, formatDiagnostics, @@ -193457,11 +194686,8 @@ if (typeof console !== "undefined") { formatMessage, formatStringFromArgs, formatting, - fullTripleSlashAMDReferencePathRegEx, - fullTripleSlashReferencePathRegEx, generateDjb2Hash, generateTSConfig, - generatorHelper, getAdjustedReferenceLocation, getAdjustedRenameLocation, getAliasDeclarationFromName, @@ -193480,7 +194706,6 @@ if (typeof console !== "undefined") { getAreDeclarationMapsEnabled, getAssignedExpandoInitializer, getAssignedName, - getAssignedNameOfIdentifier, getAssignmentDeclarationKind, getAssignmentDeclarationPropertyAccessKind, getAssignmentTargetKind, @@ -193521,7 +194746,6 @@ if (typeof console !== "undefined") { getContainingObjectLiteralElement, getContextualTypeFromParent, getContextualTypeFromParentOrAncestorTypeNode, - getCurrentTime, getDeclarationDiagnostics, getDeclarationEmitExtensionForPath, getDeclarationEmitOutputFilePath, @@ -193539,6 +194763,7 @@ if (typeof console !== "undefined") { getDefaultLibFilePath, getDefaultLikeExportInfo, getDefaultLikeExportNameFromDeclaration, + getDefaultResolutionModeForFileWorker, getDiagnosticText, getDiagnosticsWithinSpan, getDirectoryPath, @@ -193569,6 +194794,7 @@ if (typeof console !== "undefined") { getEmitFlags, getEmitHelpers, getEmitModuleDetectionKind, + getEmitModuleFormatOfFileWorker, getEmitModuleKind, getEmitModuleResolutionKind, getEmitScriptTarget, @@ -193619,11 +194845,11 @@ if (typeof console !== "undefined") { getIdentifierGeneratedImportReference, getIdentifierTypeArguments, getImmediatelyInvokedFunctionExpression, + getImpliedNodeFormatForEmitWorker, getImpliedNodeFormatForFile, getImpliedNodeFormatForFileWorker, getImportNeedsImportDefaultHelper, getImportNeedsImportStarHelper, - getIndentSize, getIndentString, getInferredLibraryNameResolveFrom, getInitializedVariables, @@ -193632,6 +194858,7 @@ if (typeof console !== "undefined") { getInterfaceBaseTypeNodes, getInternalEmitFlags, getInvokedExpression, + getIsFileExcluded, getIsolatedModules, getJSDocAugmentsTag, getJSDocClassTag, @@ -193660,7 +194887,6 @@ if (typeof console !== "undefined") { getJSDocSatisfiesExpressionType, getJSDocSatisfiesTag, getJSDocTags, - getJSDocTagsNoCache, getJSDocTemplateTag, getJSDocThisTag, getJSDocType, @@ -193684,7 +194910,6 @@ if (typeof console !== "undefined") { getLineAndCharacterOfPosition, getLineInfo, getLineOfLocalPosition, - getLineOfLocalPositionFromLineMap, getLineStartPositionForPosition, getLineStarts, getLinesBetweenPositionAndNextNonWhitespaceCharacter, @@ -193726,7 +194951,6 @@ if (typeof console !== "undefined") { getNameOfScriptTarget, getNameOrArgument, getNameTable, - getNamesForExportedSymbol, getNamespaceDeclarationNode, getNewLineCharacter, getNewLineKind, @@ -193743,49 +194967,43 @@ if (typeof console !== "undefined") { getNonAssignmentOperatorForCompoundAssignment, getNonAugmentationDeclaration, getNonDecoratorTokenPosOfNode, + getNonIncrementalBuildInfoRoots, + getNonModifierTokenPosOfNode, getNormalizedAbsolutePath, getNormalizedAbsolutePathWithoutRoot, getNormalizedPathComponents, getObjectFlags, - getOperator, getOperatorAssociativity, getOperatorPrecedence, getOptionFromName, getOptionsForLibraryResolution, getOptionsNameMap, getOrCreateEmitNode, - getOrCreateExternalHelpersModuleNameIfNeeded, getOrUpdate, getOriginalNode, getOriginalNodeId, - getOriginalSourceFile, getOutputDeclarationFileName, getOutputDeclarationFileNameWorker, getOutputExtension, getOutputFileNames, getOutputJSFileNameWorker, getOutputPathsFor, - getOutputPathsForBundle, getOwnEmitOutputFilePath, getOwnKeys, getOwnValues, - getPackageJsonInfo, getPackageJsonTypesVersionsPaths, - getPackageJsonsVisibleToFile, getPackageNameFromTypesPackageName, getPackageScopeForPath, getParameterSymbolFromJSDoc, - getParameterTypeNode, getParentNodeInSpan, getParseTreeNode, getParsedCommandLineOfConfigFile, getPathComponents, - getPathComponentsRelativeTo, getPathFromPathComponents, getPathUpdater, getPathsBasePath, getPatternFromSpec, - getPendingEmitKind, + getPendingEmitKindWithSeen, getPositionOfLineAndCharacter, getPossibleGenericSignatures, getPossibleOriginalInputExtensionForExtension, @@ -193798,7 +195016,6 @@ if (typeof console !== "undefined") { getPropertyArrayElementValue, getPropertyAssignmentAliasLikeExpression, getPropertyNameForPropertyNameNode, - getPropertyNameForUniqueESSymbol, getPropertyNameFromType, getPropertyNameOfBindingOrAssignmentElement, getPropertySymbolFromBindingElement, @@ -193822,13 +195039,14 @@ if (typeof console !== "undefined") { getResolvePackageJsonExports, getResolvePackageJsonImports, getResolvedExternalModuleName, + getResolvedModuleFromResolution, + getResolvedTypeReferenceDirectiveFromResolution, getRestIndicatorOfBindingOrAssignmentElement, getRestParameterElementType, getRightMostAssignedExpression, getRootDeclaration, getRootDirectoryOfResolutionCache, getRootLength, - getRootPathSplitLength, getScriptKind, getScriptKindFromFileName, getScriptTargetFeatures, @@ -193840,14 +195058,12 @@ if (typeof console !== "undefined") { getSetAccessorValueParameter, getSetExternalModuleIndicator, getShebang, - getSingleInitializerOfVariableStatementOrPropertyDeclaration, getSingleVariableOfVariableStatement, getSnapshotText, getSnippetElement, getSourceFileOfModule, getSourceFileOfNode, getSourceFilePathInNewDir, - getSourceFilePathInNewDirWorker, getSourceFileVersionAsHashFromText, getSourceFilesToEmit, getSourceMapRange, @@ -193870,7 +195086,6 @@ if (typeof console !== "undefined") { getSwitchedType, getSymbolId, getSymbolNameForPrivateIdentifier, - getSymbolParentOrFail, getSymbolTarget, getSyntacticClassifications, getSyntacticModifierFlags, @@ -193901,7 +195116,6 @@ if (typeof console !== "undefined") { getTouchingToken, getTrailingCommentRanges, getTrailingSemicolonDeferringWriter, - getTransformFlagsSubtreeExclusions, getTransformers, getTsBuildInfoEmitOutputFilePath, getTsConfigObjectLiteralExpression, @@ -193929,7 +195143,6 @@ if (typeof console !== "undefined") { hasAccessorModifier, hasAmbientModifier, hasChangesInResolutions, - hasChildOfKind, hasContextSensitiveParameters, hasDecorators, hasDocComment, @@ -193938,6 +195151,7 @@ if (typeof console !== "undefined") { hasEffectiveModifiers, hasEffectiveReadonlyModifier, hasExtension, + hasImplementationTSFileExtension, hasIndexSignature, hasInferredType, hasInitializer, @@ -193965,7 +195179,6 @@ if (typeof console !== "undefined") { hasType, hasTypeArguments, hasZeroOrOneAsteriskCharacter, - helperString, hostGetCanonicalFileName, hostUsesCaseSensitiveFileNames, idText, @@ -193975,9 +195188,8 @@ if (typeof console !== "undefined") { identitySourceMapConsumer, ignoreSourceNewlines, ignoredPaths, - importDefaultHelper, importFromModuleSpecifier, - importStarHelper, + importSyntaxAffectsModuleResolution, indexOfAnyCharCode, indexOfNode, indicesOf, @@ -193985,7 +195197,6 @@ if (typeof console !== "undefined") { injectClassNamedEvaluationHelperBlockIfMissing, injectClassThisAssignmentIfMissing, insertImports, - insertLeadingStatement, insertSorted, insertStatementAfterCustomPrologue, insertStatementAfterStandardPrologue, @@ -194001,11 +195212,9 @@ if (typeof console !== "undefined") { isAccessibilityModifier, isAccessor, isAccessorModifier, - isAliasSymbolDeclaration, isAliasableExpression, isAmbientModule, isAmbientPropertyDeclaration, - isAnonymousFunctionDefinition, isAnyDirectorySeparator, isAnyImportOrBareOrAccessedRequire, isAnyImportOrReExport, @@ -194041,6 +195250,7 @@ if (typeof console !== "undefined") { isAwaitKeyword, isBigIntLiteral, isBinaryExpression, + isBinaryLogicalOperator, isBinaryOperatorToken, isBindableObjectDefinePropertyCall, isBindableStaticAccessExpression, @@ -194081,7 +195291,6 @@ if (typeof console !== "undefined") { isCatchClauseVariableDeclaration, isCatchClauseVariableDeclarationOrBindingElement, isCheckJsEnabledForFile, - isChildOfNodeWithKind, isCircularBuildOrder, isClassDeclaration, isClassElement, @@ -194093,7 +195302,6 @@ if (typeof console !== "undefined") { isClassOrTypeElement, isClassStaticBlockDeclaration, isClassThisAssignmentBlock, - isCollapsedRange, isColonToken, isCommaExpression, isCommaListExpression, @@ -194136,16 +195344,13 @@ if (typeof console !== "undefined") { isDeleteTarget, isDeprecatedDeclaration, isDestructuringAssignment, - isDiagnosticWithLocation, isDiskPathRoot, isDoStatement, isDocumentRegistryEntry, isDotDotDotToken, isDottedName, isDynamicName, - isESSymbolIdentifier, isEffectiveExternalModule, - isEffectiveModuleDeclaration, isEffectiveStrictModeSourceFile, isElementAccessChain, isElementAccessExpression, @@ -194215,13 +195420,11 @@ if (typeof console !== "undefined") { isFunctionOrModuleBlock, isFunctionSymbol, isFunctionTypeNode, - isFutureReservedKeyword, isGeneratedIdentifier, isGeneratedPrivateIdentifier, isGetAccessor, isGetAccessorDeclaration, isGetOrSetAccessorDeclaration, - isGlobalDeclaration, isGlobalScopeAugmentation, isGlobalSourceFile, isGrammarError, @@ -194269,6 +195472,8 @@ if (typeof console !== "undefined") { isInTemplateString, isInTopLevelContext, isInTypeQuery, + isIncrementalBuildInfo, + isIncrementalBundleEmitBuildInfo, isIncrementalCompilation, isIndexSignatureDeclaration, isIndexedAccessTypeNode, @@ -194375,7 +195580,6 @@ if (typeof console !== "undefined") { isLabeledStatement, isLateVisibilityPaintedStatement, isLeftHandSideExpression, - isLeftHandSideOfAssignment, isLet, isLineBreak, isLiteralComputedPropertyDeclarationName, @@ -194383,10 +195587,7 @@ if (typeof console !== "undefined") { isLiteralExpressionOfObject, isLiteralImportTypeNode, isLiteralKind, - isLiteralLikeAccess, - isLiteralLikeElementAccess, isLiteralNameOfPropertyDeclarationOrIndexAccess, - isLiteralTypeLikeExpression, isLiteralTypeLiteral, isLiteralTypeNode, isLocalName, @@ -194411,6 +195612,7 @@ if (typeof console !== "undefined") { isModuleBlock, isModuleBody, isModuleDeclaration, + isModuleExportName, isModuleExportsAccessExpression, isModuleIdentifier, isModuleName, @@ -194420,7 +195622,6 @@ if (typeof console !== "undefined") { isModuleWithStringLiteralName, isNameOfFunctionDeclaration, isNameOfModuleDeclaration, - isNamedClassElement, isNamedDeclaration, isNamedEvaluation, isNamedEvaluationSource, @@ -194438,7 +195639,6 @@ if (typeof console !== "undefined") { isNewExpression, isNewExpressionTarget, isNoSubstitutionTemplateLiteral, - isNode, isNodeArray, isNodeArrayMultiLine, isNodeDescendantOf, @@ -194447,14 +195647,11 @@ if (typeof console !== "undefined") { isNodeModulesDirectory, isNodeWithPossibleHoistedDeclaration, isNonContextualKeyword, - isNonExportDefaultModifier, isNonGlobalAmbientModule, - isNonGlobalDeclaration, isNonNullAccess, isNonNullChain, isNonNullExpression, isNonStaticMethodOrAccessorWithPrivateName, - isNotEmittedOrPartiallyEmittedNode, isNotEmittedStatement, isNullishCoalesce, isNumber, @@ -194470,7 +195667,6 @@ if (typeof console !== "undefined") { isObjectLiteralMethod, isObjectLiteralOrClassExpressionMethodOrAccessor, isObjectTypeDeclaration, - isOctalDigit, isOmittedExpression, isOptionalChain, isOptionalChainRoot, @@ -194504,7 +195700,6 @@ if (typeof console !== "undefined") { isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression, isPrivateIdentifierSymbol, - isProgramBundleEmitBuildInfo, isProgramUptoDate, isPrologueDirective, isPropertyAccessChain, @@ -194517,7 +195712,6 @@ if (typeof console !== "undefined") { isPropertyName, isPropertyNameLiteral, isPropertySignature, - isProtoSetter, isPrototypeAccess, isPrototypePropertyAssignment, isPunctuation, @@ -194527,7 +195721,6 @@ if (typeof console !== "undefined") { isQuestionOrExclamationToken, isQuestionOrPlusOrMinusToken, isQuestionToken, - isRawSourceMap, isReadonlyKeyword, isReadonlyKeywordOrPlusOrMinusToken, isRecognizedTripleSlashComment, @@ -194549,24 +195742,22 @@ if (typeof console !== "undefined") { isRootedDiskPath, isSameEntityName, isSatisfiesExpression, - isScopeMarker, isSemicolonClassElement, isSetAccessor, isSetAccessorDeclaration, - isShebangTrivia, isShiftOperatorOrHigher, isShorthandAmbientModuleSymbol, isShorthandPropertyAssignment, + isSideEffectImport, isSignedNumericLiteral, isSimpleCopiableExpression, isSimpleInlineableExpression, - isSimpleParameter, isSimpleParameterList, isSingleOrDoubleQuote, + isSourceElement, isSourceFile, isSourceFileFromLibrary, isSourceFileJS, - isSourceFileNotJS, isSourceFileNotJson, isSourceMapping, isSpecialPropertyDeclaration, @@ -194579,7 +195770,6 @@ if (typeof console !== "undefined") { isStatic, isStaticModifier, isString, - isStringAKeyword, isStringANonContextualKeyword, isStringAndEmptyAnonymousObjectIntersection, isStringDoubleQuoted, @@ -194592,7 +195782,6 @@ if (typeof console !== "undefined") { isStringTextContainingNode, isSuperCall, isSuperKeyword, - isSuperOrSuperProperty, isSuperProperty, isSupportedSourceFileName, isSwitchStatement, @@ -194638,7 +195827,6 @@ if (typeof console !== "undefined") { isTypeDeclaration, isTypeElement, isTypeKeyword, - isTypeKeywordToken, isTypeKeywordTokenOrIdentifier, isTypeLiteralNode, isTypeNode, @@ -194693,10 +195881,6 @@ if (typeof console !== "undefined") { libMap, libs, lineBreakPart, - linkNamePart, - linkPart, - linkTextPart, - listFiles, loadModuleFromGlobalCache, loadWithModeAwareCache, makeIdentifierFromModuleName, @@ -194706,7 +195890,6 @@ if (typeof console !== "undefined") { map, mapAllOrFail, mapDefined, - mapDefinedEntries, mapDefinedIterator, mapEntries, mapIterator, @@ -194716,18 +195899,19 @@ if (typeof console !== "undefined") { matchPatternOrExact, matchedText, matchesExclude, + maxBy, maybeBind, maybeSetLocalizedDiagnosticMessages, memoize, - memoizeCached, memoizeOne, - memoizeWeak, - metadataHelper, min, minAndMax, missingFileModifiedTime, modifierToFlag, modifiersToFlags, + moduleExportNameIsDefault, + moduleExportNameTextEscaped, + moduleExportNameTextUnescaped, moduleOptionDeclaration, moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter, @@ -194767,11 +195951,11 @@ if (typeof console !== "undefined") { nodePosToString, nodeSeenTracker, nodeStartsNewLexicalEnvironment, - nodeToDisplayParts, noop, noopFileWatcher, normalizePath, normalizeSlashes, + normalizeSpans, not, notImplemented, notImplementedResolver, @@ -194786,13 +195970,11 @@ if (typeof console !== "undefined") { optionsForBuild, optionsForWatch, optionsHaveChanges, - optionsHaveModuleResolutionChanges, or, orderedRemoveItem, orderedRemoveItemAt, packageIdToPackageName, packageIdToString, - paramHelper, parameterIsThisKeyword, parameterNamePart, parseBaseNodeFactory, @@ -194823,10 +196005,8 @@ if (typeof console !== "undefined") { pathIsBareSpecifier, pathIsRelative, patternText, - perfLogger, performIncrementalCompilation, performance, - plainJSErrors, positionBelongsToNode, positionIsASICandidate, positionIsSynthesized, @@ -194839,7 +196019,6 @@ if (typeof console !== "undefined") { programContainsEsModules, programContainsModules, projectReferenceIsEqualTo, - propKeyHelper, propertyNamePart, pseudoBigIntToString, punctuationPart, @@ -194862,7 +196041,6 @@ if (typeof console !== "undefined") { rangeStartPositionsAreOnSameLine, readBuilderProgram, readConfigFile, - readHelper, readJson, readJsonConfigFile, readJsonOrUndefined, @@ -194873,7 +196051,7 @@ if (typeof console !== "undefined") { reducePathComponents, refactor, regExpEscape, - regularExpressionFlagToCharacter, + regularExpressionFlagToCharacterCode, relativeComplement, removeAllComments, removeEmitHelper, @@ -194881,7 +196059,6 @@ if (typeof console !== "undefined") { removeFileExtension, removeIgnoredPath, removeMinAndVersionNumbers, - removeOptionality, removePrefix, removeSuffix, removeTrailingDirectorySeparator, @@ -194900,20 +196077,16 @@ if (typeof console !== "undefined") { resolveTripleslashReference, resolveTypeReferenceDirective, resolvingEmptyArray, - restHelper, returnFalse, returnNoopFileWatcher, returnTrue, returnUndefined, returnsPromise, - runInitializersHelper, sameFlatMap, sameMap, sameMapping, - scanShebangTrivia, scanTokenAtPosition, scanner, - screenStartingMessageCodes, semanticDiagnosticsOptionDeclarations, serializeCompilerOptions, server, @@ -194921,16 +196094,13 @@ if (typeof console !== "undefined") { setCommentRange, setConfigFileInOptions, setConstantValue, - setEachParent, setEmitFlags, - setFunctionNameHelper, setGetSourceFileAsHashVersioned, setIdentifierAutoGenerate, setIdentifierGeneratedImportReference, setIdentifierTypeArguments, setInternalEmitFlags, setLocalizedDiagnosticMessages, - setModuleDefaultHelper, setNodeChildren, setNodeFlags, setObjectAllocator, @@ -194959,7 +196129,6 @@ if (typeof console !== "undefined") { shouldPreserveConstEnums, shouldUseUriStyleNodeCoreModules, showModuleSpecifier, - signatureHasLiteralTypes, signatureHasRestParameter, signatureToDisplayParts, single, @@ -194968,18 +196137,17 @@ if (typeof console !== "undefined") { singleOrMany, singleOrUndefined, skipAlias, - skipAssertions, skipConstraint, skipOuterExpressions, skipParentheses, skipPartiallyEmittedExpressions, skipTrivia, skipTypeChecking, + skipTypeCheckingIgnoringNoCheck, skipTypeParentheses, skipWhile, sliceAfter, some, - sort, sortAndDeduplicate, sortAndDeduplicateDiagnostics, sourceFileAffectingCompilerOptions, @@ -194988,8 +196156,6 @@ if (typeof console !== "undefined") { sourceMapCommentRegExpDontCareLineStart, spacePart, spanMap, - spreadArrayHelper, - stableSort, startEndContainsRange, startEndOverlapsWithStartEnd, startOnNewLine, @@ -195002,10 +196168,8 @@ if (typeof console !== "undefined") { stringToToken, stripQuotes, supportedDeclarationExtensions, - supportedJSExtensions, supportedJSExtensionsFlat, supportedLocaleDirectories, - supportedTSExtensions, supportedTSExtensionsFlat, supportedTSImplementationExtensions, suppressLeadingAndTrailingTrivia, @@ -195014,16 +196178,12 @@ if (typeof console !== "undefined") { symbolEscapedNameNoDefault, symbolName, symbolNameNoDefault, - symbolPart, symbolToDisplayParts, - syntaxMayBeASICandidate, - syntaxRequiresTrailingSemicolonOrASI, sys, sysLog, tagNamesAreEquivalent, takeWhile, targetOptionDeclaration, - templateObjectHelper, testFormatSettings, textChangeRangeIsUnchanged, textChangeRangeNewSpan, @@ -195031,7 +196191,10 @@ if (typeof console !== "undefined") { textOrKeywordPart, textPart, textRangeContainsPositionInclusive, + textRangeContainsTextSpan, + textRangeIntersectsWithTextSpan, textSpanContainsPosition, + textSpanContainsTextRange, textSpanContainsTextSpan, textSpanEnd, textSpanIntersection, @@ -195049,15 +196212,16 @@ if (typeof console !== "undefined") { toBuilderStateFileInfoForMultiEmit, toEditorSettings, toFileNameLowerCase, - toLowerCase, toPath, toProgramEmitPending, + toSorted, tokenIsIdentifierOrKeyword, tokenIsIdentifierOrKeywordOrGreaterThan, tokenToString, trace, tracing, tracingEnabled, + transferSourceFileChildren, transform, transformClassFields, transformDeclarations, @@ -195072,11 +196236,11 @@ if (typeof console !== "undefined") { transformESDecorators, transformESNext, transformGenerators, + transformImpliedNodeFormatDependentModule, transformJsx, transformLegacyDecorators, transformModule, transformNamedEvaluation, - transformNodeModule, transformNodes, transformSystemModule, transformTypeScript, @@ -195103,7 +196267,6 @@ if (typeof console !== "undefined") { tryGetPropertyNameOfBindingOrAssignmentElement, tryGetSourceMappingURL, tryGetTextOfPropertyName, - tryIOAndConsumeErrors, tryParseJson, tryParsePattern, tryParsePatterns, @@ -195125,7 +196288,6 @@ if (typeof console !== "undefined") { unescapeLeadingUnderscores, unmangleScopedPackageName, unorderedRemoveItem, - unorderedRemoveItemAt, unreachableCodeIsError, unsetNodeChildren, unusedLabelIsError, @@ -195138,11 +196300,9 @@ if (typeof console !== "undefined") { updateSharedExtendedConfigFileWatcher, updateSourceFile, updateWatchingWildcardDirectories, - usesExtensionsOnImports, usingSingleLineStringWriter, utf16EncodeAsString, validateLocaleAndSetLanguage, - valuesHelper, version, versionMajorMinor, visitArray, @@ -195155,7 +196315,6 @@ if (typeof console !== "undefined") { visitNodes, visitParameterList, walkUpBindingElementsAndPatterns, - walkUpLexicalEnvironments, walkUpOuterExpressions, walkUpParenthesizedExpressions, walkUpParenthesizedTypes, diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index a0bce0133d..e3a0bee597 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -32,28 +32,15 @@ delete Object.prototype.__proto__; /** @type {ReadonlySet} */ const unstableDenoProps = new Set([ "AtomicOperation", - "CreateHttpClientOptions", "DatagramConn", - "HttpClient", "Kv", "KvListIterator", "KvU64", - "UnsafeCallback", - "UnsafePointer", - "UnsafePointerView", - "UnsafeFnPointer", "UnixConnectOptions", "UnixListenOptions", - "createHttpClient", - "dlopen", - "flock", - "flockSync", - "funlock", - "funlockSync", "listen", "listenDatagram", "openKv", - "umask", ]); const unstableMsgSuggestion = "If not, try changing the 'lib' compiler option to include 'deno.unstable' " + @@ -130,27 +117,6 @@ delete Object.prototype.__proto__; } } - class SpecifierIsCjsCache { - /** @type {Set} */ - #cache = new Set(); - - /** @param {[string, ts.Extension]} param */ - maybeAdd([specifier, ext]) { - if (ext === ".cjs" || ext === ".d.cts" || ext === ".cts") { - this.#cache.add(specifier); - } - } - - add(specifier) { - this.#cache.add(specifier); - } - - /** @param specifier {string} */ - has(specifier) { - return this.#cache.has(specifier); - } - } - // In the case of the LSP, this will only ever contain the assets. /** @type {Map} */ const sourceFileCache = new Map(); @@ -167,7 +133,8 @@ delete Object.prototype.__proto__; /** @type {Map} */ const isNodeSourceFileCache = new Map(); - const isCjsCache = new SpecifierIsCjsCache(); + /** @type {Map} */ + const isCjsCache = new Map(); // Maps asset specifiers to the first scope that the asset was loaded into. /** @type {Map} */ @@ -248,7 +215,7 @@ delete Object.prototype.__proto__; scriptSnapshot, { ...getCreateSourceFileOptions(sourceFileOptions), - impliedNodeFormat: isCjsCache.has(fileName) + impliedNodeFormat: (isCjsCache.get(fileName) ?? false) ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext, // in the lsp we want to be able to show documentation @@ -495,6 +462,8 @@ delete Object.prototype.__proto__; // TS2792: Cannot find module. Did you mean to set the 'moduleResolution' // option to 'node', or to add aliases to the 'paths' option? 2792, + // TS2307: Cannot find module '{0}' or its corresponding type declarations. + 2307, // TS5009: Cannot find the common subdirectory path for the input files. 5009, // TS5055: Cannot write file @@ -649,18 +618,13 @@ delete Object.prototype.__proto__; if (!fileInfo) { return undefined; } - let { data, scriptKind, version, isCjs } = fileInfo; + const { data, scriptKind, version, isCjs } = fileInfo; assert( data != null, `"data" is unexpectedly null for "${specifier}".`, ); - // use the cache for non-lsp - if (isCjs == null) { - isCjs = isCjsCache.has(specifier); - } else if (isCjs) { - isCjsCache.add(specifier); - } + isCjsCache.set(specifier, isCjs); sourceFile = ts.createSourceFile( specifier, @@ -735,11 +699,10 @@ delete Object.prototype.__proto__; /** @type {[string, ts.Extension] | undefined} */ const resolved = ops.op_resolve( containingFilePath, - isCjsCache.has(containingFilePath), + isCjsCache.get(containingFilePath) ?? false, [fileReference.fileName], )?.[0]; if (resolved) { - isCjsCache.maybeAdd(resolved); return { primary: true, resolvedFileName: resolved[0], @@ -769,13 +732,12 @@ delete Object.prototype.__proto__; /** @type {Array<[string, ts.Extension] | undefined>} */ const resolved = ops.op_resolve( base, - isCjsCache.has(base), + isCjsCache.get(base) ?? false, specifiers, ); if (resolved) { const result = resolved.map((item) => { if (item) { - isCjsCache.maybeAdd(item); const [resolvedFileName, extension] = item; return { resolvedFileName, @@ -854,9 +816,7 @@ delete Object.prototype.__proto__; if (!fileInfo) { return undefined; } - if (fileInfo.isCjs) { - isCjsCache.add(specifier); - } + isCjsCache.set(specifier, fileInfo.isCjs); sourceTextCache.set(specifier, fileInfo.data); scriptVersionCache.set(specifier, fileInfo.version); sourceText = fileInfo.data; @@ -984,6 +944,8 @@ delete Object.prototype.__proto__; Object.assign(options, { allowNonTsExtensions: true, allowImportingTsExtensions: true, + module: ts.ModuleKind.NodeNext, + moduleResolution: ts.ModuleResolutionKind.NodeNext, }); if (errors.length > 0 && logDebug) { debug(ts.formatDiagnostics(errors, host)); @@ -1063,7 +1025,7 @@ delete Object.prototype.__proto__; : ts.sortAndDeduplicateDiagnostics( checkFiles.map((s) => program.getSemanticDiagnostics(s)).flat(), )), - ].filter((diagnostic) => !IGNORED_DIAGNOSTICS.includes(diagnostic.code)); + ].filter(filterMapDiagnostic); // emit the tsbuildinfo file // @ts-ignore: emitBuildInfo is not exposed (https://github.com/microsoft/TypeScript/issues/49871) @@ -1078,6 +1040,27 @@ delete Object.prototype.__proto__; debug("<<< exec stop"); } + /** @param {ts.Diagnostic} diagnostic */ + function filterMapDiagnostic(diagnostic) { + if (IGNORED_DIAGNOSTICS.includes(diagnostic.code)) { + return false; + } + // make the diagnostic for using an `export =` in an es module a warning + if (diagnostic.code === 1203) { + diagnostic.category = ts.DiagnosticCategory.Warning; + if (typeof diagnostic.messageText === "string") { + const message = + " This will start erroring in a future version of Deno 2 " + + "in order to align with TypeScript."; + // seems typescript shares objects, so check if it's already been set + if (!diagnostic.messageText.endsWith(message)) { + diagnostic.messageText += message; + } + } + } + return true; + } + /** * @param {any} e * @returns {e is (OperationCanceledError | ts.OperationCanceledException)} @@ -1149,14 +1132,15 @@ delete Object.prototype.__proto__; "experimentalDecorators": false, "isolatedModules": true, "lib": ["deno.ns", "deno.window", "deno.unstable"], - "module": "esnext", + "module": "NodeNext", + "moduleResolution": "NodeNext", "moduleDetection": "force", "noEmit": true, + "noImplicitOverride": true, "resolveJsonModule": true, "strict": true, "target": "esnext", "useDefineForClassFields": true, - "useUnknownInCatchVariables": false, "jsx": "react", "jsxFactory": "React.createElement", "jsxFragmentFactory": "React.Fragment", @@ -1292,7 +1276,7 @@ delete Object.prototype.__proto__; ...ls.getSemanticDiagnostics(specifier), ...ls.getSuggestionDiagnostics(specifier), ...ls.getSyntacticDiagnostics(specifier), - ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code))); + ].filter(filterMapDiagnostic)); } return respond(id, diagnosticMap); } catch (e) { @@ -1338,48 +1322,38 @@ delete Object.prototype.__proto__; // A build time only op that provides some setup information that is used to // ensure the snapshot is setup properly. /** @type {{ buildSpecifier: string; libs: string[]; nodeBuiltInModuleNames: string[] }} */ - const { buildSpecifier, libs, nodeBuiltInModuleNames } = ops.op_build_info(); - - ts.deno.setNodeBuiltInModuleNames(nodeBuiltInModuleNames); + const { buildSpecifier, libs } = ops.op_build_info(); // list of globals that should be kept in Node's globalThis ts.deno.setNodeOnlyGlobalNames([ - // when bumping the @types/node version we should check if - // anything needs to be updated here - "NodeRequire", - "RequireResolve", - "RequireResolve", - "process", - "console", - "__filename", "__dirname", - "require", - "module", + "__filename", + "Buffer", + "BufferConstructor", + "BufferEncoding", + "clearImmediate", + "clearInterval", + "clearTimeout", + "console", + "Console", + "ErrorConstructor", "exports", "gc", - "BufferEncoding", - "BufferConstructor", - "WithImplicitCoercion", - "Buffer", - "Console", - "ImportMeta", - "setTimeout", - "setInterval", - "setImmediate", "Global", - "AbortController", - "AbortSignal", - "Blob", - "BroadcastChannel", - "MessageChannel", - "MessagePort", - "Event", - "EventTarget", - "performance", - "TextDecoder", - "TextEncoder", - "URL", - "URLSearchParams", + "ImportMeta", + "localStorage", + "module", + "NodeModule", + "NodeRequire", + "process", + "queueMicrotask", + "RequestInit", + "require", + "ResponseInit", + "sessionStorage", + "setImmediate", + "setInterval", + "setTimeout", ]); for (const lib of libs) { diff --git a/cli/tsc/_analyze_types_node.ts b/cli/tsc/_analyze_types_node.ts new file mode 100755 index 0000000000..10af00ee83 --- /dev/null +++ b/cli/tsc/_analyze_types_node.ts @@ -0,0 +1,64 @@ +#!/usr/bin/env -S deno run --allow-env --allow-read --allow-write=. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +import { + ModuleDeclarationKind, + Node, + Project, + ts, +} from "jsr:@ts-morph/ts-morph@23"; +import { Path } from "jsr:@david/path@0.2"; + +const dir = new Path(import.meta.dirname!); +const typesNodeDir = dir.join("../../../DefinitelyTyped/types/node"); + +const project = new Project({ + tsConfigFilePath: typesNodeDir.join("tsconfig.json").toString(), +}); +const names = new Set(); +const ignoredNames = new Set([ + "Array", + "BigInt64Array", + "BigUint64Array", + "Float32Array", + "Float64Array", + "Int16Array", + "Int32Array", + "Int8Array", + "NodeJS", + "ReadonlyArray", + "RelativeIndexable", + "RequireResolve", + "String", + "SymbolConstructor", + "Uint16Array", + "Uint32Array", + "Uint8Array", + "Uint8ClampedArray", + "WithImplicitCoercion", +]); + +for (const file of project.getSourceFiles()) { + for ( + const mod of file.getDescendantsOfKind(ts.SyntaxKind.ModuleDeclaration) + ) { + if (mod.getDeclarationKind() !== ModuleDeclarationKind.Global) continue; + + for (const statement of mod.getStatements()) { + if (Node.isVariableStatement(statement)) { + for (const decl of statement.getDeclarations()) { + if (ignoredNames.has(decl.getName())) continue; + names.add(decl.getName()); + } + } else if (Node.hasName(statement)) { + if (ignoredNames.has(statement.getName())) continue; + names.add(statement.getName()); + } + } + } +} + +// deno-lint-ignore no-console +console.log( + "Globals: ", + Array.from(names).sort(), +); diff --git a/cli/tsc/diagnostics.rs b/cli/tsc/diagnostics.rs index 9525d1855d..b0394ec177 100644 --- a/cli/tsc/diagnostics.rs +++ b/cli/tsc/diagnostics.rs @@ -140,7 +140,9 @@ impl Diagnostic { pub fn include_when_remote(&self) -> bool { /// TS6133: value is declared but its value is never read (noUnusedParameters and noUnusedLocals) const TS6133: u64 = 6133; - self.code != TS6133 + /// TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'X'. + const TS4114: u64 = 4114; + !matches!(self.code, TS6133 | TS4114) } fn fmt_category_and_code(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -280,6 +282,17 @@ impl Diagnostics { Diagnostics(diagnostics) } + pub fn emit_warnings(&mut self) { + self.0.retain(|d| { + if d.category == DiagnosticCategory::Warning { + log::warn!("{}\n", d); + false + } else { + true + } + }); + } + /// Return a set of diagnostics where only the values where the predicate /// returns `true` are included. pub fn filter

(self, predicate: P) -> Self diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index 0cc96d5429..36592e10dc 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -10,7 +10,7 @@ * * @category Platform */ -declare interface ImportMeta { +interface ImportMeta { /** A string representation of the fully qualified module URL. When the * module is loaded locally, the value will be a file URL (e.g. * `file:///path/module.ts`). @@ -89,7 +89,7 @@ declare interface ImportMeta { * * @category Performance */ -declare interface Performance { +interface Performance { /** Stores a timestamp with the associated name (a "mark"). */ mark(markName: string, options?: PerformanceMarkOptions): PerformanceMark; @@ -109,7 +109,7 @@ declare interface Performance { * * @category Performance */ -declare interface PerformanceMarkOptions { +interface PerformanceMarkOptions { /** Metadata to be included in the mark. */ // deno-lint-ignore no-explicit-any detail?: any; @@ -126,7 +126,7 @@ declare interface PerformanceMarkOptions { * * @category Performance */ -declare interface PerformanceMeasureOptions { +interface PerformanceMeasureOptions { /** Metadata to be included in the measure. */ // deno-lint-ignore no-explicit-any detail?: any; @@ -175,8 +175,11 @@ declare namespace Deno { /** * Raised when the underlying operating system indicates the current user * which the Deno process is running under does not have the appropriate - * permissions to a file or resource, or the user _did not_ provide required - * `--allow-*` flag. + * permissions to a file or resource. + * + * Before Deno 2.0, this error was raised when the user _did not_ provide + * required `--allow-*` flag. As of Deno 2.0, that case is now handled by + * the {@link NotCapable} error. * * @category Errors */ export class PermissionDenied extends Error {} @@ -314,6 +317,18 @@ declare namespace Deno { * * @category Errors */ export class NotADirectory extends Error {} + + /** + * Raised when trying to perform an operation while the relevant Deno + * permission (like `--allow-read`) has not been granted. + * + * Before Deno 2.0, this condition was covered by the {@link PermissionDenied} + * error. + * + * @category Errors */ + export class NotCapable extends Error {} + + export {}; // only export exports } /** The current process ID of this instance of the Deno CLI. @@ -524,10 +539,7 @@ declare namespace Deno { * set of permissions to the test context. * * @category Permissions */ - export type PermissionOptions = - | "inherit" - | "none" - | PermissionOptionsObject; + export type PermissionOptions = "inherit" | "none" | PermissionOptionsObject; /** * A set of options which can define the permissions within a test or worker @@ -553,15 +565,6 @@ declare namespace Deno { */ sys?: "inherit" | boolean | string[]; - /** Specifies if the `hrtime` permission should be requested or revoked. - * If set to `"inherit"`, the current `hrtime` permission will be inherited. - * If set to `true`, the global `hrtime` permission will be requested. - * If set to `false`, the global `hrtime` permission will be revoked. - * - * @default {false} - */ - hrtime?: "inherit" | boolean; - /** Specifies if the `net` permission should be requested or revoked. * if set to `"inherit"`, the current `net` permission will be inherited. * if set to `true`, the global `net` permission will be requested. @@ -941,10 +944,7 @@ declare namespace Deno { * * @category Testing */ - ( - name: string, - fn: (t: TestContext) => void | Promise, - ): void; + (name: string, fn: (t: TestContext) => void | Promise): void; /** Register a test which will be run when `deno test` is used on the command * line and the containing module looks like a test module. @@ -1076,10 +1076,7 @@ declare namespace Deno { * * @category Testing */ - ignore( - name: string, - fn: (t: TestContext) => void | Promise, - ): void; + ignore(name: string, fn: (t: TestContext) => void | Promise): void; /** Shorthand property for ignoring a particular test case. * @@ -1125,10 +1122,7 @@ declare namespace Deno { * * @category Testing */ - only( - name: string, - fn: (t: TestContext) => void | Promise, - ): void; + only(name: string, fn: (t: TestContext) => void | Promise): void; /** Shorthand property for focusing a particular test case. * @@ -1666,233 +1660,6 @@ declare namespace Deno { End = 2, } - /** - * An abstract interface which when implemented provides an interface to read - * bytes into an array buffer asynchronously. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O */ - export interface Reader { - /** Reads up to `p.byteLength` bytes into `p`. It resolves to the number of - * bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error - * encountered. Even if `read()` resolves to `n` < `p.byteLength`, it may - * use all of `p` as scratch space during the call. If some data is - * available but not `p.byteLength` bytes, `read()` conventionally resolves - * to what is available instead of waiting for more. - * - * When `read()` encounters end-of-file condition, it resolves to EOF - * (`null`). - * - * When `read()` encounters an error, it rejects with an error. - * - * Callers should always process the `n` > `0` bytes returned before - * considering the EOF (`null`). Doing so correctly handles I/O errors that - * happen after reading some bytes and also both of the allowed EOF - * behaviors. - * - * Implementations should not retain a reference to `p`. - * - * Use - * {@linkcode https://jsr.io/@std/io/doc/iterate-reader/~/iterateReader | iterateReader} - * to turn {@linkcode Reader} into an {@linkcode AsyncIterator}. - */ - read(p: Uint8Array): Promise; - } - - /** - * An abstract interface which when implemented provides an interface to read - * bytes into an array buffer synchronously. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O */ - export interface ReaderSync { - /** Reads up to `p.byteLength` bytes into `p`. It resolves to the number - * of bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error - * encountered. Even if `readSync()` returns `n` < `p.byteLength`, it may use - * all of `p` as scratch space during the call. If some data is available - * but not `p.byteLength` bytes, `readSync()` conventionally returns what is - * available instead of waiting for more. - * - * When `readSync()` encounters end-of-file condition, it returns EOF - * (`null`). - * - * When `readSync()` encounters an error, it throws with an error. - * - * Callers should always process the `n` > `0` bytes returned before - * considering the EOF (`null`). Doing so correctly handles I/O errors that - * happen after reading some bytes and also both of the allowed EOF - * behaviors. - * - * Implementations should not retain a reference to `p`. - * - * Use - * {@linkcode https://jsr.io/@std/io/doc/iterate-reader/~/iterateReaderSync | iterateReaderSync} - * to turn {@linkcode ReaderSync} into an {@linkcode Iterator}. - */ - readSync(p: Uint8Array): number | null; - } - - /** - * An abstract interface which when implemented provides an interface to write - * bytes from an array buffer to a file/resource asynchronously. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O */ - export interface Writer { - /** Writes `p.byteLength` bytes from `p` to the underlying data stream. It - * resolves to the number of bytes written from `p` (`0` <= `n` <= - * `p.byteLength`) or reject with the error encountered that caused the - * write to stop early. `write()` must reject with a non-null error if - * would resolve to `n` < `p.byteLength`. `write()` must not modify the - * slice data, even temporarily. - * - * This function is one of the lowest - * level APIs and most users should not work with this directly, but rather - * use {@linkcode https://jsr.io/@std/io/doc/write-all/~/writeAll | writeAll} - * instead. - * - * Implementations should not retain a reference to `p`. - */ - write(p: Uint8Array): Promise; - } - - /** - * An abstract interface which when implemented provides an interface to write - * bytes from an array buffer to a file/resource synchronously. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O */ - export interface WriterSync { - /** Writes `p.byteLength` bytes from `p` to the underlying data - * stream. It returns the number of bytes written from `p` (`0` <= `n` - * <= `p.byteLength`) and any error encountered that caused the write to - * stop early. `writeSync()` must throw a non-null error if it returns `n` < - * `p.byteLength`. `writeSync()` must not modify the slice data, even - * temporarily. - * - * Implementations should not retain a reference to `p`. - */ - writeSync(p: Uint8Array): number; - } - - /** - * An abstract interface which when implemented provides an interface to close - * files/resources that were previously opened. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O */ - export interface Closer { - /** Closes the resource, "freeing" the backing file/resource. */ - close(): void; - } - - /** - * An abstract interface which when implemented provides an interface to seek - * within an open file/resource asynchronously. - * - * @category I/O */ - export interface Seeker { - /** Seek sets the offset for the next `read()` or `write()` to offset, - * interpreted according to `whence`: `Start` means relative to the - * start of the file, `Current` means relative to the current offset, - * and `End` means relative to the end. Seek resolves to the new offset - * relative to the start of the file. - * - * Seeking to an offset before the start of the file is an error. Seeking to - * any positive offset is legal, but the behavior of subsequent I/O - * operations on the underlying object is implementation-dependent. - * - * It resolves with the updated offset. - */ - seek(offset: number | bigint, whence: SeekMode): Promise; - } - - /** - * An abstract interface which when implemented provides an interface to seek - * within an open file/resource synchronously. - * - * @category I/O */ - export interface SeekerSync { - /** Seek sets the offset for the next `readSync()` or `writeSync()` to - * offset, interpreted according to `whence`: `Start` means relative - * to the start of the file, `Current` means relative to the current - * offset, and `End` means relative to the end. - * - * Seeking to an offset before the start of the file is an error. Seeking to - * any positive offset is legal, but the behavior of subsequent I/O - * operations on the underlying object is implementation-dependent. - * - * It returns the updated offset. - */ - seekSync(offset: number | bigint, whence: SeekMode): number; - } - - /** - * Copies from `src` to `dst` until either EOF (`null`) is read from `src` or - * an error occurs. It resolves to the number of bytes copied or rejects with - * the first error encountered while copying. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - * - * @param src The source to copy from - * @param dst The destination to copy to - * @param options Can be used to tune size of the buffer. Default size is 32kB - */ - export function copy( - src: Reader, - dst: Writer, - options?: { bufSize?: number }, - ): Promise; - - /** - * Turns a Reader, `r`, into an async iterator. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function iter( - r: Reader, - options?: { bufSize?: number }, - ): AsyncIterableIterator; - - /** - * Turns a ReaderSync, `r`, into an iterator. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function iterSync( - r: ReaderSync, - options?: { - bufSize?: number; - }, - ): IterableIterator; - /** Open a file and resolve to an instance of {@linkcode Deno.FsFile}. The * file does not need to previously exist if using the `create` or `createNew` * open options. The caller may have the resulting file automatically closed @@ -1980,318 +1747,6 @@ declare namespace Deno { */ export function createSync(path: string | URL): FsFile; - /** Read from a resource ID (`rid`) into an array buffer (`buffer`). - * - * Resolves to either the number of bytes read during the operation or EOF - * (`null`) if there was nothing more to read. - * - * It is possible for a read to successfully return with `0` bytes. This does - * not indicate EOF. - * - * This function is one of the lowest level APIs and most users should not - * work with this directly, but rather use {@linkcode ReadableStream} and - * {@linkcode https://jsr.io/@std/streams/doc/to-array-buffer/~/toArrayBuffer | toArrayBuffer} - * instead. - * - * **It is not guaranteed that the full buffer will be read in a single call.** - * - * ```ts - * // if "/foo/bar.txt" contains the text "hello world": - * using file = await Deno.open("/foo/bar.txt"); - * const buf = new Uint8Array(100); - * const numberOfBytesRead = await Deno.read(file.rid, buf); // 11 bytes - * const text = new TextDecoder().decode(buf); // "hello world" - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function read(rid: number, buffer: Uint8Array): Promise; - - /** Synchronously read from a resource ID (`rid`) into an array buffer - * (`buffer`). - * - * Returns either the number of bytes read during the operation or EOF - * (`null`) if there was nothing more to read. - * - * It is possible for a read to successfully return with `0` bytes. This does - * not indicate EOF. - * - * This function is one of the lowest level APIs and most users should not - * work with this directly, but rather use {@linkcode ReadableStream} and - * {@linkcode https://jsr.io/@std/streams/doc/to-array-buffer/~/toArrayBuffer | toArrayBuffer} - * instead. - * - * **It is not guaranteed that the full buffer will be read in a single - * call.** - * - * ```ts - * // if "/foo/bar.txt" contains the text "hello world": - * using file = Deno.openSync("/foo/bar.txt"); - * const buf = new Uint8Array(100); - * const numberOfBytesRead = Deno.readSync(file.rid, buf); // 11 bytes - * const text = new TextDecoder().decode(buf); // "hello world" - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function readSync(rid: number, buffer: Uint8Array): number | null; - - /** Write to the resource ID (`rid`) the contents of the array buffer (`data`). - * - * Resolves to the number of bytes written. This function is one of the lowest - * level APIs and most users should not work with this directly, but rather - * use {@linkcode WritableStream}, {@linkcode ReadableStream.from} and - * {@linkcode ReadableStream.pipeTo}. - * - * **It is not guaranteed that the full buffer will be written in a single - * call.** - * - * ```ts - * const encoder = new TextEncoder(); - * const data = encoder.encode("Hello world"); - * using file = await Deno.open("/foo/bar.txt", { write: true }); - * const bytesWritten = await Deno.write(file.rid, data); // 11 - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function write(rid: number, data: Uint8Array): Promise; - - /** Synchronously write to the resource ID (`rid`) the contents of the array - * buffer (`data`). - * - * Returns the number of bytes written. This function is one of the lowest - * level APIs and most users should not work with this directly, but rather - * use {@linkcode WritableStream}, {@linkcode ReadableStream.from} and - * {@linkcode ReadableStream.pipeTo}. - * - * **It is not guaranteed that the full buffer will be written in a single - * call.** - * - * ```ts - * const encoder = new TextEncoder(); - * const data = encoder.encode("Hello world"); - * using file = Deno.openSync("/foo/bar.txt", { write: true }); - * const bytesWritten = Deno.writeSync(file.rid, data); // 11 - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function writeSync(rid: number, data: Uint8Array): number; - - /** Seek a resource ID (`rid`) to the given `offset` under mode given by `whence`. - * The call resolves to the new position within the resource (bytes from the start). - * - * ```ts - * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * using file = await Deno.open( - * "hello.txt", - * { read: true, write: true, truncate: true, create: true }, - * ); - * await file.write(new TextEncoder().encode("Hello world")); - * - * // advance cursor 6 bytes - * const cursorPosition = await Deno.seek(file.rid, 6, Deno.SeekMode.Start); - * console.log(cursorPosition); // 6 - * const buf = new Uint8Array(100); - * await file.read(buf); - * console.log(new TextDecoder().decode(buf)); // "world" - * ``` - * - * The seek modes work as follows: - * - * ```ts - * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * using file = await Deno.open( - * "hello.txt", - * { read: true, write: true, truncate: true, create: true }, - * ); - * await file.write(new TextEncoder().encode("Hello world")); - * - * // Seek 6 bytes from the start of the file - * console.log(await Deno.seek(file.rid, 6, Deno.SeekMode.Start)); // "6" - * // Seek 2 more bytes from the current position - * console.log(await Deno.seek(file.rid, 2, Deno.SeekMode.Current)); // "8" - * // Seek backwards 2 bytes from the end of the file - * console.log(await Deno.seek(file.rid, -2, Deno.SeekMode.End)); // "9" (i.e. 11-2) - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function seek( - rid: number, - offset: number | bigint, - whence: SeekMode, - ): Promise; - - /** Synchronously seek a resource ID (`rid`) to the given `offset` under mode - * given by `whence`. The new position within the resource (bytes from the - * start) is returned. - * - * ```ts - * using file = Deno.openSync( - * "hello.txt", - * { read: true, write: true, truncate: true, create: true }, - * ); - * file.writeSync(new TextEncoder().encode("Hello world")); - * - * // advance cursor 6 bytes - * const cursorPosition = Deno.seekSync(file.rid, 6, Deno.SeekMode.Start); - * console.log(cursorPosition); // 6 - * const buf = new Uint8Array(100); - * file.readSync(buf); - * console.log(new TextDecoder().decode(buf)); // "world" - * ``` - * - * The seek modes work as follows: - * - * ```ts - * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * using file = Deno.openSync( - * "hello.txt", - * { read: true, write: true, truncate: true, create: true }, - * ); - * file.writeSync(new TextEncoder().encode("Hello world")); - * - * // Seek 6 bytes from the start of the file - * console.log(Deno.seekSync(file.rid, 6, Deno.SeekMode.Start)); // "6" - * // Seek 2 more bytes from the current position - * console.log(Deno.seekSync(file.rid, 2, Deno.SeekMode.Current)); // "8" - * // Seek backwards 2 bytes from the end of the file - * console.log(Deno.seekSync(file.rid, -2, Deno.SeekMode.End)); // "9" (i.e. 11-2) - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function seekSync( - rid: number, - offset: number | bigint, - whence: SeekMode, - ): number; - - /** - * Flushes any pending data and metadata operations of the given file stream - * to disk. - * - * ```ts - * const file = await Deno.open( - * "my_file.txt", - * { read: true, write: true, create: true }, - * ); - * await file.write(new TextEncoder().encode("Hello World")); - * await file.truncate(1); - * await Deno.fsync(file.rid); - * console.log(await Deno.readTextFile("my_file.txt")); // H - * ``` - * - * @category File System - */ - export function fsync(rid: number): Promise; - - /** - * Synchronously flushes any pending data and metadata operations of the given - * file stream to disk. - * - * ```ts - * const file = Deno.openSync( - * "my_file.txt", - * { read: true, write: true, create: true }, - * ); - * file.writeSync(new TextEncoder().encode("Hello World")); - * file.truncateSync(1); - * Deno.fsyncSync(file.rid); - * console.log(Deno.readTextFileSync("my_file.txt")); // H - * ``` - * - * @category File System - */ - export function fsyncSync(rid: number): void; - - /** - * Flushes any pending data operations of the given file stream to disk. - * ```ts - * const file = await Deno.open( - * "my_file.txt", - * { read: true, write: true, create: true }, - * ); - * await file.write(new TextEncoder().encode("Hello World")); - * await Deno.fdatasync(file.rid); - * console.log(await Deno.readTextFile("my_file.txt")); // Hello World - * ``` - * - * @category File System - */ - export function fdatasync(rid: number): Promise; - - /** - * Synchronously flushes any pending data operations of the given file stream - * to disk. - * - * ```ts - * const file = Deno.openSync( - * "my_file.txt", - * { read: true, write: true, create: true }, - * ); - * file.writeSync(new TextEncoder().encode("Hello World")); - * Deno.fdatasyncSync(file.rid); - * console.log(Deno.readTextFileSync("my_file.txt")); // Hello World - * ``` - * - * @category File System - */ - export function fdatasyncSync(rid: number): void; - - /** Close the given resource ID (`rid`) which has been previously opened, such - * as via opening or creating a file. Closing a file when you are finished - * with it is important to avoid leaking resources. - * - * ```ts - * const file = await Deno.open("my_file.txt"); - * // do work with "file" object - * Deno.close(file.rid); - * ``` - * - * It is recommended to define the variable with the `using` keyword so the - * runtime will automatically close the resource when it goes out of scope. - * Doing so negates the need to manually close the resource. - * - * ```ts - * using file = await Deno.open("my_file.txt"); - * // do work with "file" object - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function close(rid: number): void; - /** The Deno abstraction for reading and writing files. * * This is the most straight forward way of handling files within Deno and is @@ -2309,25 +1764,7 @@ declare namespace Deno { * * @category File System */ - export class FsFile - implements - Reader, - ReaderSync, - Writer, - WriterSync, - Seeker, - SeekerSync, - Closer, - Disposable { - /** - * The resource ID associated with the file instance. The resource ID - * should be considered an opaque reference to resource. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; + export class FsFile implements Disposable { /** A {@linkcode ReadableStream} instance representing to the byte contents * of the file. This makes it easy to interoperate with other web streams * based APIs. @@ -2356,16 +1793,6 @@ declare namespace Deno { * ``` */ readonly writable: WritableStream; - /** - * The constructor which takes a resource ID. Generally `FsFile` should - * not be constructed directly. Instead use {@linkcode Deno.open} or - * {@linkcode Deno.openSync} to create a new instance of `FsFile`. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - constructor(rid: number); /** Write the contents of the array buffer (`p`) to the file. * * Resolves to the number of bytes written. @@ -2487,7 +1914,7 @@ declare namespace Deno { * resolves to the new position within the resource (bytes from the start). * * ```ts - * // Given file pointing to file with "Hello world", which is 11 bytes long: + * // Given the file contains "Hello world" text, which is 11 bytes long: * using file = await Deno.open( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, @@ -2505,7 +1932,7 @@ declare namespace Deno { * The seek modes work as follows: * * ```ts - * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: + * // Given the file contains "Hello world" text, which is 11 bytes long: * const file = await Deno.open( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, @@ -2542,7 +1969,7 @@ declare namespace Deno { * The seek modes work as follows: * * ```ts - * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: + * // Given the file contains "Hello world" text, which is 11 bytes long: * using file = Deno.openSync( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, @@ -2732,17 +2159,6 @@ declare namespace Deno { [Symbol.dispose](): void; } - /** - * The Deno abstraction for reading and writing files. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export const File: typeof FsFile; - /** Gets the size of the console as columns/rows. * * ```ts @@ -2772,9 +2188,12 @@ declare namespace Deno { } /** A reference to `stdin` which can be used to read directly from `stdin`. - * It implements the Deno specific {@linkcode Reader}, {@linkcode ReaderSync}, - * and {@linkcode Closer} interfaces as well as provides a - * {@linkcode ReadableStream} interface. + * + * It implements the Deno specific + * {@linkcode https://jsr.io/@std/io/doc/types/~/Reader | Reader}, + * {@linkcode https://jsr.io/@std/io/doc/types/~/ReaderSync | ReaderSync}, + * and {@linkcode https://jsr.io/@std/io/doc/types/~/Closer | Closer} + * interfaces as well as provides a {@linkcode ReadableStream} interface. * * ### Reading chunks from the readable stream * @@ -2788,16 +2207,57 @@ declare namespace Deno { * * @category I/O */ - export const stdin: Reader & ReaderSync & Closer & { - /** - * The resource ID assigned to `stdin`. This can be used with the discrete - * I/O functions in the `Deno` namespace. + export const stdin: { + /** Read the incoming data from `stdin` into an array buffer (`p`). * - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. + * Resolves to either the number of bytes read during the operation or EOF + * (`null`) if there was nothing more to read. + * + * It is possible for a read to successfully return with `0` bytes. This + * does not indicate EOF. + * + * **It is not guaranteed that the full buffer will be read in a single + * call.** + * + * ```ts + * // If the text "hello world" is piped into the script: + * const buf = new Uint8Array(100); + * const numberOfBytesRead = await Deno.stdin.read(buf); // 11 bytes + * const text = new TextDecoder().decode(buf); // "hello world" + * ``` + * + * @category I/O */ - readonly rid: number; + read(p: Uint8Array): Promise; + /** Synchronously read from the incoming data from `stdin` into an array + * buffer (`p`). + * + * Returns either the number of bytes read during the operation or EOF + * (`null`) if there was nothing more to read. + * + * It is possible for a read to successfully return with `0` bytes. This + * does not indicate EOF. + * + * **It is not guaranteed that the full buffer will be read in a single + * call.** + * + * ```ts + * // If the text "hello world" is piped into the script: + * const buf = new Uint8Array(100); + * const numberOfBytesRead = Deno.stdin.readSync(buf); // 11 bytes + * const text = new TextDecoder().decode(buf); // "hello world" + * ``` + * + * @category I/O + */ + readSync(p: Uint8Array): number | null; + /** Closes `stdin`, freeing the resource. + * + * ```ts + * Deno.stdin.close(); + * ``` + */ + close(): void; /** A readable stream interface to `stdin`. */ readonly readable: ReadableStream; /** @@ -2827,8 +2287,10 @@ declare namespace Deno { isTerminal(): boolean; }; /** A reference to `stdout` which can be used to write directly to `stdout`. - * It implements the Deno specific {@linkcode Writer}, {@linkcode WriterSync}, - * and {@linkcode Closer} interfaces as well as provides a + * It implements the Deno specific + * {@linkcode https://jsr.io/@std/io/doc/types/~/Writer | Writer}, + * {@linkcode https://jsr.io/@std/io/doc/types/~/WriterSync | WriterSync}, + * and {@linkcode https://jsr.io/@std/io/doc/types/~/Closer | Closer} interfaces as well as provides a * {@linkcode WritableStream} interface. * * These are low level constructs, and the {@linkcode console} interface is a @@ -2836,16 +2298,44 @@ declare namespace Deno { * * @category I/O */ - export const stdout: Writer & WriterSync & Closer & { - /** - * The resource ID assigned to `stdout`. This can be used with the discrete - * I/O functions in the `Deno` namespace. + export const stdout: { + /** Write the contents of the array buffer (`p`) to `stdout`. * - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. + * Resolves to the number of bytes written. + * + * **It is not guaranteed that the full buffer will be written in a single + * call.** + * + * ```ts + * const encoder = new TextEncoder(); + * const data = encoder.encode("Hello world"); + * const bytesWritten = await Deno.stdout.write(data); // 11 + * ``` + * + * @category I/O */ - readonly rid: number; + write(p: Uint8Array): Promise; + /** Synchronously write the contents of the array buffer (`p`) to `stdout`. + * + * Returns the number of bytes written. + * + * **It is not guaranteed that the full buffer will be written in a single + * call.** + * + * ```ts + * const encoder = new TextEncoder(); + * const data = encoder.encode("Hello world"); + * const bytesWritten = Deno.stdout.writeSync(data); // 11 + * ``` + */ + writeSync(p: Uint8Array): number; + /** Closes `stdout`, freeing the resource. + * + * ```ts + * Deno.stdout.close(); + * ``` + */ + close(): void; /** A writable stream interface to `stdout`. */ readonly writable: WritableStream; /** @@ -2861,8 +2351,10 @@ declare namespace Deno { isTerminal(): boolean; }; /** A reference to `stderr` which can be used to write directly to `stderr`. - * It implements the Deno specific {@linkcode Writer}, {@linkcode WriterSync}, - * and {@linkcode Closer} interfaces as well as provides a + * It implements the Deno specific + * {@linkcode https://jsr.io/@std/io/doc/types/~/Writer | Writer}, + * {@linkcode https://jsr.io/@std/io/doc/types/~/WriterSync | WriterSync}, + * and {@linkcode https://jsr.io/@std/io/doc/types/~/Closer | Closer} interfaces as well as provides a * {@linkcode WritableStream} interface. * * These are low level constructs, and the {@linkcode console} interface is a @@ -2870,16 +2362,44 @@ declare namespace Deno { * * @category I/O */ - export const stderr: Writer & WriterSync & Closer & { - /** - * The resource ID assigned to `stderr`. This can be used with the discrete - * I/O functions in the `Deno` namespace. + export const stderr: { + /** Write the contents of the array buffer (`p`) to `stderr`. * - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. + * Resolves to the number of bytes written. + * + * **It is not guaranteed that the full buffer will be written in a single + * call.** + * + * ```ts + * const encoder = new TextEncoder(); + * const data = encoder.encode("Hello world"); + * const bytesWritten = await Deno.stderr.write(data); // 11 + * ``` + * + * @category I/O */ - readonly rid: number; + write(p: Uint8Array): Promise; + /** Synchronously write the contents of the array buffer (`p`) to `stderr`. + * + * Returns the number of bytes written. + * + * **It is not guaranteed that the full buffer will be written in a single + * call.** + * + * ```ts + * const encoder = new TextEncoder(); + * const data = encoder.encode("Hello world"); + * const bytesWritten = Deno.stderr.writeSync(data); // 11 + * ``` + */ + writeSync(p: Uint8Array): number; + /** Closes `stderr`, freeing the resource. + * + * ```ts + * Deno.stderr.close(); + * ``` + */ + close(): void; /** A writable stream interface to `stderr`. */ readonly writable: WritableStream; /** @@ -2962,147 +2482,6 @@ declare namespace Deno { signal?: AbortSignal; } - /** - * Check if a given resource id (`rid`) is a TTY (a terminal). - * - * ```ts - * // This example is system and context specific - * const nonTTYRid = Deno.openSync("my_file.txt").rid; - * const ttyRid = Deno.openSync("/dev/tty6").rid; - * console.log(Deno.isatty(nonTTYRid)); // false - * console.log(Deno.isatty(ttyRid)); // true - * ``` - * - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function isatty(rid: number): boolean; - - /** - * A variable-sized buffer of bytes with `read()` and `write()` methods. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export class Buffer implements Reader, ReaderSync, Writer, WriterSync { - constructor(ab?: ArrayBuffer); - /** Returns a slice holding the unread portion of the buffer. - * - * The slice is valid for use only until the next buffer modification (that - * is, only until the next call to a method like `read()`, `write()`, - * `reset()`, or `truncate()`). If `options.copy` is false the slice aliases the buffer content at - * least until the next buffer modification, so immediate changes to the - * slice will affect the result of future reads. - * @param options Defaults to `{ copy: true }` - */ - bytes(options?: { copy?: boolean }): Uint8Array; - /** Returns whether the unread portion of the buffer is empty. */ - empty(): boolean; - /** A read only number of bytes of the unread portion of the buffer. */ - readonly length: number; - /** The read only capacity of the buffer's underlying byte slice, that is, - * the total space allocated for the buffer's data. */ - readonly capacity: number; - /** Discards all but the first `n` unread bytes from the buffer but - * continues to use the same allocated storage. It throws if `n` is - * negative or greater than the length of the buffer. */ - truncate(n: number): void; - /** Resets the buffer to be empty, but it retains the underlying storage for - * use by future writes. `.reset()` is the same as `.truncate(0)`. */ - reset(): void; - /** Reads the next `p.length` bytes from the buffer or until the buffer is - * drained. Returns the number of bytes read. If the buffer has no data to - * return, the return is EOF (`null`). */ - readSync(p: Uint8Array): number | null; - /** Reads the next `p.length` bytes from the buffer or until the buffer is - * drained. Resolves to the number of bytes read. If the buffer has no - * data to return, resolves to EOF (`null`). - * - * NOTE: This methods reads bytes synchronously; it's provided for - * compatibility with `Reader` interfaces. - */ - read(p: Uint8Array): Promise; - writeSync(p: Uint8Array): number; - /** NOTE: This methods writes bytes synchronously; it's provided for - * compatibility with `Writer` interface. */ - write(p: Uint8Array): Promise; - /** Grows the buffer's capacity, if necessary, to guarantee space for - * another `n` bytes. After `.grow(n)`, at least `n` bytes can be written to - * the buffer without another allocation. If `n` is negative, `.grow()` will - * throw. If the buffer can't grow it will throw an error. - * - * Based on Go Lang's - * [Buffer.Grow](https://golang.org/pkg/bytes/#Buffer.Grow). */ - grow(n: number): void; - /** Reads data from `r` until EOF (`null`) and appends it to the buffer, - * growing the buffer as needed. It resolves to the number of bytes read. - * If the buffer becomes too large, `.readFrom()` will reject with an error. - * - * Based on Go Lang's - * [Buffer.ReadFrom](https://golang.org/pkg/bytes/#Buffer.ReadFrom). */ - readFrom(r: Reader): Promise; - /** Reads data from `r` until EOF (`null`) and appends it to the buffer, - * growing the buffer as needed. It returns the number of bytes read. If the - * buffer becomes too large, `.readFromSync()` will throw an error. - * - * Based on Go Lang's - * [Buffer.ReadFrom](https://golang.org/pkg/bytes/#Buffer.ReadFrom). */ - readFromSync(r: ReaderSync): number; - } - - /** - * Read Reader `r` until EOF (`null`) and resolve to the content as - * Uint8Array`. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function readAll(r: Reader): Promise; - - /** - * Synchronously reads Reader `r` until EOF (`null`) and returns the content - * as `Uint8Array`. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function readAllSync(r: ReaderSync): Uint8Array; - - /** - * Write all the content of the array buffer (`arr`) to the writer (`w`). - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function writeAll(w: Writer, arr: Uint8Array): Promise; - - /** - * Synchronously write all the content of the array buffer (`arr`) to the - * writer (`w`). - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export function writeAllSync(w: WriterSync, arr: Uint8Array): void; - /** * Options which can be set when using {@linkcode Deno.mkdir} and * {@linkcode Deno.mkdirSync}. @@ -4060,73 +3439,6 @@ declare namespace Deno { bytesReceived: number; } - /** @category Runtime - * - * @deprecated This will be removed in Deno 2.0. - */ - export interface Metrics extends OpMetrics { - ops: Record; - } - - /** Receive metrics from the privileged side of Deno. This is primarily used - * in the development of Deno. _Ops_, also called _bindings_, are the - * go-between between Deno JavaScript sandbox and the rest of Deno. - * - * ```shell - * > console.table(Deno.metrics()) - * ┌─────────────────────────┬────────┐ - * │ (index) │ Values │ - * ├─────────────────────────┼────────┤ - * │ opsDispatched │ 3 │ - * │ opsDispatchedSync │ 2 │ - * │ opsDispatchedAsync │ 1 │ - * │ opsDispatchedAsyncUnref │ 0 │ - * │ opsCompleted │ 3 │ - * │ opsCompletedSync │ 2 │ - * │ opsCompletedAsync │ 1 │ - * │ opsCompletedAsyncUnref │ 0 │ - * │ bytesSentControl │ 73 │ - * │ bytesSentData │ 0 │ - * │ bytesReceived │ 375 │ - * └─────────────────────────┴────────┘ - * ``` - * - * @category Runtime - * - * @deprecated This will be removed in Deno 2.0. - */ - export function metrics(): Metrics; - - /** - * A map of open resources that Deno is tracking. The key is the resource ID - * (_rid_) and the value is its representation. - * - * @deprecated This will be removed in Deno 2.0. - * - * @category Runtime */ - export interface ResourceMap { - [rid: number]: unknown; - } - - /** Returns a map of open resource IDs (_rid_) along with their string - * representations. This is an internal API and as such resource - * representation has `unknown` type; that means it can change any time and - * should not be depended upon. - * - * ```ts - * console.log(Deno.resources()); - * // { 0: "stdin", 1: "stdout", 2: "stderr" } - * Deno.openSync('../test.file'); - * console.log(Deno.resources()); - * // { 0: "stdin", 1: "stdout", 2: "stderr", 3: "fsFile" } - * ``` - * - * @deprecated This will be removed in Deno 2.0. - * - * @category Runtime - */ - export function resources(): ResourceMap; - /** * Additional information for FsEvent objects with the "other" kind. * @@ -4171,22 +3483,10 @@ declare namespace Deno { * @category File System */ export interface FsWatcher extends AsyncIterable, Disposable { - /** - * The resource id. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; /** Stops watching the file system and closes the watcher resource. */ close(): void; /** * Stops watching the file system and closes the watcher resource. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. */ return?(value?: any): Promise>; [Symbol.asyncIterator](): AsyncIterableIterator; @@ -4236,175 +3536,6 @@ declare namespace Deno { options?: { recursive: boolean }, ): FsWatcher; - /** - * Options which can be used with {@linkcode Deno.run}. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Subprocess */ - export interface RunOptions { - /** Arguments to pass. - * - * _Note_: the first element needs to be a path to the executable that is - * being run. */ - cmd: readonly string[] | [string | URL, ...string[]]; - /** The current working directory that should be used when running the - * sub-process. */ - cwd?: string; - /** Any environment variables to be set when running the sub-process. */ - env?: Record; - /** By default subprocess inherits `stdout` of parent process. To change - * this this option can be set to a resource ID (_rid_) of an open file, - * `"inherit"`, `"piped"`, or `"null"`: - * - * - _number_: the resource ID of an open file/resource. This allows you to - * write to a file. - * - `"inherit"`: The default if unspecified. The subprocess inherits from the - * parent. - * - `"piped"`: A new pipe should be arranged to connect the parent and child - * sub-process. - * - `"null"`: This stream will be ignored. This is the equivalent of attaching - * the stream to `/dev/null`. - */ - stdout?: "inherit" | "piped" | "null" | number; - /** By default subprocess inherits `stderr` of parent process. To change - * this this option can be set to a resource ID (_rid_) of an open file, - * `"inherit"`, `"piped"`, or `"null"`: - * - * - _number_: the resource ID of an open file/resource. This allows you to - * write to a file. - * - `"inherit"`: The default if unspecified. The subprocess inherits from the - * parent. - * - `"piped"`: A new pipe should be arranged to connect the parent and child - * sub-process. - * - `"null"`: This stream will be ignored. This is the equivalent of attaching - * the stream to `/dev/null`. - */ - stderr?: "inherit" | "piped" | "null" | number; - /** By default subprocess inherits `stdin` of parent process. To change - * this this option can be set to a resource ID (_rid_) of an open file, - * `"inherit"`, `"piped"`, or `"null"`: - * - * - _number_: the resource ID of an open file/resource. This allows you to - * read from a file. - * - `"inherit"`: The default if unspecified. The subprocess inherits from the - * parent. - * - `"piped"`: A new pipe should be arranged to connect the parent and child - * sub-process. - * - `"null"`: This stream will be ignored. This is the equivalent of attaching - * the stream to `/dev/null`. - */ - stdin?: "inherit" | "piped" | "null" | number; - } - - /** - * The status resolved from the `.status()` method of a - * {@linkcode Deno.Process} instance. - * - * If `success` is `true`, then `code` will be `0`, but if `success` is - * `false`, the sub-process exit code will be set in `code`. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Subprocess */ - export type ProcessStatus = - | { - success: true; - code: 0; - signal?: undefined; - } - | { - success: false; - code: number; - signal?: number; - }; - - /** - * Represents an instance of a sub process that is returned from - * {@linkcode Deno.run} which can be used to manage the sub-process. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Subprocess */ - export class Process { - /** The resource ID of the sub-process. */ - readonly rid: number; - /** The operating system's process ID for the sub-process. */ - readonly pid: number; - /** A reference to the sub-processes `stdin`, which allows interacting with - * the sub-process at a low level. */ - readonly stdin: T["stdin"] extends "piped" ? Writer & Closer & { - writable: WritableStream; - } - : (Writer & Closer & { writable: WritableStream }) | null; - /** A reference to the sub-processes `stdout`, which allows interacting with - * the sub-process at a low level. */ - readonly stdout: T["stdout"] extends "piped" ? Reader & Closer & { - readable: ReadableStream; - } - : (Reader & Closer & { readable: ReadableStream }) | null; - /** A reference to the sub-processes `stderr`, which allows interacting with - * the sub-process at a low level. */ - readonly stderr: T["stderr"] extends "piped" ? Reader & Closer & { - readable: ReadableStream; - } - : (Reader & Closer & { readable: ReadableStream }) | null; - /** Wait for the process to exit and return its exit status. - * - * Calling this function multiple times will return the same status. - * - * The `stdin` reference to the process will be closed before waiting to - * avoid a deadlock. - * - * If `stdout` and/or `stderr` were set to `"piped"`, they must be closed - * manually before the process can exit. - * - * To run process to completion and collect output from both `stdout` and - * `stderr` use: - * - * ```ts - * const p = Deno.run({ cmd: [ "echo", "hello world" ], stderr: 'piped', stdout: 'piped' }); - * const [status, stdout, stderr] = await Promise.all([ - * p.status(), - * p.output(), - * p.stderrOutput() - * ]); - * p.close(); - * ``` - */ - status(): Promise; - /** Buffer the stdout until EOF and return it as `Uint8Array`. - * - * You must set `stdout` to `"piped"` when creating the process. - * - * This calls `close()` on stdout after its done. */ - output(): Promise; - /** Buffer the stderr until EOF and return it as `Uint8Array`. - * - * You must set `stderr` to `"piped"` when creating the process. - * - * This calls `close()` on stderr after its done. */ - stderrOutput(): Promise; - /** Clean up resources associated with the sub-process instance. */ - close(): void; - /** Send a signal to process. - * Default signal is `"SIGTERM"`. - * - * ```ts - * const p = Deno.run({ cmd: [ "sleep", "20" ]}); - * p.kill("SIGTERM"); - * p.close(); - * ``` - */ - kill(signo?: Signal): void; - } - /** Operating signals which can be listened for or sent to sub-processes. What * signals and what their standard behaviors are OS dependent. * @@ -4486,61 +3617,6 @@ declare namespace Deno { handler: () => void, ): void; - /** - * Spawns new subprocess. RunOptions must contain at a minimum the `opt.cmd`, - * an array of program arguments, the first of which is the binary. - * - * ```ts - * const p = Deno.run({ - * cmd: ["curl", "https://example.com"], - * }); - * const status = await p.status(); - * ``` - * - * Subprocess uses same working directory as parent process unless `opt.cwd` - * is specified. - * - * Environmental variables from parent process can be cleared using `opt.clearEnv`. - * Doesn't guarantee that only `opt.env` variables are present, - * as the OS may set environmental variables for processes. - * - * Environmental variables for subprocess can be specified using `opt.env` - * mapping. - * - * `opt.uid` sets the child process’s user ID. This translates to a setuid call - * in the child process. Failure in the setuid call will cause the spawn to fail. - * - * `opt.gid` is similar to `opt.uid`, but sets the group ID of the child process. - * This has the same semantics as the uid field. - * - * By default subprocess inherits stdio of parent process. To change - * this this, `opt.stdin`, `opt.stdout`, and `opt.stderr` can be set - * independently to a resource ID (_rid_) of an open file, `"inherit"`, - * `"piped"`, or `"null"`: - * - * - _number_: the resource ID of an open file/resource. This allows you to - * read or write to a file. - * - `"inherit"`: The default if unspecified. The subprocess inherits from the - * parent. - * - `"piped"`: A new pipe should be arranged to connect the parent and child - * sub-process. - * - `"null"`: This stream will be ignored. This is the equivalent of attaching - * the stream to `/dev/null`. - * - * Details of the spawned process are returned as an instance of - * {@linkcode Deno.Process}. - * - * Requires `allow-run` permission. - * - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @tags allow-run - * @category Subprocess - */ - export function run(opt: T): Process; - /** Create a child process. * * If any stdio options are not set to `"piped"`, accessing the corresponding @@ -4865,8 +3941,7 @@ declare namespace Deno { | "net" | "env" | "sys" - | "ffi" - | "hrtime"; + | "ffi"; /** The current status of the permission: * @@ -4876,10 +3951,7 @@ declare namespace Deno { * * @category Permissions */ - export type PermissionState = - | "granted" - | "denied" - | "prompt"; + export type PermissionState = "granted" | "denied" | "prompt"; /** The permission descriptor for the `allow-run` and `deny-run` permissions, which controls * access to what sub-processes can be executed by Deno. The option `command` @@ -4997,17 +4069,6 @@ declare namespace Deno { path?: string | URL; } - /** The permission descriptor for the `allow-hrtime` and `deny-hrtime` permissions, which - * controls if the runtime code has access to high resolution time. High - * resolution time is considered sensitive information, because it can be used - * by malicious code to gain information about the host that it might not - * otherwise have access to. - * - * @category Permissions */ - export interface HrtimePermissionDescriptor { - name: "hrtime"; - } - /** Permission descriptors which define a permission and can be queried, * requested, or revoked. * @@ -5023,15 +4084,14 @@ declare namespace Deno { | NetPermissionDescriptor | EnvPermissionDescriptor | SysPermissionDescriptor - | FfiPermissionDescriptor - | HrtimePermissionDescriptor; + | FfiPermissionDescriptor; /** The interface which defines what event types are supported by * {@linkcode PermissionStatus} instances. * * @category Permissions */ export interface PermissionStatusEventMap { - "change": Event; + change: Event; } /** An {@linkcode EventTarget} returned from the {@linkcode Deno.permissions} @@ -5340,19 +4400,6 @@ declare namespace Deno { */ export const args: string[]; - /** - * A symbol which can be used as a key for a custom method which will be - * called when `Deno.inspect()` is called, or when the object is logged to - * the console. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category I/O - */ - export const customInspect: unique symbol; - /** The URL of the entrypoint module entered from the command-line. It * requires read permission to the CWD. * @@ -5415,180 +4462,6 @@ declare namespace Deno { options?: SymlinkOptions, ): void; - /** - * Truncates or extends the specified file stream, to reach the specified - * `len`. - * - * If `len` is not specified then the entire file contents are truncated as if - * `len` was set to `0`. - * - * If the file previously was larger than this new length, the extra data is - * lost. - * - * If the file previously was shorter, it is extended, and the extended part - * reads as null bytes ('\0'). - * - * ### Truncate the entire file - * - * ```ts - * const file = await Deno.open( - * "my_file.txt", - * { read: true, write: true, create: true } - * ); - * await Deno.ftruncate(file.rid); - * ``` - * - * ### Truncate part of the file - * - * ```ts - * const file = await Deno.open( - * "my_file.txt", - * { read: true, write: true, create: true } - * ); - * await file.write(new TextEncoder().encode("Hello World")); - * await Deno.ftruncate(file.rid, 7); - * const data = new Uint8Array(32); - * await Deno.read(file.rid, data); - * console.log(new TextDecoder().decode(data)); // Hello W - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function ftruncate(rid: number, len?: number): Promise; - - /** - * Synchronously truncates or extends the specified file stream, to reach the - * specified `len`. - * - * If `len` is not specified then the entire file contents are truncated as if - * `len` was set to `0`. - * - * If the file previously was larger than this new length, the extra data is - * lost. - * - * If the file previously was shorter, it is extended, and the extended part - * reads as null bytes ('\0'). - * - * ### Truncate the entire file - * - * ```ts - * const file = Deno.openSync( - * "my_file.txt", - * { read: true, write: true, truncate: true, create: true } - * ); - * Deno.ftruncateSync(file.rid); - * ``` - * - * ### Truncate part of the file - * - * ```ts - * const file = Deno.openSync( - * "my_file.txt", - * { read: true, write: true, create: true } - * ); - * file.writeSync(new TextEncoder().encode("Hello World")); - * Deno.ftruncateSync(file.rid, 7); - * Deno.seekSync(file.rid, 0, Deno.SeekMode.Start); - * const data = new Uint8Array(32); - * Deno.readSync(file.rid, data); - * console.log(new TextDecoder().decode(data)); // Hello W - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function ftruncateSync(rid: number, len?: number): void; - - /** - * Synchronously changes the access (`atime`) and modification (`mtime`) times - * of a file stream resource referenced by `rid`. Given times are either in - * seconds (UNIX epoch time) or as `Date` objects. - * - * ```ts - * const file = Deno.openSync("file.txt", { create: true, write: true }); - * Deno.futimeSync(file.rid, 1556495550, new Date()); - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function futimeSync( - rid: number, - atime: number | Date, - mtime: number | Date, - ): void; - - /** - * Changes the access (`atime`) and modification (`mtime`) times of a file - * stream resource referenced by `rid`. Given times are either in seconds - * (UNIX epoch time) or as `Date` objects. - * - * ```ts - * const file = await Deno.open("file.txt", { create: true, write: true }); - * await Deno.futime(file.rid, 1556495550, new Date()); - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function futime( - rid: number, - atime: number | Date, - mtime: number | Date, - ): Promise; - - /** - * Returns a `Deno.FileInfo` for the given file stream. - * - * ```ts - * import { assert } from "jsr:@std/assert"; - * - * const file = await Deno.open("file.txt", { read: true }); - * const fileInfo = await Deno.fstat(file.rid); - * assert(fileInfo.isFile); - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function fstat(rid: number): Promise; - - /** - * Synchronously returns a {@linkcode Deno.FileInfo} for the given file - * stream. - * - * ```ts - * import { assert } from "jsr:@std/assert"; - * - * const file = Deno.openSync("file.txt", { read: true }); - * const fileInfo = Deno.fstatSync(file.rid); - * assert(fileInfo.isFile); - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category File System - */ - export function fstatSync(rid: number): FileInfo; - /** * Synchronously changes the access (`atime`) and modification (`mtime`) times * of a file system object referenced by `path`. Given times are either in @@ -5629,109 +4502,23 @@ declare namespace Deno { mtime: number | Date, ): Promise; - /** The event yielded from an {@linkcode HttpConn} which represents an HTTP - * request from a remote client. - * - * @category HTTP Server - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - export interface RequestEvent { - /** The request from the client in the form of the web platform - * {@linkcode Request}. */ - readonly request: Request; - /** The method to be used to respond to the event. The response needs to - * either be an instance of {@linkcode Response} or a promise that resolves - * with an instance of `Response`. - * - * When the response is successfully processed then the promise returned - * will be resolved. If there are any issues with sending the response, - * the promise will be rejected. */ - respondWith(r: Response | PromiseLike): Promise; - } - - /** - * The async iterable that is returned from {@linkcode serveHttp} which - * yields up {@linkcode RequestEvent} events, representing individual - * requests on the HTTP server connection. - * - * @category HTTP Server - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - export interface HttpConn extends AsyncIterable, Disposable { - /** The resource ID associated with this connection. Generally users do not - * need to be aware of this identifier. */ - readonly rid: number; - - /** An alternative to the async iterable interface which provides promises - * which resolve with either a {@linkcode RequestEvent} when there is - * another request or `null` when the client has closed the connection. */ - nextRequest(): Promise; - /** Initiate a server side closure of the connection, indicating to the - * client that you refuse to accept any more requests on this connection. - * - * Typically the client closes the connection, which will result in the - * async iterable terminating or the `nextRequest()` method returning - * `null`. */ - close(): void; - } - - /** - * Provides an interface to handle HTTP request and responses over TCP or TLS - * connections. The method returns an {@linkcode HttpConn} which yields up - * {@linkcode RequestEvent} events, which utilize the web platform standard - * {@linkcode Request} and {@linkcode Response} objects to handle the request. + /** Retrieve the process umask. If `mask` is provided, sets the process umask. + * This call always returns what the umask was before the call. * * ```ts - * const conn = Deno.listen({ port: 80 }); - * const httpConn = Deno.serveHttp(await conn.accept()); - * const e = await httpConn.nextRequest(); - * if (e) { - * e.respondWith(new Response("Hello World")); - * } + * console.log(Deno.umask()); // e.g. 18 (0o022) + * const prevUmaskValue = Deno.umask(0o077); // e.g. 18 (0o022) + * console.log(Deno.umask()); // e.g. 63 (0o077) * ``` * - * Alternatively, you can also use the async iterator approach: + * This API is under consideration to determine if permissions are required to + * call it. * - * ```ts - * async function handleHttp(conn: Deno.Conn) { - * for await (const e of Deno.serveHttp(conn)) { - * e.respondWith(new Response("Hello World")); - * } - * } + * *Note*: This API is not implemented on Windows * - * for await (const conn of Deno.listen({ port: 80 })) { - * handleHttp(conn); - * } - * ``` - * - * If `httpConn.nextRequest()` encounters an error or returns `null` then the - * underlying {@linkcode HttpConn} resource is closed automatically. - * - * Also see the experimental Flash HTTP server {@linkcode Deno.serve} which - * provides a ground up rewrite of handling of HTTP requests and responses - * within the Deno CLI. - * - * Note that this function *consumes* the given connection passed to it, thus - * the original connection will be unusable after calling this. Additionally, - * you need to ensure that the connection is not being used elsewhere when - * calling this function in order for the connection to be consumed properly. - * - * For instance, if there is a `Promise` that is waiting for read operation on - * the connection to complete, it is considered that the connection is being - * used elsewhere. In such a case, this function will fail. - * - * @category HTTP Server - * @deprecated This will be soft-removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. + * @category File System */ - export function serveHttp(conn: Conn): HttpConn; + export function umask(mask?: number): number; /** The object that is returned from a {@linkcode Deno.upgradeWebSocket} * request. @@ -5775,22 +4562,21 @@ declare namespace Deno { * with the returned response for the websocket upgrade to be successful. * * ```ts - * const conn = Deno.listen({ port: 80 }); - * const httpConn = Deno.serveHttp(await conn.accept()); - * const e = await httpConn.nextRequest(); - * if (e) { - * const { socket, response } = Deno.upgradeWebSocket(e.request); - * socket.onopen = () => { - * socket.send("Hello World!"); - * }; - * socket.onmessage = (e) => { - * console.log(e.data); - * socket.close(); - * }; - * socket.onclose = () => console.log("WebSocket has been closed."); - * socket.onerror = (e) => console.error("WebSocket error:", e); - * e.respondWith(response); - * } + * Deno.serve((req) => { + * if (req.headers.get("upgrade") !== "websocket") { + * return new Response(null, { status: 501 }); + * } + * const { socket, response } = Deno.upgradeWebSocket(req); + * socket.addEventListener("open", () => { + * console.log("a client connected!"); + * }); + * socket.addEventListener("message", (event) => { + * if (event.data === "ping") { + * socket.send("pong"); + * } + * }); + * return response; + * }); * ``` * * If the request body is disturbed (read from) before the upgrade is @@ -5819,11 +4605,10 @@ declare namespace Deno { * Windows. * * ```ts - * const p = Deno.run({ - * cmd: ["sleep", "10000"] - * }); + * const command = new Deno.Command("sleep", { args: ["10000"] }); + * const child = command.spawn(); * - * Deno.kill(p.pid, "SIGINT"); + * Deno.kill(child.pid, "SIGINT"); * ``` * * Requires `allow-run` permission. @@ -5884,7 +4669,7 @@ declare namespace Deno { * * @category Network */ - export interface CAARecord { + export interface CaaRecord { /** If `true`, indicates that the corresponding property tag **must** be * understood if the semantics of the CAA record are to be correctly * interpreted by an issuer. @@ -5904,7 +4689,7 @@ declare namespace Deno { * specified, it will return an array of objects with this interface. * * @category Network */ - export interface MXRecord { + export interface MxRecord { /** A priority value, which is a relative value compared to the other * preferences of MX records for the domain. */ preference: number; @@ -5916,7 +4701,7 @@ declare namespace Deno { * specified, it will return an array of objects with this interface. * * @category Network */ - export interface NAPTRRecord { + export interface NaptrRecord { order: number; preference: number; flags: string; @@ -5929,7 +4714,7 @@ declare namespace Deno { * specified, it will return an array of objects with this interface. * * @category Network */ - export interface SOARecord { + export interface SoaRecord { mname: string; rname: string; serial: number; @@ -5944,7 +4729,7 @@ declare namespace Deno { * * @category Network */ - export interface SRVRecord { + export interface SrvRecord { priority: number; weight: number; port: number; @@ -6009,7 +4794,7 @@ declare namespace Deno { query: string, recordType: "CAA", options?: ResolveDnsOptions, - ): Promise; + ): Promise; /** * Performs DNS resolution against the given query, returning resolved @@ -6039,7 +4824,7 @@ declare namespace Deno { query: string, recordType: "MX", options?: ResolveDnsOptions, - ): Promise; + ): Promise; /** * Performs DNS resolution against the given query, returning resolved @@ -6069,7 +4854,7 @@ declare namespace Deno { query: string, recordType: "NAPTR", options?: ResolveDnsOptions, - ): Promise; + ): Promise; /** * Performs DNS resolution against the given query, returning resolved @@ -6099,7 +4884,7 @@ declare namespace Deno { query: string, recordType: "SOA", options?: ResolveDnsOptions, - ): Promise; + ): Promise; /** * Performs DNS resolution against the given query, returning resolved @@ -6129,7 +4914,7 @@ declare namespace Deno { query: string, recordType: "SRV", options?: ResolveDnsOptions, - ): Promise; + ): Promise; /** * Performs DNS resolution against the given query, returning resolved @@ -6191,11 +4976,11 @@ declare namespace Deno { options?: ResolveDnsOptions, ): Promise< | string[] - | CAARecord[] - | MXRecord[] - | NAPTRRecord[] - | SOARecord[] - | SRVRecord[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord[] + | SrvRecord[] | string[][] >; @@ -6245,9 +5030,11 @@ declare namespace Deno { * * @category HTTP Server */ - export interface ServeHandlerInfo { + export interface ServeHandlerInfo { /** The remote address of the connection. */ - remoteAddr: Deno.NetAddr; + remoteAddr: Addr; + /** The completion promise */ + completed: Promise; } /** A handler for HTTP requests. Consumes a request and returns a response. @@ -6258,9 +5045,9 @@ declare namespace Deno { * * @category HTTP Server */ - export type ServeHandler = ( + export type ServeHandler = ( request: Request, - info: ServeHandlerInfo, + info: ServeHandlerInfo, ) => Response | Promise; /** Interface that module run with `deno serve` subcommand must conform to. @@ -6287,16 +5074,34 @@ declare namespace Deno { * * @category HTTP Server */ - fetch: ( - request: Request, - ) => Response | Promise; + fetch: ServeHandler; } /** Options which can be set when calling {@linkcode Deno.serve}. * * @category HTTP Server */ - export interface ServeOptions { + export interface ServeOptions { + /** An {@linkcode AbortSignal} to close the server and all connections. */ + signal?: AbortSignal; + + /** The handler to invoke when route handlers throw an error. */ + onError?: (error: unknown) => Response | Promise; + + /** The callback which is called when the server starts listening. */ + onListen?: (localAddr: Addr) => void; + } + + /** + * Options that can be passed to `Deno.serve` to create a server listening on + * a TCP port. + * + * @category HTTP Server + */ + export interface ServeTcpOptions extends ServeOptions { + /** The transport to use. */ + transport?: "tcp"; + /** The port to listen on. * * Set to `0` to listen on any available port. @@ -6314,109 +5119,37 @@ declare namespace Deno { * @default {"0.0.0.0"} */ hostname?: string; - /** An {@linkcode AbortSignal} to close the server and all connections. */ - signal?: AbortSignal; - /** Sets `SO_REUSEPORT` on POSIX systems. */ reusePort?: boolean; - - /** The handler to invoke when route handlers throw an error. */ - onError?: (error: unknown) => Response | Promise; - - /** The callback which is called when the server starts listening. */ - onListen?: (localAddr: Deno.NetAddr) => void; } - /** Additional options which are used when opening a TLS (HTTPS) server. + /** + * Options that can be passed to `Deno.serve` to create a server listening on + * a Unix domain socket. * * @category HTTP Server */ - export interface ServeTlsOptions extends ServeOptions { - /** - * Server private key in PEM format. Use {@linkcode TlsCertifiedKeyOptions} instead. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - cert?: string; + export interface ServeUnixOptions extends ServeOptions { + /** The transport to use. */ + transport?: "unix"; - /** - * Cert chain in PEM format. Use {@linkcode TlsCertifiedKeyOptions} instead. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - key?: string; - } - - /** - * @category HTTP Server - */ - export interface ServeInit { - /** The handler to invoke to process each incoming request. */ - handler: ServeHandler; - } - - /** - * @category HTTP Server - */ - export interface ServeTlsInit { - /** The handler to invoke to process each incoming request. */ - handler: ServeHandler; - } - - /** @category HTTP Server */ - export interface ServeUnixOptions { /** The unix domain socket path to listen on. */ path: string; - - /** An {@linkcode AbortSignal} to close the server and all connections. */ - signal?: AbortSignal; - - /** The handler to invoke when route handlers throw an error. */ - onError?: (error: unknown) => Response | Promise; - - /** The callback which is called when the server starts listening. */ - onListen?: (localAddr: Deno.UnixAddr) => void; } - /** Information for a unix domain socket HTTP request. - * - * @category HTTP Server - */ - export interface ServeUnixHandlerInfo { - /** The remote address of the connection. */ - remoteAddr: Deno.UnixAddr; - } - - /** A handler for unix domain socket HTTP requests. Consumes a request and returns a response. - * - * If a handler throws, the server calling the handler will assume the impact - * of the error is isolated to the individual request. It will catch the error - * and if necessary will close the underlying connection. - * - * @category HTTP Server - */ - export type ServeUnixHandler = ( - request: Request, - info: ServeUnixHandlerInfo, - ) => Response | Promise; - /** * @category HTTP Server */ - export interface ServeUnixInit { + export interface ServeInit { /** The handler to invoke to process each incoming request. */ - handler: ServeUnixHandler; + handler: ServeHandler; } /** An instance of the server created using `Deno.serve()` API. * * @category HTTP Server */ - export interface HttpServer + export interface HttpServer extends AsyncDisposable { /** A promise that resolves once server finishes - eg. when aborted using * the signal passed to {@linkcode ServeOptions.signal}. @@ -6424,7 +5157,7 @@ declare namespace Deno { finished: Promise; /** The local address this server is listening on. */ - addr: A; + addr: Addr; /** * Make the server block the event loop from finishing. @@ -6443,15 +5176,6 @@ declare namespace Deno { shutdown(): Promise; } - /** - * @category HTTP Server - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - export type Server = HttpServer; - /** Serves HTTP requests with the given handler. * * The below example serves with the port `8000` on hostname `"127.0.0.1"`. @@ -6462,7 +5186,9 @@ declare namespace Deno { * * @category HTTP Server */ - export function serve(handler: ServeHandler): HttpServer; + export function serve( + handler: ServeHandler, + ): HttpServer; /** Serves HTTP requests with the given option bag and handler. * * You can specify the socket path with `path` option. @@ -6510,19 +5236,19 @@ declare namespace Deno { */ export function serve( options: ServeUnixOptions, - handler: ServeUnixHandler, + handler: ServeHandler, ): HttpServer; /** Serves HTTP requests with the given option bag and handler. * * You can specify an object with a port and hostname option, which is the - * address to listen on. The default is port `8000` on hostname `"127.0.0.1"`. + * address to listen on. The default is port `8000` on hostname `"0.0.0.0"`. * * You can change the address to listen on using the `hostname` and `port` - * options. The below example serves on port `3000` and hostname `"0.0.0.0"`. + * options. The below example serves on port `3000` and hostname `"127.0.0.1"`. * * ```ts * Deno.serve( - * { port: 3000, hostname: "0.0.0.0" }, + * { port: 3000, hostname: "127.0.0.1" }, * (_req) => new Response("Hello, world") * ); * ``` @@ -6569,70 +5295,8 @@ declare namespace Deno { * @category HTTP Server */ export function serve( - options: ServeOptions, - handler: ServeHandler, - ): HttpServer; - /** Serves HTTP requests with the given option bag and handler. - * - * You can specify an object with a port and hostname option, which is the - * address to listen on. The default is port `8000` on hostname `"127.0.0.1"`. - * - * You can change the address to listen on using the `hostname` and `port` - * options. The below example serves on port `3000` and hostname `"0.0.0.0"`. - * - * ```ts - * Deno.serve( - * { port: 3000, hostname: "0.0.0.0" }, - * (_req) => new Response("Hello, world") - * ); - * ``` - * - * You can stop the server with an {@linkcode AbortSignal}. The abort signal - * needs to be passed as the `signal` option in the options bag. The server - * aborts when the abort signal is aborted. To wait for the server to close, - * await the promise returned from the `Deno.serve` API. - * - * ```ts - * const ac = new AbortController(); - * - * const server = Deno.serve( - * { signal: ac.signal }, - * (_req) => new Response("Hello, world") - * ); - * server.finished.then(() => console.log("Server closed")); - * - * console.log("Closing server..."); - * ac.abort(); - * ``` - * - * By default `Deno.serve` prints the message - * `Listening on http://:/` on listening. If you like to - * change this behavior, you can specify a custom `onListen` callback. - * - * ```ts - * Deno.serve({ - * onListen({ port, hostname }) { - * console.log(`Server started at http://${hostname}:${port}`); - * // ... more info specific to your server .. - * }, - * }, (_req) => new Response("Hello, world")); - * ``` - * - * To enable TLS you must specify the `key` and `cert` options. - * - * ```ts - * const cert = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"; - * const key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"; - * Deno.serve({ cert, key }, (_req) => new Response("Hello, world")); - * ``` - * - * @category HTTP Server - */ - export function serve( - options: - | ServeTlsOptions - | (ServeTlsOptions & TlsCertifiedKeyOptions), - handler: ServeHandler, + options: ServeTcpOptions | (ServeTcpOptions & TlsCertifiedKeyPem), + handler: ServeHandler, ): HttpServer; /** Serves HTTP requests with the given option bag. * @@ -6659,19 +5323,19 @@ declare namespace Deno { * @category HTTP Server */ export function serve( - options: ServeUnixInit & ServeUnixOptions, + options: ServeUnixOptions & ServeInit, ): HttpServer; /** Serves HTTP requests with the given option bag. * * You can specify an object with a port and hostname option, which is the - * address to listen on. The default is port `8000` on hostname `"127.0.0.1"`. + * address to listen on. The default is port `8000` on hostname `"0.0.0.0"`. * * ```ts * const ac = new AbortController(); * * const server = Deno.serve({ * port: 3000, - * hostname: "0.0.0.0", + * hostname: "127.0.0.1", * handler: (_req) => new Response("Hello, world"), * signal: ac.signal, * onListen({ port, hostname }) { @@ -6688,40 +5352,800 @@ declare namespace Deno { */ export function serve( options: - & ServeInit - & ServeOptions, + & (ServeTcpOptions | (ServeTcpOptions & TlsCertifiedKeyPem)) + & ServeInit, ): HttpServer; - /** Serves HTTP requests with the given option bag. + + /** All plain number types for interfacing with foreign functions. * - * You can specify an object with a port and hostname option, which is the - * address to listen on. The default is port `8000` on hostname `"127.0.0.1"`. + * @category FFI + */ + export type NativeNumberType = + | "u8" + | "i8" + | "u16" + | "i16" + | "u32" + | "i32" + | "f32" + | "f64"; + + /** All BigInt number types for interfacing with foreign functions. + * + * @category FFI + */ + export type NativeBigIntType = "u64" | "i64" | "usize" | "isize"; + + /** The native boolean type for interfacing to foreign functions. + * + * @category FFI + */ + export type NativeBooleanType = "bool"; + + /** The native pointer type for interfacing to foreign functions. + * + * @category FFI + */ + export type NativePointerType = "pointer"; + + /** The native buffer type for interfacing to foreign functions. + * + * @category FFI + */ + export type NativeBufferType = "buffer"; + + /** The native function type for interfacing with foreign functions. + * + * @category FFI + */ + export type NativeFunctionType = "function"; + + /** The native void type for interfacing with foreign functions. + * + * @category FFI + */ + export type NativeVoidType = "void"; + + /** The native struct type for interfacing with foreign functions. + * + * @category FFI + */ + export interface NativeStructType { + readonly struct: readonly NativeType[]; + } + + /** + * @category FFI + */ + export const brand: unique symbol; + + /** + * @category FFI + */ + export type NativeU8Enum = "u8" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeI8Enum = "i8" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeU16Enum = "u16" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeI16Enum = "i16" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeU32Enum = "u32" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeI32Enum = "i32" & { [brand]: T }; + /** + * @category FFI + */ + export type NativeTypedPointer = "pointer" & { + [brand]: T; + }; + /** + * @category FFI + */ + export type NativeTypedFunction = + & "function" + & { + [brand]: T; + }; + + /** All supported types for interfacing with foreign functions. + * + * @category FFI + */ + export type NativeType = + | NativeNumberType + | NativeBigIntType + | NativeBooleanType + | NativePointerType + | NativeBufferType + | NativeFunctionType + | NativeStructType; + + /** @category FFI + */ + export type NativeResultType = NativeType | NativeVoidType; + + /** Type conversion for foreign symbol parameters and unsafe callback return + * types. + * + * @category FFI + */ + export type ToNativeType = T extends + NativeStructType ? BufferSource + : T extends NativeNumberType ? T extends NativeU8Enum ? U + : T extends NativeI8Enum ? U + : T extends NativeU16Enum ? U + : T extends NativeI16Enum ? U + : T extends NativeU32Enum ? U + : T extends NativeI32Enum ? U + : number + : T extends NativeBigIntType ? bigint + : T extends NativeBooleanType ? boolean + : T extends NativePointerType + ? T extends NativeTypedPointer ? U | null + : PointerValue + : T extends NativeFunctionType + ? T extends NativeTypedFunction ? PointerValue | null + : PointerValue + : T extends NativeBufferType ? BufferSource | null + : never; + + /** Type conversion for unsafe callback return types. + * + * @category FFI + */ + export type ToNativeResultType< + T extends NativeResultType = NativeResultType, + > = T extends NativeStructType ? BufferSource + : T extends NativeNumberType ? T extends NativeU8Enum ? U + : T extends NativeI8Enum ? U + : T extends NativeU16Enum ? U + : T extends NativeI16Enum ? U + : T extends NativeU32Enum ? U + : T extends NativeI32Enum ? U + : number + : T extends NativeBigIntType ? bigint + : T extends NativeBooleanType ? boolean + : T extends NativePointerType + ? T extends NativeTypedPointer ? U | null + : PointerValue + : T extends NativeFunctionType + ? T extends NativeTypedFunction ? PointerObject | null + : PointerValue + : T extends NativeBufferType ? BufferSource | null + : T extends NativeVoidType ? void + : never; + + /** A utility type for conversion of parameter types of foreign functions. + * + * @category FFI + */ + export type ToNativeParameterTypes = + // + [T[number][]] extends [T] ? ToNativeType[] + : [readonly T[number][]] extends [T] ? readonly ToNativeType[] + : T extends readonly [...NativeType[]] ? { + [K in keyof T]: ToNativeType; + } + : never; + + /** Type conversion for foreign symbol return types and unsafe callback + * parameters. + * + * @category FFI + */ + export type FromNativeType = T extends + NativeStructType ? Uint8Array + : T extends NativeNumberType ? T extends NativeU8Enum ? U + : T extends NativeI8Enum ? U + : T extends NativeU16Enum ? U + : T extends NativeI16Enum ? U + : T extends NativeU32Enum ? U + : T extends NativeI32Enum ? U + : number + : T extends NativeBigIntType ? bigint + : T extends NativeBooleanType ? boolean + : T extends NativePointerType + ? T extends NativeTypedPointer ? U | null + : PointerValue + : T extends NativeBufferType ? PointerValue + : T extends NativeFunctionType + ? T extends NativeTypedFunction ? PointerObject | null + : PointerValue + : never; + + /** Type conversion for foreign symbol return types. + * + * @category FFI + */ + export type FromNativeResultType< + T extends NativeResultType = NativeResultType, + > = T extends NativeStructType ? Uint8Array + : T extends NativeNumberType ? T extends NativeU8Enum ? U + : T extends NativeI8Enum ? U + : T extends NativeU16Enum ? U + : T extends NativeI16Enum ? U + : T extends NativeU32Enum ? U + : T extends NativeI32Enum ? U + : number + : T extends NativeBigIntType ? bigint + : T extends NativeBooleanType ? boolean + : T extends NativePointerType + ? T extends NativeTypedPointer ? U | null + : PointerValue + : T extends NativeBufferType ? PointerValue + : T extends NativeFunctionType + ? T extends NativeTypedFunction ? PointerObject | null + : PointerValue + : T extends NativeVoidType ? void + : never; + + /** @category FFI + */ + export type FromNativeParameterTypes = + // + [T[number][]] extends [T] ? FromNativeType[] + : [readonly T[number][]] extends [T] + ? readonly FromNativeType[] + : T extends readonly [...NativeType[]] ? { + [K in keyof T]: FromNativeType; + } + : never; + + /** The interface for a foreign function as defined by its parameter and result + * types. + * + * @category FFI + */ + export interface ForeignFunction< + Parameters extends readonly NativeType[] = readonly NativeType[], + Result extends NativeResultType = NativeResultType, + NonBlocking extends boolean = boolean, + > { + /** Name of the symbol. + * + * Defaults to the key name in symbols object. */ + name?: string; + /** The parameters of the foreign function. */ + parameters: Parameters; + /** The result (return value) of the foreign function. */ + result: Result; + /** When `true`, function calls will run on a dedicated blocking thread and + * will return a `Promise` resolving to the `result`. */ + nonblocking?: NonBlocking; + /** When `true`, dlopen will not fail if the symbol is not found. + * Instead, the symbol will be set to `null`. + * + * @default {false} */ + optional?: boolean; + } + + /** @category FFI + */ + export interface ForeignStatic { + /** Name of the symbol, defaults to the key name in symbols object. */ + name?: string; + /** The type of the foreign static value. */ + type: Type; + /** When `true`, dlopen will not fail if the symbol is not found. + * Instead, the symbol will be set to `null`. + * + * @default {false} */ + optional?: boolean; + } + + /** A foreign library interface descriptor. + * + * @category FFI + */ + export interface ForeignLibraryInterface { + [name: string]: ForeignFunction | ForeignStatic; + } + + /** A utility type that infers a foreign symbol. + * + * @category FFI + */ + export type StaticForeignSymbol = + T extends ForeignFunction ? FromForeignFunction + : T extends ForeignStatic ? FromNativeType + : never; + + /** @category FFI + */ + export type FromForeignFunction = + T["parameters"] extends readonly [] ? () => StaticForeignSymbolReturnType + : ( + ...args: ToNativeParameterTypes + ) => StaticForeignSymbolReturnType; + + /** @category FFI + */ + export type StaticForeignSymbolReturnType = + ConditionalAsync>; + + /** @category FFI + */ + export type ConditionalAsync< + IsAsync extends boolean | undefined, + T, + > = IsAsync extends true ? Promise : T; + + /** A utility type that infers a foreign library interface. + * + * @category FFI + */ + export type StaticForeignLibraryInterface = + { + [K in keyof T]: T[K]["optional"] extends true + ? StaticForeignSymbol | null + : StaticForeignSymbol; + }; + + /** A non-null pointer, represented as an object + * at runtime. The object's prototype is `null` + * and cannot be changed. The object cannot be + * assigned to either and is thus entirely read-only. + * + * To interact with memory through a pointer use the + * {@linkcode UnsafePointerView} class. To create a + * pointer from an address or the get the address of + * a pointer use the static methods of the + * {@linkcode UnsafePointer} class. + * + * @category FFI + */ + export interface PointerObject { + [brand]: T; + } + + /** Pointers are represented either with a {@linkcode PointerObject} + * object or a `null` if the pointer is null. + * + * @category FFI + */ + export type PointerValue = null | PointerObject; + + /** A collection of static functions for interacting with pointer objects. + * + * @category FFI + */ + export class UnsafePointer { + /** Create a pointer from a numeric value. This one is really dangerous! */ + static create(value: bigint): PointerValue; + /** Returns `true` if the two pointers point to the same address. */ + static equals(a: PointerValue, b: PointerValue): boolean; + /** Return the direct memory pointer to the typed array in memory. */ + static of( + value: Deno.UnsafeCallback | BufferSource, + ): PointerValue; + /** Return a new pointer offset from the original by `offset` bytes. */ + static offset( + value: PointerObject, + offset: number, + ): PointerValue; + /** Get the numeric value of a pointer */ + static value(value: PointerValue): bigint; + } + + /** An unsafe pointer view to a memory location as specified by the `pointer` + * value. The `UnsafePointerView` API follows the standard built in interface + * {@linkcode DataView} for accessing the underlying types at an memory + * location (numbers, strings and raw bytes). + * + * @category FFI + */ + export class UnsafePointerView { + constructor(pointer: PointerObject); + + pointer: PointerObject; + + /** Gets a boolean at the specified byte offset from the pointer. */ + getBool(offset?: number): boolean; + /** Gets an unsigned 8-bit integer at the specified byte offset from the + * pointer. */ + getUint8(offset?: number): number; + /** Gets a signed 8-bit integer at the specified byte offset from the + * pointer. */ + getInt8(offset?: number): number; + /** Gets an unsigned 16-bit integer at the specified byte offset from the + * pointer. */ + getUint16(offset?: number): number; + /** Gets a signed 16-bit integer at the specified byte offset from the + * pointer. */ + getInt16(offset?: number): number; + /** Gets an unsigned 32-bit integer at the specified byte offset from the + * pointer. */ + getUint32(offset?: number): number; + /** Gets a signed 32-bit integer at the specified byte offset from the + * pointer. */ + getInt32(offset?: number): number; + /** Gets an unsigned 64-bit integer at the specified byte offset from the + * pointer. */ + getBigUint64(offset?: number): bigint; + /** Gets a signed 64-bit integer at the specified byte offset from the + * pointer. */ + getBigInt64(offset?: number): bigint; + /** Gets a signed 32-bit float at the specified byte offset from the + * pointer. */ + getFloat32(offset?: number): number; + /** Gets a signed 64-bit float at the specified byte offset from the + * pointer. */ + getFloat64(offset?: number): number; + /** Gets a pointer at the specified byte offset from the pointer */ + getPointer(offset?: number): PointerValue; + /** Gets a C string (`null` terminated string) at the specified byte offset + * from the pointer. */ + getCString(offset?: number): string; + /** Gets a C string (`null` terminated string) at the specified byte offset + * from the specified pointer. */ + static getCString(pointer: PointerObject, offset?: number): string; + /** Gets an `ArrayBuffer` of length `byteLength` at the specified byte + * offset from the pointer. */ + getArrayBuffer(byteLength: number, offset?: number): ArrayBuffer; + /** Gets an `ArrayBuffer` of length `byteLength` at the specified byte + * offset from the specified pointer. */ + static getArrayBuffer( + pointer: PointerObject, + byteLength: number, + offset?: number, + ): ArrayBuffer; + /** Copies the memory of the pointer into a typed array. + * + * Length is determined from the typed array's `byteLength`. + * + * Also takes optional byte offset from the pointer. */ + copyInto(destination: BufferSource, offset?: number): void; + /** Copies the memory of the specified pointer into a typed array. + * + * Length is determined from the typed array's `byteLength`. + * + * Also takes optional byte offset from the pointer. */ + static copyInto( + pointer: PointerObject, + destination: BufferSource, + offset?: number, + ): void; + } + + /** An unsafe pointer to a function, for calling functions that are not present + * as symbols. + * + * @category FFI + */ + export class UnsafeFnPointer { + /** The pointer to the function. */ + pointer: PointerObject; + /** The definition of the function. */ + definition: Fn; + + constructor( + pointer: PointerObject>>, + definition: Fn, + ); + + /** Call the foreign function. */ + call: FromForeignFunction; + } + + /** Definition of a unsafe callback function. + * + * @category FFI + */ + export interface UnsafeCallbackDefinition< + Parameters extends readonly NativeType[] = readonly NativeType[], + Result extends NativeResultType = NativeResultType, + > { + /** The parameters of the callbacks. */ + parameters: Parameters; + /** The current result of the callback. */ + result: Result; + } + + /** An unsafe callback function. + * + * @category FFI + */ + export type UnsafeCallbackFunction< + Parameters extends readonly NativeType[] = readonly NativeType[], + Result extends NativeResultType = NativeResultType, + > = Parameters extends readonly [] ? () => ToNativeResultType + : ( + ...args: FromNativeParameterTypes + ) => ToNativeResultType; + + /** An unsafe function pointer for passing JavaScript functions as C function + * pointers to foreign function calls. + * + * The function pointer remains valid until the `close()` method is called. + * + * All `UnsafeCallback` are always thread safe in that they can be called from + * foreign threads without crashing. However, they do not wake up the Deno event + * loop by default. + * + * If a callback is to be called from foreign threads, use the `threadSafe()` + * static constructor or explicitly call `ref()` to have the callback wake up + * the Deno event loop when called from foreign threads. This also stops + * Deno's process from exiting while the callback still exists and is not + * unref'ed. + * + * Use `deref()` to then allow Deno's process to exit. Calling `deref()` on + * a ref'ed callback does not stop it from waking up the Deno event loop when + * called from foreign threads. + * + * @category FFI + */ + export class UnsafeCallback< + const Definition extends UnsafeCallbackDefinition = + UnsafeCallbackDefinition, + > { + constructor( + definition: Definition, + callback: UnsafeCallbackFunction< + Definition["parameters"], + Definition["result"] + >, + ); + + /** The pointer to the unsafe callback. */ + readonly pointer: PointerObject; + /** The definition of the unsafe callback. */ + readonly definition: Definition; + /** The callback function. */ + readonly callback: UnsafeCallbackFunction< + Definition["parameters"], + Definition["result"] + >; + + /** + * Creates an {@linkcode UnsafeCallback} and calls `ref()` once to allow it to + * wake up the Deno event loop when called from foreign threads. + * + * This also stops Deno's process from exiting while the callback still + * exists and is not unref'ed. + */ + static threadSafe< + Definition extends UnsafeCallbackDefinition = UnsafeCallbackDefinition, + >( + definition: Definition, + callback: UnsafeCallbackFunction< + Definition["parameters"], + Definition["result"] + >, + ): UnsafeCallback; + + /** + * Increments the callback's reference counting and returns the new + * reference count. + * + * After `ref()` has been called, the callback always wakes up the + * Deno event loop when called from foreign threads. + * + * If the callback's reference count is non-zero, it keeps Deno's + * process from exiting. + */ + ref(): number; + + /** + * Decrements the callback's reference counting and returns the new + * reference count. + * + * Calling `unref()` does not stop a callback from waking up the Deno + * event loop when called from foreign threads. + * + * If the callback's reference counter is zero, it no longer keeps + * Deno's process from exiting. + */ + unref(): number; + + /** + * Removes the C function pointer associated with this instance. + * + * Continuing to use the instance or the C function pointer after closing + * the `UnsafeCallback` will lead to errors and crashes. + * + * Calling this method sets the callback's reference counting to zero, + * stops the callback from waking up the Deno event loop when called from + * foreign threads and no longer keeps Deno's process from exiting. + */ + close(): void; + } + + /** A dynamic library resource. Use {@linkcode Deno.dlopen} to load a dynamic + * library and return this interface. + * + * @category FFI + */ + export interface DynamicLibrary { + /** All of the registered library along with functions for calling them. */ + symbols: StaticForeignLibraryInterface; + /** Removes the pointers associated with the library symbols. + * + * Continuing to use symbols that are part of the library will lead to + * errors and crashes. + * + * Calling this method will also immediately set any references to zero and + * will no longer keep Deno's process from exiting. + */ + close(): void; + } + + /** Opens an external dynamic library and registers symbols, making foreign + * functions available to be called. + * + * Requires `allow-ffi` permission. Loading foreign dynamic libraries can in + * theory bypass all of the sandbox permissions. While it is a separate + * permission users should acknowledge in practice that is effectively the + * same as running with the `allow-all` permission. + * + * @example Given a C library which exports a foreign function named `add()` * * ```ts - * const ac = new AbortController(); + * // Determine library extension based on + * // your OS. + * let libSuffix = ""; + * switch (Deno.build.os) { + * case "windows": + * libSuffix = "dll"; + * break; + * case "darwin": + * libSuffix = "dylib"; + * break; + * default: + * libSuffix = "so"; + * break; + * } * - * const server = Deno.serve({ - * port: 3000, - * hostname: "0.0.0.0", - * handler: (_req) => new Response("Hello, world"), - * signal: ac.signal, - * onListen({ port, hostname }) { - * console.log(`Server started at http://${hostname}:${port}`); - * }, - * }); - * server.finished.then(() => console.log("Server closed")); + * const libName = `./libadd.${libSuffix}`; + * // Open library and define exported symbols + * const dylib = Deno.dlopen( + * libName, + * { + * "add": { parameters: ["isize", "isize"], result: "isize" }, + * } as const, + * ); * - * console.log("Closing server..."); - * ac.abort(); + * // Call the symbol `add` + * const result = dylib.symbols.add(35n, 34n); // 69n + * + * console.log(`Result from external addition of 35 and 34: ${result}`); * ``` * - * @category HTTP Server + * @tags allow-ffi + * @category FFI */ - export function serve( + export function dlopen( + filename: string | URL, + symbols: S, + ): DynamicLibrary; + + /** + * A custom `HttpClient` for use with {@linkcode fetch} function. This is + * designed to allow custom certificates or proxies to be used with `fetch()`. + * + * @example ```ts + * const caCert = await Deno.readTextFile("./ca.pem"); + * const client = Deno.createHttpClient({ caCerts: [ caCert ] }); + * const req = await fetch("https://myserver.com", { client }); + * ``` + * + * @category Fetch + */ + export class HttpClient implements Disposable { + /** Close the HTTP client. */ + close(): void; + + [Symbol.dispose](): void; + } + + /** + * The options used when creating a {@linkcode Deno.HttpClient}. + * + * @category Fetch + */ + export interface CreateHttpClientOptions { + /** A list of root certificates that will be used in addition to the + * default root certificates to verify the peer's certificate. + * + * Must be in PEM format. */ + caCerts?: string[]; + /** A HTTP proxy to use for new connections. */ + proxy?: Proxy; + /** Sets the maximum number of idle connections per host allowed in the pool. */ + poolMaxIdlePerHost?: number; + /** Set an optional timeout for idle sockets being kept-alive. + * Set to false to disable the timeout. */ + poolIdleTimeout?: number | false; + /** + * Whether HTTP/1.1 is allowed or not. + * + * @default {true} + */ + http1?: boolean; + /** Whether HTTP/2 is allowed or not. + * + * @default {true} + */ + http2?: boolean; + /** Whether setting the host header is allowed or not. + * + * @default {false} + */ + allowHost?: boolean; + } + + /** + * The definition of a proxy when specifying + * {@linkcode Deno.CreateHttpClientOptions}. + * + * @category Fetch + */ + export interface Proxy { + /** The string URL of the proxy server to use. */ + url: string; + /** The basic auth credentials to be used against the proxy server. */ + basicAuth?: BasicAuth; + } + + /** + * Basic authentication credentials to be used with a {@linkcode Deno.Proxy} + * server when specifying {@linkcode Deno.CreateHttpClientOptions}. + * + * @category Fetch + */ + export interface BasicAuth { + /** The username to be used against the proxy server. */ + username: string; + /** The password to be used against the proxy server. */ + password: string; + } + + /** Create a custom HttpClient to use with {@linkcode fetch}. This is an + * extension of the web platform Fetch API which allows Deno to use custom + * TLS CA certificates and connect via a proxy while using `fetch()`. + * + * The `cert` and `key` options can be used to specify a client certificate + * and key to use when connecting to a server that requires client + * authentication (mutual TLS or mTLS). The `cert` and `key` options must be + * provided in PEM format. + * + * @example ```ts + * const caCert = await Deno.readTextFile("./ca.pem"); + * const client = Deno.createHttpClient({ caCerts: [ caCert ] }); + * const response = await fetch("https://myserver.com", { client }); + * ``` + * + * @example ```ts + * const client = Deno.createHttpClient({ + * proxy: { url: "http://myproxy.com:8080" } + * }); + * const response = await fetch("https://myserver.com", { client }); + * ``` + * + * @example ```ts + * const key = "----BEGIN PRIVATE KEY----..."; + * const cert = "----BEGIN CERTIFICATE----..."; + * const client = Deno.createHttpClient({ key, cert }); + * const response = await fetch("https://myserver.com", { client }); + * ``` + * + * @category Fetch + */ + export function createHttpClient( options: - & ServeTlsInit - & ( - | ServeTlsOptions - | (ServeTlsOptions & TlsCertifiedKeyOptions) - ), - ): HttpServer; + | CreateHttpClientOptions + | (CreateHttpClientOptions & TlsCertifiedKeyPem), + ): HttpClient; + + export {}; // only export exports } diff --git a/cli/tsc/dts/lib.deno.shared_globals.d.ts b/cli/tsc/dts/lib.deno.shared_globals.d.ts index 1521cf12de..ba872ef46e 100644 --- a/cli/tsc/dts/lib.deno.shared_globals.d.ts +++ b/cli/tsc/dts/lib.deno.shared_globals.d.ts @@ -13,6 +13,7 @@ /// /// /// +/// /** @category WASM */ declare namespace WebAssembly { @@ -412,7 +413,7 @@ declare function clearInterval(id?: number): void; declare function clearTimeout(id?: number): void; /** @category Platform */ -declare interface VoidFunction { +interface VoidFunction { (): void; } @@ -444,7 +445,7 @@ declare function queueMicrotask(func: VoidFunction): void; declare function dispatchEvent(event: Event): boolean; /** @category Platform */ -declare interface DOMStringList { +interface DOMStringList { /** Returns the number of strings in strings. */ readonly length: number; /** Returns true if strings contains string, and false otherwise. */ @@ -455,13 +456,13 @@ declare interface DOMStringList { } /** @category Platform */ -declare type BufferSource = ArrayBufferView | ArrayBuffer; +type BufferSource = ArrayBufferView | ArrayBuffer; /** @category I/O */ declare var console: Console; /** @category Events */ -declare interface ErrorEventInit extends EventInit { +interface ErrorEventInit extends EventInit { message?: string; filename?: string; lineno?: number; @@ -470,7 +471,7 @@ declare interface ErrorEventInit extends EventInit { } /** @category Events */ -declare interface ErrorEvent extends Event { +interface ErrorEvent extends Event { readonly message: string; readonly filename: string; readonly lineno: number; @@ -485,13 +486,13 @@ declare var ErrorEvent: { }; /** @category Events */ -declare interface PromiseRejectionEventInit extends EventInit { +interface PromiseRejectionEventInit extends EventInit { promise: Promise; reason?: any; } /** @category Events */ -declare interface PromiseRejectionEvent extends Event { +interface PromiseRejectionEvent extends Event { readonly promise: Promise; readonly reason: any; } @@ -506,24 +507,24 @@ declare var PromiseRejectionEvent: { }; /** @category Workers */ -declare interface AbstractWorkerEventMap { +interface AbstractWorkerEventMap { "error": ErrorEvent; } /** @category Workers */ -declare interface WorkerEventMap extends AbstractWorkerEventMap { +interface WorkerEventMap extends AbstractWorkerEventMap { "message": MessageEvent; "messageerror": MessageEvent; } /** @category Workers */ -declare interface WorkerOptions { +interface WorkerOptions { type?: "classic" | "module"; name?: string; } /** @category Workers */ -declare interface Worker extends EventTarget { +interface Worker extends EventTarget { onerror: (this: Worker, e: ErrorEvent) => any | null; onmessage: (this: Worker, e: MessageEvent) => any | null; onmessageerror: (this: Worker, e: MessageEvent) => any | null; @@ -559,10 +560,10 @@ declare var Worker: { }; /** @category Performance */ -declare type PerformanceEntryList = PerformanceEntry[]; +type PerformanceEntryList = PerformanceEntry[]; /** @category Performance */ -declare interface Performance extends EventTarget { +interface Performance extends EventTarget { /** Returns a timestamp representing the start of the performance measurement. */ readonly timeOrigin: number; @@ -593,16 +594,12 @@ declare interface Performance extends EventTarget { endMark?: string, ): PerformanceMeasure; - /** Returns a current time from Deno's start in milliseconds. - * - * Use the permission flag `--allow-hrtime` to return a precise value. + /** Returns a current time from Deno's start in fractional milliseconds. * * ```ts * const t = performance.now(); * console.log(`${t} ms since start!`); * ``` - * - * @tags allow-hrtime */ now(): number; @@ -620,7 +617,7 @@ declare var Performance: { declare var performance: Performance; /** @category Performance */ -declare interface PerformanceMarkOptions { +interface PerformanceMarkOptions { /** Metadata to be included in the mark. */ detail?: any; @@ -629,7 +626,7 @@ declare interface PerformanceMarkOptions { } /** @category Performance */ -declare interface PerformanceMeasureOptions { +interface PerformanceMeasureOptions { /** Metadata to be included in the measure. */ detail?: any; @@ -651,7 +648,7 @@ declare interface PerformanceMeasureOptions { * * @category Performance */ -declare interface PerformanceEntry { +interface PerformanceEntry { readonly duration: number; readonly entryType: string; readonly name: string; @@ -678,7 +675,7 @@ declare var PerformanceEntry: { * * @category Performance */ -declare interface PerformanceMark extends PerformanceEntry { +interface PerformanceMark extends PerformanceEntry { readonly detail: any; readonly entryType: "mark"; } @@ -702,7 +699,7 @@ declare var PerformanceMark: { * * @category Performance */ -declare interface PerformanceMeasure extends PerformanceEntry { +interface PerformanceMeasure extends PerformanceEntry { readonly detail: any; readonly entryType: "measure"; } @@ -720,12 +717,12 @@ declare var PerformanceMeasure: { }; /** @category Events */ -declare interface CustomEventInit extends EventInit { +interface CustomEventInit extends EventInit { detail?: T; } /** @category Events */ -declare interface CustomEvent extends Event { +interface CustomEvent extends Event { /** Returns any custom data event was created with. Typically used for * synthetic events. */ readonly detail: T; @@ -738,9 +735,21 @@ declare var CustomEvent: { }; /** @category Platform */ -declare interface ErrorConstructor { +interface ErrorConstructor { /** See https://v8.dev/docs/stack-trace-api#stack-trace-collection-for-custom-exceptions. */ captureStackTrace(error: Object, constructor?: Function): void; // TODO(nayeemrmn): Support `Error.prepareStackTrace()`. We currently use this // internally in a way that makes it unavailable for users. } + +/** The [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) + * which also supports setting a {@linkcode Deno.HttpClient} which provides a + * way to connect via proxies and use custom TLS certificates. + * + * @tags allow-net, allow-read + * @category Fetch + */ +declare function fetch( + input: Request | URL | string, + init?: RequestInit & { client: Deno.HttpClient }, +): Promise; diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts index 747ce5a7f0..973a09d92a 100644 --- a/cli/tsc/dts/lib.deno.unstable.d.ts +++ b/cli/tsc/dts/lib.deno.unstable.d.ts @@ -3,828 +3,12 @@ /// /// /// -/// /// /// declare namespace Deno { export {}; // stop default export type behavior - /** Information for a HTTP request. - * - * @category HTTP Server - * @experimental - */ - export interface ServeHandlerInfo { - /** The remote address of the connection. */ - remoteAddr: Deno.NetAddr; - /** The completion promise */ - completed: Promise; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Retrieve the process umask. If `mask` is provided, sets the process umask. - * This call always returns what the umask was before the call. - * - * ```ts - * console.log(Deno.umask()); // e.g. 18 (0o022) - * const prevUmaskValue = Deno.umask(0o077); // e.g. 18 (0o022) - * console.log(Deno.umask()); // e.g. 63 (0o077) - * ``` - * - * This API is under consideration to determine if permissions are required to - * call it. - * - * *Note*: This API is not implemented on Windows - * - * @category File System - * @experimental - */ - export function umask(mask?: number): number; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * All plain number types for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeNumberType = - | "u8" - | "i8" - | "u16" - | "i16" - | "u32" - | "i32" - | "f32" - | "f64"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * All BigInt number types for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeBigIntType = - | "u64" - | "i64" - | "usize" - | "isize"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native boolean type for interfacing to foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeBooleanType = "bool"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native pointer type for interfacing to foreign functions. - * - * @category FFI - * @experimental - */ - export type NativePointerType = "pointer"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native buffer type for interfacing to foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeBufferType = "buffer"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native function type for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeFunctionType = "function"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native void type for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeVoidType = "void"; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The native struct type for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeStructType = { readonly struct: readonly NativeType[] }; - - /** - * @category FFI - * @experimental - */ - export const brand: unique symbol; - - /** - * @category FFI - * @experimental - */ - export type NativeU8Enum = "u8" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeI8Enum = "i8" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeU16Enum = "u16" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeI16Enum = "i16" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeU32Enum = "u32" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeI32Enum = "i32" & { [brand]: T }; - /** - * @category FFI - * @experimental - */ - export type NativeTypedPointer = "pointer" & { - [brand]: T; - }; - /** - * @category FFI - * @experimental - */ - export type NativeTypedFunction = - & "function" - & { - [brand]: T; - }; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * All supported types for interfacing with foreign functions. - * - * @category FFI - * @experimental - */ - export type NativeType = - | NativeNumberType - | NativeBigIntType - | NativeBooleanType - | NativePointerType - | NativeBufferType - | NativeFunctionType - | NativeStructType; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export type NativeResultType = NativeType | NativeVoidType; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Type conversion for foreign symbol parameters and unsafe callback return - * types. - * - * @category FFI - * @experimental - */ - export type ToNativeType = T extends - NativeStructType ? BufferSource - : T extends NativeNumberType ? T extends NativeU8Enum ? U - : T extends NativeI8Enum ? U - : T extends NativeU16Enum ? U - : T extends NativeI16Enum ? U - : T extends NativeU32Enum ? U - : T extends NativeI32Enum ? U - : number - : T extends NativeBigIntType ? bigint - : T extends NativeBooleanType ? boolean - : T extends NativePointerType - ? T extends NativeTypedPointer ? U | null : PointerValue - : T extends NativeFunctionType - ? T extends NativeTypedFunction ? PointerValue | null - : PointerValue - : T extends NativeBufferType ? BufferSource | null - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Type conversion for unsafe callback return types. - * - * @category FFI - * @experimental - */ - export type ToNativeResultType< - T extends NativeResultType = NativeResultType, - > = T extends NativeStructType ? BufferSource - : T extends NativeNumberType ? T extends NativeU8Enum ? U - : T extends NativeI8Enum ? U - : T extends NativeU16Enum ? U - : T extends NativeI16Enum ? U - : T extends NativeU32Enum ? U - : T extends NativeI32Enum ? U - : number - : T extends NativeBigIntType ? bigint - : T extends NativeBooleanType ? boolean - : T extends NativePointerType - ? T extends NativeTypedPointer ? U | null : PointerValue - : T extends NativeFunctionType - ? T extends NativeTypedFunction ? PointerObject | null - : PointerValue - : T extends NativeBufferType ? BufferSource | null - : T extends NativeVoidType ? void - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A utility type for conversion of parameter types of foreign functions. - * - * @category FFI - * @experimental - */ - export type ToNativeParameterTypes = - // - [(T[number])[]] extends [T] ? ToNativeType[] - : [readonly (T[number])[]] extends [T] - ? readonly ToNativeType[] - : T extends readonly [...NativeType[]] ? { - [K in keyof T]: ToNativeType; - } - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Type conversion for foreign symbol return types and unsafe callback - * parameters. - * - * @category FFI - * @experimental - */ - export type FromNativeType = T extends - NativeStructType ? Uint8Array - : T extends NativeNumberType ? T extends NativeU8Enum ? U - : T extends NativeI8Enum ? U - : T extends NativeU16Enum ? U - : T extends NativeI16Enum ? U - : T extends NativeU32Enum ? U - : T extends NativeI32Enum ? U - : number - : T extends NativeBigIntType ? bigint - : T extends NativeBooleanType ? boolean - : T extends NativePointerType - ? T extends NativeTypedPointer ? U | null : PointerValue - : T extends NativeBufferType ? PointerValue - : T extends NativeFunctionType - ? T extends NativeTypedFunction ? PointerObject | null - : PointerValue - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Type conversion for foreign symbol return types. - * - * @category FFI - * @experimental - */ - export type FromNativeResultType< - T extends NativeResultType = NativeResultType, - > = T extends NativeStructType ? Uint8Array - : T extends NativeNumberType ? T extends NativeU8Enum ? U - : T extends NativeI8Enum ? U - : T extends NativeU16Enum ? U - : T extends NativeI16Enum ? U - : T extends NativeU32Enum ? U - : T extends NativeI32Enum ? U - : number - : T extends NativeBigIntType ? bigint - : T extends NativeBooleanType ? boolean - : T extends NativePointerType - ? T extends NativeTypedPointer ? U | null : PointerValue - : T extends NativeBufferType ? PointerValue - : T extends NativeFunctionType - ? T extends NativeTypedFunction ? PointerObject | null - : PointerValue - : T extends NativeVoidType ? void - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export type FromNativeParameterTypes< - T extends readonly NativeType[], - > = - // - [(T[number])[]] extends [T] ? FromNativeType[] - : [readonly (T[number])[]] extends [T] - ? readonly FromNativeType[] - : T extends readonly [...NativeType[]] ? { - [K in keyof T]: FromNativeType; - } - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The interface for a foreign function as defined by its parameter and result - * types. - * - * @category FFI - * @experimental - */ - export interface ForeignFunction< - Parameters extends readonly NativeType[] = readonly NativeType[], - Result extends NativeResultType = NativeResultType, - NonBlocking extends boolean = boolean, - > { - /** Name of the symbol. - * - * Defaults to the key name in symbols object. */ - name?: string; - /** The parameters of the foreign function. */ - parameters: Parameters; - /** The result (return value) of the foreign function. */ - result: Result; - /** When `true`, function calls will run on a dedicated blocking thread and - * will return a `Promise` resolving to the `result`. */ - nonblocking?: NonBlocking; - /** When `true`, dlopen will not fail if the symbol is not found. - * Instead, the symbol will be set to `null`. - * - * @default {false} */ - optional?: boolean; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export interface ForeignStatic { - /** Name of the symbol, defaults to the key name in symbols object. */ - name?: string; - /** The type of the foreign static value. */ - type: Type; - /** When `true`, dlopen will not fail if the symbol is not found. - * Instead, the symbol will be set to `null`. - * - * @default {false} */ - optional?: boolean; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A foreign library interface descriptor. - * - * @category FFI - * @experimental - */ - export interface ForeignLibraryInterface { - [name: string]: ForeignFunction | ForeignStatic; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A utility type that infers a foreign symbol. - * - * @category FFI - * @experimental - */ - export type StaticForeignSymbol = - T extends ForeignFunction ? FromForeignFunction - : T extends ForeignStatic ? FromNativeType - : never; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export type FromForeignFunction = - T["parameters"] extends readonly [] ? () => StaticForeignSymbolReturnType - : ( - ...args: ToNativeParameterTypes - ) => StaticForeignSymbolReturnType; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export type StaticForeignSymbolReturnType = - ConditionalAsync>; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * @category FFI - * @experimental - */ - export type ConditionalAsync = - IsAsync extends true ? Promise : T; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A utility type that infers a foreign library interface. - * - * @category FFI - * @experimental - */ - export type StaticForeignLibraryInterface = - { - [K in keyof T]: T[K]["optional"] extends true - ? StaticForeignSymbol | null - : StaticForeignSymbol; - }; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A non-null pointer, represented as an object - * at runtime. The object's prototype is `null` - * and cannot be changed. The object cannot be - * assigned to either and is thus entirely read-only. - * - * To interact with memory through a pointer use the - * {@linkcode UnsafePointerView} class. To create a - * pointer from an address or the get the address of - * a pointer use the static methods of the - * {@linkcode UnsafePointer} class. - * - * @category FFI - * @experimental - */ - export type PointerObject = { [brand]: T }; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Pointers are represented either with a {@linkcode PointerObject} - * object or a `null` if the pointer is null. - * - * @category FFI - * @experimental - */ - export type PointerValue = null | PointerObject; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A collection of static functions for interacting with pointer objects. - * - * @category FFI - * @experimental - */ - export class UnsafePointer { - /** Create a pointer from a numeric value. This one is really dangerous! */ - static create(value: bigint): PointerValue; - /** Returns `true` if the two pointers point to the same address. */ - static equals(a: PointerValue, b: PointerValue): boolean; - /** Return the direct memory pointer to the typed array in memory. */ - static of( - value: Deno.UnsafeCallback | BufferSource, - ): PointerValue; - /** Return a new pointer offset from the original by `offset` bytes. */ - static offset( - value: PointerObject, - offset: number, - ): PointerValue; - /** Get the numeric value of a pointer */ - static value(value: PointerValue): bigint; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * An unsafe pointer view to a memory location as specified by the `pointer` - * value. The `UnsafePointerView` API follows the standard built in interface - * {@linkcode DataView} for accessing the underlying types at an memory - * location (numbers, strings and raw bytes). - * - * @category FFI - * @experimental - */ - export class UnsafePointerView { - constructor(pointer: PointerObject); - - pointer: PointerObject; - - /** Gets a boolean at the specified byte offset from the pointer. */ - getBool(offset?: number): boolean; - /** Gets an unsigned 8-bit integer at the specified byte offset from the - * pointer. */ - getUint8(offset?: number): number; - /** Gets a signed 8-bit integer at the specified byte offset from the - * pointer. */ - getInt8(offset?: number): number; - /** Gets an unsigned 16-bit integer at the specified byte offset from the - * pointer. */ - getUint16(offset?: number): number; - /** Gets a signed 16-bit integer at the specified byte offset from the - * pointer. */ - getInt16(offset?: number): number; - /** Gets an unsigned 32-bit integer at the specified byte offset from the - * pointer. */ - getUint32(offset?: number): number; - /** Gets a signed 32-bit integer at the specified byte offset from the - * pointer. */ - getInt32(offset?: number): number; - /** Gets an unsigned 64-bit integer at the specified byte offset from the - * pointer. */ - getBigUint64(offset?: number): bigint; - /** Gets a signed 64-bit integer at the specified byte offset from the - * pointer. */ - getBigInt64(offset?: number): bigint; - /** Gets a signed 32-bit float at the specified byte offset from the - * pointer. */ - getFloat32(offset?: number): number; - /** Gets a signed 64-bit float at the specified byte offset from the - * pointer. */ - getFloat64(offset?: number): number; - /** Gets a pointer at the specified byte offset from the pointer */ - getPointer(offset?: number): PointerValue; - /** Gets a C string (`null` terminated string) at the specified byte offset - * from the pointer. */ - getCString(offset?: number): string; - /** Gets a C string (`null` terminated string) at the specified byte offset - * from the specified pointer. */ - static getCString( - pointer: PointerObject, - offset?: number, - ): string; - /** Gets an `ArrayBuffer` of length `byteLength` at the specified byte - * offset from the pointer. */ - getArrayBuffer(byteLength: number, offset?: number): ArrayBuffer; - /** Gets an `ArrayBuffer` of length `byteLength` at the specified byte - * offset from the specified pointer. */ - static getArrayBuffer( - pointer: PointerObject, - byteLength: number, - offset?: number, - ): ArrayBuffer; - /** Copies the memory of the pointer into a typed array. - * - * Length is determined from the typed array's `byteLength`. - * - * Also takes optional byte offset from the pointer. */ - copyInto(destination: BufferSource, offset?: number): void; - /** Copies the memory of the specified pointer into a typed array. - * - * Length is determined from the typed array's `byteLength`. - * - * Also takes optional byte offset from the pointer. */ - static copyInto( - pointer: PointerObject, - destination: BufferSource, - offset?: number, - ): void; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * An unsafe pointer to a function, for calling functions that are not present - * as symbols. - * - * @category FFI - * @experimental - */ - export class UnsafeFnPointer { - /** The pointer to the function. */ - pointer: PointerObject; - /** The definition of the function. */ - definition: Fn; - - constructor(pointer: PointerObject>, definition: Fn); - /** @deprecated Properly type {@linkcode pointer} using {@linkcode NativeTypedFunction} or {@linkcode UnsafeCallbackDefinition} types. */ - constructor(pointer: PointerObject, definition: Fn); - - /** Call the foreign function. */ - call: FromForeignFunction; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Definition of a unsafe callback function. - * - * @category FFI - * @experimental - */ - export interface UnsafeCallbackDefinition< - Parameters extends readonly NativeType[] = readonly NativeType[], - Result extends NativeResultType = NativeResultType, - > { - /** The parameters of the callbacks. */ - parameters: Parameters; - /** The current result of the callback. */ - result: Result; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * An unsafe callback function. - * - * @category FFI - * @experimental - */ - export type UnsafeCallbackFunction< - Parameters extends readonly NativeType[] = readonly NativeType[], - Result extends NativeResultType = NativeResultType, - > = Parameters extends readonly [] ? () => ToNativeResultType : ( - ...args: FromNativeParameterTypes - ) => ToNativeResultType; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * An unsafe function pointer for passing JavaScript functions as C function - * pointers to foreign function calls. - * - * The function pointer remains valid until the `close()` method is called. - * - * All `UnsafeCallback` are always thread safe in that they can be called from - * foreign threads without crashing. However, they do not wake up the Deno event - * loop by default. - * - * If a callback is to be called from foreign threads, use the `threadSafe()` - * static constructor or explicitly call `ref()` to have the callback wake up - * the Deno event loop when called from foreign threads. This also stops - * Deno's process from exiting while the callback still exists and is not - * unref'ed. - * - * Use `deref()` to then allow Deno's process to exit. Calling `deref()` on - * a ref'ed callback does not stop it from waking up the Deno event loop when - * called from foreign threads. - * - * @category FFI - * @experimental - */ - export class UnsafeCallback< - const Definition extends UnsafeCallbackDefinition = - UnsafeCallbackDefinition, - > { - constructor( - definition: Definition, - callback: UnsafeCallbackFunction< - Definition["parameters"], - Definition["result"] - >, - ); - - /** The pointer to the unsafe callback. */ - readonly pointer: PointerObject; - /** The definition of the unsafe callback. */ - readonly definition: Definition; - /** The callback function. */ - readonly callback: UnsafeCallbackFunction< - Definition["parameters"], - Definition["result"] - >; - - /** - * Creates an {@linkcode UnsafeCallback} and calls `ref()` once to allow it to - * wake up the Deno event loop when called from foreign threads. - * - * This also stops Deno's process from exiting while the callback still - * exists and is not unref'ed. - */ - static threadSafe< - Definition extends UnsafeCallbackDefinition = UnsafeCallbackDefinition, - >( - definition: Definition, - callback: UnsafeCallbackFunction< - Definition["parameters"], - Definition["result"] - >, - ): UnsafeCallback; - - /** - * Increments the callback's reference counting and returns the new - * reference count. - * - * After `ref()` has been called, the callback always wakes up the - * Deno event loop when called from foreign threads. - * - * If the callback's reference count is non-zero, it keeps Deno's - * process from exiting. - */ - ref(): number; - - /** - * Decrements the callback's reference counting and returns the new - * reference count. - * - * Calling `unref()` does not stop a callback from waking up the Deno - * event loop when called from foreign threads. - * - * If the callback's reference counter is zero, it no longer keeps - * Deno's process from exiting. - */ - unref(): number; - - /** - * Removes the C function pointer associated with this instance. - * - * Continuing to use the instance or the C function pointer after closing - * the `UnsafeCallback` will lead to errors and crashes. - * - * Calling this method sets the callback's reference counting to zero, - * stops the callback from waking up the Deno event loop when called from - * foreign threads and no longer keeps Deno's process from exiting. - */ - close(): void; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A dynamic library resource. Use {@linkcode Deno.dlopen} to load a dynamic - * library and return this interface. - * - * @category FFI - * @experimental - */ - export interface DynamicLibrary { - /** All of the registered library along with functions for calling them. */ - symbols: StaticForeignLibraryInterface; - /** Removes the pointers associated with the library symbols. - * - * Continuing to use symbols that are part of the library will lead to - * errors and crashes. - * - * Calling this method will also immediately set any references to zero and - * will no longer keep Deno's process from exiting. - */ - close(): void; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Opens an external dynamic library and registers symbols, making foreign - * functions available to be called. - * - * Requires `allow-ffi` permission. Loading foreign dynamic libraries can in - * theory bypass all of the sandbox permissions. While it is a separate - * permission users should acknowledge in practice that is effectively the - * same as running with the `allow-all` permission. - * - * @example Given a C library which exports a foreign function named `add()` - * - * ```ts - * // Determine library extension based on - * // your OS. - * let libSuffix = ""; - * switch (Deno.build.os) { - * case "windows": - * libSuffix = "dll"; - * break; - * case "darwin": - * libSuffix = "dylib"; - * break; - * default: - * libSuffix = "so"; - * break; - * } - * - * const libName = `./libadd.${libSuffix}`; - * // Open library and define exported symbols - * const dylib = Deno.dlopen( - * libName, - * { - * "add": { parameters: ["isize", "isize"], result: "isize" }, - * } as const, - * ); - * - * // Call the symbol `add` - * const result = dylib.symbols.add(35n, 34n); // 69n - * - * console.log(`Result from external addition of 35 and 34: ${result}`); - * ``` - * - * @tags allow-ffi - * @category FFI - * @experimental - */ - export function dlopen( - filename: string | URL, - symbols: S, - ): DynamicLibrary; - /** **UNSTABLE**: New API, yet to be vetted. * * Creates a presentable WebGPU surface from given window and @@ -844,223 +28,18 @@ declare namespace Deno { */ export class UnsafeWindowSurface { constructor( - system: "cocoa" | "win32" | "x11" | "wayland", - windowHandle: Deno.PointerValue, - displayHandle: Deno.PointerValue, + options: { + system: "cocoa" | "win32" | "x11" | "wayland"; + windowHandle: Deno.PointerValue; + displayHandle: Deno.PointerValue; + width: number; + height: number; + }, ); getContext(context: "webgpu"): GPUCanvasContext; present(): void; } - /** **UNSTABLE**: New API, yet to be vetted. - * - * These are unstable options which can be used with {@linkcode Deno.run}. - * - * @category Subprocess - * @experimental - */ - export interface UnstableRunOptions extends RunOptions { - /** If `true`, clears the environment variables before executing the - * sub-process. - * - * @default {false} */ - clearEnv?: boolean; - /** For POSIX systems, sets the group ID for the sub process. */ - gid?: number; - /** For POSIX systems, sets the user ID for the sub process. */ - uid?: number; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Spawns new subprocess. RunOptions must contain at a minimum the `opt.cmd`, - * an array of program arguments, the first of which is the binary. - * - * ```ts - * const p = Deno.run({ - * cmd: ["curl", "https://example.com"], - * }); - * const status = await p.status(); - * ``` - * - * Subprocess uses same working directory as parent process unless `opt.cwd` - * is specified. - * - * Environmental variables from parent process can be cleared using `opt.clearEnv`. - * Doesn't guarantee that only `opt.env` variables are present, - * as the OS may set environmental variables for processes. - * - * Environmental variables for subprocess can be specified using `opt.env` - * mapping. - * - * `opt.uid` sets the child process’s user ID. This translates to a setuid call - * in the child process. Failure in the setuid call will cause the spawn to fail. - * - * `opt.gid` is similar to `opt.uid`, but sets the group ID of the child process. - * This has the same semantics as the uid field. - * - * By default subprocess inherits stdio of parent process. To change - * this this, `opt.stdin`, `opt.stdout`, and `opt.stderr` can be set - * independently to a resource ID (_rid_) of an open file, `"inherit"`, - * `"piped"`, or `"null"`: - * - * - _number_: the resource ID of an open file/resource. This allows you to - * read or write to a file. - * - `"inherit"`: The default if unspecified. The subprocess inherits from the - * parent. - * - `"piped"`: A new pipe should be arranged to connect the parent and child - * sub-process. - * - `"null"`: This stream will be ignored. This is the equivalent of attaching - * the stream to `/dev/null`. - * - * Details of the spawned process are returned as an instance of - * {@linkcode Deno.Process}. - * - * Requires `allow-run` permission. - * - * @tags allow-run - * @category Subprocess - * @experimental - */ - export function run( - opt: T, - ): Process; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * A custom `HttpClient` for use with {@linkcode fetch} function. This is - * designed to allow custom certificates or proxies to be used with `fetch()`. - * - * @example ```ts - * const caCert = await Deno.readTextFile("./ca.pem"); - * const client = Deno.createHttpClient({ caCerts: [ caCert ] }); - * const req = await fetch("https://myserver.com", { client }); - * ``` - * - * @category Fetch - * @experimental - */ - export interface HttpClient extends Disposable { - /** Close the HTTP client. */ - close(): void; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The options used when creating a {@linkcode Deno.HttpClient}. - * - * @category Fetch - * @experimental - */ - export interface CreateHttpClientOptions { - /** A list of root certificates that will be used in addition to the - * default root certificates to verify the peer's certificate. - * - * Must be in PEM format. */ - caCerts?: string[]; - /** A HTTP proxy to use for new connections. */ - proxy?: Proxy; - /** Sets the maximum number of idle connections per host allowed in the pool. */ - poolMaxIdlePerHost?: number; - /** Set an optional timeout for idle sockets being kept-alive. - * Set to false to disable the timeout. */ - poolIdleTimeout?: number | false; - /** - * Whether HTTP/1.1 is allowed or not. - * - * @default {true} - */ - http1?: boolean; - /** Whether HTTP/2 is allowed or not. - * - * @default {true} - */ - http2?: boolean; - /** Whether setting the host header is allowed or not. - * - * @default {false} - */ - allowHost?: boolean; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * The definition of a proxy when specifying - * {@linkcode Deno.CreateHttpClientOptions}. - * - * @category Fetch - * @experimental - */ - export interface Proxy { - /** The string URL of the proxy server to use. */ - url: string; - /** The basic auth credentials to be used against the proxy server. */ - basicAuth?: BasicAuth; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Basic authentication credentials to be used with a {@linkcode Deno.Proxy} - * server when specifying {@linkcode Deno.CreateHttpClientOptions}. - * - * @category Fetch - * @experimental - */ - export interface BasicAuth { - /** The username to be used against the proxy server. */ - username: string; - /** The password to be used against the proxy server. */ - password: string; - } - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Create a custom HttpClient to use with {@linkcode fetch}. This is an - * extension of the web platform Fetch API which allows Deno to use custom - * TLS certificates and connect via a proxy while using `fetch()`. - * - * @example ```ts - * const caCert = await Deno.readTextFile("./ca.pem"); - * const client = Deno.createHttpClient({ caCerts: [ caCert ] }); - * const response = await fetch("https://myserver.com", { client }); - * ``` - * - * @example ```ts - * const client = Deno.createHttpClient({ - * proxy: { url: "http://myproxy.com:8080" } - * }); - * const response = await fetch("https://myserver.com", { client }); - * ``` - * - * @category Fetch - * @experimental - */ - export function createHttpClient( - options: CreateHttpClientOptions, - ): HttpClient; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Create a custom HttpClient to use with {@linkcode fetch}. This is an - * extension of the web platform Fetch API which allows Deno to use custom - * TLS certificates and connect via a proxy while using `fetch()`. - * - * @example ```ts - * const caCert = await Deno.readTextFile("./ca.pem"); - * // Load a client key and certificate that we'll use to connect - * const key = await Deno.readTextFile("./key.key"); - * const cert = await Deno.readTextFile("./cert.crt"); - * const client = Deno.createHttpClient({ caCerts: [ caCert ], key, cert }); - * const response = await fetch("https://myserver.com", { client }); - * ``` - * - * @category Fetch - * @experimental - */ - export function createHttpClient( - options: CreateHttpClientOptions & TlsCertifiedKeyOptions, - ): HttpClient; - /** **UNSTABLE**: New API, yet to be vetted. * * Represents membership of a IPv4 multicast group. @@ -1216,44 +195,6 @@ declare namespace Deno { options: UnixListenOptions & { transport: "unixpacket" }, ): DatagramConn; - /** **UNSTABLE**: New API, yet to be vetted. - * - * Acquire an advisory file-system lock for the provided file. - * - * @param [exclusive=false] - * @category File System - * @experimental - */ - export function flock(rid: number, exclusive?: boolean): Promise; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Acquire an advisory file-system lock synchronously for the provided file. - * - * @param [exclusive=false] - * @category File System - * @experimental - */ - export function flockSync(rid: number, exclusive?: boolean): void; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Release an advisory file-system lock for the provided file. - * - * @category File System - * @experimental - */ - export function funlock(rid: number): Promise; - - /** **UNSTABLE**: New API, yet to be vetted. - * - * Release an advisory file-system lock for the provided file synchronously. - * - * @category File System - * @experimental - */ - export function funlockSync(rid: number): void; - /** **UNSTABLE**: New API, yet to be vetted. * * Open a new {@linkcode Deno.Kv} connection to persist data. @@ -1271,7 +212,7 @@ declare namespace Deno { * @category Cloud * @experimental */ - export function openKv(path?: string): Promise; + export function openKv(path?: string): Promise; /** **UNSTABLE**: New API, yet to be vetted. * @@ -1534,7 +475,11 @@ declare namespace Deno { * @category Cloud * @experimental */ - export type KvEntry = { key: KvKey; value: T; versionstamp: string }; + export interface KvEntry { + key: KvKey; + value: T; + versionstamp: string; + } /** * **UNSTABLE**: New API, yet to be vetted. @@ -1739,7 +684,7 @@ declare namespace Deno { value: unknown, options?: { delay?: number; - keysIfUndelivered?: Deno.KvKey[]; + keysIfUndelivered?: KvKey[]; backoffSchedule?: number[]; }, ): this; @@ -1970,7 +915,7 @@ declare namespace Deno { value: unknown, options?: { delay?: number; - keysIfUndelivered?: Deno.KvKey[]; + keysIfUndelivered?: KvKey[]; backoffSchedule?: number[]; }, ): Promise; @@ -2100,10 +1045,10 @@ declare namespace Deno { * @category Jupyter * @experimental */ - export type VegaObject = { + export interface VegaObject { $schema: string; [key: string]: unknown; - }; + } /** * A collection of supported media types and data for Jupyter frontends. @@ -2111,7 +1056,7 @@ declare namespace Deno { * @category Jupyter * @experimental */ - export type MediaBundle = { + export interface MediaBundle { "text/plain"?: string; "text/html"?: string; "image/svg+xml"?: string; @@ -2137,7 +1082,7 @@ declare namespace Deno { // Must support a catch all for custom media types / mimetypes [key: string]: string | object | undefined; - }; + } /** * @category Jupyter @@ -2149,9 +1094,9 @@ declare namespace Deno { * @category Jupyter * @experimental */ - export type Displayable = { + export interface Displayable { [$display]: () => MediaBundle | Promise; - }; + } /** * Display function for Jupyter Deno Kernel. @@ -2163,7 +1108,10 @@ declare namespace Deno { * @category Jupyter * @experimental */ - export function display(obj: unknown, options?: DisplayOptions): void; + export function display( + obj: unknown, + options?: DisplayOptions, + ): Promise; /** * Show Markdown in Jupyter frontends with a tagged template function. @@ -2236,12 +1184,12 @@ declare namespace Deno { * Format an object for displaying in Deno * * @param obj - The object to be displayed - * @returns MediaBundle + * @returns Promise * * @category Jupyter * @experimental */ - export function format(obj: unknown): MediaBundle; + export function format(obj: unknown): Promise; /** * Broadcast a message on IO pub channel. @@ -2273,30 +1221,19 @@ declare namespace Deno { buffers?: Uint8Array[]; }, ): Promise; - } -} -/** **UNSTABLE**: New API, yet to be vetted. - * - * The [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) - * which also supports setting a {@linkcode Deno.HttpClient} which provides a - * way to connect via proxies and use custom TLS certificates. - * - * @tags allow-net, allow-read - * @category Fetch - * @experimental - */ -declare function fetch( - input: Request | URL | string, - init?: RequestInit & { client: Deno.HttpClient }, -): Promise; + export {}; // only export exports + } + + export {}; // only export exports +} /** **UNSTABLE**: New API, yet to be vetted. * * @category Workers * @experimental */ -declare interface WorkerOptions { +interface WorkerOptions { /** **UNSTABLE**: New API, yet to be vetted. * * Configure permissions options to change the level of access the worker will @@ -2337,7 +1274,7 @@ declare interface WorkerOptions { * @category WebSockets * @experimental */ -declare interface WebSocketStreamOptions { +interface WebSocketStreamOptions { protocols?: string[]; signal?: AbortSignal; headers?: HeadersInit; @@ -2348,7 +1285,7 @@ declare interface WebSocketStreamOptions { * @category WebSockets * @experimental */ -declare interface WebSocketConnection { +interface WebSocketConnection { readable: ReadableStream; writable: WritableStream; extensions: string; @@ -2360,7 +1297,7 @@ declare interface WebSocketConnection { * @category WebSockets * @experimental */ -declare interface WebSocketCloseInfo { +interface WebSocketCloseInfo { code?: number; reason?: string; } @@ -2371,7 +1308,7 @@ declare interface WebSocketCloseInfo { * @category WebSockets * @experimental */ -declare interface WebSocketStream { +interface WebSocketStream { url: string; opened: Promise; closed: Promise; @@ -2395,7 +1332,7 @@ declare var WebSocketStream: { * @category WebSockets * @experimental */ -declare interface WebSocketError extends DOMException { +interface WebSocketError extends DOMException { readonly closeCode: number; readonly reason: string; } @@ -2992,8 +1929,7 @@ declare namespace Temporal { }; /** - * Options to control behavior of `Duration.compare()`, `Duration.add()`, and - * `Duration.subtract()` + * Options to control behavior of `Duration.compare()` * * @category Temporal * @experimental @@ -3196,9 +2132,6 @@ declare namespace Temporal { | "nanosecond" >, ): Temporal.Instant; - toZonedDateTime( - calendarAndTimeZone: { timeZone: TimeZoneLike; calendar: CalendarLike }, - ): Temporal.ZonedDateTime; toZonedDateTimeISO(tzLike: TimeZoneLike): Temporal.ZonedDateTime; toLocaleString( locales?: string | string[], @@ -3211,356 +2144,19 @@ declare namespace Temporal { } /** - * @category Temporal - * @experimental - */ - export type YearOrEraAndEraYear = { era: string; eraYear: number } | { - year: number; - }; - /** - * @category Temporal - * @experimental - */ - export type MonthCodeOrMonthAndYear = - | (YearOrEraAndEraYear & { month: number }) - | { - monthCode: string; - }; - /** - * @category Temporal - * @experimental - */ - export type MonthOrMonthCode = { month: number } | { monthCode: string }; - - /** - * @category Temporal - * @experimental - */ - export interface CalendarProtocol { - id: string; - year( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - month( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): number; - monthCode( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): string; - day( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): number; - era( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): string | undefined; - eraYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - dayOfWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - dayOfYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - weekOfYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - yearOfWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - daysInWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - daysInMonth( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - daysInYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - monthsInYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - inLeapYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): boolean; - dateFromFields( - fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number }, - options?: AssignmentOptions, - ): Temporal.PlainDate; - yearMonthFromFields( - fields: YearOrEraAndEraYear & MonthOrMonthCode, - options?: AssignmentOptions, - ): Temporal.PlainYearMonth; - monthDayFromFields( - fields: MonthCodeOrMonthAndYear & { day: number }, - options?: AssignmentOptions, - ): Temporal.PlainMonthDay; - dateAdd( - date: Temporal.PlainDate | PlainDateLike | string, - duration: Temporal.Duration | DurationLike | string, - options?: ArithmeticOptions, - ): Temporal.PlainDate; - dateUntil( - one: Temporal.PlainDate | PlainDateLike | string, - two: Temporal.PlainDate | PlainDateLike | string, - options?: DifferenceOptions<"year" | "month" | "week" | "day">, - ): Temporal.Duration; - fields(fields: Iterable): Iterable; - mergeFields( - fields: Record, - additionalFields: Record, - ): Record; - toString?(): string; - toJSON?(): string; - } - - /** - * Any of these types can be passed to Temporal methods instead of a Temporal.Calendar. + * Any of these types can be passed to Temporal methods instead of a calendar ID. * * @category Temporal * @experimental */ export type CalendarLike = | string - | CalendarProtocol | ZonedDateTime | PlainDateTime | PlainDate | PlainYearMonth | PlainMonthDay; - /** - * A `Temporal.Calendar` is a representation of a calendar system. It includes - * information about how many days are in each year, how many months are in - * each year, how many days are in each month, and how to do arithmetic in - * that calendar system. - * - * See https://tc39.es/proposal-temporal/docs/calendar.html for more details. - * - * @category Temporal - * @experimental - */ - export class Calendar implements CalendarProtocol { - static from(item: CalendarLike): Temporal.Calendar | CalendarProtocol; - constructor(calendarIdentifier: string); - readonly id: string; - year( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - month( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): number; - monthCode( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): string; - day( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainMonthDay - | PlainDateLike - | string, - ): number; - era( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): string | undefined; - eraYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - dayOfWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - dayOfYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - weekOfYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - yearOfWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number | undefined; - daysInWeek( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | PlainDateLike - | string, - ): number; - daysInMonth( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - daysInYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - monthsInYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): number; - inLeapYear( - date: - | Temporal.PlainDate - | Temporal.PlainDateTime - | Temporal.PlainYearMonth - | PlainDateLike - | string, - ): boolean; - dateFromFields( - fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number }, - options?: AssignmentOptions, - ): Temporal.PlainDate; - yearMonthFromFields( - fields: YearOrEraAndEraYear & MonthOrMonthCode, - options?: AssignmentOptions, - ): Temporal.PlainYearMonth; - monthDayFromFields( - fields: MonthCodeOrMonthAndYear & { day: number }, - options?: AssignmentOptions, - ): Temporal.PlainMonthDay; - dateAdd( - date: Temporal.PlainDate | PlainDateLike | string, - duration: Temporal.Duration | DurationLike | string, - options?: ArithmeticOptions, - ): Temporal.PlainDate; - dateUntil( - one: Temporal.PlainDate | PlainDateLike | string, - two: Temporal.PlainDate | PlainDateLike | string, - options?: DifferenceOptions<"year" | "month" | "week" | "day">, - ): Temporal.Duration; - fields(fields: Iterable): string[]; - mergeFields( - fields: Record, - additionalFields: Record, - ): Record; - toString(): string; - toJSON(): string; - readonly [Symbol.toStringTag]: "Temporal.Calendar"; - } - /** * @category Temporal * @experimental @@ -3575,17 +2171,6 @@ declare namespace Temporal { calendar?: CalendarLike; }; - /** - * @category Temporal - * @experimental - */ - export type PlainDateISOFields = { - isoYear: number; - isoMonth: number; - isoDay: number; - calendar: string | CalendarProtocol; - }; - /** * A `Temporal.PlainDate` represents a calendar date. "Calendar date" refers to the * concept of a date as expressed in everyday usage, independent of any time @@ -3611,7 +2196,7 @@ declare namespace Temporal { isoYear: number, isoMonth: number, isoDay: number, - calendar?: CalendarLike, + calendar?: string, ); readonly era: string | undefined; readonly eraYear: number | undefined; @@ -3656,7 +2241,6 @@ declare namespace Temporal { ): Temporal.PlainDateTime; toZonedDateTime( timeZoneAndTime: - | TimeZoneProtocol | string | { timeZone: TimeZoneLike; @@ -3665,7 +2249,6 @@ declare namespace Temporal { ): Temporal.ZonedDateTime; toPlainYearMonth(): Temporal.PlainYearMonth; toPlainMonthDay(): Temporal.PlainMonthDay; - getISOFields(): PlainDateISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -3696,23 +2279,6 @@ declare namespace Temporal { calendar?: CalendarLike; }; - /** - * @category Temporal - * @experimental - */ - export type PlainDateTimeISOFields = { - isoYear: number; - isoMonth: number; - isoDay: number; - isoHour: number; - isoMinute: number; - isoSecond: number; - isoMillisecond: number; - isoMicrosecond: number; - isoNanosecond: number; - calendar: string | CalendarProtocol; - }; - /** * A `Temporal.PlainDateTime` represents a calendar date and wall-clock time, with * a precision in nanoseconds, and without any time zone. Of the Temporal @@ -3745,7 +2311,7 @@ declare namespace Temporal { millisecond?: number, microsecond?: number, nanosecond?: number, - calendar?: CalendarLike, + calendar?: string, ); readonly era: string | undefined; readonly eraYear: number | undefined; @@ -3833,7 +2399,6 @@ declare namespace Temporal { ): Temporal.ZonedDateTime; toPlainDate(): Temporal.PlainDate; toPlainTime(): Temporal.PlainTime; - getISOFields(): PlainDateTimeISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -3876,7 +2441,7 @@ declare namespace Temporal { constructor( isoMonth: number, isoDay: number, - calendar?: CalendarLike, + calendar?: string, referenceISOYear?: number, ); readonly monthCode: string; @@ -3888,7 +2453,6 @@ declare namespace Temporal { options?: AssignmentOptions, ): Temporal.PlainMonthDay; toPlainDate(year: { year: number }): Temporal.PlainDate; - getISOFields(): PlainDateISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -3912,19 +2476,6 @@ declare namespace Temporal { nanosecond?: number; }; - /** - * @category Temporal - * @experimental - */ - export type PlainTimeISOFields = { - isoHour: number; - isoMinute: number; - isoSecond: number; - isoMillisecond: number; - isoMicrosecond: number; - isoNanosecond: number; - }; - /** * A `Temporal.PlainTime` represents a wall-clock time, with a precision in * nanoseconds, and without any time zone. "Wall-clock time" refers to the @@ -4011,7 +2562,6 @@ declare namespace Temporal { | "nanosecond" >, ): Temporal.PlainTime; - getISOFields(): PlainTimeISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -4023,76 +2573,12 @@ declare namespace Temporal { } /** - * A plain object implementing the protocol for a custom time zone. + * Any of these types can be passed to Temporal methods instead of a time zone ID. * * @category Temporal * @experimental */ - export interface TimeZoneProtocol { - id: string; - getOffsetNanosecondsFor(instant: Temporal.Instant | string): number; - getOffsetStringFor?(instant: Temporal.Instant | string): string; - getPlainDateTimeFor?( - instant: Temporal.Instant | string, - calendar?: CalendarLike, - ): Temporal.PlainDateTime; - getInstantFor?( - dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string, - options?: ToInstantOptions, - ): Temporal.Instant; - getPossibleInstantsFor( - dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string, - ): Temporal.Instant[]; - toString?(): string; - toJSON?(): string; - } - - /** - * Any of these types can be passed to Temporal methods instead of a Temporal.TimeZone. - * - * @category Temporal - * @experimental - */ - export type TimeZoneLike = string | TimeZoneProtocol | ZonedDateTime; - - /** - * A `Temporal.TimeZone` is a representation of a time zone: either an - * {@link https://www.iana.org/time-zones|IANA time zone}, including - * information about the time zone such as the offset between the local time - * and UTC at a particular time, and daylight saving time (DST) changes; or - * simply a particular UTC offset with no DST. - * - * `Temporal.ZonedDateTime` is the only Temporal type to contain a time zone. - * Other types, like `Temporal.Instant` and `Temporal.PlainDateTime`, do not - * contain any time zone information, and a `Temporal.TimeZone` object is - * required to convert between them. - * - * See https://tc39.es/proposal-temporal/docs/timezone.html for more details. - * - * @category Temporal - * @experimental - */ - export class TimeZone implements TimeZoneProtocol { - static from(timeZone: TimeZoneLike): Temporal.TimeZone | TimeZoneProtocol; - constructor(timeZoneIdentifier: string); - readonly id: string; - getOffsetNanosecondsFor(instant: Temporal.Instant | string): number; - getOffsetStringFor(instant: Temporal.Instant | string): string; - getPlainDateTimeFor( - instant: Temporal.Instant | string, - calendar?: CalendarLike, - ): Temporal.PlainDateTime; - getInstantFor( - dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string, - options?: ToInstantOptions, - ): Temporal.Instant; - getPossibleInstantsFor( - dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string, - ): Temporal.Instant[]; - toString(): string; - toJSON(): string; - readonly [Symbol.toStringTag]: "Temporal.TimeZone"; - } + export type TimeZoneLike = string | ZonedDateTime; /** * @category Temporal @@ -4129,7 +2615,7 @@ declare namespace Temporal { constructor( isoYear: number, isoMonth: number, - calendar?: CalendarLike, + calendar?: string, referenceISODay?: number, ); readonly era: string | undefined; @@ -4166,7 +2652,6 @@ declare namespace Temporal { options?: DifferenceOptions<"year" | "month">, ): Temporal.Duration; toPlainDate(day: { day: number }): Temporal.PlainDate; - getISOFields(): PlainDateISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -4199,25 +2684,6 @@ declare namespace Temporal { calendar?: CalendarLike; }; - /** - * @category Temporal - * @experimental - */ - export type ZonedDateTimeISOFields = { - isoYear: number; - isoMonth: number; - isoDay: number; - isoHour: number; - isoMinute: number; - isoSecond: number; - isoMillisecond: number; - isoMicrosecond: number; - isoNanosecond: number; - offset: string; - timeZone: string | TimeZoneProtocol; - calendar: string | CalendarProtocol; - }; - /** * @category Temporal * @experimental @@ -4231,11 +2697,7 @@ declare namespace Temporal { one: Temporal.ZonedDateTime | ZonedDateTimeLike | string, two: Temporal.ZonedDateTime | ZonedDateTimeLike | string, ): ComparisonResult; - constructor( - epochNanoseconds: bigint, - timeZone: TimeZoneLike, - calendar?: CalendarLike, - ); + constructor(epochNanoseconds: bigint, timeZone: string, calendar?: string); readonly era: string | undefined; readonly eraYear: number | undefined; readonly year: number; @@ -4262,9 +2724,7 @@ declare namespace Temporal { readonly inLeapYear: boolean; readonly offsetNanoseconds: number; readonly offset: string; - readonly epochSeconds: number; readonly epochMilliseconds: number; - readonly epochMicroseconds: bigint; readonly epochNanoseconds: bigint; equals(other: Temporal.ZonedDateTime | ZonedDateTimeLike | string): boolean; with( @@ -4333,7 +2793,6 @@ declare namespace Temporal { toPlainDateTime(): Temporal.PlainDateTime; toPlainDate(): Temporal.PlainDate; toPlainTime(): Temporal.PlainTime; - getISOFields(): ZonedDateTimeISOFields; toLocaleString( locales?: string | string[], options?: Intl.DateTimeFormatOptions, @@ -4374,8 +2833,7 @@ declare namespace Temporal { * * @param {TimeZoneLike} [tzLike] - * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier} - * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an - * object implementing the time zone protocol. If omitted, the environment's + * string (e.g. `'Europe/London'`). If omitted, the environment's * current time zone will be used. */ zonedDateTimeISO: (tzLike?: TimeZoneLike) => Temporal.ZonedDateTime; @@ -4391,8 +2849,7 @@ declare namespace Temporal { * * @param {TimeZoneLike} [tzLike] - * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier} - * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an - * object implementing the time zone protocol. If omitted, the environment's + * string (e.g. `'Europe/London'`). If omitted, the environment's * current time zone will be used. */ plainDateTimeISO: (tzLike?: TimeZoneLike) => Temporal.PlainDateTime; @@ -4403,8 +2860,7 @@ declare namespace Temporal { * * @param {TimeZoneLike} [tzLike] - * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier} - * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an - * object implementing the time zone protocol. If omitted, the environment's + * string (e.g. `'Europe/London'`). If omitted, the environment's * current time zone will be used. */ plainDateISO: (tzLike?: TimeZoneLike) => Temporal.PlainDate; @@ -4414,8 +2870,7 @@ declare namespace Temporal { * * @param {TimeZoneLike} [tzLike] - * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier} - * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an - * object implementing the time zone protocol. If omitted, the environment's + * string (e.g. `'Europe/London'`). If omitted, the environment's * current time zone will be used. */ plainTimeISO: (tzLike?: TimeZoneLike) => Temporal.PlainTime; @@ -4437,7 +2892,7 @@ declare namespace Temporal { * @category Temporal * @experimental */ -declare interface Date { +interface Date { toTemporalInstant(): Temporal.Instant; } @@ -4539,7 +2994,7 @@ declare namespace Intl { * @category Platform * @experimental */ -declare interface Float16Array { +interface Float16Array { /** * The size in bytes of each element in the array. */ @@ -4854,7 +3309,7 @@ declare interface Float16Array { * @category Platform * @experimental */ -declare interface Float16ArrayConstructor { +interface Float16ArrayConstructor { readonly prototype: Float16Array; new (length: number): Float16Array; new (array: ArrayLike | ArrayBufferLike): Float16Array; @@ -4903,7 +3358,7 @@ declare var Float16Array: Float16ArrayConstructor; * @category Platform * @experimental */ -declare interface Float16 { +interface Float16Array { [Symbol.iterator](): IterableIterator; /** * Returns an array of key, value pairs for every entry in the array @@ -4923,8 +3378,8 @@ declare interface Float16 { * @category Platform * @experimental */ -declare interface Float16Constructor { - new (elements: Iterable): Float16; +interface Float16Constructor { + new (elements: Iterable): Float16Array; /** * Creates an array from an array-like or iterable object. @@ -4936,14 +3391,14 @@ declare interface Float16Constructor { arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any, - ): Float16; + ): Float16Array; } /** * @category Platform * @experimental */ -declare interface Float16Array { +interface Float16Array { readonly [Symbol.toStringTag]: "Float16Array"; } @@ -4951,7 +3406,7 @@ declare interface Float16Array { * @category Platform * @experimental */ -declare interface Float16Array { +interface Float16Array { /** * Determines whether an array includes a certain element, returning true or false as appropriate. * @param searchElement The element to search for. @@ -4964,7 +3419,7 @@ declare interface Float16Array { * @category Platform * @experimental */ -declare interface Float16ArrayConstructor { +interface Float16ArrayConstructor { new (): Float16Array; } @@ -4972,7 +3427,7 @@ declare interface Float16ArrayConstructor { * @category Platform * @experimental */ -declare interface Float16Array { +interface Float16Array { /** * Returns the item located at the specified index. * @param index The zero-based index of the desired code unit. A negative index will count back from the last item. @@ -4984,7 +3439,7 @@ declare interface Float16Array { * @category Platform * @experimental */ -declare interface Float16Array { +interface Float16Array { /** * Returns the value of the last element in the array where predicate is true, and undefined * otherwise. @@ -5060,7 +3515,7 @@ declare interface Float16Array { * @category Platform * @experimental */ -declare interface DataView { +interface DataView { /** * Gets the Float16 value at the specified byte offset from the start of the view. There is * no alignment constraint; multi-byte values may be fetched from any offset. diff --git a/cli/tsc/dts/lib.deno.window.d.ts b/cli/tsc/dts/lib.deno.window.d.ts index 511bb04ad4..636e2b0fd0 100644 --- a/cli/tsc/dts/lib.deno.window.d.ts +++ b/cli/tsc/dts/lib.deno.window.d.ts @@ -8,14 +8,14 @@ /// /** @category Platform */ -declare interface WindowEventMap { +interface WindowEventMap { "error": ErrorEvent; "unhandledrejection": PromiseRejectionEvent; "rejectionhandled": PromiseRejectionEvent; } /** @category Platform */ -declare interface Window extends EventTarget { +interface Window extends EventTarget { readonly window: Window & typeof globalThis; readonly self: Window & typeof globalThis; onerror: ((this: Window, ev: ErrorEvent) => any) | null; @@ -105,7 +105,7 @@ declare var sessionStorage: Storage; declare var caches: CacheStorage; /** @category Platform */ -declare interface Navigator { +interface Navigator { readonly gpu: GPU; readonly hardwareConcurrency: number; readonly userAgent: string; @@ -221,7 +221,7 @@ declare function removeEventListener( * * @category Platform */ -declare interface Location { +interface Location { /** Returns a DOMStringList object listing the origins of the ancestor * browsing contexts, from the parent browsing context to the top-level * browsing context. diff --git a/cli/tsc/dts/lib.deno_webgpu.d.ts b/cli/tsc/dts/lib.deno_webgpu.d.ts index 944af0e4c5..2deb63abc7 100644 --- a/cli/tsc/dts/lib.deno_webgpu.d.ts +++ b/cli/tsc/dts/lib.deno_webgpu.d.ts @@ -5,26 +5,17 @@ /// /// -/** - * @category GPU - * @experimental - */ -declare interface GPUObjectBase { +/** @category GPU */ +interface GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUObjectDescriptorBase { label?: string; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUSupportedLimits { maxTextureDimension1D?: number; maxTextureDimension2D?: number; @@ -58,10 +49,7 @@ declare class GPUSupportedLimits { maxComputeWorkgroupsPerDimension?: number; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUSupportedFeatures { forEach( callbackfn: ( @@ -79,10 +67,7 @@ declare class GPUSupportedFeatures { values(): IterableIterator; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUAdapterInfo { readonly vendor: string; readonly architecture: string; @@ -90,10 +75,7 @@ declare class GPUAdapterInfo { readonly description: string; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPU { requestAdapter( options?: GPURequestAdapterOptions, @@ -101,25 +83,16 @@ declare class GPU { getPreferredCanvasFormat(): GPUTextureFormat; } -/** - * @category GPU - * @experimental - */ -declare interface GPURequestAdapterOptions { +/** @category GPU */ +interface GPURequestAdapterOptions { powerPreference?: GPUPowerPreference; forceFallbackAdapter?: boolean; } -/** - * @category GPU - * @experimental - */ -declare type GPUPowerPreference = "low-power" | "high-performance"; +/** @category GPU */ +type GPUPowerPreference = "low-power" | "high-performance"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUAdapter { readonly features: GPUSupportedFeatures; readonly limits: GPUSupportedLimits; @@ -129,20 +102,14 @@ declare class GPUAdapter { requestDevice(descriptor?: GPUDeviceDescriptor): Promise; } -/** - * @category GPU - * @experimental - */ -declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { requiredFeatures?: GPUFeatureName[]; requiredLimits?: Record; } -/** - * @category GPU - * @experimental - */ -declare type GPUFeatureName = +/** @category GPU */ +type GPUFeatureName = | "depth-clip-control" | "depth32float-stencil8" | "pipeline-statistics-query" @@ -169,10 +136,7 @@ declare type GPUFeatureName = | "shader-float64" | "vertex-attribute-64bit"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUDevice extends EventTarget implements GPUObjectBase { label: string; @@ -222,10 +186,7 @@ declare class GPUDevice extends EventTarget implements GPUObjectBase { createQuerySet(descriptor: GPUQuerySetDescriptor): GPUQuerySet; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUBuffer implements GPUObjectBase { label: string; @@ -244,38 +205,23 @@ declare class GPUBuffer implements GPUObjectBase { destroy(): undefined; } -/** - * @category GPU - * @experimental - */ -declare type GPUBufferMapState = "unmapped" | "pending" | "mapped"; +/** @category GPU */ +type GPUBufferMapState = "unmapped" | "pending" | "mapped"; -/** - * @category GPU - * @experimental - */ -declare interface GPUBufferDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUBufferDescriptor extends GPUObjectDescriptorBase { size: number; usage: GPUBufferUsageFlags; mappedAtCreation?: boolean; } -/** - * @category GPU - * @experimental - */ -declare type GPUBufferUsageFlags = number; +/** @category GPU */ +type GPUBufferUsageFlags = number; -/** - * @category GPU - * @experimental - */ -declare type GPUFlagsConstant = number; +/** @category GPU */ +type GPUFlagsConstant = number; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUBufferUsage { static MAP_READ: 0x0001; static MAP_WRITE: 0x0002; @@ -289,25 +235,16 @@ declare class GPUBufferUsage { static QUERY_RESOLVE: 0x0200; } -/** - * @category GPU - * @experimental - */ -declare type GPUMapModeFlags = number; +/** @category GPU */ +type GPUMapModeFlags = number; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUMapMode { static READ: 0x0001; static WRITE: 0x0002; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUTexture implements GPUObjectBase { label: string; @@ -324,11 +261,8 @@ declare class GPUTexture implements GPUObjectBase { readonly usage: GPUFlagsConstant; } -/** - * @category GPU - * @experimental - */ -declare interface GPUTextureDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUTextureDescriptor extends GPUObjectDescriptorBase { size: GPUExtent3D; mipLevelCount?: number; sampleCount?: number; @@ -338,22 +272,13 @@ declare interface GPUTextureDescriptor extends GPUObjectDescriptorBase { viewFormats?: GPUTextureFormat[]; } -/** - * @category GPU - * @experimental - */ -declare type GPUTextureDimension = "1d" | "2d" | "3d"; +/** @category GPU */ +type GPUTextureDimension = "1d" | "2d" | "3d"; -/** - * @category GPU - * @experimental - */ -declare type GPUTextureUsageFlags = number; +/** @category GPU */ +type GPUTextureUsageFlags = number; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUTextureUsage { static COPY_SRC: 0x01; static COPY_DST: 0x02; @@ -362,19 +287,13 @@ declare class GPUTextureUsage { static RENDER_ATTACHMENT: 0x10; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUTextureView implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase { format?: GPUTextureFormat; dimension?: GPUTextureViewDimension; aspect?: GPUTextureAspect; @@ -384,11 +303,8 @@ declare interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase { arrayLayerCount?: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUTextureViewDimension = +/** @category GPU */ +type GPUTextureViewDimension = | "1d" | "2d" | "2d-array" @@ -396,17 +312,11 @@ declare type GPUTextureViewDimension = | "cube-array" | "3d"; -/** - * @category GPU - * @experimental - */ -declare type GPUTextureAspect = "all" | "stencil-only" | "depth-only"; +/** @category GPU */ +type GPUTextureAspect = "all" | "stencil-only" | "depth-only"; -/** - * @category GPU - * @experimental - */ -declare type GPUTextureFormat = +/** @category GPU */ +type GPUTextureFormat = | "r8unorm" | "r8snorm" | "r8uint" @@ -503,19 +413,13 @@ declare type GPUTextureFormat = | "astc-12x12-unorm" | "astc-12x12-unorm-srgb"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUSampler implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { addressModeU?: GPUAddressMode; addressModeV?: GPUAddressMode; addressModeW?: GPUAddressMode; @@ -528,29 +432,17 @@ declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { maxAnisotropy?: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUAddressMode = "clamp-to-edge" | "repeat" | "mirror-repeat"; +/** @category GPU */ +type GPUAddressMode = "clamp-to-edge" | "repeat" | "mirror-repeat"; -/** - * @category GPU - * @experimental - */ -declare type GPUFilterMode = "nearest" | "linear"; +/** @category GPU */ +type GPUFilterMode = "nearest" | "linear"; -/** - * @category GPU - * @experimental - */ -declare type GPUMipmapFilterMode = "nearest" | "linear"; +/** @category GPU */ +type GPUMipmapFilterMode = "nearest" | "linear"; -/** - * @category GPU - * @experimental - */ -declare type GPUCompareFunction = +/** @category GPU */ +type GPUCompareFunction = | "never" | "less" | "equal" @@ -560,27 +452,18 @@ declare type GPUCompareFunction = | "greater-equal" | "always"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUBindGroupLayout implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase { entries: GPUBindGroupLayoutEntry[]; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBindGroupLayoutEntry { +/** @category GPU */ +interface GPUBindGroupLayoutEntry { binding: number; visibility: GPUShaderStageFlags; @@ -590,289 +473,188 @@ declare interface GPUBindGroupLayoutEntry { storageTexture?: GPUStorageTextureBindingLayout; } -/** - * @category GPU - * @experimental - */ -declare type GPUShaderStageFlags = number; +/** @category GPU */ +type GPUShaderStageFlags = number; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUShaderStage { static VERTEX: 0x1; static FRAGMENT: 0x2; static COMPUTE: 0x4; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBufferBindingLayout { +/** @category GPU */ +interface GPUBufferBindingLayout { type?: GPUBufferBindingType; hasDynamicOffset?: boolean; minBindingSize?: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUBufferBindingType = "uniform" | "storage" | "read-only-storage"; +/** @category GPU */ +type GPUBufferBindingType = "uniform" | "storage" | "read-only-storage"; -/** - * @category GPU - * @experimental - */ -declare interface GPUSamplerBindingLayout { +/** @category GPU */ +interface GPUSamplerBindingLayout { type?: GPUSamplerBindingType; } -/** - * @category GPU - * @experimental - */ -declare type GPUSamplerBindingType = +/** @category GPU */ +type GPUSamplerBindingType = | "filtering" | "non-filtering" | "comparison"; -/** - * @category GPU - * @experimental - */ -declare interface GPUTextureBindingLayout { +/** @category GPU */ +interface GPUTextureBindingLayout { sampleType?: GPUTextureSampleType; viewDimension?: GPUTextureViewDimension; multisampled?: boolean; } -/** - * @category GPU - * @experimental - */ -declare type GPUTextureSampleType = +/** @category GPU */ +type GPUTextureSampleType = | "float" | "unfilterable-float" | "depth" | "sint" | "uint"; -/** - * @category GPU - * @experimental - */ -declare type GPUStorageTextureAccess = +/** @category GPU */ +type GPUStorageTextureAccess = | "write-only" | "read-only" | "read-write"; -/** - * @category GPU - * @experimental - */ -declare interface GPUStorageTextureBindingLayout { +/** @category GPU */ +interface GPUStorageTextureBindingLayout { access: GPUStorageTextureAccess; format: GPUTextureFormat; viewDimension?: GPUTextureViewDimension; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUBindGroup implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBindGroupDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUBindGroupDescriptor extends GPUObjectDescriptorBase { layout: GPUBindGroupLayout; entries: GPUBindGroupEntry[]; } -/** - * @category GPU - * @experimental - */ -declare type GPUBindingResource = +/** @category GPU */ +type GPUBindingResource = | GPUSampler | GPUTextureView | GPUBufferBinding; -/** - * @category GPU - * @experimental - */ -declare interface GPUBindGroupEntry { +/** @category GPU */ +interface GPUBindGroupEntry { binding: number; resource: GPUBindingResource; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBufferBinding { +/** @category GPU */ +interface GPUBufferBinding { buffer: GPUBuffer; offset?: number; size?: number; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUPipelineLayout implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase { bindGroupLayouts: GPUBindGroupLayout[]; } -/** - * @category GPU - * @experimental - */ -declare type GPUCompilationMessageType = "error" | "warning" | "info"; +/** @category GPU */ +type GPUCompilationMessageType = "error" | "warning" | "info"; -/** - * @category GPU - * @experimental - */ -declare interface GPUCompilationMessage { +/** @category GPU */ +interface GPUCompilationMessage { readonly message: string; readonly type: GPUCompilationMessageType; readonly lineNum: number; readonly linePos: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUCompilationInfo { +/** @category GPU */ +interface GPUCompilationInfo { readonly messages: ReadonlyArray; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUPipelineError extends DOMException { constructor(message?: string, options?: GPUPipelineErrorInit); readonly reason: GPUPipelineErrorReason; } -/** - * @category GPU - * @experimental - */ -declare interface GPUPipelineErrorInit { +/** @category GPU */ +interface GPUPipelineErrorInit { reason: GPUPipelineErrorReason; } -/** - * @category GPU - * @experimental - */ -declare type GPUPipelineErrorReason = "validation" | "internal"; +/** @category GPU */ +type GPUPipelineErrorReason = "validation" | "internal"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUShaderModule implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUShaderModuleDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUShaderModuleDescriptor extends GPUObjectDescriptorBase { code: string; sourceMap?: any; } -/** - * @category GPU - * @experimental - */ -declare type GPUAutoLayoutMode = "auto"; +/** @category GPU */ +type GPUAutoLayoutMode = "auto"; -/** - * @category GPU - * @experimental - */ -declare interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase { layout: GPUPipelineLayout | GPUAutoLayoutMode; } -/** - * @category GPU - * @experimental - */ -declare interface GPUPipelineBase { +/** @category GPU */ +interface GPUPipelineBase { getBindGroupLayout(index: number): GPUBindGroupLayout; } -/** - * @category GPU - * @experimental - */ -declare interface GPUProgrammableStage { +/** @category GPU */ +interface GPUProgrammableStage { module: GPUShaderModule; entryPoint?: string; constants?: Record; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUComputePipeline implements GPUObjectBase, GPUPipelineBase { label: string; getBindGroupLayout(index: number): GPUBindGroupLayout; } -/** - * @category GPU - * @experimental - */ -declare interface GPUComputePipelineDescriptor - extends GPUPipelineDescriptorBase { +/** @category GPU */ +interface GPUComputePipelineDescriptor extends GPUPipelineDescriptorBase { compute: GPUProgrammableStage; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPURenderPipeline implements GPUObjectBase, GPUPipelineBase { label: string; getBindGroupLayout(index: number): GPUBindGroupLayout; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPipelineDescriptor - extends GPUPipelineDescriptorBase { +/** @category GPU */ +interface GPURenderPipelineDescriptor extends GPUPipelineDescriptorBase { vertex: GPUVertexState; primitive?: GPUPrimitiveState; depthStencil?: GPUDepthStencilState; @@ -880,11 +662,8 @@ declare interface GPURenderPipelineDescriptor fragment?: GPUFragmentState; } -/** - * @category GPU - * @experimental - */ -declare interface GPUPrimitiveState { +/** @category GPU */ +interface GPUPrimitiveState { topology?: GPUPrimitiveTopology; stripIndexFormat?: GPUIndexFormat; frontFace?: GPUFrontFace; @@ -892,77 +671,50 @@ declare interface GPUPrimitiveState { unclippedDepth?: boolean; } -/** - * @category GPU - * @experimental - */ -declare type GPUPrimitiveTopology = +/** @category GPU */ +type GPUPrimitiveTopology = | "point-list" | "line-list" | "line-strip" | "triangle-list" | "triangle-strip"; -/** - * @category GPU - * @experimental - */ -declare type GPUFrontFace = "ccw" | "cw"; +/** @category GPU */ +type GPUFrontFace = "ccw" | "cw"; -/** - * @category GPU - * @experimental - */ -declare type GPUCullMode = "none" | "front" | "back"; +/** @category GPU */ +type GPUCullMode = "none" | "front" | "back"; -/** - * @category GPU - * @experimental - */ -declare interface GPUMultisampleState { +/** @category GPU */ +interface GPUMultisampleState { count?: number; mask?: number; alphaToCoverageEnabled?: boolean; } -/** - * @category GPU - * @experimental - */ -declare interface GPUFragmentState extends GPUProgrammableStage { +/** @category GPU */ +interface GPUFragmentState extends GPUProgrammableStage { targets: (GPUColorTargetState | null)[]; } -/** - * @category GPU - * @experimental - */ -declare interface GPUColorTargetState { +/** @category GPU */ +interface GPUColorTargetState { format: GPUTextureFormat; blend?: GPUBlendState; writeMask?: GPUColorWriteFlags; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBlendState { +/** @category GPU */ +interface GPUBlendState { color: GPUBlendComponent; alpha: GPUBlendComponent; } -/** - * @category GPU - * @experimental - */ -declare type GPUColorWriteFlags = number; +/** @category GPU */ +type GPUColorWriteFlags = number; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUColorWrite { static RED: 0x1; static GREEN: 0x2; @@ -971,21 +723,15 @@ declare class GPUColorWrite { static ALL: 0xF; } -/** - * @category GPU - * @experimental - */ -declare interface GPUBlendComponent { +/** @category GPU */ +interface GPUBlendComponent { operation?: GPUBlendOperation; srcFactor?: GPUBlendFactor; dstFactor?: GPUBlendFactor; } -/** - * @category GPU - * @experimental - */ -declare type GPUBlendFactor = +/** @category GPU */ +type GPUBlendFactor = | "zero" | "one" | "src" @@ -1000,22 +746,16 @@ declare type GPUBlendFactor = | "constant" | "one-minus-constant"; -/** - * @category GPU - * @experimental - */ -declare type GPUBlendOperation = +/** @category GPU */ +type GPUBlendOperation = | "add" | "subtract" | "reverse-subtract" | "min" | "max"; -/** - * @category GPU - * @experimental - */ -declare interface GPUDepthStencilState { +/** @category GPU */ +interface GPUDepthStencilState { format: GPUTextureFormat; depthWriteEnabled: boolean; @@ -1032,22 +772,16 @@ declare interface GPUDepthStencilState { depthBiasClamp?: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUStencilFaceState { +/** @category GPU */ +interface GPUStencilFaceState { compare?: GPUCompareFunction; failOp?: GPUStencilOperation; depthFailOp?: GPUStencilOperation; passOp?: GPUStencilOperation; } -/** - * @category GPU - * @experimental - */ -declare type GPUStencilOperation = +/** @category GPU */ +type GPUStencilOperation = | "keep" | "zero" | "replace" @@ -1057,17 +791,11 @@ declare type GPUStencilOperation = | "increment-wrap" | "decrement-wrap"; -/** - * @category GPU - * @experimental - */ -declare type GPUIndexFormat = "uint16" | "uint32"; +/** @category GPU */ +type GPUIndexFormat = "uint16" | "uint32"; -/** - * @category GPU - * @experimental - */ -declare type GPUVertexFormat = +/** @category GPU */ +type GPUVertexFormat = | "uint8x2" | "uint8x4" | "sint8x2" @@ -1100,69 +828,45 @@ declare type GPUVertexFormat = | "sint32x4" | "unorm10-10-10-2"; -/** - * @category GPU - * @experimental - */ -declare type GPUVertexStepMode = "vertex" | "instance"; +/** @category GPU */ +type GPUVertexStepMode = "vertex" | "instance"; -/** - * @category GPU - * @experimental - */ -declare interface GPUVertexState extends GPUProgrammableStage { +/** @category GPU */ +interface GPUVertexState extends GPUProgrammableStage { buffers?: (GPUVertexBufferLayout | null)[]; } -/** - * @category GPU - * @experimental - */ -declare interface GPUVertexBufferLayout { +/** @category GPU */ +interface GPUVertexBufferLayout { arrayStride: number; stepMode?: GPUVertexStepMode; attributes: GPUVertexAttribute[]; } -/** - * @category GPU - * @experimental - */ -declare interface GPUVertexAttribute { +/** @category GPU */ +interface GPUVertexAttribute { format: GPUVertexFormat; offset: number; shaderLocation: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUImageDataLayout { +/** @category GPU */ +interface GPUImageDataLayout { offset?: number; bytesPerRow?: number; rowsPerImage?: number; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUCommandBuffer implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {} +/** @category GPU */ +interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {} -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUCommandEncoder implements GPUObjectBase { label: string; @@ -1220,36 +924,24 @@ declare class GPUCommandEncoder implements GPUObjectBase { finish(descriptor?: GPUCommandBufferDescriptor): GPUCommandBuffer; } -/** - * @category GPU - * @experimental - */ -declare interface GPUCommandEncoderDescriptor extends GPUObjectDescriptorBase {} +/** @category GPU */ +interface GPUCommandEncoderDescriptor extends GPUObjectDescriptorBase {} -/** - * @category GPU - * @experimental - */ -declare interface GPUImageCopyBuffer extends GPUImageDataLayout { +/** @category GPU */ +interface GPUImageCopyBuffer extends GPUImageDataLayout { buffer: GPUBuffer; } -/** - * @category GPU - * @experimental - */ -declare interface GPUImageCopyTexture { +/** @category GPU */ +interface GPUImageCopyTexture { texture: GPUTexture; mipLevel?: number; origin?: GPUOrigin3D; aspect?: GPUTextureAspect; } -/** - * @category GPU - * @experimental - */ -declare interface GPUProgrammablePassEncoder { +/** @category GPU */ +interface GPUProgrammablePassEncoder { setBindGroup( index: number, bindGroup: GPUBindGroup, @@ -1269,10 +961,7 @@ declare interface GPUProgrammablePassEncoder { insertDebugMarker(markerLabel: string): undefined; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUComputePassEncoder implements GPUObjectBase, GPUProgrammablePassEncoder { label: string; @@ -1301,29 +990,20 @@ declare class GPUComputePassEncoder end(): undefined; } -/** - * @category GPU - * @experimental - */ -declare interface GPUComputePassTimestampWrites { +/** @category GPU */ +interface GPUComputePassTimestampWrites { querySet: GPUQuerySet; beginningOfPassWriteIndex?: number; endOfPassWriteIndex?: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUComputePassDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUComputePassDescriptor extends GPUObjectDescriptorBase { timestampWrites?: GPUComputePassTimestampWrites; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderEncoderBase { +/** @category GPU */ +interface GPURenderEncoderBase { setPipeline(pipeline: GPURenderPipeline): undefined; setIndexBuffer( @@ -1360,10 +1040,7 @@ declare interface GPURenderEncoderBase { ): undefined; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPURenderPassEncoder implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { label: string; @@ -1440,32 +1117,23 @@ declare class GPURenderPassEncoder end(): undefined; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPassTimestampWrites { +/** @category GPU */ +interface GPURenderPassTimestampWrites { querySet: GPUQuerySet; beginningOfPassWriteIndex?: number; endOfPassWriteIndex?: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPassDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPURenderPassDescriptor extends GPUObjectDescriptorBase { colorAttachments: (GPURenderPassColorAttachment | null)[]; depthStencilAttachment?: GPURenderPassDepthStencilAttachment; occlusionQuerySet?: GPUQuerySet; timestampWrites?: GPURenderPassTimestampWrites; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPassColorAttachment { +/** @category GPU */ +interface GPURenderPassColorAttachment { view: GPUTextureView; resolveTarget?: GPUTextureView; @@ -1474,11 +1142,8 @@ declare interface GPURenderPassColorAttachment { storeOp: GPUStoreOp; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPassDepthStencilAttachment { +/** @category GPU */ +interface GPURenderPassDepthStencilAttachment { view: GPUTextureView; depthClearValue?: number; @@ -1492,36 +1157,21 @@ declare interface GPURenderPassDepthStencilAttachment { stencilReadOnly?: boolean; } -/** - * @category GPU - * @experimental - */ -declare type GPULoadOp = "load" | "clear"; +/** @category GPU */ +type GPULoadOp = "load" | "clear"; -/** - * @category GPU - * @experimental - */ -declare type GPUStoreOp = "store" | "discard"; +/** @category GPU */ +type GPUStoreOp = "store" | "discard"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPURenderBundle implements GPUObjectBase { label: string; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderBundleDescriptor extends GPUObjectDescriptorBase {} +/** @category GPU */ +interface GPURenderBundleDescriptor extends GPUObjectDescriptorBase {} -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPURenderBundleEncoder implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { label: string; @@ -1575,29 +1225,20 @@ declare class GPURenderBundleEncoder finish(descriptor?: GPURenderBundleDescriptor): GPURenderBundle; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderPassLayout extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPURenderPassLayout extends GPUObjectDescriptorBase { colorFormats: (GPUTextureFormat | null)[]; depthStencilFormat?: GPUTextureFormat; sampleCount?: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPURenderBundleEncoderDescriptor extends GPURenderPassLayout { +/** @category GPU */ +interface GPURenderBundleEncoderDescriptor extends GPURenderPassLayout { depthReadOnly?: boolean; stencilReadOnly?: boolean; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUQueue implements GPUObjectBase { label: string; @@ -1621,10 +1262,7 @@ declare class GPUQueue implements GPUObjectBase { ): undefined; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUQuerySet implements GPUObjectBase { label: string; @@ -1634,78 +1272,48 @@ declare class GPUQuerySet implements GPUObjectBase { readonly count: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUQuerySetDescriptor extends GPUObjectDescriptorBase { +/** @category GPU */ +interface GPUQuerySetDescriptor extends GPUObjectDescriptorBase { type: GPUQueryType; count: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUQueryType = "occlusion" | "timestamp"; +/** @category GPU */ +type GPUQueryType = "occlusion" | "timestamp"; -/** - * @category GPU - * @experimental - */ -declare type GPUDeviceLostReason = "destroyed"; +/** @category GPU */ +type GPUDeviceLostReason = "destroyed"; -/** - * @category GPU - * @experimental - */ -declare interface GPUDeviceLostInfo { +/** @category GPU */ +interface GPUDeviceLostInfo { readonly reason: GPUDeviceLostReason; readonly message: string; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUError { readonly message: string; } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUOutOfMemoryError extends GPUError { constructor(message: string); } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUValidationError extends GPUError { constructor(message: string); } -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUInternalError extends GPUError { constructor(message: string); } -/** - * @category GPU - * @experimental - */ -declare type GPUErrorFilter = "out-of-memory" | "validation" | "internal"; +/** @category GPU */ +type GPUErrorFilter = "out-of-memory" | "validation" | "internal"; -/** - * @category GPU - * @experimental - */ +/** @category GPU */ declare class GPUUncapturedErrorEvent extends Event { constructor( type: string, @@ -1715,88 +1323,56 @@ declare class GPUUncapturedErrorEvent extends Event { readonly error: GPUError; } -/** - * @category GPU - * @experimental - */ -declare interface GPUUncapturedErrorEventInit extends EventInit { +/** @category GPU */ +interface GPUUncapturedErrorEventInit extends EventInit { error: GPUError; } -/** - * @category GPU - * @experimental - */ -declare interface GPUColorDict { +/** @category GPU */ +interface GPUColorDict { r: number; g: number; b: number; a: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUColor = number[] | GPUColorDict; +/** @category GPU */ +type GPUColor = number[] | GPUColorDict; -/** - * @category GPU - * @experimental - */ -declare interface GPUOrigin3DDict { +/** @category GPU */ +interface GPUOrigin3DDict { x?: number; y?: number; z?: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUOrigin3D = number[] | GPUOrigin3DDict; +/** @category GPU */ +type GPUOrigin3D = number[] | GPUOrigin3DDict; -/** - * @category GPU - * @experimental - */ -declare interface GPUExtent3DDict { +/** @category GPU */ +interface GPUExtent3DDict { width: number; height?: number; depthOrArrayLayers?: number; } -/** - * @category GPU - * @experimental - */ -declare type GPUExtent3D = number[] | GPUExtent3DDict; +/** @category GPU */ +type GPUExtent3D = number[] | GPUExtent3DDict; -/** - * @category GPU - * @experimental - */ -declare type GPUCanvasAlphaMode = "opaque" | "premultiplied"; +/** @category GPU */ +type GPUCanvasAlphaMode = "opaque" | "premultiplied"; -/** - * @category GPU - * @experimental - */ -declare interface GPUCanvasConfiguration { +/** @category GPU */ +interface GPUCanvasConfiguration { device: GPUDevice; format: GPUTextureFormat; usage?: GPUTextureUsageFlags; viewFormats?: GPUTextureFormat[]; colorSpace?: "srgb" | "display-p3"; alphaMode?: GPUCanvasAlphaMode; - width: number; - height: number; } -/** - * @category GPU - * @experimental - */ -declare interface GPUCanvasContext { +/** @category GPU */ +interface GPUCanvasContext { configure(configuration: GPUCanvasConfiguration): undefined; unconfigure(): undefined; getCurrentTexture(): GPUTexture; diff --git a/cli/tsc/dts/lib.dom.asynciterable.d.ts b/cli/tsc/dts/lib.dom.asynciterable.d.ts index 28e1bfd80e..98b96b8160 100644 --- a/cli/tsc/dts/lib.dom.asynciterable.d.ts +++ b/cli/tsc/dts/lib.dom.asynciterable.d.ts @@ -20,14 +20,22 @@ and limitations under the License. /// Window Async Iterable APIs ///////////////////////////// +interface FileSystemDirectoryHandleAsyncIterator extends AsyncIteratorObject { + [Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator; +} + interface FileSystemDirectoryHandle { - [Symbol.asyncIterator](): AsyncIterableIterator<[string, FileSystemHandle]>; - entries(): AsyncIterableIterator<[string, FileSystemHandle]>; - keys(): AsyncIterableIterator; - values(): AsyncIterableIterator; + [Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>; + entries(): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>; + keys(): FileSystemDirectoryHandleAsyncIterator; + values(): FileSystemDirectoryHandleAsyncIterator; +} + +interface ReadableStreamAsyncIterator extends AsyncIteratorObject { + [Symbol.asyncIterator](): ReadableStreamAsyncIterator; } interface ReadableStream { - [Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): AsyncIterableIterator; - values(options?: ReadableStreamIteratorOptions): AsyncIterableIterator; + [Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator; + values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator; } diff --git a/cli/tsc/dts/lib.dom.d.ts b/cli/tsc/dts/lib.dom.d.ts index 486f0e425b..0a2f9b9eda 100644 --- a/cli/tsc/dts/lib.dom.d.ts +++ b/cli/tsc/dts/lib.dom.d.ts @@ -597,6 +597,11 @@ interface GetAnimationsOptions { subtree?: boolean; } +interface GetHTMLOptions { + serializableShadowRoots?: boolean; + shadowRoots?: ShadowRoot[]; +} + interface GetNotificationOptions { tag?: string; } @@ -686,10 +691,6 @@ interface ImageEncodeOptions { type?: string; } -interface ImportMeta { - url: string; -} - interface InputEventInit extends UIEventInit { data?: string | null; dataTransfer?: DataTransfer | null; @@ -863,6 +864,10 @@ interface MediaKeySystemMediaCapability { robustness?: string; } +interface MediaKeysPolicy { + minHdcpVersion?: string; +} + interface MediaMetadataInit { album?: string; artist?: string; @@ -1202,6 +1207,10 @@ interface PointerEventInit extends MouseEventInit { width?: number; } +interface PointerLockOptions { + unadjustedMovement?: boolean; +} + interface PopStateEventInit extends EventInit { state?: any; } @@ -1385,11 +1394,6 @@ interface RTCIceCandidateInit { usernameFragment?: string | null; } -interface RTCIceCandidatePair { - local: RTCIceCandidate; - remote: RTCIceCandidate; -} - interface RTCIceCandidatePairStats extends RTCStats { availableIncomingBitrate?: number; availableOutgoingBitrate?: number; @@ -1521,7 +1525,7 @@ interface RTCRtcpParameters { } interface RTCRtpCapabilities { - codecs: RTCRtpCodecCapability[]; + codecs: RTCRtpCodec[]; headerExtensions: RTCRtpHeaderExtensionCapability[]; } @@ -1532,9 +1536,6 @@ interface RTCRtpCodec { sdpFmtpLine?: string; } -interface RTCRtpCodecCapability extends RTCRtpCodec { -} - interface RTCRtpCodecParameters extends RTCRtpCodec { payloadType: number; } @@ -1930,16 +1931,11 @@ interface TrackEventInit extends EventInit { track?: TextTrack | null; } -interface TransformerCancelCallback { - (reason: any): void | PromiseLike; -} - interface Transformer { flush?: TransformerFlushCallback; readableType?: undefined; start?: TransformerStartCallback; transform?: TransformerTransformCallback; - cancel?: TransformerCancelCallback; writableType?: undefined; } @@ -2234,7 +2230,9 @@ interface ARIAMixin { ariaAtomic: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/ariaAutoComplete) */ ariaAutoComplete: string | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/ariaBrailleLabel) */ ariaBrailleLabel: string | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/ariaBrailleRoleDescription) */ ariaBrailleRoleDescription: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/ariaBusy) */ ariaBusy: string | null; @@ -2817,7 +2815,6 @@ declare var AudioNode: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/AudioParam) */ interface AudioParam { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AudioParam/automationRate) */ automationRate: AutomationRate; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AudioParam/defaultValue) */ readonly defaultValue: number; @@ -3105,7 +3102,11 @@ declare var BaseAudioContext: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/BeforeUnloadEvent) */ interface BeforeUnloadEvent extends Event { - /** @deprecated */ + /** + * @deprecated + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/BeforeUnloadEvent/returnValue) + */ returnValue: any; } @@ -3417,7 +3418,7 @@ interface CSSImportRule extends CSSRule { readonly layerName: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSImportRule/media) */ readonly media: MediaList; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSImportRule/styleSheet) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSImportRule/stylesheet) */ readonly styleSheet: CSSStyleSheet | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSImportRule/supportsText) */ readonly supportsText: string | null; @@ -3710,7 +3711,7 @@ declare var CSSPerspective: { interface CSSPropertyRule extends CSSRule { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSPropertyRule/inherits) */ readonly inherits: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSPropertyRule/initialValue) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSPropertyRule/initialvalue) */ readonly initialValue: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSPropertyRule/name) */ readonly name: string; @@ -3823,8 +3824,11 @@ declare var CSSScale: { new(x: CSSNumberish, y: CSSNumberish, z?: CSSNumberish): CSSScale; }; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSScopeRule) */ interface CSSScopeRule extends CSSGroupingRule { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSScopeRule/end) */ readonly end: string | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CSSScopeRule/start) */ readonly start: string | null; } @@ -3947,7 +3951,6 @@ interface CSSStyleDeclaration { /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/background-size) */ backgroundSize: string; baselineShift: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/baseline-source) */ baselineSource: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/block-size) */ blockSize: string; @@ -4129,11 +4132,9 @@ interface CSSStyleDeclaration { columns: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/contain) */ contain: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-contain-intrinsic-block-size) */ containIntrinsicBlockSize: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-height) */ containIntrinsicHeight: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-contain-intrinsic-inline-size) */ containIntrinsicInlineSize: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-size) */ containIntrinsicSize: string; @@ -4650,7 +4651,9 @@ interface CSSStyleDeclaration { textUnderlinePosition: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/text-wrap) */ textWrap: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/text-wrap-mode) */ textWrapMode: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/text-wrap-style) */ textWrapStyle: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/top) */ top: string; @@ -4685,6 +4688,8 @@ interface CSSStyleDeclaration { vectorEffect: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/vertical-align) */ verticalAlign: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/view-transition-name) */ + viewTransitionName: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/visibility) */ visibility: string; /** @@ -4915,7 +4920,11 @@ interface CSSStyleDeclaration { * [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/justify-content) */ webkitJustifyContent: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/-webkit-line-clamp) */ + /** + * @deprecated This is a legacy alias of `lineClamp`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/CSS/-webkit-line-clamp) + */ webkitLineClamp: string; /** * @deprecated This is a legacy alias of `mask`. @@ -5577,6 +5586,8 @@ interface CanvasShadowStyles { } interface CanvasState { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/isContextLost) */ + isContextLost(): boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/reset) */ reset(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/restore) */ @@ -5774,6 +5785,8 @@ declare var ClipboardEvent: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/ClipboardItem) */ interface ClipboardItem { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ClipboardItem/presentationStyle) */ + readonly presentationStyle: PresentationStyle; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ClipboardItem/types) */ readonly types: ReadonlyArray; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ClipboardItem/getType) */ @@ -5783,6 +5796,8 @@ interface ClipboardItem { declare var ClipboardItem: { prototype: ClipboardItem; new(items: Record>, options?: ClipboardItemOptions): ClipboardItem; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ClipboardItem/supports_static) */ + supports(type: string): boolean; }; /** @@ -5852,8 +5867,6 @@ declare var CompositionEvent: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream) */ interface CompressionStream extends GenericTransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; } declare var CompressionStream: { @@ -6186,9 +6199,7 @@ interface DOMMatrix extends DOMMatrixReadOnly { rotateAxisAngleSelf(x?: number, y?: number, z?: number, angle?: number): DOMMatrix; rotateFromVectorSelf(x?: number, y?: number): DOMMatrix; rotateSelf(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scale3dSelf) */ scale3dSelf(scale?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scaleSelf) */ scaleSelf(scaleX?: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; setMatrixValue(transformList: string): DOMMatrix; skewXSelf(sx?: number): DOMMatrix; @@ -6212,88 +6223,48 @@ declare var WebKitCSSMatrix: typeof DOMMatrix; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly) */ interface DOMMatrixReadOnly { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/a) */ readonly a: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/b) */ readonly b: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/c) */ readonly c: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/d) */ readonly d: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/e) */ readonly e: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/f) */ readonly f: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/is2D) */ readonly is2D: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/isIdentity) */ readonly isIdentity: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m11) */ readonly m11: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m12) */ readonly m12: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m13) */ readonly m13: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m14) */ readonly m14: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m21) */ readonly m21: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m22) */ readonly m22: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m23) */ readonly m23: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m24) */ readonly m24: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m31) */ readonly m31: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m32) */ readonly m32: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m33) */ readonly m33: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m34) */ readonly m34: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m41) */ readonly m41: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m42) */ readonly m42: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m43) */ readonly m43: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m44) */ readonly m44: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipX) */ flipX(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipY) */ flipY(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/inverse) */ inverse(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/multiply) */ multiply(other?: DOMMatrixInit): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotate) */ rotate(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateAxisAngle) */ rotateAxisAngle(x?: number, y?: number, z?: number, angle?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateFromVector) */ rotateFromVector(x?: number, y?: number): DOMMatrix; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale) */ scale(scaleX?: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale3d) */ scale3d(scale?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scaleNonUniform) - */ + /** @deprecated */ scaleNonUniform(scaleX?: number, scaleY?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewX) */ skewX(sx?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewY) */ skewY(sy?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat32Array) */ toFloat32Array(): Float32Array; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat64Array) */ toFloat64Array(): Float64Array; toJSON(): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/transformPoint) */ transformPoint(point?: DOMPointInit): DOMPoint; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/translate) */ translate(tx?: number, ty?: number, tz?: number): DOMMatrix; @@ -6365,7 +6336,6 @@ interface DOMPointReadOnly { readonly y: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/z) */ readonly z: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/matrixTransform) */ matrixTransform(matrix?: DOMMatrixInit): DOMPoint; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/toJSON) */ toJSON(): any; @@ -6380,15 +6350,10 @@ declare var DOMPointReadOnly: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad) */ interface DOMQuad { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p1) */ readonly p1: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p2) */ readonly p2: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p3) */ readonly p3: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p4) */ readonly p4: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/getBounds) */ getBounds(): DOMRect; toJSON(): any; } @@ -6411,6 +6376,7 @@ interface DOMRect extends DOMRectReadOnly { declare var DOMRect: { prototype: DOMRect; new(x?: number, y?: number, width?: number, height?: number): DOMRect; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/fromRect_static) */ fromRect(other?: DOMRectInit): DOMRect; }; @@ -6751,8 +6717,6 @@ declare var DataTransferItemList: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DecompressionStream) */ interface DecompressionStream extends GenericTransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; } declare var DecompressionStream: { @@ -7157,11 +7121,7 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEve * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/adoptNode) */ adoptNode(node: T): T; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/captureEvents) - */ + /** @deprecated */ captureEvents(): void; /** @deprecated */ caretRangeFromPoint(x: number, y: number): Range | null; @@ -7295,6 +7255,7 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEve createEvent(eventInterface: "SpeechSynthesisEvent"): SpeechSynthesisEvent; createEvent(eventInterface: "StorageEvent"): StorageEvent; createEvent(eventInterface: "SubmitEvent"): SubmitEvent; + createEvent(eventInterface: "TextEvent"): TextEvent; createEvent(eventInterface: "ToggleEvent"): ToggleEvent; createEvent(eventInterface: "TouchEvent"): TouchEvent; createEvent(eventInterface: "TrackEvent"): TrackEvent; @@ -7451,8 +7412,6 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEve * Returns a Boolean value that indicates whether the specified command is in the indeterminate state. * @param commandId String that specifies a command identifier. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/queryCommandIndeterm) */ queryCommandIndeterm(commandId: string): boolean; /** @@ -7475,18 +7434,14 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEve * Returns the current value of the document, range, or current selection for the given command. * @param commandId String that specifies a command identifier. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/queryCommandValue) */ queryCommandValue(commandId: string): string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/releaseEvents) - */ + /** @deprecated */ releaseEvents(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/requestStorageAccess) */ requestStorageAccess(): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/startViewTransition) */ + startViewTransition(callbackOptions?: UpdateCallback): ViewTransition; /** * Writes one or more HTML expressions to a document in the specified window. * @param content Specifies the text and HTML tags to write. @@ -7510,6 +7465,7 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEve declare var Document: { prototype: Document; new(): Document; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/parseHTMLUnsafe_static) */ parseHTMLUnsafe(html: string): Document; }; @@ -7731,7 +7687,7 @@ interface ElementEventMap { * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element) */ -interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable { +interface Element extends Node, ARIAMixin, Animatable, ChildNode, NonDocumentTypeChildNode, ParentNode, Slottable { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/attributes) */ readonly attributes: NamedNodeMap; /** @@ -7760,6 +7716,8 @@ interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, Non * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id) */ id: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) */ + innerHTML: string; /** * Returns the local name. * @@ -7876,6 +7834,8 @@ interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, Non getElementsByTagNameNS(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf; getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1998/Math/MathML", localName: string): HTMLCollectionOf; getElementsByTagNameNS(namespace: string | null, localName: string): HTMLCollectionOf; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/getHTML) */ + getHTML(options?: GetHTMLOptions): string; /** * Returns true if element has an attribute whose qualified name is qualifiedName, and false otherwise. * @@ -7899,7 +7859,7 @@ interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, Non /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/insertAdjacentElement) */ insertAdjacentElement(where: InsertPosition, element: Element): Element | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/insertAdjacentHTML) */ - insertAdjacentHTML(position: InsertPosition, text: string): void; + insertAdjacentHTML(position: InsertPosition, string: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/insertAdjacentText) */ insertAdjacentText(where: InsertPosition, data: string): void; /** @@ -7933,7 +7893,7 @@ interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, Non */ requestFullscreen(options?: FullscreenOptions): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/requestPointerLock) */ - requestPointerLock(): void; + requestPointerLock(options?: PointerLockOptions): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/scroll) */ scroll(options?: ScrollToOptions): void; scroll(x: number, y: number): void; @@ -7961,6 +7921,7 @@ interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, Non setAttributeNode(attr: Attr): Attr | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttributeNodeNS) */ setAttributeNodeNS(attr: Attr): Attr | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setHTMLUnsafe) */ setHTMLUnsafe(html: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setPointerCapture) */ setPointerCapture(pointerId: number): void; @@ -7990,6 +7951,7 @@ declare var Element: { }; interface ElementCSSInlineStyle { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/attributeStyleMap) */ readonly attributeStyleMap: StylePropertyMap; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/style) */ readonly style: CSSStyleDeclaration; @@ -8104,15 +8066,10 @@ declare var EncodedVideoChunk: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent) */ interface ErrorEvent extends Event { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/colno) */ readonly colno: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/error) */ readonly error: any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/filename) */ readonly filename: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/lineno) */ readonly lineno: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/message) */ readonly message: string; } @@ -8368,23 +8325,11 @@ declare var EventTarget: { new(): EventTarget; }; -/** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/External) - */ +/** @deprecated */ interface External { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/External/AddSearchProvider) - */ + /** @deprecated */ AddSearchProvider(): void; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/External/IsSearchProviderInstalled) - */ + /** @deprecated */ IsSearchProviderInstalled(): void; } @@ -8824,6 +8769,7 @@ interface Gamepad { readonly mapping: GamepadMappingType; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Gamepad/timestamp) */ readonly timestamp: DOMHighResTimeStamp; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Gamepad/vibrationActuator) */ readonly vibrationActuator: GamepadHapticActuator; } @@ -8852,7 +8798,7 @@ declare var GamepadButton: { }; /** - * This Gamepad API interface contains references to gamepads connected to the system, which is what the gamepad events Window.gamepadconnected and Window.gamepaddisconnected are fired in response to. + * This Gamepad API interface contains references to gamepads connected to the system, which is what the gamepad events globalThis.gamepadconnected and globalThis.gamepaddisconnected are fired in response to. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/GamepadEvent) */ @@ -8872,6 +8818,7 @@ declare var GamepadEvent: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/GamepadHapticActuator) */ interface GamepadHapticActuator { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/GamepadHapticActuator/playEffect) */ playEffect(type: GamepadHapticEffectType, params?: GamepadEffectParameters): Promise; reset(): Promise; } @@ -8882,7 +8829,9 @@ declare var GamepadHapticActuator: { }; interface GenericTransformStream { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream/readable) */ readonly readable: ReadableStream; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream/writable) */ readonly writable: WritableStream; } @@ -8925,6 +8874,8 @@ interface GeolocationCoordinates { readonly longitude: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/GeolocationCoordinates/speed) */ readonly speed: number | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/GeolocationCoordinates/toJSON) */ + toJSON(): any; } declare var GeolocationCoordinates: { @@ -8942,6 +8893,8 @@ interface GeolocationPosition { readonly coords: GeolocationCoordinates; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/GeolocationPosition/timestamp) */ readonly timestamp: EpochTimeStamp; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/GeolocationPosition/toJSON) */ + toJSON(): any; } declare var GeolocationPosition: { @@ -8987,7 +8940,9 @@ interface GlobalEventHandlersEventMap { "compositionend": CompositionEvent; "compositionstart": CompositionEvent; "compositionupdate": CompositionEvent; + "contextlost": Event; "contextmenu": MouseEvent; + "contextrestored": Event; "copy": ClipboardEvent; "cuechange": Event; "cut": ClipboardEvent; @@ -9101,7 +9056,7 @@ interface GlobalEventHandlers { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/blur_event) */ onblur: ((this: GlobalEventHandlers, ev: FocusEvent) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDialogElement/cancel_event) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/cancel_event) */ oncancel: ((this: GlobalEventHandlers, ev: Event) => any) | null; /** * Occurs when playback is possible, but would require further buffering. @@ -9128,6 +9083,8 @@ interface GlobalEventHandlers { onclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDialogElement/close_event) */ onclose: ((this: GlobalEventHandlers, ev: Event) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/webglcontextlost_event) */ + oncontextlost: ((this: GlobalEventHandlers, ev: Event) => any) | null; /** * Fires when the user clicks the right mouse button in the client area, opening the context menu. * @param ev The mouse event. @@ -9135,6 +9092,8 @@ interface GlobalEventHandlers { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event) */ oncontextmenu: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/contextrestored_event) */ + oncontextrestored: ((this: GlobalEventHandlers, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/copy_event) */ oncopy: ((this: GlobalEventHandlers, ev: ClipboardEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/cuechange_event) */ @@ -9285,7 +9244,7 @@ interface GlobalEventHandlers { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/loadstart_event) */ onloadstart: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/lostpointercapture_event) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/lostpointercapture_event) */ onlostpointercapture: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; /** * Fires when the user clicks the object with either mouse button. @@ -9554,15 +9513,11 @@ interface HTMLAnchorElement extends HTMLElement, HTMLHyperlinkElementUtils { /** * Sets or retrieves the character set used to encode the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/charset) */ charset: string; /** * Sets or retrieves the coordinates of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/coords) */ coords: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/download) */ @@ -9576,8 +9531,6 @@ interface HTMLAnchorElement extends HTMLElement, HTMLHyperlinkElementUtils { /** * Sets or retrieves the shape of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/name) */ name: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/ping) */ @@ -9595,15 +9548,11 @@ interface HTMLAnchorElement extends HTMLElement, HTMLHyperlinkElementUtils { /** * Sets or retrieves the relationship between the object and the destination of the link. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/rev) */ rev: string; /** * Sets or retrieves the shape of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/shape) */ shape: string; /** @@ -9637,25 +9586,14 @@ declare var HTMLAnchorElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement) */ interface HTMLAreaElement extends HTMLElement, HTMLHyperlinkElementUtils { - /** - * Sets or retrieves a text alternative to the graphic. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/alt) - */ + /** Sets or retrieves a text alternative to the graphic. */ alt: string; - /** - * Sets or retrieves the coordinates of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/coords) - */ + /** Sets or retrieves the coordinates of the object. */ coords: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/download) */ download: string; /** * Sets or gets whether clicks in this region cause action. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/noHref) */ noHref: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/ping) */ @@ -9666,11 +9604,7 @@ interface HTMLAreaElement extends HTMLElement, HTMLHyperlinkElementUtils { rel: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/relList) */ readonly relList: DOMTokenList; - /** - * Sets or retrieves the shape of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLAreaElement/shape) - */ + /** Sets or retrieves the shape of the object. */ shape: string; /** * Sets or retrieves the window or frame at which to target content. @@ -9715,8 +9649,6 @@ interface HTMLBRElement extends HTMLElement { /** * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBRElement/clear) */ clear: string; addEventListener(type: K, listener: (this: HTMLBRElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -9736,11 +9668,7 @@ declare var HTMLBRElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBaseElement) */ interface HTMLBaseElement extends HTMLElement { - /** - * Gets or sets the baseline URL on which relative links are based. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBaseElement/href) - */ + /** Gets or sets the baseline URL on which relative links are based. */ href: string; /** * Sets or retrieves the window or frame at which to target content. @@ -9768,41 +9696,17 @@ interface HTMLBodyElementEventMap extends HTMLElementEventMap, WindowEventHandle * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement) */ interface HTMLBodyElement extends HTMLElement, WindowEventHandlers { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/aLink) - */ + /** @deprecated */ aLink: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/background) - */ + /** @deprecated */ background: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/bgColor) - */ + /** @deprecated */ bgColor: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/link) - */ + /** @deprecated */ link: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/text) - */ + /** @deprecated */ text: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLBodyElement/vLink) - */ + /** @deprecated */ vLink: string; addEventListener(type: K, listener: (this: HTMLBodyElement, ev: HTMLBodyElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -9823,49 +9727,21 @@ declare var HTMLBodyElement: { interface HTMLButtonElement extends HTMLElement, PopoverInvokerElement { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/disabled) */ disabled: boolean; - /** - * Retrieves a reference to the form that the object is embedded in. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/form) - */ + /** Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement | null; - /** - * Overrides the action attribute (where the data on a form is sent) on the parent form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/formAction) - */ + /** Overrides the action attribute (where the data on a form is sent) on the parent form element. */ formAction: string; - /** - * Used to override the encoding (formEnctype attribute) specified on the form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/formEnctype) - */ + /** Used to override the encoding (formEnctype attribute) specified on the form element. */ formEnctype: string; - /** - * Overrides the submit method attribute previously specified on a form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/formMethod) - */ + /** Overrides the submit method attribute previously specified on a form element. */ formMethod: string; - /** - * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/formNoValidate) - */ + /** Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option. */ formNoValidate: boolean; - /** - * Overrides the target attribute on a form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/formTarget) - */ + /** Overrides the target attribute on a form element. */ formTarget: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/labels) */ readonly labels: NodeListOf; - /** - * Sets or retrieves the name of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/name) - */ + /** Sets or retrieves the name of the object. */ name: string; /** * Gets the classification and default behavior of the button. @@ -9873,33 +9749,16 @@ interface HTMLButtonElement extends HTMLElement, PopoverInvokerElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/type) */ type: "submit" | "reset" | "button"; - /** - * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/validationMessage) - */ + /** Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. */ readonly validationMessage: string; - /** - * Returns a ValidityState object that represents the validity states of an element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/validity) - */ + /** Returns a ValidityState object that represents the validity states of an element. */ readonly validity: ValidityState; - /** - * Sets or retrieves the default or selected value of the control. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/value) - */ + /** Sets or retrieves the default or selected value of the control. */ value: string; - /** - * Returns whether an element will successfully validate based on forms validation rules and constraints. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/willValidate) - */ + /** Returns whether an element will successfully validate based on forms validation rules and constraints. */ readonly willValidate: boolean; /** Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLButtonElement/reportValidity) */ reportValidity(): boolean; /** * Sets a custom error message that is displayed when a form is submitted. @@ -10017,11 +9876,7 @@ interface HTMLCollectionOf extends HTMLCollectionBase { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDListElement) */ interface HTMLDListElement extends HTMLElement { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDListElement/compact) - */ + /** @deprecated */ compact: boolean; addEventListener(type: K, listener: (this: HTMLDListElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -10059,11 +9914,7 @@ declare var HTMLDataElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDataListElement) */ interface HTMLDataListElement extends HTMLElement { - /** - * Returns an HTMLCollection of the option elements of the datalist element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDataListElement/options) - */ + /** Returns an HTMLCollection of the option elements of the datalist element. */ readonly options: HTMLCollectionOf; addEventListener(type: K, listener: (this: HTMLDataListElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -10150,8 +10001,6 @@ interface HTMLDivElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDivElement/align) */ align: string; addEventListener(type: K, listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -10192,6 +10041,7 @@ interface HTMLElement extends Element, ElementCSSInlineStyle, ElementContentEdit accessKey: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/accessKeyLabel) */ readonly accessKeyLabel: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/autocapitalize) */ autocapitalize: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/dir) */ dir: string; @@ -10265,7 +10115,11 @@ interface HTMLEmbedElement extends HTMLElement { * @deprecated */ name: string; - /** Sets or retrieves a URL to be loaded by the object. */ + /** + * Sets or retrieves a URL to be loaded by the object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLEmbedElement/src) + */ src: string; type: string; /** @@ -10292,49 +10146,22 @@ declare var HTMLEmbedElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement) */ interface HTMLFieldSetElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/disabled) */ disabled: boolean; - /** - * Returns an HTMLCollection of the form controls in the element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/elements) - */ + /** Returns an HTMLCollection of the form controls in the element. */ readonly elements: HTMLCollection; - /** - * Retrieves a reference to the form that the object is embedded in. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/form) - */ + /** Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/name) */ name: string; - /** - * Returns the string "fieldset". - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/type) - */ + /** Returns the string "fieldset". */ readonly type: string; - /** - * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/validationMessage) - */ + /** Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. */ readonly validationMessage: string; - /** - * Returns a ValidityState object that represents the validity states of an element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/validity) - */ + /** Returns a ValidityState object that represents the validity states of an element. */ readonly validity: ValidityState; - /** - * Returns whether an element will successfully validate based on forms validation rules and constraints. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/willValidate) - */ + /** Returns whether an element will successfully validate based on forms validation rules and constraints. */ readonly willValidate: boolean; /** Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFieldSetElement/reportValidity) */ reportValidity(): boolean; /** * Sets a custom error message that is displayed when a form is submitted. @@ -10429,11 +10256,7 @@ interface HTMLFormElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/action) */ action: string; - /** - * Specifies whether autocomplete is applied to an editable text field. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/autocomplete) - */ + /** Specifies whether autocomplete is applied to an editable text field. */ autocomplete: AutoFillBase; /** * Retrieves a collection, in source order, of all controls in a given form. @@ -10471,11 +10294,7 @@ interface HTMLFormElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/name) */ name: string; - /** - * Designates a form that is not validated when submitted. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/noValidate) - */ + /** Designates a form that is not validated when submitted. */ noValidate: boolean; rel: string; readonly relList: DOMTokenList; @@ -10485,11 +10304,7 @@ interface HTMLFormElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/target) */ target: string; - /** - * Returns whether a form will validate when it is submitted, without having to submit it. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/checkValidity) - */ + /** Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/reportValidity) */ reportValidity(): boolean; @@ -10520,80 +10335,56 @@ declare var HTMLFormElement: { new(): HTMLFormElement; }; -/** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement) - */ +/** @deprecated */ interface HTMLFrameElement extends HTMLElement { /** * Retrieves the document object of the page or frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/contentDocument) */ readonly contentDocument: Document | null; /** * Retrieves the object of the specified. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/contentWindow) */ readonly contentWindow: WindowProxy | null; /** * Sets or retrieves whether to display a border for the frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/frameBorder) */ frameBorder: string; /** * Sets or retrieves a URI to a long description of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/longDesc) */ longDesc: string; /** * Sets or retrieves the top and bottom margin heights before displaying the text in a frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/marginHeight) */ marginHeight: string; /** * Sets or retrieves the left and right margin widths before displaying the text in a frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/marginWidth) */ marginWidth: string; /** * Sets or retrieves the frame name. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/name) */ name: string; /** * Sets or retrieves whether the user can resize the frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/noResize) */ noResize: boolean; /** * Sets or retrieves whether the frame can be scrolled. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/scrolling) */ scrolling: string; /** * Sets or retrieves a URL to be loaded by the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFrameElement/src) */ src: string; addEventListener(type: K, listener: (this: HTMLFrameElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -10702,8 +10493,6 @@ interface HTMLHeadingElement extends HTMLElement { /** * Sets or retrieves a value that indicates the table alignment. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLHeadingElement/align) */ align: string; addEventListener(type: K, listener: (this: HTMLHeadingElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -10840,10 +10629,9 @@ interface HTMLIFrameElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/align) */ align: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/allow) */ allow: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/allowFullscreen) */ allowFullscreen: boolean; @@ -10862,8 +10650,6 @@ interface HTMLIFrameElement extends HTMLElement { /** * Sets or retrieves whether to display a border for the frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/frameBorder) */ frameBorder: string; /** @@ -10877,22 +10663,16 @@ interface HTMLIFrameElement extends HTMLElement { /** * Sets or retrieves a URI to a long description of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/longDesc) */ longDesc: string; /** * Sets or retrieves the top and bottom margin heights before displaying the text in a frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/marginHeight) */ marginHeight: string; /** * Sets or retrieves the left and right margin widths before displaying the text in a frame. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/marginWidth) */ marginWidth: string; /** @@ -10903,12 +10683,11 @@ interface HTMLIFrameElement extends HTMLElement { name: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/referrerPolicy) */ referrerPolicy: ReferrerPolicy; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/sandbox) */ readonly sandbox: DOMTokenList; /** * Sets or retrieves whether the frame can be scrolled. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement/scrolling) */ scrolling: string; /** @@ -11013,11 +10792,7 @@ interface HTMLImageElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/longDesc) */ longDesc: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/lowsrc) - */ + /** @deprecated */ lowsrc: string; /** * Sets or retrieves the name of the object. @@ -11101,22 +10876,14 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { align: string; /** Sets or retrieves a text alternative to the graphic. */ alt: string; - /** - * Specifies whether autocomplete is applied to an editable text field. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/autocomplete) - */ + /** Specifies whether autocomplete is applied to an editable text field. */ autocomplete: AutoFill; capture: string; /** Sets or retrieves the state of the check box or radio button. */ checked: boolean; /** Sets or retrieves the state of the check box or radio button. */ defaultChecked: boolean; - /** - * Sets or retrieves the initial contents of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/defaultValue) - */ + /** Sets or retrieves the initial contents of the object. */ defaultValue: string; dirName: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/disabled) */ @@ -11129,71 +10896,30 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { files: FileList | null; /** Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement | null; - /** - * Overrides the action attribute (where the data on a form is sent) on the parent form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/formAction) - */ + /** Overrides the action attribute (where the data on a form is sent) on the parent form element. */ formAction: string; - /** - * Used to override the encoding (formEnctype attribute) specified on the form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/formEnctype) - */ + /** Used to override the encoding (formEnctype attribute) specified on the form element. */ formEnctype: string; - /** - * Overrides the submit method attribute previously specified on a form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/formMethod) - */ + /** Overrides the submit method attribute previously specified on a form element. */ formMethod: string; - /** - * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/formNoValidate) - */ + /** Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option. */ formNoValidate: boolean; - /** - * Overrides the target attribute on a form element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/formTarget) - */ + /** Overrides the target attribute on a form element. */ formTarget: string; - /** - * Sets or retrieves the height of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/height) - */ + /** Sets or retrieves the height of the object. */ height: number; /** When set, overrides the rendering of checkbox controls so that the current value is not visible. */ indeterminate: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/labels) */ readonly labels: NodeListOf | null; - /** - * Specifies the ID of a pre-defined datalist of options for an input element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/list) - */ + /** Specifies the ID of a pre-defined datalist of options for an input element. */ readonly list: HTMLDataListElement | null; - /** - * Defines the maximum acceptable value for an input element with type="number".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/max) - */ + /** Defines the maximum acceptable value for an input element with type="number".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field. */ max: string; - /** - * Sets or retrieves the maximum number of characters that the user can enter in a text control. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/maxLength) - */ + /** Sets or retrieves the maximum number of characters that the user can enter in a text control. */ maxLength: number; - /** - * Defines the minimum acceptable value for an input element with type="number". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/min) - */ + /** Defines the minimum acceptable value for an input element with type="number". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field. */ min: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/minLength) */ minLength: number; /** * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list. @@ -11203,24 +10929,12 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { multiple: boolean; /** Sets or retrieves the name of the object. */ name: string; - /** - * Gets or sets a string containing a regular expression that the user's input must match. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/pattern) - */ + /** Gets or sets a string containing a regular expression that the user's input must match. */ pattern: string; - /** - * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/placeholder) - */ + /** Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field. */ placeholder: string; readOnly: boolean; - /** - * When present, marks an element that can't be submitted without a value. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/required) - */ + /** When present, marks an element that can't be submitted without a value. */ required: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/selectionDirection) */ selectionDirection: "forward" | "backward" | "none" | null; @@ -11252,23 +10966,11 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { * @deprecated */ useMap: string; - /** - * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/validationMessage) - */ + /** Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. */ readonly validationMessage: string; - /** - * Returns a ValidityState object that represents the validity states of an element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/validity) - */ + /** Returns a ValidityState object that represents the validity states of an element. */ readonly validity: ValidityState; - /** - * Returns the value of the data at the cursor's current position. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/value) - */ + /** Returns the value of the data at the cursor's current position. */ value: string; /** Returns a Date object representing the form control's value, if applicable; otherwise, returns null. Can be set, to change the value. Throws an "InvalidStateError" DOMException if the control isn't date- or time-based. */ valueAsDate: Date | null; @@ -11278,17 +10980,9 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { readonly webkitEntries: ReadonlyArray; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/webkitdirectory) */ webkitdirectory: boolean; - /** - * Sets or retrieves the width of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/width) - */ + /** Sets or retrieves the width of the object. */ width: number; - /** - * Returns whether an element will successfully validate based on forms validation rules and constraints. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/willValidate) - */ + /** Returns whether an element will successfully validate based on forms validation rules and constraints. */ readonly willValidate: boolean; /** * Returns whether a form will validate when it is submitted, without having to submit it. @@ -11442,14 +11136,11 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle { charset: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/crossOrigin) */ crossOrigin: string | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/disabled) */ disabled: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/fetchPriority) */ fetchPriority: string; - /** - * Sets or retrieves a destination URL or an anchor point. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/href) - */ + /** Sets or retrieves a destination URL or an anchor point. */ href: string; /** * Sets or retrieves the language code of the object. @@ -11459,6 +11150,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle { hreflang: string; imageSizes: string; imageSrcset: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/integrity) */ integrity: string; /** Sets or retrieves the media type. */ media: string; @@ -11477,14 +11169,17 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle { * @deprecated */ rev: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/sizes) */ readonly sizes: DOMTokenList; /** * Sets or retrieves the window or frame at which to target content. * @deprecated */ target: string; - /** Sets or retrieves the MIME type of the object. */ + /** + * Sets or retrieves the MIME type of the object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLLinkElement/type) + */ type: string; addEventListener(type: K, listener: (this: HTMLLinkElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -11503,11 +11198,7 @@ declare var HTMLLinkElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMapElement) */ interface HTMLMapElement extends HTMLElement { - /** - * Retrieves a collection of the area objects defined for the given map object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMapElement/areas) - */ + /** Retrieves a collection of the area objects defined for the given map object. */ readonly areas: HTMLCollection; /** * Sets or retrieves the name of the object. @@ -11668,7 +11359,6 @@ interface HTMLMediaElement extends HTMLElement { readonly networkState: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/encrypted_event) */ onencrypted: ((this: HTMLMediaElement, ev: MediaEncryptedEvent) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/waitingforkey_event) */ onwaitingforkey: ((this: HTMLMediaElement, ev: Event) => any) | null; /** * Gets a flag that specifies whether playback is paused. @@ -11682,11 +11372,7 @@ interface HTMLMediaElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/playbackRate) */ playbackRate: number; - /** - * Gets TimeRanges for the current media resource that has been played. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/played) - */ + /** Gets TimeRanges for the current media resource that has been played. */ readonly played: TimeRanges; /** * Gets or sets a value indicating what data should be preloaded, if any. @@ -11706,11 +11392,7 @@ interface HTMLMediaElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/seekable) */ readonly seekable: TimeRanges; - /** - * Gets a flag that indicates whether the client is currently moving to a new playback position in the media resource. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/seeking) - */ + /** Gets a flag that indicates whether the client is currently moving to a new playback position in the media resource. */ readonly seeking: boolean; /** * Available only in secure contexts. @@ -11734,7 +11416,6 @@ interface HTMLMediaElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/volume) */ volume: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/addTextTrack) */ addTextTrack(kind: TextTrackKind, label?: string, language?: string): TextTrack; /** * Returns a string that specifies whether the client can play a given media resource type. @@ -11805,11 +11486,7 @@ declare var HTMLMediaElement: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMenuElement) */ interface HTMLMenuElement extends HTMLElement { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMenuElement/compact) - */ + /** @deprecated */ compact: boolean; addEventListener(type: K, listener: (this: HTMLMenuElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -11872,19 +11549,13 @@ declare var HTMLMetaElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement) */ interface HTMLMeterElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/high) */ high: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/labels) */ readonly labels: NodeListOf; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/low) */ low: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/max) */ max: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/min) */ min: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/optimum) */ optimum: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMeterElement/value) */ value: number; addEventListener(type: K, listener: (this: HTMLMeterElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -11903,17 +11574,9 @@ declare var HTMLMeterElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLModElement) */ interface HTMLModElement extends HTMLElement { - /** - * Sets or retrieves reference information about the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLModElement/cite) - */ + /** Sets or retrieves reference information about the object. */ cite: string; - /** - * Sets or retrieves the date and time of a modification to the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLModElement/dateTime) - */ + /** Sets or retrieves the date and time of a modification to the object. */ dateTime: string; addEventListener(type: K, listener: (this: HTMLModElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -11932,11 +11595,7 @@ declare var HTMLModElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOListElement) */ interface HTMLOListElement extends HTMLElement { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOListElement/compact) - */ + /** @deprecated */ compact: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOListElement/reversed) */ reversed: boolean; @@ -11965,44 +11624,28 @@ declare var HTMLOListElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement) */ interface HTMLObjectElement extends HTMLElement { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/align) - */ + /** @deprecated */ align: string; /** * Sets or retrieves a character string that can be used to implement your own archive functionality for the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/archive) */ archive: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/border) - */ + /** @deprecated */ border: string; /** * Sets or retrieves the URL of the file containing the compiled Java class. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/code) */ code: string; /** * Sets or retrieves the URL of the component. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/codeBase) */ codeBase: string; /** * Sets or retrieves the Internet media type for the code associated with the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/codeType) */ codeType: string; /** @@ -12019,11 +11662,7 @@ interface HTMLObjectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/data) */ data: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/declare) - */ + /** @deprecated */ declare: boolean; /** * Retrieves a reference to the form that the object is embedded in. @@ -12037,11 +11676,7 @@ interface HTMLObjectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/height) */ height: string; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/hspace) - */ + /** @deprecated */ hspace: number; /** * Sets or retrieves the name of the object. @@ -12052,8 +11687,6 @@ interface HTMLObjectElement extends HTMLElement { /** * Sets or retrieves a message to be displayed while an object is loading. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/standby) */ standby: string; /** @@ -12081,11 +11714,7 @@ interface HTMLObjectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/validity) */ readonly validity: ValidityState; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/vspace) - */ + /** @deprecated */ vspace: number; /** * Sets or retrieves the width of the object. @@ -12105,9 +11734,7 @@ interface HTMLObjectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/checkValidity) */ checkValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/getSVGDocument) */ getSVGDocument(): Document | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLObjectElement/reportValidity) */ reportValidity(): boolean; /** * Sets a custom error message that is displayed when a form is submitted. @@ -12133,13 +11760,8 @@ declare var HTMLObjectElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptGroupElement) */ interface HTMLOptGroupElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptGroupElement/disabled) */ disabled: boolean; - /** - * Sets or retrieves a value that you can use to implement your own label functionality for the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptGroupElement/label) - */ + /** Sets or retrieves a value that you can use to implement your own label functionality for the object. */ label: string; addEventListener(type: K, listener: (this: HTMLOptGroupElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -12158,49 +11780,20 @@ declare var HTMLOptGroupElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement) */ interface HTMLOptionElement extends HTMLElement { - /** - * Sets or retrieves the status of an option. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/defaultSelected) - */ + /** Sets or retrieves the status of an option. */ defaultSelected: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/disabled) */ disabled: boolean; - /** - * Retrieves a reference to the form that the object is embedded in. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/form) - */ + /** Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement | null; - /** - * Sets or retrieves the ordinal position of an option in a list box. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/index) - */ + /** Sets or retrieves the ordinal position of an option in a list box. */ readonly index: number; - /** - * Sets or retrieves a value that you can use to implement your own label functionality for the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/label) - */ + /** Sets or retrieves a value that you can use to implement your own label functionality for the object. */ label: string; - /** - * Sets or retrieves whether the option in the list box is the default item. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/selected) - */ + /** Sets or retrieves whether the option in the list box is the default item. */ selected: boolean; - /** - * Sets or retrieves the text string specified by the option tag. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/text) - */ + /** Sets or retrieves the text string specified by the option tag. */ text: string; - /** - * Sets or retrieves the value which is returned to the server when the form control is submitted. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionElement/value) - */ + /** Sets or retrieves the value which is returned to the server when the form control is submitted. */ value: string; addEventListener(type: K, listener: (this: HTMLOptionElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -12225,16 +11818,12 @@ interface HTMLOptionsCollection extends HTMLCollectionOf { * When set to a smaller number, truncates the number of option elements in the corresponding container. * * When set to a greater number, adds new blank option elements to that container. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionsCollection/length) */ length: number; /** * Returns the index of the first selected item, if any, or −1 if there is no selected item. * * Can be set, to change the selection. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionsCollection/selectedIndex) */ selectedIndex: number; /** @@ -12245,15 +11834,9 @@ interface HTMLOptionsCollection extends HTMLCollectionOf { * If before is omitted, null, or a number out of range, then element will be added at the end of the list. * * This method will throw a "HierarchyRequestError" DOMException if element is an ancestor of the element into which it is to be inserted. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionsCollection/add) */ add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number | null): void; - /** - * Removes the item with index index from the collection. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOptionsCollection/remove) - */ + /** Removes the item with index index from the collection. */ remove(index: number): void; } @@ -12283,41 +11866,25 @@ interface HTMLOrSVGElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement) */ interface HTMLOutputElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/defaultValue) */ defaultValue: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/form) */ readonly form: HTMLFormElement | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/htmlFor) */ readonly htmlFor: DOMTokenList; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/labels) */ readonly labels: NodeListOf; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/name) */ name: string; - /** - * Returns the string "output". - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/type) - */ + /** Returns the string "output". */ readonly type: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/validationMessage) */ readonly validationMessage: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/validity) */ readonly validity: ValidityState; /** * Returns the element's current value. * * Can be set, to change the value. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/value) */ value: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/willValidate) */ readonly willValidate: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/checkValidity) */ checkValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/reportValidity) */ reportValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLOutputElement/setCustomValidity) */ setCustomValidity(error: string): void; addEventListener(type: K, listener: (this: HTMLOutputElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -12339,8 +11906,6 @@ interface HTMLParagraphElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLParagraphElement/align) */ align: string; addEventListener(type: K, listener: (this: HTMLParagraphElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -12364,29 +11929,21 @@ interface HTMLParamElement extends HTMLElement { /** * Sets or retrieves the name of an input parameter for an element. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLParamElement/name) */ name: string; /** * Sets or retrieves the content type of the resource designated by the value attribute. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLParamElement/type) */ type: string; /** * Sets or retrieves the value of an input parameter for an element. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLParamElement/value) */ value: string; /** * Sets or retrieves the data type of the value attribute. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLParamElement/valueType) */ valueType: string; addEventListener(type: K, listener: (this: HTMLParamElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -12427,8 +11984,6 @@ interface HTMLPreElement extends HTMLElement { /** * Sets or gets a value that you can use to implement your own width functionality for the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLPreElement/width) */ width: number; addEventListener(type: K, listener: (this: HTMLPreElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -12485,11 +12040,7 @@ declare var HTMLProgressElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLQuoteElement) */ interface HTMLQuoteElement extends HTMLElement { - /** - * Sets or retrieves reference information about the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLQuoteElement/cite) - */ + /** Sets or retrieves reference information about the object. */ cite: string; addEventListener(type: K, listener: (this: HTMLQuoteElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -12508,6 +12059,7 @@ declare var HTMLQuoteElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement) */ interface HTMLScriptElement extends HTMLElement { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/async) */ async: boolean; /** * Sets or retrieves the character set used to encode the object. @@ -12516,28 +12068,47 @@ interface HTMLScriptElement extends HTMLElement { charset: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/crossOrigin) */ crossOrigin: string | null; - /** Sets or retrieves the status of the script. */ + /** + * Sets or retrieves the status of the script. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/defer) + */ defer: boolean; /** * Sets or retrieves the event for which the script is written. * @deprecated */ event: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/fetchPriority) */ fetchPriority: string; /** * Sets or retrieves the object that is bound to the event script. * @deprecated */ htmlFor: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/integrity) */ integrity: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/noModule) */ noModule: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/referrerPolicy) */ referrerPolicy: string; - /** Retrieves the URL to an external file that contains the source code or data. */ + /** + * Retrieves the URL to an external file that contains the source code or data. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/src) + */ src: string; - /** Retrieves or sets the text of the object as a string. */ + /** + * Retrieves or sets the text of the object as a string. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/text) + */ text: string; - /** Sets or retrieves the MIME type for the associated scripting engine. */ + /** + * Sets or retrieves the MIME type for the associated scripting engine. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLScriptElement/type) + */ type: string; addEventListener(type: K, listener: (this: HTMLScriptElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -12558,7 +12129,6 @@ declare var HTMLScriptElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement) */ interface HTMLSelectElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/autocomplete) */ autocomplete: AutoFill; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/disabled) */ disabled: boolean; @@ -12570,23 +12140,11 @@ interface HTMLSelectElement extends HTMLElement { readonly form: HTMLFormElement | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/labels) */ readonly labels: NodeListOf; - /** - * Sets or retrieves the number of objects in a collection. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/length) - */ + /** Sets or retrieves the number of objects in a collection. */ length: number; - /** - * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/multiple) - */ + /** Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list. */ multiple: boolean; - /** - * Sets or retrieves the name of the object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/name) - */ + /** Sets or retrieves the name of the object. */ name: string; /** * Returns an HTMLOptionsCollection of the list of options. @@ -12594,11 +12152,7 @@ interface HTMLSelectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/options) */ readonly options: HTMLOptionsCollection; - /** - * When present, marks an element that can't be submitted without a value. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/required) - */ + /** When present, marks an element that can't be submitted without a value. */ required: boolean; /** * Sets or retrieves the index of the selected option in a select object. @@ -12608,11 +12162,7 @@ interface HTMLSelectElement extends HTMLElement { selectedIndex: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/selectedOptions) */ readonly selectedOptions: HTMLCollectionOf; - /** - * Sets or retrieves the number of rows in the list box. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/size) - */ + /** Sets or retrieves the number of rows in the list box. */ size: number; /** * Retrieves the type of select control based on the value of the MULTIPLE attribute. @@ -12620,17 +12170,9 @@ interface HTMLSelectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/type) */ readonly type: "select-one" | "select-multiple"; - /** - * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/validationMessage) - */ + /** Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. */ readonly validationMessage: string; - /** - * Returns a ValidityState object that represents the validity states of an element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/validity) - */ + /** Returns a ValidityState object that represents the validity states of an element. */ readonly validity: ValidityState; /** * Sets or retrieves the value which is returned to the server when the form control is submitted. @@ -12638,11 +12180,7 @@ interface HTMLSelectElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/value) */ value: string; - /** - * Returns whether an element will successfully validate based on forms validation rules and constraints. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/willValidate) - */ + /** Returns whether an element will successfully validate based on forms validation rules and constraints. */ readonly willValidate: boolean; /** * Adds an element to the areas, controlRange, or options collection. @@ -12681,7 +12219,6 @@ interface HTMLSelectElement extends HTMLElement { */ remove(): void; remove(index: number): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/reportValidity) */ reportValidity(): boolean; /** * Sets a custom error message that is displayed when a form is submitted. @@ -12733,27 +12270,13 @@ declare var HTMLSlotElement: { interface HTMLSourceElement extends HTMLElement { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/height) */ height: number; - /** - * Gets or sets the intended media type of the media source. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/media) - */ + /** Gets or sets the intended media type of the media source. */ media: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/sizes) */ sizes: string; - /** - * The address or URL of the a media resource that is to be considered. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/src) - */ + /** The address or URL of the a media resource that is to be considered. */ src: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/srcset) */ srcset: string; - /** - * Gets or sets the MIME type of a media resource. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/type) - */ + /** Gets or sets the MIME type of a media resource. */ type: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSourceElement/width) */ width: number; @@ -12830,8 +12353,6 @@ interface HTMLTableCaptionElement extends HTMLElement { /** * Sets or retrieves the alignment of the caption or legend. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableCaptionElement/align) */ align: string; addEventListener(type: K, listener: (this: HTMLTableCaptionElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -12867,8 +12388,6 @@ interface HTMLTableCellElement extends HTMLElement { /** * Sets or retrieves a comma-delimited list of conceptual categories associated with the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableCellElement/axis) */ axis: string; /** @@ -12910,8 +12429,6 @@ interface HTMLTableCellElement extends HTMLElement { /** * Sets or retrieves the height of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableCellElement/height) */ height: string; /** @@ -12942,8 +12459,6 @@ interface HTMLTableCellElement extends HTMLElement { /** * Sets or retrieves the width of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableCellElement/width) */ width: string; addEventListener(type: K, listener: (this: HTMLTableCellElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -12997,8 +12512,6 @@ interface HTMLTableColElement extends HTMLElement { /** * Sets or retrieves the width of the object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableColElement/width) */ width: string; addEventListener(type: K, listener: (this: HTMLTableColElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -13202,8 +12715,6 @@ interface HTMLTableRowElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableRowElement/align) */ align: string; /** @@ -13242,11 +12753,7 @@ interface HTMLTableRowElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableRowElement/sectionRowIndex) */ readonly sectionRowIndex: number; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableRowElement/vAlign) - */ + /** @deprecated */ vAlign: string; /** * Removes the specified cell from the table row, as well as from the cells collection. @@ -13282,8 +12789,6 @@ interface HTMLTableSectionElement extends HTMLElement { /** * Sets or retrieves a value that indicates the table alignment. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableSectionElement/align) */ align: string; /** @@ -13304,11 +12809,7 @@ interface HTMLTableSectionElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableSectionElement/rows) */ readonly rows: HTMLCollectionOf; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTableSectionElement/vAlign) - */ + /** @deprecated */ vAlign: string; /** * Removes the specified row (tr) from the element and from the rows collection. @@ -13347,7 +12848,14 @@ interface HTMLTemplateElement extends HTMLElement { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTemplateElement/content) */ readonly content: DocumentFragment; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTemplateElement/shadowRootClonable) */ + shadowRootClonable: boolean; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTemplateElement/shadowRootDelegatesFocus) */ + shadowRootDelegatesFocus: boolean; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTemplateElement/shadowRootMode) */ shadowRootMode: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTemplateElement/shadowRootSerializable) */ + shadowRootSerializable: boolean; addEventListener(type: K, listener: (this: HTMLTemplateElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: HTMLTemplateElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -13365,7 +12873,6 @@ declare var HTMLTemplateElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTextAreaElement) */ interface HTMLTextAreaElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTextAreaElement/autocomplete) */ autocomplete: AutoFill; /** Sets or retrieves the width of the object. */ cols: number; @@ -13395,7 +12902,6 @@ interface HTMLTextAreaElement extends HTMLElement { selectionEnd: number; /** Gets or sets the starting position or offset of a text selection. */ selectionStart: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTextAreaElement/textLength) */ readonly textLength: number; /** * Retrieves the type of control. @@ -13415,7 +12921,6 @@ interface HTMLTextAreaElement extends HTMLElement { wrap: string; /** Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTextAreaElement/reportValidity) */ reportValidity(): boolean; /** Highlights the input area of a form element. */ select(): void; @@ -13492,23 +12997,14 @@ declare var HTMLTitleElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement) */ interface HTMLTrackElement extends HTMLElement { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/default) */ default: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/kind) */ kind: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/label) */ label: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/readyState) */ readonly readyState: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/src) */ src: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/srclang) */ srclang: string; - /** - * Returns the TextTrack object corresponding to the text track of the track element. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/track) - */ + /** Returns the TextTrack object corresponding to the text track of the track element. */ readonly track: TextTrack; readonly NONE: 0; readonly LOADING: 1; @@ -13535,17 +13031,9 @@ declare var HTMLTrackElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLUListElement) */ interface HTMLUListElement extends HTMLElement { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLUListElement/compact) - */ + /** @deprecated */ compact: boolean; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLUListElement/type) - */ + /** @deprecated */ type: string; addEventListener(type: K, listener: (this: HTMLUListElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -14376,7 +13864,7 @@ interface IDBTransaction extends EventTarget { /** * Returns a list of the names of object stores in the transaction's scope. For an upgrade transaction this is all object stores in the database. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/objectStoreNames) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/ObjectStoreNames) */ readonly objectStoreNames: DOMStringList; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/abort_event) */ @@ -14533,9 +14021,9 @@ declare var ImageData: { new(data: Uint8ClampedArray, sw: number, sh?: number, settings?: ImageDataSettings): ImageData; }; -interface InnerHTML { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) */ - innerHTML: string; +interface ImportMeta { + url: string; + resolve(specifier: string): string; } /** @@ -15304,6 +14792,7 @@ declare var MediaKeySystemAccess: { interface MediaKeys { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaKeys/createSession) */ createSession(sessionType?: MediaKeySessionType): MediaKeySession; + getStatusForPolicy(policy?: MediaKeysPolicy): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaKeys/setServerCertificate) */ setServerCertificate(serverCertificate: BufferSource): Promise; } @@ -15492,11 +14981,8 @@ interface MediaSource extends EventTarget { readonly activeSourceBuffers: SourceBufferList; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/duration) */ duration: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/sourceclose_event) */ onsourceclose: ((this: MediaSource, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/sourceended_event) */ onsourceended: ((this: MediaSource, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/sourceopen_event) */ onsourceopen: ((this: MediaSource, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/readyState) */ readonly readyState: ReadyState; @@ -15521,10 +15007,21 @@ interface MediaSource extends EventTarget { declare var MediaSource: { prototype: MediaSource; new(): MediaSource; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/canConstructInDedicatedWorker_static) */ + readonly canConstructInDedicatedWorker: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSource/isTypeSupported_static) */ isTypeSupported(type: string): boolean; }; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSourceHandle) */ +interface MediaSourceHandle { +} + +declare var MediaSourceHandle: { + prototype: MediaSourceHandle; + new(): MediaSourceHandle; +}; + interface MediaStreamEventMap { "addtrack": MediaStreamTrackEvent; "removetrack": MediaStreamTrackEvent; @@ -15728,11 +15225,7 @@ interface MessageEvent extends Event { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/source) */ readonly source: MessageEventSource | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/initMessageEvent) - */ + /** @deprecated */ initMessageEvent(type: string, bubbles?: boolean, cancelable?: boolean, data?: any, origin?: string, lastEventId?: string, source?: MessageEventSource | null, ports?: MessagePort[]): void; } @@ -15798,29 +15291,21 @@ interface MimeType { /** * Returns the MIME type's description. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeType/description) */ readonly description: string; /** * Returns the Plugin object that implements this MIME type. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeType/enabledPlugin) */ readonly enabledPlugin: Plugin; /** * Returns the MIME type's typical file extensions, in a comma-separated list. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeType/suffixes) */ readonly suffixes: string; /** * Returns the MIME type. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeType/type) */ readonly type: string; } @@ -15838,23 +15323,11 @@ declare var MimeType: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeTypeArray) */ interface MimeTypeArray { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeTypeArray/length) - */ + /** @deprecated */ readonly length: number; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeTypeArray/item) - */ + /** @deprecated */ item(index: number): MimeType | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MimeTypeArray/namedItem) - */ + /** @deprecated */ namedItem(name: string): MimeType | null; [index: number]: MimeType; } @@ -16325,7 +15798,7 @@ interface NavigatorPlugins { /** * @deprecated * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/NavigatorPlugins/mimeTypes) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Navigator/mimeTypes) */ readonly mimeTypes: MimeTypeArray; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Navigator/pdfViewerEnabled) */ @@ -16874,7 +16347,9 @@ interface OffscreenCanvas extends EventTarget { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/height) */ height: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/contextlost_event) */ oncontextlost: ((this: OffscreenCanvas, ev: Event) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/contextrestored_event) */ oncontextrestored: ((this: OffscreenCanvas, ev: Event) => any) | null; /** * These attributes return the dimensions of the OffscreenCanvas object's bitmap. @@ -16926,8 +16401,6 @@ declare var OffscreenCanvas: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvasRenderingContext2D) */ interface OffscreenCanvasRenderingContext2D extends CanvasCompositing, CanvasDrawImage, CanvasDrawPath, CanvasFillStrokeStyles, CanvasFilters, CanvasImageData, CanvasImageSmoothing, CanvasPath, CanvasPathDrawingStyles, CanvasRect, CanvasShadowStyles, CanvasState, CanvasText, CanvasTextDrawingStyles, CanvasTransform { readonly canvas: OffscreenCanvas; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvasRenderingContext2D/commit) */ - commit(): void; } declare var OffscreenCanvasRenderingContext2D: { @@ -17787,15 +17260,11 @@ interface Plugin { /** * Returns the plugin's description. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Plugin/description) */ readonly description: string; /** * Returns the plugin library's filename, if applicable on the current platform. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Plugin/filename) */ readonly filename: string; /** @@ -17806,22 +17275,14 @@ interface Plugin { /** * Returns the plugin's name. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Plugin/name) */ readonly name: string; /** * Returns the specified MimeType object. * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Plugin/item) */ item(index: number): MimeType | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Plugin/namedItem) - */ + /** @deprecated */ namedItem(name: string): MimeType | null; [index: number]: MimeType; } @@ -17839,29 +17300,13 @@ declare var Plugin: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PluginArray) */ interface PluginArray { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PluginArray/length) - */ + /** @deprecated */ readonly length: number; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PluginArray/item) - */ + /** @deprecated */ item(index: number): Plugin | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PluginArray/namedItem) - */ + /** @deprecated */ namedItem(name: string): Plugin | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PluginArray/refresh) - */ + /** @deprecated */ refresh(): void; [index: number]: Plugin; } @@ -17919,6 +17364,7 @@ declare var PointerEvent: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PopStateEvent) */ interface PopStateEvent extends Event { + readonly hasUAVisualTransition: boolean; /** * Returns a copy of the information that was provided to pushState() or replaceState(). * @@ -17994,6 +17440,7 @@ declare var PromiseRejectionEvent: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential) */ interface PublicKeyCredential extends Credential { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/authenticatorAttachment) */ readonly authenticatorAttachment: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/rawId) */ readonly rawId: ArrayBuffer; @@ -18213,12 +17660,11 @@ interface RTCDtlsTransportEventMap { interface RTCDtlsTransport extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCDtlsTransport/iceTransport) */ readonly iceTransport: RTCIceTransport; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCDtlsTransport/error_event) */ onerror: ((this: RTCDtlsTransport, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCDtlsTransport/statechange_event) */ onstatechange: ((this: RTCDtlsTransport, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCDtlsTransport/state) */ readonly state: RTCDtlsTransportState; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCDtlsTransport/getRemoteCertificates) */ getRemoteCertificates(): ArrayBuffer[]; addEventListener(type: K, listener: (this: RTCDtlsTransport, ev: RTCDtlsTransportEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -18336,6 +17782,11 @@ declare var RTCIceCandidate: { new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate; }; +interface RTCIceCandidatePair { + local: RTCIceCandidate; + remote: RTCIceCandidate; +} + interface RTCIceTransportEventMap { "gatheringstatechange": Event; "selectedcandidatepairchange": Event; @@ -18492,12 +17943,9 @@ declare var RTCPeerConnection: { interface RTCPeerConnectionIceErrorEvent extends Event { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCPeerConnectionIceErrorEvent/address) */ readonly address: string | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCPeerConnectionIceErrorEvent/errorCode) */ readonly errorCode: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCPeerConnectionIceErrorEvent/errorText) */ readonly errorText: string; readonly port: number | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCPeerConnectionIceErrorEvent/url) */ readonly url: string; } @@ -18527,6 +17975,8 @@ declare var RTCPeerConnectionIceEvent: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpReceiver) */ interface RTCRtpReceiver { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpReceiver/jitterBufferTarget) */ + jitterBufferTarget: DOMHighResTimeStamp | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpReceiver/track) */ readonly track: MediaStreamTrack; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpReceiver/transform) */ @@ -18605,7 +18055,7 @@ interface RTCRtpTransceiver { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpTransceiver/sender) */ readonly sender: RTCRtpSender; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpTransceiver/setCodecPreferences) */ - setCodecPreferences(codecs: RTCRtpCodecCapability[]): void; + setCodecPreferences(codecs: RTCRtpCodec[]): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpTransceiver/stop) */ stop(): void; } @@ -18625,6 +18075,7 @@ interface RTCSctpTransport extends EventTarget { readonly maxChannels: number | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCSctpTransport/maxMessageSize) */ readonly maxMessageSize: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCSctpTransport/statechange_event) */ onstatechange: ((this: RTCSctpTransport, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCSctpTransport/state) */ readonly state: RTCSctpTransportState; @@ -18652,7 +18103,7 @@ interface RTCSessionDescription { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCSessionDescription/type) */ readonly type: RTCSdpType; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCSessionDescription/toJSON) */ - toJSON(): any; + toJSON(): RTCSessionDescriptionInit; } declare var RTCSessionDescription: { @@ -18725,7 +18176,7 @@ interface Range extends AbstractRange { */ comparePoint(node: Node, offset: number): number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Range/createContextualFragment) */ - createContextualFragment(fragment: string): DocumentFragment; + createContextualFragment(string: string): DocumentFragment; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Range/deleteContents) */ deleteContents(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Range/detach) */ @@ -18829,21 +18280,17 @@ declare var ReadableStream: { from(asyncIterable: AsyncIterable | Iterable>): ReadableStream; }; -interface ReadableStreamBYOBReaderReadOptions { - min?: number; -} - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader) */ interface ReadableStreamBYOBReader extends ReadableStreamGenericReader { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader/read) */ - read(view: T, options?: ReadableStreamBYOBReaderReadOptions): Promise>; + read(view: T): Promise>; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader/releaseLock) */ releaseLock(): void; } declare var ReadableStreamBYOBReader: { prototype: ReadableStreamBYOBReader; - new(stream: ReadableStream): ReadableStreamBYOBReader; + new(stream: ReadableStream): ReadableStreamBYOBReader; }; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBRequest) */ @@ -18949,6 +18396,7 @@ declare var Report: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReportBody) */ interface ReportBody { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReportBody/toJSON) */ toJSON(): any; } @@ -19008,11 +18456,7 @@ interface Request extends Body { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/integrity) */ readonly integrity: string; - /** - * Returns a boolean indicating whether or not request can outlive the global in which it was created. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/keepalive) - */ + /** Returns a boolean indicating whether or not request can outlive the global in which it was created. */ readonly keepalive: boolean; /** * Returns request's HTTP method, which is "GET" by default. @@ -19088,6 +18532,7 @@ interface ResizeObserverEntry { readonly contentBoxSize: ReadonlyArray; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserverEntry/contentRect) */ readonly contentRect: DOMRectReadOnly; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserverEntry/devicePixelContentBoxSize) */ readonly devicePixelContentBoxSize: ReadonlyArray; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserverEntry/target) */ readonly target: Element; @@ -19271,7 +18716,9 @@ declare var SVGAnimatedBoolean: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedEnumeration) */ interface SVGAnimatedEnumeration { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedEnumeration/animVal) */ readonly animVal: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedEnumeration/baseVal) */ baseVal: number; } @@ -19301,7 +18748,9 @@ declare var SVGAnimatedInteger: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedLength) */ interface SVGAnimatedLength { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedLength/animVal) */ readonly animVal: SVGLength; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGAnimatedLength/baseVal) */ readonly baseVal: SVGLength; } @@ -19663,11 +19112,8 @@ declare var SVGFEBlendElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGFEColorMatrixElement) */ interface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGFEColorMatrixElement/in1) */ readonly in1: SVGAnimatedString; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGFEColorMatrixElement/type) */ readonly type: SVGAnimatedEnumeration; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGFEColorMatrixElement/values) */ readonly values: SVGAnimatedNumberList; readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: 0; readonly SVG_FECOLORMATRIX_TYPE_MATRIX: 1; @@ -20357,7 +19803,6 @@ declare var SVGGraphicsElement: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGImageElement) */ interface SVGImageElement extends SVGGraphicsElement, SVGURIReference { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGImageElement/crossorigin) */ crossOrigin: string | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SVGImageElement/height) */ readonly height: SVGAnimatedLength; @@ -21306,6 +20751,7 @@ interface ScreenOrientationEventMap { interface ScreenOrientation extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ScreenOrientation/angle) */ readonly angle: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ScreenOrientation/change_event) */ onchange: ((this: ScreenOrientation, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ScreenOrientation/type) */ readonly type: OrientationType; @@ -21404,6 +20850,8 @@ interface Selection { readonly anchorNode: Node | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Selection/anchorOffset) */ readonly anchorOffset: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Selection/direction) */ + readonly direction: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Selection/focusNode) */ readonly focusNode: Node | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Selection/focusOffset) */ @@ -21576,18 +21024,25 @@ interface ShadowRootEventMap { } /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot) */ -interface ShadowRoot extends DocumentFragment, DocumentOrShadowRoot, InnerHTML { +interface ShadowRoot extends DocumentFragment, DocumentOrShadowRoot { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/clonable) */ readonly clonable: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/delegatesFocus) */ readonly delegatesFocus: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/host) */ readonly host: Element; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/innerHTML) */ + innerHTML: string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/mode) */ readonly mode: ShadowRootMode; onslotchange: ((this: ShadowRoot, ev: Event) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/serializable) */ + readonly serializable: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/slotAssignment) */ readonly slotAssignment: SlotAssignmentMode; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/getHTML) */ + getHTML(options?: GetHTMLOptions): string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ShadowRoot/setHTMLUnsafe) */ setHTMLUnsafe(html: string): void; /** Throws a "NotSupportedError" DOMException if context object is a shadow root. */ addEventListener(type: K, listener: (this: ShadowRoot, ev: ShadowRootEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -21647,15 +21102,10 @@ interface SourceBuffer extends EventTarget { readonly buffered: TimeRanges; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/mode) */ mode: AppendMode; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/abort_event) */ onabort: ((this: SourceBuffer, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/error_event) */ onerror: ((this: SourceBuffer, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/update_event) */ onupdate: ((this: SourceBuffer, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/updateend_event) */ onupdateend: ((this: SourceBuffer, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/updatestart_event) */ onupdatestart: ((this: SourceBuffer, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBuffer/timestampOffset) */ timestampOffset: number; @@ -21693,9 +21143,7 @@ interface SourceBufferListEventMap { interface SourceBufferList extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBufferList/length) */ readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBufferList/addsourcebuffer_event) */ onaddsourcebuffer: ((this: SourceBufferList, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SourceBufferList/removesourcebuffer_event) */ onremovesourcebuffer: ((this: SourceBufferList, ev: Event) => any) | null; addEventListener(type: K, listener: (this: SourceBufferList, ev: SourceBufferListEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; @@ -22155,7 +21603,7 @@ declare var SubmitEvent: { }; /** - * This Web Crypto API interface provides a number of low-level cryptographic functions. It is accessed via the Crypto.subtle properties available in a window context (via Window.crypto). + * This Web Crypto API interface provides a number of low-level cryptographic functions. It is accessed via the Crypto.subtle properties available in a window context (via globalThis.crypto). * Available only in secure contexts. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto) @@ -22329,6 +21777,16 @@ declare var TextEncoderStream: { new(): TextEncoderStream; }; +interface TextEvent extends UIEvent { + readonly data: string; + initTextEvent(type: string, bubbles?: boolean, cancelable?: boolean, view?: Window | null, data?: string): void; +} + +declare var TextEvent: { + prototype: TextEvent; + new(): TextEvent; +}; + /** * The dimensions of a piece of text in the canvas, as created by the CanvasRenderingContext2D.measureText() method. * @@ -22605,7 +22063,7 @@ interface TextTrackList extends EventTarget { onaddtrack: ((this: TextTrackList, ev: TrackEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextTrackList/change_event) */ onchange: ((this: TextTrackList, ev: Event) => any) | null; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextTrackList/removetrack_event) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextTrackList/removeTrack_event) */ onremovetrack: ((this: TextTrackList, ev: TrackEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextTrackList/getTrackById) */ getTrackById(id: string): TextTrack | null; @@ -23036,21 +22494,13 @@ declare var VTTCue: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion) */ interface VTTRegion { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/id) */ id: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/lines) */ lines: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/regionAnchorX) */ regionAnchorX: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/regionAnchorY) */ regionAnchorY: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/scroll) */ scroll: ScrollSetting; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/viewportAnchorX) */ viewportAnchorX: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/viewportAnchorY) */ viewportAnchorY: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VTTRegion/width) */ width: number; } @@ -23067,7 +22517,6 @@ declare var VTTRegion: { interface ValidityState { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/badInput) */ readonly badInput: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/customError) */ readonly customError: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/patternMismatch) */ readonly patternMismatch: boolean; @@ -23083,7 +22532,6 @@ interface ValidityState { readonly tooShort: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/typeMismatch) */ readonly typeMismatch: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/valid) */ readonly valid: boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ValidityState/valueMissing) */ readonly valueMissing: boolean; @@ -23125,6 +22573,7 @@ interface VideoDecoderEventMap { interface VideoDecoder extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/decodeQueueSize) */ readonly decodeQueueSize: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/dequeue_event) */ ondequeue: ((this: VideoDecoder, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/state) */ readonly state: CodecState; @@ -23147,6 +22596,7 @@ interface VideoDecoder extends EventTarget { declare var VideoDecoder: { prototype: VideoDecoder; new(init: VideoDecoderInit): VideoDecoder; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/isConfigSupported_static) */ isConfigSupported(config: VideoDecoderConfig): Promise; }; @@ -23162,6 +22612,7 @@ interface VideoEncoderEventMap { interface VideoEncoder extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/encodeQueueSize) */ readonly encodeQueueSize: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/dequeue_event) */ ondequeue: ((this: VideoEncoder, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/state) */ readonly state: CodecState; @@ -23171,6 +22622,7 @@ interface VideoEncoder extends EventTarget { configure(config: VideoEncoderConfig): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/encode) */ encode(frame: VideoFrame, options?: VideoEncoderEncodeOptions): void; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/flush) */ flush(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/reset) */ reset(): void; @@ -23183,6 +22635,7 @@ interface VideoEncoder extends EventTarget { declare var VideoEncoder: { prototype: VideoEncoder; new(init: VideoEncoderInit): VideoEncoder; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/isConfigSupported_static) */ isConfigSupported(config: VideoEncoderConfig): Promise; }; @@ -23214,6 +22667,7 @@ interface VideoFrame { clone(): VideoFrame; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoFrame/close) */ close(): void; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoFrame/copyTo) */ copyTo(destination: AllowSharedBufferSource, options?: VideoFrameCopyToOptions): Promise; } @@ -23248,6 +22702,23 @@ declare var VideoPlaybackQuality: { new(): VideoPlaybackQuality; }; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ViewTransition) */ +interface ViewTransition { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ViewTransition/finished) */ + readonly finished: Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ViewTransition/ready) */ + readonly ready: Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ViewTransition/updateCallbackDone) */ + readonly updateCallbackDone: Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ViewTransition/skipTransition) */ + skipTransition(): void; +} + +declare var ViewTransition: { + prototype: ViewTransition; + new(): ViewTransition; +}; + interface VisualViewportEventMap { "resize": Event; "scroll": Event; @@ -24113,7 +23584,7 @@ interface WebGL2RenderingContextBase { clearBufferuiv(buffer: GLenum, drawbuffer: GLint, values: Uint32List, srcOffset?: number): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/clientWaitSync) */ clientWaitSync(sync: WebGLSync, flags: GLbitfield, timeout: GLuint64): GLenum; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/compressedTexImage3D) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/compressedTexImage2D) */ compressedTexImage3D(target: GLenum, level: GLint, internalformat: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, imageSize: GLsizei, offset: GLintptr): void; compressedTexImage3D(target: GLenum, level: GLint, internalformat: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, srcData: ArrayBufferView, srcOffset?: number, srcLengthOverride?: GLuint): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/compressedTexSubImage3D) */ @@ -24996,6 +24467,7 @@ declare var WebGLRenderingContext: { interface WebGLRenderingContextBase { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/canvas) */ readonly canvas: HTMLCanvasElement | OffscreenCanvas; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/drawingBufferColorSpace) */ drawingBufferColorSpace: PredefinedColorSpace; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/drawingBufferHeight) */ readonly drawingBufferHeight: GLsizei; @@ -25705,7 +25177,7 @@ declare var WebGLVertexArrayObject: { new(): WebGLVertexArrayObject; }; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLVertexArrayObjectOES) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLVertexArrayObject) */ interface WebGLVertexArrayObjectOES { } @@ -26286,24 +25758,24 @@ interface WindowOrWorkerGlobalScope { /** * Available only in secure contexts. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/caches) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/caches) */ readonly caches: CacheStorage; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crossOriginIsolated) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crossOriginIsolated) */ readonly crossOriginIsolated: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crypto_property) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto) */ readonly crypto: Crypto; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/indexedDB) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/indexedDB) */ readonly indexedDB: IDBFactory; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/isSecureContext) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/isSecureContext) */ readonly isSecureContext: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/origin) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/origin) */ readonly origin: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/performance_property) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/performance) */ readonly performance: Performance; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/atob) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */ atob(data: string): string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/btoa) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */ btoa(data: string): string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/clearInterval) */ clearInterval(id: number | undefined): void; @@ -26810,7 +26282,7 @@ interface Console { clear(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/count_static) */ count(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countReset_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countreset_static) */ countReset(label?: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/debug_static) */ debug(...data: any[]): void; @@ -26822,9 +26294,9 @@ interface Console { error(...data: any[]): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/group_static) */ group(...data: any[]): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupCollapsed_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupcollapsed_static) */ groupCollapsed(...data: any[]): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupEnd_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupend_static) */ groupEnd(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/info_static) */ info(...data: any[]): void; @@ -26834,9 +26306,9 @@ interface Console { table(tabularData?: any, properties?: string[]): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/time_static) */ time(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeEnd_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeend_static) */ timeEnd(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeLog_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timelog_static) */ timeLog(label?: string, ...data: any[]): void; timeStamp(label?: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/trace_static) */ @@ -26988,9 +26460,7 @@ declare namespace WebAssembly { /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global) */ interface Global { - /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global/value) */ value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global/valueOf) */ valueOf(): ValueTypeMap[T]; } @@ -27289,6 +26759,10 @@ interface UnderlyingSourceStartCallback { (controller: ReadableStreamController): any; } +interface UpdateCallback { + (): any; +} + interface VideoFrameOutputCallback { (output: VideoFrame): void; } @@ -27865,7 +27339,7 @@ declare var onbeforetoggle: ((this: Window, ev: Event) => any) | null; * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/blur_event) */ declare var onblur: ((this: Window, ev: FocusEvent) => any) | null; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDialogElement/cancel_event) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/cancel_event) */ declare var oncancel: ((this: Window, ev: Event) => any) | null; /** * Occurs when playback is possible, but would require further buffering. @@ -27892,6 +27366,8 @@ declare var onchange: ((this: Window, ev: Event) => any) | null; declare var onclick: ((this: Window, ev: MouseEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLDialogElement/close_event) */ declare var onclose: ((this: Window, ev: Event) => any) | null; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/webglcontextlost_event) */ +declare var oncontextlost: ((this: Window, ev: Event) => any) | null; /** * Fires when the user clicks the right mouse button in the client area, opening the context menu. * @param ev The mouse event. @@ -27899,6 +27375,8 @@ declare var onclose: ((this: Window, ev: Event) => any) | null; * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event) */ declare var oncontextmenu: ((this: Window, ev: MouseEvent) => any) | null; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/contextrestored_event) */ +declare var oncontextrestored: ((this: Window, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/copy_event) */ declare var oncopy: ((this: Window, ev: ClipboardEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTrackElement/cuechange_event) */ @@ -28049,7 +27527,7 @@ declare var onloadedmetadata: ((this: Window, ev: Event) => any) | null; * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement/loadstart_event) */ declare var onloadstart: ((this: Window, ev: Event) => any) | null; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/lostpointercapture_event) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/lostpointercapture_event) */ declare var onlostpointercapture: ((this: Window, ev: PointerEvent) => any) | null; /** * Fires when the user clicks the object with either mouse button. @@ -28316,24 +27794,24 @@ declare var localStorage: Storage; /** * Available only in secure contexts. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/caches) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/caches) */ declare var caches: CacheStorage; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crossOriginIsolated) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crossOriginIsolated) */ declare var crossOriginIsolated: boolean; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crypto_property) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto) */ declare var crypto: Crypto; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/indexedDB) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/indexedDB) */ declare var indexedDB: IDBFactory; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/isSecureContext) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/isSecureContext) */ declare var isSecureContext: boolean; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/origin) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/origin) */ declare var origin: string; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/performance_property) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/performance) */ declare var performance: Performance; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/atob) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */ declare function atob(data: string): string; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/btoa) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */ declare function btoa(data: string): string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/clearInterval) */ declare function clearInterval(id: number | undefined): void; @@ -28427,7 +27905,7 @@ type ReportList = Report[]; type RequestInfo = Request | string; type TexImageSource = ImageBitmap | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | VideoFrame; type TimerHandler = string | Function; -type Transferable = OffscreenCanvas | ImageBitmap | MessagePort | ReadableStream | WritableStream | TransformStream | VideoFrame | ArrayBuffer; +type Transferable = OffscreenCanvas | ImageBitmap | MessagePort | MediaSourceHandle | ReadableStream | WritableStream | TransformStream | VideoFrame | ArrayBuffer; type Uint32List = Uint32Array | GLuint[]; type VibratePattern = number | number[]; type WindowProxy = Window; diff --git a/cli/tsc/dts/lib.dom.iterable.d.ts b/cli/tsc/dts/lib.dom.iterable.d.ts index f8ac3d9c11..b4cec2ce2d 100644 --- a/cli/tsc/dts/lib.dom.iterable.d.ts +++ b/cli/tsc/dts/lib.dom.iterable.d.ts @@ -41,36 +41,36 @@ interface BaseAudioContext { } interface CSSKeyframesRule { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface CSSNumericArray { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSNumericValue]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSNumericValue]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface CSSRuleList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface CSSStyleDeclaration { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface CSSTransformValue { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSTransformComponent]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSTransformComponent]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface CSSUnparsedValue { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSUnparsedSegment]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSUnparsedSegment]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface Cache { @@ -92,72 +92,80 @@ interface CustomStateSet extends Set { } interface DOMRectList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface DOMStringList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface DOMTokenList { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, string]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, string]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface DataTransferItemList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface EventCounts extends ReadonlyMap { } interface FileList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface FontFaceSet extends Set { } +interface FormDataIterator extends IteratorObject { + [Symbol.iterator](): FormDataIterator; +} + interface FormData { - [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>; + [Symbol.iterator](): FormDataIterator<[string, FormDataEntryValue]>; /** Returns an array of key, value pairs for every entry in the list. */ - entries(): IterableIterator<[string, FormDataEntryValue]>; + entries(): FormDataIterator<[string, FormDataEntryValue]>; /** Returns a list of keys in the list. */ - keys(): IterableIterator; + keys(): FormDataIterator; /** Returns a list of values in the list. */ - values(): IterableIterator; + values(): FormDataIterator; } interface HTMLAllCollection { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface HTMLCollectionBase { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface HTMLCollectionOf { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface HTMLFormElement { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface HTMLSelectElement { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; +} + +interface HeadersIterator extends IteratorObject { + [Symbol.iterator](): HeadersIterator; } interface Headers { - [Symbol.iterator](): IterableIterator<[string, string]>; + [Symbol.iterator](): HeadersIterator<[string, string]>; /** Returns an iterator allowing to go through all key/value pairs contained in this object. */ - entries(): IterableIterator<[string, string]>; + entries(): HeadersIterator<[string, string]>; /** Returns an iterator allowing to go through all keys of the key/value pairs contained in this object. */ - keys(): IterableIterator; + keys(): HeadersIterator; /** Returns an iterator allowing to go through all values of the key/value pairs contained in this object. */ - values(): IterableIterator; + values(): HeadersIterator; } interface Highlight extends Set { @@ -197,32 +205,32 @@ interface MIDIOutput { interface MIDIOutputMap extends ReadonlyMap { } +interface MediaKeyStatusMapIterator extends IteratorObject { + [Symbol.iterator](): MediaKeyStatusMapIterator; +} + interface MediaKeyStatusMap { - [Symbol.iterator](): IterableIterator<[BufferSource, MediaKeyStatus]>; - entries(): IterableIterator<[BufferSource, MediaKeyStatus]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): MediaKeyStatusMapIterator<[BufferSource, MediaKeyStatus]>; + entries(): MediaKeyStatusMapIterator<[BufferSource, MediaKeyStatus]>; + keys(): MediaKeyStatusMapIterator; + values(): MediaKeyStatusMapIterator; } interface MediaList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface MessageEvent { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/initMessageEvent) - */ + /** @deprecated */ initMessageEvent(type: string, bubbles?: boolean, cancelable?: boolean, data?: any, origin?: string, lastEventId?: string, source?: MessageEventSource | null, ports?: Iterable): void; } interface MimeTypeArray { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface NamedNodeMap { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface Navigator { @@ -237,82 +245,86 @@ interface Navigator { } interface NodeList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** Returns an array of key, value pairs for every entry in the list. */ - entries(): IterableIterator<[number, Node]>; + entries(): ArrayIterator<[number, Node]>; /** Returns an list of keys in the list. */ - keys(): IterableIterator; + keys(): ArrayIterator; /** Returns an list of values in the list. */ - values(): IterableIterator; + values(): ArrayIterator; } interface NodeListOf { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** Returns an array of key, value pairs for every entry in the list. */ - entries(): IterableIterator<[number, TNode]>; + entries(): ArrayIterator<[number, TNode]>; /** Returns an list of keys in the list. */ - keys(): IterableIterator; + keys(): ArrayIterator; /** Returns an list of values in the list. */ - values(): IterableIterator; + values(): ArrayIterator; } interface Plugin { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface PluginArray { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface RTCRtpTransceiver { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/RTCRtpTransceiver/setCodecPreferences) */ - setCodecPreferences(codecs: Iterable): void; + setCodecPreferences(codecs: Iterable): void; } interface RTCStatsReport extends ReadonlyMap { } interface SVGLengthList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SVGNumberList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SVGPointList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SVGStringList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SVGTransformList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SourceBufferList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SpeechRecognitionResult { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SpeechRecognitionResultList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; +} + +interface StylePropertyMapReadOnlyIterator extends IteratorObject { + [Symbol.iterator](): StylePropertyMapReadOnlyIterator; } interface StylePropertyMapReadOnly { - [Symbol.iterator](): IterableIterator<[string, Iterable]>; - entries(): IterableIterator<[string, Iterable]>; - keys(): IterableIterator; - values(): IterableIterator>; + [Symbol.iterator](): StylePropertyMapReadOnlyIterator<[string, Iterable]>; + entries(): StylePropertyMapReadOnlyIterator<[string, Iterable]>; + keys(): StylePropertyMapReadOnlyIterator; + values(): StylePropertyMapReadOnlyIterator>; } interface StyleSheetList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface SubtleCrypto { @@ -331,25 +343,29 @@ interface SubtleCrypto { } interface TextTrackCueList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface TextTrackList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface TouchList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; +} + +interface URLSearchParamsIterator extends IteratorObject { + [Symbol.iterator](): URLSearchParamsIterator; } interface URLSearchParams { - [Symbol.iterator](): IterableIterator<[string, string]>; + [Symbol.iterator](): URLSearchParamsIterator<[string, string]>; /** Returns an array of key, value pairs for every entry in the search params. */ - entries(): IterableIterator<[string, string]>; + entries(): URLSearchParamsIterator<[string, string]>; /** Returns a list of keys in the search params. */ - keys(): IterableIterator; + keys(): URLSearchParamsIterator; /** Returns a list of values in the search params. */ - values(): IterableIterator; + values(): URLSearchParamsIterator; } interface WEBGL_draw_buffers { diff --git a/cli/tsc/dts/lib.es2015.generator.d.ts b/cli/tsc/dts/lib.es2015.generator.d.ts index 716bac29c1..dc7460a0ff 100644 --- a/cli/tsc/dts/lib.es2015.generator.d.ts +++ b/cli/tsc/dts/lib.es2015.generator.d.ts @@ -18,9 +18,9 @@ and limitations under the License. /// -interface Generator extends Iterator { +interface Generator extends IteratorObject { // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places. - next(...args: [] | [TNext]): IteratorResult; + next(...[value]: [] | [TNext]): IteratorResult; return(value: TReturn): IteratorResult; throw(e: any): IteratorResult; [Symbol.iterator](): Generator; diff --git a/cli/tsc/dts/lib.es2015.iterable.d.ts b/cli/tsc/dts/lib.es2015.iterable.d.ts index 3ad043c679..eaff26d9a3 100644 --- a/cli/tsc/dts/lib.es2015.iterable.d.ts +++ b/cli/tsc/dts/lib.es2015.iterable.d.ts @@ -38,39 +38,59 @@ interface IteratorReturnResult { type IteratorResult = IteratorYieldResult | IteratorReturnResult; -interface Iterator { +interface Iterator { // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places. - next(...args: [] | [TNext]): IteratorResult; + next(...[value]: [] | [TNext]): IteratorResult; return?(value?: TReturn): IteratorResult; throw?(e?: any): IteratorResult; } -interface Iterable { - [Symbol.iterator](): Iterator; +interface Iterable { + [Symbol.iterator](): Iterator; } -interface IterableIterator extends Iterator { - [Symbol.iterator](): IterableIterator; +/** + * Describes a user-defined {@link Iterator} that is also iterable. + */ +interface IterableIterator extends Iterator { + [Symbol.iterator](): IterableIterator; +} + +/** + * Describes an {@link Iterator} produced by the runtime that inherits from the intrinsic `Iterator.prototype`. + */ +interface IteratorObject extends Iterator { + [Symbol.iterator](): IteratorObject; +} + +/** + * Defines the `TReturn` type used for built-in iterators produced by `Array`, `Map`, `Set`, and others. + * This is `undefined` when `strictBuiltInIteratorReturn` is `true`; otherwise, this is `any`. + */ +type BuiltinIteratorReturn = intrinsic; + +interface ArrayIterator extends IteratorObject { + [Symbol.iterator](): ArrayIterator; } interface Array { /** Iterator */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an iterable of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, T]>; + entries(): ArrayIterator<[number, T]>; /** * Returns an iterable of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an iterable of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface ArrayConstructor { @@ -91,67 +111,71 @@ interface ArrayConstructor { interface ReadonlyArray { /** Iterator of values in the array. */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an iterable of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, T]>; + entries(): ArrayIterator<[number, T]>; /** * Returns an iterable of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an iterable of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface IArguments { /** Iterator */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; +} + +interface MapIterator extends IteratorObject { + [Symbol.iterator](): MapIterator; } interface Map { /** Returns an iterable of entries in the map. */ - [Symbol.iterator](): IterableIterator<[K, V]>; + [Symbol.iterator](): MapIterator<[K, V]>; /** * Returns an iterable of key, value pairs for every entry in the map. */ - entries(): IterableIterator<[K, V]>; + entries(): MapIterator<[K, V]>; /** * Returns an iterable of keys in the map */ - keys(): IterableIterator; + keys(): MapIterator; /** * Returns an iterable of values in the map */ - values(): IterableIterator; + values(): MapIterator; } interface ReadonlyMap { /** Returns an iterable of entries in the map. */ - [Symbol.iterator](): IterableIterator<[K, V]>; + [Symbol.iterator](): MapIterator<[K, V]>; /** * Returns an iterable of key, value pairs for every entry in the map. */ - entries(): IterableIterator<[K, V]>; + entries(): MapIterator<[K, V]>; /** * Returns an iterable of keys in the map */ - keys(): IterableIterator; + keys(): MapIterator; /** * Returns an iterable of values in the map */ - values(): IterableIterator; + values(): MapIterator; } interface MapConstructor { @@ -165,42 +189,46 @@ interface WeakMapConstructor { new (iterable: Iterable): WeakMap; } +interface SetIterator extends IteratorObject { + [Symbol.iterator](): SetIterator; +} + interface Set { /** Iterates over values in the set. */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): SetIterator; /** * Returns an iterable of [v,v] pairs for every value `v` in the set. */ - entries(): IterableIterator<[T, T]>; + entries(): SetIterator<[T, T]>; /** * Despite its name, returns an iterable of the values in the set. */ - keys(): IterableIterator; + keys(): SetIterator; /** * Returns an iterable of values in the set. */ - values(): IterableIterator; + values(): SetIterator; } interface ReadonlySet { /** Iterates over values in the set. */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): SetIterator; /** * Returns an iterable of [v,v] pairs for every value `v` in the set. */ - entries(): IterableIterator<[T, T]>; + entries(): SetIterator<[T, T]>; /** * Despite its name, returns an iterable of the values in the set. */ - keys(): IterableIterator; + keys(): SetIterator; /** * Returns an iterable of values in the set. */ - values(): IterableIterator; + values(): SetIterator; } interface SetConstructor { @@ -233,25 +261,29 @@ interface PromiseConstructor { race(values: Iterable>): Promise>; } +interface StringIterator extends IteratorObject { + [Symbol.iterator](): StringIterator; +} + interface String { /** Iterator */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): StringIterator; } interface Int8Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Int8ArrayConstructor { @@ -267,19 +299,19 @@ interface Int8ArrayConstructor { } interface Uint8Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Uint8ArrayConstructor { @@ -295,21 +327,21 @@ interface Uint8ArrayConstructor { } interface Uint8ClampedArray { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Uint8ClampedArrayConstructor { @@ -325,21 +357,21 @@ interface Uint8ClampedArrayConstructor { } interface Int16Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Int16ArrayConstructor { @@ -355,19 +387,19 @@ interface Int16ArrayConstructor { } interface Uint16Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Uint16ArrayConstructor { @@ -383,19 +415,19 @@ interface Uint16ArrayConstructor { } interface Int32Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Int32ArrayConstructor { @@ -411,19 +443,19 @@ interface Int32ArrayConstructor { } interface Uint32Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Uint32ArrayConstructor { @@ -439,19 +471,19 @@ interface Uint32ArrayConstructor { } interface Float32Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Float32ArrayConstructor { @@ -467,19 +499,19 @@ interface Float32ArrayConstructor { } interface Float64Array { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; /** * Returns an array of key, value pairs for every entry in the array */ - entries(): IterableIterator<[number, number]>; + entries(): ArrayIterator<[number, number]>; /** * Returns an list of keys in the array */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns an list of values in the array */ - values(): IterableIterator; + values(): ArrayIterator; } interface Float64ArrayConstructor { diff --git a/cli/tsc/dts/lib.es2017.object.d.ts b/cli/tsc/dts/lib.es2017.object.d.ts index af9ef2f987..523b05dc8b 100644 --- a/cli/tsc/dts/lib.es2017.object.d.ts +++ b/cli/tsc/dts/lib.es2017.object.d.ts @@ -18,25 +18,25 @@ and limitations under the License. interface ObjectConstructor { /** - * Returns an array of values of the enumerable properties of an object + * Returns an array of values of the enumerable own properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ values(o: { [s: string]: T; } | ArrayLike): T[]; /** - * Returns an array of values of the enumerable properties of an object + * Returns an array of values of the enumerable own properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ values(o: {}): any[]; /** - * Returns an array of key/values of the enumerable properties of an object + * Returns an array of key/values of the enumerable own properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ entries(o: { [s: string]: T; } | ArrayLike): [string, T][]; /** - * Returns an array of key/values of the enumerable properties of an object + * Returns an array of key/values of the enumerable own properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ entries(o: {}): [string, any][]; diff --git a/cli/tsc/dts/lib.es2018.asyncgenerator.d.ts b/cli/tsc/dts/lib.es2018.asyncgenerator.d.ts index 092a34f010..429c218200 100644 --- a/cli/tsc/dts/lib.es2018.asyncgenerator.d.ts +++ b/cli/tsc/dts/lib.es2018.asyncgenerator.d.ts @@ -18,9 +18,9 @@ and limitations under the License. /// -interface AsyncGenerator extends AsyncIterator { +interface AsyncGenerator extends AsyncIteratorObject { // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places. - next(...args: [] | [TNext]): Promise>; + next(...[value]: [] | [TNext]): Promise>; return(value: TReturn | PromiseLike): Promise>; throw(e: any): Promise>; [Symbol.asyncIterator](): AsyncGenerator; diff --git a/cli/tsc/dts/lib.es2018.asynciterable.d.ts b/cli/tsc/dts/lib.es2018.asynciterable.d.ts index f3de8021d7..a2ddd99be6 100644 --- a/cli/tsc/dts/lib.es2018.asynciterable.d.ts +++ b/cli/tsc/dts/lib.es2018.asynciterable.d.ts @@ -27,17 +27,27 @@ interface SymbolConstructor { readonly asyncIterator: unique symbol; } -interface AsyncIterator { +interface AsyncIterator { // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places. - next(...args: [] | [TNext]): Promise>; + next(...[value]: [] | [TNext]): Promise>; return?(value?: TReturn | PromiseLike): Promise>; throw?(e?: any): Promise>; } -interface AsyncIterable { - [Symbol.asyncIterator](): AsyncIterator; +interface AsyncIterable { + [Symbol.asyncIterator](): AsyncIterator; } -interface AsyncIterableIterator extends AsyncIterator { - [Symbol.asyncIterator](): AsyncIterableIterator; +/** + * Describes a user-defined {@link AsyncIterator} that is also async iterable. + */ +interface AsyncIterableIterator extends AsyncIterator { + [Symbol.asyncIterator](): AsyncIterableIterator; +} + +/** + * Describes an {@link AsyncIterator} produced by the runtime that inherits from the intrinsic `AsyncIterator.prototype`. + */ +interface AsyncIteratorObject extends AsyncIterator { + [Symbol.asyncIterator](): AsyncIteratorObject; } diff --git a/cli/tsc/dts/lib.es2020.bigint.d.ts b/cli/tsc/dts/lib.es2020.bigint.d.ts index 4b8939601b..9997ac0003 100644 --- a/cli/tsc/dts/lib.es2020.bigint.d.ts +++ b/cli/tsc/dts/lib.es2020.bigint.d.ts @@ -171,7 +171,7 @@ interface BigInt64Array { copyWithin(target: number, start: number, end?: number): this; /** Yields index, value pairs for every entry in the array. */ - entries(): IterableIterator<[number, bigint]>; + entries(): ArrayIterator<[number, bigint]>; /** * Determines whether all the members of an array satisfy the specified test. @@ -256,7 +256,7 @@ interface BigInt64Array { join(separator?: string): string; /** Yields each index in the array. */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns the index of the last occurrence of a value in an array. @@ -378,9 +378,9 @@ interface BigInt64Array { valueOf(): BigInt64Array; /** Yields each value in the array. */ - values(): IterableIterator; + values(): ArrayIterator; - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; readonly [Symbol.toStringTag]: "BigInt64Array"; @@ -443,7 +443,7 @@ interface BigUint64Array { copyWithin(target: number, start: number, end?: number): this; /** Yields index, value pairs for every entry in the array. */ - entries(): IterableIterator<[number, bigint]>; + entries(): ArrayIterator<[number, bigint]>; /** * Determines whether all the members of an array satisfy the specified test. @@ -528,7 +528,7 @@ interface BigUint64Array { join(separator?: string): string; /** Yields each index in the array. */ - keys(): IterableIterator; + keys(): ArrayIterator; /** * Returns the index of the last occurrence of a value in an array. @@ -650,9 +650,9 @@ interface BigUint64Array { valueOf(): BigUint64Array; /** Yields each value in the array. */ - values(): IterableIterator; + values(): ArrayIterator; - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; readonly [Symbol.toStringTag]: "BigUint64Array"; diff --git a/cli/tsc/dts/lib.es2020.string.d.ts b/cli/tsc/dts/lib.es2020.string.d.ts index 17c15806ed..cdb38e0d86 100644 --- a/cli/tsc/dts/lib.es2020.string.d.ts +++ b/cli/tsc/dts/lib.es2020.string.d.ts @@ -16,7 +16,7 @@ and limitations under the License. /// -/// +/// interface String { /** @@ -24,7 +24,7 @@ interface String { * containing the results of that search. * @param regexp A variable name or string literal containing the regular expression pattern and flags. */ - matchAll(regexp: RegExp): IterableIterator; + matchAll(regexp: RegExp): RegExpStringIterator; /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */ toLocaleLowerCase(locales?: Intl.LocalesArgument): string; diff --git a/cli/tsc/dts/lib.es2020.symbol.wellknown.d.ts b/cli/tsc/dts/lib.es2020.symbol.wellknown.d.ts index 89262b74c9..a3b45bb8a9 100644 --- a/cli/tsc/dts/lib.es2020.symbol.wellknown.d.ts +++ b/cli/tsc/dts/lib.es2020.symbol.wellknown.d.ts @@ -27,11 +27,15 @@ interface SymbolConstructor { readonly matchAll: unique symbol; } +interface RegExpStringIterator extends IteratorObject { + [Symbol.iterator](): RegExpStringIterator; +} + interface RegExp { /** * Matches a string with this regular expression, and returns an iterable of matches * containing the results of that search. * @param string A string to search within. */ - [Symbol.matchAll](str: string): IterableIterator; + [Symbol.matchAll](str: string): RegExpStringIterator; } diff --git a/cli/tsc/dts/lib.es2022.intl.d.ts b/cli/tsc/dts/lib.es2022.intl.d.ts index 6a2ba07870..cd8eb11408 100644 --- a/cli/tsc/dts/lib.es2022.intl.d.ts +++ b/cli/tsc/dts/lib.es2022.intl.d.ts @@ -46,6 +46,10 @@ declare namespace Intl { granularity: "grapheme" | "word" | "sentence"; } + interface SegmentIterator extends IteratorObject { + [Symbol.iterator](): SegmentIterator; + } + interface Segments { /** * Returns an object describing the segment in the original string that includes the code unit at a specified index. @@ -55,7 +59,7 @@ declare namespace Intl { containing(codeUnitIndex?: number): SegmentData; /** Returns an iterator to iterate over the segments. */ - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): SegmentIterator; } interface SegmentData { diff --git a/cli/tsc/dts/lib.es2023.array.d.ts b/cli/tsc/dts/lib.es2023.array.d.ts index bd4db2ceb9..57362da53c 100644 --- a/cli/tsc/dts/lib.es2023.array.d.ts +++ b/cli/tsc/dts/lib.es2023.array.d.ts @@ -203,7 +203,7 @@ interface Int8Array { /** * Copies the array and returns the copy with the elements in reverse order. */ - toReversed(): Uint8Array; + toReversed(): Int8Array; /** * Copies and sorts the array. @@ -211,11 +211,11 @@ interface Int8Array { * a negative value if the first argument is less than the second argument, zero if they're equal, and a positive * value otherwise. If omitted, the elements are sorted in ascending order. * ```ts - * const myNums = Uint8Array.from([11, 2, 22, 1]); - * myNums.toSorted((a, b) => a - b) // Uint8Array(4) [1, 2, 11, 22] + * const myNums = Int8Array.from([11, 2, 22, 1]); + * myNums.toSorted((a, b) => a - b) // Int8Array(4) [1, 2, 11, 22] * ``` */ - toSorted(compareFn?: (a: number, b: number) => number): Uint8Array; + toSorted(compareFn?: (a: number, b: number) => number): Int8Array; /** * Copies the array and inserts the given number at the provided index. @@ -224,7 +224,7 @@ interface Int8Array { * @param value The value to insert into the copied array. * @returns A copy of the original array with the inserted value. */ - with(index: number, value: number): Uint8Array; + with(index: number, value: number): Int8Array; } interface Uint8Array { diff --git a/cli/tsc/dts/lib.esnext.d.ts b/cli/tsc/dts/lib.esnext.d.ts index a2912fe3d8..e0217b6c60 100644 --- a/cli/tsc/dts/lib.esnext.d.ts +++ b/cli/tsc/dts/lib.esnext.d.ts @@ -26,3 +26,4 @@ and limitations under the License. /// /// /// +/// diff --git a/cli/tsc/dts/lib.esnext.disposable.d.ts b/cli/tsc/dts/lib.esnext.disposable.d.ts index 0fea9442a0..b169d962e7 100644 --- a/cli/tsc/dts/lib.esnext.disposable.d.ts +++ b/cli/tsc/dts/lib.esnext.disposable.d.ts @@ -17,6 +17,8 @@ and limitations under the License. /// /// +/// +/// interface SymbolConstructor { /** @@ -183,3 +185,9 @@ interface AsyncDisposableStackConstructor { readonly prototype: AsyncDisposableStack; } declare var AsyncDisposableStack: AsyncDisposableStackConstructor; + +interface IteratorObject extends Disposable { +} + +interface AsyncIteratorObject extends AsyncDisposable { +} diff --git a/cli/tsc/dts/lib.esnext.iterator.d.ts b/cli/tsc/dts/lib.esnext.iterator.d.ts new file mode 100644 index 0000000000..9833442792 --- /dev/null +++ b/cli/tsc/dts/lib.esnext.iterator.d.ts @@ -0,0 +1,148 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +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 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + + +/// + +/// + +// NOTE: This is specified as what is essentially an unreachable module. All actual global declarations can be found +// in the `declare global` section, below. This is necessary as there is currently no way to declare an `abstract` +// member without declaring a `class`, but declaring `class Iterator` globally would conflict with TypeScript's +// general purpose `Iterator` interface. +export {}; + +// Abstract type that allows us to mark `next` as `abstract` +declare abstract class Iterator { // eslint-disable-line @typescript-eslint/no-unsafe-declaration-merging + abstract next(value?: TNext): IteratorResult; +} + +// Merge all members of `IteratorObject` into `Iterator` +interface Iterator extends globalThis.IteratorObject {} + +// Capture the `Iterator` constructor in a type we can use in the `extends` clause of `IteratorConstructor`. +type IteratorObjectConstructor = typeof Iterator; + +declare global { + // Global `IteratorObject` interface that can be augmented by polyfills + interface IteratorObject { + /** + * Returns this iterator. + */ + [Symbol.iterator](): IteratorObject; + + /** + * Creates an iterator whose values are the result of applying the callback to the values from this iterator. + * @param callbackfn A function that accepts up to two arguments to be used to transform values from the underlying iterator. + */ + map(callbackfn: (value: T, index: number) => U): IteratorObject; + + /** + * Creates an iterator whose values are those from this iterator for which the provided predicate returns true. + * @param predicate A function that accepts up to two arguments to be used to test values from the underlying iterator. + */ + filter(predicate: (value: T, index: number) => value is S): IteratorObject; + + /** + * Creates an iterator whose values are those from this iterator for which the provided predicate returns true. + * @param predicate A function that accepts up to two arguments to be used to test values from the underlying iterator. + */ + filter(predicate: (value: T, index: number) => unknown): IteratorObject; + + /** + * Creates an iterator whose values are the values from this iterator, stopping once the provided limit is reached. + * @param limit The maximum number of values to yield. + */ + take(limit: number): IteratorObject; + + /** + * Creates an iterator whose values are the values from this iterator after skipping the provided count. + * @param count The number of values to drop. + */ + drop(count: number): IteratorObject; + + /** + * Creates an iterator whose values are the result of applying the callback to the values from this iterator and then flattening the resulting iterators or iterables. + * @param callback A function that accepts up to two arguments to be used to transform values from the underlying iterator into new iterators or iterables to be flattened into the result. + */ + flatMap(callback: (value: T, index: number) => Iterator | Iterable): IteratorObject; + + /** + * Calls the specified callback function for all the elements in this iterator. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. + * @param callbackfn A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the iterator. + * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of a value from the iterator. + */ + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T): T; + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T, initialValue: T): T; + + /** + * Calls the specified callback function for all the elements in this iterator. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. + * @param callbackfn A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the iterator. + * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of a value from the iterator. + */ + reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U; + + /** + * Creates a new array from the values yielded by this iterator. + */ + toArray(): T[]; + + /** + * Performs the specified action for each element in the iterator. + * @param callbackfn A function that accepts up to two arguments. forEach calls the callbackfn function one time for each element in the iterator. + */ + forEach(callbackfn: (value: T, index: number) => void): void; + + /** + * Determines whether the specified callback function returns true for any element of this iterator. + * @param predicate A function that accepts up to two arguments. The some method calls + * the predicate function for each element in this iterator until the predicate returns a value + * true, or until the end of the iterator. + */ + some(predicate: (value: T, index: number) => unknown): boolean; + + /** + * Determines whether all the members of this iterator satisfy the specified test. + * @param predicate A function that accepts up to two arguments. The every method calls + * the predicate function for each element in this iterator until the predicate returns + * false, or until the end of this iterator. + */ + every(predicate: (value: T, index: number) => unknown): boolean; + + /** + * Returns the value of the first element in this iterator where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of this iterator, in + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + */ + find(predicate: (value: T, index: number) => value is S): S | undefined; + find(predicate: (value: T, index: number) => unknown): T | undefined; + + readonly [Symbol.toStringTag]: string; + } + + // Global `IteratorConstructor` interface that can be augmented by polyfills + interface IteratorConstructor extends IteratorObjectConstructor { + /** + * Creates a native iterator from an iterator or iterable object. + * Returns its input if the input already inherits from the built-in Iterator class. + * @param value An iterator or iterable object to convert a native iterator. + */ + from(value: Iterator | Iterable): IteratorObject; + } + + var Iterator: IteratorConstructor; +} diff --git a/cli/tsc/dts/lib.webworker.asynciterable.d.ts b/cli/tsc/dts/lib.webworker.asynciterable.d.ts index 86de21097f..4c7aaadc6a 100644 --- a/cli/tsc/dts/lib.webworker.asynciterable.d.ts +++ b/cli/tsc/dts/lib.webworker.asynciterable.d.ts @@ -20,14 +20,22 @@ and limitations under the License. /// Worker Async Iterable APIs ///////////////////////////// +interface FileSystemDirectoryHandleAsyncIterator extends AsyncIteratorObject { + [Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator; +} + interface FileSystemDirectoryHandle { - [Symbol.asyncIterator](): AsyncIterableIterator<[string, FileSystemHandle]>; - entries(): AsyncIterableIterator<[string, FileSystemHandle]>; - keys(): AsyncIterableIterator; - values(): AsyncIterableIterator; + [Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>; + entries(): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>; + keys(): FileSystemDirectoryHandleAsyncIterator; + values(): FileSystemDirectoryHandleAsyncIterator; +} + +interface ReadableStreamAsyncIterator extends AsyncIteratorObject { + [Symbol.asyncIterator](): ReadableStreamAsyncIterator; } interface ReadableStream { - [Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): AsyncIterableIterator; - values(options?: ReadableStreamIteratorOptions): AsyncIterableIterator; + [Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator; + values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator; } diff --git a/cli/tsc/dts/lib.webworker.d.ts b/cli/tsc/dts/lib.webworker.d.ts index 8b281e9ca6..f0c5b32000 100644 --- a/cli/tsc/dts/lib.webworker.d.ts +++ b/cli/tsc/dts/lib.webworker.d.ts @@ -340,10 +340,6 @@ interface ImageEncodeOptions { type?: string; } -interface ImportMeta { - url: string; -} - interface JsonWebKey { alg?: string; crv?: string; @@ -414,6 +410,10 @@ interface MediaEncodingConfiguration extends MediaConfiguration { type: MediaEncodingType; } +interface MediaStreamTrackProcessorInit { + maxBufferSize?: number; +} + interface MessageEventInit extends EventInit { data?: T; lastEventId?: string; @@ -717,16 +717,11 @@ interface TextEncoderEncodeIntoResult { written: number; } -interface TransformerCancelCallback { - (reason: any): void | PromiseLike; -} - interface Transformer { flush?: TransformerFlushCallback; readableType?: undefined; start?: TransformerStartCallback; transform?: TransformerTransformCallback; - cancel?: TransformerCancelCallback; writableType?: undefined; } @@ -1676,6 +1671,8 @@ interface CanvasShadowStyles { } interface CanvasState { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/isContextLost) */ + isContextLost(): boolean; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/reset) */ reset(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/restore) */ @@ -1812,8 +1809,6 @@ declare var CloseEvent: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream) */ interface CompressionStream extends GenericTransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; } declare var CompressionStream: { @@ -2011,9 +2006,7 @@ interface DOMMatrix extends DOMMatrixReadOnly { rotateAxisAngleSelf(x?: number, y?: number, z?: number, angle?: number): DOMMatrix; rotateFromVectorSelf(x?: number, y?: number): DOMMatrix; rotateSelf(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scale3dSelf) */ scale3dSelf(scale?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scaleSelf) */ scaleSelf(scaleX?: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; skewXSelf(sx?: number): DOMMatrix; skewYSelf(sy?: number): DOMMatrix; @@ -2030,88 +2023,48 @@ declare var DOMMatrix: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly) */ interface DOMMatrixReadOnly { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/a) */ readonly a: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/b) */ readonly b: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/c) */ readonly c: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/d) */ readonly d: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/e) */ readonly e: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/f) */ readonly f: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/is2D) */ readonly is2D: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/isIdentity) */ readonly isIdentity: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m11) */ readonly m11: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m12) */ readonly m12: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m13) */ readonly m13: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m14) */ readonly m14: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m21) */ readonly m21: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m22) */ readonly m22: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m23) */ readonly m23: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m24) */ readonly m24: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m31) */ readonly m31: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m32) */ readonly m32: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m33) */ readonly m33: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m34) */ readonly m34: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m41) */ readonly m41: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m42) */ readonly m42: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m43) */ readonly m43: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/m44) */ readonly m44: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipX) */ flipX(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipY) */ flipY(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/inverse) */ inverse(): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/multiply) */ multiply(other?: DOMMatrixInit): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotate) */ rotate(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateAxisAngle) */ rotateAxisAngle(x?: number, y?: number, z?: number, angle?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateFromVector) */ rotateFromVector(x?: number, y?: number): DOMMatrix; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale) */ scale(scaleX?: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale3d) */ scale3d(scale?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scaleNonUniform) - */ + /** @deprecated */ scaleNonUniform(scaleX?: number, scaleY?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewX) */ skewX(sx?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewY) */ skewY(sy?: number): DOMMatrix; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat32Array) */ toFloat32Array(): Float32Array; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat64Array) */ toFloat64Array(): Float64Array; toJSON(): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/transformPoint) */ transformPoint(point?: DOMPointInit): DOMPoint; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/translate) */ translate(tx?: number, ty?: number, tz?: number): DOMMatrix; @@ -2154,7 +2107,6 @@ interface DOMPointReadOnly { readonly y: number; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/z) */ readonly z: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/matrixTransform) */ matrixTransform(matrix?: DOMMatrixInit): DOMPoint; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/toJSON) */ toJSON(): any; @@ -2169,15 +2121,10 @@ declare var DOMPointReadOnly: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad) */ interface DOMQuad { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p1) */ readonly p1: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p2) */ readonly p2: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p3) */ readonly p3: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p4) */ readonly p4: DOMPoint; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/getBounds) */ getBounds(): DOMRect; toJSON(): any; } @@ -2200,6 +2147,7 @@ interface DOMRect extends DOMRectReadOnly { declare var DOMRect: { prototype: DOMRect; new(x?: number, y?: number, width?: number, height?: number): DOMRect; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/fromRect_static) */ fromRect(other?: DOMRectInit): DOMRect; }; @@ -2265,8 +2213,6 @@ declare var DOMStringList: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DecompressionStream) */ interface DecompressionStream extends GenericTransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; } declare var DecompressionStream: { @@ -2427,15 +2373,10 @@ declare var EncodedVideoChunk: { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent) */ interface ErrorEvent extends Event { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/colno) */ readonly colno: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/error) */ readonly error: any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/filename) */ readonly filename: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/lineno) */ readonly lineno: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ErrorEvent/message) */ readonly message: string; } @@ -3091,7 +3032,9 @@ declare var FormData: { }; interface GenericTransformStream { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream/readable) */ readonly readable: ReadableStream; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CompressionStream/writable) */ readonly writable: WritableStream; } @@ -3750,7 +3693,7 @@ interface IDBTransaction extends EventTarget { /** * Returns a list of the names of object stores in the transaction's scope. For an upgrade transaction this is all object stores in the database. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/objectStoreNames) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/ObjectStoreNames) */ readonly objectStoreNames: DOMStringList; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/IDBTransaction/abort_event) */ @@ -3877,6 +3820,11 @@ declare var ImageData: { new(data: Uint8ClampedArray, sw: number, sh?: number, settings?: ImageDataSettings): ImageData; }; +interface ImportMeta { + url: string; + resolve(specifier: string): string; +} + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/KHR_parallel_shader_compile) */ interface KHR_parallel_shader_compile { readonly COMPLETION_STATUS_KHR: 0x91B1; @@ -3930,6 +3878,26 @@ declare var MediaCapabilities: { new(): MediaCapabilities; }; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaSourceHandle) */ +interface MediaSourceHandle { +} + +declare var MediaSourceHandle: { + prototype: MediaSourceHandle; + new(): MediaSourceHandle; +}; + +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaStreamTrackProcessor) */ +interface MediaStreamTrackProcessor { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaStreamTrackProcessor/readable) */ + readonly readable: ReadableStream; +} + +declare var MediaStreamTrackProcessor: { + prototype: MediaStreamTrackProcessor; + new(init: MediaStreamTrackProcessorInit): MediaStreamTrackProcessor; +}; + /** * This Channel Messaging API interface allows us to create a new message channel and send data through it via its two MessagePort properties. * @@ -3991,11 +3959,7 @@ interface MessageEvent extends Event { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/source) */ readonly source: MessageEventSource | null; - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/initMessageEvent) - */ + /** @deprecated */ initMessageEvent(type: string, bubbles?: boolean, cancelable?: boolean, data?: any, origin?: string, lastEventId?: string, source?: MessageEventSource | null, ports?: MessagePort[]): void; } @@ -4327,7 +4291,9 @@ interface OffscreenCanvas extends EventTarget { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/height) */ height: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/contextlost_event) */ oncontextlost: ((this: OffscreenCanvas, ev: Event) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvas/contextrestored_event) */ oncontextrestored: ((this: OffscreenCanvas, ev: Event) => any) | null; /** * These attributes return the dimensions of the OffscreenCanvas object's bitmap. @@ -4379,8 +4345,6 @@ declare var OffscreenCanvas: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvasRenderingContext2D) */ interface OffscreenCanvasRenderingContext2D extends CanvasCompositing, CanvasDrawImage, CanvasDrawPath, CanvasFillStrokeStyles, CanvasFilters, CanvasImageData, CanvasImageSmoothing, CanvasPath, CanvasPathDrawingStyles, CanvasRect, CanvasShadowStyles, CanvasState, CanvasText, CanvasTextDrawingStyles, CanvasTransform { readonly canvas: OffscreenCanvas; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/OffscreenCanvasRenderingContext2D/commit) */ - commit(): void; } declare var OffscreenCanvasRenderingContext2D: { @@ -4885,24 +4849,19 @@ declare var ReadableStream: { new(underlyingSource: UnderlyingByteSource, strategy?: { highWaterMark?: number }): ReadableStream; new(underlyingSource: UnderlyingDefaultSource, strategy?: QueuingStrategy): ReadableStream; new(underlyingSource?: UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - from(asyncIterable: AsyncIterable | Iterable>): ReadableStream; }; -interface ReadableStreamBYOBReaderReadOptions { - min?: number; -} - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader) */ interface ReadableStreamBYOBReader extends ReadableStreamGenericReader { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader/read) */ - read(view: T, options?: ReadableStreamBYOBReaderReadOptions): Promise>; + read(view: T): Promise>; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader/releaseLock) */ releaseLock(): void; } declare var ReadableStreamBYOBReader: { prototype: ReadableStreamBYOBReader; - new(stream: ReadableStream): ReadableStreamBYOBReader; + new(stream: ReadableStream): ReadableStreamBYOBReader; }; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBRequest) */ @@ -4975,6 +4934,7 @@ declare var Report: { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReportBody) */ interface ReportBody { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ReportBody/toJSON) */ toJSON(): any; } @@ -5034,11 +4994,7 @@ interface Request extends Body { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/integrity) */ readonly integrity: string; - /** - * Returns a boolean indicating whether or not request can outlive the global in which it was created. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/keepalive) - */ + /** Returns a boolean indicating whether or not request can outlive the global in which it was created. */ readonly keepalive: boolean; /** * Returns request's HTTP method, which is "GET" by default. @@ -5407,7 +5363,7 @@ declare var StylePropertyMapReadOnly: { }; /** - * This Web Crypto API interface provides a number of low-level cryptographic functions. It is accessed via the Crypto.subtle properties available in a window context (via Window.crypto). + * This Web Crypto API interface provides a number of low-level cryptographic functions. It is accessed via the Crypto.subtle properties available in a window context (via globalThis.crypto). * Available only in secure contexts. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto) @@ -5802,6 +5758,7 @@ interface VideoDecoderEventMap { interface VideoDecoder extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/decodeQueueSize) */ readonly decodeQueueSize: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/dequeue_event) */ ondequeue: ((this: VideoDecoder, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/state) */ readonly state: CodecState; @@ -5824,6 +5781,7 @@ interface VideoDecoder extends EventTarget { declare var VideoDecoder: { prototype: VideoDecoder; new(init: VideoDecoderInit): VideoDecoder; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoDecoder/isConfigSupported_static) */ isConfigSupported(config: VideoDecoderConfig): Promise; }; @@ -5839,6 +5797,7 @@ interface VideoEncoderEventMap { interface VideoEncoder extends EventTarget { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/encodeQueueSize) */ readonly encodeQueueSize: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/dequeue_event) */ ondequeue: ((this: VideoEncoder, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/state) */ readonly state: CodecState; @@ -5848,6 +5807,7 @@ interface VideoEncoder extends EventTarget { configure(config: VideoEncoderConfig): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/encode) */ encode(frame: VideoFrame, options?: VideoEncoderEncodeOptions): void; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/flush) */ flush(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/reset) */ reset(): void; @@ -5860,6 +5820,7 @@ interface VideoEncoder extends EventTarget { declare var VideoEncoder: { prototype: VideoEncoder; new(init: VideoEncoderInit): VideoEncoder; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoEncoder/isConfigSupported_static) */ isConfigSupported(config: VideoEncoderConfig): Promise; }; @@ -5891,6 +5852,7 @@ interface VideoFrame { clone(): VideoFrame; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoFrame/close) */ close(): void; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/VideoFrame/copyTo) */ copyTo(destination: AllowSharedBufferSource, options?: VideoFrameCopyToOptions): Promise; } @@ -6668,7 +6630,7 @@ interface WebGL2RenderingContextBase { clearBufferuiv(buffer: GLenum, drawbuffer: GLint, values: Uint32List, srcOffset?: number): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/clientWaitSync) */ clientWaitSync(sync: WebGLSync, flags: GLbitfield, timeout: GLuint64): GLenum; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/compressedTexImage3D) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/compressedTexImage2D) */ compressedTexImage3D(target: GLenum, level: GLint, internalformat: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, imageSize: GLsizei, offset: GLintptr): void; compressedTexImage3D(target: GLenum, level: GLint, internalformat: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, srcData: ArrayBufferView, srcOffset?: number, srcLengthOverride?: GLuint): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGL2RenderingContext/compressedTexSubImage3D) */ @@ -7549,6 +7511,7 @@ declare var WebGLRenderingContext: { }; interface WebGLRenderingContextBase { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/drawingBufferColorSpace) */ drawingBufferColorSpace: PredefinedColorSpace; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLRenderingContext/drawingBufferHeight) */ readonly drawingBufferHeight: GLsizei; @@ -8258,7 +8221,7 @@ declare var WebGLVertexArrayObject: { new(): WebGLVertexArrayObject; }; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLVertexArrayObjectOES) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WebGLVertexArrayObject) */ interface WebGLVertexArrayObjectOES { } @@ -8469,24 +8432,24 @@ interface WindowOrWorkerGlobalScope { /** * Available only in secure contexts. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/caches) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/caches) */ readonly caches: CacheStorage; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crossOriginIsolated) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crossOriginIsolated) */ readonly crossOriginIsolated: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crypto_property) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto) */ readonly crypto: Crypto; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/indexedDB) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/indexedDB) */ readonly indexedDB: IDBFactory; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/isSecureContext) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/isSecureContext) */ readonly isSecureContext: boolean; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/origin) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/origin) */ readonly origin: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/performance_property) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/performance) */ readonly performance: Performance; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/atob) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */ atob(data: string): string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/btoa) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */ btoa(data: string): string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/clearInterval) */ clearInterval(id: number | undefined): void; @@ -8583,7 +8546,9 @@ interface WorkerGlobalScope extends EventTarget, FontFaceSource, WindowOrWorkerG onoffline: ((this: WorkerGlobalScope, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/online_event) */ ononline: ((this: WorkerGlobalScope, ev: Event) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/rejectionhandled_event) */ onrejectionhandled: ((this: WorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/unhandledrejection_event) */ onunhandledrejection: ((this: WorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null; /** * Returns workerGlobal. @@ -8917,7 +8882,7 @@ interface Console { clear(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/count_static) */ count(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countReset_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countreset_static) */ countReset(label?: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/debug_static) */ debug(...data: any[]): void; @@ -8929,9 +8894,9 @@ interface Console { error(...data: any[]): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/group_static) */ group(...data: any[]): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupCollapsed_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupcollapsed_static) */ groupCollapsed(...data: any[]): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupEnd_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupend_static) */ groupEnd(): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/info_static) */ info(...data: any[]): void; @@ -8941,9 +8906,9 @@ interface Console { table(tabularData?: any, properties?: string[]): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/time_static) */ time(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeEnd_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeend_static) */ timeEnd(label?: string): void; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeLog_static) */ + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timelog_static) */ timeLog(label?: string, ...data: any[]): void; timeStamp(label?: string): void; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/trace_static) */ @@ -8966,9 +8931,7 @@ declare namespace WebAssembly { /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global) */ interface Global { - /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global/value) */ value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/WebAssembly/JavaScript_interface/Global/valueOf) */ valueOf(): ValueTypeMap[T]; } @@ -9246,7 +9209,9 @@ declare var onlanguagechange: ((this: DedicatedWorkerGlobalScope, ev: Event) => declare var onoffline: ((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/online_event) */ declare var ononline: ((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/rejectionhandled_event) */ declare var onrejectionhandled: ((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null; +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/WorkerGlobalScope/unhandledrejection_event) */ declare var onunhandledrejection: ((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null; /** * Returns workerGlobal. @@ -9271,24 +9236,24 @@ declare var fonts: FontFaceSet; /** * Available only in secure contexts. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/caches) + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/caches) */ declare var caches: CacheStorage; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crossOriginIsolated) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crossOriginIsolated) */ declare var crossOriginIsolated: boolean; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/crypto_property) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto) */ declare var crypto: Crypto; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/indexedDB) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/indexedDB) */ declare var indexedDB: IDBFactory; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/isSecureContext) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/isSecureContext) */ declare var isSecureContext: boolean; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/origin) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/origin) */ declare var origin: string; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/performance_property) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/performance) */ declare var performance: Performance; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/atob) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */ declare function atob(data: string): string; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/btoa) */ +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */ declare function btoa(data: string): string; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/clearInterval) */ declare function clearInterval(id: number | undefined): void; @@ -9365,7 +9330,7 @@ type ReportList = Report[]; type RequestInfo = Request | string; type TexImageSource = ImageBitmap | ImageData | OffscreenCanvas | VideoFrame; type TimerHandler = string | Function; -type Transferable = OffscreenCanvas | ImageBitmap | MessagePort | ReadableStream | WritableStream | TransformStream | VideoFrame | ArrayBuffer; +type Transferable = OffscreenCanvas | ImageBitmap | MessagePort | MediaSourceHandle | ReadableStream | WritableStream | TransformStream | VideoFrame | ArrayBuffer; type Uint32List = Uint32Array | GLuint[]; type XMLHttpRequestBodyInit = Blob | BufferSource | FormData | URLSearchParams | string; type AlphaOption = "discard" | "keep"; diff --git a/cli/tsc/dts/lib.webworker.iterable.d.ts b/cli/tsc/dts/lib.webworker.iterable.d.ts index 4f53ad5e08..be864068e7 100644 --- a/cli/tsc/dts/lib.webworker.iterable.d.ts +++ b/cli/tsc/dts/lib.webworker.iterable.d.ts @@ -26,24 +26,24 @@ interface AbortSignal { } interface CSSNumericArray { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSNumericValue]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSNumericValue]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface CSSTransformValue { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSTransformComponent]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSTransformComponent]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface CSSUnparsedValue { - [Symbol.iterator](): IterableIterator; - entries(): IterableIterator<[number, CSSUnparsedSegment]>; - keys(): IterableIterator; - values(): IterableIterator; + [Symbol.iterator](): ArrayIterator; + entries(): ArrayIterator<[number, CSSUnparsedSegment]>; + keys(): ArrayIterator; + values(): ArrayIterator; } interface Cache { @@ -62,34 +62,42 @@ interface CanvasPathDrawingStyles { } interface DOMStringList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface FileList { - [Symbol.iterator](): IterableIterator; + [Symbol.iterator](): ArrayIterator; } interface FontFaceSet extends Set { } +interface FormDataIterator extends IteratorObject { + [Symbol.iterator](): FormDataIterator; +} + interface FormData { - [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>; + [Symbol.iterator](): FormDataIterator<[string, FormDataEntryValue]>; /** Returns an array of key, value pairs for every entry in the list. */ - entries(): IterableIterator<[string, FormDataEntryValue]>; + entries(): FormDataIterator<[string, FormDataEntryValue]>; /** Returns a list of keys in the list. */ - keys(): IterableIterator; + keys(): FormDataIterator; /** Returns a list of values in the list. */ - values(): IterableIterator; + values(): FormDataIterator; +} + +interface HeadersIterator extends IteratorObject { + [Symbol.iterator](): HeadersIterator; } interface Headers { - [Symbol.iterator](): IterableIterator<[string, string]>; + [Symbol.iterator](): HeadersIterator<[string, string]>; /** Returns an iterator allowing to go through all key/value pairs contained in this object. */ - entries(): IterableIterator<[string, string]>; + entries(): HeadersIterator<[string, string]>; /** Returns an iterator allowing to go through all keys of the key/value pairs contained in this object. */ - keys(): IterableIterator; + keys(): HeadersIterator; /** Returns an iterator allowing to go through all values of the key/value pairs contained in this object. */ - values(): IterableIterator; + values(): HeadersIterator; } interface IDBDatabase { @@ -113,19 +121,19 @@ interface IDBObjectStore { } interface MessageEvent { - /** - * @deprecated - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/initMessageEvent) - */ + /** @deprecated */ initMessageEvent(type: string, bubbles?: boolean, cancelable?: boolean, data?: any, origin?: string, lastEventId?: string, source?: MessageEventSource | null, ports?: Iterable): void; } +interface StylePropertyMapReadOnlyIterator extends IteratorObject { + [Symbol.iterator](): StylePropertyMapReadOnlyIterator; +} + interface StylePropertyMapReadOnly { - [Symbol.iterator](): IterableIterator<[string, Iterable]>; - entries(): IterableIterator<[string, Iterable]>; - keys(): IterableIterator; - values(): IterableIterator>; + [Symbol.iterator](): StylePropertyMapReadOnlyIterator<[string, Iterable]>; + entries(): StylePropertyMapReadOnlyIterator<[string, Iterable]>; + keys(): StylePropertyMapReadOnlyIterator; + values(): StylePropertyMapReadOnlyIterator>; } interface SubtleCrypto { @@ -143,14 +151,18 @@ interface SubtleCrypto { unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: Iterable): Promise; } +interface URLSearchParamsIterator extends IteratorObject { + [Symbol.iterator](): URLSearchParamsIterator; +} + interface URLSearchParams { - [Symbol.iterator](): IterableIterator<[string, string]>; + [Symbol.iterator](): URLSearchParamsIterator<[string, string]>; /** Returns an array of key, value pairs for every entry in the search params. */ - entries(): IterableIterator<[string, string]>; + entries(): URLSearchParamsIterator<[string, string]>; /** Returns a list of keys in the search params. */ - keys(): IterableIterator; + keys(): URLSearchParamsIterator; /** Returns a list of values in the search params. */ - values(): IterableIterator; + values(): URLSearchParamsIterator; } interface WEBGL_draw_buffers { diff --git a/cli/tsc/dts/typescript.d.ts b/cli/tsc/dts/typescript.d.ts index 882767d3cb..5326c98dd0 100644 --- a/cli/tsc/dts/typescript.d.ts +++ b/cli/tsc/dts/typescript.d.ts @@ -214,6 +214,22 @@ declare namespace ts { * The time spent creating or updating the auto-import program, in milliseconds. */ createAutoImportProviderProgramDurationMs?: number; + /** + * The time spent computing diagnostics, in milliseconds. + */ + diagnosticsDuration?: FileDiagnosticPerformanceData[]; + } + /** + * Time spent computing each kind of diagnostics, in milliseconds. + */ + export type DiagnosticPerformanceData = { + [Kind in DiagnosticEventKind]?: number; + }; + export interface FileDiagnosticPerformanceData extends DiagnosticPerformanceData { + /** + * The file for which the performance data is reported. + */ + file: string; } /** * Arguments for FileRequest messages. @@ -584,23 +600,7 @@ declare namespace ts { } export interface ApplyCodeActionCommandResponse extends Response { } - export interface FileRangeRequestArgs extends FileRequestArgs { - /** - * The line number for the request (1-based). - */ - startLine: number; - /** - * The character offset (on the line) for the request (1-based). - */ - startOffset: number; - /** - * The line number for the request (1-based). - */ - endLine: number; - /** - * The character offset (on the line) for the request (1-based). - */ - endOffset: number; + export interface FileRangeRequestArgs extends FileRequestArgs, FileRange { } /** * Instances of this interface specify errorcodes on a specific location in a sourcefile. @@ -1866,7 +1866,7 @@ declare namespace ts { * List of file names for which to compute compiler errors. * The files will be checked in list order. */ - files: string[]; + files: (string | FileRangesRequestArgs)[]; /** * Delay in milliseconds to wait before starting to compute * errors for the files in the file list @@ -1887,6 +1887,27 @@ declare namespace ts { command: CommandTypes.Geterr; arguments: GeterrRequestArgs; } + export interface FileRange { + /** + * The line number for the request (1-based). + */ + startLine: number; + /** + * The character offset (on the line) for the request (1-based). + */ + startOffset: number; + /** + * The line number for the request (1-based). + */ + endLine: number; + /** + * The character offset (on the line) for the request (1-based). + */ + endOffset: number; + } + export interface FileRangesRequestArgs extends Pick { + ranges: FileRange[]; + } export type RequestCompletedEventName = "requestCompleted"; /** * Event that is sent when server have finished processing request with specified id. @@ -1897,6 +1918,7 @@ declare namespace ts { } export interface RequestCompletedEventBody { request_seq: number; + performanceData?: PerformanceData; } /** * Item of diagnostic information found in a DiagnosticEvent message. @@ -1969,8 +1991,12 @@ declare namespace ts { * An array of diagnostic information items. */ diagnostics: Diagnostic[]; + /** + * Spans where the region diagnostic was requested, if this is a region semantic diagnostic event. + */ + spans?: TextSpan[]; } - export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag"; + export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag" | "regionSemanticDiag"; /** * Event message for DiagnosticEventKind event types. * These events provide syntactic and semantic errors for a file. @@ -2510,6 +2536,7 @@ declare namespace ts { private readonly knownCachesSet; private readonly projectWatchers; private safeList; + private pendingRunRequests; private installRunCount; private inFlightRequestCount; abstract readonly typesRegistry: Map>; @@ -2636,6 +2663,7 @@ declare namespace ts { interface ServerHost extends System { watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + preferNonRecursiveWatch?: boolean; setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; @@ -2644,6 +2672,18 @@ declare namespace ts { trace?(s: string): void; require?(initialPath: string, moduleName: string): ModuleImportResult; } + interface InstallPackageOptionsWithProject extends InstallPackageOptions { + projectName: string; + projectRootPath: Path; + } + interface ITypingsInstaller { + isKnownTypesPackageName(name: string): boolean; + installPackage(options: InstallPackageOptionsWithProject): Promise; + enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; + attach(projectService: ProjectService): void; + onProjectClosed(p: Project): void; + readonly globalTypingsCacheLocation: string | undefined; + } function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings; function toNormalizedPath(fileName: string): NormalizedPath; function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path; @@ -2702,6 +2742,7 @@ declare namespace ts { readonly containingProjects: Project[]; private formatSettings; private preferences; + private realpath; constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent: boolean, path: Path, initialVersion?: number); isScriptOpen(): boolean; open(newText: string | undefined): void; @@ -2735,19 +2776,6 @@ declare namespace ts { positionToLineOffset(position: number): protocol.Location; isJavaScript(): boolean; } - interface InstallPackageOptionsWithProject extends InstallPackageOptions { - projectName: string; - projectRootPath: Path; - } - interface ITypingsInstaller { - isKnownTypesPackageName(name: string): boolean; - installPackage(options: InstallPackageOptionsWithProject): Promise; - enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; - attach(projectService: ProjectService): void; - onProjectClosed(p: Project): void; - readonly globalTypingsCacheLocation: string | undefined; - } - const nullTypingsInstaller: ITypingsInstaller; function allRootFilesAreJsOrDts(project: Project): boolean; function allFilesAreJsOrDts(project: Project): boolean; enum ProjectKind { @@ -2789,33 +2817,31 @@ declare namespace ts { private externalFiles; private missingFilesMap; private generatedFilesMap; + private hasAddedorRemovedFiles; + private hasAddedOrRemovedSymlinks; protected languageService: LanguageService; languageServiceEnabled: boolean; readonly trace?: (s: string) => void; readonly realpath?: (path: string) => string; private builderState; - /** - * Set of files names that were updated since the last call to getChangesSinceVersion. - */ private updatedFileNames; - /** - * Set of files that was returned from the last call to getChangesSinceVersion. - */ private lastReportedFileNames; - /** - * Last version that was reported. - */ private lastReportedVersion; protected projectErrors: Diagnostic[] | undefined; protected isInitialLoadPending: () => boolean; + private typingsCache; + private typingWatchers; private readonly cancellationToken; isNonTsProject(): boolean; isJsOnlyProject(): boolean; static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined; + private exportMapCache; + private changedFilesForExportMapCache; + private moduleSpecifierCache; + private symlinks; readonly jsDocParsingMode: JSDocParsingMode | undefined; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; - private get typingsCache(); getCompilationSettings(): ts.CompilerOptions; getCompilerOptions(): ts.CompilerOptions; getNewLine(): string; @@ -2882,6 +2908,8 @@ declare namespace ts { * @returns: true if set of files in the project stays the same and false - otherwise. */ updateGraph(): boolean; + private closeWatchingTypingLocations; + private onTypingInstallerWatchInvoke; protected removeExistingTypings(include: string[]): string[]; private updateGraphWorker; private detachScriptInfoFromProject; @@ -2893,6 +2921,7 @@ declare namespace ts { getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined; getScriptInfo(uncheckedFileName: string): ts.server.ScriptInfo | undefined; filesToString(writeProjectFileNames: boolean): string; + private filesToStringWorker; setCompilerOptions(compilerOptions: CompilerOptions): void; setTypeAcquisition(newTypeAcquisition: TypeAcquisition | undefined): void; getTypeAcquisition(): ts.TypeAcquisition; @@ -2901,6 +2930,8 @@ declare namespace ts { protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]): void; /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */ refreshDiagnostics(): void; + private isDefaultProjectForOpenFiles; + private getCompilerOptionsForNoDtsResolutionProject; } /** * If a file is opened and no tsconfig (or jsconfig) is found, @@ -2920,6 +2951,7 @@ declare namespace ts { } class AutoImportProviderProject extends Project { private hostProject; + private static readonly maxDependencies; private rootFileNames; updateGraph(): boolean; hasRoots(): boolean; @@ -2936,6 +2968,8 @@ declare namespace ts { class ConfiguredProject extends Project { readonly canonicalConfigFilePath: NormalizedPath; private projectReferences; + private compilerHost?; + private releaseParsedConfig; /** * If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph * @returns: true if set of files in the project stays the same and false - otherwise. @@ -3126,6 +3160,7 @@ declare namespace ts { configFileName?: NormalizedPath; configFileErrors?: readonly Diagnostic[]; } + const nullTypingsInstaller: ITypingsInstaller; interface ProjectServiceOptions { host: ServerHost; logger: Logger; @@ -3151,16 +3186,8 @@ declare namespace ts { } class ProjectService { private readonly nodeModulesWatchers; - /** - * Contains all the deleted script info's version information so that - * it does not reset when creating script info again - * (and could have potentially collided with version where contents mismatch) - */ private readonly filenameToScriptInfoVersion; private readonly allJsFilesForOpenFileTelemetry; - /** - * maps external project file name to list of config files that were the part of this project - */ private readonly externalProjectToConfiguredProjectMap; /** * external projects (configuration and list of root files is not controlled by tsserver) @@ -3178,13 +3205,8 @@ declare namespace ts { * Open files: with value being project root path, and key being Path of the file that is open */ readonly openFiles: Map; - /** Config files looked up and cached config files for open script info */ private readonly configFileForOpenFiles; - /** Set of open script infos that are root of inferred project */ private rootOfInferredProjects; - /** - * Map of open files that are opened without complete path but have projectRoot as current directory - */ private readonly openFilesWithNonRootedDiskPath; private compilerOptionsForInferredProjects; private compilerOptionsForInferredProjectsPerProjectRoot; @@ -3192,18 +3214,11 @@ declare namespace ts { private watchOptionsForInferredProjectsPerProjectRoot; private typeAcquisitionForInferredProjects; private typeAcquisitionForInferredProjectsPerProjectRoot; - /** - * Project size for configured or external projects - */ private readonly projectToSizeMap; private readonly hostConfiguration; private safelist; private readonly legacySafelist; private pendingProjectUpdates; - /** - * All the open script info that needs recalculation of the default project, - * this also caches config file info before config file change was detected to use it in case projects are not updated yet - */ private pendingOpenFileProjectUpdates?; readonly currentDirectory: NormalizedPath; readonly toCanonicalFileName: (f: string) => string; @@ -3221,8 +3236,11 @@ declare namespace ts { readonly allowLocalPluginLoads: boolean; readonly typesMapLocation: string | undefined; readonly serverMode: LanguageServiceMode; - /** Tracks projects that we have already sent telemetry for. */ private readonly seenProjects; + private readonly sharedExtendedConfigFileWatchers; + private readonly extendedConfigCache; + private packageJsonFilesMap; + private incompleteCompletionsCache; private performanceEventHandler?; private pendingPluginEnablements?; private currentPluginEnablementPromise?; @@ -3236,20 +3254,9 @@ declare namespace ts { setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.InferredProjectCompilerOptions, projectRootPath?: string): void; findProject(projectName: string): Project | undefined; getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined; - /** - * If there is default project calculation pending for this file, - * then it completes that calculation so that correct default project is used for the project - */ private tryGetDefaultProjectForEnsuringConfiguredProjectForFile; private doEnsureDefaultProjectForFile; getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo | undefined; - /** - * Ensures the project structures are upto date - * This means, - * - we go through all the projects and update them if they are dirty - * - if updates reflect some change in structure or there was pending request to ensure projects for open files - * ensure that each open script info has project - */ private ensureProjectStructuresUptoDate; getFormatCodeOptions(file: NormalizedPath): FormatCodeSettings; getPreferences(file: NormalizedPath): protocol.UserPreferences; @@ -3260,37 +3267,30 @@ declare namespace ts { private delayUpdateSourceInfoProjects; private delayUpdateProjectsOfScriptInfoPath; private handleDeletedFile; + private watchWildcardDirectory; + private onWildCardDirectoryWatcherInvoke; + private delayUpdateProjectsFromParsedConfigOnConfigFileChange; + private onConfigFileChanged; private removeProject; private assignOrphanScriptInfosToInferredProject; - /** - * Remove this file from the set of open, non-configured files. - * @param info The file that has been closed or newly configured - */ private closeOpenFile; private deleteScriptInfo; private configFileExists; - /** - * This function tries to search for a tsconfig.json for the given file. - * This is different from the method the compiler uses because - * the compiler can assume it will always start searching in the - * current directory (the directory in which tsc was invoked). - * The server must start searching from the directory containing - * the newly opened file. - */ + private createConfigFileWatcherForParsedConfig; private forEachConfigFileLocation; - /** Get cached configFileName for scriptInfo or ancestor of open script info */ private getConfigFileNameForFileFromCache; - /** Caches the configFilename for script info or ancestor of open script info */ private setConfigFileNameForFileInCache; private printProjects; private getConfiguredProjectByCanonicalConfigFilePath; private findExternalProjectByProjectName; - /** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */ private getFilenameForExceededTotalSizeLimitForNonTsFiles; private createExternalProject; private addFilesToNonInferredProject; + private loadConfiguredProject; private updateNonInferredProjectFiles; private updateRootAndOptionsOfNonInferredProject; + private reloadFileNamesOfParsedConfig; + private clearSemanticCache; private getOrCreateInferredProjectForProjectRootPathIfEnabled; private getOrCreateSingleInferredProjectIfEnabled; private getOrCreateSingleInferredWithoutProjectRoot; @@ -3316,23 +3316,15 @@ declare namespace ts { private addSourceInfoToSourceMap; private addMissingSourceMapFile; setHostConfiguration(args: protocol.ConfigureRequestArguments): void; + private getWatchOptionsFromProjectWatchOptions; closeLog(): void; + private sendSourceFileChange; /** * This function rebuilds the project for every file opened by the client * This does not reload contents of open files from disk. But we could do that if needed */ reloadProjects(): void; - /** - * Remove the root of inferred project if script info is part of another project - */ private removeRootOfInferredProjectIfNowPartOfOtherProject; - /** - * This function is to update the project structure for every inferred project. - * It is called on the premise that all the configured projects are - * up to date. - * This will go through open files and assign them to inferred project if open file is not part of any other project - * After that all the inferred project graphs are updated - */ private ensureProjectForOpenFiles; /** * Open file whose contents is managed by the client @@ -3343,20 +3335,12 @@ declare namespace ts { private findExternalProjectContainingOpenScriptInfo; private getOrCreateOpenScriptInfo; private assignProjectToOpenedScriptInfo; - /** - * Finds the default configured project for given info - * For any tsconfig found, it looks into that project, if not then all its references, - * The search happens for all tsconfigs till projectRootPath - */ private tryFindDefaultConfiguredProjectForOpenScriptInfo; - /** - * Finds the default configured project, if found, it creates the solution projects (does not load them right away) - * with Find: finds the projects even if the project is deferredClosed - */ private tryFindDefaultConfiguredProjectAndLoadAncestorsForOpenScriptInfo; private ensureProjectChildren; private cleanupConfiguredProjects; private cleanupProjectsAndScriptInfos; + private tryInvokeWildCardDirectories; openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult; private removeOrphanScriptInfos; private telemetryOnOpenFile; @@ -3368,7 +3352,6 @@ declare namespace ts { private collectChanges; closeExternalProject(uncheckedFileName: string): void; openExternalProjects(projects: protocol.ExternalProject[]): void; - /** Makes a filename safe to insert in a RegExp */ private static readonly filenameEscapeRegexp; private static escapeFilenameForRegex; resetSafeList(): void; @@ -3376,9 +3359,12 @@ declare namespace ts { private applySafeListWorker; openExternalProject(proj: protocol.ExternalProject): void; hasDeferredExtension(): boolean; + private endEnablePlugin; private enableRequestedPluginsAsync; private enableRequestedPluginsWorker; configurePlugin(args: protocol.ConfigurePluginRequestArguments): void; + private watchPackageJsonFile; + private onPackageJsonChange; } function formatMessage(msg: T, logger: Logger, byteLength: (s: string, encoding: BufferEncoding) => number, newLine: string): string; interface ServerCancellationToken extends HostCancellationToken { @@ -3386,10 +3372,6 @@ declare namespace ts { resetRequest(requestId: number): void; } const nullCancellationToken: ServerCancellationToken; - interface PendingErrorCheck { - fileName: NormalizedPath; - project: Project; - } /** @deprecated use ts.server.protocol.CommandTypes */ type CommandNames = protocol.CommandTypes; /** @deprecated use ts.server.protocol.CommandTypes */ @@ -3449,6 +3431,7 @@ declare namespace ts { constructor(opts: SessionOptions); private sendRequestCompletedEvent; private addPerformanceData; + private addDiagnosticsPerformanceData; private performanceEventHandler; private defaultEventHandler; private projectsUpdatedInBackgroundEvent; @@ -3460,8 +3443,8 @@ declare namespace ts { private semanticCheck; private syntacticCheck; private suggestionCheck; + private regionSemanticCheck; private sendDiagnosticsEvent; - /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */ private updateErrorCheck; private cleanProjects; private cleanup; @@ -3508,10 +3491,6 @@ declare namespace ts { private toSpanGroups; private getReferences; private getFileReferences; - /** - * @param fileName is the name of the file to be opened - * @param fileContent is a version of the file content that is known to be more up to date than the one on disk - */ private openClientFile; private getPosition; private getPositionInFile; @@ -3610,19 +3589,12 @@ declare namespace ts { } namespace deno { function setIsNodeSourceFileCallback(callback: IsNodeSourceFileCallback): void; - function setNodeBuiltInModuleNames(names: readonly string[]): void; function setNodeOnlyGlobalNames(names: readonly string[]): void; - function createDenoForkContext({ mergeSymbol, globals, nodeGlobals, ambientModuleSymbolRegex }: { + function createDenoForkContext({ mergeSymbol, globals, nodeGlobals }: { mergeSymbol(target: ts.Symbol, source: ts.Symbol, unidirectional?: boolean): ts.Symbol; globals: ts.SymbolTable; nodeGlobals: ts.SymbolTable; - ambientModuleSymbolRegex: RegExp; - }): { - hasNodeSourceFile: (node: ts.Node | undefined) => boolean; - getGlobalsForName: (id: ts.__String) => ts.SymbolTable; - mergeGlobalSymbolTable: (node: ts.Node, source: ts.SymbolTable, unidirectional?: boolean) => void; - combinedGlobals: ts.SymbolTable; - }; + }): DenoForkContext; function tryParseNpmPackageReference(text: string): { name: string; versionReq: string | undefined; @@ -3634,6 +3606,12 @@ declare namespace ts { subPath: string | undefined; }; type IsNodeSourceFileCallback = (sourceFile: ts.SourceFile) => boolean; + interface DenoForkContext { + hasNodeSourceFile: (node: ts.Node | undefined) => boolean; + getGlobalsForName: (id: ts.__String) => ts.SymbolTable; + mergeGlobalSymbolTable: (node: ts.Node, source: ts.SymbolTable, unidirectional?: boolean) => void; + combinedGlobals: ts.SymbolTable; + } interface NpmPackageReference { name: string; versionReq: string; @@ -3648,7 +3626,7 @@ declare namespace ts { readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; } } - const versionMajorMinor = "5.5"; + const versionMajorMinor = "5.6"; /** The version of the TypeScript compiler release */ const version: string; /** @@ -4478,7 +4456,7 @@ declare namespace ts { readonly right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier; + type PropertyName = Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier | BigIntLiteral; type MemberName = Identifier | PrivateIdentifier; type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression; interface Declaration extends Node { @@ -4829,7 +4807,7 @@ declare namespace ts { readonly kind: SyntaxKind.StringLiteral; } type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; - type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName; + type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName | BigIntLiteral; interface TemplateLiteralTypeNode extends TypeNode { kind: SyntaxKind.TemplateLiteralType; readonly head: TemplateHead; @@ -5549,7 +5527,7 @@ declare namespace ts { interface NamespaceExport extends NamedDeclaration { readonly kind: SyntaxKind.NamespaceExport; readonly parent: ExportDeclaration; - readonly name: Identifier; + readonly name: ModuleExportName; } interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { readonly kind: SyntaxKind.NamespaceExportDeclaration; @@ -5581,7 +5559,7 @@ declare namespace ts { interface ImportSpecifier extends NamedDeclaration { readonly kind: SyntaxKind.ImportSpecifier; readonly parent: NamedImports; - readonly propertyName?: Identifier; + readonly propertyName?: ModuleExportName; readonly name: Identifier; readonly isTypeOnly: boolean; } @@ -5589,9 +5567,10 @@ declare namespace ts { readonly kind: SyntaxKind.ExportSpecifier; readonly parent: NamedExports; readonly isTypeOnly: boolean; - readonly propertyName?: Identifier; - readonly name: Identifier; + readonly propertyName?: ModuleExportName; + readonly name: ModuleExportName; } + type ModuleExportName = Identifier | StringLiteral; type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport; type TypeOnlyImportDeclaration = @@ -6046,19 +6025,67 @@ declare namespace ts { isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; /** - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode; /** - * Calculates the final resolution mode for an import at some index within a file's `imports` list. This is the resolution mode - * explicitly provided via import attributes, if present, or the syntax the usage would have if emitted to JavaScript. In - * `--module node16` or `nodenext`, this may depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the - * input syntax of the reference. In other `module` modes, when overriding import attributes are not provided, this function returns - * `undefined`, as the result would have no impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for an import at some index within a file's `imports` list. This function only returns a result + * when module resolution settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided + * via import attributes, which cause an `import` or `require` condition to be used during resolution regardless of module resolution + * settings. In absence of overriding attributes, and in modes that support differing resolution, the result indicates the syntax the + * usage would emit to JavaScript. Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode; getProjectReferences(): readonly ProjectReference[] | undefined; @@ -6125,6 +6152,27 @@ declare namespace ts { getBaseTypes(type: InterfaceType): BaseType[]; getBaseTypeOfLiteralType(type: Type): Type; getWidenedType(type: Type): Type; + /** + * Gets the "awaited type" of a type. + * + * If an expression has a Promise-like type, the "awaited type" of the expression is + * derived from the type of the first argument of the fulfillment callback for that + * Promise's `then` method. If the "awaited type" is itself a Promise-like, it is + * recursively unwrapped in the same manner until a non-promise type is found. + * + * If an expression does not have a Promise-like type, its "awaited type" is the type + * of the expression. + * + * If the resulting "awaited type" is a generic object type, then it is wrapped in + * an `Awaited`. + * + * In the event the "awaited type" circularly references itself, or is a non-Promise + * object-type with a callable `then()` method, an "awaited type" cannot be determined + * and the value `undefined` will be returned. + * + * This is used to reflect the runtime behavior of the `await` keyword. + */ + getAwaitedType(type: Type): Type | undefined; getReturnTypeOfSignature(signature: Signature): Type; getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; @@ -6217,6 +6265,7 @@ declare namespace ts { getNumberType(): Type; getNumberLiteralType(value: number): NumberLiteralType; getBigIntType(): Type; + getBigIntLiteralType(value: PseudoBigInt): BigIntLiteralType; getBooleanType(): Type; getFalseType(): Type; getTrueType(): Type; @@ -6686,7 +6735,11 @@ declare namespace ts { minLength: number; /** Number of initial required or optional elements */ fixedLength: number; - /** True if tuple has any rest or variadic elements */ + /** + * True if tuple has any rest or variadic elements + * + * @deprecated Use `.combinedFlags & ElementFlags.Variable` instead + */ hasRestElement: boolean; combinedFlags: ElementFlags; readonly: boolean; @@ -7010,6 +7063,7 @@ declare namespace ts { strictBindCallApply?: boolean; strictNullChecks?: boolean; strictPropertyInitialization?: boolean; + strictBuiltinIteratorReturn?: boolean; stripInternal?: boolean; /** @deprecated */ suppressExcessPropertyErrors?: boolean; @@ -7018,6 +7072,7 @@ declare namespace ts { target?: ScriptTarget; traceResolution?: boolean; useUnknownInCatchVariables?: boolean; + noUncheckedSideEffectImports?: boolean; resolveJsonModule?: boolean; types?: string[]; /** Paths used to compute primary types search locations */ @@ -7344,9 +7399,10 @@ declare namespace ts { TypeAssertions = 2, NonNullAssertions = 4, PartiallyEmittedExpressions = 8, + ExpressionsWithTypeArguments = 16, Assertions = 6, - All = 15, - ExcludeJSDocTypeAssertion = 16, + All = 31, + ExcludeJSDocTypeAssertion = -2147483648, } type ImmediatelyInvokedFunctionExpression = CallExpression & { readonly expression: FunctionExpression; @@ -7645,20 +7701,20 @@ declare namespace ts { updateImportAttribute(node: ImportAttribute, name: ImportAttributeName, value: Expression): ImportAttribute; createNamespaceImport(name: Identifier): NamespaceImport; updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; - createNamespaceExport(name: Identifier): NamespaceExport; - updateNamespaceExport(node: NamespaceExport, name: Identifier): NamespaceExport; + createNamespaceExport(name: ModuleExportName): NamespaceExport; + updateNamespaceExport(node: NamespaceExport, name: ModuleExportName): NamespaceExport; createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; - createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + createImportSpecifier(isTypeOnly: boolean, propertyName: ModuleExportName | undefined, name: Identifier): ImportSpecifier; + updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: ModuleExportName | undefined, name: Identifier): ImportSpecifier; createExportAssignment(modifiers: readonly ModifierLike[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; updateExportAssignment(node: ExportAssignment, modifiers: readonly ModifierLike[] | undefined, expression: Expression): ExportAssignment; createExportDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier?: Expression, attributes?: ImportAttributes): ExportDeclaration; updateExportDeclaration(node: ExportDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier: Expression | undefined, attributes: ImportAttributes | undefined): ExportDeclaration; createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExportSpecifier(isTypeOnly: boolean, propertyName: string | ModuleExportName | undefined, name: string | ModuleExportName): ExportSpecifier; + updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: ModuleExportName | undefined, name: ModuleExportName): ExportSpecifier; createExternalModuleReference(expression: Expression): ExternalModuleReference; updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; createJSDocAllType(): JSDocAllType; @@ -8238,6 +8294,7 @@ declare namespace ts { readonly interactiveInlayHints?: boolean; readonly allowRenameOfImportPath?: boolean; readonly autoImportFileExcludePatterns?: string[]; + readonly autoImportSpecifierExcludeRegexes?: string[]; readonly preferTypeOnlyAutoImports?: boolean; /** * Indicates whether imports should be organized in a case-insensitive manner. @@ -8976,6 +9033,7 @@ declare namespace ts { function isExportDeclaration(node: Node): node is ExportDeclaration; function isNamedExports(node: Node): node is NamedExports; function isExportSpecifier(node: Node): node is ExportSpecifier; + function isModuleExportName(node: Node): node is ModuleExportName; function isMissingDeclaration(node: Node): node is MissingDeclaration; function isNotEmittedStatement(node: Node): node is NotEmittedStatement; function isExternalModuleReference(node: Node): node is ExternalModuleReference; @@ -9411,24 +9469,43 @@ declare namespace ts { function getModeForResolutionAtIndex(file: SourceFile, index: number, compilerOptions: CompilerOptions): ResolutionMode; /** * Use `program.getModeForUsageLocation`, which retrieves the correct `compilerOptions`, instead of this function whenever possible. - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` + * * @param file The file the import or import-like reference is contained within * @param usage The module reference string * @param compilerOptions The compiler options for the program that owns the file. If the file belongs to a referenced project, the compiler options * should be the options of the referenced project, not the referencing project. * @returns The final resolution mode of the import */ - function getModeForUsageLocation( - file: { - impliedNodeFormat?: ResolutionMode; - }, - usage: StringLiteralLike, - compilerOptions: CompilerOptions, - ): ModuleKind.CommonJS | ModuleKind.ESNext | undefined; + function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike, compilerOptions: CompilerOptions): ResolutionMode; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[]; /** * A function for determining if a given file is esm or cjs format, assuming modern node module resolution rules, as configured by the @@ -9654,6 +9731,7 @@ declare namespace ts { setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; /** If provided, will be used to reset existing delayed compilation */ clearTimeout?(timeoutId: any): void; + preferNonRecursiveWatch?: boolean; } interface ProgramHost { /** @@ -9776,6 +9854,7 @@ declare namespace ts { dry?: boolean; force?: boolean; verbose?: boolean; + stopBuildOnErrors?: boolean; incremental?: boolean; assumeChangesOnlyAffectDirectDependencies?: boolean; declaration?: boolean; @@ -10743,6 +10822,10 @@ declare namespace ts { */ isIncomplete?: true; entries: CompletionEntry[]; + /** + * Default commit characters for the completion entries. + */ + defaultCommitCharacters?: string[]; } interface CompletionEntryDataAutoImport { /** @@ -10849,6 +10932,10 @@ declare namespace ts { * is an auto-import. */ data?: CompletionEntryData; + /** + * If this completion entry is selected, typing a commit character will cause the entry to be accepted. + */ + commitCharacters?: string[]; } interface CompletionEntryLabelDetails { /** diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index ac7fc48e37..de91889b62 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -5,6 +5,7 @@ use crate::args::TypeCheckMode; use crate::cache::FastInsecureHasher; use crate::node; use crate::npm::CliNpmResolver; +use crate::npm::ResolvePkgFolderFromDenoReqError; use crate::util::checksum; use crate::util::path::mapped_specifier_for_tsc; @@ -22,6 +23,7 @@ use deno_core::serde::Serialize; use deno_core::serde::Serializer; use deno_core::serde_json::json; use deno_core::serde_v8; +use deno_core::url::Url; use deno_core::JsRuntime; use deno_core::ModuleSpecifier; use deno_core::OpState; @@ -32,9 +34,9 @@ use deno_graph::ModuleGraph; use deno_graph::ResolutionResolved; use deno_runtime::deno_node::NodeResolver; use deno_semver::npm::NpmPackageReqReference; -use lsp_types::Url; use node_resolver::errors::NodeJsErrorCode; use node_resolver::errors::NodeJsErrorCoded; +use node_resolver::errors::ResolvePkgSubpathFromDenoModuleError; use node_resolver::NodeModuleKind; use node_resolver::NodeResolution; use node_resolver::NodeResolutionMode; @@ -45,6 +47,7 @@ use std::fmt; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; +use thiserror::Error; mod diagnostics; @@ -468,6 +471,7 @@ struct LoadResponse { data: String, version: Option, script_kind: i32, + is_cjs: bool, } #[op2] @@ -483,6 +487,29 @@ fn op_load_inner( state: &mut OpState, load_specifier: &str, ) -> Result, AnyError> { + fn load_from_node_modules( + specifier: &ModuleSpecifier, + node_resolver: Option<&NodeResolver>, + media_type: &mut MediaType, + is_cjs: &mut bool, + ) -> Result { + *media_type = MediaType::from_specifier(specifier); + *is_cjs = node_resolver + .map(|node_resolver| { + match node_resolver.url_to_node_resolution(specifier.clone()) { + Ok(NodeResolution::CommonJs(_)) => true, + Ok(NodeResolution::Esm(_)) + | Ok(NodeResolution::BuiltIn(_)) + | Err(_) => false, + } + }) + .unwrap_or(false); + let file_path = specifier.to_file_path().unwrap(); + let code = std::fs::read_to_string(&file_path) + .with_context(|| format!("Unable to load {}", file_path.display()))?; + Ok(code) + } + let state = state.borrow_mut::(); let specifier = normalize_specifier(load_specifier, &state.current_dir) @@ -491,6 +518,7 @@ fn op_load_inner( let mut hash: Option = None; let mut media_type = MediaType::Unknown; let graph = &state.graph; + let mut is_cjs = false; let data = if load_specifier == "internal:///.tsbuildinfo" { state.maybe_tsbuildinfo.as_deref().map(Cow::Borrowed) @@ -522,6 +550,7 @@ fn op_load_inner( data: "".to_string(), version: Some("1".to_string()), script_kind: as_ts_script_kind(*media_type), + is_cjs: false, })) } _ => None, @@ -546,26 +575,25 @@ fn op_load_inner( // means it's Deno code importing an npm module let specifier = node::resolve_specifier_into_node_modules(&module.specifier); - media_type = MediaType::from_specifier(&specifier); - let file_path = specifier.to_file_path().unwrap(); - let code = - std::fs::read_to_string(&file_path).with_context(|| { - format!("Unable to load {}", file_path.display()) - })?; - Some(Cow::Owned(code)) + Some(Cow::Owned(load_from_node_modules( + &specifier, + state.maybe_npm.as_ref().map(|n| n.node_resolver.as_ref()), + &mut media_type, + &mut is_cjs, + )?)) } } - } else if state + } else if let Some(npm) = state .maybe_npm .as_ref() - .map(|npm| npm.node_resolver.in_npm_package(specifier)) - .unwrap_or(false) + .filter(|npm| npm.node_resolver.in_npm_package(specifier)) { - media_type = MediaType::from_specifier(specifier); - let file_path = specifier.to_file_path().unwrap(); - let code = std::fs::read_to_string(&file_path) - .with_context(|| format!("Unable to load {}", file_path.display()))?; - Some(Cow::Owned(code)) + Some(Cow::Owned(load_from_node_modules( + specifier, + Some(npm.node_resolver.as_ref()), + &mut media_type, + &mut is_cjs, + )?)) } else { None }; @@ -579,6 +607,7 @@ fn op_load_inner( data: data.into_owned(), version: hash, script_kind: as_ts_script_kind(media_type), + is_cjs, })) } @@ -601,7 +630,7 @@ fn op_resolve( #[string] base: String, is_base_cjs: bool, #[serde] specifiers: Vec, -) -> Result, AnyError> { +) -> Result, AnyError> { op_resolve_inner( state, ResolveArgs { @@ -616,9 +645,9 @@ fn op_resolve( fn op_resolve_inner( state: &mut OpState, args: ResolveArgs, -) -> Result, AnyError> { +) -> Result, AnyError> { let state = state.borrow_mut::(); - let mut resolved: Vec<(String, String)> = + let mut resolved: Vec<(String, &'static str)> = Vec::with_capacity(args.specifiers.len()); let referrer_kind = if args.is_base_cjs { NodeModuleKind::Cjs @@ -640,16 +669,14 @@ fn op_resolve_inner( if specifier.starts_with("node:") { resolved.push(( MISSING_DEPENDENCY_SPECIFIER.to_string(), - MediaType::Dts.to_string(), + MediaType::Dts.as_ts_extension(), )); continue; } if specifier.starts_with("asset:///") { - let media_type = MediaType::from_str(&specifier) - .as_ts_extension() - .to_string(); - resolved.push((specifier, media_type)); + let ext = MediaType::from_str(&specifier).as_ts_extension(); + resolved.push((specifier, ext)); continue; } @@ -664,12 +691,30 @@ fn op_resolve_inner( Some(ResolutionResolved { specifier, .. }) => { resolve_graph_specifier_types(specifier, &referrer, state)? } - _ => resolve_non_graph_specifier_types( - &specifier, - &referrer, - referrer_kind, - state, - )?, + _ => { + match resolve_non_graph_specifier_types( + &specifier, + &referrer, + referrer_kind, + state, + ) { + Ok(maybe_result) => maybe_result, + Err( + err @ ResolveNonGraphSpecifierTypesError::ResolvePkgFolderFromDenoReq( + ResolvePkgFolderFromDenoReqError::Managed(_), + ), + ) => { + // it's most likely requesting the jsxImportSource, which isn't loaded + // into the graph when not using jsx, so just ignore this error + if specifier.ends_with("/jsx-runtime") { + None + } else { + return Err(err.into()); + } + } + Err(err) => return Err(err.into()), + } + } }; let result = match maybe_result { Some((specifier, media_type)) => { @@ -694,11 +739,11 @@ fn op_resolve_inner( } } }; - (specifier_str, media_type.as_ts_extension().into()) + (specifier_str, media_type.as_ts_extension()) } None => ( MISSING_DEPENDENCY_SPECIFIER.to_string(), - ".d.ts".to_string(), + MediaType::Dts.as_ts_extension(), ), }; log::debug!("Resolved {} to {:?}", specifier, result); @@ -794,12 +839,23 @@ fn resolve_graph_specifier_types( } } +#[derive(Debug, Error)] +enum ResolveNonGraphSpecifierTypesError { + #[error(transparent)] + ResolvePkgFolderFromDenoReq(#[from] ResolvePkgFolderFromDenoReqError), + #[error(transparent)] + ResolvePkgSubpathFromDenoModule(#[from] ResolvePkgSubpathFromDenoModuleError), +} + fn resolve_non_graph_specifier_types( - specifier: &str, + raw_specifier: &str, referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, state: &State, -) -> Result, AnyError> { +) -> Result< + Option<(ModuleSpecifier, MediaType)>, + ResolveNonGraphSpecifierTypesError, +> { let npm = match state.maybe_npm.as_ref() { Some(npm) => npm, None => return Ok(None), // we only support non-graph types for npm packages @@ -810,14 +866,16 @@ fn resolve_non_graph_specifier_types( Ok(Some(NodeResolution::into_specifier_and_media_type( node_resolver .resolve( - specifier, + raw_specifier, referrer, referrer_kind, NodeResolutionMode::Types, ) .ok(), ))) - } else if let Ok(npm_req_ref) = NpmPackageReqReference::from_str(specifier) { + } else if let Ok(npm_req_ref) = + NpmPackageReqReference::from_str(raw_specifier) + { debug_assert_eq!(referrer_kind, NodeModuleKind::Esm); // todo(dsherret): add support for injecting this in the graph so // we don't need this special code here. @@ -851,14 +909,15 @@ fn resolve_non_graph_specifier_types( #[op2(fast)] fn op_is_node_file(state: &mut OpState, #[string] path: &str) -> bool { let state = state.borrow::(); - match ModuleSpecifier::parse(path) { - Ok(specifier) => state - .maybe_npm - .as_ref() - .map(|n| n.node_resolver.in_npm_package(&specifier)) - .unwrap_or(false), - Err(_) => false, - } + ModuleSpecifier::parse(path) + .ok() + .and_then(|specifier| { + state + .maybe_npm + .as_ref() + .map(|n| n.node_resolver.in_npm_package(&specifier)) + }) + .unwrap_or(false) } #[derive(Debug, Deserialize, Eq, PartialEq)] @@ -1069,7 +1128,6 @@ mod tests { "jsxFactory": "React.createElement", "jsxFragmentFactory": "React.Fragment", "lib": ["deno.window"], - "module": "esnext", "noEmit": true, "outDir": "internal:///", "strict": true, @@ -1166,6 +1224,7 @@ mod tests { "data": "console.log(\"hello deno\");\n", "version": "7821807483407828376", "scriptKind": 3, + "isCjs": false, }) ); } @@ -1204,6 +1263,7 @@ mod tests { "data": "some content", "version": null, "scriptKind": 0, + "isCjs": false, }) ); } @@ -1233,10 +1293,7 @@ mod tests { }, ) .expect("should have invoked op"); - assert_eq!( - actual, - vec![("https://deno.land/x/b.ts".into(), ".ts".into())] - ); + assert_eq!(actual, vec![("https://deno.land/x/b.ts".into(), ".ts")]); } #[tokio::test] @@ -1256,10 +1313,7 @@ mod tests { }, ) .expect("should have not errored"); - assert_eq!( - actual, - vec![(MISSING_DEPENDENCY_SPECIFIER.into(), ".d.ts".into())] - ); + assert_eq!(actual, vec![(MISSING_DEPENDENCY_SPECIFIER.into(), ".d.ts")]); } #[tokio::test] diff --git a/cli/util/draw_thread.rs b/cli/util/draw_thread.rs index d9ab176a93..164a8fc713 100644 --- a/cli/util/draw_thread.rs +++ b/cli/util/draw_thread.rs @@ -40,7 +40,7 @@ struct InternalEntry { struct InternalState { // this ensures only one actual draw thread is running drawer_id: usize, - hide: bool, + hide_count: usize, has_draw_thread: bool, next_entry_id: u16, entries: Vec, @@ -56,7 +56,7 @@ impl InternalState { static INTERNAL_STATE: Lazy>> = Lazy::new(|| { Arc::new(Mutex::new(InternalState { drawer_id: 0, - hide: false, + hide_count: 0, has_draw_thread: false, entries: Vec::new(), next_entry_id: 0, @@ -113,7 +113,7 @@ impl DrawThread { pub fn hide() { let internal_state = &*INTERNAL_STATE; let mut internal_state = internal_state.lock(); - internal_state.hide = true; + internal_state.hide_count += 1; Self::clear_and_stop_draw_thread(&mut internal_state); } @@ -122,9 +122,12 @@ impl DrawThread { pub fn show() { let internal_state = &*INTERNAL_STATE; let mut internal_state = internal_state.lock(); - internal_state.hide = false; - - Self::maybe_start_draw_thread(&mut internal_state); + if internal_state.hide_count > 0 { + internal_state.hide_count -= 1; + if internal_state.hide_count == 0 { + Self::maybe_start_draw_thread(&mut internal_state); + } + } } fn finish_entry(entry_id: u16) { @@ -153,7 +156,7 @@ impl DrawThread { fn maybe_start_draw_thread(internal_state: &mut InternalState) { if internal_state.has_draw_thread - || internal_state.hide + || internal_state.hide_count > 0 || internal_state.entries.is_empty() || !DrawThread::is_supported() { diff --git a/cli/util/extract.rs b/cli/util/extract.rs new file mode 100644 index 0000000000..873b7e7f2d --- /dev/null +++ b/cli/util/extract.rs @@ -0,0 +1,1652 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use deno_ast::swc::ast; +use deno_ast::swc::atoms::Atom; +use deno_ast::swc::common::collections::AHashSet; +use deno_ast::swc::common::comments::CommentKind; +use deno_ast::swc::common::DUMMY_SP; +use deno_ast::swc::utils as swc_utils; +use deno_ast::swc::visit::as_folder; +use deno_ast::swc::visit::FoldWith as _; +use deno_ast::swc::visit::Visit; +use deno_ast::swc::visit::VisitMut; +use deno_ast::swc::visit::VisitWith as _; +use deno_ast::MediaType; +use deno_ast::SourceRangedForSpanned as _; +use deno_core::error::AnyError; +use deno_core::ModuleSpecifier; +use regex::Regex; +use std::collections::BTreeSet; +use std::fmt::Write as _; +use std::sync::Arc; + +use crate::file_fetcher::File; +use crate::util::path::mapped_specifier_for_tsc; + +/// Extracts doc tests from a given file, transforms them into pseudo test +/// files by wrapping the content of the doc tests in a `Deno.test` call, and +/// returns a list of the pseudo test files. +/// +/// The difference from [`extract_snippet_files`] is that this function wraps +/// extracted code snippets in a `Deno.test` call. +pub fn extract_doc_tests(file: File) -> Result, AnyError> { + extract_inner(file, WrapKind::DenoTest) +} + +/// Extracts code snippets from a given file and returns a list of the extracted +/// files. +/// +/// The difference from [`extract_doc_tests`] is that this function does *not* +/// wrap extracted code snippets in a `Deno.test` call. +pub fn extract_snippet_files(file: File) -> Result, AnyError> { + extract_inner(file, WrapKind::NoWrap) +} + +#[derive(Clone, Copy)] +enum WrapKind { + DenoTest, + NoWrap, +} + +fn extract_inner( + file: File, + wrap_kind: WrapKind, +) -> Result, AnyError> { + let file = file.into_text_decoded()?; + + let exports = match deno_ast::parse_program(deno_ast::ParseParams { + specifier: file.specifier.clone(), + text: file.source.clone(), + media_type: file.media_type, + capture_tokens: false, + scope_analysis: false, + maybe_syntax: None, + }) { + Ok(parsed) => { + let mut c = ExportCollector::default(); + c.visit_program(parsed.program_ref()); + c + } + Err(_) => ExportCollector::default(), + }; + + let extracted_files = if file.media_type == MediaType::Unknown { + extract_files_from_fenced_blocks( + &file.specifier, + &file.source, + file.media_type, + )? + } else { + extract_files_from_source_comments( + &file.specifier, + file.source.clone(), + file.media_type, + )? + }; + + extracted_files + .into_iter() + .map(|extracted_file| { + generate_pseudo_file(extracted_file, &file.specifier, &exports, wrap_kind) + }) + .collect::>() +} + +fn extract_files_from_fenced_blocks( + specifier: &ModuleSpecifier, + source: &str, + media_type: MediaType, +) -> Result, AnyError> { + // The pattern matches code blocks as well as anything in HTML comment syntax, + // but it stores the latter without any capturing groups. This way, a simple + // check can be done to see if a block is inside a comment (and skip typechecking) + // or not by checking for the presence of capturing groups in the matches. + let blocks_regex = + lazy_regex::regex!(r"(?s)|```([^\r\n]*)\r?\n([\S\s]*?)```"); + let lines_regex = lazy_regex::regex!(r"(?:\# ?)?(.*)"); + + extract_files_from_regex_blocks( + specifier, + source, + media_type, + /* file line index */ 0, + blocks_regex, + lines_regex, + ) +} + +fn extract_files_from_source_comments( + specifier: &ModuleSpecifier, + source: Arc, + media_type: MediaType, +) -> Result, AnyError> { + let parsed_source = deno_ast::parse_module(deno_ast::ParseParams { + specifier: specifier.clone(), + text: source, + media_type, + capture_tokens: false, + maybe_syntax: None, + scope_analysis: false, + })?; + let comments = parsed_source.comments().get_vec(); + let blocks_regex = lazy_regex::regex!(r"```([^\r\n]*)\r?\n([\S\s]*?)```"); + let lines_regex = lazy_regex::regex!(r"(?:\* ?)(?:\# ?)?(.*)"); + + let files = comments + .iter() + .filter(|comment| { + if comment.kind != CommentKind::Block || !comment.text.starts_with('*') { + return false; + } + + true + }) + .flat_map(|comment| { + extract_files_from_regex_blocks( + specifier, + &comment.text, + media_type, + parsed_source.text_info_lazy().line_index(comment.start()), + blocks_regex, + lines_regex, + ) + }) + .flatten() + .collect(); + + Ok(files) +} + +fn extract_files_from_regex_blocks( + specifier: &ModuleSpecifier, + source: &str, + media_type: MediaType, + file_line_index: usize, + blocks_regex: &Regex, + lines_regex: &Regex, +) -> Result, AnyError> { + let files = blocks_regex + .captures_iter(source) + .filter_map(|block| { + block.get(1)?; + + let maybe_attributes: Option> = block + .get(1) + .map(|attributes| attributes.as_str().split(' ').collect()); + + let file_media_type = if let Some(attributes) = maybe_attributes { + if attributes.contains(&"ignore") { + return None; + } + + match attributes.first() { + Some(&"js") => MediaType::JavaScript, + Some(&"javascript") => MediaType::JavaScript, + Some(&"mjs") => MediaType::Mjs, + Some(&"cjs") => MediaType::Cjs, + Some(&"jsx") => MediaType::Jsx, + Some(&"ts") => MediaType::TypeScript, + Some(&"typescript") => MediaType::TypeScript, + Some(&"mts") => MediaType::Mts, + Some(&"cts") => MediaType::Cts, + Some(&"tsx") => MediaType::Tsx, + _ => MediaType::Unknown, + } + } else { + media_type + }; + + if file_media_type == MediaType::Unknown { + return None; + } + + let line_offset = source[0..block.get(0).unwrap().start()] + .chars() + .filter(|c| *c == '\n') + .count(); + + let line_count = block.get(0).unwrap().as_str().split('\n').count(); + + let body = block.get(2).unwrap(); + let text = body.as_str(); + + // TODO(caspervonb) generate an inline source map + let mut file_source = String::new(); + for line in lines_regex.captures_iter(text) { + let text = line.get(1).unwrap(); + writeln!(file_source, "{}", text.as_str()).unwrap(); + } + + let file_specifier = ModuleSpecifier::parse(&format!( + "{}${}-{}", + specifier, + file_line_index + line_offset + 1, + file_line_index + line_offset + line_count + 1, + )) + .unwrap(); + let file_specifier = + mapped_specifier_for_tsc(&file_specifier, file_media_type) + .map(|s| ModuleSpecifier::parse(&s).unwrap()) + .unwrap_or(file_specifier); + + Some(File { + specifier: file_specifier, + maybe_headers: None, + source: file_source.into_bytes().into(), + }) + }) + .collect(); + + Ok(files) +} + +#[derive(Default)] +struct ExportCollector { + named_exports: BTreeSet, + default_export: Option, +} + +impl ExportCollector { + fn to_import_specifiers( + &self, + symbols_to_exclude: &AHashSet, + ) -> Vec { + let mut import_specifiers = vec![]; + + if let Some(default_export) = &self.default_export { + // If the default export conflicts with a named export, a named one + // takes precedence. + if !symbols_to_exclude.contains(default_export) + && !self.named_exports.contains(default_export) + { + import_specifiers.push(ast::ImportSpecifier::Default( + ast::ImportDefaultSpecifier { + span: DUMMY_SP, + local: ast::Ident { + span: DUMMY_SP, + ctxt: Default::default(), + sym: default_export.clone(), + optional: false, + }, + }, + )); + } + } + + for named_export in &self.named_exports { + if symbols_to_exclude.contains(named_export) { + continue; + } + + import_specifiers.push(ast::ImportSpecifier::Named( + ast::ImportNamedSpecifier { + span: DUMMY_SP, + local: ast::Ident { + span: DUMMY_SP, + ctxt: Default::default(), + sym: named_export.clone(), + optional: false, + }, + imported: None, + is_type_only: false, + }, + )); + } + + import_specifiers + } +} + +impl Visit for ExportCollector { + fn visit_ts_module_decl(&mut self, ts_module_decl: &ast::TsModuleDecl) { + if ts_module_decl.declare { + return; + } + + ts_module_decl.visit_children_with(self); + } + + fn visit_export_decl(&mut self, export_decl: &ast::ExportDecl) { + match &export_decl.decl { + ast::Decl::Class(class) => { + self.named_exports.insert(class.ident.sym.clone()); + } + ast::Decl::Fn(func) => { + self.named_exports.insert(func.ident.sym.clone()); + } + ast::Decl::Var(var) => { + for var_decl in &var.decls { + let atoms = extract_sym_from_pat(&var_decl.name); + self.named_exports.extend(atoms); + } + } + ast::Decl::TsEnum(ts_enum) => { + self.named_exports.insert(ts_enum.id.sym.clone()); + } + ast::Decl::TsModule(ts_module) => { + if ts_module.declare { + return; + } + + match &ts_module.id { + ast::TsModuleName::Ident(ident) => { + self.named_exports.insert(ident.sym.clone()); + } + ast::TsModuleName::Str(s) => { + self.named_exports.insert(s.value.clone()); + } + } + } + ast::Decl::TsTypeAlias(ts_type_alias) => { + self.named_exports.insert(ts_type_alias.id.sym.clone()); + } + ast::Decl::TsInterface(ts_interface) => { + self.named_exports.insert(ts_interface.id.sym.clone()); + } + ast::Decl::Using(_) => {} + } + } + + fn visit_export_default_decl( + &mut self, + export_default_decl: &ast::ExportDefaultDecl, + ) { + match &export_default_decl.decl { + ast::DefaultDecl::Class(class) => { + if let Some(ident) = &class.ident { + self.default_export = Some(ident.sym.clone()); + } + } + ast::DefaultDecl::Fn(func) => { + if let Some(ident) = &func.ident { + self.default_export = Some(ident.sym.clone()); + } + } + ast::DefaultDecl::TsInterfaceDecl(iface_decl) => { + self.default_export = Some(iface_decl.id.sym.clone()); + } + } + } + + fn visit_export_default_expr( + &mut self, + export_default_expr: &ast::ExportDefaultExpr, + ) { + if let ast::Expr::Ident(ident) = &*export_default_expr.expr { + self.default_export = Some(ident.sym.clone()); + } + } + + fn visit_export_named_specifier( + &mut self, + export_named_specifier: &ast::ExportNamedSpecifier, + ) { + fn get_atom(export_name: &ast::ModuleExportName) -> Atom { + match export_name { + ast::ModuleExportName::Ident(ident) => ident.sym.clone(), + ast::ModuleExportName::Str(s) => s.value.clone(), + } + } + + match &export_named_specifier.exported { + Some(exported) => { + self.named_exports.insert(get_atom(exported)); + } + None => { + self + .named_exports + .insert(get_atom(&export_named_specifier.orig)); + } + } + } + + fn visit_named_export(&mut self, named_export: &ast::NamedExport) { + // ExportCollector does not handle re-exports + if named_export.src.is_some() { + return; + } + + named_export.visit_children_with(self); + } +} + +fn extract_sym_from_pat(pat: &ast::Pat) -> Vec { + fn rec(pat: &ast::Pat, atoms: &mut Vec) { + match pat { + ast::Pat::Ident(binding_ident) => { + atoms.push(binding_ident.sym.clone()); + } + ast::Pat::Array(array_pat) => { + for elem in array_pat.elems.iter().flatten() { + rec(elem, atoms); + } + } + ast::Pat::Rest(rest_pat) => { + rec(&rest_pat.arg, atoms); + } + ast::Pat::Object(object_pat) => { + for prop in &object_pat.props { + match prop { + ast::ObjectPatProp::Assign(assign_pat_prop) => { + atoms.push(assign_pat_prop.key.sym.clone()); + } + ast::ObjectPatProp::KeyValue(key_value_pat_prop) => { + rec(&key_value_pat_prop.value, atoms); + } + ast::ObjectPatProp::Rest(rest_pat) => { + rec(&rest_pat.arg, atoms); + } + } + } + } + ast::Pat::Assign(assign_pat) => { + rec(&assign_pat.left, atoms); + } + ast::Pat::Invalid(_) | ast::Pat::Expr(_) => {} + } + } + + let mut atoms = vec![]; + rec(pat, &mut atoms); + atoms +} + +/// Generates a "pseudo" file from a given file by applying the following +/// transformations: +/// +/// 1. Injects `import` statements for expoted items from the base file +/// 2. If `wrap_kind` is [`WrapKind::DenoTest`], wraps the content of the file +/// in a `Deno.test` call. +/// +/// For example, given a file that looks like: +/// +/// ```ts +/// import { assertEquals } from "@std/assert/equals"; +/// +/// assertEquals(increment(1), 2); +/// ``` +/// +/// and the base file (from which the above snippet was extracted): +/// +/// ```ts +/// export function increment(n: number): number { +/// return n + 1; +/// } +/// +/// export const SOME_CONST = "HELLO"; +/// ``` +/// +/// The generated pseudo test file would look like (if `wrap_in_deno_test` is enabled): +/// +/// ```ts +/// import { assertEquals } from "@std/assert/equals"; +/// import { increment, SOME_CONST } from "./base.ts"; +/// +/// Deno.test("./base.ts$1-3.ts", async () => { +/// assertEquals(increment(1), 2); +/// }); +/// ``` +/// +/// # Edge case 1 - duplicate identifier +/// +/// If a given file imports, say, `doSomething` from an external module while +/// the base file exports `doSomething` as well, the generated pseudo test file +/// would end up having two duplciate imports for `doSomething`, causing the +/// duplicate identifier error. +/// +/// To avoid this issue, when a given file imports `doSomething`, this takes +/// precedence over the automatic import injection for the base file's +/// `doSomething`. So the generated pseudo test file would look like: +/// +/// ```ts +/// import { assertEquals } from "@std/assert/equals"; +/// import { doSomething } from "./some_external_module.ts"; +/// +/// Deno.test("./base.ts$1-3.ts", async () => { +/// assertEquals(doSomething(1), 2); +/// }); +/// ``` +/// +/// # Edge case 2 - exports can't be put inside `Deno.test` blocks +/// +/// All exports like `export const foo = 42` must be at the top level of the +/// module, making it impossible to wrap exports in `Deno.test` blocks. For +/// example, when the following code snippet is provided: +/// +/// ```ts +/// const logger = createLogger("my-awesome-module"); +/// +/// export function sum(a: number, b: number): number { +/// logger.debug("sum called"); +/// return a + b; +/// } +/// ``` +/// +/// If we applied the naive transformation to this, the generated pseudo test +/// file would look like: +/// +/// ```ts +/// Deno.test("./base.ts$1-7.ts", async () => { +/// const logger = createLogger("my-awesome-module"); +/// +/// export function sum(a: number, b: number): number { +/// logger.debug("sum called"); +/// return a + b; +/// } +/// }); +/// ``` +/// +/// But obviously this violates the rule because `export function sum` is not +/// at the top level of the module. +/// +/// To address this issue, the `export` keyword is removed so that the item can +/// stay in the `Deno.test` block's scope: +/// +/// ```ts +/// Deno.test("./base.ts$1-7.ts", async () => { +/// const logger = createLogger("my-awesome-module"); +/// +/// function sum(a: number, b: number): number { +/// logger.debug("sum called"); +/// return a + b; +/// } +/// }); +/// ``` +fn generate_pseudo_file( + file: File, + base_file_specifier: &ModuleSpecifier, + exports: &ExportCollector, + wrap_kind: WrapKind, +) -> Result { + let file = file.into_text_decoded()?; + + let parsed = deno_ast::parse_program(deno_ast::ParseParams { + specifier: file.specifier.clone(), + text: file.source, + media_type: file.media_type, + capture_tokens: false, + scope_analysis: true, + maybe_syntax: None, + })?; + + let top_level_atoms = swc_utils::collect_decls_with_ctxt::( + parsed.program_ref(), + parsed.top_level_context(), + ); + + let transformed = + parsed + .program_ref() + .clone() + .fold_with(&mut as_folder(Transform { + specifier: &file.specifier, + base_file_specifier, + exports_from_base: exports, + atoms_to_be_excluded_from_import: top_level_atoms, + wrap_kind, + })); + + let source = deno_ast::swc::codegen::to_code(&transformed); + + log::debug!("{}:\n{}", file.specifier, source); + + Ok(File { + specifier: file.specifier, + maybe_headers: None, + source: source.into_bytes().into(), + }) +} + +struct Transform<'a> { + specifier: &'a ModuleSpecifier, + base_file_specifier: &'a ModuleSpecifier, + exports_from_base: &'a ExportCollector, + atoms_to_be_excluded_from_import: AHashSet, + wrap_kind: WrapKind, +} + +impl<'a> VisitMut for Transform<'a> { + fn visit_mut_program(&mut self, node: &mut ast::Program) { + let new_module_items = match node { + ast::Program::Module(module) => { + let mut module_decls = vec![]; + let mut stmts = vec![]; + + for item in &module.body { + match item { + ast::ModuleItem::ModuleDecl(decl) => match self.wrap_kind { + WrapKind::NoWrap => { + module_decls.push(decl.clone()); + } + // We remove `export` keywords so that they can be put inside + // `Deno.test` block scope. + WrapKind::DenoTest => match decl { + ast::ModuleDecl::ExportDecl(export_decl) => { + stmts.push(ast::Stmt::Decl(export_decl.decl.clone())); + } + ast::ModuleDecl::ExportDefaultDecl(export_default_decl) => { + let stmt = match &export_default_decl.decl { + ast::DefaultDecl::Class(class) => { + let expr = ast::Expr::Class(class.clone()); + ast::Stmt::Expr(ast::ExprStmt { + span: DUMMY_SP, + expr: Box::new(expr), + }) + } + ast::DefaultDecl::Fn(func) => { + let expr = ast::Expr::Fn(func.clone()); + ast::Stmt::Expr(ast::ExprStmt { + span: DUMMY_SP, + expr: Box::new(expr), + }) + } + ast::DefaultDecl::TsInterfaceDecl(ts_interface_decl) => { + ast::Stmt::Decl(ast::Decl::TsInterface( + ts_interface_decl.clone(), + )) + } + }; + stmts.push(stmt); + } + ast::ModuleDecl::ExportDefaultExpr(export_default_expr) => { + stmts.push(ast::Stmt::Expr(ast::ExprStmt { + span: DUMMY_SP, + expr: export_default_expr.expr.clone(), + })); + } + _ => { + module_decls.push(decl.clone()); + } + }, + }, + ast::ModuleItem::Stmt(stmt) => { + stmts.push(stmt.clone()); + } + } + } + + let mut transformed_items = vec![]; + transformed_items + .extend(module_decls.into_iter().map(ast::ModuleItem::ModuleDecl)); + let import_specifiers = self + .exports_from_base + .to_import_specifiers(&self.atoms_to_be_excluded_from_import); + if !import_specifiers.is_empty() { + transformed_items.push(ast::ModuleItem::ModuleDecl( + ast::ModuleDecl::Import(ast::ImportDecl { + span: DUMMY_SP, + specifiers: import_specifiers, + src: Box::new(ast::Str { + span: DUMMY_SP, + value: self.base_file_specifier.to_string().into(), + raw: None, + }), + type_only: false, + with: None, + phase: ast::ImportPhase::Evaluation, + }), + )); + } + match self.wrap_kind { + WrapKind::DenoTest => { + transformed_items.push(ast::ModuleItem::Stmt(wrap_in_deno_test( + stmts, + self.specifier.to_string().into(), + ))); + } + WrapKind::NoWrap => { + transformed_items + .extend(stmts.into_iter().map(ast::ModuleItem::Stmt)); + } + } + + transformed_items + } + ast::Program::Script(script) => { + let mut transformed_items = vec![]; + + let import_specifiers = self + .exports_from_base + .to_import_specifiers(&self.atoms_to_be_excluded_from_import); + if !import_specifiers.is_empty() { + transformed_items.push(ast::ModuleItem::ModuleDecl( + ast::ModuleDecl::Import(ast::ImportDecl { + span: DUMMY_SP, + specifiers: import_specifiers, + src: Box::new(ast::Str { + span: DUMMY_SP, + value: self.base_file_specifier.to_string().into(), + raw: None, + }), + type_only: false, + with: None, + phase: ast::ImportPhase::Evaluation, + }), + )); + } + + match self.wrap_kind { + WrapKind::DenoTest => { + transformed_items.push(ast::ModuleItem::Stmt(wrap_in_deno_test( + script.body.clone(), + self.specifier.to_string().into(), + ))); + } + WrapKind::NoWrap => { + transformed_items.extend( + script.body.clone().into_iter().map(ast::ModuleItem::Stmt), + ); + } + } + + transformed_items + } + }; + + *node = ast::Program::Module(ast::Module { + span: DUMMY_SP, + body: new_module_items, + shebang: None, + }); + } +} + +fn wrap_in_deno_test(stmts: Vec, test_name: Atom) -> ast::Stmt { + ast::Stmt::Expr(ast::ExprStmt { + span: DUMMY_SP, + expr: Box::new(ast::Expr::Call(ast::CallExpr { + span: DUMMY_SP, + callee: ast::Callee::Expr(Box::new(ast::Expr::Member(ast::MemberExpr { + span: DUMMY_SP, + obj: Box::new(ast::Expr::Ident(ast::Ident { + span: DUMMY_SP, + sym: "Deno".into(), + optional: false, + ..Default::default() + })), + prop: ast::MemberProp::Ident(ast::IdentName { + span: DUMMY_SP, + sym: "test".into(), + }), + }))), + args: vec![ + ast::ExprOrSpread { + spread: None, + expr: Box::new(ast::Expr::Lit(ast::Lit::Str(ast::Str { + span: DUMMY_SP, + value: test_name, + raw: None, + }))), + }, + ast::ExprOrSpread { + spread: None, + expr: Box::new(ast::Expr::Arrow(ast::ArrowExpr { + span: DUMMY_SP, + params: vec![], + body: Box::new(ast::BlockStmtOrExpr::BlockStmt(ast::BlockStmt { + span: DUMMY_SP, + stmts, + ..Default::default() + })), + is_async: true, + is_generator: false, + type_params: None, + return_type: None, + ..Default::default() + })), + }, + ], + type_args: None, + ..Default::default() + })), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::file_fetcher::TextDecodedFile; + use deno_ast::swc::atoms::Atom; + use pretty_assertions::assert_eq; + + #[test] + fn test_extract_doc_tests() { + struct Input { + source: &'static str, + specifier: &'static str, + } + struct Expected { + source: &'static str, + specifier: &'static str, + media_type: MediaType, + } + struct Test { + input: Input, + expected: Vec, + } + + let tests = [ + Test { + input: Input { + source: r#""#, + specifier: "file:///main.ts", + }, + expected: vec![], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * import { assertEquals } from "@std/assert/equal"; + * + * assertEquals(add(1, 2), 3); + * ``` + */ +export function add(a: number, b: number): number { + return a + b; +} +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { assertEquals } from "@std/assert/equal"; +import { add } from "file:///main.ts"; +Deno.test("file:///main.ts$3-8.ts", async ()=>{ + assertEquals(add(1, 2), 3); +}); +"#, + specifier: "file:///main.ts$3-8.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * foo(); + * ``` + */ +export function foo() {} + +export default class Bar {} +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import Bar, { foo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-6.ts", async ()=>{ + foo(); +}); +"#, + specifier: "file:///main.ts$3-6.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * const input = { a: 42 } satisfies Args; + * foo(input); + * ``` + */ +export function foo(args: Args) {} + +export type Args = { a: number }; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { Args, foo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-7.ts", async ()=>{ + const input = { + a: 42 + } satisfies Args; + foo(input); +}); +"#, + specifier: "file:///main.ts$3-7.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +/** + * This is a module-level doc. + * + * ```ts + * foo(); + * ``` + * + * @module doc + */ +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"Deno.test("file:///main.ts$5-8.ts", async ()=>{ + foo(); +}); +"#, + specifier: "file:///main.ts$5-8.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +/** + * This is a module-level doc. + * + * ```js + * const cls = new MyClass(); + * ``` + * + * @module doc + */ + +/** + * ```ts + * foo(); + * ``` + */ +export function foo() {} + +export default class MyClass {} + +export * from "./other.ts"; +"#, + specifier: "file:///main.ts", + }, + expected: vec![ + Expected { + source: r#"import MyClass, { foo } from "file:///main.ts"; +Deno.test("file:///main.ts$5-8.js", async ()=>{ + const cls = new MyClass(); +}); +"#, + specifier: "file:///main.ts$5-8.js", + media_type: MediaType::JavaScript, + }, + Expected { + source: r#"import MyClass, { foo } from "file:///main.ts"; +Deno.test("file:///main.ts$13-16.ts", async ()=>{ + foo(); +}); +"#, + specifier: "file:///main.ts$13-16.ts", + media_type: MediaType::TypeScript, + }, + ], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * foo(); + * ``` + */ +export function foo() {} + +export const ONE = 1; +const TWO = 2; +export default TWO; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import TWO, { ONE, foo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-6.ts", async ()=>{ + foo(); +}); +"#, + specifier: "file:///main.ts$3-6.ts", + media_type: MediaType::TypeScript, + }], + }, + // Avoid duplicate imports + Test { + input: Input { + source: r#" +/** + * ```ts + * import { DUPLICATE1 } from "./other1.ts"; + * import * as DUPLICATE2 from "./other2.js"; + * import { foo as DUPLICATE3 } from "./other3.tsx"; + * + * foo(); + * ``` + */ +export function foo() {} + +export const DUPLICATE1 = "dup1"; +const DUPLICATE2 = "dup2"; +export default DUPLICATE2; +const DUPLICATE3 = "dup3"; +export { DUPLICATE3 }; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { DUPLICATE1 } from "./other1.ts"; +import * as DUPLICATE2 from "./other2.js"; +import { foo as DUPLICATE3 } from "./other3.tsx"; +import { foo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-10.ts", async ()=>{ + foo(); +}); +"#, + specifier: "file:///main.ts$3-10.ts", + media_type: MediaType::TypeScript, + }], + }, + // duplication of imported identifier and local identifier is fine + Test { + input: Input { + source: r#" +/** + * ```ts + * const foo = createFoo(); + * foo(); + * ``` + */ +export function createFoo() { + return () => "created foo"; +} + +export const foo = () => "foo"; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { createFoo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-7.ts", async ()=>{ + const foo = createFoo(); + foo(); +}); +"#, + specifier: "file:///main.ts$3-7.ts", + media_type: MediaType::TypeScript, + }], + }, + // https://github.com/denoland/deno/issues/25718 + // A case where the example code has an exported item which references + // a variable from one upper scope. + // Naive application of `Deno.test` wrap would cause a reference error + // because the variable would go inside the `Deno.test` block while the + // exported item would be moved to the top level. To suppress the auto + // move of the exported item to the top level, the `export` keyword is + // removed so that the item stays in the same scope as the variable. + Test { + input: Input { + source: r#" +/** + * ```ts + * import { getLogger } from "@std/log"; + * + * const logger = getLogger("my-awesome-module"); + * + * export function foo() { + * logger.debug("hello"); + * } + * ``` + * + * @module + */ +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { getLogger } from "@std/log"; +Deno.test("file:///main.ts$3-12.ts", async ()=>{ + const logger = getLogger("my-awesome-module"); + function foo() { + logger.debug("hello"); + } +}); +"#, + specifier: "file:///main.ts$3-12.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +# Header + +This is a *markdown*. + +```js +import { assertEquals } from "@std/assert/equal"; +import { add } from "jsr:@deno/non-existent"; + +assertEquals(add(1, 2), 3); +``` +"#, + specifier: "file:///README.md", + }, + expected: vec![Expected { + source: r#"import { assertEquals } from "@std/assert/equal"; +import { add } from "jsr:@deno/non-existent"; +Deno.test("file:///README.md$6-12.js", async ()=>{ + assertEquals(add(1, 2), 3); +}); +"#, + specifier: "file:///README.md$6-12.js", + media_type: MediaType::JavaScript, + }], + }, + // https://github.com/denoland/deno/issues/26009 + Test { + input: Input { + source: r#" +/** + * ```ts + * console.log(Foo) + * ``` + */ +export class Foo {} +export default Foo +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { Foo } from "file:///main.ts"; +Deno.test("file:///main.ts$3-6.ts", async ()=>{ + console.log(Foo); +}); +"#, + specifier: "file:///main.ts$3-6.ts", + media_type: MediaType::TypeScript, + }], + }, + ]; + + for test in tests { + let file = File { + specifier: ModuleSpecifier::parse(test.input.specifier).unwrap(), + maybe_headers: None, + source: test.input.source.as_bytes().into(), + }; + let got_decoded = extract_doc_tests(file) + .unwrap() + .into_iter() + .map(|f| f.into_text_decoded().unwrap()) + .collect::>(); + let expected = test + .expected + .iter() + .map(|e| TextDecodedFile { + specifier: ModuleSpecifier::parse(e.specifier).unwrap(), + media_type: e.media_type, + source: e.source.into(), + }) + .collect::>(); + assert_eq!(got_decoded, expected); + } + } + + #[test] + fn test_extract_snippet_files() { + struct Input { + source: &'static str, + specifier: &'static str, + } + struct Expected { + source: &'static str, + specifier: &'static str, + media_type: MediaType, + } + struct Test { + input: Input, + expected: Vec, + } + + let tests = [ + Test { + input: Input { + source: r#""#, + specifier: "file:///main.ts", + }, + expected: vec![], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + */ +export function add(a: number, b: number): number { + return a + b; +} +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { assertEquals } from "@std/assert/equals"; +import { add } from "file:///main.ts"; +assertEquals(add(1, 2), 3); +"#, + specifier: "file:///main.ts$3-8.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * import { DUPLICATE } from "./other.ts"; + * + * assertEquals(add(1, 2), 3); + * ``` + */ +export function add(a: number, b: number): number { + return a + b; +} + +export const DUPLICATE = "dup"; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { assertEquals } from "@std/assert/equals"; +import { DUPLICATE } from "./other.ts"; +import { add } from "file:///main.ts"; +assertEquals(add(1, 2), 3); +"#, + specifier: "file:///main.ts$3-9.ts", + media_type: MediaType::TypeScript, + }], + }, + // If the snippet has a local variable with the same name as an exported + // item, the local variable takes precedence. + Test { + input: Input { + source: r#" +/** + * ```ts + * const foo = createFoo(); + * foo(); + * ``` + */ +export function createFoo() { + return () => "created foo"; +} + +export const foo = () => "foo"; +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { createFoo } from "file:///main.ts"; +const foo = createFoo(); +foo(); +"#, + specifier: "file:///main.ts$3-7.ts", + media_type: MediaType::TypeScript, + }], + }, + // Unlike `extract_doc_tests`, `extract_snippet_files` does not remove + // the `export` keyword from the exported items. + Test { + input: Input { + source: r#" +/** + * ```ts + * import { getLogger } from "@std/log"; + * + * const logger = getLogger("my-awesome-module"); + * + * export function foo() { + * logger.debug("hello"); + * } + * ``` + * + * @module + */ +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { getLogger } from "@std/log"; +export function foo() { + logger.debug("hello"); +} +const logger = getLogger("my-awesome-module"); +"#, + specifier: "file:///main.ts$3-12.ts", + media_type: MediaType::TypeScript, + }], + }, + Test { + input: Input { + source: r#" +# Header + +This is a *markdown*. + +```js +import { assertEquals } from "@std/assert/equal"; +import { add } from "jsr:@deno/non-existent"; + +assertEquals(add(1, 2), 3); +``` +"#, + specifier: "file:///README.md", + }, + expected: vec![Expected { + source: r#"import { assertEquals } from "@std/assert/equal"; +import { add } from "jsr:@deno/non-existent"; +assertEquals(add(1, 2), 3); +"#, + specifier: "file:///README.md$6-12.js", + media_type: MediaType::JavaScript, + }], + }, + // https://github.com/denoland/deno/issues/26009 + Test { + input: Input { + source: r#" +/** + * ```ts + * console.log(Foo) + * ``` + */ +export class Foo {} +export default Foo +"#, + specifier: "file:///main.ts", + }, + expected: vec![Expected { + source: r#"import { Foo } from "file:///main.ts"; +console.log(Foo); +"#, + specifier: "file:///main.ts$3-6.ts", + media_type: MediaType::TypeScript, + }], + }, + ]; + + for test in tests { + let file = File { + specifier: ModuleSpecifier::parse(test.input.specifier).unwrap(), + maybe_headers: None, + source: test.input.source.as_bytes().into(), + }; + let got_decoded = extract_snippet_files(file) + .unwrap() + .into_iter() + .map(|f| f.into_text_decoded().unwrap()) + .collect::>(); + let expected = test + .expected + .iter() + .map(|e| TextDecodedFile { + specifier: ModuleSpecifier::parse(e.specifier).unwrap(), + media_type: e.media_type, + source: e.source.into(), + }) + .collect::>(); + assert_eq!(got_decoded, expected); + } + } + + #[test] + fn test_export_collector() { + fn helper(input: &'static str) -> ExportCollector { + let mut collector = ExportCollector::default(); + let parsed = deno_ast::parse_module(deno_ast::ParseParams { + specifier: deno_ast::ModuleSpecifier::parse("file:///main.ts").unwrap(), + text: input.into(), + media_type: deno_ast::MediaType::TypeScript, + capture_tokens: false, + scope_analysis: false, + maybe_syntax: None, + }) + .unwrap(); + + collector.visit_program(parsed.program_ref()); + collector + } + + struct Test { + input: &'static str, + named_expected: BTreeSet, + default_expected: Option, + } + + macro_rules! atom_set { + ($( $x:expr ),*) => { + [$( Atom::from($x) ),*].into_iter().collect::>() + }; + } + + let tests = [ + Test { + input: r#"export const foo = 42;"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export let foo = 42;"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export var foo = 42;"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export const foo = () => {};"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export function foo() {}"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export class Foo {}"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export enum Foo {}"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export module Foo {}"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export module "foo" {}"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + Test { + input: r#"export namespace Foo {}"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export type Foo = string;"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export interface Foo {};"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#"export let name1, name2;"#, + named_expected: atom_set!("name1", "name2"), + default_expected: None, + }, + Test { + input: r#"export const name1 = 1, name2 = 2;"#, + named_expected: atom_set!("name1", "name2"), + default_expected: None, + }, + Test { + input: r#"export function* generatorFunc() {}"#, + named_expected: atom_set!("generatorFunc"), + default_expected: None, + }, + Test { + input: r#"export const { name1, name2: bar } = obj;"#, + named_expected: atom_set!("name1", "bar"), + default_expected: None, + }, + Test { + input: r#"export const [name1, name2] = arr;"#, + named_expected: atom_set!("name1", "name2"), + default_expected: None, + }, + Test { + input: r#"export const { name1 = 42 } = arr;"#, + named_expected: atom_set!("name1"), + default_expected: None, + }, + Test { + input: r#"export default function foo() {}"#, + named_expected: atom_set!(), + default_expected: Some("foo".into()), + }, + Test { + input: r#"export default class Foo {}"#, + named_expected: atom_set!(), + default_expected: Some("Foo".into()), + }, + Test { + input: r#"export default interface Foo {}"#, + named_expected: atom_set!(), + default_expected: Some("Foo".into()), + }, + Test { + input: r#"const foo = 42; export default foo;"#, + named_expected: atom_set!(), + default_expected: Some("foo".into()), + }, + Test { + input: r#"export { foo, bar as barAlias };"#, + named_expected: atom_set!("foo", "barAlias"), + default_expected: None, + }, + Test { + input: r#" +export default class Foo {} +export let value1 = 42; +const value2 = "Hello"; +const value3 = "World"; +export { value2 }; +"#, + named_expected: atom_set!("value1", "value2"), + default_expected: Some("Foo".into()), + }, + // overloaded function + Test { + input: r#" +export function foo(a: number): boolean; +export function foo(a: boolean): string; +export function foo(a: number | boolean): boolean | string { + return typeof a === "number" ? true : "hello"; +} +"#, + named_expected: atom_set!("foo"), + default_expected: None, + }, + // The collector deliberately does not handle re-exports, because from + // doc reader's perspective, an example code would become hard to follow + // if it uses re-exported items (as opposed to normal, non-re-exported + // items that would look verbose if an example code explicitly imports + // them). + Test { + input: r#" +export * from "./module1.ts"; +export * as name1 from "./module2.ts"; +export { name2, name3 as N3 } from "./module3.js"; +export { default } from "./module4.ts"; +export { default as myDefault } from "./module5.ts"; +"#, + named_expected: atom_set!(), + default_expected: None, + }, + Test { + input: r#" +export namespace Foo { + export type MyType = string; + export const myValue = 42; + export function myFunc(): boolean; +} +"#, + named_expected: atom_set!("Foo"), + default_expected: None, + }, + Test { + input: r#" +declare namespace Foo { + export type MyType = string; + export const myValue = 42; + export function myFunc(): boolean; +} +"#, + named_expected: atom_set!(), + default_expected: None, + }, + Test { + input: r#" +declare module Foo { + export type MyType = string; + export const myValue = 42; + export function myFunc(): boolean; +} +"#, + named_expected: atom_set!(), + default_expected: None, + }, + Test { + input: r#" +declare global { + export type MyType = string; + export const myValue = 42; + export function myFunc(): boolean; +} +"#, + named_expected: atom_set!(), + default_expected: None, + }, + // The identifier `Foo` conflicts, but `ExportCollector` doesn't do + // anything about it. It is handled by `to_import_specifiers` method. + Test { + input: r#" +export class Foo {} +export default Foo +"#, + named_expected: atom_set!("Foo"), + default_expected: Some("Foo".into()), + }, + ]; + + for test in tests { + let got = helper(test.input); + assert_eq!(got.named_exports, test.named_expected); + assert_eq!(got.default_export, test.default_expected); + } + } +} diff --git a/cli/util/file_watcher.rs b/cli/util/file_watcher.rs index d92d880bc1..8d734af88e 100644 --- a/cli/util/file_watcher.rs +++ b/cli/util/file_watcher.rs @@ -30,7 +30,7 @@ use tokio::sync::mpsc; use tokio::sync::mpsc::UnboundedReceiver; use tokio::time::sleep; -const CLEAR_SCREEN: &str = "\x1B[2J\x1B[1;1H"; +const CLEAR_SCREEN: &str = "\x1B[H\x1B[2J\x1B[3J"; const DEBOUNCE_INTERVAL: Duration = Duration::from_millis(200); struct DebouncedReceiver { diff --git a/cli/util/fs.rs b/cli/util/fs.rs index c414abd591..2c34f486ad 100644 --- a/cli/util/fs.rs +++ b/cli/util/fs.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use std::env::current_dir; use std::fs::OpenOptions; use std::io::Error; use std::io::ErrorKind; @@ -18,11 +17,9 @@ use deno_config::glob::WalkEntry; use deno_core::anyhow::anyhow; use deno_core::anyhow::Context; use deno_core::error::AnyError; -pub use deno_core::normalize_path; use deno_core::unsync::spawn_blocking; use deno_core::ModuleSpecifier; use deno_runtime::deno_fs::FileSystem; -use deno_runtime::deno_node::PathClean; use crate::util::path::get_atomic_file_path; use crate::util::progress_bar::ProgressBar; @@ -39,10 +36,98 @@ pub fn atomic_write_file_with_retries>( file_path: &Path, data: T, mode: u32, +) -> std::io::Result<()> { + struct RealAtomicWriteFileFs { + mode: u32, + } + + impl AtomicWriteFileFs for RealAtomicWriteFileFs { + fn write_file(&self, path: &Path, bytes: &[u8]) -> std::io::Result<()> { + write_file(path, bytes, self.mode) + } + fn rename_file(&self, from: &Path, to: &Path) -> std::io::Result<()> { + std::fs::rename(from, to) + } + fn remove_file(&self, path: &Path) -> std::io::Result<()> { + std::fs::remove_file(path) + } + fn create_dir_all(&self, dir_path: &Path) -> std::io::Result<()> { + std::fs::create_dir_all(dir_path) + } + fn path_exists(&self, path: &Path) -> bool { + path.exists() + } + } + + atomic_write_file_with_retries_and_fs( + &RealAtomicWriteFileFs { mode }, + file_path, + data.as_ref(), + ) +} + +pub trait AtomicWriteFileFs { + fn write_file(&self, path: &Path, bytes: &[u8]) -> std::io::Result<()>; + fn rename_file(&self, from: &Path, to: &Path) -> std::io::Result<()>; + fn remove_file(&self, path: &Path) -> std::io::Result<()>; + fn create_dir_all(&self, dir_path: &Path) -> std::io::Result<()>; + fn path_exists(&self, path: &Path) -> bool; +} + +pub struct AtomicWriteFileFsAdapter<'a> { + pub fs: &'a dyn FileSystem, + pub write_mode: u32, +} + +impl<'a> AtomicWriteFileFs for AtomicWriteFileFsAdapter<'a> { + fn write_file(&self, path: &Path, bytes: &[u8]) -> std::io::Result<()> { + self + .fs + .write_file_sync( + path, + deno_runtime::deno_fs::OpenOptions::write( + true, + false, + false, + Some(self.write_mode), + ), + None, + bytes, + ) + .map_err(|e| e.into_io_error()) + } + + fn rename_file(&self, from: &Path, to: &Path) -> std::io::Result<()> { + self.fs.rename_sync(from, to).map_err(|e| e.into_io_error()) + } + + fn remove_file(&self, path: &Path) -> std::io::Result<()> { + self + .fs + .remove_sync(path, false) + .map_err(|e| e.into_io_error()) + } + + fn create_dir_all(&self, dir_path: &Path) -> std::io::Result<()> { + self + .fs + .mkdir_sync(dir_path, /* recursive */ true, None) + .map_err(|e| e.into_io_error()) + } + + fn path_exists(&self, path: &Path) -> bool { + self.fs.exists_sync(path) + } +} + +pub fn atomic_write_file_with_retries_and_fs>( + fs: &impl AtomicWriteFileFs, + file_path: &Path, + data: T, ) -> std::io::Result<()> { let mut count = 0; loop { - match atomic_write_file(file_path, data.as_ref(), mode) { + match atomic_write_file(fs, file_path, data.as_ref()) { Ok(()) => return Ok(()), Err(err) => { if count >= 5 { @@ -63,63 +148,54 @@ pub fn atomic_write_file_with_retries>( /// /// This also handles creating the directory if a NotFound error /// occurs. -fn atomic_write_file>( +fn atomic_write_file( + fs: &impl AtomicWriteFileFs, file_path: &Path, - data: T, - mode: u32, + data: &[u8], ) -> std::io::Result<()> { fn atomic_write_file_raw( + fs: &impl AtomicWriteFileFs, temp_file_path: &Path, file_path: &Path, data: &[u8], - mode: u32, ) -> std::io::Result<()> { - write_file(temp_file_path, data, mode)?; - std::fs::rename(temp_file_path, file_path).map_err(|err| { - // clean up the created temp file on error - let _ = std::fs::remove_file(temp_file_path); - err - }) + fs.write_file(temp_file_path, data)?; + fs.rename_file(temp_file_path, file_path) + .inspect_err(|_err| { + // clean up the created temp file on error + let _ = fs.remove_file(temp_file_path); + }) } - fn inner(file_path: &Path, data: &[u8], mode: u32) -> std::io::Result<()> { - let temp_file_path = get_atomic_file_path(file_path); + let temp_file_path = get_atomic_file_path(file_path); - if let Err(write_err) = - atomic_write_file_raw(&temp_file_path, file_path, data, mode) - { - if write_err.kind() == ErrorKind::NotFound { - let parent_dir_path = file_path.parent().unwrap(); - match std::fs::create_dir_all(parent_dir_path) { - Ok(()) => { - return atomic_write_file_raw( - &temp_file_path, - file_path, - data, - mode, - ) + if let Err(write_err) = + atomic_write_file_raw(fs, &temp_file_path, file_path, data) + { + if write_err.kind() == ErrorKind::NotFound { + let parent_dir_path = file_path.parent().unwrap(); + match fs.create_dir_all(parent_dir_path) { + Ok(()) => { + return atomic_write_file_raw(fs, &temp_file_path, file_path, data) .map_err(|err| add_file_context_to_err(file_path, err)); - } - Err(create_err) => { - if !parent_dir_path.exists() { - return Err(Error::new( - create_err.kind(), - format!( - "{:#} (for '{}')\nCheck the permission of the directory.", - create_err, - parent_dir_path.display() - ), - )); - } + } + Err(create_err) => { + if !fs.path_exists(parent_dir_path) { + return Err(Error::new( + create_err.kind(), + format!( + "{:#} (for '{}')\nCheck the permission of the directory.", + create_err, + parent_dir_path.display() + ), + )); } } } - return Err(add_file_context_to_err(file_path, write_err)); } - Ok(()) + return Err(add_file_context_to_err(file_path, write_err)); } - - inner(file_path, data.as_ref(), mode) + Ok(()) } /// Creates a std::fs::File handling if the parent does not exist. @@ -201,7 +277,7 @@ pub fn write_file_2>( /// Similar to `std::fs::canonicalize()` but strips UNC prefixes on Windows. pub fn canonicalize_path(path: &Path) -> Result { - Ok(deno_core::strip_unc_prefix(path.canonicalize()?)) + Ok(deno_path_util::strip_unc_prefix(path.canonicalize()?)) } /// Canonicalizes a path which might be non-existent by going up the @@ -213,60 +289,18 @@ pub fn canonicalize_path(path: &Path) -> Result { pub fn canonicalize_path_maybe_not_exists( path: &Path, ) -> Result { - canonicalize_path_maybe_not_exists_with_custom_fn(path, canonicalize_path) + deno_path_util::canonicalize_path_maybe_not_exists(path, &canonicalize_path) } pub fn canonicalize_path_maybe_not_exists_with_fs( path: &Path, fs: &dyn FileSystem, ) -> Result { - canonicalize_path_maybe_not_exists_with_custom_fn(path, |path| { + deno_path_util::canonicalize_path_maybe_not_exists(path, &|path| { fs.realpath_sync(path).map_err(|err| err.into_io_error()) }) } -fn canonicalize_path_maybe_not_exists_with_custom_fn( - path: &Path, - canonicalize: impl Fn(&Path) -> Result, -) -> Result { - let path = path.to_path_buf().clean(); - let mut path = path.as_path(); - let mut names_stack = Vec::new(); - loop { - match canonicalize(path) { - Ok(mut canonicalized_path) => { - for name in names_stack.into_iter().rev() { - canonicalized_path = canonicalized_path.join(name); - } - return Ok(canonicalized_path); - } - Err(err) if err.kind() == ErrorKind::NotFound => { - names_stack.push(match path.file_name() { - Some(name) => name.to_owned(), - None => return Err(err), - }); - path = match path.parent() { - Some(parent) => parent, - None => return Err(err), - }; - } - Err(err) => return Err(err), - } - } -} - -pub fn resolve_from_cwd(path: &Path) -> Result { - let resolved_path = if path.is_absolute() { - path.to_owned() - } else { - let cwd = - current_dir().context("Failed to get current working directory")?; - cwd.join(path) - }; - - Ok(normalize_path(resolved_path)) -} - /// Collects module specifiers that satisfy the given predicate as a file path, by recursively walking `include`. /// Specifiers that start with http and https are left intact. /// Note: This ignores all .git and node_modules folders. @@ -509,10 +543,10 @@ pub fn hard_link_dir_recursive(from: &Path, to: &Path) -> Result<(), AnyError> { Ok(()) } -pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), AnyError> { - let err_mapper = |err: Error| { +pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), Error> { + let err_mapper = |err: Error, kind: Option| { Error::new( - err.kind(), + kind.unwrap_or_else(|| err.kind()), format!( "{}, symlink '{}' -> '{}'", err, @@ -524,12 +558,19 @@ pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), AnyError> { #[cfg(unix)] { use std::os::unix::fs::symlink; - symlink(oldpath, newpath).map_err(err_mapper)?; + symlink(oldpath, newpath).map_err(|e| err_mapper(e, None))?; } #[cfg(not(unix))] { use std::os::windows::fs::symlink_dir; - symlink_dir(oldpath, newpath).map_err(err_mapper)?; + symlink_dir(oldpath, newpath).map_err(|err| { + if let Some(code) = err.raw_os_error() { + if code as u32 == winapi::shared::winerror::ERROR_PRIVILEGE_NOT_HELD { + return err_mapper(err, Some(ErrorKind::PermissionDenied)); + } + } + err_mapper(err, None) + })?; } Ok(()) } @@ -716,29 +757,12 @@ mod tests { use super::*; use deno_core::futures; use deno_core::parking_lot::Mutex; + use deno_path_util::normalize_path; use pretty_assertions::assert_eq; use test_util::PathRef; use test_util::TempDir; use tokio::sync::Notify; - #[test] - fn resolve_from_cwd_child() { - let cwd = current_dir().unwrap(); - assert_eq!(resolve_from_cwd(Path::new("a")).unwrap(), cwd.join("a")); - } - - #[test] - fn resolve_from_cwd_dot() { - let cwd = current_dir().unwrap(); - assert_eq!(resolve_from_cwd(Path::new(".")).unwrap(), cwd); - } - - #[test] - fn resolve_from_cwd_parent() { - let cwd = current_dir().unwrap(); - assert_eq!(resolve_from_cwd(Path::new("a/..")).unwrap(), cwd); - } - #[test] fn test_normalize_path() { assert_eq!(normalize_path(Path::new("a/../b")), PathBuf::from("b")); @@ -756,14 +780,6 @@ mod tests { } } - #[test] - fn resolve_from_cwd_absolute() { - let expected = Path::new("a"); - let cwd = current_dir().unwrap(); - let absolute_expected = cwd.join(expected); - assert_eq!(resolve_from_cwd(expected).unwrap(), absolute_expected); - } - #[test] fn test_collect_specifiers() { fn create_files(dir_path: &PathRef, files: &[&str]) { diff --git a/cli/util/logger.rs b/cli/util/logger.rs index f3510c5020..cdc89411fe 100644 --- a/cli/util/logger.rs +++ b/cli/util/logger.rs @@ -2,6 +2,8 @@ use std::io::Write; +use super::draw_thread::DrawThread; + struct CliLogger(env_logger::Logger); impl CliLogger { @@ -21,7 +23,13 @@ impl log::Log for CliLogger { fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { + // it was considered to hold the draw thread's internal lock + // across logging, but if outputting to stderr blocks then that + // could potentially block other threads that access the draw + // thread's state + DrawThread::hide(); self.0.log(record); + DrawThread::show(); } } @@ -33,8 +41,10 @@ impl log::Log for CliLogger { pub fn init(maybe_level: Option) { let log_level = maybe_level.unwrap_or(log::Level::Info); let logger = env_logger::Builder::from_env( - env_logger::Env::default() - .default_filter_or(log_level.to_level_filter().to_string()), + env_logger::Env::new() + // Use `DENO_LOG` and `DENO_LOG_STYLE` instead of `RUST_` prefix + .filter_or("DENO_LOG", log_level.to_level_filter().to_string()) + .write_style("DENO_LOG_STYLE"), ) // https://github.com/denoland/deno/issues/6641 .filter_module("rustyline", log::LevelFilter::Off) @@ -46,6 +56,15 @@ pub fn init(maybe_level: Option) { // in the cli logger .filter_module("deno::lsp::performance", log::LevelFilter::Debug) .filter_module("rustls", log::LevelFilter::Off) + // swc_ecma_codegen's `srcmap!` macro emits error-level spans only on debug + // build: + // https://github.com/swc-project/swc/blob/74d6478be1eb8cdf1df096c360c159db64b64d8a/crates/swc_ecma_codegen/src/macros.rs#L112 + // We suppress them here to avoid flooding our CI logs in integration tests. + .filter_module("swc_ecma_codegen", log::LevelFilter::Off) + .filter_module("swc_ecma_transforms_optimization", log::LevelFilter::Off) + .filter_module("swc_ecma_parser", log::LevelFilter::Error) + // Suppress span lifecycle logs since they are too verbose + .filter_module("tracing::span", log::LevelFilter::Off) .format(|buf, record| { let mut target = record.target().to_string(); if let Some(line_no) = record.line() { diff --git a/cli/util/mod.rs b/cli/util/mod.rs index b9071c4963..f81a74c449 100644 --- a/cli/util/mod.rs +++ b/cli/util/mod.rs @@ -7,12 +7,14 @@ pub mod console; pub mod diff; pub mod display; pub mod draw_thread; +pub mod extract; pub mod file_watcher; pub mod fs; pub mod logger; pub mod path; pub mod progress_bar; pub mod result; +pub mod retry; pub mod sync; pub mod text_encoding; pub mod unix; diff --git a/cli/util/path.rs b/cli/util/path.rs index 16378e30b0..e4ae6e7cb1 100644 --- a/cli/util/path.rs +++ b/cli/util/path.rs @@ -42,6 +42,21 @@ pub fn get_extension(file_path: &Path) -> Option { .map(|e| e.to_lowercase()); } +pub fn specifier_has_extension( + specifier: &ModuleSpecifier, + searching_ext: &str, +) -> bool { + let Some((_, ext)) = specifier.path().rsplit_once('.') else { + return false; + }; + let searching_ext = searching_ext.strip_prefix('.').unwrap_or(searching_ext); + debug_assert!(!searching_ext.contains('.')); // exts like .d.ts are not implemented here + if ext.len() != searching_ext.len() { + return false; + } + ext.eq_ignore_ascii_case(searching_ext) +} + pub fn get_atomic_dir_path(file_path: &Path) -> PathBuf { let rand = gen_rand_path_component(); let new_file_name = format!( @@ -145,81 +160,11 @@ pub fn relative_specifier( Some(to_percent_decoded_str(&text)) } -/// Gets a path with the specified file stem suffix. -/// -/// Ex. `file.ts` with suffix `_2` returns `file_2.ts` -pub fn path_with_stem_suffix(path: &Path, suffix: &str) -> PathBuf { - if let Some(file_name) = path.file_name().map(|f| f.to_string_lossy()) { - if let Some(file_stem) = path.file_stem().map(|f| f.to_string_lossy()) { - if let Some(ext) = path.extension().map(|f| f.to_string_lossy()) { - return if file_stem.to_lowercase().ends_with(".d") { - path.with_file_name(format!( - "{}{}.{}.{}", - &file_stem[..file_stem.len() - ".d".len()], - suffix, - // maintain casing - &file_stem[file_stem.len() - "d".len()..], - ext - )) - } else { - path.with_file_name(format!("{file_stem}{suffix}.{ext}")) - }; - } - } - - path.with_file_name(format!("{file_name}{suffix}")) - } else { - path.with_file_name(suffix) - } -} - #[cfg_attr(windows, allow(dead_code))] pub fn relative_path(from: &Path, to: &Path) -> Option { pathdiff::diff_paths(to, from) } -/// Gets if the provided character is not supported on all -/// kinds of file systems. -pub fn is_banned_path_char(c: char) -> bool { - matches!(c, '<' | '>' | ':' | '"' | '|' | '?' | '*') -} - -/// Gets a safe local directory name for the provided url. -/// -/// For example: -/// https://deno.land:8080/path -> deno.land_8080/path -pub fn root_url_to_safe_local_dirname(root: &ModuleSpecifier) -> PathBuf { - fn sanitize_segment(text: &str) -> String { - text - .chars() - .map(|c| if is_banned_segment_char(c) { '_' } else { c }) - .collect() - } - - fn is_banned_segment_char(c: char) -> bool { - matches!(c, '/' | '\\') || is_banned_path_char(c) - } - - let mut result = String::new(); - if let Some(domain) = root.domain() { - result.push_str(&sanitize_segment(domain)); - } - if let Some(port) = root.port() { - if !result.is_empty() { - result.push('_'); - } - result.push_str(&port.to_string()); - } - let mut result = PathBuf::from(result); - if let Some(segments) = root.path_segments() { - for segment in segments.filter(|s| !s.is_empty()) { - result = result.join(sanitize_segment(segment)); - } - } - - result -} - /// Slightly different behaviour than the default matching /// where an exact path needs to be matched to be opted-in /// rather than just a partial directory match. @@ -406,43 +351,15 @@ mod test { } #[test] - fn test_path_with_stem_suffix() { - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/"), "_2"), - PathBuf::from("/_2") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test"), "_2"), - PathBuf::from("/test_2") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test.txt"), "_2"), - PathBuf::from("/test_2.txt") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test/subdir"), "_2"), - PathBuf::from("/test/subdir_2") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test/subdir.other.txt"), "_2"), - PathBuf::from("/test/subdir.other_2.txt") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test.d.ts"), "_2"), - PathBuf::from("/test_2.d.ts") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test.D.TS"), "_2"), - PathBuf::from("/test_2.D.TS") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test.d.mts"), "_2"), - PathBuf::from("/test_2.d.mts") - ); - assert_eq!( - path_with_stem_suffix(&PathBuf::from("/test.d.cts"), "_2"), - PathBuf::from("/test_2.d.cts") - ); + fn test_specifier_has_extension() { + fn get(specifier: &str, ext: &str) -> bool { + specifier_has_extension(&ModuleSpecifier::parse(specifier).unwrap(), ext) + } + + assert!(get("file:///a/b/c.ts", "ts")); + assert!(get("file:///a/b/c.ts", ".ts")); + assert!(!get("file:///a/b/c.ts", ".cts")); + assert!(get("file:///a/b/c.CtS", ".cts")); } #[test] diff --git a/cli/util/retry.rs b/cli/util/retry.rs new file mode 100644 index 0000000000..a8febe60de --- /dev/null +++ b/cli/util/retry.rs @@ -0,0 +1,41 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::future::Future; +use std::time::Duration; + +pub fn retry< + F: FnMut() -> Fut, + T, + E, + Fut: Future>, + ShouldRetry: FnMut(&E) -> bool, +>( + mut f: F, + mut should_retry: ShouldRetry, +) -> impl Future> { + const WAITS: [Duration; 3] = [ + Duration::from_millis(100), + Duration::from_millis(250), + Duration::from_millis(500), + ]; + + let mut waits = WAITS.into_iter(); + async move { + let mut first_result = None; + loop { + let result = f().await; + match result { + Ok(r) => return Ok(r), + Err(e) if !should_retry(&e) => return Err(e), + _ => {} + } + if first_result.is_none() { + first_result = Some(result); + } + let Some(wait) = waits.next() else { + return first_result.unwrap(); + }; + tokio::time::sleep(wait).await; + } + } +} diff --git a/cli/util/text_encoding.rs b/cli/util/text_encoding.rs index d2e0832c95..df72cc2be6 100644 --- a/cli/util/text_encoding.rs +++ b/cli/util/text_encoding.rs @@ -1,6 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; use std::ops::Range; +use std::sync::Arc; use base64::prelude::BASE64_STANDARD; use base64::Engine; @@ -9,6 +11,15 @@ use deno_core::ModuleSourceCode; static SOURCE_MAP_PREFIX: &[u8] = b"//# sourceMappingURL=data:application/json;base64,"; +pub fn from_utf8_lossy_owned(bytes: Vec) -> String { + match String::from_utf8_lossy(&bytes) { + Cow::Owned(code) => code, + // SAFETY: `String::from_utf8_lossy` guarantees that the result is valid + // UTF-8 if `Cow::Borrowed` is returned. + Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(bytes) }, + } +} + pub fn source_map_from_code(code: &[u8]) -> Option> { let range = find_source_map_range(code)?; let source_map_range = &code[range]; @@ -85,6 +96,28 @@ fn find_source_map_range(code: &[u8]) -> Option> { } } +/// Converts an `Arc` to an `Arc<[u8]>`. +pub fn arc_str_to_bytes(arc_str: Arc) -> Arc<[u8]> { + let raw = Arc::into_raw(arc_str); + // SAFETY: This is safe because they have the same memory layout. + unsafe { Arc::from_raw(raw as *const [u8]) } +} + +/// Converts an `Arc` to an `Arc` if able. +#[allow(dead_code)] +pub fn arc_u8_to_arc_str( + arc_u8: Arc<[u8]>, +) -> Result, std::str::Utf8Error> { + // Check that the string is valid UTF-8. + std::str::from_utf8(&arc_u8)?; + // SAFETY: the string is valid UTF-8, and the layout Arc<[u8]> is the same as + // Arc. This is proven by the From> impl for Arc<[u8]> from the + // standard library. + Ok(unsafe { + std::mem::transmute::, std::sync::Arc>(arc_u8) + }) +} + #[cfg(test)] mod tests { use std::sync::Arc; diff --git a/cli/version.rs b/cli/version.rs index dbd63f614e..0cdb32102a 100644 --- a/cli/version.rs +++ b/cli/version.rs @@ -9,6 +9,8 @@ const TYPESCRIPT: &str = env!("TS_VERSION"); const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); // TODO(bartlomieju): ideally we could remove this const. const IS_CANARY: bool = option_env!("DENO_CANARY").is_some(); +// TODO(bartlomieju): this is temporary, to allow Homebrew to cut RC releases as well +const IS_RC: bool = option_env!("DENO_RC").is_some(); pub static DENO_VERSION_INFO: Lazy = Lazy::new(|| { let release_channel = libsui::find_section("denover") @@ -17,6 +19,8 @@ pub static DENO_VERSION_INFO: Lazy = Lazy::new(|| { .unwrap_or({ if IS_CANARY { ReleaseChannel::Canary + } else if IS_RC { + ReleaseChannel::Rc } else { ReleaseChannel::Stable } diff --git a/cli/worker.rs b/cli/worker.rs index 09aa1aec49..e230197d2b 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -29,11 +29,14 @@ use deno_runtime::deno_tls::RootCertStoreProvider; use deno_runtime::deno_web::BlobStore; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::inspector_server::InspectorServer; +use deno_runtime::ops::process::NpmProcessStateProviderRc; use deno_runtime::ops::worker_host::CreateWebWorkerCb; use deno_runtime::web_worker::WebWorker; use deno_runtime::web_worker::WebWorkerOptions; +use deno_runtime::web_worker::WebWorkerServiceOptions; use deno_runtime::worker::MainWorker; use deno_runtime::worker::WorkerOptions; +use deno_runtime::worker::WorkerServiceOptions; use deno_runtime::BootstrapOptions; use deno_runtime::WorkerExecutionMode; use deno_runtime::WorkerLogLevel; @@ -48,9 +51,11 @@ use crate::args::DenoSubcommand; use crate::args::StorageKeyResolver; use crate::errors; use crate::npm::CliNpmResolver; +use crate::resolver::CjsResolutionStore; use crate::util::checksum; use crate::util::file_watcher::WatcherCommunicator; use crate::util::file_watcher::WatcherRestartMode; +use crate::util::path::specifier_has_extension; use crate::version; pub struct ModuleLoaderAndSourceMapGetter { @@ -61,13 +66,12 @@ pub trait ModuleLoaderFactory: Send + Sync { fn create_for_main( &self, root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter; fn create_for_worker( &self, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, + parent_permissions: PermissionsContainer, + permissions: PermissionsContainer, ) -> ModuleLoaderAndSourceMapGetter; } @@ -112,36 +116,35 @@ pub struct CliMainWorkerOptions { pub origin_data_folder_path: Option, pub seed: Option, pub unsafely_ignore_certificate_errors: Option>, - pub unstable: bool, pub skip_op_registration: bool, pub create_hmr_runner: Option, pub create_coverage_collector: Option, + pub node_ipc: Option, + pub serve_port: Option, + pub serve_host: Option, + pub unstable_detect_cjs: bool, } struct SharedWorkerState { - options: CliMainWorkerOptions, - subcommand: DenoSubcommand, - storage_key_resolver: StorageKeyResolver, - npm_resolver: Arc, - node_resolver: Arc, blob_store: Arc, broadcast_channel: InMemoryBroadcastChannel, - shared_array_buffer_store: SharedArrayBufferStore, + cjs_resolution_store: Arc, + code_cache: Option>, compiled_wasm_module_store: CompiledWasmModuleStore, - module_loader_factory: Box, - root_cert_store_provider: Arc, + feature_checker: Arc, fs: Arc, maybe_file_watcher_communicator: Option>, maybe_inspector_server: Option>, maybe_lockfile: Option>, - feature_checker: Arc, - node_ipc: Option, - enable_future_features: bool, - disable_deprecated_api_warning: bool, - verbose_deprecated_api_warning: bool, - code_cache: Option>, - serve_port: Option, - serve_host: Option, + module_loader_factory: Box, + node_resolver: Arc, + npm_resolver: Arc, + root_cert_store_provider: Arc, + root_permissions: PermissionsContainer, + shared_array_buffer_store: SharedArrayBufferStore, + storage_key_resolver: StorageKeyResolver, + options: CliMainWorkerOptions, + subcommand: DenoSubcommand, } impl SharedWorkerState { @@ -149,13 +152,13 @@ impl SharedWorkerState { NodeExtInitServices { node_require_resolver: self.npm_resolver.clone().into_require_resolver(), node_resolver: self.node_resolver.clone(), - npm_process_state_provider: self - .npm_resolver - .clone() - .into_process_state_provider(), npm_resolver: self.npm_resolver.clone().into_npm_resolver(), } } + + pub fn npm_process_state_provider(&self) -> NpmProcessStateProviderRc { + self.npm_resolver.clone().into_process_state_provider() + } } pub struct CliMainWorker { @@ -422,52 +425,44 @@ pub struct CliMainWorkerFactory { impl CliMainWorkerFactory { #[allow(clippy::too_many_arguments)] pub fn new( - storage_key_resolver: StorageKeyResolver, - subcommand: DenoSubcommand, - npm_resolver: Arc, - node_resolver: Arc, blob_store: Arc, - module_loader_factory: Box, - root_cert_store_provider: Arc, + cjs_resolution_store: Arc, + code_cache: Option>, + feature_checker: Arc, fs: Arc, maybe_file_watcher_communicator: Option>, maybe_inspector_server: Option>, maybe_lockfile: Option>, - feature_checker: Arc, + module_loader_factory: Box, + node_resolver: Arc, + npm_resolver: Arc, + root_cert_store_provider: Arc, + root_permissions: PermissionsContainer, + storage_key_resolver: StorageKeyResolver, + subcommand: DenoSubcommand, options: CliMainWorkerOptions, - node_ipc: Option, - serve_port: Option, - serve_host: Option, - enable_future_features: bool, - disable_deprecated_api_warning: bool, - verbose_deprecated_api_warning: bool, - code_cache: Option>, ) -> Self { Self { shared: Arc::new(SharedWorkerState { - options, - subcommand, - storage_key_resolver, - npm_resolver, - node_resolver, blob_store, broadcast_channel: Default::default(), - shared_array_buffer_store: Default::default(), + cjs_resolution_store, + code_cache, compiled_wasm_module_store: Default::default(), - module_loader_factory, - root_cert_store_provider, + feature_checker, fs, maybe_file_watcher_communicator, maybe_inspector_server, maybe_lockfile, - feature_checker, - node_ipc, - serve_port, - serve_host, - enable_future_features, - disable_deprecated_api_warning, - verbose_deprecated_api_warning, - code_cache, + module_loader_factory, + node_resolver, + npm_resolver, + root_cert_store_provider, + root_permissions, + shared_array_buffer_store: Default::default(), + storage_key_resolver, + options, + subcommand, }), } } @@ -476,13 +471,12 @@ impl CliMainWorkerFactory { &self, mode: WorkerExecutionMode, main_module: ModuleSpecifier, - permissions: PermissionsContainer, ) -> Result { self .create_custom_worker( mode, main_module, - permissions, + self.shared.root_permissions.clone(), vec![], Default::default(), ) @@ -498,6 +492,9 @@ impl CliMainWorkerFactory { stdio: deno_runtime::deno_io::Stdio, ) -> Result { let shared = &self.shared; + let ModuleLoaderAndSourceMapGetter { module_loader } = shared + .module_loader_factory + .create_for_main(permissions.clone()); let (main_module, is_main_cjs) = if let Ok(package_ref) = NpmPackageReqReference::from_specifier(&main_module) { @@ -538,12 +535,29 @@ impl CliMainWorkerFactory { let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else { - (main_module, false) + let is_maybe_cjs_js_ext = self.shared.options.unstable_detect_cjs + && specifier_has_extension(&main_module, "js") + && self + .shared + .node_resolver + .get_closest_package_json(&main_module) + .ok() + .flatten() + .map(|pkg_json| pkg_json.typ == "commonjs") + .unwrap_or(false); + let is_cjs = if is_maybe_cjs_js_ext { + // fill the cjs resolution store by preparing the module load + module_loader + .prepare_load(&main_module, None, false) + .await?; + self.shared.cjs_resolution_store.is_known_cjs(&main_module) + } else { + main_module.scheme() == "file" + && specifier_has_extension(&main_module, "cjs") + }; + (main_module, is_cjs) }; - let ModuleLoaderAndSourceMapGetter { module_loader } = shared - .module_loader_factory - .create_for_main(PermissionsContainer::allow_all(), permissions.clone()); let maybe_inspector_server = shared.maybe_inspector_server.clone(); let create_web_worker_cb = @@ -573,12 +587,28 @@ impl CliMainWorkerFactory { let feature_checker = shared.feature_checker.clone(); let mut unstable_features = Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len()); - for (feature_name, _, id) in crate::UNSTABLE_GRANULAR_FLAGS { - if feature_checker.check(feature_name) { - unstable_features.push(*id); + for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS { + if feature_checker.check(granular_flag.name) { + unstable_features.push(granular_flag.id); } } + let services = WorkerServiceOptions { + root_cert_store_provider: Some(shared.root_cert_store_provider.clone()), + module_loader, + fs: shared.fs.clone(), + node_services: Some(shared.create_node_init_services()), + npm_process_state_provider: Some(shared.npm_process_state_provider()), + blob_store: shared.blob_store.clone(), + broadcast_channel: shared.broadcast_channel.clone(), + shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), + compiled_wasm_module_store: Some( + shared.compiled_wasm_module_store.clone(), + ), + feature_checker, + permissions, + v8_code_cache: shared.code_cache.clone(), + }; let options = WorkerOptions { bootstrap: BootstrapOptions { deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(), @@ -595,20 +625,16 @@ impl CliMainWorkerFactory { is_stdout_tty: deno_terminal::is_stdout_tty(), is_stderr_tty: deno_terminal::is_stderr_tty(), color_level: colors::get_color_level(), - unstable: shared.options.unstable, unstable_features, user_agent: version::DENO_VERSION_INFO.user_agent.to_string(), inspect: shared.options.is_inspecting, has_node_modules_dir: shared.options.has_node_modules_dir, argv0: shared.options.argv0.clone(), node_debug: shared.options.node_debug.clone(), - node_ipc_fd: shared.node_ipc, - disable_deprecated_api_warning: shared.disable_deprecated_api_warning, - verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning, - future: shared.enable_future_features, + node_ipc_fd: shared.options.node_ipc, mode, - serve_port: shared.serve_port, - serve_host: shared.serve_host.clone(), + serve_port: shared.options.serve_port, + serve_host: shared.options.serve_host.clone(), }, extensions: custom_extensions, startup_snapshot: crate::js::deno_isolate_init(), @@ -617,7 +643,6 @@ impl CliMainWorkerFactory { .options .unsafely_ignore_certificate_errors .clone(), - root_cert_store_provider: Some(shared.root_cert_store_provider.clone()), seed: shared.options.seed, format_js_error_fn: Some(Arc::new(format_js_error)), create_web_worker_cb, @@ -625,27 +650,16 @@ impl CliMainWorkerFactory { should_break_on_first_statement: shared.options.inspect_brk, should_wait_for_inspector_session: shared.options.inspect_wait, strace_ops: shared.options.strace_ops.clone(), - module_loader, - fs: shared.fs.clone(), - node_services: Some(shared.create_node_init_services()), get_error_class_fn: Some(&errors::get_error_class_name), cache_storage_dir, origin_storage_dir, - blob_store: shared.blob_store.clone(), - broadcast_channel: shared.broadcast_channel.clone(), - shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), - compiled_wasm_module_store: Some( - shared.compiled_wasm_module_store.clone(), - ), stdio, - feature_checker, skip_op_registration: shared.options.skip_op_registration, - v8_code_cache: shared.code_cache.clone(), }; let mut worker = MainWorker::bootstrap_from_options( main_module.clone(), - permissions, + services, options, ); @@ -771,13 +785,32 @@ fn create_web_worker_callback( let feature_checker = shared.feature_checker.clone(); let mut unstable_features = Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len()); - for (feature_name, _, id) in crate::UNSTABLE_GRANULAR_FLAGS { - if feature_checker.check(feature_name) { - unstable_features.push(*id); + for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS { + if feature_checker.check(granular_flag.name) { + unstable_features.push(granular_flag.id); } } + let services = WebWorkerServiceOptions { + root_cert_store_provider: Some(shared.root_cert_store_provider.clone()), + module_loader, + fs: shared.fs.clone(), + node_services: Some(shared.create_node_init_services()), + blob_store: shared.blob_store.clone(), + broadcast_channel: shared.broadcast_channel.clone(), + shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), + compiled_wasm_module_store: Some( + shared.compiled_wasm_module_store.clone(), + ), + maybe_inspector_server, + feature_checker, + npm_process_state_provider: Some(shared.npm_process_state_provider()), + permissions: args.permissions, + }; let options = WebWorkerOptions { + name: args.name, + main_module: args.main_module.clone(), + worker_id: args.worker_id, bootstrap: BootstrapOptions { deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(), args: shared.options.argv.clone(), @@ -788,12 +821,11 @@ fn create_web_worker_callback( enable_op_summary_metrics: shared.options.enable_op_summary_metrics, enable_testing_features: shared.options.enable_testing_features, locale: deno_core::v8::icu::get_language_tag(), - location: Some(args.main_module.clone()), + location: Some(args.main_module), no_color: !colors::use_color(), color_level: colors::get_color_level(), is_stdout_tty: deno_terminal::is_stdout_tty(), is_stderr_tty: deno_terminal::is_stderr_tty(), - unstable: shared.options.unstable, unstable_features, user_agent: version::DENO_VERSION_INFO.user_agent.to_string(), inspect: shared.options.is_inspecting, @@ -801,12 +833,9 @@ fn create_web_worker_callback( argv0: shared.options.argv0.clone(), node_debug: shared.options.node_debug.clone(), node_ipc_fd: None, - disable_deprecated_api_warning: shared.disable_deprecated_api_warning, - verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning, - future: shared.enable_future_features, mode: WorkerExecutionMode::Worker, - serve_port: shared.serve_port, - serve_host: shared.serve_host.clone(), + serve_port: shared.options.serve_port, + serve_host: shared.options.serve_host.clone(), }, extensions: vec![], startup_snapshot: crate::js::deno_isolate_init(), @@ -814,37 +843,19 @@ fn create_web_worker_callback( .options .unsafely_ignore_certificate_errors .clone(), - root_cert_store_provider: Some(shared.root_cert_store_provider.clone()), seed: shared.options.seed, create_web_worker_cb, format_js_error_fn: Some(Arc::new(format_js_error)), - module_loader, - fs: shared.fs.clone(), - node_services: Some(shared.create_node_init_services()), worker_type: args.worker_type, - maybe_inspector_server, get_error_class_fn: Some(&errors::get_error_class_name), - blob_store: shared.blob_store.clone(), - broadcast_channel: shared.broadcast_channel.clone(), - shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), - compiled_wasm_module_store: Some( - shared.compiled_wasm_module_store.clone(), - ), stdio: stdio.clone(), cache_storage_dir, - feature_checker, strace_ops: shared.options.strace_ops.clone(), close_on_idle: args.close_on_idle, maybe_worker_metadata: args.maybe_worker_metadata, }; - WebWorker::bootstrap_from_options( - args.name, - args.permissions, - args.main_module, - args.worker_id, - options, - ) + WebWorker::bootstrap_from_options(services, options) }) } @@ -854,20 +865,43 @@ fn create_web_worker_callback( mod tests { use super::*; use deno_core::resolve_path; + use deno_core::FsModuleLoader; + use deno_fs::RealFs; use deno_runtime::deno_permissions::Permissions; + use deno_runtime::permissions::RuntimePermissionDescriptorParser; fn create_test_worker() -> MainWorker { let main_module = resolve_path("./hello.js", &std::env::current_dir().unwrap()).unwrap(); - let permissions = - PermissionsContainer::new(Permissions::none_without_prompt()); - + let fs = Arc::new(RealFs); + let permission_desc_parser = + Arc::new(RuntimePermissionDescriptorParser::new(fs.clone())); let options = WorkerOptions { startup_snapshot: crate::js::deno_isolate_init(), ..Default::default() }; - MainWorker::bootstrap_from_options(main_module, permissions, options) + MainWorker::bootstrap_from_options( + main_module, + WorkerServiceOptions { + module_loader: Rc::new(FsModuleLoader), + permissions: PermissionsContainer::new( + permission_desc_parser, + Permissions::none_without_prompt(), + ), + blob_store: Default::default(), + broadcast_channel: Default::default(), + feature_checker: Default::default(), + node_services: Default::default(), + npm_process_state_provider: Default::default(), + root_cert_store_provider: Default::default(), + shared_array_buffer_store: Default::default(), + compiled_wasm_module_store: Default::default(), + v8_code_cache: Default::default(), + fs, + }, + options, + ) } #[tokio::test] diff --git a/ext/broadcast_channel/Cargo.toml b/ext/broadcast_channel/Cargo.toml index 96e1e4614c..845544f0c8 100644 --- a/ext/broadcast_channel/Cargo.toml +++ b/ext/broadcast_channel/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_broadcast_channel" -version = "0.158.0" +version = "0.168.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -16,5 +16,6 @@ path = "lib.rs" [dependencies] async-trait.workspace = true deno_core.workspace = true +thiserror.workspace = true tokio.workspace = true uuid.workspace = true diff --git a/ext/broadcast_channel/in_memory_broadcast_channel.rs b/ext/broadcast_channel/in_memory_broadcast_channel.rs index 00b52a9d60..61dc68e17d 100644 --- a/ext/broadcast_channel/in_memory_broadcast_channel.rs +++ b/ext/broadcast_channel/in_memory_broadcast_channel.rs @@ -3,13 +3,13 @@ use std::sync::Arc; use async_trait::async_trait; -use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use tokio::sync::broadcast; use tokio::sync::mpsc; use uuid::Uuid; use crate::BroadcastChannel; +use crate::BroadcastChannelError; #[derive(Clone)] pub struct InMemoryBroadcastChannel(Arc>>); @@ -41,7 +41,7 @@ impl Default for InMemoryBroadcastChannel { impl BroadcastChannel for InMemoryBroadcastChannel { type Resource = InMemoryBroadcastChannelResource; - fn subscribe(&self) -> Result { + fn subscribe(&self) -> Result { let (cancel_tx, cancel_rx) = mpsc::unbounded_channel(); let broadcast_rx = self.0.lock().subscribe(); let rx = tokio::sync::Mutex::new((broadcast_rx, cancel_rx)); @@ -53,7 +53,10 @@ impl BroadcastChannel for InMemoryBroadcastChannel { }) } - fn unsubscribe(&self, resource: &Self::Resource) -> Result<(), AnyError> { + fn unsubscribe( + &self, + resource: &Self::Resource, + ) -> Result<(), BroadcastChannelError> { Ok(resource.cancel_tx.send(())?) } @@ -62,7 +65,7 @@ impl BroadcastChannel for InMemoryBroadcastChannel { resource: &Self::Resource, name: String, data: Vec, - ) -> Result<(), AnyError> { + ) -> Result<(), BroadcastChannelError> { let name = Arc::new(name); let data = Arc::new(data); let uuid = resource.uuid; @@ -73,7 +76,7 @@ impl BroadcastChannel for InMemoryBroadcastChannel { async fn recv( &self, resource: &Self::Resource, - ) -> Result, AnyError> { + ) -> Result, BroadcastChannelError> { let mut g = resource.rx.lock().await; let (broadcast_rx, cancel_rx) = &mut *g; loop { diff --git a/ext/broadcast_channel/lib.deno_broadcast_channel.d.ts b/ext/broadcast_channel/lib.deno_broadcast_channel.d.ts index ed56de0094..339765ec9c 100644 --- a/ext/broadcast_channel/lib.deno_broadcast_channel.d.ts +++ b/ext/broadcast_channel/lib.deno_broadcast_channel.d.ts @@ -9,7 +9,7 @@ * @category Messaging * @experimental */ -declare interface BroadcastChannelEventMap { +interface BroadcastChannelEventMap { "message": MessageEvent; "messageerror": MessageEvent; } @@ -18,7 +18,7 @@ declare interface BroadcastChannelEventMap { * @category Messaging * @experimental */ -declare interface BroadcastChannel extends EventTarget { +interface BroadcastChannel extends EventTarget { /** * Returns the channel name (as passed to the constructor). */ diff --git a/ext/broadcast_channel/lib.rs b/ext/broadcast_channel/lib.rs index 4375809712..c1de118a36 100644 --- a/ext/broadcast_channel/lib.rs +++ b/ext/broadcast_channel/lib.rs @@ -10,34 +10,69 @@ use std::path::PathBuf; use std::rc::Rc; use async_trait::async_trait; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::JsBuffer; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; +use tokio::sync::broadcast::error::SendError as BroadcastSendError; +use tokio::sync::mpsc::error::SendError as MpscSendError; pub const UNSTABLE_FEATURE_NAME: &str = "broadcast-channel"; +#[derive(Debug, thiserror::Error)] +pub enum BroadcastChannelError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + MPSCSendError(MpscSendError>), + #[error(transparent)] + BroadcastSendError( + BroadcastSendError>, + ), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + +impl From> + for BroadcastChannelError +{ + fn from(value: MpscSendError) -> Self { + BroadcastChannelError::MPSCSendError(MpscSendError(Box::new(value.0))) + } +} +impl From> + for BroadcastChannelError +{ + fn from(value: BroadcastSendError) -> Self { + BroadcastChannelError::BroadcastSendError(BroadcastSendError(Box::new( + value.0, + ))) + } +} + #[async_trait] pub trait BroadcastChannel: Clone { type Resource: Resource; - fn subscribe(&self) -> Result; + fn subscribe(&self) -> Result; - fn unsubscribe(&self, resource: &Self::Resource) -> Result<(), AnyError>; + fn unsubscribe( + &self, + resource: &Self::Resource, + ) -> Result<(), BroadcastChannelError>; async fn send( &self, resource: &Self::Resource, name: String, data: Vec, - ) -> Result<(), AnyError>; + ) -> Result<(), BroadcastChannelError>; async fn recv( &self, resource: &Self::Resource, - ) -> Result, AnyError>; + ) -> Result, BroadcastChannelError>; } pub type Message = (String, Vec); @@ -46,16 +81,13 @@ pub type Message = (String, Vec); #[smi] pub fn op_broadcast_subscribe( state: &mut OpState, -) -> Result +) -> Result where BC: BroadcastChannel + 'static, { - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` - state.feature_checker.check_or_exit_with_legacy_fallback( - UNSTABLE_FEATURE_NAME, - "BroadcastChannel", - ); + state + .feature_checker + .check_or_exit(UNSTABLE_FEATURE_NAME, "BroadcastChannel"); let bc = state.borrow::(); let resource = bc.subscribe()?; Ok(state.resource_table.add(resource)) @@ -65,11 +97,14 @@ where pub fn op_broadcast_unsubscribe( state: &mut OpState, #[smi] rid: ResourceId, -) -> Result<(), AnyError> +) -> Result<(), BroadcastChannelError> where BC: BroadcastChannel + 'static, { - let resource = state.resource_table.get::(rid)?; + let resource = state + .resource_table + .get::(rid) + .map_err(BroadcastChannelError::Resource)?; let bc = state.borrow::(); bc.unsubscribe(&resource) } @@ -80,11 +115,15 @@ pub async fn op_broadcast_send( #[smi] rid: ResourceId, #[string] name: String, #[buffer] buf: JsBuffer, -) -> Result<(), AnyError> +) -> Result<(), BroadcastChannelError> where BC: BroadcastChannel + 'static, { - let resource = state.borrow().resource_table.get::(rid)?; + let resource = state + .borrow() + .resource_table + .get::(rid) + .map_err(BroadcastChannelError::Resource)?; let bc = state.borrow().borrow::().clone(); bc.send(&resource, name, buf.to_vec()).await } @@ -94,11 +133,15 @@ where pub async fn op_broadcast_recv( state: Rc>, #[smi] rid: ResourceId, -) -> Result, AnyError> +) -> Result, BroadcastChannelError> where BC: BroadcastChannel + 'static, { - let resource = state.borrow().resource_table.get::(rid)?; + let resource = state + .borrow() + .resource_table + .get::(rid) + .map_err(BroadcastChannelError::Resource)?; let bc = state.borrow().borrow::().clone(); bc.recv(&resource).await } diff --git a/ext/cache/01_cache.js b/ext/cache/01_cache.js index a5bcde598f..269261f401 100644 --- a/ext/cache/01_cache.js +++ b/ext/cache/01_cache.js @@ -105,7 +105,7 @@ class Cache { const reqUrl = new URL(innerRequest.url()); if (reqUrl.protocol !== "http:" && reqUrl.protocol !== "https:") { throw new TypeError( - "Request url protocol must be 'http:' or 'https:'", + `Request url protocol must be 'http:' or 'https:': received '${reqUrl.protocol}'`, ); } if (innerRequest.method !== "GET") { diff --git a/ext/cache/Cargo.toml b/ext/cache/Cargo.toml index 8a15c9d9ce..a07a8f7207 100644 --- a/ext/cache/Cargo.toml +++ b/ext/cache/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_cache" -version = "0.96.0" +version = "0.106.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -19,4 +19,5 @@ deno_core.workspace = true rusqlite.workspace = true serde.workspace = true sha2.workspace = true +thiserror.workspace = true tokio.workspace = true diff --git a/ext/cache/lib.deno_cache.d.ts b/ext/cache/lib.deno_cache.d.ts index f28de94cee..f9e1818482 100644 --- a/ext/cache/lib.deno_cache.d.ts +++ b/ext/cache/lib.deno_cache.d.ts @@ -9,7 +9,7 @@ declare var caches: CacheStorage; /** @category Cache */ -declare interface CacheStorage { +interface CacheStorage { /** Open a cache storage for the provided name. */ open(cacheName: string): Promise; /** Check if cache already exists for the provided name. */ @@ -19,7 +19,7 @@ declare interface CacheStorage { } /** @category Cache */ -declare interface Cache { +interface Cache { /** * Put the provided request/response into the cache. * @@ -65,7 +65,7 @@ declare var CacheStorage: { }; /** @category Cache */ -declare interface CacheQueryOptions { +interface CacheQueryOptions { ignoreMethod?: boolean; ignoreSearch?: boolean; ignoreVary?: boolean; diff --git a/ext/cache/lib.rs b/ext/cache/lib.rs index e399b08e07..b9cc5427c2 100644 --- a/ext/cache/lib.rs +++ b/ext/cache/lib.rs @@ -7,7 +7,6 @@ use std::sync::Arc; use async_trait::async_trait; use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::serde::Deserialize; use deno_core::serde::Serialize; @@ -19,6 +18,20 @@ use deno_core::ResourceId; mod sqlite; pub use sqlite::SqliteBackedCache; +#[derive(Debug, thiserror::Error)] +pub enum CacheError { + #[error(transparent)] + Sqlite(#[from] rusqlite::Error), + #[error(transparent)] + JoinError(#[from] tokio::task::JoinError), + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + Other(deno_core::error::AnyError), + #[error("{0}")] + Io(#[from] std::io::Error), +} + #[derive(Clone)] pub struct CreateCache(pub Arc C>); @@ -92,26 +105,31 @@ pub struct CacheDeleteRequest { pub trait Cache: Clone + 'static { type CacheMatchResourceType: Resource; - async fn storage_open(&self, cache_name: String) -> Result; - async fn storage_has(&self, cache_name: String) -> Result; - async fn storage_delete(&self, cache_name: String) -> Result; + async fn storage_open(&self, cache_name: String) -> Result; + async fn storage_has(&self, cache_name: String) -> Result; + async fn storage_delete( + &self, + cache_name: String, + ) -> Result; /// Put a resource into the cache. async fn put( &self, request_response: CachePutRequest, resource: Option>, - ) -> Result<(), AnyError>; + ) -> Result<(), CacheError>; async fn r#match( &self, request: CacheMatchRequest, ) -> Result< Option<(CacheMatchResponseMeta, Option)>, - AnyError, + CacheError, >; - async fn delete(&self, request: CacheDeleteRequest) - -> Result; + async fn delete( + &self, + request: CacheDeleteRequest, + ) -> Result; } #[op2(async)] @@ -119,7 +137,7 @@ pub trait Cache: Clone + 'static { pub async fn op_cache_storage_open( state: Rc>, #[string] cache_name: String, -) -> Result +) -> Result where CA: Cache, { @@ -131,7 +149,7 @@ where pub async fn op_cache_storage_has( state: Rc>, #[string] cache_name: String, -) -> Result +) -> Result where CA: Cache, { @@ -143,7 +161,7 @@ where pub async fn op_cache_storage_delete( state: Rc>, #[string] cache_name: String, -) -> Result +) -> Result where CA: Cache, { @@ -155,13 +173,19 @@ where pub async fn op_cache_put( state: Rc>, #[serde] request_response: CachePutRequest, -) -> Result<(), AnyError> +) -> Result<(), CacheError> where CA: Cache, { let cache = get_cache::(&state)?; let resource = match request_response.response_rid { - Some(rid) => Some(state.borrow_mut().resource_table.take_any(rid)?), + Some(rid) => Some( + state + .borrow_mut() + .resource_table + .take_any(rid) + .map_err(CacheError::Resource)?, + ), None => None, }; cache.put(request_response, resource).await @@ -172,7 +196,7 @@ where pub async fn op_cache_match( state: Rc>, #[serde] request: CacheMatchRequest, -) -> Result, AnyError> +) -> Result, CacheError> where CA: Cache, { @@ -191,7 +215,7 @@ where pub async fn op_cache_delete( state: Rc>, #[serde] request: CacheDeleteRequest, -) -> Result +) -> Result where CA: Cache, { @@ -199,7 +223,7 @@ where cache.delete(request).await } -pub fn get_cache(state: &Rc>) -> Result +pub fn get_cache(state: &Rc>) -> Result where CA: Cache, { @@ -211,7 +235,9 @@ where state.put(cache); Ok(state.borrow::().clone()) } else { - Err(type_error("CacheStorage is not available in this context.")) + Err(CacheError::Other(type_error( + "CacheStorage is not available in this context", + ))) } } diff --git a/ext/cache/sqlite.rs b/ext/cache/sqlite.rs index c3c55dd5e9..e4991c32f1 100644 --- a/ext/cache/sqlite.rs +++ b/ext/cache/sqlite.rs @@ -30,6 +30,7 @@ use crate::serialize_headers; use crate::vary_header_matches; use crate::Cache; use crate::CacheDeleteRequest; +use crate::CacheError; use crate::CacheMatchRequest; use crate::CacheMatchResponseMeta; use crate::CachePutRequest; @@ -102,7 +103,7 @@ impl Cache for SqliteBackedCache { /// Open a cache storage. Internally, this creates a row in the /// sqlite db if the cache doesn't exist and returns the internal id /// of the cache. - async fn storage_open(&self, cache_name: String) -> Result { + async fn storage_open(&self, cache_name: String) -> Result { let db = self.connection.clone(); let cache_storage_dir = self.cache_storage_dir.clone(); spawn_blocking(move || { @@ -121,14 +122,14 @@ impl Cache for SqliteBackedCache { )?; let responses_dir = get_responses_dir(cache_storage_dir, cache_id); std::fs::create_dir_all(responses_dir)?; - Ok::(cache_id) + Ok::(cache_id) }) .await? } /// Check if a cache with the provided name exists. /// Note: this doesn't check the disk, it only checks the sqlite db. - async fn storage_has(&self, cache_name: String) -> Result { + async fn storage_has(&self, cache_name: String) -> Result { let db = self.connection.clone(); spawn_blocking(move || { let db = db.lock(); @@ -140,13 +141,16 @@ impl Cache for SqliteBackedCache { Ok(count > 0) }, )?; - Ok::(cache_exists) + Ok::(cache_exists) }) .await? } /// Delete a cache storage. Internally, this deletes the row in the sqlite db. - async fn storage_delete(&self, cache_name: String) -> Result { + async fn storage_delete( + &self, + cache_name: String, + ) -> Result { let db = self.connection.clone(); let cache_storage_dir = self.cache_storage_dir.clone(); spawn_blocking(move || { @@ -167,7 +171,7 @@ impl Cache for SqliteBackedCache { std::fs::remove_dir_all(cache_dir)?; } } - Ok::(maybe_cache_id.is_some()) + Ok::(maybe_cache_id.is_some()) }) .await? } @@ -176,10 +180,12 @@ impl Cache for SqliteBackedCache { &self, request_response: CachePutRequest, resource: Option>, - ) -> Result<(), AnyError> { + ) -> Result<(), CacheError> { let db = self.connection.clone(); let cache_storage_dir = self.cache_storage_dir.clone(); - let now = SystemTime::now().duration_since(UNIX_EPOCH)?; + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("SystemTime is before unix epoch"); if let Some(resource) = resource { let body_key = hash(&format!( @@ -193,7 +199,11 @@ impl Cache for SqliteBackedCache { let mut file = tokio::fs::File::create(response_path).await?; let mut buf = BufMutView::new(64 * 1024); loop { - let (size, buf2) = resource.clone().read_byob(buf).await?; + let (size, buf2) = resource + .clone() + .read_byob(buf) + .await + .map_err(CacheError::Other)?; if size == 0 { break; } @@ -224,7 +234,7 @@ impl Cache for SqliteBackedCache { request: CacheMatchRequest, ) -> Result< Option<(CacheMatchResponseMeta, Option)>, - AnyError, + CacheError, > { let db = self.connection.clone(); let cache_storage_dir = self.cache_storage_dir.clone(); @@ -290,19 +300,17 @@ impl Cache for SqliteBackedCache { } Err(err) => return Err(err.into()), }; - return Ok(Some((cache_meta, Some(CacheResponseResource::new(file))))); + Ok(Some((cache_meta, Some(CacheResponseResource::new(file))))) } - Some((cache_meta, None)) => { - return Ok(Some((cache_meta, None))); - } - None => return Ok(None), + Some((cache_meta, None)) => Ok(Some((cache_meta, None))), + None => Ok(None), } } async fn delete( &self, request: CacheDeleteRequest, - ) -> Result { + ) -> Result { let db = self.connection.clone(); spawn_blocking(move || { // TODO(@satyarohith): remove the response body from disk if one exists @@ -311,17 +319,17 @@ impl Cache for SqliteBackedCache { "DELETE FROM request_response_list WHERE cache_id = ?1 AND request_url = ?2", (request.cache_id, &request.request_url), )?; - Ok::(rows_effected > 0) + Ok::(rows_effected > 0) }) .await? } } async fn insert_cache_asset( - db: Arc>, + db: Arc>, put: CachePutRequest, response_body_key: Option, -) -> Result, deno_core::anyhow::Error> { +) -> Result, CacheError> { spawn_blocking(move || { let maybe_response_body = { let db = db.lock(); @@ -339,7 +347,7 @@ async fn insert_cache_asset( response_body_key, put.response_status, put.response_status_text, - SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(), + SystemTime::now().duration_since(UNIX_EPOCH).expect("SystemTime is before unix epoch").as_secs(), ), |row| { let response_body_key: Option = row.get(0)?; @@ -347,7 +355,7 @@ async fn insert_cache_asset( }, )? }; - Ok::, AnyError>(maybe_response_body) + Ok::, CacheError>(maybe_response_body) }).await? } diff --git a/ext/canvas/01_image.js b/ext/canvas/01_image.js index 6fb1ee62fc..3ea72db6ac 100644 --- a/ext/canvas/01_image.js +++ b/ext/canvas/01_image.js @@ -307,7 +307,9 @@ function processImage(input, width, height, sx, sy, sw, sh, options) { } if (options.colorSpaceConversion === "none") { - throw new TypeError("options.colorSpaceConversion 'none' is not supported"); + throw new TypeError( + "Cannot create image: invalid colorSpaceConversion option, 'none' is not supported", + ); } /* diff --git a/ext/canvas/Cargo.toml b/ext/canvas/Cargo.toml index 1be761e344..4c125ea9b5 100644 --- a/ext/canvas/Cargo.toml +++ b/ext/canvas/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_canvas" -version = "0.33.0" +version = "0.43.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -18,3 +18,4 @@ deno_core.workspace = true deno_webgpu.workspace = true image = { version = "0.24.7", default-features = false, features = ["png"] } serde = { workspace = true, features = ["derive"] } +thiserror.workspace = true diff --git a/ext/canvas/lib.deno_canvas.d.ts b/ext/canvas/lib.deno_canvas.d.ts index 54ae3e66bd..c695ba5cd8 100644 --- a/ext/canvas/lib.deno_canvas.d.ts +++ b/ext/canvas/lib.deno_canvas.d.ts @@ -12,14 +12,14 @@ * * @category Canvas */ -declare type ColorSpaceConversion = "default" | "none"; +type ColorSpaceConversion = "default" | "none"; /** * Specifies how the bitmap image should be oriented. * * @category Canvas */ -declare type ImageOrientation = "flipY" | "from-image" | "none"; +type ImageOrientation = "flipY" | "from-image" | "none"; /** * Specifies whether the bitmap's color channels should be premultiplied by @@ -27,7 +27,7 @@ declare type ImageOrientation = "flipY" | "from-image" | "none"; * * @category Canvas */ -declare type PremultiplyAlpha = "default" | "none" | "premultiply"; +type PremultiplyAlpha = "default" | "none" | "premultiply"; /** * Specifies the algorithm to be used for resizing the input to match the @@ -35,20 +35,20 @@ declare type PremultiplyAlpha = "default" | "none" | "premultiply"; * * @category Canvas */ -declare type ResizeQuality = "high" | "low" | "medium" | "pixelated"; +type ResizeQuality = "high" | "low" | "medium" | "pixelated"; /** * The `ImageBitmapSource` type represents an image data source that can be * used to create an `ImageBitmap`. * * @category Canvas */ -declare type ImageBitmapSource = Blob | ImageData; +type ImageBitmapSource = Blob | ImageData; /** * The options of {@linkcode createImageBitmap}. * * @category Canvas */ -declare interface ImageBitmapOptions { +interface ImageBitmapOptions { /** * Specifies whether the image should be decoded using color space * conversion. Either none or default (default). The value default @@ -116,7 +116,7 @@ declare function createImageBitmap( * * @category Canvas */ -declare interface ImageBitmap { +interface ImageBitmap { /** * The height of the bitmap. */ diff --git a/ext/canvas/lib.rs b/ext/canvas/lib.rs index 72173f1331..defb288ac9 100644 --- a/ext/canvas/lib.rs +++ b/ext/canvas/lib.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::ToJsBuffer; use image::imageops::FilterType; @@ -13,6 +11,14 @@ use serde::Deserialize; use serde::Serialize; use std::path::PathBuf; +#[derive(Debug, thiserror::Error)] +pub enum CanvasError { + #[error("Color type '{0:?}' not supported")] + UnsupportedColorType(ColorType), + #[error(transparent)] + Image(#[from] image::ImageError), +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "snake_case")] enum ImageResizeQuality { @@ -43,7 +49,7 @@ struct ImageProcessArgs { fn op_image_process( #[buffer] buf: &[u8], #[serde] args: ImageProcessArgs, -) -> Result { +) -> ToJsBuffer { let view = RgbaImage::from_vec(args.width, args.height, buf.to_vec()).unwrap(); @@ -105,7 +111,7 @@ fn op_image_process( } } - Ok(image_out.to_vec().into()) + image_out.to_vec().into() } #[derive(Debug, Serialize)] @@ -117,17 +123,16 @@ struct DecodedPng { #[op2] #[serde] -fn op_image_decode_png(#[buffer] buf: &[u8]) -> Result { +fn op_image_decode_png( + #[buffer] buf: &[u8], +) -> Result { let png = image::codecs::png::PngDecoder::new(buf)?; let (width, height) = png.dimensions(); // TODO(@crowlKats): maybe use DynamicImage https://docs.rs/image/0.24.7/image/enum.DynamicImage.html ? if png.color_type() != ColorType::Rgba8 { - return Err(type_error(format!( - "Color type '{:?}' not supported", - png.color_type() - ))); + return Err(CanvasError::UnsupportedColorType(png.color_type())); } // read_image will assert that the buffer is the correct size, so we need to fill it with zeros diff --git a/ext/console/01_console.js b/ext/console/01_console.js index 6812583e0b..3803492b90 100644 --- a/ext/console/01_console.js +++ b/ext/console/01_console.js @@ -33,6 +33,7 @@ import { op_get_non_index_property_names, op_preview_entries, } from "ext:core/ops"; +import * as ops from "ext:core/ops"; const { Array, ArrayBufferPrototypeGetByteLength, @@ -83,6 +84,8 @@ const { NumberIsInteger, NumberIsNaN, NumberParseInt, + NumberParseFloat, + NumberPrototypeToFixed, NumberPrototypeToString, NumberPrototypeValueOf, ObjectAssign, @@ -151,11 +154,23 @@ const { SymbolPrototypeToString, SymbolPrototypeValueOf, SymbolToStringTag, + TypedArrayPrototypeGetBuffer, TypedArrayPrototypeGetByteLength, TypedArrayPrototypeGetLength, Uint8Array, + Uint32Array, } = primordials; +let currentTime = DateNow; +if (ops.op_now) { + const hrU8 = new Uint8Array(8); + const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8)); + currentTime = function opNow() { + ops.op_now(hrU8); + return (hr[0] * 1000 + hr[1] / 1e6); + }; +} + let noColorStdout = () => false; let noColorStderr = () => false; @@ -179,7 +194,7 @@ class AssertionError extends Error { } } -function assert(cond, msg = "Assertion failed.") { +function assert(cond, msg = "Assertion failed") { if (!cond) { throw new AssertionError(msg); } @@ -260,6 +275,7 @@ const colors = { function defineColorAlias(target, alias) { ObjectDefineProperty(colors, alias, { + __proto__: null, get() { return this[target]; }, @@ -843,14 +859,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) { ObjectPrototypeIsPrototypeOf( globalThis.Temporal.Duration.prototype, value, - ) || - ObjectPrototypeIsPrototypeOf( - globalThis.Temporal.TimeZone.prototype, - value, - ) || - ObjectPrototypeIsPrototypeOf( - globalThis.Temporal.Calendar.prototype, - value, ) ) ) { @@ -1294,6 +1302,9 @@ function getKeys(value, showHidden) { ArrayPrototypePushApply(keys, ArrayPrototypeFilter(symbols, filter)); } } + if (ObjectPrototypeIsPrototypeOf(ErrorPrototype, value)) { + keys = ArrayPrototypeFilter(keys, (key) => key !== "cause"); + } return keys; } @@ -2642,6 +2653,7 @@ const HSL_PATTERN = new SafeRegExp( ); function parseCssColor(colorString) { + colorString = StringPrototypeToLowerCase(colorString); if (colorKeywords.has(colorString)) { colorString = colorKeywords.get(colorString); } @@ -3000,20 +3012,18 @@ function inspectArgs(args, inspectOptions = { __proto__: null }) { } else if (ArrayPrototypeIncludes(["d", "i"], char)) { // Format as an integer. const value = args[a++]; - if (typeof value == "bigint") { - formattedArg = `${value}n`; - } else if (typeof value == "number") { - formattedArg = `${NumberParseInt(String(value))}`; - } else { + if (typeof value === "symbol") { formattedArg = "NaN"; + } else { + formattedArg = `${NumberParseInt(value)}`; } } else if (char == "f") { // Format as a floating point value. const value = args[a++]; - if (typeof value == "number") { - formattedArg = `${value}`; - } else { + if (typeof value === "symbol") { formattedArg = "NaN"; + } else { + formattedArg = `${NumberParseFloat(value)}`; } } else if (ArrayPrototypeIncludes(["O", "o"], char)) { // Format as an object. @@ -3236,8 +3246,8 @@ class Console { table = (data = undefined, properties = undefined) => { if (properties !== undefined && !ArrayIsArray(properties)) { throw new Error( - "The 'properties' argument must be of type Array. " + - "Received type " + typeof properties, + "The 'properties' argument must be of type Array: " + + "received type " + typeof properties, ); } @@ -3247,7 +3257,7 @@ class Console { const stringifyValue = (value) => inspectValueWithQuotes(value, { - ...getDefaultInspectOptions(), + ...getConsoleInspectOptions(noColorStdout()), depth: 1, compact: true, }); @@ -3337,7 +3347,7 @@ class Console { return; } - MapPrototypeSet(timerMap, label, DateNow()); + MapPrototypeSet(timerMap, label, currentTime()); }; timeLog = (label = "default", ...args) => { @@ -3349,7 +3359,16 @@ class Console { } const startTime = MapPrototypeGet(timerMap, label); - const duration = DateNow() - startTime; + let duration = currentTime() - startTime; + if (duration < 1) { + duration = NumberPrototypeToFixed(duration, 3); + } else if (duration < 10) { + duration = NumberPrototypeToFixed(duration, 2); + } else if (duration < 100) { + duration = NumberPrototypeToFixed(duration, 1); + } else { + duration = NumberPrototypeToFixed(duration, 0); + } this.info(`${label}: ${duration}ms`, ...new SafeArrayIterator(args)); }; @@ -3364,7 +3383,16 @@ class Console { const startTime = MapPrototypeGet(timerMap, label); MapPrototypeDelete(timerMap, label); - const duration = DateNow() - startTime; + let duration = currentTime() - startTime; + if (duration < 1) { + duration = NumberPrototypeToFixed(duration, 3); + } else if (duration < 10) { + duration = NumberPrototypeToFixed(duration, 2); + } else if (duration < 100) { + duration = NumberPrototypeToFixed(duration, 1); + } else { + duration = NumberPrototypeToFixed(duration, 0); + } this.info(`${label}: ${duration}ms`); }; @@ -3447,7 +3475,10 @@ function inspect( function createFilteredInspectProxy({ object, keys, evaluate }) { const obj = class {}; if (object.constructor?.name) { - ObjectDefineProperty(obj, "name", { value: object.constructor.name }); + ObjectDefineProperty(obj, "name", { + __proto__: null, + value: object.constructor.name, + }); } return new Proxy(new obj(), { diff --git a/ext/console/Cargo.toml b/ext/console/Cargo.toml index 14fb2407ab..b89f67fece 100644 --- a/ext/console/Cargo.toml +++ b/ext/console/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_console" -version = "0.164.0" +version = "0.174.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/console/lib.deno_console.d.ts b/ext/console/lib.deno_console.d.ts index a4968dc836..0c73972d36 100644 --- a/ext/console/lib.deno_console.d.ts +++ b/ext/console/lib.deno_console.d.ts @@ -6,7 +6,7 @@ /// /** @category I/O */ -declare interface Console { +interface Console { assert(condition?: boolean, ...data: any[]): void; clear(): void; count(label?: string): void; diff --git a/ext/cron/01_cron.ts b/ext/cron/01_cron.ts index 7592e75ef5..b5c556a677 100644 --- a/ext/cron/01_cron.ts +++ b/ext/cron/01_cron.ts @@ -41,7 +41,9 @@ export function formatToCronSchedule( } else if (end === undefined && every !== undefined) { return "*/" + every; } else { - throw new TypeError("Invalid cron schedule"); + throw new TypeError( + `Invalid cron schedule: start=${start}, end=${end}, every=${every}`, + ); } } else { if (typeof exact === "number") { @@ -103,10 +105,14 @@ function cron( handler2?: () => Promise | void, ) { if (name === undefined) { - throw new TypeError("Deno.cron requires a unique name"); + throw new TypeError( + "Cannot create cron job, a unique name is required: received 'undefined'", + ); } if (schedule === undefined) { - throw new TypeError("Deno.cron requires a valid schedule"); + throw new TypeError( + "Cannot create cron job, a schedule is required: received 'undefined'", + ); } schedule = parseScheduleToString(schedule); @@ -119,13 +125,15 @@ function cron( if (typeof handlerOrOptions1 === "function") { handler = handlerOrOptions1; if (handler2 !== undefined) { - throw new TypeError("Deno.cron requires a single handler"); + throw new TypeError( + "Cannot create cron job, a single handler is required: two handlers were specified", + ); } } else if (typeof handler2 === "function") { handler = handler2; options = handlerOrOptions1; } else { - throw new TypeError("Deno.cron requires a handler"); + throw new TypeError("Cannot create cron job: a handler is required"); } const rid = op_cron_create( @@ -157,6 +165,7 @@ function cron( const _res = isPromise(result) ? (await result) : result; success = true; } catch (error) { + // deno-lint-ignore no-console console.error(`Exception in cron handler ${name}`, error); success = false; } diff --git a/ext/cron/Cargo.toml b/ext/cron/Cargo.toml index cf71a7a96e..6c5547c35f 100644 --- a/ext/cron/Cargo.toml +++ b/ext/cron/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_cron" -version = "0.44.0" +version = "0.54.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -19,4 +19,5 @@ async-trait.workspace = true chrono = { workspace = true, features = ["now"] } deno_core.workspace = true saffron.workspace = true +thiserror.workspace = true tokio.workspace = true diff --git a/ext/cron/interface.rs b/ext/cron/interface.rs index 01b1d17895..a19525cc4e 100644 --- a/ext/cron/interface.rs +++ b/ext/cron/interface.rs @@ -1,17 +1,17 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use crate::CronError; use async_trait::async_trait; -use deno_core::error::AnyError; pub trait CronHandler { type EH: CronHandle + 'static; - fn create(&self, spec: CronSpec) -> Result; + fn create(&self, spec: CronSpec) -> Result; } #[async_trait(?Send)] pub trait CronHandle { - async fn next(&self, prev_success: bool) -> Result; + async fn next(&self, prev_success: bool) -> Result; fn close(&self); } diff --git a/ext/cron/lib.rs b/ext/cron/lib.rs index ede01ba45f..feffb5e511 100644 --- a/ext/cron/lib.rs +++ b/ext/cron/lib.rs @@ -7,16 +7,13 @@ use std::borrow::Cow; use std::cell::RefCell; use std::rc::Rc; +pub use crate::interface::*; use deno_core::error::get_custom_error_class; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; -pub use crate::interface::*; - pub const UNSTABLE_FEATURE_NAME: &str = "cron"; deno_core::extension!(deno_cron, @@ -49,6 +46,28 @@ impl Resource for CronResource { } } +#[derive(Debug, thiserror::Error)] +pub enum CronError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("Cron name cannot exceed 64 characters: current length {0}")] + NameExceeded(usize), + #[error("Invalid cron name: only alphanumeric characters, whitespace, hyphens, and underscores are allowed")] + NameInvalid, + #[error("Cron with this name already exists")] + AlreadyExists, + #[error("Too many crons")] + TooManyCrons, + #[error("Invalid cron schedule")] + InvalidCron, + #[error("Invalid backoff schedule")] + InvalidBackoff, + #[error(transparent)] + AcquireError(#[from] tokio::sync::AcquireError), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + #[op2] #[smi] fn op_cron_create( @@ -56,17 +75,15 @@ fn op_cron_create( #[string] name: String, #[string] cron_schedule: String, #[serde] backoff_schedule: Option>, -) -> Result +) -> Result where C: CronHandler + 'static, { let cron_handler = { let state = state.borrow(); - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` state .feature_checker - .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, "Deno.cron"); + .check_or_exit(UNSTABLE_FEATURE_NAME, "Deno.cron"); state.borrow::>().clone() }; @@ -92,7 +109,7 @@ async fn op_cron_next( state: Rc>, #[smi] rid: ResourceId, prev_success: bool, -) -> Result +) -> Result where C: CronHandler + 'static, { @@ -104,7 +121,7 @@ where if get_custom_error_class(&err) == Some("BadResource") { return Ok(false); } else { - return Err(err); + return Err(CronError::Resource(err)); } } }; @@ -114,14 +131,14 @@ where cron_handler.next(prev_success).await } -fn validate_cron_name(name: &str) -> Result<(), AnyError> { +fn validate_cron_name(name: &str) -> Result<(), CronError> { if name.len() > 64 { - return Err(type_error("Cron name is too long")); + return Err(CronError::NameExceeded(name.len())); } if !name.chars().all(|c| { c.is_ascii_whitespace() || c.is_ascii_alphanumeric() || c == '_' || c == '-' }) { - return Err(type_error("Invalid cron name. Only alphanumeric characters, whitespace, hyphens, and underscores are allowed")); + return Err(CronError::NameInvalid); } Ok(()) } diff --git a/ext/cron/local.rs b/ext/cron/local.rs index dd60e750a0..1110baadb8 100644 --- a/ext/cron/local.rs +++ b/ext/cron/local.rs @@ -10,8 +10,6 @@ use std::rc::Weak; use std::sync::Arc; use async_trait::async_trait; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures; use deno_core::futures::FutureExt; use deno_core::unsync::spawn; @@ -21,6 +19,7 @@ use tokio::sync::mpsc::WeakSender; use tokio::sync::OwnedSemaphorePermit; use tokio::sync::Semaphore; +use crate::CronError; use crate::CronHandle; use crate::CronHandler; use crate::CronSpec; @@ -81,7 +80,7 @@ impl LocalCronHandler { async fn cron_loop( runtime_state: Rc>, mut cron_schedule_rx: mpsc::Receiver<(String, bool)>, - ) -> Result<(), AnyError> { + ) -> Result<(), CronError> { loop { let earliest_deadline = runtime_state .borrow() @@ -154,7 +153,7 @@ impl LocalCronHandler { impl RuntimeState { fn get_ready_crons( &mut self, - ) -> Result)>, AnyError> { + ) -> Result)>, CronError> { let now = chrono::Utc::now().timestamp_millis() as u64; let ready = { @@ -191,7 +190,7 @@ impl RuntimeState { impl CronHandler for LocalCronHandler { type EH = CronExecutionHandle; - fn create(&self, spec: CronSpec) -> Result { + fn create(&self, spec: CronSpec) -> Result { // Ensure that the cron loop is started. self.cron_loop_join_handle.get_or_init(|| { let (cron_schedule_tx, cron_schedule_rx) = @@ -208,17 +207,17 @@ impl CronHandler for LocalCronHandler { let mut runtime_state = self.runtime_state.borrow_mut(); if runtime_state.crons.len() > MAX_CRONS { - return Err(type_error("Too many crons")); + return Err(CronError::TooManyCrons); } if runtime_state.crons.contains_key(&spec.name) { - return Err(type_error("Cron with this name already exists")); + return Err(CronError::AlreadyExists); } // Validate schedule expression. spec .cron_schedule .parse::() - .map_err(|_| type_error("Invalid cron schedule"))?; + .map_err(|_| CronError::InvalidCron)?; // Validate backoff_schedule. if let Some(backoff_schedule) = &spec.backoff_schedule { @@ -263,7 +262,7 @@ struct Inner { #[async_trait(?Send)] impl CronHandle for CronExecutionHandle { - async fn next(&self, prev_success: bool) -> Result { + async fn next(&self, prev_success: bool) -> Result { self.inner.borrow_mut().permit.take(); if self @@ -300,7 +299,7 @@ impl CronHandle for CronExecutionHandle { } } -fn compute_next_deadline(cron_expression: &str) -> Result { +fn compute_next_deadline(cron_expression: &str) -> Result { let now = chrono::Utc::now(); if let Ok(test_schedule) = env::var("DENO_CRON_TEST_SCHEDULE_OFFSET") { @@ -311,19 +310,21 @@ fn compute_next_deadline(cron_expression: &str) -> Result { let cron = cron_expression .parse::() - .map_err(|_| anyhow::anyhow!("invalid cron expression"))?; + .map_err(|_| CronError::InvalidCron)?; let Some(next_deadline) = cron.next_after(now) else { - return Err(anyhow::anyhow!("invalid cron expression")); + return Err(CronError::InvalidCron); }; Ok(next_deadline.timestamp_millis() as u64) } -fn validate_backoff_schedule(backoff_schedule: &[u32]) -> Result<(), AnyError> { +fn validate_backoff_schedule( + backoff_schedule: &[u32], +) -> Result<(), CronError> { if backoff_schedule.len() > MAX_BACKOFF_COUNT { - return Err(type_error("Invalid backoff schedule")); + return Err(CronError::InvalidBackoff); } if backoff_schedule.iter().any(|s| *s > MAX_BACKOFF_MS) { - return Err(type_error("Invalid backoff schedule")); + return Err(CronError::InvalidBackoff); } Ok(()) } diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 80a2e11c7c..63b1905145 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -18,21 +18,27 @@ import { op_crypto_decrypt, op_crypto_derive_bits, op_crypto_derive_bits_x25519, + op_crypto_derive_bits_x448, op_crypto_encrypt, op_crypto_export_key, op_crypto_export_pkcs8_ed25519, op_crypto_export_pkcs8_x25519, + op_crypto_export_pkcs8_x448, op_crypto_export_spki_ed25519, op_crypto_export_spki_x25519, + op_crypto_export_spki_x448, op_crypto_generate_ed25519_keypair, op_crypto_generate_key, op_crypto_generate_x25519_keypair, + op_crypto_generate_x448_keypair, op_crypto_get_random_values, op_crypto_import_key, op_crypto_import_pkcs8_ed25519, op_crypto_import_pkcs8_x25519, + op_crypto_import_pkcs8_x448, op_crypto_import_spki_ed25519, op_crypto_import_spki_x25519, + op_crypto_import_spki_x448, op_crypto_jwk_x_ed25519, op_crypto_random_uuid, op_crypto_sign_ed25519, @@ -134,6 +140,7 @@ const supportedAlgorithms = { "AES-KW": "AesKeyGenParams", "HMAC": "HmacKeyGenParams", "X25519": null, + "X448": null, "Ed25519": null, }, "sign": { @@ -165,12 +172,14 @@ const supportedAlgorithms = { "AES-KW": null, "Ed25519": null, "X25519": null, + "X448": null, }, "deriveBits": { "HKDF": "HkdfParams", "PBKDF2": "Pbkdf2Params", "ECDH": "EcdhKeyDeriveParams", "X25519": "EcdhKeyDeriveParams", + "X448": "EcdhKeyDeriveParams", }, "encrypt": { "RSA-OAEP": "RsaOaepParams", @@ -292,7 +301,7 @@ function normalizeAlgorithm(algorithm, op) { normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, "digest"); } else if (idlType === "AlgorithmIdentifier") { // TODO(lucacasonato): implement - throw new TypeError("unimplemented"); + throw new TypeError("Unimplemented"); } } @@ -443,7 +452,7 @@ function getKeyLength(algorithm) { // 1. if (!ArrayPrototypeIncludes([128, 192, 256], algorithm.length)) { throw new DOMException( - "length must be 128, 192, or 256", + `Length must be 128, 192, or 256: received ${algorithm.length}`, "OperationError", ); } @@ -470,14 +479,14 @@ function getKeyLength(algorithm) { break; default: throw new DOMException( - "Unrecognized hash algorithm", + `Unrecognized hash algorithm: ${algorithm.hash.name}`, "NotSupportedError", ); } } else if (algorithm.length !== 0) { length = algorithm.length; } else { - throw new TypeError("Invalid length."); + throw new TypeError(`Invalid length: ${algorithm.length}`); } // 2. @@ -492,7 +501,7 @@ function getKeyLength(algorithm) { return null; } default: - throw new TypeError("unreachable"); + throw new TypeError("Unreachable"); } } @@ -556,7 +565,7 @@ class SubtleCrypto { // 8. if (normalizedAlgorithm.name !== key[_algorithm].name) { throw new DOMException( - "Encryption algorithm doesn't match key algorithm.", + `Encryption algorithm '${normalizedAlgorithm.name}' does not match key algorithm`, "InvalidAccessError", ); } @@ -564,7 +573,7 @@ class SubtleCrypto { // 9. if (!ArrayPrototypeIncludes(key[_usages], "encrypt")) { throw new DOMException( - "Key does not support the 'encrypt' operation.", + "Key does not support the 'encrypt' operation", "InvalidAccessError", ); } @@ -599,7 +608,7 @@ class SubtleCrypto { // 8. if (normalizedAlgorithm.name !== key[_algorithm].name) { throw new DOMException( - "Decryption algorithm doesn't match key algorithm.", + `Decryption algorithm "${normalizedAlgorithm.name}" does not match key algorithm`, "OperationError", ); } @@ -607,7 +616,7 @@ class SubtleCrypto { // 9. if (!ArrayPrototypeIncludes(key[_usages], "decrypt")) { throw new DOMException( - "Key does not support the 'decrypt' operation.", + "Key does not support the 'decrypt' operation", "InvalidAccessError", ); } @@ -683,7 +692,7 @@ class SubtleCrypto { normalizedAlgorithm.length === 0 || normalizedAlgorithm.length > 128 ) { throw new DOMException( - "Counter length must not be 0 or greater than 128", + `Counter length must not be 0 or greater than 128: received ${normalizedAlgorithm.length}`, "OperationError", ); } @@ -713,7 +722,7 @@ class SubtleCrypto { ) ) { throw new DOMException( - "Invalid tag length", + `Invalid tag length: ${normalizedAlgorithm.tagLength}`, "OperationError", ); } @@ -805,7 +814,7 @@ class SubtleCrypto { // 8. if (normalizedAlgorithm.name !== key[_algorithm].name) { throw new DOMException( - "Signing algorithm doesn't match key algorithm.", + "Signing algorithm does not match key algorithm", "InvalidAccessError", ); } @@ -813,7 +822,7 @@ class SubtleCrypto { // 9. if (!ArrayPrototypeIncludes(key[_usages], "sign")) { throw new DOMException( - "Key does not support the 'sign' operation.", + "Key does not support the 'sign' operation", "InvalidAccessError", ); } @@ -928,7 +937,7 @@ class SubtleCrypto { } } - throw new TypeError("unreachable"); + throw new TypeError("Unreachable"); } /** @@ -939,7 +948,6 @@ class SubtleCrypto { * @param {KeyUsages[]} keyUsages * @returns {Promise} */ - // deno-lint-ignore require-await async importKey(format, keyData, algorithm, extractable, keyUsages) { webidl.assertBranded(this, SubtleCryptoPrototype); const prefix = "Failed to execute 'importKey' on 'SubtleCrypto'"; @@ -967,96 +975,34 @@ class SubtleCrypto { if (ArrayBufferIsView(keyData) || isArrayBuffer(keyData)) { keyData = copyBuffer(keyData); } else { - throw new TypeError("keyData is a JsonWebKey"); + throw new TypeError("Cannot import key: 'keyData' is a JsonWebKey"); } } else { if (ArrayBufferIsView(keyData) || isArrayBuffer(keyData)) { - throw new TypeError("keyData is not a JsonWebKey"); + throw new TypeError("Cannot import key: 'keyData' is not a JsonWebKey"); } } const normalizedAlgorithm = normalizeAlgorithm(algorithm, "importKey"); - const algorithmName = normalizedAlgorithm.name; + // 8. + const result = await importKeyInner( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ); - switch (algorithmName) { - case "HMAC": { - return importKeyHMAC( - format, - normalizedAlgorithm, - keyData, - extractable, - keyUsages, - ); - } - case "ECDH": - case "ECDSA": { - return importKeyEC( - format, - normalizedAlgorithm, - keyData, - extractable, - keyUsages, - ); - } - case "RSASSA-PKCS1-v1_5": - case "RSA-PSS": - case "RSA-OAEP": { - return importKeyRSA( - format, - normalizedAlgorithm, - keyData, - extractable, - keyUsages, - ); - } - case "HKDF": { - return importKeyHKDF(format, keyData, extractable, keyUsages); - } - case "PBKDF2": { - return importKeyPBKDF2(format, keyData, extractable, keyUsages); - } - case "AES-CTR": - case "AES-CBC": - case "AES-GCM": { - return importKeyAES( - format, - normalizedAlgorithm, - keyData, - extractable, - keyUsages, - ["encrypt", "decrypt", "wrapKey", "unwrapKey"], - ); - } - case "AES-KW": { - return importKeyAES( - format, - normalizedAlgorithm, - keyData, - extractable, - keyUsages, - ["wrapKey", "unwrapKey"], - ); - } - case "X25519": { - return importKeyX25519( - format, - keyData, - extractable, - keyUsages, - ); - } - case "Ed25519": { - return importKeyEd25519( - format, - keyData, - extractable, - keyUsages, - ); - } - default: - throw new DOMException("Not implemented", "NotSupportedError"); + // 9. + if ( + ArrayPrototypeIncludes(["private", "secret"], result[_type]) && + keyUsages.length == 0 + ) { + throw new SyntaxError("Invalid key usage"); } + + return result; } /** @@ -1100,6 +1046,10 @@ class SubtleCrypto { result = exportKeyEd25519(format, key, innerKey); break; } + case "X448": { + result = exportKeyX448(format, key, innerKey); + break; + } case "X25519": { result = exportKeyX25519(format, key, innerKey); break; @@ -1156,7 +1106,7 @@ class SubtleCrypto { // 8. if (!ArrayPrototypeIncludes(baseKey[_usages], "deriveBits")) { throw new DOMException( - "baseKey usages does not contain `deriveBits`", + "'baseKey' usages does not contain 'deriveBits'", "InvalidAccessError", ); } @@ -1222,7 +1172,7 @@ class SubtleCrypto { // 11. if (normalizedAlgorithm.name !== baseKey[_algorithm].name) { throw new DOMException( - "Invalid algorithm name", + `Invalid algorithm name: ${normalizedAlgorithm.name}`, "InvalidAccessError", ); } @@ -1230,7 +1180,7 @@ class SubtleCrypto { // 12. if (!ArrayPrototypeIncludes(baseKey[_usages], "deriveKey")) { throw new DOMException( - "baseKey usages does not contain `deriveKey`", + "'baseKey' usages does not contain 'deriveKey'", "InvalidAccessError", ); } @@ -1259,7 +1209,7 @@ class SubtleCrypto { ArrayPrototypeIncludes(["private", "secret"], result[_type]) && keyUsages.length == 0 ) { - throw new SyntaxError("Invalid key usages"); + throw new SyntaxError("Invalid key usage"); } // 17. return result; @@ -1298,14 +1248,14 @@ class SubtleCrypto { if (normalizedAlgorithm.name !== key[_algorithm].name) { throw new DOMException( - "Verifying algorithm doesn't match key algorithm.", + "Verifying algorithm does not match key algorithm", "InvalidAccessError", ); } if (!ArrayPrototypeIncludes(key[_usages], "verify")) { throw new DOMException( - "Key does not support the 'verify' operation.", + "Key does not support the 'verify' operation", "InvalidAccessError", ); } @@ -1396,7 +1346,7 @@ class SubtleCrypto { } } - throw new TypeError("unreachable"); + throw new TypeError("Unreachable"); } /** @@ -1435,7 +1385,7 @@ class SubtleCrypto { // 8. if (normalizedAlgorithm.name !== wrappingKey[_algorithm].name) { throw new DOMException( - "Wrapping algorithm doesn't match key algorithm.", + "Wrapping algorithm does not match key algorithm", "InvalidAccessError", ); } @@ -1443,7 +1393,7 @@ class SubtleCrypto { // 9. if (!ArrayPrototypeIncludes(wrappingKey[_usages], "wrapKey")) { throw new DOMException( - "Key does not support the 'wrapKey' operation.", + "Key does not support the 'wrapKey' operation", "InvalidAccessError", ); } @@ -1591,7 +1541,7 @@ class SubtleCrypto { // 11. if (normalizedAlgorithm.name !== unwrappingKey[_algorithm].name) { throw new DOMException( - "Unwrapping algorithm doesn't match key algorithm.", + "Unwrapping algorithm does not match key algorithm", "InvalidAccessError", ); } @@ -1599,7 +1549,7 @@ class SubtleCrypto { // 12. if (!ArrayPrototypeIncludes(unwrappingKey[_usages], "unwrapKey")) { throw new DOMException( - "Key does not support the 'unwrapKey' operation.", + "Key does not support the 'unwrapKey' operation", "InvalidAccessError", ); } @@ -1678,7 +1628,7 @@ class SubtleCrypto { (result[_type] == "secret" || result[_type] == "private") && keyUsages.length == 0 ) { - throw new SyntaxError("Invalid key type."); + throw new SyntaxError("Invalid key type"); } // 17. result[_extractable] = extractable; @@ -1726,13 +1676,13 @@ class SubtleCrypto { if (ObjectPrototypeIsPrototypeOf(CryptoKeyPrototype, result)) { const type = result[_type]; if ((type === "secret" || type === "private") && usages.length === 0) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } else if ( ObjectPrototypeIsPrototypeOf(CryptoKeyPrototype, result.privateKey) ) { if (result.privateKey[_usages].length === 0) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } @@ -1758,7 +1708,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["sign", "verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2. @@ -1817,7 +1767,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { ], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2. @@ -1873,7 +1823,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["sign", "verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2-3. @@ -1933,7 +1883,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2-3. @@ -1999,7 +1949,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { ], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } return generateKeyAES(normalizedAlgorithm, extractable, usages); @@ -2012,11 +1962,53 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["wrapKey", "unwrapKey"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } return generateKeyAES(normalizedAlgorithm, extractable, usages); } + case "X448": { + if ( + ArrayPrototypeFind( + usages, + (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), + ) !== undefined + ) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + const privateKeyData = new Uint8Array(56); + const publicKeyData = new Uint8Array(56); + + op_crypto_generate_x448_keypair(privateKeyData, publicKeyData); + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData); + + const publicHandle = {}; + WeakMapPrototypeSet(KEY_STORE, publicHandle, publicKeyData); + + const algorithm = { + name: algorithmName, + }; + + const publicKey = constructKey( + "public", + true, + usageIntersection(usages, []), + algorithm, + publicHandle, + ); + + const privateKey = constructKey( + "private", + extractable, + usageIntersection(usages, ["deriveKey", "deriveBits"]), + algorithm, + handle, + ); + + return { publicKey, privateKey }; + } case "X25519": { if ( ArrayPrototypeFind( @@ -2024,7 +2016,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const privateKeyData = new Uint8Array(32); const publicKeyData = new Uint8Array(32); @@ -2065,7 +2057,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["sign", "verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const ED25519_SEED_LEN = 32; @@ -2114,7 +2106,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { (u) => !ArrayPrototypeIncludes(["sign", "verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2. @@ -2163,6 +2155,211 @@ async function generateKey(normalizedAlgorithm, extractable, usages) { } } +function importKeyX448( + format, + keyData, + extractable, + keyUsages, +) { + switch (format) { + case "raw": { + // 1. + if (keyUsages.length > 0) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, keyData); + + // 2-3. + const algorithm = { + name: "X448", + }; + + // 4-6. + return constructKey( + "public", + extractable, + [], + algorithm, + handle, + ); + } + case "spki": { + // 1. + if (keyUsages.length > 0) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + + const publicKeyData = new Uint8Array(56); + if (!op_crypto_import_spki_x448(keyData, publicKeyData)) { + throw new DOMException("Invalid key data", "DataError"); + } + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData); + + const algorithm = { + name: "X448", + }; + + return constructKey( + "public", + extractable, + [], + algorithm, + handle, + ); + } + case "pkcs8": { + // 1. + if ( + ArrayPrototypeFind( + keyUsages, + (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), + ) !== undefined + ) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + + const privateKeyData = new Uint8Array(32); + if (!op_crypto_import_pkcs8_x448(keyData, privateKeyData)) { + throw new DOMException("Invalid key data", "DataError"); + } + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData); + + const algorithm = { + name: "X448", + }; + + return constructKey( + "private", + extractable, + usageIntersection(keyUsages, recognisedUsages), + algorithm, + handle, + ); + } + case "jwk": { + // 1. + const jwk = keyData; + + // 2. + if (jwk.d !== undefined) { + if ( + ArrayPrototypeFind( + keyUsages, + (u) => + !ArrayPrototypeIncludes( + ["deriveKey", "deriveBits"], + u, + ), + ) !== undefined + ) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + } + + // 3. + if (jwk.d === undefined && keyUsages.length > 0) { + throw new DOMException("Invalid key usage", "SyntaxError"); + } + + // 4. + if (jwk.kty !== "OKP") { + throw new DOMException("Invalid key type", "DataError"); + } + + // 5. + if (jwk.crv !== "X448") { + throw new DOMException("Invalid curve", "DataError"); + } + + // 6. + if (keyUsages.length > 0 && jwk.use !== undefined) { + if (jwk.use !== "enc") { + throw new DOMException("Invalid key use", "DataError"); + } + } + + // 7. + if (jwk.key_ops !== undefined) { + if ( + ArrayPrototypeFind( + jwk.key_ops, + (u) => !ArrayPrototypeIncludes(recognisedUsages, u), + ) !== undefined + ) { + throw new DOMException( + "'key_ops' property of JsonWebKey is invalid", + "DataError", + ); + } + + if ( + !ArrayPrototypeEvery( + jwk.key_ops, + (u) => ArrayPrototypeIncludes(keyUsages, u), + ) + ) { + throw new DOMException( + "'key_ops' property of JsonWebKey is invalid", + "DataError", + ); + } + } + + // 8. + if (jwk.ext !== undefined && jwk.ext === false && extractable) { + throw new DOMException("Invalid key extractability", "DataError"); + } + + // 9. + if (jwk.d !== undefined) { + // https://www.rfc-editor.org/rfc/rfc8037#section-2 + const privateKeyData = op_crypto_base64url_decode(jwk.d); + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData); + + const algorithm = { + name: "X448", + }; + + return constructKey( + "private", + extractable, + usageIntersection(keyUsages, ["deriveKey", "deriveBits"]), + algorithm, + handle, + ); + } else { + // https://www.rfc-editor.org/rfc/rfc8037#section-2 + const publicKeyData = op_crypto_base64url_decode(jwk.x); + + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData); + + const algorithm = { + name: "X448", + }; + + return constructKey( + "public", + extractable, + [], + algorithm, + handle, + ); + } + } + default: + throw new DOMException("Not implemented", "NotSupportedError"); + } +} + function importKeyEd25519( format, keyData, @@ -2178,7 +2375,7 @@ function importKeyEd25519( (u) => !ArrayPrototypeIncludes(["verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const handle = {}; @@ -2206,7 +2403,7 @@ function importKeyEd25519( (u) => !ArrayPrototypeIncludes(["verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const publicKeyData = new Uint8Array(32); @@ -2237,7 +2434,7 @@ function importKeyEd25519( (u) => !ArrayPrototypeIncludes(["sign"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const privateKeyData = new Uint8Array(32); @@ -2276,7 +2473,7 @@ function importKeyEd25519( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } else { if ( @@ -2289,7 +2486,7 @@ function importKeyEd25519( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } @@ -2349,7 +2546,7 @@ function importKeyEd25519( try { privateKeyData = op_crypto_base64url_decode(jwk.d); } catch (_) { - throw new DOMException("invalid private key data", "DataError"); + throw new DOMException("Invalid private key data", "DataError"); } const handle = {}; @@ -2372,7 +2569,7 @@ function importKeyEd25519( try { publicKeyData = op_crypto_base64url_decode(jwk.x); } catch (_) { - throw new DOMException("invalid public key data", "DataError"); + throw new DOMException("Invalid public key data", "DataError"); } const handle = {}; @@ -2406,7 +2603,7 @@ function importKeyX25519( case "raw": { // 1. if (keyUsages.length > 0) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const handle = {}; @@ -2429,7 +2626,7 @@ function importKeyX25519( case "spki": { // 1. if (keyUsages.length > 0) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const publicKeyData = new Uint8Array(32); @@ -2460,7 +2657,7 @@ function importKeyX25519( (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const privateKeyData = new Uint8Array(32); @@ -2499,13 +2696,13 @@ function importKeyX25519( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } // 3. if (jwk.d === undefined && keyUsages.length > 0) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 4. @@ -2641,7 +2838,7 @@ function exportKeyAES( break; default: throw new DOMException( - "Invalid key length", + `Invalid key length: ${algorithm.length}`, "NotSupportedError", ); } @@ -2675,7 +2872,7 @@ function importKeyAES( (u) => !ArrayPrototypeIncludes(supportedKeyUsages, u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } const algorithmName = normalizedAlgorithm.name; @@ -2731,7 +2928,10 @@ function importKeyAES( jwk.alg !== undefined && jwk.alg !== aesJwkAlg[algorithmName][128] ) { - throw new DOMException("Invalid algorithm", "DataError"); + throw new DOMException( + `Invalid algorithm: ${jwk.alg}`, + "DataError", + ); } break; case 192: @@ -2739,7 +2939,10 @@ function importKeyAES( jwk.alg !== undefined && jwk.alg !== aesJwkAlg[algorithmName][192] ) { - throw new DOMException("Invalid algorithm", "DataError"); + throw new DOMException( + `Invalid algorithm: ${jwk.alg}`, + "DataError", + ); } break; case 256: @@ -2747,7 +2950,10 @@ function importKeyAES( jwk.alg !== undefined && jwk.alg !== aesJwkAlg[algorithmName][256] ) { - throw new DOMException("Invalid algorithm", "DataError"); + throw new DOMException( + `Invalid algorithm: ${jwk.alg}`, + "DataError", + ); } break; default: @@ -2761,7 +2967,7 @@ function importKeyAES( if ( keyUsages.length > 0 && jwk.use !== undefined && jwk.use !== "enc" ) { - throw new DOMException("Invalid key usages", "DataError"); + throw new DOMException("Invalid key usage", "DataError"); } // 7. @@ -2844,7 +3050,7 @@ function importKeyHMAC( (u) => !ArrayPrototypeIncludes(["sign", "verify"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 3. @@ -2926,7 +3132,7 @@ function importKeyHMAC( break; } default: - throw new TypeError("unreachable"); + throw new TypeError("Unreachable"); } // 7. @@ -3059,7 +3265,7 @@ function importKeyEC( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 3. @@ -3100,7 +3306,7 @@ function importKeyEC( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2-9. @@ -3140,7 +3346,7 @@ function importKeyEC( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } else if (keyUsages.length != 0) { throw new DOMException("Key usage must be empty", "SyntaxError"); @@ -3183,7 +3389,7 @@ function importKeyEC( (u) => !ArrayPrototypeIncludes(supportedUsages[keyType], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 3. @@ -3343,6 +3549,104 @@ function importKeyEC( } } +// deno-lint-ignore require-await +async function importKeyInner( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, +) { + const algorithmName = normalizedAlgorithm.name; + + switch (algorithmName) { + case "HMAC": { + return importKeyHMAC( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ); + } + case "ECDH": + case "ECDSA": { + return importKeyEC( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ); + } + case "RSASSA-PKCS1-v1_5": + case "RSA-PSS": + case "RSA-OAEP": { + return importKeyRSA( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ); + } + case "HKDF": { + return importKeyHKDF(format, keyData, extractable, keyUsages); + } + case "PBKDF2": { + return importKeyPBKDF2(format, keyData, extractable, keyUsages); + } + case "AES-CTR": + case "AES-CBC": + case "AES-GCM": { + return importKeyAES( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + ); + } + case "AES-KW": { + return importKeyAES( + format, + normalizedAlgorithm, + keyData, + extractable, + keyUsages, + ["wrapKey", "unwrapKey"], + ); + } + case "X448": { + return importKeyX448( + format, + keyData, + extractable, + keyUsages, + ); + } + case "X25519": { + return importKeyX25519( + format, + keyData, + extractable, + keyUsages, + ); + } + case "Ed25519": { + return importKeyEd25519( + format, + keyData, + extractable, + keyUsages, + ); + } + default: + throw new DOMException("Not implemented", "NotSupportedError"); + } +} + const SUPPORTED_KEY_USAGES = { "RSASSA-PKCS1-v1_5": { public: ["verify"], @@ -3391,7 +3695,7 @@ function importKeyRSA( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2-9. @@ -3436,7 +3740,7 @@ function importKeyRSA( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2-9. @@ -3485,7 +3789,7 @@ function importKeyRSA( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } } else if ( ArrayPrototypeFind( @@ -3497,7 +3801,7 @@ function importKeyRSA( ), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 3. @@ -3579,7 +3883,7 @@ function importKeyRSA( break; default: throw new DOMException( - `'alg' property of JsonWebKey must be one of 'RS1', 'RS256', 'RS384', 'RS512'`, + `'alg' property of JsonWebKey must be one of 'RS1', 'RS256', 'RS384', 'RS512': received ${jwk.alg}`, "DataError", ); } @@ -3602,7 +3906,7 @@ function importKeyRSA( break; default: throw new DOMException( - `'alg' property of JsonWebKey must be one of 'PS1', 'PS256', 'PS384', 'PS512'`, + `'alg' property of JsonWebKey must be one of 'PS1', 'PS256', 'PS384', 'PS512': received ${jwk.alg}`, "DataError", ); } @@ -3625,7 +3929,7 @@ function importKeyRSA( break; default: throw new DOMException( - `'alg' property of JsonWebKey must be one of 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', or 'RSA-OAEP-512'`, + `'alg' property of JsonWebKey must be one of 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', or 'RSA-OAEP-512': received ${jwk.alg}`, "DataError", ); } @@ -3639,7 +3943,7 @@ function importKeyRSA( // 9.2. if (normalizedHash.name !== normalizedAlgorithm.hash.name) { throw new DOMException( - `'alg' property of JsonWebKey must be '${normalizedAlgorithm.name}'`, + `'alg' property of JsonWebKey must be '${normalizedAlgorithm.name}': received ${jwk.alg}`, "DataError", ); } @@ -3684,7 +3988,7 @@ function importKeyRSA( } } else { throw new DOMException( - "only optimized private keys are supported", + "Only optimized private keys are supported", "NotSupportedError", ); } @@ -3782,7 +4086,7 @@ function importKeyHKDF( (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 2. @@ -3834,7 +4138,7 @@ function importKeyPBKDF2( (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), ) !== undefined ) { - throw new DOMException("Invalid key usages", "SyntaxError"); + throw new DOMException("Invalid key usage", "SyntaxError"); } // 3. @@ -3878,7 +4182,7 @@ function exportKeyHMAC(format, key, innerKey) { // 3. case "raw": { const bits = innerKey.data; - // TODO(petamoriken): Uint8Array doesn't have push method + // TODO(petamoriken): Uint8Array does not have push method // for (let _i = 7 & (8 - bits.length % 8); _i > 0; _i--) { // bits.push(0); // } @@ -4126,6 +4430,66 @@ function exportKeyEd25519(format, key, innerKey) { } } +function exportKeyX448(format, key, innerKey) { + switch (format) { + case "raw": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + // 2-3. + return TypedArrayPrototypeGetBuffer(innerKey); + } + case "spki": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + const spkiDer = op_crypto_export_spki_x448(innerKey); + return TypedArrayPrototypeGetBuffer(spkiDer); + } + case "pkcs8": { + // 1. + if (key[_type] !== "private") { + throw new DOMException( + "Key is not a private key", + "InvalidAccessError", + ); + } + + const pkcs8Der = op_crypto_export_pkcs8_x448( + new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]), + ); + pkcs8Der[15] = 0x20; + return TypedArrayPrototypeGetBuffer(pkcs8Der); + } + case "jwk": { + if (key[_type] === "private") { + throw new DOMException("Not implemented", "NotSupportedError"); + } + const x = op_crypto_base64url_encode(innerKey); + const jwk = { + kty: "OKP", + crv: "X448", + x, + "key_ops": key.usages, + ext: key[_extractable], + }; + return jwk; + } + default: + throw new DOMException("Not implemented", "NotSupportedError"); + } +} + function exportKeyX25519(format, key, innerKey) { switch (format) { case "raw": { @@ -4331,7 +4695,10 @@ async function generateKeyAES(normalizedAlgorithm, extractable, usages) { // 2. if (!ArrayPrototypeIncludes([128, 192, 256], normalizedAlgorithm.length)) { - throw new DOMException("Invalid key length", "OperationError"); + throw new DOMException( + `Invalid key length: ${normalizedAlgorithm.length}`, + "OperationError", + ); } // 3. @@ -4417,7 +4784,7 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) { publicKey[_algorithm].namedCurve !== baseKey[_algorithm].namedCurve ) { throw new DOMException( - "namedCurve mismatch", + "'namedCurve' mismatch", "InvalidAccessError", ); } @@ -4480,6 +4847,55 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) { return TypedArrayPrototypeGetBuffer(buf); } + case "X448": { + // 1. + if (baseKey[_type] !== "private") { + throw new DOMException("Invalid key type", "InvalidAccessError"); + } + // 2. + const publicKey = normalizedAlgorithm.public; + // 3. + if (publicKey[_type] !== "public") { + throw new DOMException("Invalid key type", "InvalidAccessError"); + } + // 4. + if (publicKey[_algorithm].name !== baseKey[_algorithm].name) { + throw new DOMException( + "Algorithm mismatch", + "InvalidAccessError", + ); + } + + // 5. + const kHandle = baseKey[_handle]; + const k = WeakMapPrototypeGet(KEY_STORE, kHandle); + + const uHandle = publicKey[_handle]; + const u = WeakMapPrototypeGet(KEY_STORE, uHandle); + + const secret = new Uint8Array(56); + const isIdentity = op_crypto_derive_bits_x448(k, u, secret); + + // 6. + if (isIdentity) { + throw new DOMException("Invalid key", "OperationError"); + } + + // 7. + if (length === null) { + return TypedArrayPrototypeGetBuffer(secret); + } else if ( + TypedArrayPrototypeGetByteLength(secret) * 8 < length + ) { + throw new DOMException("Invalid length", "OperationError"); + } else { + return ArrayBufferPrototypeSlice( + TypedArrayPrototypeGetBuffer(secret), + 0, + MathCeil(length / 8), + ); + } + } case "X25519": { // 1. if (baseKey[_type] !== "private") { @@ -4670,7 +5086,7 @@ async function encrypt(normalizedAlgorithm, key, data) { ) ) { throw new DOMException( - "Invalid tag length", + `Invalid tag length: ${normalizedAlgorithm.tagLength}`, "OperationError", ); } diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml index b71e1f5b78..e9761f48f1 100644 --- a/ext/crypto/Cargo.toml +++ b/ext/crypto/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_crypto" -version = "0.178.0" +version = "0.188.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -24,6 +24,7 @@ ctr = "0.9.1" curve25519-dalek = "4.1.3" deno_core.workspace = true deno_web.workspace = true +ed448-goldilocks = { version = "0.8.3", features = ["zeroize"] } elliptic-curve = { version = "0.13.1", features = ["std", "pem"] } num-traits = "0.2.14" once_cell.workspace = true @@ -33,11 +34,14 @@ p521 = "0.13.3" rand.workspace = true ring = { workspace = true, features = ["std"] } rsa.workspace = true +sec1.workspace = true serde.workspace = true serde_bytes.workspace = true sha1.workspace = true sha2.workspace = true signature.workspace = true spki.workspace = true +thiserror.workspace = true +tokio.workspace = true uuid.workspace = true x25519-dalek = "2.0.0" diff --git a/ext/crypto/decrypt.rs b/ext/crypto/decrypt.rs index 9b104e1784..1140475183 100644 --- a/ext/crypto/decrypt.rs +++ b/ext/crypto/decrypt.rs @@ -16,9 +16,6 @@ use ctr::cipher::StreamCipher; use ctr::Ctr128BE; use ctr::Ctr32BE; use ctr::Ctr64BE; -use deno_core::error::custom_error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::unsync::spawn_blocking; use deno_core::JsBuffer; @@ -73,12 +70,36 @@ pub enum DecryptAlgorithm { }, } +#[derive(Debug, thiserror::Error)] +pub enum DecryptError { + #[error(transparent)] + General(#[from] SharedError), + #[error(transparent)] + Pkcs1(#[from] rsa::pkcs1::Error), + #[error("Decryption failed")] + Failed, + #[error("invalid length")] + InvalidLength, + #[error("invalid counter length. Currently supported 32/64/128 bits")] + InvalidCounterLength, + #[error("tag length not equal to 128")] + InvalidTagLength, + #[error("invalid key or iv")] + InvalidKeyOrIv, + #[error("tried to decrypt too much data")] + TooMuchData, + #[error("iv length not equal to 12 or 16")] + InvalidIvLength, + #[error("{0}")] + Rsa(rsa::Error), +} + #[op2(async)] #[serde] pub async fn op_crypto_decrypt( #[serde] opts: DecryptOptions, #[buffer] data: JsBuffer, -) -> Result { +) -> Result { let key = opts.key; let fun = move || match opts.algorithm { DecryptAlgorithm::RsaOaep { hash, label } => { @@ -108,7 +129,7 @@ fn decrypt_rsa_oaep( hash: ShaHash, label: Vec, data: &[u8], -) -> Result, deno_core::anyhow::Error> { +) -> Result, DecryptError> { let key = key.as_rsa_private_key()?; let private_key = rsa::RsaPrivateKey::from_pkcs1_der(key)?; @@ -139,7 +160,7 @@ fn decrypt_rsa_oaep( private_key .decrypt(padding, data) - .map_err(|e| custom_error("DOMExceptionOperationError", e.to_string())) + .map_err(DecryptError::Rsa) } fn decrypt_aes_cbc( @@ -147,7 +168,7 @@ fn decrypt_aes_cbc( length: usize, iv: Vec, data: &[u8], -) -> Result, deno_core::anyhow::Error> { +) -> Result, DecryptError> { let key = key.as_secret_key()?; // 2. @@ -155,53 +176,32 @@ fn decrypt_aes_cbc( 128 => { // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315 type Aes128CbcDec = cbc::Decryptor; - let cipher = Aes128CbcDec::new_from_slices(key, &iv).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Invalid key or iv".to_string(), - ) - })?; + let cipher = Aes128CbcDec::new_from_slices(key, &iv) + .map_err(|_| DecryptError::InvalidKeyOrIv)?; - cipher.decrypt_padded_vec_mut::(data).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Decryption failed".to_string(), - ) - })? + cipher + .decrypt_padded_vec_mut::(data) + .map_err(|_| DecryptError::Failed)? } 192 => { // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315 type Aes192CbcDec = cbc::Decryptor; - let cipher = Aes192CbcDec::new_from_slices(key, &iv).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Invalid key or iv".to_string(), - ) - })?; + let cipher = Aes192CbcDec::new_from_slices(key, &iv) + .map_err(|_| DecryptError::InvalidKeyOrIv)?; - cipher.decrypt_padded_vec_mut::(data).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Decryption failed".to_string(), - ) - })? + cipher + .decrypt_padded_vec_mut::(data) + .map_err(|_| DecryptError::Failed)? } 256 => { // Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315 type Aes256CbcDec = cbc::Decryptor; - let cipher = Aes256CbcDec::new_from_slices(key, &iv).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Invalid key or iv".to_string(), - ) - })?; + let cipher = Aes256CbcDec::new_from_slices(key, &iv) + .map_err(|_| DecryptError::InvalidKeyOrIv)?; - cipher.decrypt_padded_vec_mut::(data).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "Decryption failed".to_string(), - ) - })? + cipher + .decrypt_padded_vec_mut::(data) + .map_err(|_| DecryptError::Failed)? } _ => unreachable!(), }; @@ -214,7 +214,7 @@ fn decrypt_aes_ctr_gen( key: &[u8], counter: &[u8], data: &[u8], -) -> Result, AnyError> +) -> Result, DecryptError> where B: KeyIvInit + StreamCipher, { @@ -223,7 +223,7 @@ where let mut plaintext = data.to_vec(); cipher .try_apply_keystream(&mut plaintext) - .map_err(|_| operation_error("tried to decrypt too much data"))?; + .map_err(|_| DecryptError::TooMuchData)?; Ok(plaintext) } @@ -235,12 +235,12 @@ fn decrypt_aes_gcm_gen>( length: usize, additional_data: Vec, plaintext: &mut [u8], -) -> Result<(), AnyError> { +) -> Result<(), DecryptError> { let nonce = Nonce::from_slice(nonce); match length { 128 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Decryption failed"))?; + .map_err(|_| DecryptError::Failed)?; cipher .decrypt_in_place_detached( nonce, @@ -248,11 +248,11 @@ fn decrypt_aes_gcm_gen>( plaintext, tag, ) - .map_err(|_| operation_error("Decryption failed"))? + .map_err(|_| DecryptError::Failed)? } 192 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Decryption failed"))?; + .map_err(|_| DecryptError::Failed)?; cipher .decrypt_in_place_detached( nonce, @@ -260,11 +260,11 @@ fn decrypt_aes_gcm_gen>( plaintext, tag, ) - .map_err(|_| operation_error("Decryption failed"))? + .map_err(|_| DecryptError::Failed)? } 256 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Decryption failed"))?; + .map_err(|_| DecryptError::Failed)?; cipher .decrypt_in_place_detached( nonce, @@ -272,9 +272,9 @@ fn decrypt_aes_gcm_gen>( plaintext, tag, ) - .map_err(|_| operation_error("Decryption failed"))? + .map_err(|_| DecryptError::Failed)? } - _ => return Err(type_error("invalid length")), + _ => return Err(DecryptError::InvalidLength), }; Ok(()) @@ -286,7 +286,7 @@ fn decrypt_aes_ctr( counter: &[u8], ctr_length: usize, data: &[u8], -) -> Result, deno_core::anyhow::Error> { +) -> Result, DecryptError> { let key = key.as_secret_key()?; match ctr_length { @@ -294,23 +294,21 @@ fn decrypt_aes_ctr( 128 => decrypt_aes_ctr_gen::>(key, counter, data), 192 => decrypt_aes_ctr_gen::>(key, counter, data), 256 => decrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(DecryptError::InvalidLength), }, 64 => match key_length { 128 => decrypt_aes_ctr_gen::>(key, counter, data), 192 => decrypt_aes_ctr_gen::>(key, counter, data), 256 => decrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(DecryptError::InvalidLength), }, 128 => match key_length { 128 => decrypt_aes_ctr_gen::>(key, counter, data), 192 => decrypt_aes_ctr_gen::>(key, counter, data), 256 => decrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(DecryptError::InvalidLength), }, - _ => Err(type_error( - "invalid counter length. Currently supported 32/64/128 bits", - )), + _ => Err(DecryptError::InvalidCounterLength), } } @@ -321,7 +319,7 @@ fn decrypt_aes_gcm( iv: Vec, additional_data: Option>, data: &[u8], -) -> Result, AnyError> { +) -> Result, DecryptError> { let key = key.as_secret_key()?; let additional_data = additional_data.unwrap_or_default(); @@ -330,7 +328,7 @@ fn decrypt_aes_gcm( // Note that encryption won't fail, it instead truncates the tag // to the specified tag length as specified in the spec. if tag_length != 128 { - return Err(type_error("tag length not equal to 128")); + return Err(DecryptError::InvalidTagLength); } let sep = data.len() - (tag_length / 8); @@ -357,7 +355,7 @@ fn decrypt_aes_gcm( additional_data, &mut plaintext, )?, - _ => return Err(type_error("iv length not equal to 12 or 16")), + _ => return Err(DecryptError::InvalidIvLength), } Ok(plaintext) diff --git a/ext/crypto/ed25519.rs b/ext/crypto/ed25519.rs index 4f604fe513..da34b7d25d 100644 --- a/ext/crypto/ed25519.rs +++ b/ext/crypto/ed25519.rs @@ -2,8 +2,6 @@ use base64::prelude::BASE64_URL_SAFE_NO_PAD; use base64::Engine; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::ToJsBuffer; use elliptic_curve::pkcs8::PrivateKeyInfo; @@ -15,6 +13,16 @@ use spki::der::asn1::BitString; use spki::der::Decode; use spki::der::Encode; +#[derive(Debug, thiserror::Error)] +pub enum Ed25519Error { + #[error("Failed to export key")] + FailedExport, + #[error(transparent)] + Der(#[from] rsa::pkcs1::der::Error), + #[error(transparent)] + KeyRejected(#[from] ring::error::KeyRejected), +} + #[op2(fast)] pub fn op_crypto_generate_ed25519_keypair( #[buffer] pkey: &mut [u8], @@ -116,7 +124,7 @@ pub fn op_crypto_import_pkcs8_ed25519( #[serde] pub fn op_crypto_export_spki_ed25519( #[buffer] pubkey: &[u8], -) -> Result { +) -> Result { let key_info = spki::SubjectPublicKeyInfo { algorithm: spki::AlgorithmIdentifierOwned { // id-Ed25519 @@ -128,9 +136,7 @@ pub fn op_crypto_export_spki_ed25519( Ok( key_info .to_der() - .map_err(|_| { - custom_error("DOMExceptionOperationError", "Failed to export key") - })? + .map_err(|_| Ed25519Error::FailedExport)? .into(), ) } @@ -139,7 +145,7 @@ pub fn op_crypto_export_spki_ed25519( #[serde] pub fn op_crypto_export_pkcs8_ed25519( #[buffer] pkey: &[u8], -) -> Result { +) -> Result { use rsa::pkcs1::der::Encode; // This should probably use OneAsymmetricKey instead @@ -164,7 +170,7 @@ pub fn op_crypto_export_pkcs8_ed25519( #[string] pub fn op_crypto_jwk_x_ed25519( #[buffer] pkey: &[u8], -) -> Result { +) -> Result { let pair = Ed25519KeyPair::from_seed_unchecked(pkey)?; Ok(BASE64_URL_SAFE_NO_PAD.encode(pair.public_key().as_ref())) } diff --git a/ext/crypto/encrypt.rs b/ext/crypto/encrypt.rs index 204648e892..66b27657f8 100644 --- a/ext/crypto/encrypt.rs +++ b/ext/crypto/encrypt.rs @@ -16,8 +16,6 @@ use aes_gcm::Nonce; use ctr::Ctr128BE; use ctr::Ctr32BE; use ctr::Ctr64BE; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::unsync::spawn_blocking; use deno_core::JsBuffer; @@ -73,12 +71,30 @@ pub enum EncryptAlgorithm { }, } +#[derive(Debug, thiserror::Error)] +pub enum EncryptError { + #[error(transparent)] + General(#[from] SharedError), + #[error("invalid length")] + InvalidLength, + #[error("invalid key or iv")] + InvalidKeyOrIv, + #[error("iv length not equal to 12 or 16")] + InvalidIvLength, + #[error("invalid counter length. Currently supported 32/64/128 bits")] + InvalidCounterLength, + #[error("tried to encrypt too much data")] + TooMuchData, + #[error("Encryption failed")] + Failed, +} + #[op2(async)] #[serde] pub async fn op_crypto_encrypt( #[serde] opts: EncryptOptions, #[buffer] data: JsBuffer, -) -> Result { +) -> Result { let key = opts.key; let fun = move || match opts.algorithm { EncryptAlgorithm::RsaOaep { hash, label } => { @@ -108,12 +124,12 @@ fn encrypt_rsa_oaep( hash: ShaHash, label: Vec, data: &[u8], -) -> Result, AnyError> { +) -> Result, EncryptError> { let label = String::from_utf8_lossy(&label).to_string(); let public_key = key.as_rsa_public_key()?; let public_key = rsa::RsaPublicKey::from_pkcs1_der(&public_key) - .map_err(|_| operation_error("failed to decode public key"))?; + .map_err(|_| SharedError::FailedDecodePublicKey)?; let mut rng = OsRng; let padding = match hash { ShaHash::Sha1 => rsa::Oaep { @@ -139,7 +155,7 @@ fn encrypt_rsa_oaep( }; let encrypted = public_key .encrypt(&mut rng, padding, data) - .map_err(|_| operation_error("Encryption failed"))?; + .map_err(|_| EncryptError::Failed)?; Ok(encrypted) } @@ -148,7 +164,7 @@ fn encrypt_aes_cbc( length: usize, iv: Vec, data: &[u8], -) -> Result, AnyError> { +) -> Result, EncryptError> { let key = key.as_secret_key()?; let ciphertext = match length { 128 => { @@ -156,7 +172,7 @@ fn encrypt_aes_cbc( type Aes128CbcEnc = cbc::Encryptor; let cipher = Aes128CbcEnc::new_from_slices(key, &iv) - .map_err(|_| operation_error("invalid key or iv".to_string()))?; + .map_err(|_| EncryptError::InvalidKeyOrIv)?; cipher.encrypt_padded_vec_mut::(data) } 192 => { @@ -164,7 +180,7 @@ fn encrypt_aes_cbc( type Aes192CbcEnc = cbc::Encryptor; let cipher = Aes192CbcEnc::new_from_slices(key, &iv) - .map_err(|_| operation_error("invalid key or iv".to_string()))?; + .map_err(|_| EncryptError::InvalidKeyOrIv)?; cipher.encrypt_padded_vec_mut::(data) } 256 => { @@ -172,10 +188,10 @@ fn encrypt_aes_cbc( type Aes256CbcEnc = cbc::Encryptor; let cipher = Aes256CbcEnc::new_from_slices(key, &iv) - .map_err(|_| operation_error("invalid key or iv".to_string()))?; + .map_err(|_| EncryptError::InvalidKeyOrIv)?; cipher.encrypt_padded_vec_mut::(data) } - _ => return Err(type_error("invalid length")), + _ => return Err(EncryptError::InvalidLength), }; Ok(ciphertext) } @@ -186,31 +202,31 @@ fn encrypt_aes_gcm_general>( length: usize, ciphertext: &mut [u8], additional_data: Vec, -) -> Result { +) -> Result { let nonce = Nonce::::from_slice(&iv); let tag = match length { 128 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Encryption failed"))?; + .map_err(|_| EncryptError::Failed)?; cipher .encrypt_in_place_detached(nonce, &additional_data, ciphertext) - .map_err(|_| operation_error("Encryption failed"))? + .map_err(|_| EncryptError::Failed)? } 192 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Encryption failed"))?; + .map_err(|_| EncryptError::Failed)?; cipher .encrypt_in_place_detached(nonce, &additional_data, ciphertext) - .map_err(|_| operation_error("Encryption failed"))? + .map_err(|_| EncryptError::Failed)? } 256 => { let cipher = aes_gcm::AesGcm::::new_from_slice(key) - .map_err(|_| operation_error("Encryption failed"))?; + .map_err(|_| EncryptError::Failed)?; cipher .encrypt_in_place_detached(nonce, &additional_data, ciphertext) - .map_err(|_| operation_error("Encryption failed"))? + .map_err(|_| EncryptError::Failed)? } - _ => return Err(type_error("invalid length")), + _ => return Err(EncryptError::InvalidLength), }; Ok(tag) @@ -223,7 +239,7 @@ fn encrypt_aes_gcm( iv: Vec, additional_data: Option>, data: &[u8], -) -> Result, AnyError> { +) -> Result, EncryptError> { let key = key.as_secret_key()?; let additional_data = additional_data.unwrap_or_default(); @@ -244,7 +260,7 @@ fn encrypt_aes_gcm( &mut ciphertext, additional_data, )?, - _ => return Err(type_error("iv length not equal to 12 or 16")), + _ => return Err(EncryptError::InvalidIvLength), }; // Truncated tag to the specified tag length. @@ -261,7 +277,7 @@ fn encrypt_aes_ctr_gen( key: &[u8], counter: &[u8], data: &[u8], -) -> Result, AnyError> +) -> Result, EncryptError> where B: KeyIvInit + StreamCipher, { @@ -270,7 +286,7 @@ where let mut ciphertext = data.to_vec(); cipher .try_apply_keystream(&mut ciphertext) - .map_err(|_| operation_error("tried to encrypt too much data"))?; + .map_err(|_| EncryptError::TooMuchData)?; Ok(ciphertext) } @@ -281,7 +297,7 @@ fn encrypt_aes_ctr( counter: &[u8], ctr_length: usize, data: &[u8], -) -> Result, AnyError> { +) -> Result, EncryptError> { let key = key.as_secret_key()?; match ctr_length { @@ -289,22 +305,20 @@ fn encrypt_aes_ctr( 128 => encrypt_aes_ctr_gen::>(key, counter, data), 192 => encrypt_aes_ctr_gen::>(key, counter, data), 256 => encrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(EncryptError::InvalidLength), }, 64 => match key_length { 128 => encrypt_aes_ctr_gen::>(key, counter, data), 192 => encrypt_aes_ctr_gen::>(key, counter, data), 256 => encrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(EncryptError::InvalidLength), }, 128 => match key_length { 128 => encrypt_aes_ctr_gen::>(key, counter, data), 192 => encrypt_aes_ctr_gen::>(key, counter, data), 256 => encrypt_aes_ctr_gen::>(key, counter, data), - _ => Err(type_error("invalid length")), + _ => Err(EncryptError::InvalidLength), }, - _ => Err(type_error( - "invalid counter length. Currently supported 32/64/128 bits", - )), + _ => Err(EncryptError::InvalidCounterLength), } } diff --git a/ext/crypto/export_key.rs b/ext/crypto/export_key.rs index 588e9978b0..edf0d7239c 100644 --- a/ext/crypto/export_key.rs +++ b/ext/crypto/export_key.rs @@ -4,8 +4,6 @@ use base64::prelude::BASE64_URL_SAFE_NO_PAD; use base64::Engine; use const_oid::AssociatedOid; use const_oid::ObjectIdentifier; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::ToJsBuffer; use elliptic_curve::sec1::ToEncodedPoint; @@ -22,6 +20,16 @@ use spki::AlgorithmIdentifierOwned; use crate::shared::*; +#[derive(Debug, thiserror::Error)] +pub enum ExportKeyError { + #[error(transparent)] + General(#[from] SharedError), + #[error(transparent)] + Der(#[from] spki::der::Error), + #[error("Unsupported named curve")] + UnsupportedNamedCurve, +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExportKeyOptions { @@ -99,7 +107,7 @@ pub enum ExportKeyResult { pub fn op_crypto_export_key( #[serde] opts: ExportKeyOptions, #[serde] key_data: V8RawKeyData, -) -> Result { +) -> Result { match opts.algorithm { ExportKeyAlgorithm::RsassaPkcs1v15 {} | ExportKeyAlgorithm::RsaPss {} @@ -125,7 +133,7 @@ fn bytes_to_b64(bytes: &[u8]) -> String { fn export_key_rsa( format: ExportKeyFormat, key_data: V8RawKeyData, -) -> Result { +) -> Result { match format { ExportKeyFormat::Spki => { let subject_public_key = &key_data.as_rsa_public_key()?; @@ -181,12 +189,7 @@ fn export_key_rsa( ExportKeyFormat::JwkPublic => { let public_key = key_data.as_rsa_public_key()?; let public_key = rsa::pkcs1::RsaPublicKey::from_der(&public_key) - .map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "failed to decode public key", - ) - })?; + .map_err(|_| SharedError::FailedDecodePublicKey)?; Ok(ExportKeyResult::JwkPublicRsa { n: uint_to_b64(public_key.modulus), @@ -196,12 +199,7 @@ fn export_key_rsa( ExportKeyFormat::JwkPrivate => { let private_key = key_data.as_rsa_private_key()?; let private_key = rsa::pkcs1::RsaPrivateKey::from_der(private_key) - .map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "failed to decode private key", - ) - })?; + .map_err(|_| SharedError::FailedDecodePrivateKey)?; Ok(ExportKeyResult::JwkPrivateRsa { n: uint_to_b64(private_key.modulus), @@ -214,14 +212,14 @@ fn export_key_rsa( qi: uint_to_b64(private_key.coefficient), }) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } fn export_key_symmetric( format: ExportKeyFormat, key_data: V8RawKeyData, -) -> Result { +) -> Result { match format { ExportKeyFormat::JwkSecret => { let bytes = key_data.as_secret_key()?; @@ -230,7 +228,7 @@ fn export_key_symmetric( k: bytes_to_b64(bytes), }) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } @@ -239,7 +237,7 @@ fn export_key_ec( key_data: V8RawKeyData, algorithm: ExportKeyAlgorithm, named_curve: EcNamedCurve, -) -> Result { +) -> Result { match format { ExportKeyFormat::Raw => { let subject_public_key = match named_curve { @@ -254,7 +252,9 @@ fn export_key_ec( point.as_ref().to_vec() } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + let point = key_data.as_ec_public_key_p521()?; + + point.as_ref().to_vec() } }; Ok(ExportKeyResult::Raw(subject_public_key.into())) @@ -272,7 +272,9 @@ fn export_key_ec( point.as_ref().to_vec() } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + let point = key_data.as_ec_public_key_p521()?; + + point.as_ref().to_vec() } }; @@ -285,9 +287,10 @@ fn export_key_ec( oid: elliptic_curve::ALGORITHM_OID, parameters: Some((&p384::NistP384::OID).into()), }, - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } + EcNamedCurve::P521 => AlgorithmIdentifierOwned { + oid: elliptic_curve::ALGORITHM_OID, + parameters: Some((&p521::NistP521::OID).into()), + }, }; let alg_id = match algorithm { @@ -327,10 +330,7 @@ fn export_key_ec( y: bytes_to_b64(y), }) } else { - Err(custom_error( - "DOMExceptionOperationError", - "failed to decode public key", - )) + Err(SharedError::FailedDecodePublicKey.into()) } } EcNamedCurve::P384 => { @@ -345,26 +345,32 @@ fn export_key_ec( y: bytes_to_b64(y), }) } else { - Err(custom_error( - "DOMExceptionOperationError", - "failed to decode public key", - )) + Err(SharedError::FailedDecodePublicKey.into()) + } + } + EcNamedCurve::P521 => { + let point = key_data.as_ec_public_key_p521()?; + let coords = point.coordinates(); + + if let p521::elliptic_curve::sec1::Coordinates::Uncompressed { x, y } = + coords + { + Ok(ExportKeyResult::JwkPublicEc { + x: bytes_to_b64(x), + y: bytes_to_b64(y), + }) + } else { + Err(SharedError::FailedDecodePublicKey.into()) } } - EcNamedCurve::P521 => Err(data_error("Unsupported named curve")), }, ExportKeyFormat::JwkPrivate => { let private_key = key_data.as_ec_private_key()?; match named_curve { EcNamedCurve::P256 => { - let ec_key = - p256::SecretKey::from_pkcs8_der(private_key).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "failed to decode private key", - ) - })?; + let ec_key = p256::SecretKey::from_pkcs8_der(private_key) + .map_err(|_| SharedError::FailedDecodePrivateKey)?; let point = ec_key.public_key().to_encoded_point(false); if let elliptic_curve::sec1::Coordinates::Uncompressed { x, y } = @@ -376,18 +382,13 @@ fn export_key_ec( d: bytes_to_b64(&ec_key.to_bytes()), }) } else { - Err(data_error("expected valid public EC key")) + Err(SharedError::ExpectedValidPublicECKey.into()) } } EcNamedCurve::P384 => { - let ec_key = - p384::SecretKey::from_pkcs8_der(private_key).map_err(|_| { - custom_error( - "DOMExceptionOperationError", - "failed to decode private key", - ) - })?; + let ec_key = p384::SecretKey::from_pkcs8_der(private_key) + .map_err(|_| SharedError::FailedDecodePrivateKey)?; let point = ec_key.public_key().to_encoded_point(false); if let elliptic_curve::sec1::Coordinates::Uncompressed { x, y } = @@ -399,12 +400,12 @@ fn export_key_ec( d: bytes_to_b64(&ec_key.to_bytes()), }) } else { - Err(data_error("expected valid public EC key")) + Err(SharedError::ExpectedValidPublicECKey.into()) } } - _ => Err(not_supported_error("Unsupported namedCurve")), + _ => Err(ExportKeyError::UnsupportedNamedCurve), } } - ExportKeyFormat::JwkSecret => Err(unsupported_format()), + ExportKeyFormat::JwkSecret => Err(SharedError::UnsupportedFormat.into()), } } diff --git a/ext/crypto/generate_key.rs b/ext/crypto/generate_key.rs index 43aea2c705..3c0bd77c22 100644 --- a/ext/crypto/generate_key.rs +++ b/ext/crypto/generate_key.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::unsync::spawn_blocking; use deno_core::ToJsBuffer; @@ -16,6 +15,26 @@ use serde::Deserialize; use crate::shared::*; +#[derive(Debug, thiserror::Error)] +pub enum GenerateKeyError { + #[error(transparent)] + General(#[from] SharedError), + #[error("Bad public exponent")] + BadPublicExponent, + #[error("Invalid HMAC key length")] + InvalidHMACKeyLength, + #[error("Failed to serialize RSA key")] + FailedRSAKeySerialization, + #[error("Invalid AES key length")] + InvalidAESKeyLength, + #[error("Failed to generate RSA key")] + FailedRSAKeyGeneration, + #[error("Failed to generate EC key")] + FailedECKeyGeneration, + #[error("Failed to generate key")] + FailedKeyGeneration, +} + // Allowlist for RSA public exponents. static PUB_EXPONENT_1: Lazy = Lazy::new(|| BigUint::from_u64(3).unwrap()); @@ -46,7 +65,7 @@ pub enum GenerateKeyOptions { #[serde] pub async fn op_crypto_generate_key( #[serde] opts: GenerateKeyOptions, -) -> Result { +) -> Result { let fun = || match opts { GenerateKeyOptions::Rsa { modulus_length, @@ -65,21 +84,21 @@ pub async fn op_crypto_generate_key( fn generate_key_rsa( modulus_length: u32, public_exponent: &[u8], -) -> Result, AnyError> { +) -> Result, GenerateKeyError> { let exponent = BigUint::from_bytes_be(public_exponent); if exponent != *PUB_EXPONENT_1 && exponent != *PUB_EXPONENT_2 { - return Err(operation_error("Bad public exponent")); + return Err(GenerateKeyError::BadPublicExponent); } let mut rng = OsRng; let private_key = RsaPrivateKey::new_with_exp(&mut rng, modulus_length as usize, &exponent) - .map_err(|_| operation_error("Failed to generate RSA key"))?; + .map_err(|_| GenerateKeyError::FailedRSAKeyGeneration)?; let private_key = private_key .to_pkcs1_der() - .map_err(|_| operation_error("Failed to serialize RSA key"))?; + .map_err(|_| GenerateKeyError::FailedRSAKeySerialization)?; Ok(private_key.as_bytes().to_vec()) } @@ -90,7 +109,9 @@ fn generate_key_ec_p521() -> Vec { key.to_nonzero_scalar().to_bytes().to_vec() } -fn generate_key_ec(named_curve: EcNamedCurve) -> Result, AnyError> { +fn generate_key_ec( + named_curve: EcNamedCurve, +) -> Result, GenerateKeyError> { let curve = match named_curve { EcNamedCurve::P256 => &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING, EcNamedCurve::P384 => &ring::signature::ECDSA_P384_SHA384_FIXED_SIGNING, @@ -100,21 +121,21 @@ fn generate_key_ec(named_curve: EcNamedCurve) -> Result, AnyError> { let rng = ring::rand::SystemRandom::new(); let pkcs8 = EcdsaKeyPair::generate_pkcs8(curve, &rng) - .map_err(|_| operation_error("Failed to generate EC key"))?; + .map_err(|_| GenerateKeyError::FailedECKeyGeneration)?; Ok(pkcs8.as_ref().to_vec()) } -fn generate_key_aes(length: usize) -> Result, AnyError> { +fn generate_key_aes(length: usize) -> Result, GenerateKeyError> { if length % 8 != 0 || length > 256 { - return Err(operation_error("Invalid AES key length")); + return Err(GenerateKeyError::InvalidAESKeyLength); } let mut key = vec![0u8; length / 8]; let rng = ring::rand::SystemRandom::new(); rng .fill(&mut key) - .map_err(|_| operation_error("Failed to generate key"))?; + .map_err(|_| GenerateKeyError::FailedKeyGeneration)?; Ok(key) } @@ -122,7 +143,7 @@ fn generate_key_aes(length: usize) -> Result, AnyError> { fn generate_key_hmac( hash: ShaHash, length: Option, -) -> Result, AnyError> { +) -> Result, GenerateKeyError> { let hash = match hash { ShaHash::Sha1 => &ring::hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, ShaHash::Sha256 => &ring::hmac::HMAC_SHA256, @@ -132,12 +153,12 @@ fn generate_key_hmac( let length = if let Some(length) = length { if length % 8 != 0 { - return Err(operation_error("Invalid HMAC key length")); + return Err(GenerateKeyError::InvalidHMACKeyLength); } let length = length / 8; if length > ring::digest::MAX_BLOCK_LEN { - return Err(operation_error("Invalid HMAC key length")); + return Err(GenerateKeyError::InvalidHMACKeyLength); } length @@ -149,7 +170,7 @@ fn generate_key_hmac( let mut key = vec![0u8; length]; rng .fill(&mut key) - .map_err(|_| operation_error("Failed to generate key"))?; + .map_err(|_| GenerateKeyError::FailedKeyGeneration)?; Ok(key) } diff --git a/ext/crypto/import_key.rs b/ext/crypto/import_key.rs index 7b06cae99e..3463ca2beb 100644 --- a/ext/crypto/import_key.rs +++ b/ext/crypto/import_key.rs @@ -1,22 +1,83 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use base64::Engine; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::JsBuffer; use deno_core::ToJsBuffer; use elliptic_curve::pkcs8::PrivateKeyInfo; use p256::pkcs8::EncodePrivateKey; -use ring::signature::EcdsaKeyPair; use rsa::pkcs1::UintRef; use rsa::pkcs8::der::Encode; use serde::Deserialize; use serde::Serialize; use spki::der::Decode; -use crate::key::CryptoNamedCurve; use crate::shared::*; +#[derive(Debug, thiserror::Error)] +pub enum ImportKeyError { + #[error(transparent)] + General(#[from] SharedError), + #[error("invalid modulus")] + InvalidModulus, + #[error("invalid public exponent")] + InvalidPublicExponent, + #[error("invalid private exponent")] + InvalidPrivateExponent, + #[error("invalid first prime factor")] + InvalidFirstPrimeFactor, + #[error("invalid second prime factor")] + InvalidSecondPrimeFactor, + #[error("invalid first CRT exponent")] + InvalidFirstCRTExponent, + #[error("invalid second CRT exponent")] + InvalidSecondCRTExponent, + #[error("invalid CRT coefficient")] + InvalidCRTCoefficient, + #[error("invalid b64 coordinate")] + InvalidB64Coordinate, + #[error("invalid RSA public key")] + InvalidRSAPublicKey, + #[error("invalid RSA private key")] + InvalidRSAPrivateKey, + #[error("unsupported algorithm")] + UnsupportedAlgorithm, + #[error("public key is invalid (too long)")] + PublicKeyTooLong, + #[error("private key is invalid (too long)")] + PrivateKeyTooLong, + #[error("invalid P-256 elliptic curve point")] + InvalidP256ECPoint, + #[error("invalid P-384 elliptic curve point")] + InvalidP384ECPoint, + #[error("invalid P-521 elliptic curve point")] + InvalidP521ECPoint, + #[error("invalid P-256 elliptic curve SPKI data")] + InvalidP256ECSPKIData, + #[error("invalid P-384 elliptic curve SPKI data")] + InvalidP384ECSPKIData, + #[error("invalid P-521 elliptic curve SPKI data")] + InvalidP521ECSPKIData, + #[error("curve mismatch")] + CurveMismatch, + #[error("Unsupported named curve")] + UnsupportedNamedCurve, + #[error("invalid key data")] + InvalidKeyData, + #[error("invalid JWK private key")] + InvalidJWKPrivateKey, + #[error(transparent)] + EllipticCurve(#[from] elliptic_curve::Error), + #[error("expected valid PKCS#8 data")] + ExpectedValidPkcs8Data, + #[error("malformed parameters")] + MalformedParameters, + #[error(transparent)] + Spki(#[from] spki::Error), + #[error(transparent)] + Der(#[from] rsa::pkcs1::der::Error), +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub enum KeyData { @@ -45,7 +106,9 @@ pub enum KeyData { y: String, }, JwkPrivateEc { + #[allow(dead_code)] x: String, + #[allow(dead_code)] y: String, d: String, }, @@ -93,7 +156,7 @@ pub enum ImportKeyResult { pub fn op_crypto_import_key( #[serde] opts: ImportKeyOptions, #[serde] key_data: KeyData, -) -> Result { +) -> Result { match opts { ImportKeyOptions::RsassaPkcs1v15 {} => import_key_rsassa(key_data), ImportKeyOptions::RsaPss {} => import_key_rsapss(key_data), @@ -117,21 +180,21 @@ const BASE64_URL_SAFE_FORGIVING: ); macro_rules! jwt_b64_int_or_err { - ($name:ident, $b64:expr, $err:expr) => { + ($name:ident, $b64:expr, $err:tt) => { let bytes = BASE64_URL_SAFE_FORGIVING .decode($b64) - .map_err(|_| data_error($err))?; - let $name = UintRef::new(&bytes).map_err(|_| data_error($err))?; + .map_err(|_| ImportKeyError::$err)?; + let $name = UintRef::new(&bytes).map_err(|_| ImportKeyError::$err)?; }; } fn import_key_rsa_jwk( key_data: KeyData, -) -> Result { +) -> Result { match key_data { KeyData::JwkPublicRsa { n, e } => { - jwt_b64_int_or_err!(modulus, &n, "invalid modulus"); - jwt_b64_int_or_err!(public_exponent, &e, "invalid public exponent"); + jwt_b64_int_or_err!(modulus, &n, InvalidModulus); + jwt_b64_int_or_err!(public_exponent, &e, InvalidPublicExponent); let public_key = rsa::pkcs1::RsaPublicKey { modulus, @@ -141,7 +204,7 @@ fn import_key_rsa_jwk( let mut data = Vec::new(); public_key .encode_to_vec(&mut data) - .map_err(|_| data_error("invalid rsa public key"))?; + .map_err(|_| ImportKeyError::InvalidRSAPublicKey)?; let public_exponent = public_key.public_exponent.as_bytes().to_vec().into(); @@ -163,14 +226,14 @@ fn import_key_rsa_jwk( dq, qi, } => { - jwt_b64_int_or_err!(modulus, &n, "invalid modulus"); - jwt_b64_int_or_err!(public_exponent, &e, "invalid public exponent"); - jwt_b64_int_or_err!(private_exponent, &d, "invalid private exponent"); - jwt_b64_int_or_err!(prime1, &p, "invalid first prime factor"); - jwt_b64_int_or_err!(prime2, &q, "invalid second prime factor"); - jwt_b64_int_or_err!(exponent1, &dp, "invalid first CRT exponent"); - jwt_b64_int_or_err!(exponent2, &dq, "invalid second CRT exponent"); - jwt_b64_int_or_err!(coefficient, &qi, "invalid CRT coefficient"); + jwt_b64_int_or_err!(modulus, &n, InvalidModulus); + jwt_b64_int_or_err!(public_exponent, &e, InvalidPublicExponent); + jwt_b64_int_or_err!(private_exponent, &d, InvalidPrivateExponent); + jwt_b64_int_or_err!(prime1, &p, InvalidFirstPrimeFactor); + jwt_b64_int_or_err!(prime2, &q, InvalidSecondPrimeFactor); + jwt_b64_int_or_err!(exponent1, &dp, InvalidFirstCRTExponent); + jwt_b64_int_or_err!(exponent2, &dq, InvalidSecondCRTExponent); + jwt_b64_int_or_err!(coefficient, &qi, InvalidCRTCoefficient); let private_key = rsa::pkcs1::RsaPrivateKey { modulus, @@ -187,7 +250,7 @@ fn import_key_rsa_jwk( let mut data = Vec::new(); private_key .encode_to_vec(&mut data) - .map_err(|_| data_error("invalid rsa private key"))?; + .map_err(|_| ImportKeyError::InvalidRSAPrivateKey)?; let public_exponent = private_key.public_exponent.as_bytes().to_vec().into(); @@ -205,37 +268,33 @@ fn import_key_rsa_jwk( fn import_key_rsassa( key_data: KeyData, -) -> Result { +) -> Result { match key_data { KeyData::Spki(data) => { // 2-3. - let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let public_key = rsa::pkcs1::RsaPublicKey::from_der( pk_info.subject_public_key.raw_bytes(), - ) - .map_err(|e| data_error(e.to_string()))?; + )?; - let bytes_consumed = public_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = public_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new( pk_info.subject_public_key.raw_bytes().len() as u16, ) { - return Err(data_error("public key is invalid (too long)")); + return Err(ImportKeyError::PublicKeyTooLong); } let data = pk_info.subject_public_key.raw_bytes().to_vec().into(); @@ -251,30 +310,26 @@ fn import_key_rsassa( } KeyData::Pkcs8(data) => { // 2-3. - let pk_info = PrivateKeyInfo::from_der(&data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = PrivateKeyInfo::from_der(&data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let private_key = - rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key) - .map_err(|e| data_error(e.to_string()))?; + rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; - let bytes_consumed = private_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = private_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16) { - return Err(data_error("private key is invalid (too long)")); + return Err(ImportKeyError::PrivateKeyTooLong); } let data = pk_info.private_key.to_vec().into(); @@ -291,43 +346,39 @@ fn import_key_rsassa( KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => { import_key_rsa_jwk(key_data) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } fn import_key_rsapss( key_data: KeyData, -) -> Result { +) -> Result { match key_data { KeyData::Spki(data) => { // 2-3. - let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let public_key = rsa::pkcs1::RsaPublicKey::from_der( pk_info.subject_public_key.raw_bytes(), - ) - .map_err(|e| data_error(e.to_string()))?; + )?; - let bytes_consumed = public_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = public_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new( pk_info.subject_public_key.raw_bytes().len() as u16, ) { - return Err(data_error("public key is invalid (too long)")); + return Err(ImportKeyError::PublicKeyTooLong); } let data = pk_info.subject_public_key.raw_bytes().to_vec().into(); @@ -343,30 +394,26 @@ fn import_key_rsapss( } KeyData::Pkcs8(data) => { // 2-3. - let pk_info = PrivateKeyInfo::from_der(&data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = PrivateKeyInfo::from_der(&data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let private_key = - rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key) - .map_err(|e| data_error(e.to_string()))?; + rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; - let bytes_consumed = private_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = private_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16) { - return Err(data_error("private key is invalid (too long)")); + return Err(ImportKeyError::PrivateKeyTooLong); } let data = pk_info.private_key.to_vec().into(); @@ -383,43 +430,39 @@ fn import_key_rsapss( KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => { import_key_rsa_jwk(key_data) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } fn import_key_rsaoaep( key_data: KeyData, -) -> Result { +) -> Result { match key_data { KeyData::Spki(data) => { // 2-3. - let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let public_key = rsa::pkcs1::RsaPublicKey::from_der( pk_info.subject_public_key.raw_bytes(), - ) - .map_err(|e| data_error(e.to_string()))?; + )?; - let bytes_consumed = public_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = public_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new( pk_info.subject_public_key.raw_bytes().len() as u16, ) { - return Err(data_error("public key is invalid (too long)")); + return Err(ImportKeyError::PublicKeyTooLong); } let data = pk_info.subject_public_key.raw_bytes().to_vec().into(); @@ -435,30 +478,26 @@ fn import_key_rsaoaep( } KeyData::Pkcs8(data) => { // 2-3. - let pk_info = PrivateKeyInfo::from_der(&data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = PrivateKeyInfo::from_der(&data)?; // 4-5. let alg = pk_info.algorithm.oid; // 6-7. (skipped, only support rsaEncryption for interoperability) if alg != RSA_ENCRYPTION_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 8-9. let private_key = - rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key) - .map_err(|e| data_error(e.to_string()))?; + rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; - let bytes_consumed = private_key - .encoded_len() - .map_err(|e| data_error(e.to_string()))?; + let bytes_consumed = private_key.encoded_len()?; if bytes_consumed != rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16) { - return Err(data_error("private key is invalid (too long)")); + return Err(ImportKeyError::PrivateKeyTooLong); } let data = pk_info.private_key.to_vec().into(); @@ -475,14 +514,14 @@ fn import_key_rsaoaep( KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => { import_key_rsa_jwk(key_data) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } fn decode_b64url_to_field_bytes( b64: &str, -) -> Result, deno_core::anyhow::Error> { - jwt_b64_int_or_err!(val, b64, "invalid b64 coordinate"); +) -> Result, ImportKeyError> { + jwt_b64_int_or_err!(val, b64, InvalidB64Coordinate); let mut bytes = elliptic_curve::FieldBytes::::default(); let original_bytes = val.as_bytes(); @@ -495,7 +534,7 @@ fn decode_b64url_to_field_bytes( let val = new_bytes.as_slice(); if val.len() != bytes.len() { - return Err(data_error("invalid b64 coordinate")); + return Err(ImportKeyError::InvalidB64Coordinate); } bytes.copy_from_slice(val); @@ -506,7 +545,7 @@ fn import_key_ec_jwk_to_point( x: String, y: String, named_curve: EcNamedCurve, -) -> Result, deno_core::anyhow::Error> { +) -> Result, ImportKeyError> { let point_bytes = match named_curve { EcNamedCurve::P256 => { let x = decode_b64url_to_field_bytes::(&x)?; @@ -534,7 +573,7 @@ fn import_key_ec_jwk_to_point( fn import_key_ec_jwk( key_data: KeyData, named_curve: EcNamedCurve, -) -> Result { +) -> Result { match key_data { KeyData::JwkPublicEc { x, y } => { let point_bytes = import_key_ec_jwk_to_point(x, y, named_curve)?; @@ -543,46 +582,31 @@ fn import_key_ec_jwk( raw_data: RustRawKeyData::Public(point_bytes.into()), }) } - KeyData::JwkPrivateEc { d, x, y } => { - jwt_b64_int_or_err!(private_d, &d, "invalid JWK private key"); - let point_bytes = import_key_ec_jwk_to_point(x, y, named_curve)?; + KeyData::JwkPrivateEc { d, .. } => { let pkcs8_der = match named_curve { EcNamedCurve::P256 => { let d = decode_b64url_to_field_bytes::(&d)?; let pk = p256::SecretKey::from_bytes(&d)?; pk.to_pkcs8_der() - .map_err(|_| data_error("invalid JWK private key"))? + .map_err(|_| ImportKeyError::InvalidJWKPrivateKey)? } EcNamedCurve::P384 => { let d = decode_b64url_to_field_bytes::(&d)?; let pk = p384::SecretKey::from_bytes(&d)?; pk.to_pkcs8_der() - .map_err(|_| data_error("invalid JWK private key"))? + .map_err(|_| ImportKeyError::InvalidJWKPrivateKey)? } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + let d = decode_b64url_to_field_bytes::(&d)?; + let pk = p521::SecretKey::from_bytes(&d)?; + + pk.to_pkcs8_der() + .map_err(|_| ImportKeyError::InvalidJWKPrivateKey)? } }; - // Import using ring, to validate key - let key_alg = match named_curve { - EcNamedCurve::P256 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P384 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; - - let rng = ring::rand::SystemRandom::new(); - let _key_pair = EcdsaKeyPair::from_private_key_and_public_key( - key_alg, - private_d.as_bytes(), - point_bytes.as_ref(), - &rng, - ); - Ok(ImportKeyResult::Ec { raw_data: RustRawKeyData::Private(pkcs8_der.as_bytes().to_vec().into()), }) @@ -610,7 +634,7 @@ impl<'a> TryFrom> for ECParametersSpki { fn import_key_ec( key_data: KeyData, named_curve: EcNamedCurve, -) -> Result { +) -> Result { match key_data { KeyData::Raw(data) => { // The point is parsed and validated, ultimately the original data is @@ -619,28 +643,28 @@ fn import_key_ec( EcNamedCurve::P256 => { // 1-2. let point = p256::EncodedPoint::from_bytes(&data) - .map_err(|_| data_error("invalid P-256 elliptic curve point"))?; + .map_err(|_| ImportKeyError::InvalidP256ECPoint)?; // 3. if point.is_identity() { - return Err(data_error("invalid P-256 elliptic curve point")); + return Err(ImportKeyError::InvalidP256ECPoint); } } EcNamedCurve::P384 => { // 1-2. let point = p384::EncodedPoint::from_bytes(&data) - .map_err(|_| data_error("invalid P-384 elliptic curve point"))?; + .map_err(|_| ImportKeyError::InvalidP384ECPoint)?; // 3. if point.is_identity() { - return Err(data_error("invalid P-384 elliptic curve point")); + return Err(ImportKeyError::InvalidP384ECPoint); } } EcNamedCurve::P521 => { // 1-2. let point = p521::EncodedPoint::from_bytes(&data) - .map_err(|_| data_error("invalid P-521 elliptic curve point"))?; + .map_err(|_| ImportKeyError::InvalidP521ECPoint)?; // 3. if point.is_identity() { - return Err(data_error("invalid P-521 elliptic curve point")); + return Err(ImportKeyError::InvalidP521ECPoint); } } }; @@ -649,24 +673,15 @@ fn import_key_ec( }) } KeyData::Pkcs8(data) => { - // 2-7 - // Deserialize PKCS8 - validate structure, extracts named_curve - let named_curve_alg = match named_curve { - EcNamedCurve::P256 | EcNamedCurve::P384 => { - let pk = PrivateKeyInfo::from_der(data.as_ref()) - .map_err(|_| data_error("expected valid PKCS#8 data"))?; - pk.algorithm - .parameters - .ok_or_else(|| data_error("malformed parameters"))? - .try_into() - .unwrap() - } - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; + let pk = PrivateKeyInfo::from_der(data.as_ref()) + .map_err(|_| ImportKeyError::ExpectedValidPkcs8Data)?; + let named_curve_alg = pk + .algorithm + .parameters + .ok_or(ImportKeyError::MalformedParameters)? + .try_into() + .unwrap(); - // 8-9. let pk_named_curve = match named_curve_alg { // id-secp256r1 ID_SECP256R1_OID => Some(EcNamedCurve::P256), @@ -677,26 +692,8 @@ fn import_key_ec( _ => None, }; - // 10. - if let Some(pk_named_curve) = pk_named_curve { - let signing_alg = match pk_named_curve { - EcNamedCurve::P256 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P384 => CryptoNamedCurve::P384.into(), - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; - - let rng = ring::rand::SystemRandom::new(); - // deserialize pkcs8 using ring crate, to VALIDATE public key - let _private_key = EcdsaKeyPair::from_pkcs8(signing_alg, &data, &rng)?; - - // 11. - if named_curve != pk_named_curve { - return Err(data_error("curve mismatch")); - } - } else { - return Err(data_error("Unsupported named curve")); + if pk_named_curve != Some(named_curve) { + return Err(ImportKeyError::CurveMismatch); } Ok(ImportKeyResult::Ec { @@ -705,14 +702,13 @@ fn import_key_ec( } KeyData::Spki(data) => { // 2-3. - let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data) - .map_err(|e| data_error(e.to_string()))?; + let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?; // 4. let alg = pk_info.algorithm.oid; // id-ecPublicKey if alg != elliptic_curve::ALGORITHM_OID { - return Err(data_error("unsupported algorithm")); + return Err(ImportKeyError::UnsupportedAlgorithm); } // 5-7. @@ -720,9 +716,9 @@ fn import_key_ec( pk_info .algorithm .parameters - .ok_or_else(|| data_error("malformed parameters"))?, + .ok_or(ImportKeyError::MalformedParameters)?, ) - .map_err(|_| data_error("malformed parameters"))?; + .map_err(|_| ImportKeyError::MalformedParameters)?; // 8-9. let named_curve_alg = params.named_curve_alg; @@ -746,36 +742,30 @@ fn import_key_ec( let bytes_consumed = match named_curve { EcNamedCurve::P256 => { - let point = - p256::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| { - data_error("invalid P-256 elliptic curve SPKI data") - })?; + let point = p256::EncodedPoint::from_bytes(&*encoded_key) + .map_err(|_| ImportKeyError::InvalidP256ECSPKIData)?; if point.is_identity() { - return Err(data_error("invalid P-256 elliptic curve point")); + return Err(ImportKeyError::InvalidP256ECPoint); } point.as_bytes().len() } EcNamedCurve::P384 => { - let point = - p384::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| { - data_error("invalid P-384 elliptic curve SPKI data") - })?; + let point = p384::EncodedPoint::from_bytes(&*encoded_key) + .map_err(|_| ImportKeyError::InvalidP384ECSPKIData)?; if point.is_identity() { - return Err(data_error("invalid P-384 elliptic curve point")); + return Err(ImportKeyError::InvalidP384ECPoint); } point.as_bytes().len() } EcNamedCurve::P521 => { - let point = - p521::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| { - data_error("invalid P-521 elliptic curve SPKI data") - })?; + let point = p521::EncodedPoint::from_bytes(&*encoded_key) + .map_err(|_| ImportKeyError::InvalidP521ECSPKIData)?; if point.is_identity() { - return Err(data_error("invalid P-521 elliptic curve point")); + return Err(ImportKeyError::InvalidP521ECPoint); } point.as_bytes().len() @@ -783,15 +773,15 @@ fn import_key_ec( }; if bytes_consumed != pk_info.subject_public_key.raw_bytes().len() { - return Err(data_error("public key is invalid (too long)")); + return Err(ImportKeyError::PublicKeyTooLong); } // 11. if named_curve != pk_named_curve { - return Err(data_error("curve mismatch")); + return Err(ImportKeyError::CurveMismatch); } } else { - return Err(data_error("Unsupported named curve")); + return Err(ImportKeyError::UnsupportedNamedCurve); } Ok(ImportKeyResult::Ec { @@ -801,34 +791,38 @@ fn import_key_ec( KeyData::JwkPublicEc { .. } | KeyData::JwkPrivateEc { .. } => { import_key_ec_jwk(key_data, named_curve) } - _ => Err(unsupported_format()), + _ => Err(SharedError::UnsupportedFormat.into()), } } -fn import_key_aes(key_data: KeyData) -> Result { +fn import_key_aes( + key_data: KeyData, +) -> Result { Ok(match key_data { KeyData::JwkSecret { k } => { let data = BASE64_URL_SAFE_FORGIVING .decode(k) - .map_err(|_| data_error("invalid key data"))?; + .map_err(|_| ImportKeyError::InvalidKeyData)?; ImportKeyResult::Hmac { raw_data: RustRawKeyData::Secret(data.into()), } } - _ => return Err(unsupported_format()), + _ => return Err(SharedError::UnsupportedFormat.into()), }) } -fn import_key_hmac(key_data: KeyData) -> Result { +fn import_key_hmac( + key_data: KeyData, +) -> Result { Ok(match key_data { KeyData::JwkSecret { k } => { let data = BASE64_URL_SAFE_FORGIVING .decode(k) - .map_err(|_| data_error("invalid key data"))?; + .map_err(|_| ImportKeyError::InvalidKeyData)?; ImportKeyResult::Hmac { raw_data: RustRawKeyData::Secret(data.into()), } } - _ => return Err(unsupported_format()), + _ => return Err(SharedError::UnsupportedFormat.into()), }) } diff --git a/ext/crypto/lib.deno_crypto.d.ts b/ext/crypto/lib.deno_crypto.d.ts index 0c00470ecd..827c0224ce 100644 --- a/ext/crypto/lib.deno_crypto.d.ts +++ b/ext/crypto/lib.deno_crypto.d.ts @@ -9,23 +9,23 @@ declare var crypto: Crypto; /** @category Crypto */ -declare interface Algorithm { +interface Algorithm { name: string; } /** @category Crypto */ -declare interface KeyAlgorithm { +interface KeyAlgorithm { name: string; } /** @category Crypto */ -declare type AlgorithmIdentifier = string | Algorithm; +type AlgorithmIdentifier = string | Algorithm; /** @category Crypto */ -declare type HashAlgorithmIdentifier = AlgorithmIdentifier; +type HashAlgorithmIdentifier = AlgorithmIdentifier; /** @category Crypto */ -declare type KeyType = "private" | "public" | "secret"; +type KeyType = "private" | "public" | "secret"; /** @category Crypto */ -declare type KeyUsage = +type KeyUsage = | "decrypt" | "deriveBits" | "deriveKey" @@ -35,19 +35,19 @@ declare type KeyUsage = | "verify" | "wrapKey"; /** @category Crypto */ -declare type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki"; +type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki"; /** @category Crypto */ -declare type NamedCurve = string; +type NamedCurve = string; /** @category Crypto */ -declare interface RsaOtherPrimesInfo { +interface RsaOtherPrimesInfo { d?: string; r?: string; t?: string; } /** @category Crypto */ -declare interface JsonWebKey { +interface JsonWebKey { alg?: string; crv?: string; d?: string; @@ -56,6 +56,7 @@ declare interface JsonWebKey { e?: string; ext?: boolean; k?: string; + // deno-lint-ignore camelcase key_ops?: string[]; kty?: string; n?: string; @@ -69,129 +70,129 @@ declare interface JsonWebKey { } /** @category Crypto */ -declare interface AesCbcParams extends Algorithm { +interface AesCbcParams extends Algorithm { iv: BufferSource; } /** @category Crypto */ -declare interface AesGcmParams extends Algorithm { +interface AesGcmParams extends Algorithm { iv: BufferSource; additionalData?: BufferSource; tagLength?: number; } /** @category Crypto */ -declare interface AesCtrParams extends Algorithm { +interface AesCtrParams extends Algorithm { counter: BufferSource; length: number; } /** @category Crypto */ -declare interface HmacKeyGenParams extends Algorithm { +interface HmacKeyGenParams extends Algorithm { hash: HashAlgorithmIdentifier; length?: number; } /** @category Crypto */ -declare interface EcKeyGenParams extends Algorithm { +interface EcKeyGenParams extends Algorithm { namedCurve: NamedCurve; } /** @category Crypto */ -declare interface EcKeyImportParams extends Algorithm { +interface EcKeyImportParams extends Algorithm { namedCurve: NamedCurve; } /** @category Crypto */ -declare interface EcdsaParams extends Algorithm { +interface EcdsaParams extends Algorithm { hash: HashAlgorithmIdentifier; } /** @category Crypto */ -declare interface RsaHashedImportParams extends Algorithm { +interface RsaHashedImportParams extends Algorithm { hash: HashAlgorithmIdentifier; } /** @category Crypto */ -declare interface RsaHashedKeyGenParams extends RsaKeyGenParams { +interface RsaHashedKeyGenParams extends RsaKeyGenParams { hash: HashAlgorithmIdentifier; } /** @category Crypto */ -declare interface RsaKeyGenParams extends Algorithm { +interface RsaKeyGenParams extends Algorithm { modulusLength: number; publicExponent: Uint8Array; } /** @category Crypto */ -declare interface RsaPssParams extends Algorithm { +interface RsaPssParams extends Algorithm { saltLength: number; } /** @category Crypto */ -declare interface RsaOaepParams extends Algorithm { +interface RsaOaepParams extends Algorithm { label?: Uint8Array; } /** @category Crypto */ -declare interface HmacImportParams extends Algorithm { +interface HmacImportParams extends Algorithm { hash: HashAlgorithmIdentifier; length?: number; } /** @category Crypto */ -declare interface EcKeyAlgorithm extends KeyAlgorithm { +interface EcKeyAlgorithm extends KeyAlgorithm { namedCurve: NamedCurve; } /** @category Crypto */ -declare interface HmacKeyAlgorithm extends KeyAlgorithm { +interface HmacKeyAlgorithm extends KeyAlgorithm { hash: KeyAlgorithm; length: number; } /** @category Crypto */ -declare interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm { +interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm { hash: KeyAlgorithm; } /** @category Crypto */ -declare interface RsaKeyAlgorithm extends KeyAlgorithm { +interface RsaKeyAlgorithm extends KeyAlgorithm { modulusLength: number; publicExponent: Uint8Array; } /** @category Crypto */ -declare interface HkdfParams extends Algorithm { +interface HkdfParams extends Algorithm { hash: HashAlgorithmIdentifier; info: BufferSource; salt: BufferSource; } /** @category Crypto */ -declare interface Pbkdf2Params extends Algorithm { +interface Pbkdf2Params extends Algorithm { hash: HashAlgorithmIdentifier; iterations: number; salt: BufferSource; } /** @category Crypto */ -declare interface AesDerivedKeyParams extends Algorithm { +interface AesDerivedKeyParams extends Algorithm { length: number; } /** @category Crypto */ -declare interface EcdhKeyDeriveParams extends Algorithm { +interface EcdhKeyDeriveParams extends Algorithm { public: CryptoKey; } /** @category Crypto */ -declare interface AesKeyGenParams extends Algorithm { +interface AesKeyGenParams extends Algorithm { length: number; } /** @category Crypto */ -declare interface AesKeyAlgorithm extends KeyAlgorithm { +interface AesKeyAlgorithm extends KeyAlgorithm { length: number; } @@ -200,7 +201,7 @@ declare interface AesKeyAlgorithm extends KeyAlgorithm { * * @category Crypto */ -declare interface CryptoKey { +interface CryptoKey { readonly algorithm: KeyAlgorithm; readonly extractable: boolean; readonly type: KeyType; @@ -218,7 +219,7 @@ declare var CryptoKey: { * * @category Crypto */ -declare interface CryptoKeyPair { +interface CryptoKeyPair { privateKey: CryptoKey; publicKey: CryptoKey; } @@ -231,11 +232,11 @@ declare var CryptoKeyPair: { /** This Web Crypto API interface provides a number of low-level cryptographic * functions. It is accessed via the Crypto.subtle properties available in a - * window context (via Window.crypto). + * window context (via globalThis.crypto). * * @category Crypto */ -declare interface SubtleCrypto { +interface SubtleCrypto { generateKey( algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, @@ -374,7 +375,7 @@ declare var SubtleCrypto: { }; /** @category Crypto */ -declare interface Crypto { +interface Crypto { readonly subtle: SubtleCrypto; getRandomValues< T extends diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs index 7aa3462c76..69dcd1413a 100644 --- a/ext/crypto/lib.rs +++ b/ext/crypto/lib.rs @@ -6,10 +6,7 @@ use aes_kw::KekAes256; use base64::prelude::BASE64_URL_SAFE_NO_PAD; use base64::Engine; -use deno_core::error::custom_error; use deno_core::error::not_supported; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::ToJsBuffer; @@ -17,7 +14,6 @@ use deno_core::unsync::spawn_blocking; use deno_core::JsBuffer; use deno_core::OpState; use serde::Deserialize; -use shared::operation_error; use p256::elliptic_curve::sec1::FromEncodedPoint; use p256::pkcs8::DecodePrivateKey; @@ -64,17 +60,27 @@ mod import_key; mod key; mod shared; mod x25519; +mod x448; pub use crate::decrypt::op_crypto_decrypt; +pub use crate::decrypt::DecryptError; +pub use crate::ed25519::Ed25519Error; pub use crate::encrypt::op_crypto_encrypt; +pub use crate::encrypt::EncryptError; pub use crate::export_key::op_crypto_export_key; +pub use crate::export_key::ExportKeyError; pub use crate::generate_key::op_crypto_generate_key; +pub use crate::generate_key::GenerateKeyError; pub use crate::import_key::op_crypto_import_key; +pub use crate::import_key::ImportKeyError; use crate::key::Algorithm; use crate::key::CryptoHash; use crate::key::CryptoNamedCurve; use crate::key::HkdfOutput; +pub use crate::shared::SharedError; use crate::shared::V8RawKeyData; +pub use crate::x25519::X25519Error; +pub use crate::x448::X448Error; deno_core::extension!(deno_crypto, deps = [ deno_webidl, deno_web ], @@ -98,6 +104,14 @@ deno_core::extension!(deno_crypto, x25519::op_crypto_derive_bits_x25519, x25519::op_crypto_import_spki_x25519, x25519::op_crypto_import_pkcs8_x25519, + x25519::op_crypto_export_spki_x25519, + x25519::op_crypto_export_pkcs8_x25519, + x448::op_crypto_generate_x448_keypair, + x448::op_crypto_derive_bits_x448, + x448::op_crypto_import_spki_x448, + x448::op_crypto_import_pkcs8_x448, + x448::op_crypto_export_spki_x448, + x448::op_crypto_export_pkcs8_x448, ed25519::op_crypto_generate_ed25519_keypair, ed25519::op_crypto_import_spki_ed25519, ed25519::op_crypto_import_pkcs8_ed25519, @@ -106,8 +120,6 @@ deno_core::extension!(deno_crypto, ed25519::op_crypto_export_spki_ed25519, ed25519::op_crypto_export_pkcs8_ed25519, ed25519::op_crypto_jwk_x_ed25519, - x25519::op_crypto_export_spki_x25519, - x25519::op_crypto_export_pkcs8_x25519, ], esm = [ "00_crypto.js" ], options = { @@ -120,11 +132,63 @@ deno_core::extension!(deno_crypto, }, ); +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + General(#[from] SharedError), + #[error(transparent)] + JoinError(#[from] tokio::task::JoinError), + #[error(transparent)] + Der(#[from] rsa::pkcs1::der::Error), + #[error("Missing argument hash")] + MissingArgumentHash, + #[error("Missing argument saltLength")] + MissingArgumentSaltLength, + #[error("unsupported algorithm")] + UnsupportedAlgorithm, + #[error(transparent)] + KeyRejected(#[from] ring::error::KeyRejected), + #[error(transparent)] + RSA(#[from] rsa::Error), + #[error(transparent)] + Pkcs1(#[from] rsa::pkcs1::Error), + #[error(transparent)] + Unspecified(#[from] ring::error::Unspecified), + #[error("Invalid key format")] + InvalidKeyFormat, + #[error(transparent)] + P256Ecdsa(#[from] p256::ecdsa::Error), + #[error("Unexpected error decoding private key")] + DecodePrivateKey, + #[error("Missing argument publicKey")] + MissingArgumentPublicKey, + #[error("Missing argument namedCurve")] + MissingArgumentNamedCurve, + #[error("Missing argument info")] + MissingArgumentInfo, + #[error("The length provided for HKDF is too large")] + HKDFLengthTooLarge, + #[error(transparent)] + Base64Decode(#[from] base64::DecodeError), + #[error("Data must be multiple of 8 bytes")] + DataInvalidSize, + #[error("Invalid key length")] + InvalidKeyLength, + #[error("encryption error")] + EncryptionError, + #[error("decryption error - integrity check failed")] + DecryptionError, + #[error("The ArrayBufferView's byte length ({0}) exceeds the number of bytes of entropy available via this API (65536)")] + ArrayBufferViewLengthExceeded(usize), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + #[op2] #[serde] pub fn op_crypto_base64url_decode( #[string] data: String, -) -> Result { +) -> Result { let data: Vec = BASE64_URL_SAFE_NO_PAD.decode(data)?; Ok(data.into()) } @@ -140,12 +204,9 @@ pub fn op_crypto_base64url_encode(#[buffer] data: JsBuffer) -> String { pub fn op_crypto_get_random_values( state: &mut OpState, #[buffer] out: &mut [u8], -) -> Result<(), AnyError> { +) -> Result<(), Error> { if out.len() > 65536 { - return Err( - deno_web::DomExceptionQuotaExceededError::new(&format!("The ArrayBufferView's byte length ({}) exceeds the number of bytes of entropy available via this API (65536)", out.len())) - .into(), - ); + return Err(Error::ArrayBufferViewLengthExceeded(out.len())); } let maybe_seeded_rng = state.try_borrow_mut::(); @@ -197,7 +258,7 @@ pub struct SignArg { pub async fn op_crypto_sign_key( #[serde] args: SignArg, #[buffer] zero_copy: JsBuffer, -) -> Result { +) -> Result { deno_core::unsync::spawn_blocking(move || { let data = &*zero_copy; let algorithm = args.algorithm; @@ -206,10 +267,7 @@ pub async fn op_crypto_sign_key( Algorithm::RsassaPkcs1v15 => { use rsa::pkcs1v15::SigningKey; let private_key = RsaPrivateKey::from_pkcs1_der(&args.key.data)?; - match args - .hash - .ok_or_else(|| type_error("Missing argument hash".to_string()))? - { + match args.hash.ok_or_else(|| Error::MissingArgumentHash)? { CryptoHash::Sha1 => { let signing_key = SigningKey::::new(private_key); signing_key.sign(data) @@ -232,15 +290,13 @@ pub async fn op_crypto_sign_key( Algorithm::RsaPss => { let private_key = RsaPrivateKey::from_pkcs1_der(&args.key.data)?; - let salt_len = args.salt_length.ok_or_else(|| { - type_error("Missing argument saltLength".to_string()) - })? as usize; + let salt_len = args + .salt_length + .ok_or_else(|| Error::MissingArgumentSaltLength)? + as usize; let mut rng = OsRng; - match args - .hash - .ok_or_else(|| type_error("Missing argument hash".to_string()))? - { + match args.hash.ok_or_else(|| Error::MissingArgumentHash)? { CryptoHash::Sha1 => { let signing_key = Pss::new_with_salt::(salt_len); let hashed = Sha1::digest(data); @@ -265,8 +321,10 @@ pub async fn op_crypto_sign_key( .to_vec() } Algorithm::Ecdsa => { - let curve: &EcdsaSigningAlgorithm = - args.named_curve.ok_or_else(not_supported)?.into(); + let curve: &EcdsaSigningAlgorithm = args + .named_curve + .ok_or_else(|| Error::Other(not_supported()))? + .into(); let rng = RingRand::SystemRandom::new(); let key_pair = EcdsaKeyPair::from_pkcs8(curve, &args.key.data, &rng)?; @@ -275,7 +333,7 @@ pub async fn op_crypto_sign_key( if let Some(hash) = args.hash { match hash { CryptoHash::Sha256 | CryptoHash::Sha384 => (), - _ => return Err(type_error("Unsupported algorithm")), + _ => return Err(Error::UnsupportedAlgorithm), } }; @@ -285,14 +343,17 @@ pub async fn op_crypto_sign_key( signature.as_ref().to_vec() } Algorithm::Hmac => { - let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into(); + let hash: HmacAlgorithm = args + .hash + .ok_or_else(|| Error::Other(not_supported()))? + .into(); let key = HmacKey::new(hash, &args.key.data); let signature = ring::hmac::sign(&key, data); signature.as_ref().to_vec() } - _ => return Err(type_error("Unsupported algorithm".to_string())), + _ => return Err(Error::UnsupportedAlgorithm), }; Ok(signature.into()) @@ -315,7 +376,7 @@ pub struct VerifyArg { pub async fn op_crypto_verify_key( #[serde] args: VerifyArg, #[buffer] zero_copy: JsBuffer, -) -> Result { +) -> Result { deno_core::unsync::spawn_blocking(move || { let data = &*zero_copy; let algorithm = args.algorithm; @@ -326,10 +387,7 @@ pub async fn op_crypto_verify_key( use rsa::pkcs1v15::VerifyingKey; let public_key = read_rsa_public_key(args.key)?; let signature: Signature = args.signature.as_ref().try_into()?; - match args - .hash - .ok_or_else(|| type_error("Missing argument hash".to_string()))? - { + match args.hash.ok_or_else(|| Error::MissingArgumentHash)? { CryptoHash::Sha1 => { let verifying_key = VerifyingKey::::new(public_key); verifying_key.verify(data, &signature).is_ok() @@ -352,14 +410,12 @@ pub async fn op_crypto_verify_key( let public_key = read_rsa_public_key(args.key)?; let signature = args.signature.as_ref(); - let salt_len = args.salt_length.ok_or_else(|| { - type_error("Missing argument saltLength".to_string()) - })? as usize; + let salt_len = args + .salt_length + .ok_or_else(|| Error::MissingArgumentSaltLength)? + as usize; - match args - .hash - .ok_or_else(|| type_error("Missing argument hash".to_string()))? - { + match args.hash.ok_or_else(|| Error::MissingArgumentHash)? { CryptoHash::Sha1 => { let pss = Pss::new_with_salt::(salt_len); let hashed = Sha1::digest(data); @@ -383,15 +439,22 @@ pub async fn op_crypto_verify_key( } } Algorithm::Hmac => { - let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into(); + let hash: HmacAlgorithm = args + .hash + .ok_or_else(|| Error::Other(not_supported()))? + .into(); let key = HmacKey::new(hash, &args.key.data); ring::hmac::verify(&key, data, &args.signature).is_ok() } Algorithm::Ecdsa => { - let signing_alg: &EcdsaSigningAlgorithm = - args.named_curve.ok_or_else(not_supported)?.into(); - let verify_alg: &EcdsaVerificationAlgorithm = - args.named_curve.ok_or_else(not_supported)?.into(); + let signing_alg: &EcdsaSigningAlgorithm = args + .named_curve + .ok_or_else(|| Error::Other(not_supported()))? + .into(); + let verify_alg: &EcdsaVerificationAlgorithm = args + .named_curve + .ok_or_else(|| Error::Other(not_supported()))? + .into(); let private_key; @@ -404,7 +467,7 @@ pub async fn op_crypto_verify_key( private_key.public_key().as_ref() } KeyType::Public => &*args.key.data, - _ => return Err(type_error("Invalid Key format".to_string())), + _ => return Err(Error::InvalidKeyFormat), }; let public_key = @@ -412,7 +475,7 @@ pub async fn op_crypto_verify_key( public_key.verify(data, &args.signature).is_ok() } - _ => return Err(type_error("Unsupported algorithm".to_string())), + _ => return Err(Error::UnsupportedAlgorithm), }; Ok(verification) @@ -440,70 +503,68 @@ pub struct DeriveKeyArg { pub async fn op_crypto_derive_bits( #[serde] args: DeriveKeyArg, #[buffer] zero_copy: Option, -) -> Result { +) -> Result { deno_core::unsync::spawn_blocking(move || { let algorithm = args.algorithm; match algorithm { Algorithm::Pbkdf2 => { - let zero_copy = zero_copy.ok_or_else(not_supported)?; + let zero_copy = + zero_copy.ok_or_else(|| Error::Other(not_supported()))?; let salt = &*zero_copy; // The caller must validate these cases. assert!(args.length > 0); assert!(args.length % 8 == 0); - let algorithm = match args.hash.ok_or_else(not_supported)? { - CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1, - CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256, - CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384, - CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512, - }; + let algorithm = + match args.hash.ok_or_else(|| Error::Other(not_supported()))? { + CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1, + CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256, + CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384, + CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512, + }; // This will never panic. We have already checked length earlier. - let iterations = - NonZeroU32::new(args.iterations.ok_or_else(not_supported)?).unwrap(); + let iterations = NonZeroU32::new( + args + .iterations + .ok_or_else(|| Error::Other(not_supported()))?, + ) + .unwrap(); let secret = args.key.data; let mut out = vec![0; args.length / 8]; pbkdf2::derive(algorithm, iterations, salt, &secret, &mut out); Ok(out.into()) } Algorithm::Ecdh => { - let named_curve = args.named_curve.ok_or_else(|| { - type_error("Missing argument namedCurve".to_string()) - })?; + let named_curve = args + .named_curve + .ok_or_else(|| Error::MissingArgumentNamedCurve)?; let public_key = args .public_key - .ok_or_else(|| type_error("Missing argument publicKey"))?; + .ok_or_else(|| Error::MissingArgumentPublicKey)?; match named_curve { CryptoNamedCurve::P256 => { let secret_key = p256::SecretKey::from_pkcs8_der(&args.key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })?; + .map_err(|_| Error::DecodePrivateKey)?; let public_key = match public_key.r#type { KeyType::Private => { p256::SecretKey::from_pkcs8_der(&public_key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })? + .map_err(|_| Error::DecodePrivateKey)? .public_key() } KeyType::Public => { let point = p256::EncodedPoint::from_bytes(public_key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })?; + .map_err(|_| Error::DecodePrivateKey)?; let pk = p256::PublicKey::from_encoded_point(&point); // pk is a constant time Option. if pk.is_some().into() { pk.unwrap() } else { - return Err(type_error( - "Unexpected error decoding private key", - )); + return Err(Error::DecodePrivateKey); } } _ => unreachable!(), @@ -519,32 +580,24 @@ pub async fn op_crypto_derive_bits( } CryptoNamedCurve::P384 => { let secret_key = p384::SecretKey::from_pkcs8_der(&args.key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })?; + .map_err(|_| Error::DecodePrivateKey)?; let public_key = match public_key.r#type { KeyType::Private => { p384::SecretKey::from_pkcs8_der(&public_key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })? + .map_err(|_| Error::DecodePrivateKey)? .public_key() } KeyType::Public => { let point = p384::EncodedPoint::from_bytes(public_key.data) - .map_err(|_| { - type_error("Unexpected error decoding private key") - })?; + .map_err(|_| Error::DecodePrivateKey)?; let pk = p384::PublicKey::from_encoded_point(&point); // pk is a constant time Option. if pk.is_some().into() { pk.unwrap() } else { - return Err(type_error( - "Unexpected error decoding private key", - )); + return Err(Error::DecodePrivateKey); } } _ => unreachable!(), @@ -561,18 +614,18 @@ pub async fn op_crypto_derive_bits( } } Algorithm::Hkdf => { - let zero_copy = zero_copy.ok_or_else(not_supported)?; + let zero_copy = + zero_copy.ok_or_else(|| Error::Other(not_supported()))?; let salt = &*zero_copy; - let algorithm = match args.hash.ok_or_else(not_supported)? { - CryptoHash::Sha1 => hkdf::HKDF_SHA1_FOR_LEGACY_USE_ONLY, - CryptoHash::Sha256 => hkdf::HKDF_SHA256, - CryptoHash::Sha384 => hkdf::HKDF_SHA384, - CryptoHash::Sha512 => hkdf::HKDF_SHA512, - }; + let algorithm = + match args.hash.ok_or_else(|| Error::Other(not_supported()))? { + CryptoHash::Sha1 => hkdf::HKDF_SHA1_FOR_LEGACY_USE_ONLY, + CryptoHash::Sha256 => hkdf::HKDF_SHA256, + CryptoHash::Sha384 => hkdf::HKDF_SHA384, + CryptoHash::Sha512 => hkdf::HKDF_SHA512, + }; - let info = args - .info - .ok_or_else(|| type_error("Missing argument info".to_string()))?; + let info = args.info.ok_or_else(|| Error::MissingArgumentInfo)?; // IKM let secret = args.key.data; // L @@ -581,23 +634,20 @@ pub async fn op_crypto_derive_bits( let salt = hkdf::Salt::new(algorithm, salt); let prk = salt.extract(&secret); let info = &[&*info]; - let okm = prk.expand(info, HkdfOutput(length)).map_err(|_e| { - custom_error( - "DOMExceptionOperationError", - "The length provided for HKDF is too large", - ) - })?; + let okm = prk + .expand(info, HkdfOutput(length)) + .map_err(|_e| Error::HKDFLengthTooLarge)?; let mut r = vec![0u8; length]; okm.fill(&mut r)?; Ok(r.into()) } - _ => Err(type_error("Unsupported algorithm".to_string())), + _ => Err(Error::UnsupportedAlgorithm), } }) .await? } -fn read_rsa_public_key(key_data: KeyData) -> Result { +fn read_rsa_public_key(key_data: KeyData) -> Result { let public_key = match key_data.r#type { KeyType::Private => { RsaPrivateKey::from_pkcs1_der(&key_data.data)?.to_public_key() @@ -610,7 +660,7 @@ fn read_rsa_public_key(key_data: KeyData) -> Result { #[op2] #[string] -pub fn op_crypto_random_uuid(state: &mut OpState) -> Result { +pub fn op_crypto_random_uuid(state: &mut OpState) -> Result { let maybe_seeded_rng = state.try_borrow_mut::(); let uuid = if let Some(seeded_rng) = maybe_seeded_rng { let mut bytes = [0u8; 16]; @@ -631,7 +681,7 @@ pub fn op_crypto_random_uuid(state: &mut OpState) -> Result { pub async fn op_crypto_subtle_digest( #[serde] algorithm: CryptoHash, #[buffer] data: JsBuffer, -) -> Result { +) -> Result { let output = spawn_blocking(move || { digest::digest(algorithm.into(), &data) .as_ref() @@ -655,7 +705,7 @@ pub struct WrapUnwrapKeyArg { pub fn op_crypto_wrap_key( #[serde] args: WrapUnwrapKeyArg, #[buffer] data: JsBuffer, -) -> Result { +) -> Result { let algorithm = args.algorithm; match algorithm { @@ -663,20 +713,20 @@ pub fn op_crypto_wrap_key( let key = args.key.as_secret_key()?; if data.len() % 8 != 0 { - return Err(type_error("Data must be multiple of 8 bytes")); + return Err(Error::DataInvalidSize); } let wrapped_key = match key.len() { 16 => KekAes128::new(key.into()).wrap_vec(&data), 24 => KekAes192::new(key.into()).wrap_vec(&data), 32 => KekAes256::new(key.into()).wrap_vec(&data), - _ => return Err(type_error("Invalid key length")), + _ => return Err(Error::InvalidKeyLength), } - .map_err(|_| operation_error("encryption error"))?; + .map_err(|_| Error::EncryptionError)?; Ok(wrapped_key.into()) } - _ => Err(type_error("Unsupported algorithm")), + _ => Err(Error::UnsupportedAlgorithm), } } @@ -685,29 +735,27 @@ pub fn op_crypto_wrap_key( pub fn op_crypto_unwrap_key( #[serde] args: WrapUnwrapKeyArg, #[buffer] data: JsBuffer, -) -> Result { +) -> Result { let algorithm = args.algorithm; match algorithm { Algorithm::AesKw => { let key = args.key.as_secret_key()?; if data.len() % 8 != 0 { - return Err(type_error("Data must be multiple of 8 bytes")); + return Err(Error::DataInvalidSize); } let unwrapped_key = match key.len() { 16 => KekAes128::new(key.into()).unwrap_vec(&data), 24 => KekAes192::new(key.into()).unwrap_vec(&data), 32 => KekAes256::new(key.into()).unwrap_vec(&data), - _ => return Err(type_error("Invalid key length")), + _ => return Err(Error::InvalidKeyLength), } - .map_err(|_| { - operation_error("decryption error - integrity check failed") - })?; + .map_err(|_| Error::DecryptionError)?; Ok(unwrapped_key.into()) } - _ => Err(type_error("Unsupported algorithm")), + _ => Err(Error::UnsupportedAlgorithm), } } diff --git a/ext/crypto/shared.rs b/ext/crypto/shared.rs index 21fddc745f..f70d32856c 100644 --- a/ext/crypto/shared.rs +++ b/ext/crypto/shared.rs @@ -2,9 +2,6 @@ use std::borrow::Cow; -use deno_core::error::custom_error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::JsBuffer; use deno_core::ToJsBuffer; use elliptic_curve::sec1::ToEncodedPoint; @@ -63,49 +60,73 @@ pub enum RustRawKeyData { Public(ToJsBuffer), } +#[derive(Debug, thiserror::Error)] +pub enum SharedError { + #[error("expected valid private key")] + ExpectedValidPrivateKey, + #[error("expected valid public key")] + ExpectedValidPublicKey, + #[error("expected valid private EC key")] + ExpectedValidPrivateECKey, + #[error("expected valid public EC key")] + ExpectedValidPublicECKey, + #[error("expected private key")] + ExpectedPrivateKey, + #[error("expected public key")] + ExpectedPublicKey, + #[error("expected secret key")] + ExpectedSecretKey, + #[error("failed to decode private key")] + FailedDecodePrivateKey, + #[error("failed to decode public key")] + FailedDecodePublicKey, + #[error("unsupported format")] + UnsupportedFormat, +} + impl V8RawKeyData { - pub fn as_rsa_public_key(&self) -> Result, AnyError> { + pub fn as_rsa_public_key(&self) -> Result, SharedError> { match self { V8RawKeyData::Public(data) => Ok(Cow::Borrowed(data)), V8RawKeyData::Private(data) => { let private_key = RsaPrivateKey::from_pkcs1_der(data) - .map_err(|_| type_error("expected valid private key"))?; + .map_err(|_| SharedError::ExpectedValidPrivateKey)?; let public_key_doc = private_key .to_public_key() .to_pkcs1_der() - .map_err(|_| type_error("expected valid public key"))?; + .map_err(|_| SharedError::ExpectedValidPublicKey)?; Ok(Cow::Owned(public_key_doc.as_bytes().into())) } - _ => Err(type_error("expected public key")), + _ => Err(SharedError::ExpectedPublicKey), } } - pub fn as_rsa_private_key(&self) -> Result<&[u8], AnyError> { + pub fn as_rsa_private_key(&self) -> Result<&[u8], SharedError> { match self { V8RawKeyData::Private(data) => Ok(data), - _ => Err(type_error("expected private key")), + _ => Err(SharedError::ExpectedPrivateKey), } } - pub fn as_secret_key(&self) -> Result<&[u8], AnyError> { + pub fn as_secret_key(&self) -> Result<&[u8], SharedError> { match self { V8RawKeyData::Secret(data) => Ok(data), - _ => Err(type_error("expected secret key")), + _ => Err(SharedError::ExpectedSecretKey), } } - pub fn as_ec_public_key_p256(&self) -> Result { + pub fn as_ec_public_key_p256( + &self, + ) -> Result { match self { - V8RawKeyData::Public(data) => { - // public_key is a serialized EncodedPoint - p256::EncodedPoint::from_bytes(data) - .map_err(|_| type_error("expected valid public EC key")) - } + V8RawKeyData::Public(data) => p256::PublicKey::from_sec1_bytes(data) + .map(|p| p.to_encoded_point(false)) + .map_err(|_| SharedError::ExpectedValidPublicECKey), V8RawKeyData::Private(data) => { let signing_key = p256::SecretKey::from_pkcs8_der(data) - .map_err(|_| type_error("expected valid private EC key"))?; + .map_err(|_| SharedError::ExpectedValidPrivateECKey)?; Ok(signing_key.public_key().to_encoded_point(false)) } // Should never reach here. @@ -113,16 +134,35 @@ impl V8RawKeyData { } } - pub fn as_ec_public_key_p384(&self) -> Result { + pub fn as_ec_public_key_p384( + &self, + ) -> Result { + match self { + V8RawKeyData::Public(data) => p384::PublicKey::from_sec1_bytes(data) + .map(|p| p.to_encoded_point(false)) + .map_err(|_| SharedError::ExpectedValidPublicECKey), + V8RawKeyData::Private(data) => { + let signing_key = p384::SecretKey::from_pkcs8_der(data) + .map_err(|_| SharedError::ExpectedValidPrivateECKey)?; + Ok(signing_key.public_key().to_encoded_point(false)) + } + // Should never reach here. + V8RawKeyData::Secret(_) => unreachable!(), + } + } + + pub fn as_ec_public_key_p521( + &self, + ) -> Result { match self { V8RawKeyData::Public(data) => { // public_key is a serialized EncodedPoint - p384::EncodedPoint::from_bytes(data) - .map_err(|_| type_error("expected valid public EC key")) + p521::EncodedPoint::from_bytes(data) + .map_err(|_| SharedError::ExpectedValidPublicECKey) } V8RawKeyData::Private(data) => { - let signing_key = p384::SecretKey::from_pkcs8_der(data) - .map_err(|_| type_error("expected valid private EC key"))?; + let signing_key = p521::SecretKey::from_pkcs8_der(data) + .map_err(|_| SharedError::ExpectedValidPrivateECKey)?; Ok(signing_key.public_key().to_encoded_point(false)) } // Should never reach here. @@ -130,26 +170,10 @@ impl V8RawKeyData { } } - pub fn as_ec_private_key(&self) -> Result<&[u8], AnyError> { + pub fn as_ec_private_key(&self) -> Result<&[u8], SharedError> { match self { V8RawKeyData::Private(data) => Ok(data), - _ => Err(type_error("expected private key")), + _ => Err(SharedError::ExpectedPrivateKey), } } } - -pub fn data_error(msg: impl Into>) -> AnyError { - custom_error("DOMExceptionDataError", msg) -} - -pub fn not_supported_error(msg: impl Into>) -> AnyError { - custom_error("DOMExceptionNotSupportedError", msg) -} - -pub fn operation_error(msg: impl Into>) -> AnyError { - custom_error("DOMExceptionOperationError", msg) -} - -pub fn unsupported_format() -> AnyError { - not_supported_error("unsupported format") -} diff --git a/ext/crypto/x25519.rs b/ext/crypto/x25519.rs index 8fcad3ef21..d2c4d986b9 100644 --- a/ext/crypto/x25519.rs +++ b/ext/crypto/x25519.rs @@ -1,8 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use curve25519_dalek::montgomery::MontgomeryPoint; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::ToJsBuffer; use elliptic_curve::pkcs8::PrivateKeyInfo; @@ -13,6 +11,14 @@ use spki::der::asn1::BitString; use spki::der::Decode; use spki::der::Encode; +#[derive(Debug, thiserror::Error)] +pub enum X25519Error { + #[error("Failed to export key")] + FailedExport, + #[error(transparent)] + Der(#[from] spki::der::Error), +} + #[op2(fast)] pub fn op_crypto_generate_x25519_keypair( #[buffer] pkey: &mut [u8], @@ -47,10 +53,10 @@ pub fn op_crypto_derive_bits_x25519( let sh_sec = x25519_dalek::x25519(k, u); let point = MontgomeryPoint(sh_sec); if point.ct_eq(&MONTGOMERY_IDENTITY).unwrap_u8() == 1 { - return false; + return true; } secret.copy_from_slice(&sh_sec); - true + false } // id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } @@ -113,7 +119,7 @@ pub fn op_crypto_import_pkcs8_x25519( #[serde] pub fn op_crypto_export_spki_x25519( #[buffer] pubkey: &[u8], -) -> Result { +) -> Result { let key_info = spki::SubjectPublicKeyInfo { algorithm: spki::AlgorithmIdentifierRef { // id-X25519 @@ -125,9 +131,7 @@ pub fn op_crypto_export_spki_x25519( Ok( key_info .to_der() - .map_err(|_| { - custom_error("DOMExceptionOperationError", "Failed to export key") - })? + .map_err(|_| X25519Error::FailedExport)? .into(), ) } @@ -136,7 +140,7 @@ pub fn op_crypto_export_spki_x25519( #[serde] pub fn op_crypto_export_pkcs8_x25519( #[buffer] pkey: &[u8], -) -> Result { +) -> Result { use rsa::pkcs1::der::Encode; // This should probably use OneAsymmetricKey instead diff --git a/ext/crypto/x448.rs b/ext/crypto/x448.rs new file mode 100644 index 0000000000..89bf48e28b --- /dev/null +++ b/ext/crypto/x448.rs @@ -0,0 +1,152 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use deno_core::op2; +use deno_core::ToJsBuffer; +use ed448_goldilocks::curve::MontgomeryPoint; +use ed448_goldilocks::Scalar; +use elliptic_curve::pkcs8::PrivateKeyInfo; +use elliptic_curve::subtle::ConstantTimeEq; +use rand::rngs::OsRng; +use rand::RngCore; +use spki::der::asn1::BitString; +use spki::der::Decode; +use spki::der::Encode; + +#[derive(Debug, thiserror::Error)] +pub enum X448Error { + #[error("Failed to export key")] + FailedExport, + #[error(transparent)] + Der(#[from] spki::der::Error), +} + +#[op2(fast)] +pub fn op_crypto_generate_x448_keypair( + #[buffer] pkey: &mut [u8], + #[buffer] pubkey: &mut [u8], +) { + let mut rng = OsRng; + rng.fill_bytes(pkey); + + // x448(pkey, 5) + let point = &MontgomeryPoint::generator() + * &Scalar::from_bytes(pkey.try_into().unwrap()); + pubkey.copy_from_slice(&point.0); +} + +const MONTGOMERY_IDENTITY: MontgomeryPoint = MontgomeryPoint([0; 56]); + +#[op2(fast)] +pub fn op_crypto_derive_bits_x448( + #[buffer] k: &[u8], + #[buffer] u: &[u8], + #[buffer] secret: &mut [u8], +) -> bool { + let k: [u8; 56] = k.try_into().expect("Expected byteLength 56"); + let u: [u8; 56] = u.try_into().expect("Expected byteLength 56"); + + // x448(k, u) + let point = &MontgomeryPoint(u) * &Scalar::from_bytes(k); + if point.ct_eq(&MONTGOMERY_IDENTITY).unwrap_u8() == 1 { + return true; + } + + secret.copy_from_slice(&point.0); + false +} + +// id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } +const X448_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.3.101.111"); + +#[op2] +#[serde] +pub fn op_crypto_export_spki_x448( + #[buffer] pubkey: &[u8], +) -> Result { + let key_info = spki::SubjectPublicKeyInfo { + algorithm: spki::AlgorithmIdentifierRef { + oid: X448_OID, + parameters: None, + }, + subject_public_key: BitString::from_bytes(pubkey)?, + }; + Ok( + key_info + .to_der() + .map_err(|_| X448Error::FailedExport)? + .into(), + ) +} + +#[op2] +#[serde] +pub fn op_crypto_export_pkcs8_x448( + #[buffer] pkey: &[u8], +) -> Result { + use rsa::pkcs1::der::Encode; + + let pk_info = rsa::pkcs8::PrivateKeyInfo { + public_key: None, + algorithm: rsa::pkcs8::AlgorithmIdentifierRef { + oid: X448_OID, + parameters: None, + }, + private_key: pkey, // OCTET STRING + }; + + let mut buf = Vec::new(); + pk_info.encode_to_vec(&mut buf)?; + Ok(buf.into()) +} + +#[op2(fast)] +pub fn op_crypto_import_spki_x448( + #[buffer] key_data: &[u8], + #[buffer] out: &mut [u8], +) -> bool { + // 2-3. + let pk_info = match spki::SubjectPublicKeyInfoRef::try_from(key_data) { + Ok(pk_info) => pk_info, + Err(_) => return false, + }; + // 4. + let alg = pk_info.algorithm.oid; + if alg != X448_OID { + return false; + } + // 5. + if pk_info.algorithm.parameters.is_some() { + return false; + } + out.copy_from_slice(pk_info.subject_public_key.raw_bytes()); + true +} + +#[op2(fast)] +pub fn op_crypto_import_pkcs8_x448( + #[buffer] key_data: &[u8], + #[buffer] out: &mut [u8], +) -> bool { + // 2-3. + let pk_info = match PrivateKeyInfo::from_der(key_data) { + Ok(pk_info) => pk_info, + Err(_) => return false, + }; + // 4. + let alg = pk_info.algorithm.oid; + if alg != X448_OID { + return false; + } + // 5. + if pk_info.algorithm.parameters.is_some() { + return false; + } + // 6. + // CurvePrivateKey ::= OCTET STRING + if pk_info.private_key.len() != 56 { + return false; + } + out.copy_from_slice(&pk_info.private_key[2..]); + true +} diff --git a/ext/fetch/20_headers.js b/ext/fetch/20_headers.js index 1690d9f7d6..e56a74c423 100644 --- a/ext/fetch/20_headers.js +++ b/ext/fetch/20_headers.js @@ -73,7 +73,7 @@ function fillHeaders(headers, object) { const header = object[i]; if (header.length !== 2) { throw new TypeError( - `Invalid header. Length must be 2, but is ${header.length}`, + `Invalid header: length must be 2, but is ${header.length}`, ); } appendHeader(headers, header[0], header[1]); @@ -133,15 +133,15 @@ function appendHeader(headers, name, value) { // 2. if (!checkHeaderNameForHttpTokenCodePoint(name)) { - throw new TypeError("Header name is not valid."); + throw new TypeError(`Invalid header name: "${name}"`); } if (!checkForInvalidValueChars(value)) { - throw new TypeError("Header value is not valid."); + throw new TypeError(`Invalid header value: "${value}"`); } // 3. if (headers[_guard] == "immutable") { - throw new TypeError("Headers are immutable."); + throw new TypeError("Cannot change header: headers are immutable"); } // 7. @@ -330,10 +330,10 @@ class Headers { name = webidl.converters["ByteString"](name, prefix, "Argument 1"); if (!checkHeaderNameForHttpTokenCodePoint(name)) { - throw new TypeError("Header name is not valid."); + throw new TypeError(`Invalid header name: "${name}"`); } if (this[_guard] == "immutable") { - throw new TypeError("Headers are immutable."); + throw new TypeError("Cannot change headers: headers are immutable"); } const list = this[_headerList]; @@ -356,7 +356,7 @@ class Headers { name = webidl.converters["ByteString"](name, prefix, "Argument 1"); if (!checkHeaderNameForHttpTokenCodePoint(name)) { - throw new TypeError("Header name is not valid."); + throw new TypeError(`Invalid header name: "${name}"`); } const list = this[_headerList]; @@ -387,7 +387,7 @@ class Headers { name = webidl.converters["ByteString"](name, prefix, "Argument 1"); if (!checkHeaderNameForHttpTokenCodePoint(name)) { - throw new TypeError("Header name is not valid."); + throw new TypeError(`Invalid header name: "${name}"`); } const list = this[_headerList]; @@ -415,14 +415,14 @@ class Headers { // 2. if (!checkHeaderNameForHttpTokenCodePoint(name)) { - throw new TypeError("Header name is not valid."); + throw new TypeError(`Invalid header name: "${name}"`); } if (!checkForInvalidValueChars(value)) { - throw new TypeError("Header value is not valid."); + throw new TypeError(`Invalid header value: "${value}"`); } if (this[_guard] == "immutable") { - throw new TypeError("Headers are immutable."); + throw new TypeError("Cannot change headers: headers are immutable"); } const list = this[_headerList]; diff --git a/ext/fetch/21_formdata.js b/ext/fetch/21_formdata.js index bb33ea2d47..7d466b8e25 100644 --- a/ext/fetch/21_formdata.js +++ b/ext/fetch/21_formdata.js @@ -396,7 +396,9 @@ class MultipartParser { */ constructor(body, boundary) { if (!boundary) { - throw new TypeError("multipart/form-data must provide a boundary"); + throw new TypeError( + "Cannot construct MultipartParser: multipart/form-data must provide a boundary", + ); } this.boundary = `--${boundary}`; @@ -445,7 +447,7 @@ class MultipartParser { ) { return new FormData(); } - throw new TypeError("Unable to parse body as form data."); + throw new TypeError("Unable to parse body as form data"); } const formData = new FormData(); diff --git a/ext/fetch/22_body.js b/ext/fetch/22_body.js index ae5aef8acb..61a06b4afd 100644 --- a/ext/fetch/22_body.js +++ b/ext/fetch/22_body.js @@ -151,7 +151,7 @@ class InnerBody { * @returns {Promise} */ consume() { - if (this.unusable()) throw new TypeError("Body already consumed."); + if (this.unusable()) throw new TypeError("Body already consumed"); if ( ObjectPrototypeIsPrototypeOf( ReadableStreamPrototype, @@ -263,6 +263,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { /** @type {PropertyDescriptorMap} */ const mixin = { body: { + __proto__: null, /** * @returns {ReadableStream | null} */ @@ -278,6 +279,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, bodyUsed: { + __proto__: null, /** * @returns {boolean} */ @@ -292,6 +294,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, arrayBuffer: { + __proto__: null, /** @returns {Promise} */ value: function arrayBuffer() { return consumeBody(this, "ArrayBuffer"); @@ -301,6 +304,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, blob: { + __proto__: null, /** @returns {Promise} */ value: function blob() { return consumeBody(this, "Blob"); @@ -310,6 +314,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, bytes: { + __proto__: null, /** @returns {Promise} */ value: function bytes() { return consumeBody(this, "bytes"); @@ -319,6 +324,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, formData: { + __proto__: null, /** @returns {Promise} */ value: function formData() { return consumeBody(this, "FormData"); @@ -328,6 +334,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, json: { + __proto__: null, /** @returns {Promise} */ value: function json() { return consumeBody(this, "JSON"); @@ -337,6 +344,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { enumerable: true, }, text: { + __proto__: null, /** @returns {Promise} */ value: function text() { return consumeBody(this, "text"); @@ -372,7 +380,7 @@ function packageData(bytes, type, mimeType) { const boundary = mimeType.parameters.get("boundary"); if (boundary === null) { throw new TypeError( - "Missing boundary parameter in mime type of multipart formdata.", + "Cannot turn into form data: missing boundary parameter in mime type of multipart form data", ); } return parseFormData(chunkToU8(bytes), boundary); @@ -458,8 +466,6 @@ function extractBody(object) { if (object.locked || isReadableStreamDisturbed(object)) { throw new TypeError("ReadableStream is locked or disturbed"); } - } else if (object[webidl.AsyncIterable] === webidl.AsyncIterable) { - stream = ReadableStream.from(object.open()); } if (typeof source === "string") { // WARNING: this deviates from spec (expects length to be set) @@ -477,9 +483,6 @@ function extractBody(object) { return { body, contentType }; } -webidl.converters["async iterable"] = webidl - .createAsyncIterableConverter(webidl.converters.Uint8Array); - webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => { // Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString) if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, V)) { @@ -498,14 +501,6 @@ webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => { if (ArrayBufferIsView(V)) { return webidl.converters["ArrayBufferView"](V, prefix, context, opts); } - if (webidl.isAsyncIterator(V)) { - return webidl.converters["async iterable"]( - V, - prefix, - context, - opts, - ); - } } // BodyInit conversion is passed to extractBody(), which calls core.encode(). // core.encode() will UTF-8 encode strings with replacement, being equivalent to the USV normalization. diff --git a/ext/fetch/22_http_client.js b/ext/fetch/22_http_client.js index 061a3dda89..6a1243ee0b 100644 --- a/ext/fetch/22_http_client.js +++ b/ext/fetch/22_http_client.js @@ -42,6 +42,7 @@ class HttpClient { */ constructor(rid) { ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); diff --git a/ext/fetch/23_request.js b/ext/fetch/23_request.js index adebe13b30..6211e927d9 100644 --- a/ext/fetch/23_request.js +++ b/ext/fetch/23_request.js @@ -122,7 +122,7 @@ function newInnerRequest(method, url, headerList, body, maybeBlob) { try { this.headerListInner = headerList(); } catch { - throw new TypeError("cannot read headers: request closed"); + throw new TypeError("Cannot read headers: request closed"); } } return this.headerListInner; @@ -153,7 +153,7 @@ function newInnerRequest(method, url, headerList, body, maybeBlob) { try { this.urlListProcessed[currentIndex] = this.urlList[currentIndex](); } catch { - throw new TypeError("cannot read url: request closed"); + throw new TypeError("Cannot read url: request closed"); } } return this.urlListProcessed[currentIndex]; @@ -193,7 +193,7 @@ function cloneInnerRequest(request, skipBody = false) { try { this.urlListProcessed[0] = this.urlList[0](); } catch { - throw new TypeError("cannot read url: request closed"); + throw new TypeError("Cannot read url: request closed"); } } return this.urlListProcessed[0]; @@ -204,7 +204,7 @@ function cloneInnerRequest(request, skipBody = false) { try { this.urlListProcessed[currentIndex] = this.urlList[currentIndex](); } catch { - throw new TypeError("cannot read url: request closed"); + throw new TypeError("Cannot read url: request closed"); } } return this.urlListProcessed[currentIndex]; @@ -236,13 +236,13 @@ const KNOWN_METHODS = { */ function validateAndNormalizeMethod(m) { if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) { - throw new TypeError("Method is not valid."); + throw new TypeError("Method is not valid"); } const upperCase = byteUpperCase(m); if ( upperCase === "CONNECT" || upperCase === "TRACE" || upperCase === "TRACK" ) { - throw new TypeError("Method is forbidden."); + throw new TypeError("Method is forbidden"); } return upperCase; } @@ -418,7 +418,7 @@ class Request { ((init.body !== undefined && init.body !== null) || inputBody !== null) ) { - throw new TypeError("Request with GET/HEAD method cannot have body."); + throw new TypeError("Request with GET/HEAD method cannot have body"); } // 36. @@ -442,7 +442,7 @@ class Request { // 41. if (initBody === null && inputBody !== null) { if (input[_body] && input[_body].unusable()) { - throw new TypeError("Input request's body is unusable."); + throw new TypeError("Input request's body is unusable"); } finalBody = inputBody.createProxy(); } @@ -489,7 +489,7 @@ class Request { const prefix = "Failed to execute 'Request.clone'"; webidl.assertBranded(this, RequestPrototype); if (this[_body] && this[_body].unusable()) { - throw new TypeError("Body is unusable."); + throw new TypeError("Body is unusable"); } const clonedReq = cloneInnerRequest(this[_request]); diff --git a/ext/fetch/23_response.js b/ext/fetch/23_response.js index 94fc69a986..278dcb7dec 100644 --- a/ext/fetch/23_response.js +++ b/ext/fetch/23_response.js @@ -61,6 +61,15 @@ const _mimeType = Symbol("mime type"); const _body = Symbol("body"); const _brand = webidl.brand; +// it's slightly faster to cache these +const webidlConvertersBodyInitDomString = + webidl.converters["BodyInit_DOMString?"]; +const webidlConvertersUSVString = webidl.converters["USVString"]; +const webidlConvertersUnsignedShort = webidl.converters["unsigned short"]; +const webidlConvertersAny = webidl.converters["any"]; +const webidlConvertersByteString = webidl.converters["ByteString"]; +const webidlConvertersHeadersInit = webidl.converters["HeadersInit"]; + /** * @typedef InnerResponse * @property {"basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"} type @@ -172,7 +181,7 @@ function initializeAResponse(response, init, bodyWithType) { // 1. if ((init.status < 200 || init.status > 599) && init.status != 101) { throw new RangeError( - `The status provided (${init.status}) is not equal to 101 and outside the range [200, 599].`, + `The status provided (${init.status}) is not equal to 101 and outside the range [200, 599]`, ); } @@ -181,7 +190,9 @@ function initializeAResponse(response, init, bodyWithType) { init.statusText && RegExpPrototypeExec(REASON_PHRASE_RE, init.statusText) === null ) { - throw new TypeError("Status text is not valid."); + throw new TypeError( + `Invalid status text: "${init.statusText}"`, + ); } // 3. @@ -257,13 +268,13 @@ class Response { */ static redirect(url, status = 302) { const prefix = "Failed to execute 'Response.redirect'"; - url = webidl.converters["USVString"](url, prefix, "Argument 1"); - status = webidl.converters["unsigned short"](status, prefix, "Argument 2"); + url = webidlConvertersUSVString(url, prefix, "Argument 1"); + status = webidlConvertersUnsignedShort(status, prefix, "Argument 2"); const baseURL = getLocationHref(); const parsedURL = new URL(url, baseURL); if (!redirectStatus(status)) { - throw new RangeError("Invalid redirect status code."); + throw new RangeError(`Invalid redirect status code: ${status}`); } const inner = newInnerResponse(status); inner.type = "default"; @@ -284,8 +295,8 @@ class Response { */ static json(data = undefined, init = { __proto__: null }) { const prefix = "Failed to execute 'Response.json'"; - data = webidl.converters.any(data); - init = webidl.converters["ResponseInit_fast"](init, prefix, "Argument 2"); + data = webidlConvertersAny(data); + init = webidlConvertersResponseInitFast(init, prefix, "Argument 2"); const str = serializeJSValueToJSONString(data); const res = extractBody(str); @@ -311,8 +322,8 @@ class Response { } const prefix = "Failed to construct 'Response'"; - body = webidl.converters["BodyInit_DOMString?"](body, prefix, "Argument 1"); - init = webidl.converters["ResponseInit_fast"](init, prefix, "Argument 2"); + body = webidlConvertersBodyInitDomString(body, prefix, "Argument 1"); + init = webidlConvertersResponseInitFast(init, prefix, "Argument 2"); this[_response] = newInnerResponse(); this[_headers] = headersFromHeaderList( @@ -395,7 +406,7 @@ class Response { clone() { webidl.assertBranded(this, ResponsePrototype); if (this[_body] && this[_body].unusable()) { - throw new TypeError("Body is unusable."); + throw new TypeError("Body is unusable"); } const second = webidl.createBranded(Response); const newRes = cloneInnerResponse(this[_response]); @@ -430,9 +441,9 @@ class Response { webidl.configureInterface(Response); ObjectDefineProperties(Response, { - json: { enumerable: true }, - redirect: { enumerable: true }, - error: { enumerable: true }, + json: { __proto__: null, enumerable: true }, + redirect: { __proto__: null, enumerable: true }, + error: { __proto__: null, enumerable: true }, }); const ResponsePrototype = Response.prototype; mixinBody(ResponsePrototype, _body, _mimeType); @@ -441,47 +452,49 @@ webidl.converters["Response"] = webidl.createInterfaceConverter( "Response", ResponsePrototype, ); -webidl.converters["ResponseInit"] = webidl.createDictionaryConverter( - "ResponseInit", - [{ - key: "status", - defaultValue: 200, - converter: webidl.converters["unsigned short"], - }, { - key: "statusText", - defaultValue: "", - converter: webidl.converters["ByteString"], - }, { - key: "headers", - converter: webidl.converters["HeadersInit"], - }], -); -webidl.converters["ResponseInit_fast"] = function ( - init, - prefix, - context, - opts, -) { - if (init === undefined || init === null) { - return { status: 200, statusText: "", headers: undefined }; - } - // Fast path, if not a proxy - if (typeof init === "object" && !core.isProxy(init)) { - // Not a proxy fast path - const status = init.status !== undefined - ? webidl.converters["unsigned short"](init.status) - : 200; - const statusText = init.statusText !== undefined - ? webidl.converters["ByteString"](init.statusText) - : ""; - const headers = init.headers !== undefined - ? webidl.converters["HeadersInit"](init.headers) - : undefined; - return { status, statusText, headers }; - } - // Slow default path - return webidl.converters["ResponseInit"](init, prefix, context, opts); -}; +const webidlConvertersResponseInit = webidl.converters["ResponseInit"] = webidl + .createDictionaryConverter( + "ResponseInit", + [{ + key: "status", + defaultValue: 200, + converter: webidlConvertersUnsignedShort, + }, { + key: "statusText", + defaultValue: "", + converter: webidlConvertersByteString, + }, { + key: "headers", + converter: webidlConvertersHeadersInit, + }], + ); +const webidlConvertersResponseInitFast = webidl + .converters["ResponseInit_fast"] = function ( + init, + prefix, + context, + opts, + ) { + if (init === undefined || init === null) { + return { status: 200, statusText: "", headers: undefined }; + } + // Fast path, if not a proxy + if (typeof init === "object" && !core.isProxy(init)) { + // Not a proxy fast path + const status = init.status !== undefined + ? webidlConvertersUnsignedShort(init.status) + : 200; + const statusText = init.statusText !== undefined + ? webidlConvertersByteString(init.statusText) + : ""; + const headers = init.headers !== undefined + ? webidlConvertersHeadersInit(init.headers) + : undefined; + return { status, statusText, headers }; + } + // Slow default path + return webidlConvertersResponseInit(init, prefix, context, opts); + }; /** * @param {Response} response diff --git a/ext/fetch/26_fetch.js b/ext/fetch/26_fetch.js index e2809187b9..8ac364a931 100644 --- a/ext/fetch/26_fetch.js +++ b/ext/fetch/26_fetch.js @@ -99,7 +99,7 @@ function createResponseBodyStream(responseBodyRid, terminator) { async function mainFetch(req, recursive, terminator) { if (req.blobUrlEntry !== null) { if (req.method !== "GET") { - throw new TypeError("Blob URL fetch only supports GET method."); + throw new TypeError("Blob URL fetch only supports GET method"); } const body = new InnerBody(req.blobUrlEntry.stream()); @@ -145,7 +145,7 @@ async function mainFetch(req, recursive, terminator) { reqRid = resourceForReadableStream(stream, req.body.length); } } else { - throw TypeError("invalid body"); + throw new TypeError("Invalid body"); } } @@ -441,13 +441,15 @@ function handleWasmStreaming(source, rid) { typeof contentType !== "string" || StringPrototypeToLowerCase(contentType) !== "application/wasm" ) { - throw new TypeError("Invalid WebAssembly content type."); + throw new TypeError("Invalid WebAssembly content type"); } } // 2.5. if (!res.ok) { - throw new TypeError(`HTTP status code ${res.status}`); + throw new TypeError( + `Failed to receive WebAssembly content: HTTP status code ${res.status}`, + ); } // Pass the resolved URL to v8. diff --git a/ext/fetch/27_eventsource.js b/ext/fetch/27_eventsource.js index 685eb47c2d..aadbb5fe71 100644 --- a/ext/fetch/27_eventsource.js +++ b/ext/fetch/27_eventsource.js @@ -355,12 +355,15 @@ const EventSourcePrototype = EventSource.prototype; ObjectDefineProperties(EventSource, { CONNECTING: { + __proto__: null, value: 0, }, OPEN: { + __proto__: null, value: 1, }, CLOSED: { + __proto__: null, value: 2, }, }); diff --git a/ext/fetch/Cargo.toml b/ext/fetch/Cargo.toml index 75a358b2d7..316a6eea81 100644 --- a/ext/fetch/Cargo.toml +++ b/ext/fetch/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_fetch" -version = "0.188.0" +version = "0.198.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -32,6 +32,7 @@ percent-encoding.workspace = true rustls-webpki.workspace = true serde.workspace = true serde_json.workspace = true +thiserror.workspace = true tokio.workspace = true tokio-rustls.workspace = true tokio-socks.workspace = true diff --git a/ext/fetch/README.md b/ext/fetch/README.md index d088a6147c..3af8110a6f 100644 --- a/ext/fetch/README.md +++ b/ext/fetch/README.md @@ -78,6 +78,5 @@ Following ops are provided, which can be accessed through `Deno.ops`: - op_fetch - op_fetch_send -- op_fetch_response_upgrade - op_utf8_to_byte_string - op_fetch_custom_client diff --git a/ext/fetch/fs_fetch_handler.rs b/ext/fetch/fs_fetch_handler.rs index 6f45ee664e..c236dd9c67 100644 --- a/ext/fetch/fs_fetch_handler.rs +++ b/ext/fetch/fs_fetch_handler.rs @@ -4,7 +4,6 @@ use crate::CancelHandle; use crate::CancelableResponseFuture; use crate::FetchHandler; -use deno_core::error::type_error; use deno_core::futures::FutureExt; use deno_core::futures::TryFutureExt; use deno_core::futures::TryStreamExt; @@ -42,9 +41,7 @@ impl FetchHandler for FsFetchHandler { .map_err(|_| ())?; Ok::<_, ()>(response) } - .map_err(move |_| { - type_error("NetworkError when attempting to fetch resource.") - }) + .map_err(move |_| super::FetchError::NetworkError) .or_cancel(&cancel_handle) .boxed_local(); diff --git a/ext/fetch/lib.deno_fetch.d.ts b/ext/fetch/lib.deno_fetch.d.ts index 3bf608cdb4..d219a38592 100644 --- a/ext/fetch/lib.deno_fetch.d.ts +++ b/ext/fetch/lib.deno_fetch.d.ts @@ -6,7 +6,7 @@ /// /** @category Platform */ -declare interface DomIterable { +interface DomIterable { keys(): IterableIterator; values(): IterableIterator; entries(): IterableIterator<[K, V]>; @@ -18,7 +18,7 @@ declare interface DomIterable { } /** @category Fetch */ -declare type FormDataEntryValue = File | string; +type FormDataEntryValue = File | string; /** Provides a way to easily construct a set of key/value pairs representing * form fields and their values, which can then be easily sent using the @@ -27,7 +27,7 @@ declare type FormDataEntryValue = File | string; * * @category Fetch */ -declare interface FormData extends DomIterable { +interface FormData extends DomIterable { append(name: string, value: string | Blob, fileName?: string): void; delete(name: string): void; get(name: string): FormDataEntryValue | null; @@ -43,7 +43,7 @@ declare var FormData: { }; /** @category Fetch */ -declare interface Body { +interface Body { /** A simple getter used to expose a `ReadableStream` of the body contents. */ readonly body: ReadableStream | null; /** Stores a `Boolean` that declares whether the body has been used in a @@ -77,7 +77,7 @@ declare interface Body { } /** @category Fetch */ -declare type HeadersInit = Iterable | Record; +type HeadersInit = Iterable | Record; /** This Fetch API interface allows you to perform various actions on HTTP * request and response headers. These actions include retrieving, setting, @@ -89,7 +89,7 @@ declare type HeadersInit = Iterable | Record; * * @category Fetch */ -declare interface Headers extends DomIterable { +interface Headers extends DomIterable { /** Appends a new value onto an existing header inside a `Headers` object, or * adds the header if it does not already exist. */ @@ -130,9 +130,9 @@ declare var Headers: { }; /** @category Fetch */ -declare type RequestInfo = Request | string; +type RequestInfo = Request | string; /** @category Fetch */ -declare type RequestCache = +type RequestCache = | "default" | "force-cache" | "no-cache" @@ -140,13 +140,13 @@ declare type RequestCache = | "only-if-cached" | "reload"; /** @category Fetch */ -declare type RequestCredentials = "include" | "omit" | "same-origin"; +type RequestCredentials = "include" | "omit" | "same-origin"; /** @category Fetch */ -declare type RequestMode = "cors" | "navigate" | "no-cors" | "same-origin"; +type RequestMode = "cors" | "navigate" | "no-cors" | "same-origin"; /** @category Fetch */ -declare type RequestRedirect = "error" | "follow" | "manual"; +type RequestRedirect = "error" | "follow" | "manual"; /** @category Fetch */ -declare type ReferrerPolicy = +type ReferrerPolicy = | "" | "no-referrer" | "no-referrer-when-downgrade" @@ -157,16 +157,15 @@ declare type ReferrerPolicy = | "strict-origin-when-cross-origin" | "unsafe-url"; /** @category Fetch */ -declare type BodyInit = +type BodyInit = | Blob | BufferSource | FormData | URLSearchParams | ReadableStream - | AsyncIterable | string; /** @category Fetch */ -declare type RequestDestination = +type RequestDestination = | "" | "audio" | "audioworklet" @@ -187,7 +186,7 @@ declare type RequestDestination = | "xslt"; /** @category Fetch */ -declare interface RequestInit { +interface RequestInit { /** * A BodyInit object or null to set request's body. */ @@ -255,7 +254,7 @@ declare interface RequestInit { * * @category Fetch */ -declare interface Request extends Body { +interface Request extends Body { /** * Returns the cache mode associated with request, which is a string * indicating how the request will interact with the browser's cache when @@ -351,14 +350,14 @@ declare var Request: { }; /** @category Fetch */ -declare interface ResponseInit { +interface ResponseInit { headers?: HeadersInit; status?: number; statusText?: string; } /** @category Fetch */ -declare type ResponseType = +type ResponseType = | "basic" | "cors" | "default" @@ -370,7 +369,7 @@ declare type ResponseType = * * @category Fetch */ -declare interface Response extends Body { +interface Response extends Body { readonly headers: Headers; readonly ok: boolean; readonly redirected: boolean; @@ -414,14 +413,14 @@ declare function fetch( /** * @category Fetch */ -declare interface EventSourceInit { +interface EventSourceInit { withCredentials?: boolean; } /** * @category Fetch */ -declare interface EventSourceEventMap { +interface EventSourceEventMap { "error": Event; "message": MessageEvent; "open": Event; @@ -430,7 +429,7 @@ declare interface EventSourceEventMap { /** * @category Fetch */ -declare interface EventSource extends EventTarget { +interface EventSource extends EventTarget { onerror: ((this: EventSource, ev: Event) => any) | null; onmessage: ((this: EventSource, ev: MessageEvent) => any) | null; onopen: ((this: EventSource, ev: Event) => any) | null; diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index fa85824f44..4df8dc3d72 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -17,10 +17,6 @@ use std::sync::Arc; use std::task::Context; use std::task::Poll; -use deno_core::anyhow::anyhow; -use deno_core::anyhow::Error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures::stream::Peekable; use deno_core::futures::Future; use deno_core::futures::FutureExt; @@ -28,7 +24,7 @@ use deno_core::futures::Stream; use deno_core::futures::StreamExt; use deno_core::futures::TryFutureExt; use deno_core::op2; -use deno_core::unsync::spawn; +use deno_core::url; use deno_core::url::Url; use deno_core::AsyncRefCell; use deno_core::AsyncResult; @@ -70,12 +66,9 @@ use hyper::body::Frame; use hyper_util::client::legacy::connect::HttpConnector; use hyper_util::client::legacy::connect::HttpInfo; use hyper_util::rt::TokioExecutor; -use hyper_util::rt::TokioIo; use hyper_util::rt::TokioTimer; use serde::Deserialize; use serde::Serialize; -use tokio::io::AsyncReadExt; -use tokio::io::AsyncWriteExt; use tower::ServiceExt; use tower_http::decompression::Decompression; @@ -91,15 +84,18 @@ pub struct Options { pub root_cert_store_provider: Option>, pub proxy: Option, #[allow(clippy::type_complexity)] - pub request_builder_hook: - Option) -> Result<(), AnyError>>, + pub request_builder_hook: Option< + fn(&mut http::Request) -> Result<(), deno_core::error::AnyError>, + >, pub unsafely_ignore_certificate_errors: Option>, pub client_cert_chain_and_key: TlsKeys, pub file_fetch_handler: Rc, } impl Options { - pub fn root_cert_store(&self) -> Result, AnyError> { + pub fn root_cert_store( + &self, + ) -> Result, deno_core::error::AnyError> { Ok(match &self.root_cert_store_provider { Some(provider) => Some(provider.get_or_try_init()?.clone()), None => None, @@ -127,7 +123,6 @@ deno_core::extension!(deno_fetch, ops = [ op_fetch, op_fetch_send, - op_fetch_response_upgrade, op_utf8_to_byte_string, op_fetch_custom_client, ], @@ -149,6 +144,51 @@ deno_core::extension!(deno_fetch, }, ); +#[derive(Debug, thiserror::Error)] +pub enum FetchError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error("NetworkError when attempting to fetch resource")] + NetworkError, + #[error("Fetching files only supports the GET method: received {0}")] + FsNotGet(Method), + #[error("Invalid URL {0}")] + InvalidUrl(Url), + #[error(transparent)] + InvalidHeaderName(#[from] http::header::InvalidHeaderName), + #[error(transparent)] + InvalidHeaderValue(#[from] http::header::InvalidHeaderValue), + #[error("{0:?}")] + DataUrl(data_url::DataUrlError), + #[error("{0:?}")] + Base64(data_url::forgiving_base64::InvalidBase64), + #[error("Blob for the given URL not found.")] + BlobNotFound, + #[error("Url scheme '{0}' not supported")] + SchemeNotSupported(String), + #[error("Request was cancelled")] + RequestCanceled, + #[error(transparent)] + Http(#[from] http::Error), + #[error(transparent)] + ClientCreate(#[from] HttpClientCreateError), + #[error(transparent)] + Url(#[from] url::ParseError), + #[error(transparent)] + Method(#[from] http::method::InvalidMethod), + #[error(transparent)] + ClientSend(#[from] ClientSendError), + #[error(transparent)] + RequestBuilderHook(deno_core::error::AnyError), + #[error(transparent)] + Io(#[from] std::io::Error), + // Only used for node upgrade + #[error(transparent)] + Hyper(#[from] hyper::Error), +} + pub type CancelableResponseFuture = Pin>>; @@ -175,11 +215,7 @@ impl FetchHandler for DefaultFileFetchHandler { _state: &mut OpState, _url: &Url, ) -> (CancelableResponseFuture, Option>) { - let fut = async move { - Ok(Err(type_error( - "NetworkError when attempting to fetch resource.", - ))) - }; + let fut = async move { Ok(Err(FetchError::NetworkError)) }; (Box::pin(fut), None) } } @@ -196,7 +232,7 @@ pub struct FetchReturn { pub fn get_or_create_client_from_state( state: &mut OpState, -) -> Result { +) -> Result { if let Some(client) = state.try_borrow::() { Ok(client.clone()) } else { @@ -209,11 +245,13 @@ pub fn get_or_create_client_from_state( pub fn create_client_from_options( options: &Options, -) -> Result { +) -> Result { create_http_client( &options.user_agent, CreateHttpClientOptions { - root_cert_store: options.root_cert_store()?, + root_cert_store: options + .root_cert_store() + .map_err(HttpClientCreateError::RootCertStore)?, ca_certs: vec![], proxy: options.proxy.clone(), unsafely_ignore_certificate_errors: options @@ -235,7 +273,9 @@ pub fn create_client_from_options( #[allow(clippy::type_complexity)] pub struct ResourceToBodyAdapter( Rc, - Option>>>>, + Option< + Pin>>>, + >, ); impl ResourceToBodyAdapter { @@ -251,7 +291,7 @@ unsafe impl Send for ResourceToBodyAdapter {} unsafe impl Sync for ResourceToBodyAdapter {} impl Stream for ResourceToBodyAdapter { - type Item = Result; + type Item = Result; fn poll_next( self: Pin<&mut Self>, @@ -281,7 +321,7 @@ impl Stream for ResourceToBodyAdapter { impl hyper::body::Body for ResourceToBodyAdapter { type Data = Bytes; - type Error = Error; + type Error = deno_core::error::AnyError; fn poll_frame( self: Pin<&mut Self>, @@ -304,10 +344,15 @@ impl Drop for ResourceToBodyAdapter { pub trait FetchPermissions { fn check_net_url( &mut self, - _url: &Url, + url: &Url, api_name: &str, - ) -> Result<(), AnyError>; - fn check_read(&mut self, _p: &Path, api_name: &str) -> Result<(), AnyError>; + ) -> Result<(), deno_core::error::AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result, deno_core::error::AnyError>; } impl FetchPermissions for deno_permissions::PermissionsContainer { @@ -316,17 +361,21 @@ impl FetchPermissions for deno_permissions::PermissionsContainer { &mut self, url: &Url, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), deno_core::error::AnyError> { deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) } #[inline(always)] - fn check_read( + fn check_read<'a>( &mut self, - path: &Path, + path: &'a Path, api_name: &str, - ) -> Result<(), AnyError> { - deno_permissions::PermissionsContainer::check_read(self, path, api_name) + ) -> Result, deno_core::error::AnyError> { + deno_permissions::PermissionsContainer::check_read_path( + self, + path, + Some(api_name), + ) } } @@ -342,12 +391,15 @@ pub fn op_fetch( has_body: bool, #[buffer] data: Option, #[smi] resource: Option, -) -> Result +) -> Result where FP: FetchPermissions + 'static, { let (client, allow_host) = if let Some(rid) = client_rid { - let r = state.resource_table.get::(rid)?; + let r = state + .resource_table + .get::(rid) + .map_err(FetchError::Resource)?; (r.client.clone(), r.allow_host) } else { (get_or_create_client_from_state(state)?, false) @@ -360,16 +412,18 @@ where let scheme = url.scheme(); let (request_rid, cancel_handle_rid) = match scheme { "file" => { - let path = url.to_file_path().map_err(|_| { - type_error("NetworkError when attempting to fetch resource.") - })?; + let path = url.to_file_path().map_err(|_| FetchError::NetworkError)?; let permissions = state.borrow_mut::(); - permissions.check_read(&path, "fetch()")?; + let path = permissions + .check_read(&path, "fetch()") + .map_err(FetchError::Permission)?; + let url = match path { + Cow::Owned(path) => Url::from_file_path(path).unwrap(), + Cow::Borrowed(_) => url, + }; if method != Method::GET { - return Err(type_error(format!( - "Fetching files only supports the GET method. Received {method}." - ))); + return Err(FetchError::FsNotGet(method)); } let Options { @@ -388,13 +442,15 @@ where } "http" | "https" => { let permissions = state.borrow_mut::(); - permissions.check_net_url(&url, "fetch()")?; + permissions + .check_net_url(&url, "fetch()") + .map_err(FetchError::Resource)?; let maybe_authority = extract_authority(&mut url); let uri = url .as_str() .parse::() - .map_err(|_| type_error("Invalid URL"))?; + .map_err(|_| FetchError::InvalidUrl(url.clone()))?; let mut con_len = None; let body = if has_body { @@ -408,7 +464,10 @@ where .boxed() } (_, Some(resource)) => { - let resource = state.resource_table.take_any(resource)?; + let resource = state + .resource_table + .take_any(resource) + .map_err(FetchError::Resource)?; match resource.size_hint() { (body_size, Some(n)) if body_size == n && body_size > 0 => { con_len = Some(body_size); @@ -445,10 +504,8 @@ where } for (key, value) in headers { - let name = HeaderName::from_bytes(&key) - .map_err(|err| type_error(err.to_string()))?; - let v = HeaderValue::from_bytes(&value) - .map_err(|err| type_error(err.to_string()))?; + let name = HeaderName::from_bytes(&key)?; + let v = HeaderValue::from_bytes(&value)?; if (name != HOST || allow_host) && name != CONTENT_LENGTH { request.headers_mut().append(name, v); @@ -466,20 +523,18 @@ where let options = state.borrow::(); if let Some(request_builder_hook) = options.request_builder_hook { request_builder_hook(&mut request) - .map_err(|err| type_error(err.to_string()))?; + .map_err(FetchError::RequestBuilderHook)?; } let cancel_handle = CancelHandle::new_rc(); let cancel_handle_ = cancel_handle.clone(); - let fut = { - async move { - client - .send(request) - .map_err(Into::into) - .or_cancel(cancel_handle_) - .await - } + let fut = async move { + client + .send(request) + .map_err(Into::into) + .or_cancel(cancel_handle_) + .await }; let request_rid = state.resource_table.add(FetchRequestResource { @@ -493,12 +548,10 @@ where (request_rid, Some(cancel_handle_rid)) } "data" => { - let data_url = DataUrl::process(url.as_str()) - .map_err(|e| type_error(format!("{e:?}")))?; + let data_url = + DataUrl::process(url.as_str()).map_err(FetchError::DataUrl)?; - let (body, _) = data_url - .decode_to_vec() - .map_err(|e| type_error(format!("{e:?}")))?; + let (body, _) = data_url.decode_to_vec().map_err(FetchError::Base64)?; let body = http_body_util::Full::new(body.into()) .map_err(|never| match never {}) .boxed(); @@ -520,9 +573,9 @@ where "blob" => { // Blob URL resolution happens in the JS side of fetch. If we got here is // because the URL isn't an object URL. - return Err(type_error("Blob for the given URL not found.")); + return Err(FetchError::BlobNotFound); } - _ => return Err(type_error(format!("scheme '{scheme}' not supported"))), + _ => return Err(FetchError::SchemeNotSupported(scheme.to_string())), }; Ok(FetchReturn { @@ -554,11 +607,12 @@ pub struct FetchResponse { pub async fn op_fetch_send( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let request = state .borrow_mut() .resource_table - .take::(rid)?; + .take::(rid) + .map_err(FetchError::Resource)?; let request = Rc::try_unwrap(request) .ok() @@ -571,22 +625,23 @@ pub async fn op_fetch_send( // If any error in the chain is a hyper body error, return that as a special result we can use to // reconstruct an error chain (eg: `new TypeError(..., { cause: new Error(...) })`). // TODO(mmastrac): it would be a lot easier if we just passed a v8::Global through here instead - let mut err_ref: &dyn std::error::Error = err.as_ref(); - while let Some(err_src) = std::error::Error::source(err_ref) { - if let Some(err_src) = err_src.downcast_ref::() { - if let Some(err_src) = std::error::Error::source(err_src) { - return Ok(FetchResponse { - error: Some((err.to_string(), err_src.to_string())), - ..Default::default() - }); + + if let FetchError::ClientSend(err_src) = &err { + if let Some(client_err) = std::error::Error::source(&err_src.source) { + if let Some(err_src) = client_err.downcast_ref::() { + if let Some(err_src) = std::error::Error::source(err_src) { + return Ok(FetchResponse { + error: Some((err.to_string(), err_src.to_string())), + ..Default::default() + }); + } } } - err_ref = err_src; } - return Err(type_error(err.to_string())); + return Err(err); } - Err(_) => return Err(type_error("request was cancelled")), + Err(_) => return Err(FetchError::RequestCanceled), }; let status = res.status(); @@ -625,116 +680,8 @@ pub async fn op_fetch_send( }) } -#[op2(async)] -#[smi] -pub async fn op_fetch_response_upgrade( - state: Rc>, - #[smi] rid: ResourceId, -) -> Result { - let raw_response = state - .borrow_mut() - .resource_table - .take::(rid)?; - let raw_response = Rc::try_unwrap(raw_response) - .expect("Someone is holding onto FetchResponseResource"); - - let (read, write) = tokio::io::duplex(1024); - let (read_rx, write_tx) = tokio::io::split(read); - let (mut write_rx, mut read_tx) = tokio::io::split(write); - let upgraded = raw_response.upgrade().await?; - { - // Stage 3: Pump the data - let (mut upgraded_rx, mut upgraded_tx) = - tokio::io::split(TokioIo::new(upgraded)); - - spawn(async move { - let mut buf = [0; 1024]; - loop { - let read = upgraded_rx.read(&mut buf).await?; - if read == 0 { - break; - } - read_tx.write_all(&buf[..read]).await?; - } - Ok::<_, AnyError>(()) - }); - spawn(async move { - let mut buf = [0; 1024]; - loop { - let read = write_rx.read(&mut buf).await?; - if read == 0 { - break; - } - upgraded_tx.write_all(&buf[..read]).await?; - } - Ok::<_, AnyError>(()) - }); - } - - Ok( - state - .borrow_mut() - .resource_table - .add(UpgradeStream::new(read_rx, write_tx)), - ) -} - -struct UpgradeStream { - read: AsyncRefCell>, - write: AsyncRefCell>, - cancel_handle: CancelHandle, -} - -impl UpgradeStream { - pub fn new( - read: tokio::io::ReadHalf, - write: tokio::io::WriteHalf, - ) -> Self { - Self { - read: AsyncRefCell::new(read), - write: AsyncRefCell::new(write), - cancel_handle: CancelHandle::new(), - } - } - - async fn read(self: Rc, buf: &mut [u8]) -> Result { - let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); - async { - let read = RcRef::map(self, |this| &this.read); - let mut read = read.borrow_mut().await; - Ok(Pin::new(&mut *read).read(buf).await?) - } - .try_or_cancel(cancel_handle) - .await - } - - async fn write(self: Rc, buf: &[u8]) -> Result { - let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); - async { - let write = RcRef::map(self, |this| &this.write); - let mut write = write.borrow_mut().await; - Ok(Pin::new(&mut *write).write(buf).await?) - } - .try_or_cancel(cancel_handle) - .await - } -} - -impl Resource for UpgradeStream { - fn name(&self) -> Cow { - "fetchUpgradedStream".into() - } - - deno_core::impl_readable_byob!(); - deno_core::impl_writable!(); - - fn close(self: Rc) { - self.cancel_handle.cancel(); - } -} - type CancelableResponseResult = - Result, AnyError>, Canceled>; + Result, FetchError>, Canceled>; pub struct FetchRequestResource { pub future: Pin>>, @@ -789,7 +736,7 @@ impl FetchResponseResource { } } - pub async fn upgrade(self) -> Result { + pub async fn upgrade(self) -> Result { let reader = self.response_reader.into_inner(); match reader { FetchResponseReader::Start(resp) => Ok(hyper::upgrade::on(resp).await?), @@ -844,7 +791,9 @@ impl Resource for FetchResponseResource { // safely call `await` on it without creating a race condition. Some(_) => match reader.as_mut().next().await.unwrap() { Ok(chunk) => assert!(chunk.is_empty()), - Err(err) => break Err(type_error(err.to_string())), + Err(err) => { + break Err(deno_core::error::type_error(err.to_string())) + } }, None => break Ok(BufView::empty()), } @@ -907,14 +856,16 @@ pub fn op_fetch_custom_client( state: &mut OpState, #[serde] args: CreateHttpClientArgs, #[cppgc] tls_keys: &TlsKeysHolder, -) -> Result +) -> Result where FP: FetchPermissions + 'static, { if let Some(proxy) = args.proxy.clone() { let permissions = state.borrow_mut::(); let url = Url::parse(&proxy.url)?; - permissions.check_net_url(&url, "Deno.createHttpClient()")?; + permissions + .check_net_url(&url, "Deno.createHttpClient()") + .map_err(FetchError::Permission)?; } let options = state.borrow::(); @@ -927,7 +878,9 @@ where let client = create_http_client( &options.user_agent, CreateHttpClientOptions { - root_cert_store: options.root_cert_store()?, + root_cert_store: options + .root_cert_store() + .map_err(HttpClientCreateError::RootCertStore)?, ca_certs, proxy: args.proxy, unsafely_ignore_certificate_errors: options @@ -985,19 +938,34 @@ impl Default for CreateHttpClientOptions { } } +#[derive(Debug, thiserror::Error)] +pub enum HttpClientCreateError { + #[error(transparent)] + Tls(deno_tls::TlsError), + #[error("Illegal characters in User-Agent: received {0}")] + InvalidUserAgent(String), + #[error("invalid proxy url")] + InvalidProxyUrl, + #[error("Cannot create Http Client: either `http1` or `http2` needs to be set to true")] + HttpVersionSelectionInvalid, + #[error(transparent)] + RootCertStore(deno_core::error::AnyError), +} + /// Create new instance of async Client. This client supports /// proxies and doesn't follow redirects. pub fn create_http_client( user_agent: &str, options: CreateHttpClientOptions, -) -> Result { +) -> Result { let mut tls_config = deno_tls::create_client_config( options.root_cert_store, options.ca_certs, options.unsafely_ignore_certificate_errors, options.client_cert_chain_and_key.into(), deno_tls::SocketUse::Http, - )?; + ) + .map_err(HttpClientCreateError::Tls)?; // Proxy TLS should not send ALPN tls_config.alpn_protocols.clear(); @@ -1016,9 +984,9 @@ pub fn create_http_client( let mut http_connector = HttpConnector::new(); http_connector.enforce_http(false); - let user_agent = user_agent - .parse::() - .map_err(|_| type_error("illegal characters in User-Agent"))?; + let user_agent = user_agent.parse::().map_err(|_| { + HttpClientCreateError::InvalidUserAgent(user_agent.to_string()) + })?; let mut builder = hyper_util::client::legacy::Builder::new(TokioExecutor::new()); @@ -1028,7 +996,7 @@ pub fn create_http_client( let mut proxies = proxy::from_env(); if let Some(proxy) = options.proxy { let mut intercept = proxy::Intercept::all(&proxy.url) - .ok_or_else(|| type_error("invalid proxy url"))?; + .ok_or_else(|| HttpClientCreateError::InvalidProxyUrl)?; if let Some(basic_auth) = &proxy.basic_auth { intercept.set_auth(&basic_auth.username, &basic_auth.password); } @@ -1060,7 +1028,7 @@ pub fn create_http_client( } (true, true) => {} (false, false) => { - return Err(type_error("Either `http1` or `http2` needs to be true")) + return Err(HttpClientCreateError::HttpVersionSelectionInvalid) } } @@ -1076,10 +1044,8 @@ pub fn create_http_client( #[op2] #[serde] -pub fn op_utf8_to_byte_string( - #[string] input: String, -) -> Result { - Ok(input.into()) +pub fn op_utf8_to_byte_string(#[string] input: String) -> ByteString { + input.into() } #[derive(Clone, Debug)] @@ -1099,7 +1065,7 @@ const STAR_STAR: HeaderValue = HeaderValue::from_static("*/*"); #[derive(Debug)] pub struct ClientSendError { uri: Uri, - source: hyper_util::client::legacy::Error, + pub source: hyper_util::client::legacy::Error, } impl ClientSendError { @@ -1171,12 +1137,14 @@ impl Client { .oneshot(req) .await .map_err(|e| ClientSendError { uri, source: e })?; - Ok(resp.map(|b| b.map_err(|e| anyhow!(e)).boxed())) + Ok(resp.map(|b| b.map_err(|e| deno_core::anyhow::anyhow!(e)).boxed())) } } -pub type ReqBody = http_body_util::combinators::BoxBody; -pub type ResBody = http_body_util::combinators::BoxBody; +pub type ReqBody = + http_body_util::combinators::BoxBody; +pub type ResBody = + http_body_util::combinators::BoxBody; /// Copied from https://github.com/seanmonstar/reqwest/blob/b9d62a0323d96f11672a61a17bf8849baec00275/src/async_impl/request.rs#L572 /// Check the request URL for a "username:password" type authority, and if diff --git a/ext/fetch/proxy.rs b/ext/fetch/proxy.rs index 32a445d8b9..88fc211ecc 100644 --- a/ext/fetch/proxy.rs +++ b/ext/fetch/proxy.rs @@ -23,6 +23,7 @@ use hyper_util::client::legacy::connect::Connected; use hyper_util::client::legacy::connect::Connection; use hyper_util::rt::TokioIo; use ipnet::IpNet; +use percent_encoding::percent_decode_str; use tokio::net::TcpStream; use tokio_rustls::client::TlsStream; use tokio_rustls::TlsConnector; @@ -96,7 +97,7 @@ pub(crate) fn from_env() -> Proxies { if env::var_os("REQUEST_METHOD").is_none() { if let Some(proxy) = parse_env_var("HTTP_PROXY", Filter::Http) { intercepts.push(proxy); - } else if let Some(proxy) = parse_env_var("http_proxy", Filter::Https) { + } else if let Some(proxy) = parse_env_var("http_proxy", Filter::Http) { intercepts.push(proxy); } } @@ -192,10 +193,12 @@ impl Target { if let Some((userinfo, host_port)) = authority.as_str().split_once('@') { let (user, pass) = userinfo.split_once(':')?; + let user = percent_decode_str(user).decode_utf8_lossy(); + let pass = percent_decode_str(pass).decode_utf8_lossy(); if is_socks { socks_auth = Some((user.into(), pass.into())); } else { - http_auth = Some(basic_auth(user, Some(pass))); + http_auth = Some(basic_auth(&user, Some(&pass))); } builder = builder.authority(host_port); } else { @@ -773,6 +776,16 @@ fn test_proxy_parse_from_env() { _ => panic!("bad target"), } + // percent encoded user info + match parse("us%2Fer:p%2Fass@127.0.0.1:6666") { + Target::Http { dst, auth } => { + assert_eq!(dst, "http://127.0.0.1:6666"); + let auth = auth.unwrap(); + assert_eq!(auth.to_str().unwrap(), "Basic dXMvZXI6cC9hc3M="); + } + _ => panic!("bad target"), + } + // socks match parse("socks5://user:pass@127.0.0.1:6666") { Target::Socks { dst, auth } => { diff --git a/ext/ffi/00_ffi.js b/ext/ffi/00_ffi.js index 06caf7c6cc..d3b07dc373 100644 --- a/ext/ffi/00_ffi.js +++ b/ext/ffi/00_ffi.js @@ -250,7 +250,7 @@ class UnsafePointer { } } else { throw new TypeError( - "Expected ArrayBuffer, ArrayBufferView or UnsafeCallbackPrototype", + `Cannot access pointer: expected 'ArrayBuffer', 'ArrayBufferView' or 'UnsafeCallbackPrototype', received ${typeof value}`, ); } if (pointer) { @@ -335,7 +335,9 @@ function getTypeSizeAndAlignment(type, cache = new SafeMap()) { const cached = cache.get(type); if (cached !== undefined) { if (cached === null) { - throw new TypeError("Recursive struct definition"); + throw new TypeError( + "Cannot get pointer size: found recursive struct", + ); } return cached; } @@ -379,7 +381,7 @@ function getTypeSizeAndAlignment(type, cache = new SafeMap()) { case "isize": return [8, 8]; default: - throw new TypeError(`Unsupported type: ${type}`); + throw new TypeError(`Cannot get pointer size, unsupported type: ${type}`); } } @@ -395,7 +397,7 @@ class UnsafeCallback { constructor(definition, callback) { if (definition.nonblocking) { throw new TypeError( - "Invalid UnsafeCallback, cannot be nonblocking", + "Cannot construct UnsafeCallback: cannot be nonblocking", ); } const { 0: rid, 1: pointer } = op_ffi_unsafe_callback_create( @@ -467,7 +469,7 @@ class DynamicLibrary { const type = symbols[symbol].type; if (type === "void") { throw new TypeError( - "Foreign symbol of type 'void' is not supported.", + "Foreign symbol of type 'void' is not supported", ); } @@ -482,10 +484,11 @@ class DynamicLibrary { this.symbols, symbol, { + __proto__: null, configurable: false, enumerable: true, - value, writable: false, + value, }, ); continue; @@ -502,8 +505,10 @@ class DynamicLibrary { this.symbols, symbol, { + __proto__: null, configurable: false, enumerable: true, + writable: false, value: (...parameters) => { if (isStructResult) { const buffer = new Uint8Array(structSize); @@ -525,7 +530,6 @@ class DynamicLibrary { ); } }, - writable: false, }, ); } diff --git a/ext/ffi/Cargo.toml b/ext/ffi/Cargo.toml index 25e08a74e3..405030df29 100644 --- a/ext/ffi/Cargo.toml +++ b/ext/ffi/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_ffi" -version = "0.151.0" +version = "0.161.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,9 +21,12 @@ dynasmrt = "1.2.3" libffi = "=3.2.0" libffi-sys = "=2.3.0" log.workspace = true +num-bigint.workspace = true serde.workspace = true serde-value = "0.7" serde_json = "1.0" +thiserror.workspace = true +tokio.workspace = true [target.'cfg(windows)'.dependencies] winapi = { workspace = true, features = ["errhandlingapi", "minwindef", "ntdef", "winbase", "winnt"] } diff --git a/ext/ffi/call.rs b/ext/ffi/call.rs index 726f17fad0..ef61dc383e 100644 --- a/ext/ffi/call.rs +++ b/ext/ffi/call.rs @@ -1,30 +1,42 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::callback::PtrSymbol; -use crate::check_unstable; use crate::dlfcn::DynamicLibraryResource; use crate::ir::*; use crate::symbol::NativeType; use crate::symbol::Symbol; use crate::FfiPermissions; use crate::ForeignFunction; -use deno_core::anyhow::anyhow; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::serde_json::Value; +use deno_core::serde_v8::BigInt as V8BigInt; use deno_core::serde_v8::ExternalPointer; use deno_core::unsync::spawn_blocking; use deno_core::v8; use deno_core::OpState; use deno_core::ResourceId; use libffi::middle::Arg; +use num_bigint::BigInt; use serde::Serialize; use std::cell::RefCell; use std::ffi::c_void; use std::future::Future; use std::rc::Rc; +#[derive(Debug, thiserror::Error)] +pub enum CallError { + #[error(transparent)] + IR(#[from] IRError), + #[error("Nonblocking FFI call failed: {0}")] + NonblockingCallFailure(#[source] tokio::task::JoinError), + #[error("Invalid FFI symbol name: '{0}'")] + InvalidSymbol(String), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + Callback(#[from] super::CallbackError), +} + // SAFETY: Makes an FFI call unsafe fn ffi_call_rtype_struct( cif: &libffi::middle::Cif, @@ -46,7 +58,7 @@ pub(crate) fn ffi_call_sync<'scope>( args: v8::FunctionCallbackArguments, symbol: &Symbol, out_buffer: Option, -) -> Result +) -> Result where 'scope: 'scope, { @@ -192,6 +204,7 @@ where #[serde(untagged)] pub enum FfiValue { Value(Value), + BigInt(V8BigInt), External(ExternalPointer), } @@ -202,7 +215,7 @@ fn ffi_call( parameter_types: &[NativeType], result_type: NativeType, out_buffer: Option, -) -> Result { +) -> FfiValue { let call_args: Vec = call_args .iter() .enumerate() @@ -215,7 +228,7 @@ fn ffi_call( // SAFETY: types in the `Cif` match the actual calling convention and // types of symbol. unsafe { - Ok(match result_type { + match result_type { NativeType::Void => { cif.call::<()>(fun_ptr, &call_args); FfiValue::Value(Value::from(())) @@ -241,18 +254,18 @@ fn ffi_call( NativeType::I32 => { FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) } - NativeType::U64 => { - FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) - } - NativeType::I64 => { - FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) - } - NativeType::USize => { - FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) - } - NativeType::ISize => { - FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) - } + NativeType::U64 => FfiValue::BigInt(V8BigInt::from(BigInt::from( + cif.call::(fun_ptr, &call_args), + ))), + NativeType::I64 => FfiValue::BigInt(V8BigInt::from(BigInt::from( + cif.call::(fun_ptr, &call_args), + ))), + NativeType::USize => FfiValue::BigInt(V8BigInt::from(BigInt::from( + cif.call::(fun_ptr, &call_args), + ))), + NativeType::ISize => FfiValue::BigInt(V8BigInt::from(BigInt::from( + cif.call::(fun_ptr, &call_args), + ))), NativeType::F32 => { FfiValue::Value(Value::from(cif.call::(fun_ptr, &call_args))) } @@ -268,7 +281,7 @@ fn ffi_call( ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0); FfiValue::Value(Value::Null) } - }) + } } } @@ -281,15 +294,16 @@ pub fn op_ffi_call_ptr_nonblocking( #[serde] def: ForeignFunction, parameters: v8::Local, out_buffer: Option>, -) -> Result>, AnyError> +) -> Result>, CallError> where FP: FfiPermissions + 'static, { - check_unstable(&state.borrow(), "Deno.UnsafeFnPointer#call"); { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(CallError::Permission)?; }; let symbol = PtrSymbol::new(pointer, &def)?; @@ -311,7 +325,7 @@ where Ok(async move { let result = join_handle .await - .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??; + .map_err(CallError::NonblockingCallFailure)?; // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. Ok(result) }) @@ -327,14 +341,17 @@ pub fn op_ffi_call_nonblocking( #[string] symbol: String, parameters: v8::Local, out_buffer: Option>, -) -> Result>, AnyError> { +) -> Result>, CallError> { let symbol = { let state = state.borrow(); - let resource = state.resource_table.get::(rid)?; + let resource = state + .resource_table + .get::(rid) + .map_err(CallError::Permission)?; let symbols = &resource.symbols; *symbols .get(&symbol) - .ok_or_else(|| type_error("Invalid FFI symbol name"))? + .ok_or_else(|| CallError::InvalidSymbol(symbol))? .clone() }; @@ -362,7 +379,7 @@ pub fn op_ffi_call_nonblocking( Ok(async move { let result = join_handle .await - .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??; + .map_err(CallError::NonblockingCallFailure)?; // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. Ok(result) }) @@ -377,15 +394,16 @@ pub fn op_ffi_call_ptr( #[serde] def: ForeignFunction, parameters: v8::Local, out_buffer: Option>, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(&state.borrow(), "Deno.UnsafeFnPointer#call"); { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(CallError::Permission)?; }; let symbol = PtrSymbol::new(pointer, &def)?; @@ -400,7 +418,7 @@ where &def.parameters, def.result.clone(), out_buffer_ptr, - )?; + ); // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. Ok(result) } diff --git a/ext/ffi/callback.rs b/ext/ffi/callback.rs index 1ddb1fff51..f33e0413a3 100644 --- a/ext/ffi/callback.rs +++ b/ext/ffi/callback.rs @@ -1,10 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::check_unstable; use crate::symbol::NativeType; use crate::FfiPermissions; use crate::ForeignFunction; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::v8; use deno_core::v8::TryCatch; @@ -35,6 +33,16 @@ thread_local! { static LOCAL_THREAD_ID: RefCell = const { RefCell::new(0) }; } +#[derive(Debug, thiserror::Error)] +pub enum CallbackError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + #[derive(Clone)] pub struct PtrSymbol { pub cif: libffi::middle::Cif, @@ -45,7 +53,7 @@ impl PtrSymbol { pub fn new( fn_ptr: *mut c_void, def: &ForeignFunction, - ) -> Result { + ) -> Result { let ptr = libffi::middle::CodePtr::from_ptr(fn_ptr as _); let cif = libffi::middle::Cif::new( def @@ -53,8 +61,13 @@ impl PtrSymbol { .clone() .into_iter() .map(libffi::middle::Type::try_from) - .collect::, _>>()?, - def.result.clone().try_into()?, + .collect::, _>>() + .map_err(CallbackError::Other)?, + def + .result + .clone() + .try_into() + .map_err(CallbackError::Other)?, ); Ok(Self { cif, ptr }) @@ -174,7 +187,7 @@ unsafe extern "C" fn deno_ffi_callback( let tc_scope = &mut TryCatch::new(scope); args.run(tc_scope); if tc_scope.exception().is_some() { - log::error!("Illegal unhandled exception in nonblocking callback."); + log::error!("Illegal unhandled exception in nonblocking callback"); } }); } @@ -523,10 +536,12 @@ unsafe fn do_ffi_callback( pub fn op_ffi_unsafe_callback_ref( state: Rc>, #[smi] rid: ResourceId, -) -> Result>, AnyError> { +) -> Result, CallbackError> { let state = state.borrow(); - let callback_resource = - state.resource_table.get::(rid)?; + let callback_resource = state + .resource_table + .get::(rid) + .map_err(CallbackError::Resource)?; Ok(async move { let info: &mut CallbackInfo = @@ -537,7 +552,6 @@ pub fn op_ffi_unsafe_callback_ref( .into_future() .or_cancel(callback_resource.cancel.clone()) .await; - Ok(()) }) } @@ -553,13 +567,14 @@ pub fn op_ffi_unsafe_callback_create( scope: &mut v8::HandleScope<'scope>, #[serde] args: RegisterCallbackArgs, cb: v8::Local, -) -> Result, AnyError> +) -> Result, CallbackError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafeCallback"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(CallbackError::Permission)?; let thread_id: u32 = LOCAL_THREAD_ID.with(|s| { let value = *s.borrow(); @@ -595,8 +610,10 @@ where .parameters .into_iter() .map(libffi::middle::Type::try_from) - .collect::, _>>()?, - libffi::middle::Type::try_from(args.result)?, + .collect::, _>>() + .map_err(CallbackError::Other)?, + libffi::middle::Type::try_from(args.result) + .map_err(CallbackError::Other)?, ); // SAFETY: CallbackInfo is leaked, is not null and stays valid as long as the callback exists. @@ -621,19 +638,21 @@ where Ok(array_value) } -#[op2] +#[op2(fast)] pub fn op_ffi_unsafe_callback_close( state: &mut OpState, scope: &mut v8::HandleScope, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { +) -> Result<(), CallbackError> { // SAFETY: This drops the closure and the callback info associated with it. // Any retained function pointers to the closure become dangling pointers. // It is up to the user to know that it is safe to call the `close()` on the // UnsafeCallback instance. unsafe { - let callback_resource = - state.resource_table.take::(rid)?; + let callback_resource = state + .resource_table + .take::(rid) + .map_err(CallbackError::Resource)?; let info = Box::from_raw(callback_resource.info); let _ = v8::Global::from_raw(scope, info.callback); let _ = v8::Global::from_raw(scope, info.context); diff --git a/ext/ffi/dlfcn.rs b/ext/ffi/dlfcn.rs index 261a62cd30..53bdcbc5cc 100644 --- a/ext/ffi/dlfcn.rs +++ b/ext/ffi/dlfcn.rs @@ -1,14 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::check_unstable; use crate::ir::out_buffer_as_ptr; use crate::symbol::NativeType; use crate::symbol::Symbol; use crate::turbocall; use crate::turbocall::Turbocall; use crate::FfiPermissions; -use deno_core::error::generic_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::v8; use deno_core::GarbageCollected; @@ -20,9 +17,24 @@ use serde_value::ValueDeserializer; use std::borrow::Cow; use std::collections::HashMap; use std::ffi::c_void; -use std::path::PathBuf; use std::rc::Rc; +#[derive(Debug, thiserror::Error)] +pub enum DlfcnError { + #[error("Failed to register symbol {symbol}: {error}")] + RegisterSymbol { + symbol: String, + #[source] + error: dlopen2::Error, + }, + #[error(transparent)] + Dlopen(#[from] dlopen2::Error), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + pub struct DynamicLibraryResource { lib: Library, pub symbols: HashMap>, @@ -39,7 +51,7 @@ impl Resource for DynamicLibraryResource { } impl DynamicLibraryResource { - pub fn get_static(&self, symbol: String) -> Result<*mut c_void, AnyError> { + pub fn get_static(&self, symbol: String) -> Result<*mut c_void, DlfcnError> { // By default, Err returned by this function does not tell // which symbol wasn't exported. So we'll modify the error // message to include the name of symbol. @@ -47,9 +59,7 @@ impl DynamicLibraryResource { // SAFETY: The obtained T symbol is the size of a pointer. match unsafe { self.lib.symbol::<*mut c_void>(&symbol) } { Ok(value) => Ok(Ok(value)), - Err(err) => Err(generic_error(format!( - "Failed to register symbol {symbol}: {err}" - ))), + Err(error) => Err(DlfcnError::RegisterSymbol { symbol, error }), }? } } @@ -118,20 +128,19 @@ pub fn op_ffi_load<'scope, FP>( scope: &mut v8::HandleScope<'scope>, state: &mut OpState, #[serde] args: FfiLoadArgs, -) -> Result, AnyError> +) -> Result, DlfcnError> where FP: FfiPermissions + 'static, { - let path = args.path; - - check_unstable(state, "Deno.dlopen"); let permissions = state.borrow_mut::(); - permissions.check_partial(Some(&PathBuf::from(&path)))?; + let path = permissions + .check_partial_with_path(&args.path) + .map_err(DlfcnError::Permission)?; let lib = Library::open(&path).map_err(|e| { dlopen2::Error::OpeningLibraryError(std::io::Error::new( std::io::ErrorKind::Other, - format_error(e, path), + format_error(e, &path), )) })?; let mut resource = DynamicLibraryResource { @@ -157,15 +166,16 @@ where // SAFETY: The obtained T symbol is the size of a pointer. match unsafe { resource.lib.symbol::<*const c_void>(symbol) } { Ok(value) => Ok(value), - Err(err) => if foreign_fn.optional { + Err(error) => if foreign_fn.optional { let null: v8::Local = v8::null(scope).into(); let func_key = v8::String::new(scope, &symbol_key).unwrap(); obj.set(scope, func_key.into(), null); break 'register_symbol; } else { - Err(generic_error(format!( - "Failed to register symbol {symbol}: {err}" - ))) + Err(DlfcnError::RegisterSymbol { + symbol: symbol.to_owned(), + error, + }) }, }?; @@ -176,8 +186,13 @@ where .clone() .into_iter() .map(libffi::middle::Type::try_from) - .collect::, _>>()?, - foreign_fn.result.clone().try_into()?, + .collect::, _>>() + .map_err(DlfcnError::Other)?, + foreign_fn + .result + .clone() + .try_into() + .map_err(DlfcnError::Other)?, ); let func_key = v8::String::new(scope, &symbol_key).unwrap(); @@ -292,7 +307,10 @@ fn sync_fn_impl<'s>( // `path` is only used on Windows. #[allow(unused_variables)] -pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String { +pub(crate) fn format_error( + e: dlopen2::Error, + path: &std::path::Path, +) -> String { match e { #[cfg(target_os = "windows")] // This calls FormatMessageW with library path @@ -302,7 +320,6 @@ pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String { // // https://github.com/denoland/deno/issues/11632 dlopen2::Error::OpeningLibraryError(e) => { - use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; use winapi::shared::minwindef::DWORD; use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER; @@ -326,7 +343,8 @@ pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String { let mut buf = vec![0; 500]; - let path = OsStr::new(&path) + let path = path + .as_os_str() .encode_wide() .chain(Some(0)) .collect::>(); @@ -386,7 +404,7 @@ mod tests { std::io::Error::from_raw_os_error(0x000000C1), ); assert_eq!( - format_error(err, "foo.dll".to_string()), + format_error(err, &std::path::PathBuf::from("foo.dll")), "foo.dll is not a valid Win32 application.\r\n".to_string(), ); } diff --git a/ext/ffi/ir.rs b/ext/ffi/ir.rs index ebf64945b4..2e80842166 100644 --- a/ext/ffi/ir.rs +++ b/ext/ffi/ir.rs @@ -1,13 +1,55 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::symbol::NativeType; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::v8; use libffi::middle::Arg; use std::ffi::c_void; use std::ptr; +#[derive(Debug, thiserror::Error)] +pub enum IRError { + #[error("Invalid FFI u8 type, expected boolean")] + InvalidU8ExpectedBoolean, + #[error("Invalid FFI u8 type, expected unsigned integer")] + InvalidU8ExpectedUnsignedInteger, + #[error("Invalid FFI i8 type, expected integer")] + InvalidI8, + #[error("Invalid FFI u16 type, expected unsigned integer")] + InvalidU16, + #[error("Invalid FFI i16 type, expected integer")] + InvalidI16, + #[error("Invalid FFI u32 type, expected unsigned integer")] + InvalidU32, + #[error("Invalid FFI i32 type, expected integer")] + InvalidI32, + #[error("Invalid FFI u64 type, expected unsigned integer")] + InvalidU64, + #[error("Invalid FFI i64 type, expected integer")] + InvalidI64, + #[error("Invalid FFI usize type, expected unsigned integer")] + InvalidUsize, + #[error("Invalid FFI isize type, expected integer")] + InvalidIsize, + #[error("Invalid FFI f32 type, expected number")] + InvalidF32, + #[error("Invalid FFI f64 type, expected number")] + InvalidF64, + #[error("Invalid FFI pointer type, expected null, or External")] + InvalidPointerType, + #[error( + "Invalid FFI buffer type, expected null, ArrayBuffer, or ArrayBufferView" + )] + InvalidBufferType, + #[error("Invalid FFI ArrayBufferView, expected data in the buffer")] + InvalidArrayBufferView, + #[error("Invalid FFI ArrayBuffer, expected data in buffer")] + InvalidArrayBuffer, + #[error("Invalid FFI struct type, expected ArrayBuffer, or ArrayBufferView")] + InvalidStructType, + #[error("Invalid FFI function type, expected null, or External")] + InvalidFunctionType, +} + pub struct OutBuffer(pub *mut u8); // SAFETY: OutBuffer is allocated by us in 00_ffi.js and is guaranteed to be @@ -126,9 +168,9 @@ unsafe impl Send for NativeValue {} #[inline] pub fn ffi_parse_bool_arg( arg: v8::Local, -) -> Result { +) -> Result { let bool_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI u8 type, expected boolean"))? + .map_err(|_| IRError::InvalidU8ExpectedBoolean)? .is_true(); Ok(NativeValue { bool_value }) } @@ -136,9 +178,9 @@ pub fn ffi_parse_bool_arg( #[inline] pub fn ffi_parse_u8_arg( arg: v8::Local, -) -> Result { +) -> Result { let u8_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI u8 type, expected unsigned integer"))? + .map_err(|_| IRError::InvalidU8ExpectedUnsignedInteger)? .value() as u8; Ok(NativeValue { u8_value }) } @@ -146,9 +188,9 @@ pub fn ffi_parse_u8_arg( #[inline] pub fn ffi_parse_i8_arg( arg: v8::Local, -) -> Result { +) -> Result { let i8_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI i8 type, expected integer"))? + .map_err(|_| IRError::InvalidI8)? .value() as i8; Ok(NativeValue { i8_value }) } @@ -156,9 +198,9 @@ pub fn ffi_parse_i8_arg( #[inline] pub fn ffi_parse_u16_arg( arg: v8::Local, -) -> Result { +) -> Result { let u16_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI u16 type, expected unsigned integer"))? + .map_err(|_| IRError::InvalidU16)? .value() as u16; Ok(NativeValue { u16_value }) } @@ -166,9 +208,9 @@ pub fn ffi_parse_u16_arg( #[inline] pub fn ffi_parse_i16_arg( arg: v8::Local, -) -> Result { +) -> Result { let i16_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI i16 type, expected integer"))? + .map_err(|_| IRError::InvalidI16)? .value() as i16; Ok(NativeValue { i16_value }) } @@ -176,9 +218,9 @@ pub fn ffi_parse_i16_arg( #[inline] pub fn ffi_parse_u32_arg( arg: v8::Local, -) -> Result { +) -> Result { let u32_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI u32 type, expected unsigned integer"))? + .map_err(|_| IRError::InvalidU32)? .value(); Ok(NativeValue { u32_value }) } @@ -186,9 +228,9 @@ pub fn ffi_parse_u32_arg( #[inline] pub fn ffi_parse_i32_arg( arg: v8::Local, -) -> Result { +) -> Result { let i32_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI i32 type, expected integer"))? + .map_err(|_| IRError::InvalidI32)? .value(); Ok(NativeValue { i32_value }) } @@ -197,7 +239,7 @@ pub fn ffi_parse_i32_arg( pub fn ffi_parse_u64_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. BigInt: Uncommon and not supported by Fast API, so optimise slow call for this case. // 2. Number: Common, supported by Fast API, so let that be the optimal case. @@ -207,9 +249,7 @@ pub fn ffi_parse_u64_arg( } else if let Ok(value) = v8::Local::::try_from(arg) { value.integer_value(scope).unwrap() as u64 } else { - return Err(type_error( - "Invalid FFI u64 type, expected unsigned integer", - )); + return Err(IRError::InvalidU64); }; Ok(NativeValue { u64_value }) } @@ -218,7 +258,7 @@ pub fn ffi_parse_u64_arg( pub fn ffi_parse_i64_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. BigInt: Uncommon and not supported by Fast API, so optimise slow call for this case. // 2. Number: Common, supported by Fast API, so let that be the optimal case. @@ -228,7 +268,7 @@ pub fn ffi_parse_i64_arg( } else if let Ok(value) = v8::Local::::try_from(arg) { value.integer_value(scope).unwrap() } else { - return Err(type_error("Invalid FFI i64 type, expected integer")); + return Err(IRError::InvalidI64); }; Ok(NativeValue { i64_value }) } @@ -237,7 +277,7 @@ pub fn ffi_parse_i64_arg( pub fn ffi_parse_usize_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. BigInt: Uncommon and not supported by Fast API, so optimise slow call for this case. // 2. Number: Common, supported by Fast API, so let that be the optimal case. @@ -247,7 +287,7 @@ pub fn ffi_parse_usize_arg( } else if let Ok(value) = v8::Local::::try_from(arg) { value.integer_value(scope).unwrap() as usize } else { - return Err(type_error("Invalid FFI usize type, expected integer")); + return Err(IRError::InvalidUsize); }; Ok(NativeValue { usize_value }) } @@ -256,7 +296,7 @@ pub fn ffi_parse_usize_arg( pub fn ffi_parse_isize_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. BigInt: Uncommon and not supported by Fast API, so optimise slow call for this case. // 2. Number: Common, supported by Fast API, so let that be the optimal case. @@ -266,7 +306,7 @@ pub fn ffi_parse_isize_arg( } else if let Ok(value) = v8::Local::::try_from(arg) { value.integer_value(scope).unwrap() as isize } else { - return Err(type_error("Invalid FFI isize type, expected integer")); + return Err(IRError::InvalidIsize); }; Ok(NativeValue { isize_value }) } @@ -274,9 +314,9 @@ pub fn ffi_parse_isize_arg( #[inline] pub fn ffi_parse_f32_arg( arg: v8::Local, -) -> Result { +) -> Result { let f32_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI f32 type, expected number"))? + .map_err(|_| IRError::InvalidF32)? .value() as f32; Ok(NativeValue { f32_value }) } @@ -284,9 +324,9 @@ pub fn ffi_parse_f32_arg( #[inline] pub fn ffi_parse_f64_arg( arg: v8::Local, -) -> Result { +) -> Result { let f64_value = v8::Local::::try_from(arg) - .map_err(|_| type_error("Invalid FFI f64 type, expected number"))? + .map_err(|_| IRError::InvalidF64)? .value(); Ok(NativeValue { f64_value }) } @@ -295,15 +335,13 @@ pub fn ffi_parse_f64_arg( pub fn ffi_parse_pointer_arg( _scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { let pointer = if let Ok(value) = v8::Local::::try_from(arg) { value.value() } else if arg.is_null() { ptr::null_mut() } else { - return Err(type_error( - "Invalid FFI pointer type, expected null, or External", - )); + return Err(IRError::InvalidPointerType); }; Ok(NativeValue { pointer }) } @@ -312,7 +350,7 @@ pub fn ffi_parse_pointer_arg( pub fn ffi_parse_buffer_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. ArrayBuffer: Fairly common and not supported by Fast API, optimise this case. // 2. ArrayBufferView: Common and supported by Fast API @@ -328,9 +366,7 @@ pub fn ffi_parse_buffer_arg( let byte_offset = value.byte_offset(); let pointer = value .buffer(scope) - .ok_or_else(|| { - type_error("Invalid FFI ArrayBufferView, expected data in the buffer") - })? + .ok_or(IRError::InvalidArrayBufferView)? .data(); if let Some(non_null) = pointer { // SAFETY: Pointer is non-null, and V8 guarantees that the byte_offset @@ -342,9 +378,7 @@ pub fn ffi_parse_buffer_arg( } else if arg.is_null() { ptr::null_mut() } else { - return Err(type_error( - "Invalid FFI buffer type, expected null, ArrayBuffer, or ArrayBufferView", - )); + return Err(IRError::InvalidBufferType); }; Ok(NativeValue { pointer }) } @@ -353,7 +387,7 @@ pub fn ffi_parse_buffer_arg( pub fn ffi_parse_struct_arg( scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { // Order of checking: // 1. ArrayBuffer: Fairly common and not supported by Fast API, optimise this case. // 2. ArrayBufferView: Common and supported by Fast API @@ -362,31 +396,23 @@ pub fn ffi_parse_struct_arg( if let Some(non_null) = value.data() { non_null.as_ptr() } else { - return Err(type_error( - "Invalid FFI ArrayBuffer, expected data in buffer", - )); + return Err(IRError::InvalidArrayBuffer); } } else if let Ok(value) = v8::Local::::try_from(arg) { let byte_offset = value.byte_offset(); let pointer = value .buffer(scope) - .ok_or_else(|| { - type_error("Invalid FFI ArrayBufferView, expected data in the buffer") - })? + .ok_or(IRError::InvalidArrayBufferView)? .data(); if let Some(non_null) = pointer { // SAFETY: Pointer is non-null, and V8 guarantees that the byte_offset // is within the buffer backing store. unsafe { non_null.as_ptr().add(byte_offset) } } else { - return Err(type_error( - "Invalid FFI ArrayBufferView, expected data in buffer", - )); + return Err(IRError::InvalidArrayBufferView); } } else { - return Err(type_error( - "Invalid FFI struct type, expected ArrayBuffer, or ArrayBufferView", - )); + return Err(IRError::InvalidStructType); }; Ok(NativeValue { pointer }) } @@ -395,15 +421,13 @@ pub fn ffi_parse_struct_arg( pub fn ffi_parse_function_arg( _scope: &mut v8::HandleScope, arg: v8::Local, -) -> Result { +) -> Result { let pointer = if let Ok(value) = v8::Local::::try_from(arg) { value.value() } else if arg.is_null() { ptr::null_mut() } else { - return Err(type_error( - "Invalid FFI function type, expected null, or External", - )); + return Err(IRError::InvalidFunctionType); }; Ok(NativeValue { pointer }) } @@ -412,7 +436,7 @@ pub fn ffi_parse_args<'scope>( scope: &mut v8::HandleScope<'scope>, args: v8::Local, parameter_types: &[NativeType], -) -> Result, AnyError> +) -> Result, IRError> where 'scope: 'scope, { diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index 26b06d98fb..237f8c3b05 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -1,12 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; -use deno_core::OpState; use std::mem::size_of; use std::os::raw::c_char; use std::os::raw::c_short; -use std::path::Path; +use std::path::PathBuf; mod call; mod callback; @@ -30,6 +29,13 @@ use repr::*; use symbol::NativeType; use symbol::Symbol; +pub use call::CallError; +pub use callback::CallbackError; +pub use dlfcn::DlfcnError; +pub use ir::IRError; +pub use r#static::StaticError; +pub use repr::ReprError; + #[cfg(not(target_pointer_width = "64"))] compile_error!("platform not supported"); @@ -41,22 +47,29 @@ const _: () = { pub const UNSTABLE_FEATURE_NAME: &str = "ffi"; -fn check_unstable(state: &OpState, api_name: &str) { - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` - state - .feature_checker - .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, api_name) -} - pub trait FfiPermissions { - fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError>; + fn check_partial_no_path(&mut self) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_partial_with_path( + &mut self, + path: &str, + ) -> Result; } impl FfiPermissions for deno_permissions::PermissionsContainer { #[inline(always)] - fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> { - deno_permissions::PermissionsContainer::check_ffi_partial(self, path) + fn check_partial_no_path(&mut self) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_ffi_partial_no_path(self) + } + + #[inline(always)] + fn check_partial_with_path( + &mut self, + path: &str, + ) -> Result { + deno_permissions::PermissionsContainer::check_ffi_partial_with_path( + self, path, + ) } } diff --git a/ext/ffi/repr.rs b/ext/ffi/repr.rs index c3656f0fec..2f04f4feb4 100644 --- a/ext/ffi/repr.rs +++ b/ext/ffi/repr.rs @@ -1,10 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::check_unstable; use crate::FfiPermissions; -use deno_core::error::range_error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::v8; use deno_core::OpState; @@ -13,17 +9,58 @@ use std::ffi::c_void; use std::ffi::CStr; use std::ptr; +#[derive(Debug, thiserror::Error)] +pub enum ReprError { + #[error("Invalid pointer to offset, pointer is null")] + InvalidOffset, + #[error("Invalid ArrayBuffer pointer, pointer is null")] + InvalidArrayBuffer, + #[error("Destination length is smaller than source length")] + DestinationLengthTooShort, + #[error("Invalid CString pointer, pointer is null")] + InvalidCString, + #[error("Invalid CString pointer, string exceeds max length")] + CStringTooLong, + #[error("Invalid bool pointer, pointer is null")] + InvalidBool, + #[error("Invalid u8 pointer, pointer is null")] + InvalidU8, + #[error("Invalid i8 pointer, pointer is null")] + InvalidI8, + #[error("Invalid u16 pointer, pointer is null")] + InvalidU16, + #[error("Invalid i16 pointer, pointer is null")] + InvalidI16, + #[error("Invalid u32 pointer, pointer is null")] + InvalidU32, + #[error("Invalid i32 pointer, pointer is null")] + InvalidI32, + #[error("Invalid u64 pointer, pointer is null")] + InvalidU64, + #[error("Invalid i64 pointer, pointer is null")] + InvalidI64, + #[error("Invalid f32 pointer, pointer is null")] + InvalidF32, + #[error("Invalid f64 pointer, pointer is null")] + InvalidF64, + #[error("Invalid pointer pointer, pointer is null")] + InvalidPointer, + #[error(transparent)] + Permission(deno_core::error::AnyError), +} + #[op2(fast)] pub fn op_ffi_ptr_create( state: &mut OpState, #[bigint] ptr_number: usize, -) -> Result<*mut c_void, AnyError> +) -> Result<*mut c_void, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#create"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; Ok(ptr_number as *mut c_void) } @@ -33,13 +70,14 @@ pub fn op_ffi_ptr_equals( state: &mut OpState, a: *const c_void, b: *const c_void, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#equals"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; Ok(a == b) } @@ -48,13 +86,14 @@ where pub fn op_ffi_ptr_of( state: &mut OpState, #[anybuffer] buf: *const u8, -) -> Result<*mut c_void, AnyError> +) -> Result<*mut c_void, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#of"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; Ok(buf as *mut c_void) } @@ -63,13 +102,14 @@ where pub fn op_ffi_ptr_of_exact( state: &mut OpState, buf: v8::Local, -) -> Result<*mut c_void, AnyError> +) -> Result<*mut c_void, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#of"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; let Some(buf) = buf.get_backing_store() else { return Ok(0 as _); @@ -85,16 +125,17 @@ pub fn op_ffi_ptr_offset( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result<*mut c_void, AnyError> +) -> Result<*mut c_void, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#offset"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid pointer to offset, pointer is null")); + return Err(ReprError::InvalidOffset); } // TODO(mmastrac): Create a RawPointer that can safely do pointer math. @@ -116,13 +157,14 @@ unsafe extern "C" fn noop_deleter_callback( pub fn op_ffi_ptr_value( state: &mut OpState, ptr: *mut c_void, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointer#value"); let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; Ok(ptr as usize) } @@ -134,17 +176,17 @@ pub fn op_ffi_get_buf( ptr: *mut c_void, #[number] offset: isize, #[number] len: usize, -) -> Result, AnyError> +) -> Result, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getArrayBuffer"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid ArrayBuffer pointer, pointer is null")); + return Err(ReprError::InvalidArrayBuffer); } // SAFETY: Trust the user to have provided a real pointer, offset, and a valid matching size to it. Since this is a foreign pointer, we should not do any deletion. @@ -153,7 +195,7 @@ where ptr.offset(offset), len, noop_deleter_callback, - std::ptr::null_mut(), + ptr::null_mut(), ) } .make_shared(); @@ -168,21 +210,19 @@ pub fn op_ffi_buf_copy_into( #[number] offset: isize, #[anybuffer] dst: &mut [u8], #[number] len: usize, -) -> Result<(), AnyError> +) -> Result<(), ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#copyInto"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if src.is_null() { - Err(type_error("Invalid ArrayBuffer pointer, pointer is null")) + Err(ReprError::InvalidArrayBuffer) } else if dst.len() < len { - Err(range_error( - "Destination length is smaller than source length", - )) + Err(ReprError::DestinationLengthTooShort) } else { let src = src as *const c_void; @@ -201,26 +241,24 @@ pub fn op_ffi_cstr_read( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result, AnyError> +) -> Result, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getCString"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid CString pointer, pointer is null")); + return Err(ReprError::InvalidCString); } let cstr = // SAFETY: Pointer and offset are user provided. unsafe { CStr::from_ptr(ptr.offset(offset) as *const c_char) }.to_bytes(); let value = v8::String::new_from_utf8(scope, cstr, v8::NewStringType::Normal) - .ok_or_else(|| { - type_error("Invalid CString pointer, string exceeds max length") - })?; + .ok_or_else(|| ReprError::CStringTooLong)?; Ok(value) } @@ -229,17 +267,17 @@ pub fn op_ffi_read_bool( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getBool"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid bool pointer, pointer is null")); + return Err(ReprError::InvalidBool); } // SAFETY: ptr and offset are user provided. @@ -251,17 +289,17 @@ pub fn op_ffi_read_u8( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getUint8"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid u8 pointer, pointer is null")); + return Err(ReprError::InvalidU8); } // SAFETY: ptr and offset are user provided. @@ -275,17 +313,17 @@ pub fn op_ffi_read_i8( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getInt8"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid i8 pointer, pointer is null")); + return Err(ReprError::InvalidI8); } // SAFETY: ptr and offset are user provided. @@ -299,17 +337,17 @@ pub fn op_ffi_read_u16( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getUint16"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid u16 pointer, pointer is null")); + return Err(ReprError::InvalidU16); } // SAFETY: ptr and offset are user provided. @@ -323,17 +361,17 @@ pub fn op_ffi_read_i16( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getInt16"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid i16 pointer, pointer is null")); + return Err(ReprError::InvalidI16); } // SAFETY: ptr and offset are user provided. @@ -347,17 +385,17 @@ pub fn op_ffi_read_u32( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getUint32"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid u32 pointer, pointer is null")); + return Err(ReprError::InvalidU32); } // SAFETY: ptr and offset are user provided. @@ -369,17 +407,17 @@ pub fn op_ffi_read_i32( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getInt32"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid i32 pointer, pointer is null")); + return Err(ReprError::InvalidI32); } // SAFETY: ptr and offset are user provided. @@ -394,17 +432,17 @@ pub fn op_ffi_read_u64( // Note: The representation of 64-bit integers is function-wide. We cannot // choose to take this parameter as a number while returning a bigint. #[bigint] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getBigUint64"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid u64 pointer, pointer is null")); + return Err(ReprError::InvalidU64); } let value = @@ -422,17 +460,17 @@ pub fn op_ffi_read_i64( // Note: The representation of 64-bit integers is function-wide. We cannot // choose to take this parameter as a number while returning a bigint. #[bigint] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getBigInt64"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid i64 pointer, pointer is null")); + return Err(ReprError::InvalidI64); } let value = @@ -447,17 +485,17 @@ pub fn op_ffi_read_f32( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getFloat32"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid f32 pointer, pointer is null")); + return Err(ReprError::InvalidF32); } // SAFETY: ptr and offset are user provided. @@ -469,17 +507,17 @@ pub fn op_ffi_read_f64( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result +) -> Result where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getFloat64"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid f64 pointer, pointer is null")); + return Err(ReprError::InvalidF64); } // SAFETY: ptr and offset are user provided. @@ -491,17 +529,17 @@ pub fn op_ffi_read_ptr( state: &mut OpState, ptr: *mut c_void, #[number] offset: isize, -) -> Result<*mut c_void, AnyError> +) -> Result<*mut c_void, ReprError> where FP: FfiPermissions + 'static, { - check_unstable(state, "Deno.UnsafePointerView#getPointer"); - let permissions = state.borrow_mut::(); - permissions.check_partial(None)?; + permissions + .check_partial_no_path() + .map_err(ReprError::Permission)?; if ptr.is_null() { - return Err(type_error("Invalid pointer pointer, pointer is null")); + return Err(ReprError::InvalidPointer); } // SAFETY: ptr and offset are user provided. diff --git a/ext/ffi/static.rs b/ext/ffi/static.rs index f08605754b..61b4059336 100644 --- a/ext/ffi/static.rs +++ b/ext/ffi/static.rs @@ -2,14 +2,24 @@ use crate::dlfcn::DynamicLibraryResource; use crate::symbol::NativeType; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::v8; use deno_core::OpState; use deno_core::ResourceId; use std::ptr; +#[derive(Debug, thiserror::Error)] +pub enum StaticError { + #[error(transparent)] + Dlfcn(super::DlfcnError), + #[error("Invalid FFI static type 'void'")] + InvalidTypeVoid, + #[error("Invalid FFI static type 'struct'")] + InvalidTypeStruct, + #[error(transparent)] + Resource(deno_core::error::AnyError), +} + #[op2] pub fn op_ffi_get_static<'scope>( scope: &mut v8::HandleScope<'scope>, @@ -18,24 +28,27 @@ pub fn op_ffi_get_static<'scope>( #[string] name: String, #[serde] static_type: NativeType, optional: bool, -) -> Result, AnyError> { - let resource = state.resource_table.get::(rid)?; +) -> Result, StaticError> { + let resource = state + .resource_table + .get::(rid) + .map_err(StaticError::Resource)?; let data_ptr = match resource.get_static(name) { - Ok(data_ptr) => Ok(data_ptr), + Ok(data_ptr) => data_ptr, Err(err) => { if optional { let null: v8::Local = v8::null(scope).into(); return Ok(null); } else { - Err(err) + return Err(StaticError::Dlfcn(err)); } } - }?; + }; Ok(match static_type { NativeType::Void => { - return Err(type_error("Invalid FFI static type 'void'")); + return Err(StaticError::InvalidTypeVoid); } NativeType::Bool => { // SAFETY: ptr is user provided @@ -132,7 +145,7 @@ pub fn op_ffi_get_static<'scope>( external } NativeType::Struct(_) => { - return Err(type_error("Invalid FFI static type 'struct'")); + return Err(StaticError::InvalidTypeStruct); } }) } diff --git a/ext/fs/30_fs.js b/ext/fs/30_fs.js index 767ed11f4f..c8e19ac758 100644 --- a/ext/fs/30_fs.js +++ b/ext/fs/30_fs.js @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { core, internals, primordials } from "ext:core/mod.js"; +import { core, primordials } from "ext:core/mod.js"; const { isDate, internalRidSymbol, @@ -15,22 +15,18 @@ import { op_fs_copy_file_async, op_fs_copy_file_sync, op_fs_cwd, - op_fs_fdatasync_async, - op_fs_fdatasync_sync, op_fs_file_stat_async, op_fs_file_stat_sync, + op_fs_file_sync_async, + op_fs_file_sync_data_async, + op_fs_file_sync_data_sync, + op_fs_file_sync_sync, + op_fs_file_truncate_async, op_fs_flock_async, - op_fs_flock_async_unstable, op_fs_flock_sync, - op_fs_flock_sync_unstable, - op_fs_fsync_async, - op_fs_fsync_sync, - op_fs_ftruncate_async, op_fs_ftruncate_sync, op_fs_funlock_async, - op_fs_funlock_async_unstable, op_fs_funlock_sync, - op_fs_funlock_sync_unstable, op_fs_futime_async, op_fs_futime_sync, op_fs_link_async, @@ -397,15 +393,6 @@ function parseFileInfo(response) { }; } -function fstatSync(rid) { - op_fs_file_stat_sync(rid, statBuf); - return statStruct(statBuf); -} - -async function fstat(rid) { - return parseFileInfo(await op_fs_file_stat_async(rid)); -} - async function lstat(path) { const res = await op_fs_lstat_async(pathFromURL(path)); return parseFileInfo(res); @@ -433,14 +420,6 @@ function coerceLen(len) { return len; } -function ftruncateSync(rid, len) { - op_fs_ftruncate_sync(rid, coerceLen(len)); -} - -async function ftruncate(rid, len) { - await op_fs_ftruncate_async(rid, coerceLen(len)); -} - function truncateSync(path, len) { op_fs_truncate_sync(path, coerceLen(len)); } @@ -482,32 +461,6 @@ function toUnixTimeFromEpoch(value) { ]; } -function futimeSync( - rid, - atime, - mtime, -) { - const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime); - const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime); - op_fs_futime_sync(rid, atimeSec, atimeNsec, mtimeSec, mtimeNsec); -} - -async function futime( - rid, - atime, - mtime, -) { - const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime); - const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime); - await op_fs_futime_async( - rid, - atimeSec, - atimeNsec, - mtimeSec, - mtimeNsec, - ); -} - function utimeSync( path, atime, @@ -564,54 +517,6 @@ async function symlink( ); } -function fdatasyncSync(rid) { - op_fs_fdatasync_sync(rid); -} - -async function fdatasync(rid) { - await op_fs_fdatasync_async(rid); -} - -function fsyncSync(rid) { - op_fs_fsync_sync(rid); -} - -async function fsync(rid) { - await op_fs_fsync_async(rid); -} - -function flockSync(rid, exclusive) { - op_fs_flock_sync_unstable(rid, exclusive === true); -} - -async function flock(rid, exclusive) { - await op_fs_flock_async_unstable(rid, exclusive === true); -} - -function funlockSync(rid) { - op_fs_funlock_sync_unstable(rid); -} - -async function funlock(rid) { - await op_fs_funlock_async_unstable(rid); -} - -function seekSync( - rid, - offset, - whence, -) { - return op_fs_seek_sync(rid, offset, whence); -} - -function seek( - rid, - offset, - whence, -) { - return op_fs_seek_async(rid, offset, whence); -} - function openSync( path, options, @@ -664,33 +569,18 @@ class FsFile { constructor(rid, symbol) { ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); this.#rid = rid; if (!symbol || symbol !== SymbolFor("Deno.internal.FsFile")) { - internals.warnOnDeprecatedApi( - "new Deno.FsFile()", - new Error().stack, - "Use `Deno.open` or `Deno.openSync` instead.", + throw new TypeError( + "`Deno.FsFile` cannot be constructed, use `Deno.open()` or `Deno.openSync()` instead.", ); - if (internals.future) { - throw new TypeError( - "`Deno.FsFile` cannot be constructed, use `Deno.open()` or `Deno.openSync()` instead.", - ); - } } } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.FsFile.rid", - new Error().stack, - "Use `Deno.FsFile` methods directly instead.", - ); - return this.#rid; - } - write(p) { return write(this.#rid, p); } @@ -700,11 +590,11 @@ class FsFile { } truncate(len) { - return ftruncate(this.#rid, len); + return op_fs_file_truncate_async(this.#rid, coerceLen(len)); } truncateSync(len) { - return ftruncateSync(this.#rid, len); + return op_fs_ftruncate_sync(this.#rid, coerceLen(len)); } read(p) { @@ -716,27 +606,28 @@ class FsFile { } seek(offset, whence) { - return seek(this.#rid, offset, whence); + return op_fs_seek_async(this.#rid, offset, whence); } seekSync(offset, whence) { - return seekSync(this.#rid, offset, whence); + return op_fs_seek_sync(this.#rid, offset, whence); } - stat() { - return fstat(this.#rid); + async stat() { + return parseFileInfo(await op_fs_file_stat_async(this.#rid)); } statSync() { - return fstatSync(this.#rid); + op_fs_file_stat_sync(this.#rid, statBuf); + return statStruct(statBuf); } async syncData() { - await op_fs_fdatasync_async(this.#rid); + await op_fs_file_sync_data_async(this.#rid); } syncDataSync() { - op_fs_fdatasync_sync(this.#rid); + op_fs_file_sync_data_sync(this.#rid); } close() { @@ -758,19 +649,29 @@ class FsFile { } async sync() { - await op_fs_fsync_async(this.#rid); + await op_fs_file_sync_async(this.#rid); } syncSync() { - op_fs_fsync_sync(this.#rid); + op_fs_file_sync_sync(this.#rid); } async utime(atime, mtime) { - await futime(this.#rid, atime, mtime); + const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime); + const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime); + await op_fs_futime_async( + this.#rid, + atimeSec, + atimeNsec, + mtimeSec, + mtimeNsec, + ); } utimeSync(atime, mtime) { - futimeSync(this.#rid, atime, mtime); + const { 0: atimeSec, 1: atimeNsec } = toUnixTimeFromEpoch(atime); + const { 0: mtimeSec, 1: mtimeNsec } = toUnixTimeFromEpoch(mtime); + op_fs_futime_sync(this.#rid, atimeSec, atimeNsec, mtimeSec, mtimeNsec); } isTerminal() { @@ -828,8 +729,6 @@ function checkOpenOptions(options) { } } -const File = FsFile; - function readFileSync(path) { return op_fs_read_file_sync(pathFromURL(path)); } @@ -990,22 +889,7 @@ export { create, createSync, cwd, - fdatasync, - fdatasyncSync, - File, - flock, - flockSync, FsFile, - fstat, - fstatSync, - fsync, - fsyncSync, - ftruncate, - ftruncateSync, - funlock, - funlockSync, - futime, - futimeSync, link, linkSync, lstat, @@ -1032,8 +916,6 @@ export { removeSync, rename, renameSync, - seek, - seekSync, stat, statSync, symlink, diff --git a/ext/fs/Cargo.toml b/ext/fs/Cargo.toml index 2380ae8488..2a1c5bf2c6 100644 --- a/ext/fs/Cargo.toml +++ b/ext/fs/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_fs" -version = "0.74.0" +version = "0.84.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,15 +21,17 @@ async-trait.workspace = true base32.workspace = true deno_core.workspace = true deno_io.workspace = true +deno_path_util.workspace = true deno_permissions.workspace = true filetime.workspace = true libc.workspace = true rand.workspace = true rayon = "1.8.0" serde.workspace = true +thiserror.workspace = true [target.'cfg(unix)'.dependencies] -nix.workspace = true +nix = { workspace = true, features = ["fs", "user"] } [target.'cfg(windows)'.dependencies] winapi = { workspace = true, features = ["winbase"] } diff --git a/ext/fs/in_memory_fs.rs b/ext/fs/in_memory_fs.rs index 027539e849..e29b9d50c6 100644 --- a/ext/fs/in_memory_fs.rs +++ b/ext/fs/in_memory_fs.rs @@ -12,12 +12,12 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; -use deno_core::normalize_path; use deno_core::parking_lot::Mutex; use deno_io::fs::File; use deno_io::fs::FsError; use deno_io::fs::FsResult; use deno_io::fs::FsStat; +use deno_path_util::normalize_path; use crate::interface::AccessCheckCb; use crate::interface::FsDirEntry; @@ -44,7 +44,7 @@ impl InMemoryFs { pub fn setup_text_files(&self, files: Vec<(String, String)>) { for (path, text) in files { let path = PathBuf::from(path); - self.mkdir_sync(path.parent().unwrap(), true, 0).unwrap(); + self.mkdir_sync(path.parent().unwrap(), true, None).unwrap(); self .write_file_sync( &path, @@ -101,7 +101,7 @@ impl FileSystem for InMemoryFs { &self, path: &Path, recursive: bool, - _mode: u32, + _mode: Option, ) -> FsResult<()> { let path = normalize_path(path); @@ -119,7 +119,7 @@ impl FileSystem for InMemoryFs { }, None => { if recursive { - self.mkdir_sync(parent, true, 0)?; + self.mkdir_sync(parent, true, None)?; } else { return Err(FsError::Io(Error::new( ErrorKind::NotFound, @@ -149,7 +149,7 @@ impl FileSystem for InMemoryFs { &self, path: PathBuf, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()> { self.mkdir_sync(&path, recursive, mode) } diff --git a/ext/fs/interface.rs b/ext/fs/interface.rs index af4beb248b..73333b0fd1 100644 --- a/ext/fs/interface.rs +++ b/ext/fs/interface.rs @@ -121,13 +121,17 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync { access_check: Option>, ) -> FsResult>; - fn mkdir_sync(&self, path: &Path, recursive: bool, mode: u32) - -> FsResult<()>; + fn mkdir_sync( + &self, + path: &Path, + recursive: bool, + mode: Option, + ) -> FsResult<()>; async fn mkdir_async( &self, path: PathBuf, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()>; fn chmod_sync(&self, path: &Path, mode: u32) -> FsResult<()>; diff --git a/ext/fs/lib.rs b/ext/fs/lib.rs index 8eb6f27643..cd2baf22a9 100644 --- a/ext/fs/lib.rs +++ b/ext/fs/lib.rs @@ -14,6 +14,8 @@ pub use crate::interface::FileSystemRc; pub use crate::interface::FsDirEntry; pub use crate::interface::FsFileType; pub use crate::interface::OpenOptions; +pub use crate::ops::FsOpsError; +pub use crate::ops::OperationError; pub use crate::std_fs::RealFs; pub use crate::sync::MaybeSend; pub use crate::sync::MaybeSync; @@ -21,10 +23,10 @@ pub use crate::sync::MaybeSync; use crate::ops::*; use deno_core::error::AnyError; -use deno_core::OpState; use deno_io::fs::FsError; use std::borrow::Cow; use std::path::Path; +use std::path::PathBuf; pub trait FsPermissions { fn check_open<'a>( @@ -35,8 +37,18 @@ pub trait FsPermissions { path: &'a Path, api_name: &str, ) -> Result, FsError>; - fn check_read(&mut self, path: &Path, api_name: &str) - -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read( + &mut self, + path: &str, + api_name: &str, + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read_path<'a>( + &mut self, + path: &'a Path, + api_name: &str, + ) -> Result, AnyError>; fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError>; fn check_read_blind( &mut self, @@ -44,16 +56,24 @@ pub trait FsPermissions { display: &str, api_name: &str, ) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] fn check_write( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError>; + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_write_path<'a>( + &mut self, + path: &'a Path, + api_name: &str, + ) -> Result, AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] fn check_write_partial( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError>; + ) -> Result; fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError>; fn check_write_blind( &mut self, @@ -91,31 +111,50 @@ impl FsPermissions for deno_permissions::PermissionsContainer { if resolved { self .check_special_file(path, api_name) - .map_err(FsError::PermissionDenied)?; + .map_err(FsError::NotCapable)?; return Ok(Cow::Borrowed(path)); } // If somehow read or write aren't specified, use read let read = read || !write; + let mut path: Cow<'a, Path> = Cow::Borrowed(path); if read { - FsPermissions::check_read(self, path, api_name) - .map_err(|_| FsError::PermissionDenied("read"))?; + let resolved_path = FsPermissions::check_read_path(self, &path, api_name) + .map_err(|_| FsError::NotCapable("read"))?; + if let Cow::Owned(resolved_path) = resolved_path { + path = Cow::Owned(resolved_path); + } } if write { - FsPermissions::check_write(self, path, api_name) - .map_err(|_| FsError::PermissionDenied("write"))?; + let resolved_path = + FsPermissions::check_write_path(self, &path, api_name) + .map_err(|_| FsError::NotCapable("write"))?; + if let Cow::Owned(resolved_path) = resolved_path { + path = Cow::Owned(resolved_path); + } } - Ok(Cow::Borrowed(path)) + Ok(path) } fn check_read( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_read(self, path, api_name) } + fn check_read_path<'a>( + &mut self, + path: &'a Path, + api_name: &str, + ) -> Result, AnyError> { + deno_permissions::PermissionsContainer::check_read_path( + self, + path, + Some(api_name), + ) + } fn check_read_blind( &mut self, path: &Path, @@ -129,17 +168,27 @@ impl FsPermissions for deno_permissions::PermissionsContainer { fn check_write( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_write(self, path, api_name) } + fn check_write_path<'a>( + &mut self, + path: &'a Path, + api_name: &str, + ) -> Result, AnyError> { + deno_permissions::PermissionsContainer::check_write_path( + self, path, api_name, + ) + } + fn check_write_partial( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_write_partial( self, path, api_name, ) @@ -167,15 +216,6 @@ impl FsPermissions for deno_permissions::PermissionsContainer { pub const UNSTABLE_FEATURE_NAME: &str = "fs"; -/// Helper for checking unstable features. Used for sync ops. -fn check_unstable(state: &OpState, api_name: &str) { - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` - state - .feature_checker - .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, api_name); -} - deno_core::extension!(deno_fs, deps = [ deno_web ], parameters = [P: FsPermissions], @@ -229,22 +269,18 @@ deno_core::extension!(deno_fs, op_fs_seek_sync, op_fs_seek_async, - op_fs_fdatasync_sync, - op_fs_fdatasync_async, - op_fs_fsync_sync, - op_fs_fsync_async, + op_fs_file_sync_data_sync, + op_fs_file_sync_data_async, + op_fs_file_sync_sync, + op_fs_file_sync_async, op_fs_file_stat_sync, op_fs_file_stat_async, - op_fs_flock_sync_unstable, - op_fs_flock_async_unstable, - op_fs_funlock_sync_unstable, - op_fs_funlock_async_unstable, op_fs_flock_async, op_fs_flock_sync, op_fs_funlock_async, op_fs_funlock_sync, op_fs_ftruncate_sync, - op_fs_ftruncate_async, + op_fs_file_truncate_async, op_fs_futime_sync, op_fs_futime_async, diff --git a/ext/fs/ops.rs b/ext/fs/ops.rs index e8a074be50..a3f59da4ea 100644 --- a/ext/fs/ops.rs +++ b/ext/fs/ops.rs @@ -1,16 +1,15 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::cell::RefCell; +use std::error::Error; +use std::fmt::Formatter; use std::io; use std::io::SeekFrom; use std::path::Path; use std::path::PathBuf; +use std::path::StripPrefixError; use std::rc::Rc; -use deno_core::anyhow::bail; -use deno_core::error::custom_error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::CancelFuture; use deno_core::CancelHandle; @@ -26,7 +25,6 @@ use rand::thread_rng; use rand::Rng; use serde::Serialize; -use crate::check_unstable; use crate::interface::AccessCheckFn; use crate::interface::FileSystemRc; use crate::interface::FsDirEntry; @@ -34,6 +32,67 @@ use crate::interface::FsFileType; use crate::FsPermissions; use crate::OpenOptions; +#[derive(Debug, thiserror::Error)] +pub enum FsOpsError { + #[error("{0}")] + Io(#[source] std::io::Error), + #[error("{0}")] + OperationError(#[source] OperationError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("File name or path {0:?} is not valid UTF-8")] + InvalidUtf8(std::ffi::OsString), + #[error("{0}")] + StripPrefix(#[from] StripPrefixError), + #[error("{0}")] + Canceled(#[from] deno_core::Canceled), + #[error("Invalid seek mode: {0}")] + InvalidSeekMode(i32), + #[error("Invalid control character in prefix or suffix: {0:?}")] + InvalidControlCharacter(String), + #[error("Invalid character in prefix or suffix: {0:?}")] + InvalidCharacter(String), + #[cfg(windows)] + #[error("Invalid trailing character in suffix")] + InvalidTrailingCharacter, + #[error("Requires {err} access to {path}, {}", print_not_capable_info(*.standalone, .err))] + NotCapableAccess { + // NotCapable + standalone: bool, + err: &'static str, + path: String, + }, + #[error("permission denied: {0}")] + NotCapable(&'static str), // NotCapable + #[error(transparent)] + Other(deno_core::error::AnyError), +} + +impl From for FsOpsError { + fn from(err: FsError) -> Self { + match err { + FsError::Io(err) => FsOpsError::Io(err), + FsError::FileBusy => { + FsOpsError::Other(deno_core::error::resource_unavailable()) + } + FsError::NotSupported => { + FsOpsError::Other(deno_core::error::not_supported()) + } + FsError::NotCapable(err) => FsOpsError::NotCapable(err), + } + } +} + +fn print_not_capable_info(standalone: bool, err: &'static str) -> String { + if standalone { + format!("specify the required permissions during compilation using `deno compile --allow-{err}`") + } else { + format!("run again with the --allow-{err} flag") + } +} + fn sync_permission_check<'a, P: FsPermissions + 'static>( permissions: &'a mut P, api_name: &'static str, @@ -58,23 +117,21 @@ fn map_permission_error( operation: &'static str, error: FsError, path: &Path, -) -> AnyError { +) -> FsOpsError { match error { - FsError::PermissionDenied(err) => { + FsError::NotCapable(err) => { let path = format!("{path:?}"); let (path, truncated) = if path.len() > 1024 { (&path[0..1024], "...(truncated)") } else { (path.as_str(), "") }; - let msg = if deno_permissions::is_standalone() { - format!( - "Requires {err} access to {path}{truncated}, specify the required permissions during compilation using `deno compile --allow-{err}`") - } else { - format!( - "Requires {err} access to {path}{truncated}, run again with the --allow-{err} flag") - }; - custom_error("PermissionDenied", msg) + + FsOpsError::NotCapableAccess { + standalone: deno_permissions::is_standalone(), + err, + path: format!("{path}{truncated}"), + } } err => Err::<(), _>(err) .context_path(operation, path) @@ -85,7 +142,7 @@ fn map_permission_error( #[op2] #[string] -pub fn op_fs_cwd

(state: &mut OpState) -> Result +pub fn op_fs_cwd

(state: &mut OpState) -> Result where P: FsPermissions + 'static, { @@ -93,7 +150,8 @@ where let path = fs.cwd()?; state .borrow_mut::

() - .check_read_blind(&path, "CWD", "Deno.cwd()")?; + .check_read_blind(&path, "CWD", "Deno.cwd()") + .map_err(FsOpsError::Permission)?; let path_str = path_into_string(path.into_os_string())?; Ok(path_str) } @@ -102,12 +160,14 @@ where pub fn op_fs_chdir

( state: &mut OpState, #[string] directory: &str, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let d = PathBuf::from(&directory); - state.borrow_mut::

().check_read(&d, "Deno.chdir()")?; + let d = state + .borrow_mut::

() + .check_read(directory, "Deno.chdir()") + .map_err(FsOpsError::Permission)?; state .borrow::() .chdir(&d) @@ -118,10 +178,9 @@ where pub fn op_fs_umask( state: &mut OpState, mask: Option, -) -> Result +) -> Result where { - check_unstable(state, "Deno.umask"); state.borrow::().umask(mask).context("umask") } @@ -131,7 +190,7 @@ pub fn op_fs_open_sync

( state: &mut OpState, #[string] path: String, #[serde] options: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -158,7 +217,7 @@ pub async fn op_fs_open_async

( state: Rc>, #[string] path: String, #[serde] options: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -186,20 +245,19 @@ pub fn op_fs_mkdir_sync

( #[string] path: String, recursive: bool, mode: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let mode = mode.unwrap_or(0o777) & 0o777; - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.mkdirSync()")?; + .check_write(&path, "Deno.mkdirSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); - fs.mkdir_sync(&path, recursive, mode) + fs.mkdir_sync(&path, recursive, Some(mode)) .context_path("mkdir", &path)?; Ok(()) @@ -211,21 +269,22 @@ pub async fn op_fs_mkdir_async

( #[string] path: String, recursive: bool, mode: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let mode = mode.unwrap_or(0o777) & 0o777; - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state.borrow_mut::

().check_write(&path, "Deno.mkdir()")?; - state.borrow::().clone() + let path = state + .borrow_mut::

() + .check_write(&path, "Deno.mkdir()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; - fs.mkdir_async(path.clone(), recursive, mode) + fs.mkdir_async(path.clone(), recursive, Some(mode)) .await .context_path("mkdir", &path)?; @@ -237,14 +296,14 @@ pub fn op_fs_chmod_sync

( state: &mut OpState, #[string] path: String, mode: u32, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.chmodSync()")?; + .check_write(&path, "Deno.chmodSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.chmod_sync(&path, mode).context_path("chmod", &path)?; Ok(()) @@ -255,15 +314,17 @@ pub async fn op_fs_chmod_async

( state: Rc>, #[string] path: String, mode: u32, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state.borrow_mut::

().check_write(&path, "Deno.chmod()")?; - state.borrow::().clone() + let path = state + .borrow_mut::

() + .check_write(&path, "Deno.chmod()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; fs.chmod_async(path.clone(), mode) .await @@ -277,14 +338,14 @@ pub fn op_fs_chown_sync

( #[string] path: String, uid: Option, gid: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.chownSync()")?; + .check_write(&path, "Deno.chownSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.chown_sync(&path, uid, gid) .context_path("chown", &path)?; @@ -297,15 +358,17 @@ pub async fn op_fs_chown_async

( #[string] path: String, uid: Option, gid: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state.borrow_mut::

().check_write(&path, "Deno.chown()")?; - state.borrow::().clone() + let path = state + .borrow_mut::

() + .check_write(&path, "Deno.chown()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; fs.chown_async(path.clone(), uid, gid) .await @@ -318,15 +381,14 @@ pub fn op_fs_remove_sync

( state: &mut OpState, #[string] path: &str, recursive: bool, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.removeSync()")?; + .check_write(path, "Deno.removeSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.remove_sync(&path, recursive) @@ -340,25 +402,25 @@ pub async fn op_fs_remove_async

( state: Rc>, #[string] path: String, recursive: bool, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - if recursive { + let path = if recursive { state .borrow_mut::

() - .check_write(&path, "Deno.remove()")?; + .check_write(&path, "Deno.remove()") + .map_err(FsOpsError::Permission)? } else { state .borrow_mut::

() - .check_write_partial(&path, "Deno.remove()")?; - } + .check_write_partial(&path, "Deno.remove()") + .map_err(FsOpsError::Permission)? + }; - state.borrow::().clone() + (state.borrow::().clone(), path) }; fs.remove_async(path.clone(), recursive) @@ -373,16 +435,17 @@ pub fn op_fs_copy_file_sync

( state: &mut OpState, #[string] from: &str, #[string] to: &str, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let from = PathBuf::from(from); - let to = PathBuf::from(to); - let permissions = state.borrow_mut::

(); - permissions.check_read(&from, "Deno.copyFileSync()")?; - permissions.check_write(&to, "Deno.copyFileSync()")?; + let from = permissions + .check_read(from, "Deno.copyFileSync()") + .map_err(FsOpsError::Permission)?; + let to = permissions + .check_write(to, "Deno.copyFileSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.copy_file_sync(&from, &to) @@ -396,19 +459,20 @@ pub async fn op_fs_copy_file_async

( state: Rc>, #[string] from: String, #[string] to: String, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let from = PathBuf::from(from); - let to = PathBuf::from(to); - - let fs = { + let (fs, from, to) = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_read(&from, "Deno.copyFile()")?; - permissions.check_write(&to, "Deno.copyFile()")?; - state.borrow::().clone() + let from = permissions + .check_read(&from, "Deno.copyFile()") + .map_err(FsOpsError::Permission)?; + let to = permissions + .check_write(&to, "Deno.copyFile()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), from, to) }; fs.copy_file_async(from.clone(), to.clone()) @@ -423,14 +487,14 @@ pub fn op_fs_stat_sync

( state: &mut OpState, #[string] path: String, #[buffer] stat_out_buf: &mut [u32], -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.statSync()")?; + .check_read(&path, "Deno.statSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); let stat = fs.stat_sync(&path).context_path("stat", &path)?; let serializable_stat = SerializableStat::from(stat); @@ -443,16 +507,17 @@ where pub async fn op_fs_stat_async

( state: Rc>, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_read(&path, "Deno.stat()")?; - state.borrow::().clone() + let path = permissions + .check_read(&path, "Deno.stat()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; let stat = fs .stat_async(path.clone()) @@ -466,14 +531,14 @@ pub fn op_fs_lstat_sync

( state: &mut OpState, #[string] path: String, #[buffer] stat_out_buf: &mut [u32], -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.lstatSync()")?; + .check_read(&path, "Deno.lstatSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); let stat = fs.lstat_sync(&path).context_path("lstat", &path)?; let serializable_stat = SerializableStat::from(stat); @@ -486,16 +551,17 @@ where pub async fn op_fs_lstat_async

( state: Rc>, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_read(&path, "Deno.lstat()")?; - state.borrow::().clone() + let path = permissions + .check_read(&path, "Deno.lstat()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; let stat = fs .lstat_async(path.clone()) @@ -509,17 +575,19 @@ where pub fn op_fs_realpath_sync

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - let fs = state.borrow::().clone(); let permissions = state.borrow_mut::

(); - permissions.check_read(&path, "Deno.realPathSync()")?; + let path = permissions + .check_read(&path, "Deno.realPathSync()") + .map_err(FsOpsError::Permission)?; if path.is_relative() { - permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?; + permissions + .check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()") + .map_err(FsOpsError::Permission)?; } let resolved_path = @@ -534,22 +602,24 @@ where pub async fn op_fs_realpath_async

( state: Rc>, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs; - { + let (fs, path) = { let mut state = state.borrow_mut(); - fs = state.borrow::().clone(); + let fs = state.borrow::().clone(); let permissions = state.borrow_mut::

(); - permissions.check_read(&path, "Deno.realPath()")?; + let path = permissions + .check_read(&path, "Deno.realPath()") + .map_err(FsOpsError::Permission)?; if path.is_relative() { - permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?; + permissions + .check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()") + .map_err(FsOpsError::Permission)?; } - } + (fs, path) + }; let resolved_path = fs .realpath_async(path.clone()) .await @@ -564,15 +634,14 @@ where pub fn op_fs_read_dir_sync

( state: &mut OpState, #[string] path: String, -) -> Result, AnyError> +) -> Result, FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.readDirSync()")?; + .check_read(&path, "Deno.readDirSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); let entries = fs.read_dir_sync(&path).context_path("readdir", &path)?; @@ -585,18 +654,17 @@ where pub async fn op_fs_read_dir_async

( state: Rc>, #[string] path: String, -) -> Result, AnyError> +) -> Result, FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.readDir()")?; - state.borrow::().clone() + .check_read(&path, "Deno.readDir()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; let entries = fs @@ -612,17 +680,20 @@ pub fn op_fs_rename_sync

( state: &mut OpState, #[string] oldpath: String, #[string] newpath: String, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let oldpath = PathBuf::from(oldpath); - let newpath = PathBuf::from(newpath); - let permissions = state.borrow_mut::

(); - permissions.check_read(&oldpath, "Deno.renameSync()")?; - permissions.check_write(&oldpath, "Deno.renameSync()")?; - permissions.check_write(&newpath, "Deno.renameSync()")?; + let _ = permissions + .check_read(&oldpath, "Deno.renameSync()") + .map_err(FsOpsError::Permission)?; + let oldpath = permissions + .check_write(&oldpath, "Deno.renameSync()") + .map_err(FsOpsError::Permission)?; + let newpath = permissions + .check_write(&newpath, "Deno.renameSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.rename_sync(&oldpath, &newpath) @@ -636,20 +707,23 @@ pub async fn op_fs_rename_async

( state: Rc>, #[string] oldpath: String, #[string] newpath: String, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let oldpath = PathBuf::from(oldpath); - let newpath = PathBuf::from(newpath); - - let fs = { + let (fs, oldpath, newpath) = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_read(&oldpath, "Deno.rename()")?; - permissions.check_write(&oldpath, "Deno.rename()")?; - permissions.check_write(&newpath, "Deno.rename()")?; - state.borrow::().clone() + _ = permissions + .check_read(&oldpath, "Deno.rename()") + .map_err(FsOpsError::Permission)?; + let oldpath = permissions + .check_write(&oldpath, "Deno.rename()") + .map_err(FsOpsError::Permission)?; + let newpath = permissions + .check_write(&newpath, "Deno.rename()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), oldpath, newpath) }; fs.rename_async(oldpath.clone(), newpath.clone()) @@ -664,18 +738,23 @@ pub fn op_fs_link_sync

( state: &mut OpState, #[string] oldpath: &str, #[string] newpath: &str, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let oldpath = PathBuf::from(oldpath); - let newpath = PathBuf::from(newpath); - let permissions = state.borrow_mut::

(); - permissions.check_read(&oldpath, "Deno.linkSync()")?; - permissions.check_write(&oldpath, "Deno.linkSync()")?; - permissions.check_read(&newpath, "Deno.linkSync()")?; - permissions.check_write(&newpath, "Deno.linkSync()")?; + _ = permissions + .check_read(oldpath, "Deno.linkSync()") + .map_err(FsOpsError::Permission)?; + let oldpath = permissions + .check_write(oldpath, "Deno.linkSync()") + .map_err(FsOpsError::Permission)?; + _ = permissions + .check_read(newpath, "Deno.linkSync()") + .map_err(FsOpsError::Permission)?; + let newpath = permissions + .check_write(newpath, "Deno.linkSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.link_sync(&oldpath, &newpath) @@ -689,21 +768,26 @@ pub async fn op_fs_link_async

( state: Rc>, #[string] oldpath: String, #[string] newpath: String, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let oldpath = PathBuf::from(&oldpath); - let newpath = PathBuf::from(&newpath); - - let fs = { + let (fs, oldpath, newpath) = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_read(&oldpath, "Deno.link()")?; - permissions.check_write(&oldpath, "Deno.link()")?; - permissions.check_read(&newpath, "Deno.link()")?; - permissions.check_write(&newpath, "Deno.link()")?; - state.borrow::().clone() + _ = permissions + .check_read(&oldpath, "Deno.link()") + .map_err(FsOpsError::Permission)?; + let oldpath = permissions + .check_write(&oldpath, "Deno.link()") + .map_err(FsOpsError::Permission)?; + _ = permissions + .check_read(&newpath, "Deno.link()") + .map_err(FsOpsError::Permission)?; + let newpath = permissions + .check_write(&newpath, "Deno.link()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), oldpath, newpath) }; fs.link_async(oldpath.clone(), newpath.clone()) @@ -719,7 +803,7 @@ pub fn op_fs_symlink_sync

( #[string] oldpath: &str, #[string] newpath: &str, #[serde] file_type: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { @@ -727,8 +811,12 @@ where let newpath = PathBuf::from(newpath); let permissions = state.borrow_mut::

(); - permissions.check_write_all("Deno.symlinkSync()")?; - permissions.check_read_all("Deno.symlinkSync()")?; + permissions + .check_write_all("Deno.symlinkSync()") + .map_err(FsOpsError::Permission)?; + permissions + .check_read_all("Deno.symlinkSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.symlink_sync(&oldpath, &newpath, file_type) @@ -743,7 +831,7 @@ pub async fn op_fs_symlink_async

( #[string] oldpath: String, #[string] newpath: String, #[serde] file_type: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { @@ -753,8 +841,12 @@ where let fs = { let mut state = state.borrow_mut(); let permissions = state.borrow_mut::

(); - permissions.check_write_all("Deno.symlink()")?; - permissions.check_read_all("Deno.symlink()")?; + permissions + .check_write_all("Deno.symlink()") + .map_err(FsOpsError::Permission)?; + permissions + .check_read_all("Deno.symlink()") + .map_err(FsOpsError::Permission)?; state.borrow::().clone() }; @@ -770,15 +862,14 @@ where pub fn op_fs_read_link_sync

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.readLink()")?; + .check_read(&path, "Deno.readLink()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); @@ -792,18 +883,17 @@ where pub async fn op_fs_read_link_async

( state: Rc>, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_read(&path, "Deno.readLink()")?; - state.borrow::().clone() + .check_read(&path, "Deno.readLink()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; let target = fs @@ -819,15 +909,14 @@ pub fn op_fs_truncate_sync

( state: &mut OpState, #[string] path: &str, #[number] len: u64, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.truncateSync()")?; + .check_write(path, "Deno.truncateSync()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.truncate_sync(&path, len) @@ -841,18 +930,17 @@ pub async fn op_fs_truncate_async

( state: Rc>, #[string] path: String, #[number] len: u64, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_write(&path, "Deno.truncate()")?; - state.borrow::().clone() + .check_write(&path, "Deno.truncate()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; fs.truncate_async(path.clone(), len) @@ -870,13 +958,14 @@ pub fn op_fs_utime_sync

( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - state.borrow_mut::

().check_write(&path, "Deno.utime()")?; + let path = state + .borrow_mut::

() + .check_write(path, "Deno.utime()") + .map_err(FsOpsError::Permission)?; let fs = state.borrow::(); fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos) @@ -893,16 +982,17 @@ pub async fn op_fs_utime_async

( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state.borrow_mut::

().check_write(&path, "Deno.utime()")?; - state.borrow::().clone() + let path = state + .borrow_mut::

() + .check_write(&path, "Deno.utime()") + .map_err(FsOpsError::Permission)?; + (state.borrow::().clone(), path) }; fs.utime_async( @@ -922,23 +1012,30 @@ where #[string] pub fn op_fs_make_temp_dir_sync

( state: &mut OpState, - #[string] dir: Option, + #[string] dir_arg: Option, #[string] prefix: Option, #[string] suffix: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let (dir, fs) = - make_temp_check_sync::

(state, dir, "Deno.makeTempDirSync()")?; + let (dir, fs) = make_temp_check_sync::

( + state, + dir_arg.as_deref(), + "Deno.makeTempDirSync()", + )?; let mut rng = thread_rng(); const MAX_TRIES: u32 = 10; for _ in 0..MAX_TRIES { let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?; - match fs.mkdir_sync(&path, false, 0o700) { - Ok(_) => return path_into_string(path.into_os_string()), + match fs.mkdir_sync(&path, false, Some(0o700)) { + Ok(_) => { + // PERMISSIONS: ensure the absolute path is not leaked + let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?; + return path_into_string(path.into_os_string()); + } Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => { continue; } @@ -957,22 +1054,34 @@ where #[string] pub async fn op_fs_make_temp_dir_async

( state: Rc>, - #[string] dir: Option, + #[string] dir_arg: Option, #[string] prefix: Option, #[string] suffix: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let (dir, fs) = make_temp_check_async::

(state, dir, "Deno.makeTempDir()")?; + let (dir, fs) = make_temp_check_async::

( + state, + dir_arg.as_deref(), + "Deno.makeTempDir()", + )?; let mut rng = thread_rng(); const MAX_TRIES: u32 = 10; for _ in 0..MAX_TRIES { let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?; - match fs.clone().mkdir_async(path.clone(), false, 0o700).await { - Ok(_) => return path_into_string(path.into_os_string()), + match fs + .clone() + .mkdir_async(path.clone(), false, Some(0o700)) + .await + { + Ok(_) => { + // PERMISSIONS: ensure the absolute path is not leaked + let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?; + return path_into_string(path.into_os_string()); + } Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => { continue; } @@ -991,15 +1100,18 @@ where #[string] pub fn op_fs_make_temp_file_sync

( state: &mut OpState, - #[string] dir: Option, + #[string] dir_arg: Option, #[string] prefix: Option, #[string] suffix: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let (dir, fs) = - make_temp_check_sync::

(state, dir, "Deno.makeTempFileSync()")?; + let (dir, fs) = make_temp_check_sync::

( + state, + dir_arg.as_deref(), + "Deno.makeTempFileSync()", + )?; let open_opts = OpenOptions { write: true, @@ -1013,7 +1125,11 @@ where for _ in 0..MAX_TRIES { let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?; match fs.open_sync(&path, open_opts, None) { - Ok(_) => return path_into_string(path.into_os_string()), + Ok(_) => { + // PERMISSIONS: ensure the absolute path is not leaked + let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?; + return path_into_string(path.into_os_string()); + } Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => { continue; } @@ -1032,15 +1148,18 @@ where #[string] pub async fn op_fs_make_temp_file_async

( state: Rc>, - #[string] dir: Option, + #[string] dir_arg: Option, #[string] prefix: Option, #[string] suffix: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { - let (dir, fs) = - make_temp_check_async::

(state, dir, "Deno.makeTempFile()")?; + let (dir, fs) = make_temp_check_async::

( + state, + dir_arg.as_deref(), + "Deno.makeTempFile()", + )?; let open_opts = OpenOptions { write: true, @@ -1055,7 +1174,11 @@ where for _ in 0..MAX_TRIES { let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?; match fs.clone().open_async(path.clone(), open_opts, None).await { - Ok(_) => return path_into_string(path.into_os_string()), + Ok(_) => { + // PERMISSIONS: ensure the absolute path is not leaked + let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?; + return path_into_string(path.into_os_string()); + } Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => { continue; } @@ -1069,26 +1192,43 @@ where .context("tmpfile") } +fn strip_dir_prefix( + resolved_dir: &Path, + dir_arg: Option<&str>, + result_path: PathBuf, +) -> Result { + if resolved_dir.is_absolute() { + match &dir_arg { + Some(dir_arg) => { + Ok(Path::new(dir_arg).join(result_path.strip_prefix(resolved_dir)?)) + } + None => Ok(result_path), + } + } else { + Ok(result_path) + } +} + fn make_temp_check_sync

( state: &mut OpState, - dir: Option, + dir: Option<&str>, api_name: &str, -) -> Result<(PathBuf, FileSystemRc), AnyError> +) -> Result<(PathBuf, FileSystemRc), FsOpsError> where P: FsPermissions + 'static, { let fs = state.borrow::().clone(); let dir = match dir { - Some(dir) => { - let dir = PathBuf::from(dir); - state.borrow_mut::

().check_write(&dir, api_name)?; - dir - } + Some(dir) => state + .borrow_mut::

() + .check_write(dir, api_name) + .map_err(FsOpsError::Permission)?, None => { let dir = fs.tmp_dir().context("tmpdir")?; state .borrow_mut::

() - .check_write_blind(&dir, "TMP", api_name)?; + .check_write_blind(&dir, "TMP", api_name) + .map_err(FsOpsError::Permission)?; dir } }; @@ -1097,25 +1237,25 @@ where fn make_temp_check_async

( state: Rc>, - dir: Option, + dir: Option<&str>, api_name: &str, -) -> Result<(PathBuf, FileSystemRc), AnyError> +) -> Result<(PathBuf, FileSystemRc), FsOpsError> where P: FsPermissions + 'static, { let mut state = state.borrow_mut(); let fs = state.borrow::().clone(); let dir = match dir { - Some(dir) => { - let dir = PathBuf::from(dir); - state.borrow_mut::

().check_write(&dir, api_name)?; - dir - } + Some(dir) => state + .borrow_mut::

() + .check_write(dir, api_name) + .map_err(FsOpsError::Permission)?, None => { let dir = fs.tmp_dir().context("tmpdir")?; state .borrow_mut::

() - .check_write_blind(&dir, "TMP", api_name)?; + .check_write_blind(&dir, "TMP", api_name) + .map_err(FsOpsError::Permission)?; dir } }; @@ -1128,10 +1268,10 @@ where fn validate_temporary_filename_component( component: &str, #[allow(unused_variables)] suffix: bool, -) -> Result<(), AnyError> { +) -> Result<(), FsOpsError> { // Ban ASCII and Unicode control characters: these will often fail if let Some(c) = component.matches(|c: char| c.is_control()).next() { - bail!("Invalid control character in prefix or suffix: {:?}", c); + return Err(FsOpsError::InvalidControlCharacter(c.to_string())); } // Windows has the most restrictive filenames. As temp files aren't normal files, we just // use this set of banned characters for all platforms because wildcard-like files can also @@ -1147,13 +1287,13 @@ fn validate_temporary_filename_component( .matches(|c: char| "<>:\"/\\|?*".contains(c)) .next() { - bail!("Invalid character in prefix or suffix: {:?}", c); + return Err(FsOpsError::InvalidCharacter(c.to_string())); } // This check is only for Windows #[cfg(windows)] if suffix && component.ends_with(|c: char| ". ".contains(c)) { - bail!("Invalid trailing character in suffix"); + return Err(FsOpsError::InvalidTrailingCharacter); } Ok(()) @@ -1164,7 +1304,7 @@ fn tmp_name( dir: &Path, prefix: Option<&str>, suffix: Option<&str>, -) -> Result { +) -> Result { let prefix = prefix.unwrap_or(""); validate_temporary_filename_component(prefix, false)?; let suffix = suffix.unwrap_or(""); @@ -1191,7 +1331,7 @@ pub fn op_fs_write_file_sync

( create: bool, create_new: bool, #[buffer] data: JsBuffer, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { @@ -1219,7 +1359,7 @@ pub async fn op_fs_write_file_async

( create_new: bool, #[buffer] data: JsBuffer, #[smi] cancel_rid: Option, -) -> Result<(), AnyError> +) -> Result<(), FsOpsError> where P: FsPermissions + 'static, { @@ -1267,7 +1407,7 @@ where pub fn op_fs_read_file_sync

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -1289,7 +1429,7 @@ pub async fn op_fs_read_file_async

( state: Rc>, #[string] path: String, #[smi] cancel_rid: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -1330,7 +1470,7 @@ where pub fn op_fs_read_file_text_sync

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -1352,7 +1492,7 @@ pub async fn op_fs_read_file_text_async

( state: Rc>, #[string] path: String, #[smi] cancel_rid: Option, -) -> Result +) -> Result where P: FsPermissions + 'static, { @@ -1389,13 +1529,13 @@ where Ok(str) } -fn to_seek_from(offset: i64, whence: i32) -> Result { +fn to_seek_from(offset: i64, whence: i32) -> Result { let seek_from = match whence { 0 => SeekFrom::Start(offset as u64), 1 => SeekFrom::Current(offset), 2 => SeekFrom::End(offset), _ => { - return Err(type_error(format!("Invalid seek mode: {whence}"))); + return Err(FsOpsError::InvalidSeekMode(whence)); } }; Ok(seek_from) @@ -1408,9 +1548,10 @@ pub fn op_fs_seek_sync( #[smi] rid: ResourceId, #[number] offset: i64, #[smi] whence: i32, -) -> Result { +) -> Result { let pos = to_seek_from(offset, whence)?; - let file = FileResource::get_file(state, rid)?; + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; let cursor = file.seek_sync(pos)?; Ok(cursor) } @@ -1422,49 +1563,54 @@ pub async fn op_fs_seek_async( #[smi] rid: ResourceId, #[number] offset: i64, #[smi] whence: i32, -) -> Result { +) -> Result { let pos = to_seek_from(offset, whence)?; - let file = FileResource::get_file(&state.borrow(), rid)?; + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; let cursor = file.seek_async(pos).await?; Ok(cursor) } #[op2(fast)] -pub fn op_fs_fdatasync_sync( +pub fn op_fs_file_sync_data_sync( state: &mut OpState, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.datasync_sync()?; Ok(()) } #[op2(async)] -pub async fn op_fs_fdatasync_async( +pub async fn op_fs_file_sync_data_async( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file.datasync_async().await?; Ok(()) } #[op2(fast)] -pub fn op_fs_fsync_sync( +pub fn op_fs_file_sync_sync( state: &mut OpState, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.sync_sync()?; Ok(()) } #[op2(async)] -pub async fn op_fs_fsync_async( +pub async fn op_fs_file_sync_async( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file.sync_async().await?; Ok(()) } @@ -1474,8 +1620,9 @@ pub fn op_fs_file_stat_sync( state: &mut OpState, #[smi] rid: ResourceId, #[buffer] stat_out_buf: &mut [u32], -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; let stat = file.stat_sync()?; let serializable_stat = SerializableStat::from(stat); serializable_stat.write(stat_out_buf); @@ -1487,65 +1634,21 @@ pub fn op_fs_file_stat_sync( pub async fn op_fs_file_stat_async( state: Rc>, #[smi] rid: ResourceId, -) -> Result { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; let stat = file.stat_async().await?; Ok(stat.into()) } -#[op2(fast)] -pub fn op_fs_flock_sync_unstable( - state: &mut OpState, - #[smi] rid: ResourceId, - exclusive: bool, -) -> Result<(), AnyError> { - check_unstable(state, "Deno.flockSync"); - let file = FileResource::get_file(state, rid)?; - file.lock_sync(exclusive)?; - Ok(()) -} - -#[op2(async)] -pub async fn op_fs_flock_async_unstable( - state: Rc>, - #[smi] rid: ResourceId, - exclusive: bool, -) -> Result<(), AnyError> { - check_unstable(&state.borrow(), "Deno.flock"); - let file = FileResource::get_file(&state.borrow(), rid)?; - file.lock_async(exclusive).await?; - Ok(()) -} - -#[op2(fast)] -pub fn op_fs_funlock_sync_unstable( - state: &mut OpState, - #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - check_unstable(state, "Deno.funlockSync"); - let file = FileResource::get_file(state, rid)?; - file.unlock_sync()?; - Ok(()) -} - -#[op2(async)] -pub async fn op_fs_funlock_async_unstable( - state: Rc>, - #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - check_unstable(&state.borrow(), "Deno.funlock"); - let file = FileResource::get_file(&state.borrow(), rid)?; - file.unlock_async().await?; - Ok(()) -} - #[op2(fast)] pub fn op_fs_flock_sync( state: &mut OpState, #[smi] rid: ResourceId, exclusive: bool, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.lock_sync(exclusive)?; Ok(()) } @@ -1555,8 +1658,9 @@ pub async fn op_fs_flock_async( state: Rc>, #[smi] rid: ResourceId, exclusive: bool, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file.lock_async(exclusive).await?; Ok(()) } @@ -1565,8 +1669,9 @@ pub async fn op_fs_flock_async( pub fn op_fs_funlock_sync( state: &mut OpState, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.unlock_sync()?; Ok(()) } @@ -1575,8 +1680,9 @@ pub fn op_fs_funlock_sync( pub async fn op_fs_funlock_async( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file.unlock_async().await?; Ok(()) } @@ -1586,19 +1692,21 @@ pub fn op_fs_ftruncate_sync( state: &mut OpState, #[smi] rid: ResourceId, #[number] len: u64, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.truncate_sync(len)?; Ok(()) } #[op2(async)] -pub async fn op_fs_ftruncate_async( +pub async fn op_fs_file_truncate_async( state: Rc>, #[smi] rid: ResourceId, #[number] len: u64, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file.truncate_async(len).await?; Ok(()) } @@ -1611,8 +1719,9 @@ pub fn op_fs_futime_sync( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> { - let file = FileResource::get_file(state, rid)?; +) -> Result<(), FsOpsError> { + let file = + FileResource::get_file(state, rid).map_err(FsOpsError::Resource)?; file.utime_sync(atime_secs, atime_nanos, mtime_secs, mtime_nanos)?; Ok(()) } @@ -1625,42 +1734,64 @@ pub async fn op_fs_futime_async( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> { - let file = FileResource::get_file(&state.borrow(), rid)?; +) -> Result<(), FsOpsError> { + let file = FileResource::get_file(&state.borrow(), rid) + .map_err(FsOpsError::Resource)?; file .utime_async(atime_secs, atime_nanos, mtime_secs, mtime_nanos) .await?; Ok(()) } -trait WithContext { - fn context>>( - self, - desc: E, - ) -> AnyError; +#[derive(Debug)] +pub struct OperationError { + operation: &'static str, + kind: OperationErrorKind, + pub err: FsError, } -impl WithContext for FsError { - fn context>>( - self, - desc: E, - ) -> AnyError { - match self { - FsError::Io(io) => { - AnyError::new(io::Error::new(io.kind(), desc)).context(io) +impl std::fmt::Display for OperationError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if let FsError::Io(e) = &self.err { + std::fmt::Display::fmt(&e, f)?; + f.write_str(": ")?; + } + + f.write_str(self.operation)?; + + match &self.kind { + OperationErrorKind::Bare => Ok(()), + OperationErrorKind::WithPath(path) => write!(f, " '{}'", path.display()), + OperationErrorKind::WithTwoPaths(from, to) => { + write!(f, " '{}' -> '{}'", from.display(), to.display()) } - _ => self.into(), } } } +impl std::error::Error for OperationError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + if let FsError::Io(err) = &self.err { + Some(err) + } else { + None + } + } +} + +#[derive(Debug)] +pub enum OperationErrorKind { + Bare, + WithPath(PathBuf), + WithTwoPaths(PathBuf, PathBuf), +} + trait MapErrContext { type R; - fn context_fn(self, f: F) -> Self::R + fn context_fn(self, f: F) -> Self::R where - F: FnOnce() -> E, - E: Into>; + F: FnOnce(FsError) -> OperationError; fn context(self, desc: &'static str) -> Self::R; @@ -1675,25 +1806,29 @@ trait MapErrContext { } impl MapErrContext for Result { - type R = Result; + type R = Result; - fn context_fn(self, f: F) -> Self::R + fn context_fn(self, f: F) -> Self::R where - F: FnOnce() -> E, - E: Into>, + F: FnOnce(FsError) -> OperationError, { - self.map_err(|err| { - let message = f(); - err.context(message) + self.map_err(|err| FsOpsError::OperationError(f(err))) + } + + fn context(self, operation: &'static str) -> Self::R { + self.context_fn(move |err| OperationError { + operation, + kind: OperationErrorKind::Bare, + err, }) } - fn context(self, desc: &'static str) -> Self::R { - self.context_fn(move || desc) - } - fn context_path(self, operation: &'static str, path: &Path) -> Self::R { - self.context_fn(|| format!("{operation} '{}'", path.display())) + self.context_fn(|err| OperationError { + operation, + kind: OperationErrorKind::WithPath(path.to_path_buf()), + err, + }) } fn context_two_path( @@ -1702,21 +1837,19 @@ impl MapErrContext for Result { oldpath: &Path, newpath: &Path, ) -> Self::R { - self.context_fn(|| { - format!( - "{operation} '{}' -> '{}'", - oldpath.display(), - newpath.display() - ) + self.context_fn(|err| OperationError { + operation, + kind: OperationErrorKind::WithTwoPaths( + oldpath.to_path_buf(), + newpath.to_path_buf(), + ), + err, }) } } -fn path_into_string(s: std::ffi::OsString) -> Result { - s.into_string().map_err(|s| { - let message = format!("File name or path {s:?} is not valid UTF-8"); - custom_error("InvalidData", message) - }) +fn path_into_string(s: std::ffi::OsString) -> Result { + s.into_string().map_err(FsOpsError::InvalidUtf8) } macro_rules! create_struct_writer { diff --git a/ext/fs/std_fs.rs b/ext/fs/std_fs.rs index 3cbd154d59..1a83c97c53 100644 --- a/ext/fs/std_fs.rs +++ b/ext/fs/std_fs.rs @@ -11,13 +11,13 @@ use std::path::Path; use std::path::PathBuf; use std::rc::Rc; -use deno_core::normalize_path; use deno_core::unsync::spawn_blocking; use deno_io::fs::File; use deno_io::fs::FsError; use deno_io::fs::FsResult; use deno_io::fs::FsStat; use deno_io::StdFileResourceInner; +use deno_path_util::normalize_path; use crate::interface::AccessCheckCb; use crate::interface::FsDirEntry; @@ -101,7 +101,7 @@ impl FileSystem for RealFs { &self, path: &Path, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()> { mkdir(path, recursive, mode) } @@ -109,7 +109,7 @@ impl FileSystem for RealFs { &self, path: PathBuf, recursive: bool, - mode: u32, + mode: Option, ) -> FsResult<()> { spawn_blocking(move || mkdir(&path, recursive, mode)).await? } @@ -407,11 +407,11 @@ impl FileSystem for RealFs { } } -fn mkdir(path: &Path, recursive: bool, mode: u32) -> FsResult<()> { +fn mkdir(path: &Path, recursive: bool, mode: Option) -> FsResult<()> { let mut builder = fs::DirBuilder::new(); builder.recursive(recursive); #[cfg(unix)] - { + if let Some(mode) = mode { use std::os::unix::fs::DirBuilderExt; builder.mode(mode); } @@ -929,7 +929,7 @@ fn exists(path: &Path) -> bool { } fn realpath(path: &Path) -> FsResult { - Ok(deno_core::strip_unc_prefix(path.canonicalize()?)) + Ok(deno_path_util::strip_unc_prefix(path.canonicalize()?)) } fn read_dir(path: &Path) -> FsResult> { @@ -1069,8 +1069,10 @@ fn open_with_access_check( }; (*access_check)(false, &path, &options)?; // On Linux, /proc may contain magic links that we don't want to resolve - let needs_canonicalization = !is_windows_device_path - && (!cfg!(target_os = "linux") || path.starts_with("/proc")); + let is_linux_special_path = cfg!(target_os = "linux") + && (path.starts_with("/proc") || path.starts_with("/dev")); + let needs_canonicalization = + !is_windows_device_path && !is_linux_special_path; let path = if needs_canonicalization { match path.canonicalize() { Ok(path) => path, diff --git a/ext/http/00_serve.ts b/ext/http/00_serve.ts index 9c6f805528..1b70cf2129 100644 --- a/ext/http/00_serve.ts +++ b/ext/http/00_serve.ts @@ -76,7 +76,11 @@ import { ReadableStreamPrototype, resourceForReadableStream, } from "ext:deno_web/06_streams.js"; -import { listen, listenOptionApiName, TcpConn } from "ext:deno_net/01_net.js"; +import { + listen, + listenOptionApiName, + UpgradedConn, +} from "ext:deno_net/01_net.js"; import { hasTlsKeyPairOptions, listenTls } from "ext:deno_net/02_tls.js"; import { SymbolAsyncDispose } from "ext:deno_web/00_infra.js"; @@ -123,7 +127,7 @@ function upgradeHttpRaw(req, conn) { if (inner._wantsUpgrade) { return inner._wantsUpgrade("upgradeHttpRaw", conn); } - throw new TypeError("upgradeHttpRaw may only be used with Deno.serve"); + throw new TypeError("'upgradeHttpRaw' may only be used with Deno.serve"); } function addTrailers(resp, headerList) { @@ -170,10 +174,10 @@ class InnerRequest { _wantsUpgrade(upgradeType, ...originalArgs) { if (this.#upgraded) { - throw new Deno.errors.Http("already upgraded"); + throw new Deno.errors.Http("Already upgraded"); } if (this.#external === null) { - throw new Deno.errors.Http("already closed"); + throw new Deno.errors.Http("Already closed"); } // upgradeHttpRaw is sync @@ -189,7 +193,7 @@ class InnerRequest { const upgradeRid = op_http_upgrade_raw(external); - const conn = new TcpConn( + const conn = new UpgradedConn( upgradeRid, underlyingConn?.remoteAddr, underlyingConn?.localAddr, @@ -257,7 +261,7 @@ class InnerRequest { if (this.#methodAndUri === undefined) { if (this.#external === null) { - throw new TypeError("request closed"); + throw new TypeError("Request closed"); } // TODO(mmastrac): This is quite slow as we're serializing a large number of values. We may want to consider // splitting this up into multiple ops. @@ -315,7 +319,7 @@ class InnerRequest { } if (this.#methodAndUri === undefined) { if (this.#external === null) { - throw new TypeError("request closed"); + throw new TypeError("Request closed"); } this.#methodAndUri = op_http_get_request_method_and_url(this.#external); } @@ -329,7 +333,7 @@ class InnerRequest { get method() { if (this.#methodAndUri === undefined) { if (this.#external === null) { - throw new TypeError("request closed"); + throw new TypeError("Request closed"); } this.#methodAndUri = op_http_get_request_method_and_url(this.#external); } @@ -338,7 +342,7 @@ class InnerRequest { get body() { if (this.#external === null) { - throw new TypeError("request closed"); + throw new TypeError("Request closed"); } if (this.#body !== undefined) { return this.#body; @@ -356,7 +360,7 @@ class InnerRequest { get headerList() { if (this.#external === null) { - throw new TypeError("request closed"); + throw new TypeError("Request closed"); } const headers = []; const reqHeaders = op_http_get_request_headers(this.#external); @@ -457,7 +461,7 @@ function fastSyncResponseOrStream( // At this point in the response it needs to be a stream if (!ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, stream)) { innerRequest?.close(); - throw TypeError("invalid response"); + throw new TypeError("Invalid response"); } const resourceBacking = getReadableStreamResourceBacking(stream); let rid, autoClose; @@ -506,25 +510,32 @@ function mapToCallback(context, callback, onError) { // Throwing Error if the handler return value is not a Response class if (!ObjectPrototypeIsPrototypeOf(ResponsePrototype, response)) { - throw TypeError( + throw new TypeError( "Return value from serve handler must be a response or a promise resolving to a response", ); } + if (response.type === "error") { + throw new TypeError( + "Return value from serve handler must not be an error response (like Response.error())", + ); + } + if (response.bodyUsed) { - throw TypeError( - "The body of the Response returned from the serve handler has already been consumed.", + throw new TypeError( + "The body of the Response returned from the serve handler has already been consumed", ); } } catch (error) { try { response = await onError(error); if (!ObjectPrototypeIsPrototypeOf(ResponsePrototype, response)) { - throw TypeError( + throw new TypeError( "Return value from onError handler must be a response or a promise resolving to a response", ); } } catch (error) { + // deno-lint-ignore no-console console.error("Exception in onError while handling exception", error); response = internalServerError(); } @@ -533,6 +544,7 @@ function mapToCallback(context, callback, onError) { if (innerRequest?.[_upgraded]) { // We're done here as the connection has been upgraded during the callback and no longer requires servicing. if (response !== UPGRADE_RESPONSE_SENTINEL) { + // deno-lint-ignore no-console console.error("Upgrade response was not returned from callback"); context.close(); } @@ -581,6 +593,21 @@ type RawServeOptions = { const kLoadBalanced = Symbol("kLoadBalanced"); +function formatHostName(hostname: string): string { + // If the hostname is "0.0.0.0", we display "localhost" in console + // because browsers in Windows don't resolve "0.0.0.0". + // See the discussion in https://github.com/denoland/deno_std/issues/1165 + if ( + (Deno.build.os === "windows") && + (hostname == "0.0.0.0" || hostname == "::") + ) { + return "localhost"; + } + + // Add brackets around ipv6 hostname + return StringPrototypeIncludes(hostname, ":") ? `[${hostname}]` : hostname; +} + function serve(arg1, arg2) { let options: RawServeOptions | undefined; let handler: RawHandler | undefined; @@ -596,13 +623,15 @@ function serve(arg1, arg2) { if (handler === undefined) { if (options === undefined) { throw new TypeError( - "No handler was provided, so an options bag is mandatory.", + "Cannot serve HTTP requests: either a `handler` or `options` must be specified", ); } handler = options.handler; } if (typeof handler !== "function") { - throw new TypeError("A handler function must be provided."); + throw new TypeError( + `Cannot serve HTTP requests: handler must be a function, received ${typeof handler}`, + ); } if (options === undefined) { options = { __proto__: null }; @@ -612,6 +641,7 @@ function serve(arg1, arg2) { const wantsUnix = ObjectHasOwn(options, "path"); const signal = options.signal; const onError = options.onError ?? function (error) { + // deno-lint-ignore no-console console.error(error); return internalServerError(); }; @@ -627,7 +657,8 @@ function serve(arg1, arg2) { if (options.onListen) { options.onListen(listener.addr); } else { - console.log(`Listening on ${path}`); + // deno-lint-ignore no-console + console.error(`Listening on ${path}`); } }); } @@ -654,7 +685,7 @@ function serve(arg1, arg2) { if (wantsHttps) { if (!options.cert || !options.key) { throw new TypeError( - "Both cert and key must be provided to enable HTTPS.", + "Both 'cert' and 'key' must be provided to enable HTTPS", ); } listenOpts.cert = options.cert; @@ -668,23 +699,15 @@ function serve(arg1, arg2) { } const addr = listener.addr; - // If the hostname is "0.0.0.0", we display "localhost" in console - // because browsers in Windows don't resolve "0.0.0.0". - // See the discussion in https://github.com/denoland/deno_std/issues/1165 - const hostname = (addr.hostname == "0.0.0.0" || addr.hostname == "::") && - (Deno.build.os === "windows") - ? "localhost" - : addr.hostname; - addr.hostname = hostname; const onListen = (scheme) => { if (options.onListen) { options.onListen(addr); } else { - const host = StringPrototypeIncludes(addr.hostname, ":") - ? `[${addr.hostname}]` - : addr.hostname; - console.log(`Listening on ${scheme}${host}:${addr.port}/`); + const host = formatHostName(addr.hostname); + + // deno-lint-ignore no-console + console.error(`Listening on ${scheme}${host}:${addr.port}/`); } }; @@ -729,6 +752,7 @@ function serveHttpOn(context, addr, callback) { const promiseErrorHandler = (error) => { // Abnormal exit + // deno-lint-ignore no-console console.error( "Terminating Deno.serve loop due to unexpected error", error, @@ -856,8 +880,11 @@ function registerDeclarativeServer(exports) { const nThreads = serveWorkerCount > 1 ? ` with ${serveWorkerCount} threads` : ""; - console.debug( - `%cdeno serve%c: Listening on %chttp://${hostname}:${port}/%c${nThreads}`, + const host = formatHostName(hostname); + + // deno-lint-ignore no-console + console.error( + `%cdeno serve%c: Listening on %chttp://${host}:${port}/%c${nThreads}`, "color: green", "color: inherit", "color: yellow", @@ -865,8 +892,8 @@ function registerDeclarativeServer(exports) { ); } }, - handler: (req) => { - return exports.fetch(req); + handler: (req, connInfo) => { + return exports.fetch(req, connInfo); }, }); }; diff --git a/ext/http/01_http.js b/ext/http/01_http.js index b547682891..9302bd8a0f 100644 --- a/ext/http/01_http.js +++ b/ext/http/01_http.js @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { core, internals, primordials } from "ext:core/mod.js"; +import { core, primordials } from "ext:core/mod.js"; const { BadResourcePrototype, InterruptedPrototype, @@ -207,7 +207,7 @@ function createRespondWith( resp = await resp; if (!(ObjectPrototypeIsPrototypeOf(ResponsePrototype, resp))) { throw new TypeError( - "First argument to respondWith must be a Response or a promise resolving to a Response.", + "First argument to 'respondWith' must be a Response or a promise resolving to a Response", ); } @@ -220,7 +220,7 @@ function createRespondWith( let respBody = null; if (innerResp.body !== null) { if (innerResp.body.unusable()) { - throw new TypeError("Body is unusable."); + throw new TypeError("Body is unusable"); } if ( ObjectPrototypeIsPrototypeOf( @@ -295,7 +295,7 @@ function createRespondWith( let reader; if (resourceBacking) { if (respBody.locked) { - throw new TypeError("ReadableStream is locked."); + throw new TypeError("ReadableStream is locked"); } reader = respBody.getReader(); // Acquire JS lock. try { @@ -396,11 +396,6 @@ function createRespondWith( } function serveHttp(conn) { - internals.warnOnDeprecatedApi( - "Deno.serveHttp()", - new Error().stack, - "Use `Deno.serve()` instead.", - ); const rid = op_http_start(conn[internalRidSymbol]); return new HttpConn(rid, conn.remoteAddr, conn.localAddr); } diff --git a/ext/http/Cargo.toml b/ext/http/Cargo.toml index f1b9aa4d28..0bae99ef76 100644 --- a/ext/http/Cargo.toml +++ b/ext/http/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_http" -version = "0.162.0" +version = "0.172.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/http/fly_accept_encoding.rs b/ext/http/fly_accept_encoding.rs index 94e3368767..4d6fd2231e 100644 --- a/ext/http/fly_accept_encoding.rs +++ b/ext/http/fly_accept_encoding.rs @@ -119,7 +119,7 @@ fn encodings_iter_inner<'s>( }; Some(Ok((encoding, qval))) }) - .map(|r| r?) // flatten Result = Lazy::new(|| { false }); -// NOTE(bartlomieju): currently we don't have any unstable HTTP features, -// but let's keep this const here, because: -// a) we still need to support `--unstable-http` flag to not break user's CLI; -// b) we might add more unstable features in the future. -#[allow(dead_code)] -pub const UNSTABLE_FEATURE_NAME: &str = "http"; - /// All HTTP/2 connections start with this byte string. /// /// In HTTP/2, each endpoint is required to send a connection preface as a final confirmation @@ -153,12 +145,32 @@ macro_rules! clone_external { }}; } +#[derive(Debug, thiserror::Error)] +pub enum HttpNextError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("{0}")] + Io(#[from] io::Error), + #[error(transparent)] + WebSocketUpgrade(crate::websocket_upgrade::WebSocketUpgradeError), + #[error("{0}")] + Hyper(#[from] hyper::Error), + #[error(transparent)] + JoinError(#[from] tokio::task::JoinError), + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), + #[error(transparent)] + HttpPropertyExtractor(deno_core::error::AnyError), + #[error(transparent)] + UpgradeUnavailable(#[from] crate::service::UpgradeUnavailableError), +} + #[op2(fast)] #[smi] pub fn op_http_upgrade_raw( state: &mut OpState, external: *const c_void, -) -> Result { +) -> Result { // SAFETY: external is deleted before calling this op. let http = unsafe { take_external!(external, "op_http_upgrade_raw") }; @@ -184,7 +196,7 @@ pub fn op_http_upgrade_raw( upgraded.write_all(&bytes).await?; break upgraded; } - Err(err) => return Err(err), + Err(err) => return Err(HttpNextError::WebSocketUpgrade(err)), } }; @@ -200,7 +212,7 @@ pub fn op_http_upgrade_raw( } read_tx.write_all(&buf[..read]).await?; } - Ok::<_, AnyError>(()) + Ok::<_, HttpNextError>(()) }); spawn(async move { let mut buf = [0; 1024]; @@ -211,7 +223,7 @@ pub fn op_http_upgrade_raw( } upgraded_tx.write_all(&buf[..read]).await?; } - Ok::<_, AnyError>(()) + Ok::<_, HttpNextError>(()) }); Ok(()) @@ -230,7 +242,7 @@ pub async fn op_http_upgrade_websocket_next( state: Rc>, external: *const c_void, #[serde] headers: Vec<(ByteString, ByteString)>, -) -> Result { +) -> Result { let http = // SAFETY: external is deleted before calling this op. unsafe { take_external!(external, "op_http_upgrade_websocket_next") }; @@ -253,7 +265,11 @@ pub async fn op_http_upgrade_websocket_next( // Stage 3: take the extracted raw network stream and upgrade it to a websocket, then return it let (stream, bytes) = extract_network_stream(upgraded); - ws_create_server_stream(&mut state.borrow_mut(), stream, bytes) + Ok(ws_create_server_stream( + &mut state.borrow_mut(), + stream, + bytes, + )) } #[op2(fast)] @@ -303,7 +319,7 @@ where let authority: v8::Local = match request_properties.authority { Some(authority) => v8::String::new_from_utf8( scope, - authority.as_ref(), + authority.as_bytes(), v8::NewStringType::Normal, ) .unwrap() @@ -312,15 +328,25 @@ where }; // Only extract the path part - we handle authority elsewhere - let path = match &request_parts.uri.path_and_query() { - Some(path_and_query) => path_and_query.to_string(), - None => "".to_owned(), + let path = match request_parts.uri.path_and_query() { + Some(path_and_query) => { + let path = path_and_query.as_str(); + if matches!(path.as_bytes().first(), Some(b'/' | b'*')) { + Cow::Borrowed(path) + } else { + Cow::Owned(format!("/{}", path)) + } + } + None => Cow::Borrowed(""), }; - let path: v8::Local = - v8::String::new_from_utf8(scope, path.as_ref(), v8::NewStringType::Normal) - .unwrap() - .into(); + let path: v8::Local = v8::String::new_from_utf8( + scope, + path.as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap() + .into(); let peer_address: v8::Local = v8::String::new_from_utf8( scope, @@ -466,7 +492,7 @@ pub fn op_http_set_response_header( response_parts.headers.append(name, value); } -#[op2] +#[op2(fast)] pub fn op_http_set_response_headers( scope: &mut v8::HandleScope, external: *const c_void, @@ -683,7 +709,7 @@ pub async fn op_http_set_response_body_resource( #[smi] stream_rid: ResourceId, auto_close: bool, status: u16, -) -> Result { +) -> Result { let http = // SAFETY: op is called with external. unsafe { clone_external!(external, "op_http_set_response_body_resource") }; @@ -698,9 +724,15 @@ pub async fn op_http_set_response_body_resource( let resource = { let mut state = state.borrow_mut(); if auto_close { - state.resource_table.take_any(stream_rid)? + state + .resource_table + .take_any(stream_rid) + .map_err(HttpNextError::Resource)? } else { - state.resource_table.get_any(stream_rid)? + state + .resource_table + .get_any(stream_rid) + .map_err(HttpNextError::Resource)? } }; @@ -807,17 +839,17 @@ async fn serve_http2_autodetect( io: impl HttpServeStream, svc: impl HttpService + 'static, cancel: Rc, -) -> Result<(), AnyError> { +) -> Result<(), HttpNextError> { let prefix = NetworkStreamPrefixCheck::new(io, HTTP2_PREFIX); let (matches, io) = prefix.match_prefix().await?; if matches { serve_http2_unconditional(io, svc, cancel) .await - .map_err(|e| e.into()) + .map_err(HttpNextError::Hyper) } else { serve_http11_unconditional(io, svc, cancel) .await - .map_err(|e| e.into()) + .map_err(HttpNextError::Hyper) } } @@ -826,7 +858,7 @@ fn serve_https( request_info: HttpConnectionProperties, lifetime: HttpLifetime, tx: tokio::sync::mpsc::Sender>, -) -> JoinHandle> { +) -> JoinHandle> { let HttpLifetime { server_state, connection_cancel_handle, @@ -845,11 +877,11 @@ fn serve_https( if Some(TLS_ALPN_HTTP_2) == handshake.as_deref() { serve_http2_unconditional(io, svc, listen_cancel_handle) .await - .map_err(|e| e.into()) + .map_err(HttpNextError::Hyper) } else if Some(TLS_ALPN_HTTP_11) == handshake.as_deref() { serve_http11_unconditional(io, svc, listen_cancel_handle) .await - .map_err(|e| e.into()) + .map_err(HttpNextError::Hyper) } else { serve_http2_autodetect(io, svc, listen_cancel_handle).await } @@ -863,7 +895,7 @@ fn serve_http( request_info: HttpConnectionProperties, lifetime: HttpLifetime, tx: tokio::sync::mpsc::Sender>, -) -> JoinHandle> { +) -> JoinHandle> { let HttpLifetime { server_state, connection_cancel_handle, @@ -884,7 +916,7 @@ fn serve_http_on( listen_properties: &HttpListenProperties, lifetime: HttpLifetime, tx: tokio::sync::mpsc::Sender>, -) -> JoinHandle> +) -> JoinHandle> where HTTP: HttpPropertyExtractor, { @@ -915,7 +947,7 @@ struct HttpLifetime { } struct HttpJoinHandle { - join_handle: AsyncRefCell>>>, + join_handle: AsyncRefCell>>>, connection_cancel_handle: Rc, listen_cancel_handle: Rc, rx: AsyncRefCell>>, @@ -975,12 +1007,13 @@ impl Drop for HttpJoinHandle { pub fn op_http_serve( state: Rc>, #[smi] listener_rid: ResourceId, -) -> Result<(ResourceId, &'static str, String), AnyError> +) -> Result<(ResourceId, &'static str, String), HttpNextError> where HTTP: HttpPropertyExtractor, { let listener = - HTTP::get_listener_for_rid(&mut state.borrow_mut(), listener_rid)?; + HTTP::get_listener_for_rid(&mut state.borrow_mut(), listener_rid) + .map_err(HttpNextError::Resource)?; let listen_properties = HTTP::listen_properties_from_listener(&listener)?; @@ -995,7 +1028,8 @@ where loop { let conn = HTTP::accept_connection_from_listener(&listener) .try_or_cancel(listen_cancel_clone.clone()) - .await?; + .await + .map_err(HttpNextError::HttpPropertyExtractor)?; serve_http_on::( conn, &listen_properties_clone, @@ -1004,7 +1038,7 @@ where ); } #[allow(unreachable_code)] - Ok::<_, AnyError>(()) + Ok::<_, HttpNextError>(()) }); // Set the handle after we start the future @@ -1024,25 +1058,25 @@ where pub fn op_http_serve_on( state: Rc>, #[smi] connection_rid: ResourceId, -) -> Result<(ResourceId, &'static str, String), AnyError> +) -> Result<(ResourceId, &'static str, String), HttpNextError> where HTTP: HttpPropertyExtractor, { let connection = - HTTP::get_connection_for_rid(&mut state.borrow_mut(), connection_rid)?; + HTTP::get_connection_for_rid(&mut state.borrow_mut(), connection_rid) + .map_err(HttpNextError::Resource)?; let listen_properties = HTTP::listen_properties_from_connection(&connection)?; let (tx, rx) = tokio::sync::mpsc::channel(10); let resource: Rc = Rc::new(HttpJoinHandle::new(rx)); - let handle: JoinHandle> = - serve_http_on::( - connection, - &listen_properties, - resource.lifetime(), - tx, - ); + let handle = serve_http_on::( + connection, + &listen_properties, + resource.lifetime(), + tx, + ); // Set the handle after we start the future *RcRef::map(&resource, |this| &this.join_handle) @@ -1088,12 +1122,13 @@ pub fn op_http_try_wait( pub async fn op_http_wait( state: Rc>, #[smi] rid: ResourceId, -) -> Result<*const c_void, AnyError> { +) -> Result<*const c_void, HttpNextError> { // We will get the join handle initially, as we might be consuming requests still let join_handle = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpNextError::Resource)?; let cancel = join_handle.listen_cancel_handle(); let next = async { @@ -1120,13 +1155,12 @@ pub async fn op_http_wait( // Filter out shutdown (ENOTCONN) errors if let Err(err) = res { - if let Some(err) = err.source() { - if let Some(err) = err.downcast_ref::() { - if err.kind() == io::ErrorKind::NotConnected { - return Ok(null()); - } + if let HttpNextError::Io(err) = &err { + if err.kind() == io::ErrorKind::NotConnected { + return Ok(null()); } } + return Err(err); } @@ -1139,7 +1173,7 @@ pub fn op_http_cancel( state: &mut OpState, #[smi] rid: ResourceId, graceful: bool, -) -> Result<(), AnyError> { +) -> Result<(), deno_core::error::AnyError> { let join_handle = state.resource_table.get::(rid)?; if graceful { @@ -1159,11 +1193,12 @@ pub async fn op_http_close( state: Rc>, #[smi] rid: ResourceId, graceful: bool, -) -> Result<(), AnyError> { +) -> Result<(), HttpNextError> { let join_handle = state .borrow_mut() .resource_table - .take::(rid)?; + .take::(rid) + .map_err(HttpNextError::Resource)?; if graceful { http_general_trace!("graceful shutdown"); @@ -1209,23 +1244,26 @@ impl UpgradeStream { } } - async fn read(self: Rc, buf: &mut [u8]) -> Result { + async fn read( + self: Rc, + buf: &mut [u8], + ) -> Result { let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); async { let read = RcRef::map(self, |this| &this.read); let mut read = read.borrow_mut().await; - Ok(Pin::new(&mut *read).read(buf).await?) + Pin::new(&mut *read).read(buf).await } .try_or_cancel(cancel_handle) .await } - async fn write(self: Rc, buf: &[u8]) -> Result { + async fn write(self: Rc, buf: &[u8]) -> Result { let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); async { let write = RcRef::map(self, |this| &this.write); let mut write = write.borrow_mut().await; - Ok(Pin::new(&mut *write).write(buf).await?) + Pin::new(&mut *write).write(buf).await } .try_or_cancel(cancel_handle) .await @@ -1235,7 +1273,7 @@ impl UpgradeStream { self: Rc, buf1: &[u8], buf2: &[u8], - ) -> Result { + ) -> Result { let mut wr = RcRef::map(self, |r| &r.write).borrow_mut().await; let total = buf1.len() + buf2.len(); @@ -1288,9 +1326,12 @@ pub async fn op_raw_write_vectored( #[smi] rid: ResourceId, #[buffer] buf1: JsBuffer, #[buffer] buf2: JsBuffer, -) -> Result { - let resource: Rc = - state.borrow().resource_table.get::(rid)?; +) -> Result { + let resource: Rc = state + .borrow() + .resource_table + .get::(rid) + .map_err(HttpNextError::Resource)?; let nwritten = resource.write_vectored(&buf1, &buf2).await?; Ok(nwritten) } diff --git a/ext/http/lib.rs b/ext/http/lib.rs index 934f8a0024..6243804a14 100644 --- a/ext/http/lib.rs +++ b/ext/http/lib.rs @@ -6,8 +6,6 @@ use async_compression::Level; use base64::prelude::BASE64_STANDARD; use base64::Engine; use cache_control::CacheControl; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::futures::channel::mpsc; use deno_core::futures::channel::oneshot; use deno_core::futures::future::pending; @@ -89,11 +87,14 @@ mod service; mod websocket_upgrade; use fly_accept_encoding::Encoding; +pub use http_next::HttpNextError; pub use request_properties::DefaultHttpPropertyExtractor; pub use request_properties::HttpConnectionProperties; pub use request_properties::HttpListenProperties; pub use request_properties::HttpPropertyExtractor; pub use request_properties::HttpRequestProperties; +pub use service::UpgradeUnavailableError; +pub use websocket_upgrade::WebSocketUpgradeError; deno_core::extension!( deno_http, @@ -134,6 +135,38 @@ deno_core::extension!( esm = ["00_serve.ts", "01_http.js", "02_websocket.ts"], ); +#[derive(Debug, thiserror::Error)] +pub enum HttpError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), + #[error("{0}")] + HyperV014(#[source] Arc), + #[error("{0}")] + InvalidHeaderName(#[from] hyper_v014::header::InvalidHeaderName), + #[error("{0}")] + InvalidHeaderValue(#[from] hyper_v014::header::InvalidHeaderValue), + #[error("{0}")] + Http(#[from] hyper_v014::http::Error), + #[error("response headers already sent")] + ResponseHeadersAlreadySent, + #[error("connection closed while sending response")] + ConnectionClosedWhileSendingResponse, + #[error("already in use")] + AlreadyInUse, + #[error("{0}")] + Io(#[from] std::io::Error), + #[error("no response headers")] + NoResponseHeaders, + #[error("response already completed")] + ResponseAlreadyCompleted, + #[error("cannot upgrade because request body was used")] + UpgradeBodyUsed, + #[error(transparent)] + Other(deno_core::error::AnyError), +} + pub enum HttpSocketAddr { IpSocket(std::net::SocketAddr), #[cfg(unix)] @@ -216,7 +249,7 @@ impl HttpConnResource { String, String, )>, - AnyError, + HttpError, > { let fut = async { let (request_tx, request_rx) = oneshot::channel(); @@ -259,8 +292,8 @@ impl HttpConnResource { } /// A future that completes when this HTTP connection is closed or errors. - async fn closed(&self) -> Result<(), AnyError> { - self.closed_fut.clone().map_err(AnyError::from).await + async fn closed(&self) -> Result<(), HttpError> { + self.closed_fut.clone().map_err(HttpError::HyperV014).await } } @@ -280,14 +313,13 @@ pub fn http_create_conn_resource( io: S, addr: A, scheme: &'static str, -) -> Result +) -> ResourceId where S: AsyncRead + AsyncWrite + Unpin + Send + 'static, A: Into, { let conn = HttpConnResource::new(io, scheme, addr.into()); - let rid = state.resource_table.add(conn); - Ok(rid) + state.resource_table.add(conn) } /// An object that implements the `hyper::Service` trait, through which Hyper @@ -423,7 +455,9 @@ impl Resource for HttpStreamReadResource { // safely call `await` on it without creating a race condition. Some(_) => match body.as_mut().next().await.unwrap() { Ok(chunk) => assert!(chunk.is_empty()), - Err(err) => break Err(AnyError::from(err)), + Err(err) => { + break Err(HttpError::HyperV014(Arc::new(err)).into()) + } }, None => break Ok(BufView::empty()), } @@ -545,8 +579,12 @@ struct NextRequestResponse( async fn op_http_accept( state: Rc>, #[smi] rid: ResourceId, -) -> Result, AnyError> { - let conn = state.borrow().resource_table.get::(rid)?; +) -> Result, HttpError> { + let conn = state + .borrow() + .resource_table + .get::(rid) + .map_err(HttpError::Resource)?; match conn.accept().await { Ok(Some((read_stream, write_stream, method, url))) => { @@ -657,11 +695,12 @@ async fn op_http_write_headers( #[smi] status: u16, #[serde] headers: Vec<(ByteString, ByteString)>, #[serde] data: Option, -) -> Result<(), AnyError> { +) -> Result<(), HttpError> { let stream = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpError::Resource)?; // Track supported encoding let encoding = stream.accept_encoding; @@ -708,14 +747,14 @@ async fn op_http_write_headers( let mut old_wr = RcRef::map(&stream, |r| &r.wr).borrow_mut().await; let response_tx = match replace(&mut *old_wr, new_wr) { HttpResponseWriter::Headers(response_tx) => response_tx, - _ => return Err(http_error("response headers already sent")), + _ => return Err(HttpError::ResponseHeadersAlreadySent), }; match response_tx.send(body) { Ok(_) => Ok(()), Err(_) => { stream.conn.closed().await?; - Err(http_error("connection closed while sending response")) + Err(HttpError::ConnectionClosedWhileSendingResponse) } } } @@ -725,11 +764,14 @@ async fn op_http_write_headers( fn op_http_headers( state: &mut OpState, #[smi] rid: u32, -) -> Result, AnyError> { - let stream = state.resource_table.get::(rid)?; +) -> Result, HttpError> { + let stream = state + .resource_table + .get::(rid) + .map_err(HttpError::Resource)?; let rd = RcRef::map(&stream, |r| &r.rd) .try_borrow() - .ok_or_else(|| http_error("already in use"))?; + .ok_or(HttpError::AlreadyInUse)?; match &*rd { HttpRequestReader::Headers(request) => Ok(req_headers(request.headers())), HttpRequestReader::Body(headers, _) => Ok(req_headers(headers)), @@ -741,7 +783,7 @@ fn http_response( data: Option, compressing: bool, encoding: Encoding, -) -> Result<(HttpResponseWriter, hyper_v014::Body), AnyError> { +) -> Result<(HttpResponseWriter, hyper_v014::Body), HttpError> { // Gzip, after level 1, doesn't produce significant size difference. // This default matches nginx default gzip compression level (1): // https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level @@ -878,25 +920,34 @@ async fn op_http_write_resource( state: Rc>, #[smi] rid: ResourceId, #[smi] stream: ResourceId, -) -> Result<(), AnyError> { +) -> Result<(), HttpError> { let http_stream = state .borrow() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpError::Resource)?; let mut wr = RcRef::map(&http_stream, |r| &r.wr).borrow_mut().await; - let resource = state.borrow().resource_table.get_any(stream)?; + let resource = state + .borrow() + .resource_table + .get_any(stream) + .map_err(HttpError::Resource)?; loop { match *wr { HttpResponseWriter::Headers(_) => { - return Err(http_error("no response headers")) + return Err(HttpError::NoResponseHeaders) } HttpResponseWriter::Closed => { - return Err(http_error("response already completed")) + return Err(HttpError::ResponseAlreadyCompleted) } _ => {} }; - let view = resource.clone().read(64 * 1024).await?; // 64KB + let view = resource + .clone() + .read(64 * 1024) + .await + .map_err(HttpError::Other)?; // 64KB if view.is_empty() { break; } @@ -937,16 +988,17 @@ async fn op_http_write( state: Rc>, #[smi] rid: ResourceId, #[buffer] buf: JsBuffer, -) -> Result<(), AnyError> { +) -> Result<(), HttpError> { let stream = state .borrow() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpError::Resource)?; let mut wr = RcRef::map(&stream, |r| &r.wr).borrow_mut().await; match &mut *wr { - HttpResponseWriter::Headers(_) => Err(http_error("no response headers")), - HttpResponseWriter::Closed => Err(http_error("response already completed")), + HttpResponseWriter::Headers(_) => Err(HttpError::NoResponseHeaders), + HttpResponseWriter::Closed => Err(HttpError::ResponseAlreadyCompleted), HttpResponseWriter::Body { writer, .. } => { let mut result = writer.write_all(&buf).await; if result.is_ok() { @@ -961,7 +1013,7 @@ async fn op_http_write( stream.conn.closed().await?; // If there was no connection error, drop body_tx. *wr = HttpResponseWriter::Closed; - Err(http_error("response already completed")) + Err(HttpError::ResponseAlreadyCompleted) } } } @@ -975,7 +1027,7 @@ async fn op_http_write( stream.conn.closed().await?; // If there was no connection error, drop body_tx. *wr = HttpResponseWriter::Closed; - Err(http_error("response already completed")) + Err(HttpError::ResponseAlreadyCompleted) } } } @@ -989,11 +1041,12 @@ async fn op_http_write( async fn op_http_shutdown( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { +) -> Result<(), HttpError> { let stream = state .borrow() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpError::Resource)?; let mut wr = RcRef::map(&stream, |r| &r.wr).borrow_mut().await; let wr = take(&mut *wr); match wr { @@ -1022,14 +1075,12 @@ async fn op_http_shutdown( #[op2] #[string] -fn op_http_websocket_accept_header( - #[string] key: String, -) -> Result { +fn op_http_websocket_accept_header(#[string] key: String) -> String { let digest = ring::digest::digest( &ring::digest::SHA1_FOR_LEGACY_USE_ONLY, format!("{key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11").as_bytes(), ); - Ok(BASE64_STANDARD.encode(digest)) + BASE64_STANDARD.encode(digest) } #[op2(async)] @@ -1037,25 +1088,29 @@ fn op_http_websocket_accept_header( async fn op_http_upgrade_websocket( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let stream = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(HttpError::Resource)?; let mut rd = RcRef::map(&stream, |r| &r.rd).borrow_mut().await; let request = match &mut *rd { HttpRequestReader::Headers(request) => request, - _ => { - return Err(http_error("cannot upgrade because request body was used")) - } + _ => return Err(HttpError::UpgradeBodyUsed), }; - let (transport, bytes) = - extract_network_stream(hyper_v014::upgrade::on(request).await?); - let ws_rid = - ws_create_server_stream(&mut state.borrow_mut(), transport, bytes)?; - Ok(ws_rid) + let (transport, bytes) = extract_network_stream( + hyper_v014::upgrade::on(request) + .await + .map_err(|err| HttpError::HyperV014(Arc::new(err)))?, + ); + Ok(ws_create_server_stream( + &mut state.borrow_mut(), + transport, + bytes, + )) } // Needed so hyper can use non Send futures @@ -1082,10 +1137,6 @@ where } } -fn http_error(message: &'static str) -> AnyError { - custom_error("Http", message) -} - /// Filters out the ever-surprising 'shutdown ENOTCONN' errors. fn filter_enotconn( result: Result<(), hyper_v014::Error>, diff --git a/ext/http/request_body.rs b/ext/http/request_body.rs index 45df12457c..f1c3f358ea 100644 --- a/ext/http/request_body.rs +++ b/ext/http/request_body.rs @@ -1,9 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use bytes::Bytes; -use deno_core::error::AnyError; use deno_core::futures::stream::Peekable; use deno_core::futures::Stream; use deno_core::futures::StreamExt; +use deno_core::futures::TryFutureExt; use deno_core::AsyncRefCell; use deno_core::AsyncResult; use deno_core::BufView; @@ -22,7 +22,7 @@ use std::task::Poll; struct ReadFuture(Incoming); impl Stream for ReadFuture { - type Item = Result; + type Item = Result; fn poll_next( self: Pin<&mut Self>, @@ -37,13 +37,13 @@ impl Stream for ReadFuture { if let Ok(data) = frame.into_data() { // Ensure that we never yield an empty frame if !data.is_empty() { - break Poll::Ready(Some(Ok::<_, AnyError>(data))); + break Poll::Ready(Some(Ok(data))); } } // Loop again so we don't lose the waker continue; } - Some(Err(e)) => Poll::Ready(Some(Err(e.into()))), + Some(Err(e)) => Poll::Ready(Some(Err(e))), None => Poll::Ready(None), }; } @@ -58,7 +58,7 @@ impl HttpRequestBody { Self(AsyncRefCell::new(ReadFuture(body).peekable()), size_hint) } - async fn read(self: Rc, limit: usize) -> Result { + async fn read(self: Rc, limit: usize) -> Result { let peekable = RcRef::map(self, |this| &this.0); let mut peekable = peekable.borrow_mut().await; match Pin::new(&mut *peekable).peek_mut().await { @@ -82,7 +82,7 @@ impl Resource for HttpRequestBody { } fn read(self: Rc, limit: usize) -> AsyncResult { - Box::pin(HttpRequestBody::read(self, limit)) + Box::pin(HttpRequestBody::read(self, limit).map_err(Into::into)) } fn size_hint(&self) -> (u64, Option) { diff --git a/ext/http/request_properties.rs b/ext/http/request_properties.rs index 1422c7417d..39d35a79f1 100644 --- a/ext/http/request_properties.rs +++ b/ext/http/request_properties.rs @@ -34,8 +34,8 @@ pub struct HttpConnectionProperties { pub stream_type: NetworkStreamType, } -pub struct HttpRequestProperties { - pub authority: Option, +pub struct HttpRequestProperties<'a> { + pub authority: Option>, } /// Pluggable trait to determine listen, connection and request properties @@ -84,11 +84,11 @@ pub trait HttpPropertyExtractor { ) -> NetworkStream; /// Determines the request properties. - fn request_properties( - connection_properties: &HttpConnectionProperties, - uri: &Uri, - headers: &HeaderMap, - ) -> HttpRequestProperties; + fn request_properties<'a>( + connection_properties: &'a HttpConnectionProperties, + uri: &'a Uri, + headers: &'a HeaderMap, + ) -> HttpRequestProperties<'a>; } pub struct DefaultHttpPropertyExtractor {} @@ -180,18 +180,17 @@ impl HttpPropertyExtractor for DefaultHttpPropertyExtractor { } } - fn request_properties( - connection_properties: &HttpConnectionProperties, - uri: &Uri, - headers: &HeaderMap, - ) -> HttpRequestProperties { + fn request_properties<'a>( + connection_properties: &'a HttpConnectionProperties, + uri: &'a Uri, + headers: &'a HeaderMap, + ) -> HttpRequestProperties<'a> { let authority = req_host( uri, headers, connection_properties.stream_type, connection_properties.local_port.unwrap_or_default(), - ) - .map(|s| s.into_owned()); + ); HttpRequestProperties { authority } } diff --git a/ext/http/service.rs b/ext/http/service.rs index 787e9babf8..75f93d77c2 100644 --- a/ext/http/service.rs +++ b/ext/http/service.rs @@ -2,7 +2,6 @@ use crate::request_properties::HttpConnectionProperties; use crate::response_body::ResponseBytesInner; use crate::response_body::ResponseStreamResult; -use deno_core::error::AnyError; use deno_core::futures::ready; use deno_core::BufView; use deno_core::OpState; @@ -206,6 +205,10 @@ pub(crate) async fn handle_request( Ok(response) } +#[derive(Debug, thiserror::Error)] +#[error("upgrade unavailable")] +pub struct UpgradeUnavailableError; + struct HttpRecordInner { server_state: SignallingRc, request_info: HttpConnectionProperties, @@ -344,14 +347,14 @@ impl HttpRecord { } /// Perform the Hyper upgrade on this record. - pub fn upgrade(&self) -> Result { + pub fn upgrade(&self) -> Result { // Manually perform the upgrade. We're peeking into hyper's underlying machinery here a bit self .self_mut() .request_parts .extensions .remove::() - .ok_or_else(|| AnyError::msg("upgrade unavailable")) + .ok_or(UpgradeUnavailableError) } /// Take the Hyper body from this record. @@ -515,7 +518,7 @@ pub struct HttpRecordResponse(ManuallyDrop>); impl Body for HttpRecordResponse { type Data = BufView; - type Error = AnyError; + type Error = deno_core::error::AnyError; fn poll_frame( self: Pin<&mut Self>, @@ -640,7 +643,7 @@ mod tests { } #[tokio::test] - async fn test_handle_request() -> Result<(), AnyError> { + async fn test_handle_request() -> Result<(), deno_core::error::AnyError> { let (tx, mut rx) = tokio::sync::mpsc::channel(10); let server_state = HttpServerState::new(); let server_state_check = server_state.clone(); diff --git a/ext/http/websocket_upgrade.rs b/ext/http/websocket_upgrade.rs index 4dead767a3..af9504717e 100644 --- a/ext/http/websocket_upgrade.rs +++ b/ext/http/websocket_upgrade.rs @@ -4,7 +4,6 @@ use std::marker::PhantomData; use bytes::Bytes; use bytes::BytesMut; -use deno_core::error::AnyError; use httparse::Status; use hyper::header::HeaderName; use hyper::header::HeaderValue; @@ -13,12 +12,30 @@ use memmem::Searcher; use memmem::TwoWaySearcher; use once_cell::sync::OnceCell; -use crate::http_error; +#[derive(Debug, thiserror::Error)] +pub enum WebSocketUpgradeError { + #[error("invalid headers")] + InvalidHeaders, + #[error("{0}")] + HttpParse(#[from] httparse::Error), + #[error("{0}")] + Http(#[from] http::Error), + #[error("{0}")] + Utf8(#[from] std::str::Utf8Error), + #[error("{0}")] + InvalidHeaderName(#[from] http::header::InvalidHeaderName), + #[error("{0}")] + InvalidHeaderValue(#[from] http::header::InvalidHeaderValue), + #[error("invalid HTTP status line")] + InvalidHttpStatusLine, + #[error("attempted to write to completed upgrade buffer")] + UpgradeBufferAlreadyCompleted, +} /// Given a buffer that ends in `\n\n` or `\r\n\r\n`, returns a parsed [`Request`]. fn parse_response( header_bytes: &[u8], -) -> Result<(usize, Response), AnyError> { +) -> Result<(usize, Response), WebSocketUpgradeError> { let mut headers = [httparse::EMPTY_HEADER; 16]; let status = httparse::parse_headers(header_bytes, &mut headers)?; match status { @@ -32,7 +49,7 @@ fn parse_response( } Ok((index, resp)) } - _ => Err(http_error("invalid headers")), + _ => Err(WebSocketUpgradeError::InvalidHeaders), } } @@ -69,11 +86,14 @@ pub struct WebSocketUpgrade { impl WebSocketUpgrade { /// Ensures that the status line starts with "HTTP/1.1 101 " which matches all of the node.js /// WebSocket libraries that are known. We don't care about the trailing status text. - fn validate_status(&self, status: &[u8]) -> Result<(), AnyError> { + fn validate_status( + &self, + status: &[u8], + ) -> Result<(), WebSocketUpgradeError> { if status.starts_with(b"HTTP/1.1 101 ") { Ok(()) } else { - Err(http_error("invalid HTTP status line")) + Err(WebSocketUpgradeError::InvalidHttpStatusLine) } } @@ -82,7 +102,7 @@ impl WebSocketUpgrade { pub fn write( &mut self, bytes: &[u8], - ) -> Result, Bytes)>, AnyError> { + ) -> Result, Bytes)>, WebSocketUpgradeError> { use WebSocketUpgradeState::*; match self.state { @@ -142,9 +162,7 @@ impl WebSocketUpgrade { Ok(None) } } - Complete => { - Err(http_error("attempted to write to completed upgrade buffer")) - } + Complete => Err(WebSocketUpgradeError::UpgradeBufferAlreadyCompleted), } } } @@ -157,8 +175,8 @@ mod tests { type ExpectedResponseAndHead = Option<(Response, &'static [u8])>; fn assert_response( - result: Result, Bytes)>, AnyError>, - expected: Result, + result: Result, Bytes)>, WebSocketUpgradeError>, + expected: Result, chunk_info: Option<(usize, usize)>, ) { let formatted = format!("{result:?}"); @@ -189,8 +207,8 @@ mod tests { "Expected Ok(None), was {formatted}", ), Err(e) => assert_eq!( - e, - result.err().map(|e| format!("{e:?}")).unwrap_or_default(), + format!("{e:?}"), + format!("{:?}", result.unwrap_err()), "Expected error, was {formatted}", ), } @@ -198,7 +216,7 @@ mod tests { fn validate_upgrade_all_at_once( s: &str, - expected: Result, + expected: Result, ) { let mut upgrade = WebSocketUpgrade::default(); let res = upgrade.write(s.as_bytes()); @@ -209,7 +227,7 @@ mod tests { fn validate_upgrade_chunks( s: &str, size: usize, - expected: Result, + expected: Result, ) { let chunk_info = Some((s.as_bytes().len(), size)); let mut upgrade = WebSocketUpgrade::default(); @@ -226,7 +244,7 @@ mod tests { fn validate_upgrade( s: &str, - expected: fn() -> Result, + expected: fn() -> Result, ) { validate_upgrade_all_at_once(s, expected()); validate_upgrade_chunks(s, 1, expected()); @@ -315,7 +333,7 @@ mod tests { #[test] fn upgrade_invalid_status() { validate_upgrade("HTTP/1.1 200 OK\nConnection: Upgrade\n\n", || { - Err("invalid HTTP status line") + Err(WebSocketUpgradeError::InvalidHttpStatusLine) }); } @@ -327,7 +345,11 @@ mod tests { .join("\n"); validate_upgrade( &format!("HTTP/1.1 101 Switching Protocols\n{headers}\n\n"), - || Err("too many headers"), + || { + Err(WebSocketUpgradeError::HttpParse( + httparse::Error::TooManyHeaders, + )) + }, ); } } diff --git a/ext/io/12_io.js b/ext/io/12_io.js index 5c31c279b1..3cdcb113ba 100644 --- a/ext/io/12_io.js +++ b/ext/io/12_io.js @@ -4,7 +4,7 @@ // Documentation liberally lifted from them too. // Thank you! We love Go! <3 -import { core, internals, primordials } from "ext:core/mod.js"; +import { core, primordials } from "ext:core/mod.js"; import { op_set_raw } from "ext:core/ops"; const { Uint8Array, @@ -20,7 +20,6 @@ import { writableStreamForRid, } from "ext:deno_web/06_streams.js"; -const DEFAULT_BUFFER_SIZE = 32 * 1024; // Seek whence values. // https://golang.org/pkg/io/#pkg-constants const SeekMode = { @@ -33,79 +32,6 @@ const SeekMode = { End: 2, }; -async function copy( - src, - dst, - options, -) { - internals.warnOnDeprecatedApi( - "Deno.copy()", - new Error().stack, - "Use `copy()` from `https://jsr.io/@std/io/doc/copy/~` instead.", - ); - let n = 0; - const bufSize = options?.bufSize ?? DEFAULT_BUFFER_SIZE; - const b = new Uint8Array(bufSize); - let gotEOF = false; - while (gotEOF === false) { - const result = await src.read(b); - if (result === null) { - gotEOF = true; - } else { - let nwritten = 0; - while (nwritten < result) { - nwritten += await dst.write( - TypedArrayPrototypeSubarray(b, nwritten, result), - ); - } - n += nwritten; - } - } - return n; -} - -async function* iter( - r, - options, -) { - internals.warnOnDeprecatedApi( - "Deno.iter()", - new Error().stack, - "Use `ReadableStream` instead.", - ); - const bufSize = options?.bufSize ?? DEFAULT_BUFFER_SIZE; - const b = new Uint8Array(bufSize); - while (true) { - const result = await r.read(b); - if (result === null) { - break; - } - - yield TypedArrayPrototypeSubarray(b, 0, result); - } -} - -function* iterSync( - r, - options, -) { - internals.warnOnDeprecatedApi( - "Deno.iterSync()", - new Error().stack, - "Use `ReadableStream` instead.", - ); - const bufSize = options?.bufSize ?? DEFAULT_BUFFER_SIZE; - const b = new Uint8Array(bufSize); - while (true) { - const result = r.readSync(b); - if (result === null) { - break; - } - - yield TypedArrayPrototypeSubarray(b, 0, result); - } -} - function readSync(rid, buffer) { if (buffer.length === 0) return 0; const nread = core.readSync(rid, buffer); @@ -195,11 +121,6 @@ class Stdin { } get rid() { - internals.warnOnDeprecatedApi( - "Deno.stdin.rid", - new Error().stack, - "Use `Deno.stdin` instance methods instead.", - ); return this.#rid; } @@ -260,11 +181,6 @@ class Stdout { } get rid() { - internals.warnOnDeprecatedApi( - "Deno.stdout.rid", - new Error().stack, - "Use `Deno.stdout` instance methods instead.", - ); return this.#rid; } @@ -300,11 +216,6 @@ class Stderr { } get rid() { - internals.warnOnDeprecatedApi( - "Deno.stderr.rid", - new Error().stack, - "Use `Deno.stderr` instance methods instead.", - ); return this.#rid; } @@ -337,9 +248,6 @@ const stdout = new Stdout(); const stderr = new Stderr(); export { - copy, - iter, - iterSync, read, readAll, readAllSync, diff --git a/ext/io/Cargo.toml b/ext/io/Cargo.toml index 414bf0739d..f7ffe46bc3 100644 --- a/ext/io/Cargo.toml +++ b/ext/io/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_io" -version = "0.74.0" +version = "0.84.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/io/bi_pipe.rs b/ext/io/bi_pipe.rs index 04fff7b00b..3492e2f441 100644 --- a/ext/io/bi_pipe.rs +++ b/ext/io/bi_pipe.rs @@ -2,7 +2,6 @@ use std::rc::Rc; -use deno_core::error::AnyError; use deno_core::AsyncRefCell; use deno_core::AsyncResult; use deno_core::CancelHandle; @@ -11,11 +10,7 @@ use deno_core::RcRef; use tokio::io::AsyncReadExt; use tokio::io::AsyncWriteExt; -#[cfg(unix)] -pub type RawBiPipeHandle = std::os::fd::RawFd; - -#[cfg(windows)] -pub type RawBiPipeHandle = std::os::windows::io::RawHandle; +pub type RawBiPipeHandle = super::RawIoHandle; /// One end of a bidirectional pipe. This implements the /// `Resource` trait. @@ -75,13 +70,16 @@ impl BiPipeResource { pub async fn read( self: Rc, data: &mut [u8], - ) -> Result { + ) -> Result { let mut rd = RcRef::map(&self, |r| &r.read_half).borrow_mut().await; let cancel_handle = RcRef::map(&self, |r| &r.cancel); - Ok(rd.read(data).try_or_cancel(cancel_handle).await?) + rd.read(data).try_or_cancel(cancel_handle).await } - pub async fn write(self: Rc, data: &[u8]) -> Result { + pub async fn write( + self: Rc, + data: &[u8], + ) -> Result { let mut wr = RcRef::map(self, |r| &r.write_half).borrow_mut().await; let nwritten = wr.write(data).await?; wr.flush().await?; @@ -185,9 +183,10 @@ fn from_raw( ) -> Result<(BiPipeRead, BiPipeWrite), std::io::Error> { use std::os::fd::FromRawFd; // Safety: The fd is part of a pair of connected sockets - let unix_stream = tokio::net::UnixStream::from_std(unsafe { - std::os::unix::net::UnixStream::from_raw_fd(stream) - })?; + let unix_stream = + unsafe { std::os::unix::net::UnixStream::from_raw_fd(stream) }; + unix_stream.set_nonblocking(true)?; + let unix_stream = tokio::net::UnixStream::from_std(unix_stream)?; let (read, write) = unix_stream.into_split(); Ok((BiPipeRead { inner: read }, BiPipeWrite { inner: write })) } @@ -274,15 +273,15 @@ impl_async_write!(for BiPipe -> self.write_end); /// Creates both sides of a bidirectional pipe, returning the raw /// handles to the underlying OS resources. -pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError> -{ +pub fn bi_pipe_pair_raw( +) -> Result<(RawBiPipeHandle, RawBiPipeHandle), std::io::Error> { #[cfg(unix)] { // SockFlag is broken on macOS // https://github.com/nix-rust/nix/issues/861 let mut fds = [-1, -1]; #[cfg(not(target_os = "macos"))] - let flags = libc::SOCK_CLOEXEC | libc::SOCK_NONBLOCK; + let flags = libc::SOCK_CLOEXEC; #[cfg(target_os = "macos")] let flags = 0; @@ -297,19 +296,19 @@ pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError ) }; if ret != 0 { - return Err(std::io::Error::last_os_error().into()); + return Err(std::io::Error::last_os_error()); } if cfg!(target_os = "macos") { let fcntl = |fd: i32, flag: libc::c_int| -> Result<(), std::io::Error> { // SAFETY: libc call, fd is valid - let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) }; + let flags = unsafe { libc::fcntl(fd, libc::F_GETFD) }; if flags == -1 { return Err(fail(fds)); } // SAFETY: libc call, fd is valid - let ret = unsafe { libc::fcntl(fd, libc::F_SETFL, flags | flag) }; + let ret = unsafe { libc::fcntl(fd, libc::F_SETFD, flags | flag) }; if ret == -1 { return Err(fail(fds)); } @@ -325,13 +324,9 @@ pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError std::io::Error::last_os_error() } - // SOCK_NONBLOCK is not supported on macOS. - (fcntl)(fds[0], libc::O_NONBLOCK)?; - (fcntl)(fds[1], libc::O_NONBLOCK)?; - // SOCK_CLOEXEC is not supported on macOS. - (fcntl)(fds[0], libc::FD_CLOEXEC)?; - (fcntl)(fds[1], libc::FD_CLOEXEC)?; + fcntl(fds[0], libc::FD_CLOEXEC)?; + fcntl(fds[1], libc::FD_CLOEXEC)?; } let fd1 = fds[0]; @@ -393,7 +388,7 @@ pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError continue; } - return Err(err.into()); + return Err(err); } break (path, hd1); @@ -415,7 +410,7 @@ pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError 0, ); if hd2 == INVALID_HANDLE_VALUE { - return Err(io::Error::last_os_error().into()); + return Err(io::Error::last_os_error()); } // Will not block because we have create the pair. @@ -423,7 +418,7 @@ pub fn bi_pipe_pair_raw() -> Result<(RawBiPipeHandle, RawBiPipeHandle), AnyError let err = std::io::Error::last_os_error(); if err.raw_os_error() != Some(ERROR_PIPE_CONNECTED as i32) { CloseHandle(hd2); - return Err(err.into()); + return Err(err); } } diff --git a/ext/io/fs.rs b/ext/io/fs.rs index 88e4eee474..8854265209 100644 --- a/ext/io/fs.rs +++ b/ext/io/fs.rs @@ -1,15 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::borrow::Cow; +use std::fmt::Formatter; use std::io; use std::rc::Rc; use std::time::SystemTime; use std::time::UNIX_EPOCH; -use deno_core::error::custom_error; -use deno_core::error::not_supported; -use deno_core::error::resource_unavailable; -use deno_core::error::AnyError; use deno_core::BufMutView; use deno_core::BufView; use deno_core::OpState; @@ -22,16 +19,31 @@ pub enum FsError { Io(io::Error), FileBusy, NotSupported, - PermissionDenied(&'static str), + NotCapable(&'static str), } +impl std::fmt::Display for FsError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + FsError::Io(err) => std::fmt::Display::fmt(err, f), + FsError::FileBusy => f.write_str("file busy"), + FsError::NotSupported => f.write_str("not supported"), + FsError::NotCapable(err) => { + f.write_str(&format!("requires {err} access")) + } + } + } +} + +impl std::error::Error for FsError {} + impl FsError { pub fn kind(&self) -> io::ErrorKind { match self { Self::Io(err) => err.kind(), Self::FileBusy => io::ErrorKind::Other, Self::NotSupported => io::ErrorKind::Other, - Self::PermissionDenied(_) => io::ErrorKind::PermissionDenied, + Self::NotCapable(_) => io::ErrorKind::Other, } } @@ -40,7 +52,7 @@ impl FsError { FsError::Io(err) => err, FsError::FileBusy => io::Error::new(self.kind(), "file busy"), FsError::NotSupported => io::Error::new(self.kind(), "not supported"), - FsError::PermissionDenied(err) => { + FsError::NotCapable(err) => { io::Error::new(self.kind(), format!("requires {err} access")) } } @@ -59,19 +71,6 @@ impl From for FsError { } } -impl From for AnyError { - fn from(err: FsError) -> Self { - match err { - FsError::Io(err) => AnyError::from(err), - FsError::FileBusy => resource_unavailable(), - FsError::NotSupported => not_supported(), - FsError::PermissionDenied(err) => { - custom_error("PermissionDenied", format!("permission denied: {err}")) - } - } - } -} - impl From for FsError { fn from(err: JoinError) -> Self { if err.is_cancelled() { @@ -266,9 +265,9 @@ impl FileResource { state: &OpState, rid: ResourceId, f: F, - ) -> Result + ) -> Result where - F: FnOnce(Rc) -> Result, + F: FnOnce(Rc) -> Result, { let resource = state.resource_table.get::(rid)?; f(resource) @@ -277,7 +276,7 @@ impl FileResource { pub fn get_file( state: &OpState, rid: ResourceId, - ) -> Result, AnyError> { + ) -> Result, deno_core::error::AnyError> { let resource = state.resource_table.get::(rid)?; Ok(resource.file()) } @@ -286,9 +285,9 @@ impl FileResource { state: &OpState, rid: ResourceId, f: F, - ) -> Result + ) -> Result where - F: FnOnce(Rc) -> Result, + F: FnOnce(Rc) -> Result, { Self::with_resource(state, rid, |r| f(r.file.clone())) } @@ -303,10 +302,7 @@ impl deno_core::Resource for FileResource { Cow::Borrowed(&self.name) } - fn read( - self: Rc, - limit: usize, - ) -> deno_core::AsyncResult { + fn read(self: Rc, limit: usize) -> deno_core::AsyncResult { Box::pin(async move { self .file @@ -319,8 +315,8 @@ impl deno_core::Resource for FileResource { fn read_byob( self: Rc, - buf: deno_core::BufMutView, - ) -> deno_core::AsyncResult<(usize, deno_core::BufMutView)> { + buf: BufMutView, + ) -> deno_core::AsyncResult<(usize, BufMutView)> { Box::pin(async move { self .file @@ -333,17 +329,14 @@ impl deno_core::Resource for FileResource { fn write( self: Rc, - buf: deno_core::BufView, + buf: BufView, ) -> deno_core::AsyncResult { Box::pin(async move { self.file.clone().write(buf).await.map_err(|err| err.into()) }) } - fn write_all( - self: Rc, - buf: deno_core::BufView, - ) -> deno_core::AsyncResult<()> { + fn write_all(self: Rc, buf: BufView) -> deno_core::AsyncResult<()> { Box::pin(async move { self .file diff --git a/ext/io/lib.rs b/ext/io/lib.rs index 47921bcee4..5d183aa464 100644 --- a/ext/io/lib.rs +++ b/ext/io/lib.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::unsync::spawn_blocking; use deno_core::unsync::TaskQueue; @@ -48,6 +47,7 @@ use winapi::um::processenv::GetStdHandle; #[cfg(windows)] use winapi::um::winbase; +use deno_core::futures::TryFutureExt; #[cfg(windows)] use parking_lot::Condvar; #[cfg(windows)] @@ -67,6 +67,7 @@ pub use pipe::AsyncPipeRead; pub use pipe::AsyncPipeWrite; pub use pipe::PipeRead; pub use pipe::PipeWrite; +pub use pipe::RawPipeHandle; pub use bi_pipe::bi_pipe_pair_raw; pub use bi_pipe::BiPipe; @@ -75,6 +76,112 @@ pub use bi_pipe::BiPipeResource; pub use bi_pipe::BiPipeWrite; pub use bi_pipe::RawBiPipeHandle; +/// Abstraction over `AsRawFd` (unix) and `AsRawHandle` (windows) +pub trait AsRawIoHandle { + fn as_raw_io_handle(&self) -> RawIoHandle; +} + +#[cfg(unix)] +impl AsRawIoHandle for T +where + T: std::os::unix::io::AsRawFd, +{ + fn as_raw_io_handle(&self) -> RawIoHandle { + self.as_raw_fd() + } +} + +#[cfg(windows)] +impl AsRawIoHandle for T +where + T: std::os::windows::io::AsRawHandle, +{ + fn as_raw_io_handle(&self) -> RawIoHandle { + self.as_raw_handle() + } +} + +/// Abstraction over `IntoRawFd` (unix) and `IntoRawHandle` (windows) +pub trait IntoRawIoHandle { + fn into_raw_io_handle(self) -> RawIoHandle; +} + +#[cfg(unix)] +impl IntoRawIoHandle for T +where + T: std::os::unix::io::IntoRawFd, +{ + fn into_raw_io_handle(self) -> RawIoHandle { + self.into_raw_fd() + } +} + +#[cfg(windows)] +impl IntoRawIoHandle for T +where + T: std::os::windows::io::IntoRawHandle, +{ + fn into_raw_io_handle(self) -> RawIoHandle { + self.into_raw_handle() + } +} + +/// Abstraction over `FromRawFd` (unix) and `FromRawHandle` (windows) +pub trait FromRawIoHandle: Sized { + /// Constructs a type from a raw io handle (fd/HANDLE). + /// + /// # Safety + /// + /// Refer to the standard library docs ([unix](https://doc.rust-lang.org/stable/std/os/windows/io/trait.FromRawHandle.html#tymethod.from_raw_handle)) ([windows](https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd)) + /// + unsafe fn from_raw_io_handle(handle: RawIoHandle) -> Self; +} + +#[cfg(unix)] +impl FromRawIoHandle for T +where + T: std::os::unix::io::FromRawFd, +{ + unsafe fn from_raw_io_handle(fd: RawIoHandle) -> T { + // SAFETY: upheld by caller + unsafe { T::from_raw_fd(fd) } + } +} + +#[cfg(windows)] +impl FromRawIoHandle for T +where + T: std::os::windows::io::FromRawHandle, +{ + unsafe fn from_raw_io_handle(fd: RawIoHandle) -> T { + // SAFETY: upheld by caller + unsafe { T::from_raw_handle(fd) } + } +} + +#[cfg(unix)] +pub type RawIoHandle = std::os::fd::RawFd; + +#[cfg(windows)] +pub type RawIoHandle = std::os::windows::io::RawHandle; + +pub fn close_raw_handle(handle: RawIoHandle) { + #[cfg(unix)] + { + // SAFETY: libc call + unsafe { + libc::close(handle); + } + } + #[cfg(windows)] + { + // SAFETY: win32 call + unsafe { + windows_sys::Win32::Foundation::CloseHandle(handle as _); + } + } +} + // Store the stdio fd/handles in global statics in order to keep them // alive for the duration of the application since the last handle/fd // being dropped will close the corresponding pipe. @@ -241,13 +348,13 @@ where RcRef::map(self, |r| &r.stream).borrow_mut() } - async fn write(self: Rc, data: &[u8]) -> Result { + async fn write(self: Rc, data: &[u8]) -> Result { let mut stream = self.borrow_mut().await; let nwritten = stream.write(data).await?; Ok(nwritten) } - async fn shutdown(self: Rc) -> Result<(), AnyError> { + async fn shutdown(self: Rc) -> Result<(), io::Error> { let mut stream = self.borrow_mut().await; stream.shutdown().await?; Ok(()) @@ -289,7 +396,7 @@ where self.cancel_handle.cancel() } - async fn read(self: Rc, data: &mut [u8]) -> Result { + async fn read(self: Rc, data: &mut [u8]) -> Result { let mut rd = self.borrow_mut().await; let nread = rd.read(data).try_or_cancel(self.cancel_handle()).await?; Ok(nread) @@ -310,7 +417,7 @@ impl Resource for ChildStdinResource { deno_core::impl_writable!(); fn shutdown(self: Rc) -> AsyncResult<()> { - Box::pin(self.shutdown()) + Box::pin(self.shutdown().map_err(|e| e.into())) } } @@ -903,7 +1010,7 @@ pub fn op_print( state: &mut OpState, #[string] msg: &str, is_err: bool, -) -> Result<(), AnyError> { +) -> Result<(), deno_core::error::AnyError> { let rid = if is_err { 2 } else { 1 }; FileResource::with_file(state, rid, move |file| { Ok(file.write_all_sync(msg.as_bytes())?) diff --git a/ext/io/pipe.rs b/ext/io/pipe.rs index 70788f7520..e0e019e277 100644 --- a/ext/io/pipe.rs +++ b/ext/io/pipe.rs @@ -3,6 +3,8 @@ use std::io; use std::pin::Pin; use std::process::Stdio; +pub type RawPipeHandle = super::RawIoHandle; + // The synchronous read end of a unidirectional pipe. pub struct PipeRead { file: std::fs::File, diff --git a/ext/kv/01_db.ts b/ext/kv/01_db.ts index 9aa2036dd5..c644ff7121 100644 --- a/ext/kv/01_db.ts +++ b/ext/kv/01_db.ts @@ -60,13 +60,15 @@ const maxQueueDelay = 30 * 24 * 60 * 60 * 1000; function validateQueueDelay(delay: number) { if (delay < 0) { - throw new TypeError("delay cannot be negative"); + throw new TypeError(`Delay must be >= 0: received ${delay}`); } if (delay > maxQueueDelay) { - throw new TypeError("delay cannot be greater than 30 days"); + throw new TypeError( + `Delay cannot be greater than 30 days: received ${delay}`, + ); } if (NumberIsNaN(delay)) { - throw new TypeError("delay cannot be NaN"); + throw new TypeError("Delay cannot be NaN"); } } @@ -75,7 +77,7 @@ const maxQueueBackoffInterval = 60 * 60 * 1000; function validateBackoffSchedule(backoffSchedule: number[]) { if (backoffSchedule.length > maxQueueBackoffIntervals) { - throw new TypeError("invalid backoffSchedule"); + throw new TypeError("Invalid backoffSchedule"); } for (let i = 0; i < backoffSchedule.length; ++i) { const interval = backoffSchedule[i]; @@ -83,7 +85,7 @@ function validateBackoffSchedule(backoffSchedule: number[]) { interval < 0 || interval > maxQueueBackoffInterval || NumberIsNaN(interval) ) { - throw new TypeError("invalid backoffSchedule"); + throw new TypeError("Invalid backoffSchedule"); } } } @@ -115,7 +117,7 @@ class Kv { constructor(rid: number = undefined, symbol: symbol = undefined) { if (kvSymbol !== symbol) { throw new TypeError( - "Deno.Kv can not be constructed, use Deno.openKv instead.", + "Deno.Kv can not be constructed: use Deno.openKv instead", ); } this.#rid = rid; @@ -213,7 +215,7 @@ class Kv { } = { __proto__: null }, ): KvListIterator { if (options.limit !== undefined && options.limit <= 0) { - throw new Error("limit must be positive"); + throw new Error(`Limit must be positive: received ${options.limit}`); } let batchSize = options.batchSize ?? (options.limit ?? 100); @@ -291,7 +293,7 @@ class Kv { handler: (message: unknown) => Promise | void, ): Promise { if (this.#isClosed) { - throw new Error("already closed"); + throw new Error("Queue already closed"); } const finishMessageOps = new SafeMap>(); while (true) { @@ -318,6 +320,7 @@ class Kv { const _res = isPromise(result) ? (await result) : result; success = true; } catch (error) { + // deno-lint-ignore no-console console.error("Exception in queue handler", error); } finally { const promise: Promise = op_kv_finish_dequeued_message( @@ -367,7 +370,7 @@ class Kv { if (updates[i] === "unchanged") { if (lastEntries[i] === undefined) { throw new Error( - "watch: invalid unchanged update (internal error)", + "'watch': invalid unchanged update (internal error)", ); } continue; @@ -448,7 +451,7 @@ class AtomicOperation { case "delete": type = "delete"; if (mutation.value) { - throw new TypeError("invalid mutation 'delete' with value"); + throw new TypeError("Invalid mutation 'delete' with value"); } break; case "set": @@ -461,7 +464,7 @@ class AtomicOperation { case "max": type = mutation.type; if (!ObjectHasOwn(mutation, "value")) { - throw new TypeError(`invalid mutation '${type}' without value`); + throw new TypeError(`Invalid mutation '${type}' without value`); } value = serializeValue(mutation.value); break; @@ -558,7 +561,7 @@ class AtomicOperation { then() { throw new TypeError( - "`Deno.AtomicOperation` is not a promise. Did you forget to call `commit()`?", + "'Deno.AtomicOperation' is not a promise: did you forget to call 'commit()'", ); } } @@ -571,13 +574,15 @@ class KvU64 { constructor(value: bigint) { if (typeof value !== "bigint") { - throw new TypeError("value must be a bigint"); + throw new TypeError(`Value must be a bigint: received ${typeof value}`); } if (value < MIN_U64) { - throw new RangeError("value must be a positive bigint"); + throw new RangeError( + `Value must be a positive bigint: received ${value}`, + ); } if (value > MAX_U64) { - throw new RangeError("value must fit in a 64-bit unsigned integer"); + throw new RangeError("Value must fit in a 64-bit unsigned integer"); } this.value = value; ObjectFreeze(this); @@ -708,7 +713,7 @@ class KvListIterator extends AsyncIterator if (prefix) { if (start && end) { throw new TypeError( - "Selector can not specify both 'start' and 'end' key when specifying 'prefix'.", + "Selector can not specify both 'start' and 'end' key when specifying 'prefix'", ); } if (start) { @@ -723,7 +728,7 @@ class KvListIterator extends AsyncIterator this.#selector = { start, end }; } else { throw new TypeError( - "Selector must specify either 'prefix' or both 'start' and 'end' key.", + "Selector must specify either 'prefix' or both 'start' and 'end' key", ); } } diff --git a/ext/kv/Cargo.toml b/ext/kv/Cargo.toml index 4ac2becd9f..a4e35193d5 100644 --- a/ext/kv/Cargo.toml +++ b/ext/kv/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_kv" -version = "0.72.0" +version = "0.82.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,7 +21,7 @@ bytes.workspace = true chrono = { workspace = true, features = ["now"] } deno_core.workspace = true deno_fetch.workspace = true -deno_node.workspace = true +deno_path_util.workspace = true deno_permissions.workspace = true deno_tls.workspace = true denokv_proto.workspace = true @@ -36,6 +36,7 @@ prost.workspace = true rand.workspace = true rusqlite.workspace = true serde.workspace = true +thiserror.workspace = true url.workspace = true [build-dependencies] diff --git a/ext/kv/config.rs b/ext/kv/config.rs new file mode 100644 index 0000000000..6e2e2c3a1f --- /dev/null +++ b/ext/kv/config.rs @@ -0,0 +1,136 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +pub struct KvConfig { + pub(crate) max_write_key_size_bytes: usize, + pub(crate) max_read_key_size_bytes: usize, + pub(crate) max_value_size_bytes: usize, + pub(crate) max_read_ranges: usize, + pub(crate) max_read_entries: usize, + pub(crate) max_checks: usize, + pub(crate) max_mutations: usize, + pub(crate) max_watched_keys: usize, + pub(crate) max_total_mutation_size_bytes: usize, + pub(crate) max_total_key_size_bytes: usize, +} + +impl KvConfig { + pub fn builder() -> KvConfigBuilder { + KvConfigBuilder::default() + } +} + +#[derive(Default)] +pub struct KvConfigBuilder { + max_write_key_size_bytes: Option, + max_value_size_bytes: Option, + max_read_ranges: Option, + max_read_entries: Option, + max_checks: Option, + max_mutations: Option, + max_watched_keys: Option, + max_total_mutation_size_bytes: Option, + max_total_key_size_bytes: Option, +} + +impl KvConfigBuilder { + pub fn new() -> Self { + Self::default() + } + + pub fn max_write_key_size_bytes( + &mut self, + max_write_key_size_bytes: usize, + ) -> &mut Self { + self.max_write_key_size_bytes = Some(max_write_key_size_bytes); + self + } + + pub fn max_value_size_bytes( + &mut self, + max_value_size_bytes: usize, + ) -> &mut Self { + self.max_value_size_bytes = Some(max_value_size_bytes); + self + } + + pub fn max_read_ranges(&mut self, max_read_ranges: usize) -> &mut Self { + self.max_read_ranges = Some(max_read_ranges); + self + } + + pub fn max_read_entries(&mut self, max_read_entries: usize) -> &mut Self { + self.max_read_entries = Some(max_read_entries); + self + } + + pub fn max_checks(&mut self, max_checks: usize) -> &mut Self { + self.max_checks = Some(max_checks); + self + } + + pub fn max_mutations(&mut self, max_mutations: usize) -> &mut Self { + self.max_mutations = Some(max_mutations); + self + } + + pub fn max_watched_keys(&mut self, max_watched_keys: usize) -> &mut Self { + self.max_watched_keys = Some(max_watched_keys); + self + } + + pub fn max_total_mutation_size_bytes( + &mut self, + max_total_mutation_size_bytes: usize, + ) -> &mut Self { + self.max_total_mutation_size_bytes = Some(max_total_mutation_size_bytes); + self + } + + pub fn max_total_key_size_bytes( + &mut self, + max_total_key_size_bytes: usize, + ) -> &mut Self { + self.max_total_key_size_bytes = Some(max_total_key_size_bytes); + self + } + + pub fn build(&self) -> KvConfig { + const MAX_WRITE_KEY_SIZE_BYTES: usize = 2048; + // range selectors can contain 0x00 or 0xff suffixes + const MAX_READ_KEY_SIZE_BYTES: usize = MAX_WRITE_KEY_SIZE_BYTES + 1; + const MAX_VALUE_SIZE_BYTES: usize = 65536; + const MAX_READ_RANGES: usize = 10; + const MAX_READ_ENTRIES: usize = 1000; + const MAX_CHECKS: usize = 100; + const MAX_MUTATIONS: usize = 1000; + const MAX_WATCHED_KEYS: usize = 10; + const MAX_TOTAL_MUTATION_SIZE_BYTES: usize = 800 * 1024; + const MAX_TOTAL_KEY_SIZE_BYTES: usize = 80 * 1024; + + KvConfig { + max_write_key_size_bytes: self + .max_write_key_size_bytes + .unwrap_or(MAX_WRITE_KEY_SIZE_BYTES), + max_read_key_size_bytes: self + .max_write_key_size_bytes + .map(|x| + // range selectors can contain 0x00 or 0xff suffixes + x + 1) + .unwrap_or(MAX_READ_KEY_SIZE_BYTES), + max_value_size_bytes: self + .max_value_size_bytes + .unwrap_or(MAX_VALUE_SIZE_BYTES), + max_read_ranges: self.max_read_ranges.unwrap_or(MAX_READ_RANGES), + max_read_entries: self.max_read_entries.unwrap_or(MAX_READ_ENTRIES), + max_checks: self.max_checks.unwrap_or(MAX_CHECKS), + max_mutations: self.max_mutations.unwrap_or(MAX_MUTATIONS), + max_watched_keys: self.max_watched_keys.unwrap_or(MAX_WATCHED_KEYS), + max_total_mutation_size_bytes: self + .max_total_mutation_size_bytes + .unwrap_or(MAX_TOTAL_MUTATION_SIZE_BYTES), + max_total_key_size_bytes: self + .max_total_key_size_bytes + .unwrap_or(MAX_TOTAL_KEY_SIZE_BYTES), + } + } +} diff --git a/ext/kv/lib.rs b/ext/kv/lib.rs index 8a57d610dc..a4ccfe3d63 100644 --- a/ext/kv/lib.rs +++ b/ext/kv/lib.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +pub mod config; pub mod dynamic; mod interface; pub mod remote; @@ -11,15 +12,11 @@ use std::num::NonZeroU32; use std::rc::Rc; use std::time::Duration; -use anyhow::bail; use base64::prelude::BASE64_URL_SAFE; use base64::Engine; use chrono::DateTime; use chrono::Utc; -use deno_core::anyhow::Context; use deno_core::error::get_custom_error_class; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures::StreamExt; use deno_core::op2; use deno_core::serde_v8::AnyValue; @@ -56,22 +53,11 @@ use log::debug; use serde::Deserialize; use serde::Serialize; +pub use crate::config::*; pub use crate::interface::*; pub const UNSTABLE_FEATURE_NAME: &str = "kv"; -const MAX_WRITE_KEY_SIZE_BYTES: usize = 2048; -// range selectors can contain 0x00 or 0xff suffixes -const MAX_READ_KEY_SIZE_BYTES: usize = MAX_WRITE_KEY_SIZE_BYTES + 1; -const MAX_VALUE_SIZE_BYTES: usize = 65536; -const MAX_READ_RANGES: usize = 10; -const MAX_READ_ENTRIES: usize = 1000; -const MAX_CHECKS: usize = 100; -const MAX_MUTATIONS: usize = 1000; -const MAX_WATCHED_KEYS: usize = 10; -const MAX_TOTAL_MUTATION_SIZE_BYTES: usize = 800 * 1024; -const MAX_TOTAL_KEY_SIZE_BYTES: usize = 80 * 1024; - deno_core::extension!(deno_kv, deps = [ deno_console, deno_web ], parameters = [ DBH: DatabaseHandler ], @@ -88,8 +74,10 @@ deno_core::extension!(deno_kv, esm = [ "01_db.ts" ], options = { handler: DBH, + config: KvConfig, }, state = |state, options| { + state.put(Rc::new(options.config)); state.put(Rc::new(options.handler)); } ); @@ -126,25 +114,86 @@ impl Resource for DatabaseWatcherResource { } } +#[derive(Debug, thiserror::Error)] +pub enum KvError { + #[error(transparent)] + DatabaseHandler(deno_core::error::AnyError), + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("Too many ranges (max {0})")] + TooManyRanges(usize), + #[error("Too many entries (max {0})")] + TooManyEntries(usize), + #[error("Too many checks (max {0})")] + TooManyChecks(usize), + #[error("Too many mutations (max {0})")] + TooManyMutations(usize), + #[error("Too many keys (max {0})")] + TooManyKeys(usize), + #[error("limit must be greater than 0")] + InvalidLimit, + #[error("Invalid boundary key")] + InvalidBoundaryKey, + #[error("Key too large for read (max {0} bytes)")] + KeyTooLargeToRead(usize), + #[error("Key too large for write (max {0} bytes)")] + KeyTooLargeToWrite(usize), + #[error("Total mutation size too large (max {0} bytes)")] + TotalMutationTooLarge(usize), + #[error("Total key size too large (max {0} bytes)")] + TotalKeyTooLarge(usize), + #[error(transparent)] + Kv(deno_core::error::AnyError), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("Queue message not found")] + QueueMessageNotFound, + #[error("Start key is not in the keyspace defined by prefix")] + StartKeyNotInKeyspace, + #[error("End key is not in the keyspace defined by prefix")] + EndKeyNotInKeyspace, + #[error("Start key is greater than end key")] + StartKeyGreaterThanEndKey, + #[error("Invalid check")] + InvalidCheck(#[source] KvCheckError), + #[error("Invalid mutation")] + InvalidMutation(#[source] KvMutationError), + #[error("Invalid enqueue")] + InvalidEnqueue(#[source] std::io::Error), + #[error("key cannot be empty")] + EmptyKey, // TypeError + #[error("Value too large (max {0} bytes)")] + ValueTooLarge(usize), // TypeError + #[error("enqueue payload too large (max {0} bytes)")] + EnqueuePayloadTooLarge(usize), // TypeError + #[error("invalid cursor")] + InvalidCursor, + #[error("cursor out of bounds")] + CursorOutOfBounds, + #[error("Invalid range")] + InvalidRange, +} + #[op2(async)] #[smi] async fn op_kv_database_open( state: Rc>, #[string] path: Option, -) -> Result +) -> Result where DBH: DatabaseHandler + 'static, { let handler = { let state = state.borrow(); - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` state .feature_checker - .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, "Deno.openKv"); + .check_or_exit(UNSTABLE_FEATURE_NAME, "Deno.openKv"); state.borrow::>().clone() }; - let db = handler.open(state.clone(), path).await?; + let db = handler + .open(state.clone(), path) + .await + .map_err(KvError::DatabaseHandler)?; let rid = state.borrow_mut().resource_table.add(DatabaseResource { db, cancel_handle: CancelHandle::new_rc(), @@ -194,8 +243,8 @@ enum ToV8Value { } impl TryFrom for KvValue { - type Error = AnyError; - fn try_from(value: FromV8Value) -> Result { + type Error = num_bigint::TryFromBigIntError; + fn try_from(value: FromV8Value) -> Result { Ok(match value { FromV8Value::V8(buf) => KvValue::V8(buf.to_vec()), FromV8Value::Bytes(buf) => KvValue::Bytes(buf.to_vec()), @@ -224,8 +273,8 @@ struct ToV8KvEntry { } impl TryFrom for ToV8KvEntry { - type Error = AnyError; - fn try_from(entry: KvEntry) -> Result { + type Error = std::io::Error; + fn try_from(entry: KvEntry) -> Result { Ok(ToV8KvEntry { key: decode_key(&entry.key)? .0 @@ -271,22 +320,26 @@ async fn op_kv_snapshot_read( #[smi] rid: ResourceId, #[serde] ranges: Vec, #[serde] consistency: V8Consistency, -) -> Result>, AnyError> +) -> Result>, KvError> where DBH: DatabaseHandler + 'static, { let db = { let state = state.borrow(); - let resource = - state.resource_table.get::>(rid)?; + let resource = state + .resource_table + .get::>(rid) + .map_err(KvError::Resource)?; resource.db.clone() }; - if ranges.len() > MAX_READ_RANGES { - return Err(type_error(format!( - "too many ranges (max {})", - MAX_READ_RANGES - ))); + let config = { + let state = state.borrow(); + state.borrow::>().clone() + }; + + if ranges.len() > config.max_read_ranges { + return Err(KvError::TooManyRanges(config.max_read_ranges)); } let mut total_entries = 0usize; @@ -298,40 +351,39 @@ where let (start, end) = decode_selector_and_cursor(&selector, reverse, cursor.as_ref())?; - check_read_key_size(&start)?; - check_read_key_size(&end)?; + check_read_key_size(&start, &config)?; + check_read_key_size(&end, &config)?; total_entries += limit as usize; Ok(ReadRange { start, end, - limit: NonZeroU32::new(limit) - .with_context(|| "limit must be greater than 0")?, + limit: NonZeroU32::new(limit).ok_or(KvError::InvalidLimit)?, reverse, }) }) - .collect::, AnyError>>()?; + .collect::, KvError>>()?; - if total_entries > MAX_READ_ENTRIES { - return Err(type_error(format!( - "too many entries (max {})", - MAX_READ_ENTRIES - ))); + if total_entries > config.max_read_entries { + return Err(KvError::TooManyEntries(config.max_read_entries)); } let opts = SnapshotReadOptions { consistency: consistency.into(), }; - let output_ranges = db.snapshot_read(read_ranges, opts).await?; + let output_ranges = db + .snapshot_read(read_ranges, opts) + .await + .map_err(KvError::Kv)?; let output_ranges = output_ranges .into_iter() .map(|x| { x.entries .into_iter() .map(TryInto::try_into) - .collect::, AnyError>>() + .collect::, std::io::Error>>() }) - .collect::, AnyError>>()?; + .collect::, std::io::Error>>()?; Ok(output_ranges) } @@ -350,7 +402,7 @@ impl Resource for QueueMessageResource { async fn op_kv_dequeue_next_message( state: Rc>, #[smi] rid: ResourceId, -) -> Result, AnyError> +) -> Result, KvError> where DBH: DatabaseHandler + 'static, { @@ -363,17 +415,19 @@ where if get_custom_error_class(&err) == Some("BadResource") { return Ok(None); } else { - return Err(err); + return Err(KvError::Resource(err)); } } }; resource.db.clone() }; - let Some(mut handle) = db.dequeue_next_message().await? else { + let Some(mut handle) = + db.dequeue_next_message().await.map_err(KvError::Kv)? + else { return Ok(None); }; - let payload = handle.take_payload().await?.into(); + let payload = handle.take_payload().await.map_err(KvError::Kv)?.into(); let handle_rid = { let mut state = state.borrow_mut(); state.resource_table.add(QueueMessageResource { handle }) @@ -387,17 +441,18 @@ fn op_kv_watch( state: &mut OpState, #[smi] rid: ResourceId, #[serde] keys: Vec, -) -> Result +) -> Result where DBH: DatabaseHandler + 'static, { - let resource = state.resource_table.get::>(rid)?; + let resource = state + .resource_table + .get::>(rid) + .map_err(KvError::Resource)?; + let config = state.borrow::>().clone(); - if keys.len() > MAX_WATCHED_KEYS { - return Err(type_error(format!( - "too many keys (max {})", - MAX_WATCHED_KEYS - ))); + if keys.len() > config.max_watched_keys { + return Err(KvError::TooManyKeys(config.max_watched_keys)); } let keys: Vec> = keys @@ -406,7 +461,7 @@ where .collect::>()?; for k in &keys { - check_read_key_size(k)?; + check_read_key_size(k, &config)?; } let stream = resource.db.watch(keys); @@ -432,10 +487,13 @@ enum WatchEntry { async fn op_kv_watch_next( state: Rc>, #[smi] rid: ResourceId, -) -> Result>, AnyError> { +) -> Result>, KvError> { let resource = { let state = state.borrow(); - let resource = state.resource_table.get::(rid)?; + let resource = state + .resource_table + .get::(rid) + .map_err(KvError::Resource)?; resource.clone() }; @@ -461,7 +519,7 @@ async fn op_kv_watch_next( return Ok(None); }; - let entries = res?; + let entries = res.map_err(KvError::Kv)?; let entries = entries .into_iter() .map(|entry| { @@ -472,7 +530,7 @@ async fn op_kv_watch_next( WatchKeyOutput::Unchanged => WatchEntry::Unchanged, }) }) - .collect::>()?; + .collect::>()?; Ok(Some(entries)) } @@ -482,7 +540,7 @@ async fn op_kv_finish_dequeued_message( state: Rc>, #[smi] handle_rid: ResourceId, success: bool, -) -> Result<(), AnyError> +) -> Result<(), KvError> where DBH: DatabaseHandler + 'static, { @@ -491,9 +549,9 @@ where let handle = state .resource_table .take::::DB as Database>::QMH>>(handle_rid) - .map_err(|_| type_error("Queue message not found"))?; + .map_err(|_| KvError::QueueMessageNotFound)?; Rc::try_unwrap(handle) - .map_err(|_| type_error("Queue message not found"))? + .map_err(|_| KvError::QueueMessageNotFound)? .handle }; // if we fail to finish the message, there is not much we can do and the @@ -504,32 +562,52 @@ where Ok(()) } +#[derive(Debug, thiserror::Error)] +pub enum KvCheckError { + #[error("invalid versionstamp")] + InvalidVersionstamp, + #[error(transparent)] + Io(std::io::Error), +} + type V8KvCheck = (KvKey, Option); -fn check_from_v8(value: V8KvCheck) -> Result { +fn check_from_v8(value: V8KvCheck) -> Result { let versionstamp = match value.1 { Some(data) => { let mut out = [0u8; 10]; if data.len() != out.len() * 2 { - bail!(type_error("invalid versionstamp")); + return Err(KvCheckError::InvalidVersionstamp); } faster_hex::hex_decode(&data, &mut out) - .map_err(|_| type_error("invalid versionstamp"))?; + .map_err(|_| KvCheckError::InvalidVersionstamp)?; Some(out) } None => None, }; Ok(Check { - key: encode_v8_key(value.0)?, + key: encode_v8_key(value.0).map_err(KvCheckError::Io)?, versionstamp, }) } +#[derive(Debug, thiserror::Error)] +pub enum KvMutationError { + #[error(transparent)] + BigInt(#[from] num_bigint::TryFromBigIntError), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("Invalid mutation '{0}' with value")] + InvalidMutationWithValue(String), + #[error("Invalid mutation '{0}' without value")] + InvalidMutationWithoutValue(String), +} + type V8KvMutation = (KvKey, String, Option, Option); fn mutation_from_v8( (value, current_timstamp): (V8KvMutation, DateTime), -) -> Result { +) -> Result { let key = encode_v8_key(value.0)?; let kind = match (value.1.as_str(), value.2) { ("set", Some(value)) => MutationKind::Set(value.try_into()?), @@ -546,10 +624,10 @@ fn mutation_from_v8( MutationKind::SetSuffixVersionstampedKey(value.try_into()?) } (op, Some(_)) => { - return Err(type_error(format!("invalid mutation '{op}' with value"))) + return Err(KvMutationError::InvalidMutationWithValue(op.to_string())) } (op, None) => { - return Err(type_error(format!("invalid mutation '{op}' without value"))) + return Err(KvMutationError::InvalidMutationWithoutValue(op.to_string())) } }; Ok(Mutation { @@ -566,7 +644,7 @@ type V8Enqueue = (JsBuffer, u64, Vec, Option>); fn enqueue_from_v8( value: V8Enqueue, current_timestamp: DateTime, -) -> Result { +) -> Result { Ok(Enqueue { payload: value.0.to_vec(), deadline: current_timestamp @@ -601,7 +679,7 @@ impl RawSelector { prefix: Option, start: Option, end: Option, - ) -> Result { + ) -> Result { let prefix = prefix.map(encode_v8_key).transpose()?; let start = start.map(encode_v8_key).transpose()?; let end = end.map(encode_v8_key).transpose()?; @@ -614,9 +692,7 @@ impl RawSelector { }), (Some(prefix), Some(start), None) => { if !start.starts_with(&prefix) || start.len() == prefix.len() { - return Err(type_error( - "start key is not in the keyspace defined by prefix", - )); + return Err(KvError::StartKeyNotInKeyspace); } Ok(Self::Prefixed { prefix, @@ -626,9 +702,7 @@ impl RawSelector { } (Some(prefix), None, Some(end)) => { if !end.starts_with(&prefix) || end.len() == prefix.len() { - return Err(type_error( - "end key is not in the keyspace defined by prefix", - )); + return Err(KvError::EndKeyNotInKeyspace); } Ok(Self::Prefixed { prefix, @@ -638,7 +712,7 @@ impl RawSelector { } (None, Some(start), Some(end)) => { if start > end { - return Err(type_error("start key is greater than end key")); + return Err(KvError::StartKeyGreaterThanEndKey); } Ok(Self::Range { start, end }) } @@ -646,7 +720,7 @@ impl RawSelector { let end = start.iter().copied().chain(Some(0)).collect(); Ok(Self::Range { start, end }) } - _ => Err(type_error("invalid range")), + _ => Err(KvError::InvalidRange), } } @@ -705,10 +779,10 @@ fn common_prefix_for_bytes<'a>(a: &'a [u8], b: &'a [u8]) -> &'a [u8] { fn encode_cursor( selector: &RawSelector, boundary_key: &[u8], -) -> Result { +) -> Result { let common_prefix = selector.common_prefix(); if !boundary_key.starts_with(common_prefix) { - return Err(type_error("invalid boundary key")); + return Err(KvError::InvalidBoundaryKey); } Ok(BASE64_URL_SAFE.encode(&boundary_key[common_prefix.len()..])) } @@ -717,7 +791,7 @@ fn decode_selector_and_cursor( selector: &RawSelector, reverse: bool, cursor: Option<&ByteString>, -) -> Result<(Vec, Vec), AnyError> { +) -> Result<(Vec, Vec), KvError> { let Some(cursor) = cursor else { return Ok((selector.range_start_key(), selector.range_end_key())); }; @@ -725,7 +799,7 @@ fn decode_selector_and_cursor( let common_prefix = selector.common_prefix(); let cursor = BASE64_URL_SAFE .decode(cursor) - .map_err(|_| type_error("invalid cursor"))?; + .map_err(|_| KvError::InvalidCursor)?; let first_key: Vec; let last_key: Vec; @@ -750,13 +824,13 @@ fn decode_selector_and_cursor( // Defend against out-of-bounds reading if let Some(start) = selector.start() { if &first_key[..] < start { - return Err(type_error("cursor out of bounds")); + return Err(KvError::CursorOutOfBounds); } } if let Some(end) = selector.end() { if &last_key[..] > end { - return Err(type_error("cursor out of bounds")); + return Err(KvError::CursorOutOfBounds); } } @@ -771,44 +845,48 @@ async fn op_kv_atomic_write( #[serde] checks: Vec, #[serde] mutations: Vec, #[serde] enqueues: Vec, -) -> Result, AnyError> +) -> Result, KvError> where DBH: DatabaseHandler + 'static, { let current_timestamp = chrono::Utc::now(); let db = { let state = state.borrow(); - let resource = - state.resource_table.get::>(rid)?; + let resource = state + .resource_table + .get::>(rid) + .map_err(KvError::Resource)?; resource.db.clone() }; - if checks.len() > MAX_CHECKS { - return Err(type_error(format!("too many checks (max {})", MAX_CHECKS))); + let config = { + let state = state.borrow(); + state.borrow::>().clone() + }; + + if checks.len() > config.max_checks { + return Err(KvError::TooManyChecks(config.max_checks)); } - if mutations.len() + enqueues.len() > MAX_MUTATIONS { - return Err(type_error(format!( - "too many mutations (max {})", - MAX_MUTATIONS - ))); + if mutations.len() + enqueues.len() > config.max_mutations { + return Err(KvError::TooManyMutations(config.max_mutations)); } let checks = checks .into_iter() .map(check_from_v8) - .collect::, AnyError>>() - .with_context(|| "invalid check")?; + .collect::, KvCheckError>>() + .map_err(KvError::InvalidCheck)?; let mutations = mutations .into_iter() .map(|mutation| mutation_from_v8((mutation, current_timestamp))) - .collect::, AnyError>>() - .with_context(|| "invalid mutation")?; + .collect::, KvMutationError>>() + .map_err(KvError::InvalidMutation)?; let enqueues = enqueues .into_iter() .map(|e| enqueue_from_v8(e, current_timestamp)) - .collect::, AnyError>>() - .with_context(|| "invalid enqueue")?; + .collect::, std::io::Error>>() + .map_err(KvError::InvalidEnqueue)?; let mut total_payload_size = 0usize; let mut total_key_size = 0usize; @@ -819,40 +897,37 @@ where .chain(mutations.iter().map(|m| &m.key)) { if key.is_empty() { - return Err(type_error("key cannot be empty")); + return Err(KvError::EmptyKey); } - total_payload_size += check_write_key_size(key)?; + total_payload_size += check_write_key_size(key, &config)?; } for (key, value) in mutations .iter() .flat_map(|m| m.kind.value().map(|x| (&m.key, x))) { - let key_size = check_write_key_size(key)?; - total_payload_size += check_value_size(value)? + key_size; + let key_size = check_write_key_size(key, &config)?; + total_payload_size += check_value_size(value, &config)? + key_size; total_key_size += key_size; } for enqueue in &enqueues { - total_payload_size += check_enqueue_payload_size(&enqueue.payload)?; + total_payload_size += + check_enqueue_payload_size(&enqueue.payload, &config)?; if let Some(schedule) = enqueue.backoff_schedule.as_ref() { total_payload_size += 4 * schedule.len(); } } - if total_payload_size > MAX_TOTAL_MUTATION_SIZE_BYTES { - return Err(type_error(format!( - "total mutation size too large (max {} bytes)", - MAX_TOTAL_MUTATION_SIZE_BYTES - ))); + if total_payload_size > config.max_total_mutation_size_bytes { + return Err(KvError::TotalMutationTooLarge( + config.max_total_mutation_size_bytes, + )); } - if total_key_size > MAX_TOTAL_KEY_SIZE_BYTES { - return Err(type_error(format!( - "total key size too large (max {} bytes)", - MAX_TOTAL_KEY_SIZE_BYTES - ))); + if total_key_size > config.max_total_key_size_bytes { + return Err(KvError::TotalKeyTooLarge(config.max_total_key_size_bytes)); } let atomic_write = AtomicWrite { @@ -861,7 +936,7 @@ where enqueues, }; - let result = db.atomic_write(atomic_write).await?; + let result = db.atomic_write(atomic_write).await.map_err(KvError::Kv)?; Ok(result.map(|res| faster_hex::hex_string(&res.versionstamp))) } @@ -874,58 +949,55 @@ type EncodeCursorRangeSelector = (Option, Option, Option); fn op_kv_encode_cursor( #[serde] (prefix, start, end): EncodeCursorRangeSelector, #[serde] boundary_key: KvKey, -) -> Result { +) -> Result { let selector = RawSelector::from_tuple(prefix, start, end)?; let boundary_key = encode_v8_key(boundary_key)?; let cursor = encode_cursor(&selector, &boundary_key)?; Ok(cursor) } -fn check_read_key_size(key: &[u8]) -> Result<(), AnyError> { - if key.len() > MAX_READ_KEY_SIZE_BYTES { - Err(type_error(format!( - "key too large for read (max {} bytes)", - MAX_READ_KEY_SIZE_BYTES - ))) +fn check_read_key_size(key: &[u8], config: &KvConfig) -> Result<(), KvError> { + if key.len() > config.max_read_key_size_bytes { + Err(KvError::KeyTooLargeToRead(config.max_read_key_size_bytes)) } else { Ok(()) } } -fn check_write_key_size(key: &[u8]) -> Result { - if key.len() > MAX_WRITE_KEY_SIZE_BYTES { - Err(type_error(format!( - "key too large for write (max {} bytes)", - MAX_WRITE_KEY_SIZE_BYTES - ))) +fn check_write_key_size( + key: &[u8], + config: &KvConfig, +) -> Result { + if key.len() > config.max_write_key_size_bytes { + Err(KvError::KeyTooLargeToWrite(config.max_write_key_size_bytes)) } else { Ok(key.len()) } } -fn check_value_size(value: &KvValue) -> Result { +fn check_value_size( + value: &KvValue, + config: &KvConfig, +) -> Result { let payload = match value { KvValue::Bytes(x) => x, KvValue::V8(x) => x, KvValue::U64(_) => return Ok(8), }; - if payload.len() > MAX_VALUE_SIZE_BYTES { - Err(type_error(format!( - "value too large (max {} bytes)", - MAX_VALUE_SIZE_BYTES - ))) + if payload.len() > config.max_value_size_bytes { + Err(KvError::ValueTooLarge(config.max_value_size_bytes)) } else { Ok(payload.len()) } } -fn check_enqueue_payload_size(payload: &[u8]) -> Result { - if payload.len() > MAX_VALUE_SIZE_BYTES { - Err(type_error(format!( - "enqueue payload too large (max {} bytes)", - MAX_VALUE_SIZE_BYTES - ))) +fn check_enqueue_payload_size( + payload: &[u8], + config: &KvConfig, +) -> Result { + if payload.len() > config.max_value_size_bytes { + Err(KvError::EnqueuePayloadTooLarge(config.max_value_size_bytes)) } else { Ok(payload.len()) } diff --git a/ext/kv/sqlite.rs b/ext/kv/sqlite.rs index 37f5aa6853..0b4a3693c4 100644 --- a/ext/kv/sqlite.rs +++ b/ext/kv/sqlite.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::env::current_dir; @@ -17,7 +18,7 @@ use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::unsync::spawn_blocking; use deno_core::OpState; -use deno_node::PathClean; +use deno_path_util::normalize_path; pub use denokv_sqlite::SqliteBackendError; use denokv_sqlite::SqliteConfig; use denokv_sqlite::SqliteNotifier; @@ -36,19 +37,37 @@ pub struct SqliteDbHandler { } pub trait SqliteDbHandlerPermissions { - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>; - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read( + &mut self, + p: &str, + api_name: &str, + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_write<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result, AnyError>; } impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer { #[inline(always)] - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + fn check_read( + &mut self, + p: &str, + api_name: &str, + ) -> Result { deno_permissions::PermissionsContainer::check_read(self, p, api_name) } #[inline(always)] - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - deno_permissions::PermissionsContainer::check_write(self, p, api_name) + fn check_write<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result, AnyError> { + deno_permissions::PermissionsContainer::check_write_path(self, p, api_name) } } @@ -74,28 +93,35 @@ impl DatabaseHandler for SqliteDbHandler

{ state: Rc>, path: Option, ) -> Result { - // Validate path - if let Some(path) = &path { - if path != ":memory:" { - if path.is_empty() { - return Err(type_error("Filename cannot be empty")); - } - if path.starts_with(':') { - return Err(type_error( - "Filename cannot start with ':' unless prefixed with './'", - )); - } - let path = Path::new(path); - { - let mut state = state.borrow_mut(); - let permissions = state.borrow_mut::

(); - permissions.check_read(path, "Deno.openKv")?; - permissions.check_write(path, "Deno.openKv")?; - } + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn validate_path( + state: &RefCell, + path: Option, + ) -> Result, AnyError> { + let Some(path) = path else { + return Ok(None); + }; + if path == ":memory:" { + return Ok(Some(path)); + } + if path.is_empty() { + return Err(type_error("Filename cannot be empty")); + } + if path.starts_with(':') { + return Err(type_error( + "Filename cannot start with ':' unless prefixed with './'", + )); + } + { + let mut state = state.borrow_mut(); + let permissions = state.borrow_mut::

(); + let path = permissions.check_read(&path, "Deno.openKv")?; + let path = permissions.check_write(&path, "Deno.openKv")?; + Ok(Some(path.to_string_lossy().to_string())) } } - let path = path.clone(); + let path = validate_path::

(&state, path)?; let default_storage_dir = self.default_storage_dir.clone(); type ConnGen = Arc rusqlite::Result + Send + Sync>; @@ -176,7 +202,7 @@ impl DatabaseHandler for SqliteDbHandler

{ /// Same as Path::canonicalize, but also handles non-existing paths. fn canonicalize_path(path: &Path) -> Result { - let path = path.to_path_buf().clean(); + let path = normalize_path(path); let mut path = path; let mut names_stack = Vec::new(); loop { diff --git a/ext/napi/Cargo.toml b/ext/napi/Cargo.toml index e738087c59..622429f7c8 100644 --- a/ext/napi/Cargo.toml +++ b/ext/napi/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_napi" -version = "0.95.0" +version = "0.105.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -16,4 +16,14 @@ path = "lib.rs" [dependencies] deno_core.workspace = true deno_permissions.workspace = true +libc.workspace = true libloading = { version = "0.7" } +log.workspace = true +napi_sym.workspace = true +thiserror.workspace = true + +[target.'cfg(windows)'.dependencies] +windows-sys.workspace = true + +[dev-dependencies] +libuv-sys-lite = "=1.48.2" diff --git a/ext/napi/README.md b/ext/napi/README.md index e69de29bb2..b479295244 100644 --- a/ext/napi/README.md +++ b/ext/napi/README.md @@ -0,0 +1,114 @@ +# napi + +This directory contains source for Deno's Node-API implementation. It depends on +`napi_sym` and `deno_napi`. + +Files are generally organized the same as in Node.js's implementation to ease in +ensuring compatibility. + +## Adding a new function + +Add the symbol name to +[`cli/napi_sym/symbol_exports.json`](../napi_sym/symbol_exports.json). + +```diff +{ + "symbols": [ + ... + "napi_get_undefined", +- "napi_get_null" ++ "napi_get_null", ++ "napi_get_boolean" + ] +} +``` + +Determine where to place the implementation. `napi_get_boolean` is related to JS +values so we will place it in `js_native_api.rs`. If something is not clear, +just create a new file module. + +See [`napi_sym`](../napi_sym/) for writing the implementation: + +```rust +#[napi_sym::napi_sym] +fn napi_get_boolean( + env: *mut Env, + value: bool, + result: *mut napi_value, +) -> Result { + // ... + Ok(()) +} +``` + +Update the generated symbol lists using the script: + +``` +deno run --allow-write tools/napi/generate_symbols_lists.js +``` + +Add a test in [`/tests/napi`](../../tests/napi/). You can also refer to Node.js +test suite for Node-API. + +```js +// tests/napi/boolean_test.js +import { assertEquals, loadTestLibrary } from "./common.js"; +const lib = loadTestLibrary(); +Deno.test("napi get boolean", function () { + assertEquals(lib.test_get_boolean(true), true); + assertEquals(lib.test_get_boolean(false), false); +}); +``` + +```rust +// tests/napi/src/boolean.rs + +use napi_sys::Status::napi_ok; +use napi_sys::ValueType::napi_boolean; +use napi_sys::*; + +extern "C" fn test_boolean( + env: napi_env, + info: napi_callback_info, +) -> napi_value { + let (args, argc, _) = crate::get_callback_info!(env, info, 1); + assert_eq!(argc, 1); + + let mut ty = -1; + assert!(unsafe { napi_typeof(env, args[0], &mut ty) } == napi_ok); + assert_eq!(ty, napi_boolean); + + // Use napi_get_boolean here... + + value +} + +pub fn init(env: napi_env, exports: napi_value) { + let properties = &[crate::new_property!(env, "test_boolean\0", test_boolean)]; + + unsafe { + napi_define_properties(env, exports, properties.len(), properties.as_ptr()) + }; +} +``` + +```diff +// tests/napi/src/lib.rs + ++ mod boolean; + +... + +#[no_mangle] +unsafe extern "C" fn napi_register_module_v1( + env: napi_env, + exports: napi_value, +) -> napi_value { + ... ++ boolean::init(env, exports); + + exports +} +``` + +Run the test using `cargo test -p tests/napi`. diff --git a/ext/napi/build.rs b/ext/napi/build.rs new file mode 100644 index 0000000000..8705830a95 --- /dev/null +++ b/ext/napi/build.rs @@ -0,0 +1,22 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +fn main() { + let symbols_file_name = match std::env::consts::OS { + "android" | "freebsd" | "openbsd" => { + "generated_symbol_exports_list_linux.def".to_string() + } + os => format!("generated_symbol_exports_list_{}.def", os), + }; + let symbols_path = std::path::Path::new(".") + .join(symbols_file_name) + .canonicalize() + .expect( + "Missing symbols list! Generate using tools/napi/generate_symbols_lists.js", + ); + + println!("cargo:rustc-rerun-if-changed={}", symbols_path.display()); + + let path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()) + .join("napi_symbol_path.txt"); + std::fs::write(path, symbols_path.as_os_str().as_encoded_bytes()).unwrap(); +} diff --git a/cli/napi/generated_symbol_exports_list_linux.def b/ext/napi/generated_symbol_exports_list_linux.def similarity index 96% rename from cli/napi/generated_symbol_exports_list_linux.def rename to ext/napi/generated_symbol_exports_list_linux.def index 06e94f05bb..614880ebfa 100644 --- a/cli/napi/generated_symbol_exports_list_linux.def +++ b/ext/napi/generated_symbol_exports_list_linux.def @@ -1 +1 @@ -{ "node_api_create_syntax_error"; "napi_make_callback"; "napi_has_named_property"; "napi_async_destroy"; "napi_coerce_to_object"; "napi_get_arraybuffer_info"; "napi_detach_arraybuffer"; "napi_get_undefined"; "napi_reference_unref"; "napi_fatal_error"; "napi_open_callback_scope"; "napi_close_callback_scope"; "napi_get_value_uint32"; "napi_create_function"; "napi_create_arraybuffer"; "napi_get_value_int64"; "napi_get_all_property_names"; "napi_resolve_deferred"; "napi_is_detached_arraybuffer"; "napi_create_string_utf8"; "napi_create_threadsafe_function"; "node_api_throw_syntax_error"; "napi_create_bigint_int64"; "napi_wrap"; "napi_set_property"; "napi_get_value_bigint_int64"; "napi_open_handle_scope"; "napi_create_error"; "napi_create_buffer"; "napi_cancel_async_work"; "napi_is_exception_pending"; "napi_acquire_threadsafe_function"; "napi_create_external"; "napi_get_threadsafe_function_context"; "napi_get_null"; "napi_create_string_utf16"; "node_api_create_external_string_utf16"; "napi_get_value_bigint_uint64"; "napi_module_register"; "napi_is_typedarray"; "napi_create_external_buffer"; "napi_get_new_target"; "napi_get_instance_data"; "napi_close_handle_scope"; "napi_get_value_string_utf16"; "napi_get_property_names"; "napi_is_arraybuffer"; "napi_get_cb_info"; "napi_define_properties"; "napi_add_env_cleanup_hook"; "node_api_get_module_file_name"; "napi_get_node_version"; "napi_create_int64"; "napi_create_double"; "napi_get_and_clear_last_exception"; "napi_create_reference"; "napi_get_typedarray_info"; "napi_call_threadsafe_function"; "napi_get_last_error_info"; "napi_create_array_with_length"; "napi_coerce_to_number"; "napi_get_global"; "napi_is_error"; "napi_set_instance_data"; "napi_create_typedarray"; "napi_throw_type_error"; "napi_has_property"; "napi_get_value_external"; "napi_create_range_error"; "napi_typeof"; "napi_ref_threadsafe_function"; "napi_create_bigint_uint64"; "napi_get_prototype"; "napi_adjust_external_memory"; "napi_release_threadsafe_function"; "napi_delete_async_work"; "napi_create_string_latin1"; "node_api_create_external_string_latin1"; "napi_is_array"; "napi_unref_threadsafe_function"; "napi_throw_error"; "napi_has_own_property"; "napi_get_reference_value"; "napi_remove_env_cleanup_hook"; "napi_get_value_string_utf8"; "napi_is_promise"; "napi_get_boolean"; "napi_run_script"; "napi_get_element"; "napi_get_named_property"; "napi_get_buffer_info"; "napi_get_value_bool"; "napi_reference_ref"; "napi_create_object"; "napi_create_promise"; "napi_create_int32"; "napi_escape_handle"; "napi_open_escapable_handle_scope"; "napi_throw"; "napi_get_value_double"; "napi_set_named_property"; "napi_call_function"; "napi_create_date"; "napi_object_freeze"; "napi_get_uv_event_loop"; "napi_get_value_string_latin1"; "napi_reject_deferred"; "napi_add_finalizer"; "napi_create_array"; "napi_delete_reference"; "napi_get_date_value"; "napi_create_dataview"; "napi_get_version"; "napi_define_class"; "napi_is_date"; "napi_remove_wrap"; "napi_delete_property"; "napi_instanceof"; "napi_create_buffer_copy"; "napi_delete_element"; "napi_object_seal"; "napi_queue_async_work"; "napi_get_value_bigint_words"; "napi_is_buffer"; "napi_get_array_length"; "napi_get_property"; "napi_new_instance"; "napi_set_element"; "napi_create_bigint_words"; "napi_strict_equals"; "napi_is_dataview"; "napi_close_escapable_handle_scope"; "napi_get_dataview_info"; "napi_get_value_int32"; "napi_unwrap"; "napi_throw_range_error"; "napi_coerce_to_bool"; "napi_create_uint32"; "napi_has_element"; "napi_create_external_arraybuffer"; "napi_create_symbol"; "node_api_symbol_for"; "napi_coerce_to_string"; "napi_create_type_error"; "napi_fatal_exception"; "napi_create_async_work"; "napi_async_init"; "node_api_create_property_key_utf16"; "napi_type_tag_object"; "napi_check_object_type_tag"; "node_api_post_finalizer"; "napi_add_async_cleanup_hook"; "napi_remove_async_cleanup_hook"; }; \ No newline at end of file +{ "node_api_create_syntax_error"; "napi_make_callback"; "napi_has_named_property"; "napi_async_destroy"; "napi_coerce_to_object"; "napi_get_arraybuffer_info"; "napi_detach_arraybuffer"; "napi_get_undefined"; "napi_reference_unref"; "napi_fatal_error"; "napi_open_callback_scope"; "napi_close_callback_scope"; "napi_get_value_uint32"; "napi_create_function"; "napi_create_arraybuffer"; "napi_get_value_int64"; "napi_get_all_property_names"; "napi_resolve_deferred"; "napi_is_detached_arraybuffer"; "napi_create_string_utf8"; "napi_create_threadsafe_function"; "node_api_throw_syntax_error"; "napi_create_bigint_int64"; "napi_wrap"; "napi_set_property"; "napi_get_value_bigint_int64"; "napi_open_handle_scope"; "napi_create_error"; "napi_create_buffer"; "napi_cancel_async_work"; "napi_is_exception_pending"; "napi_acquire_threadsafe_function"; "napi_create_external"; "napi_get_threadsafe_function_context"; "napi_get_null"; "napi_create_string_utf16"; "node_api_create_external_string_utf16"; "napi_get_value_bigint_uint64"; "napi_module_register"; "napi_is_typedarray"; "napi_create_external_buffer"; "napi_get_new_target"; "napi_get_instance_data"; "napi_close_handle_scope"; "napi_get_value_string_utf16"; "napi_get_property_names"; "napi_is_arraybuffer"; "napi_get_cb_info"; "napi_define_properties"; "napi_add_env_cleanup_hook"; "node_api_get_module_file_name"; "napi_get_node_version"; "napi_create_int64"; "napi_create_double"; "napi_get_and_clear_last_exception"; "napi_create_reference"; "napi_get_typedarray_info"; "napi_call_threadsafe_function"; "napi_get_last_error_info"; "napi_create_array_with_length"; "napi_coerce_to_number"; "napi_get_global"; "napi_is_error"; "napi_set_instance_data"; "napi_create_typedarray"; "napi_throw_type_error"; "napi_has_property"; "napi_get_value_external"; "napi_create_range_error"; "napi_typeof"; "napi_ref_threadsafe_function"; "napi_create_bigint_uint64"; "napi_get_prototype"; "napi_adjust_external_memory"; "napi_release_threadsafe_function"; "napi_delete_async_work"; "napi_create_string_latin1"; "node_api_create_external_string_latin1"; "napi_is_array"; "napi_unref_threadsafe_function"; "napi_throw_error"; "napi_has_own_property"; "napi_get_reference_value"; "napi_remove_env_cleanup_hook"; "napi_get_value_string_utf8"; "napi_is_promise"; "napi_get_boolean"; "napi_run_script"; "napi_get_element"; "napi_get_named_property"; "napi_get_buffer_info"; "napi_get_value_bool"; "napi_reference_ref"; "napi_create_object"; "napi_create_promise"; "napi_create_int32"; "napi_escape_handle"; "napi_open_escapable_handle_scope"; "napi_throw"; "napi_get_value_double"; "napi_set_named_property"; "napi_call_function"; "napi_create_date"; "napi_object_freeze"; "napi_get_uv_event_loop"; "napi_get_value_string_latin1"; "napi_reject_deferred"; "napi_add_finalizer"; "napi_create_array"; "napi_delete_reference"; "napi_get_date_value"; "napi_create_dataview"; "napi_get_version"; "napi_define_class"; "napi_is_date"; "napi_remove_wrap"; "napi_delete_property"; "napi_instanceof"; "napi_create_buffer_copy"; "napi_delete_element"; "napi_object_seal"; "napi_queue_async_work"; "napi_get_value_bigint_words"; "napi_is_buffer"; "napi_get_array_length"; "napi_get_property"; "napi_new_instance"; "napi_set_element"; "napi_create_bigint_words"; "napi_strict_equals"; "napi_is_dataview"; "napi_close_escapable_handle_scope"; "napi_get_dataview_info"; "napi_get_value_int32"; "napi_unwrap"; "napi_throw_range_error"; "napi_coerce_to_bool"; "napi_create_uint32"; "napi_has_element"; "napi_create_external_arraybuffer"; "napi_create_symbol"; "node_api_symbol_for"; "napi_coerce_to_string"; "napi_create_type_error"; "napi_fatal_exception"; "napi_create_async_work"; "napi_async_init"; "node_api_create_property_key_utf16"; "napi_type_tag_object"; "napi_check_object_type_tag"; "node_api_post_finalizer"; "napi_add_async_cleanup_hook"; "napi_remove_async_cleanup_hook"; "uv_mutex_init"; "uv_mutex_lock"; "uv_mutex_unlock"; "uv_mutex_destroy"; "uv_async_init"; "uv_async_send"; "uv_close"; }; \ No newline at end of file diff --git a/cli/napi/generated_symbol_exports_list_macos.def b/ext/napi/generated_symbol_exports_list_macos.def similarity index 96% rename from cli/napi/generated_symbol_exports_list_macos.def rename to ext/napi/generated_symbol_exports_list_macos.def index cac7100c6f..36b2f37fa5 100644 --- a/cli/napi/generated_symbol_exports_list_macos.def +++ b/ext/napi/generated_symbol_exports_list_macos.def @@ -150,4 +150,11 @@ _napi_type_tag_object _napi_check_object_type_tag _node_api_post_finalizer _napi_add_async_cleanup_hook -_napi_remove_async_cleanup_hook \ No newline at end of file +_napi_remove_async_cleanup_hook +_uv_mutex_init +_uv_mutex_lock +_uv_mutex_unlock +_uv_mutex_destroy +_uv_async_init +_uv_async_send +_uv_close \ No newline at end of file diff --git a/cli/napi/generated_symbol_exports_list_windows.def b/ext/napi/generated_symbol_exports_list_windows.def similarity index 96% rename from cli/napi/generated_symbol_exports_list_windows.def rename to ext/napi/generated_symbol_exports_list_windows.def index 5386b46e54..b7355112e7 100644 --- a/cli/napi/generated_symbol_exports_list_windows.def +++ b/ext/napi/generated_symbol_exports_list_windows.def @@ -152,4 +152,11 @@ EXPORTS napi_check_object_type_tag node_api_post_finalizer napi_add_async_cleanup_hook - napi_remove_async_cleanup_hook \ No newline at end of file + napi_remove_async_cleanup_hook + uv_mutex_init + uv_mutex_lock + uv_mutex_unlock + uv_mutex_destroy + uv_async_init + uv_async_send + uv_close \ No newline at end of file diff --git a/cli/napi/js_native_api.rs b/ext/napi/js_native_api.rs similarity index 98% rename from cli/napi/js_native_api.rs rename to ext/napi/js_native_api.rs index 5269d8d1d3..53a12d6eba 100644 --- a/cli/napi/js_native_api.rs +++ b/ext/napi/js_native_api.rs @@ -5,7 +5,7 @@ const NAPI_VERSION: u32 = 9; -use deno_runtime::deno_napi::*; +use crate::*; use libc::INT_MAX; use super::util::check_new_from_utf8; @@ -17,9 +17,9 @@ use super::util::napi_set_last_error; use super::util::v8_name_from_property_descriptor; use crate::check_arg; use crate::check_env; -use deno_runtime::deno_napi::function::create_function; -use deno_runtime::deno_napi::function::create_function_template; -use deno_runtime::deno_napi::function::CallbackInfo; +use crate::function::create_function; +use crate::function::create_function_template; +use crate::function::CallbackInfo; use napi_sym::napi_sym; use std::ptr::NonNull; @@ -264,6 +264,16 @@ fn napi_define_class<'s>( Err(status) => return status, }; + let mut accessor_property = v8::PropertyAttribute::NONE; + + if p.attributes & napi_enumerable == 0 { + accessor_property = accessor_property | v8::PropertyAttribute::DONT_ENUM; + } + if p.attributes & napi_configurable == 0 { + accessor_property = + accessor_property | v8::PropertyAttribute::DONT_DELETE; + } + if p.getter.is_some() || p.setter.is_some() { let getter = p.getter.map(|g| { create_function_template(&mut env.scope(), env_ptr, None, g, p.data) @@ -271,8 +281,6 @@ fn napi_define_class<'s>( let setter = p.setter.map(|s| { create_function_template(&mut env.scope(), env_ptr, None, s, p.data) }); - - let mut accessor_property = v8::PropertyAttribute::NONE; if getter.is_some() && setter.is_some() && (p.attributes & napi_writable) == 0 @@ -280,15 +288,6 @@ fn napi_define_class<'s>( accessor_property = accessor_property | v8::PropertyAttribute::READ_ONLY; } - if p.attributes & napi_enumerable == 0 { - accessor_property = - accessor_property | v8::PropertyAttribute::DONT_ENUM; - } - if p.attributes & napi_configurable == 0 { - accessor_property = - accessor_property | v8::PropertyAttribute::DONT_DELETE; - } - let proto = tpl.prototype_template(&mut env.scope()); proto.set_accessor_property(name, getter, setter, accessor_property); } else if let Some(method) = p.method { @@ -300,10 +299,14 @@ fn napi_define_class<'s>( p.data, ); let proto = tpl.prototype_template(&mut env.scope()); - proto.set(name, function.into()); + proto.set_with_attr(name, function.into(), accessor_property); } else { let proto = tpl.prototype_template(&mut env.scope()); - proto.set(name, p.value.unwrap().into()); + if (p.attributes & napi_writable) == 0 { + accessor_property = + accessor_property | v8::PropertyAttribute::READ_ONLY; + } + proto.set_with_attr(name, p.value.unwrap().into(), accessor_property); } } @@ -1080,7 +1083,7 @@ fn napi_create_string_latin1( } #[napi_sym] -fn napi_create_string_utf8( +pub(crate) fn napi_create_string_utf8( env_ptr: *mut Env, string: *const c_char, length: usize, @@ -1644,7 +1647,7 @@ fn napi_get_cb_info( check_arg!(env, argc); let argc = unsafe { *argc as usize }; for i in 0..argc { - let mut arg = args.get(i as _); + let arg = args.get(i as _); unsafe { *argv.add(i) = arg.into(); } @@ -1694,15 +1697,14 @@ fn napi_get_new_target( } #[napi_sym] -fn napi_call_function( - env_ptr: *mut Env, - recv: napi_value, - func: napi_value, +fn napi_call_function<'s>( + env: &'s mut Env, + recv: napi_value<'s>, + func: napi_value<'s>, argc: usize, - argv: *const napi_value, - result: *mut napi_value, + argv: *const napi_value<'s>, + result: *mut napi_value<'s>, ) -> napi_status { - let env = check_env!(env_ptr); check_arg!(env, recv); let args = if argc > 0 { check_arg!(env, argv); @@ -1716,11 +1718,11 @@ fn napi_call_function( let Some(func) = func.and_then(|f| v8::Local::::try_from(f).ok()) else { - return napi_set_last_error(env, napi_function_expected); + return napi_function_expected; }; let Some(v) = func.call(&mut env.scope(), recv.unwrap(), args) else { - return napi_set_last_error(env_ptr, napi_generic_failure); + return napi_generic_failure; }; if !result.is_null() { @@ -1729,7 +1731,7 @@ fn napi_call_function( } } - return napi_clear_last_error(env_ptr); + napi_ok } #[napi_sym] @@ -3307,19 +3309,30 @@ fn napi_resolve_deferred( check_arg!(env, result); check_arg!(env, deferred); + // Make sure microtasks don't run and call back into JS + env + .scope() + .set_microtasks_policy(v8::MicrotasksPolicy::Explicit); + let deferred_ptr = unsafe { NonNull::new_unchecked(deferred as *mut v8::PromiseResolver) }; let global = unsafe { v8::Global::from_raw(env.isolate(), deferred_ptr) }; let resolver = v8::Local::new(&mut env.scope(), global); - if !resolver + let success = resolver .resolve(&mut env.scope(), result.unwrap()) - .unwrap_or(false) - { - return napi_generic_failure; - } + .unwrap_or(false); - napi_ok + // Restore policy + env + .scope() + .set_microtasks_policy(v8::MicrotasksPolicy::Auto); + + if success { + napi_ok + } else { + napi_generic_failure + } } #[napi_sym] diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index faf8a57777..0d41bb40fe 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -5,20 +5,47 @@ #![allow(clippy::undocumented_unsafe_blocks)] #![deny(clippy::missing_safety_doc)] +//! Symbols to be exported are now defined in this JSON file. +//! The `#[napi_sym]` macro checks for missing entries and panics. +//! +//! `./tools/napi/generate_symbols_list.js` is used to generate the LINK `cli/exports.def` on Windows, +//! which is also checked into git. +//! +//! To add a new napi function: +//! 1. Place `#[napi_sym]` on top of your implementation. +//! 2. Add the function's identifier to this JSON list. +//! 3. Finally, run `tools/napi/generate_symbols_list.js` to update `ext/napi/generated_symbol_exports_list_*.def`. + +pub mod js_native_api; +pub mod node_api; +pub mod util; +pub mod uv; + use core::ptr::NonNull; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; +use deno_core::parking_lot::RwLock; use deno_core::url::Url; use deno_core::ExternalOpsTracker; use deno_core::OpState; use deno_core::V8CrossThreadTaskSpawner; use std::cell::RefCell; -use std::path::Path; +use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; use std::thread_local; +#[derive(Debug, thiserror::Error)] +pub enum NApiError { + #[error("Invalid path")] + InvalidPath, + #[error(transparent)] + LibLoading(#[from] libloading::Error), + #[error("Unable to find register Node-API module at {}", .0.display())] + ModuleNotFound(PathBuf), + #[error(transparent)] + Permission(deno_core::error::AnyError), +} + #[cfg(unix)] use libloading::os::unix::*; @@ -480,19 +507,34 @@ deno_core::extension!(deno_napi, ); pub trait NapiPermissions { - fn check(&mut self, path: Option<&Path>) - -> std::result::Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check( + &mut self, + path: &str, + ) -> Result; } // NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might // change in the future. impl NapiPermissions for deno_permissions::PermissionsContainer { #[inline(always)] - fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + fn check( + &mut self, + path: &str, + ) -> Result { deno_permissions::PermissionsContainer::check_ffi(self, path) } } +unsafe impl Sync for NapiModuleHandle {} +unsafe impl Send for NapiModuleHandle {} +#[derive(Clone, Copy)] +struct NapiModuleHandle(*const NapiModule); + +static NAPI_LOADED_MODULES: std::sync::LazyLock< + RwLock>, +> = std::sync::LazyLock::new(|| RwLock::new(HashMap::new())); + #[op2(reentrant)] fn op_napi_open( scope: &mut v8::HandleScope<'scope>, @@ -502,21 +544,22 @@ fn op_napi_open( global: v8::Local<'scope, v8::Object>, buffer_constructor: v8::Local<'scope, v8::Function>, report_error: v8::Local<'scope, v8::Function>, -) -> std::result::Result, AnyError> +) -> Result, NApiError> where NP: NapiPermissions + 'static, { // We must limit the OpState borrow because this function can trigger a // re-borrow through the NAPI module. - let (async_work_sender, cleanup_hooks, external_ops_tracker) = { + let (async_work_sender, cleanup_hooks, external_ops_tracker, path) = { let mut op_state = op_state.borrow_mut(); let permissions = op_state.borrow_mut::(); - permissions.check(Some(&PathBuf::from(&path)))?; + let path = permissions.check(&path).map_err(NApiError::Permission)?; let napi_state = op_state.borrow::(); ( op_state.borrow::().clone(), napi_state.env_cleanup_hooks.clone(), op_state.external_ops_tracker.clone(), + path, ) }; @@ -529,7 +572,7 @@ where let type_tag = v8::Global::new(scope, type_tag); let url_filename = - Url::from_file_path(&path).map_err(|_| type_error("Invalid path"))?; + Url::from_file_path(&path).map_err(|_| NApiError::InvalidPath)?; let env_shared = EnvShared::new(napi_wrap, type_tag, format!("{url_filename}\0")); @@ -554,17 +597,11 @@ where // SAFETY: opening a DLL calls dlopen #[cfg(unix)] - let library = match unsafe { Library::open(Some(&path), flags) } { - Ok(lib) => lib, - Err(e) => return Err(type_error(e.to_string())), - }; + let library = unsafe { Library::open(Some(&path), flags) }?; // SAFETY: opening a DLL calls dlopen #[cfg(not(unix))] - let library = match unsafe { Library::load_with_flags(&path, flags) } { - Ok(lib) => lib, - Err(e) => return Err(type_error(e.to_string())), - }; + let library = unsafe { Library::load_with_flags(&path, flags) }?; let maybe_module = MODULE_TO_REGISTER.with(|cell| { let mut slot = cell.borrow_mut(); @@ -575,11 +612,23 @@ where let exports = v8::Object::new(scope); let maybe_exports = if let Some(module_to_register) = maybe_module { + NAPI_LOADED_MODULES + .write() + .insert(path, NapiModuleHandle(module_to_register)); // SAFETY: napi_register_module guarantees that `module_to_register` is valid. let nm = unsafe { &*module_to_register }; assert_eq!(nm.nm_version, 1); // SAFETY: we are going blind, calling the register function on the other side. unsafe { (nm.nm_register_func)(env_ptr, exports.into()) } + } else if let Some(module_to_register) = + { NAPI_LOADED_MODULES.read().get(&path).copied() } + { + // SAFETY: this originated from `napi_register_module`, so the + // pointer should still be valid. + let nm = unsafe { &*module_to_register.0 }; + assert_eq!(nm.nm_version, 1); + // SAFETY: we are going blind, calling the register function on the other side. + unsafe { (nm.nm_register_func)(env_ptr, exports.into()) } } else if let Ok(init) = unsafe { library.get::(b"napi_register_module_v1") } { @@ -587,10 +636,7 @@ where // SAFETY: we are going blind, calling the register function on the other side. unsafe { init(env_ptr, exports.into()) } } else { - return Err(type_error(format!( - "Unable to find register Node-API module at {}", - path - ))); + return Err(NApiError::ModuleNotFound(path)); }; let exports = maybe_exports.unwrap_or(exports.into()); @@ -601,3 +647,30 @@ where Ok(exports) } + +#[allow(clippy::print_stdout)] +pub fn print_linker_flags(name: &str) { + let symbols_path = + include_str!(concat!(env!("OUT_DIR"), "/napi_symbol_path.txt")); + + #[cfg(target_os = "windows")] + println!("cargo:rustc-link-arg-bin={name}=/DEF:{}", symbols_path); + + #[cfg(target_os = "macos")] + println!( + "cargo:rustc-link-arg-bin={name}=-Wl,-exported_symbols_list,{}", + symbols_path, + ); + + #[cfg(target_os = "linux")] + println!( + "cargo:rustc-link-arg-bin={name}=-Wl,--export-dynamic-symbol-list={}", + symbols_path, + ); + + #[cfg(target_os = "android")] + println!( + "cargo:rustc-link-arg-bin={name}=-Wl,--export-dynamic-symbol-list={}", + symbols_path, + ); +} diff --git a/cli/napi/node_api.rs b/ext/napi/node_api.rs similarity index 97% rename from cli/napi/node_api.rs rename to ext/napi/node_api.rs index 81cb800a7d..186ae42c48 100644 --- a/cli/napi/node_api.rs +++ b/ext/napi/node_api.rs @@ -9,10 +9,10 @@ use super::util::napi_set_last_error; use super::util::SendPtr; use crate::check_arg; use crate::check_env; +use crate::*; use deno_core::parking_lot::Condvar; use deno_core::parking_lot::Mutex; use deno_core::V8CrossThreadTaskSpawner; -use deno_runtime::deno_napi::*; use napi_sym::napi_sym; use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicU8; @@ -488,7 +488,7 @@ impl AsyncWork { } #[napi_sym] -fn napi_create_async_work( +pub(crate) fn napi_create_async_work( env: *mut Env, async_resource: napi_value, async_resource_name: napi_value, @@ -537,7 +537,10 @@ fn napi_create_async_work( } #[napi_sym] -fn napi_delete_async_work(env: *mut Env, work: napi_async_work) -> napi_status { +pub(crate) fn napi_delete_async_work( + env: *mut Env, + work: napi_async_work, +) -> napi_status { let env = check_env!(env); check_arg!(env, work); @@ -547,15 +550,23 @@ fn napi_delete_async_work(env: *mut Env, work: napi_async_work) -> napi_status { } #[napi_sym] -fn napi_get_uv_event_loop(env: *mut Env, uv_loop: *mut *mut ()) -> napi_status { - let env = check_env!(env); +fn napi_get_uv_event_loop( + env_ptr: *mut Env, + uv_loop: *mut *mut (), +) -> napi_status { + let env = check_env!(env_ptr); check_arg!(env, uv_loop); - // There is no uv_loop in Deno - napi_set_last_error(env, napi_generic_failure) + unsafe { + *uv_loop = env_ptr.cast(); + } + 0 } #[napi_sym] -fn napi_queue_async_work(env: *mut Env, work: napi_async_work) -> napi_status { +pub(crate) fn napi_queue_async_work( + env: *mut Env, + work: napi_async_work, +) -> napi_status { let env = check_env!(env); check_arg!(env, work); @@ -687,7 +698,7 @@ impl Drop for TsFn { if let Some(finalizer) = self.thread_finalize_cb { unsafe { - (finalizer)(self.env as _, self.thread_finalize_data, ptr::null_mut()); + (finalizer)(self.env as _, self.thread_finalize_data, self.context); } } } @@ -892,7 +903,7 @@ fn napi_create_threadsafe_function( }; let resource_name = resource_name.to_rust_string_lossy(&mut env.scope()); - let mut tsfn = Box::new(TsFn { + let tsfn = Box::new(TsFn { env, func, max_queue_size, diff --git a/cli/napi/sym/Cargo.toml b/ext/napi/sym/Cargo.toml similarity index 95% rename from cli/napi/sym/Cargo.toml rename to ext/napi/sym/Cargo.toml index 49cb7d13b0..9fe2d839ad 100644 --- a/cli/napi/sym/Cargo.toml +++ b/ext/napi/sym/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "napi_sym" -version = "0.94.0" +version = "0.104.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/cli/napi/sym/README.md b/ext/napi/sym/README.md similarity index 92% rename from cli/napi/sym/README.md rename to ext/napi/sym/README.md index de08a8e174..66eb4bff26 100644 --- a/cli/napi/sym/README.md +++ b/ext/napi/sym/README.md @@ -2,7 +2,8 @@ A proc_macro for Deno's Node-API implementation. It does the following things: -- Marks the symbol as `#[no_mangle]` and rewrites it as `pub extern "C" $name`. +- Marks the symbol as `#[no_mangle]` and rewrites it as + `unsafe extern "C" $name`. - Asserts that the function symbol is present in [`symbol_exports.json`](./symbol_exports.json). - Maps `deno_napi::Result` to raw `napi_result`. diff --git a/cli/napi/sym/lib.rs b/ext/napi/sym/lib.rs similarity index 100% rename from cli/napi/sym/lib.rs rename to ext/napi/sym/lib.rs diff --git a/cli/napi/sym/symbol_exports.json b/ext/napi/sym/symbol_exports.json similarity index 96% rename from cli/napi/sym/symbol_exports.json rename to ext/napi/sym/symbol_exports.json index 64b548d496..00946b8ed7 100644 --- a/cli/napi/sym/symbol_exports.json +++ b/ext/napi/sym/symbol_exports.json @@ -152,6 +152,13 @@ "napi_check_object_type_tag", "node_api_post_finalizer", "napi_add_async_cleanup_hook", - "napi_remove_async_cleanup_hook" + "napi_remove_async_cleanup_hook", + "uv_mutex_init", + "uv_mutex_lock", + "uv_mutex_unlock", + "uv_mutex_destroy", + "uv_async_init", + "uv_async_send", + "uv_close" ] } diff --git a/cli/napi/util.rs b/ext/napi/util.rs similarity index 84% rename from cli/napi/util.rs rename to ext/napi/util.rs index 63d8effbf2..21e9d433aa 100644 --- a/cli/napi/util.rs +++ b/ext/napi/util.rs @@ -1,9 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_runtime::deno_napi::*; +use crate::*; use libc::INT_MAX; #[repr(transparent)] -pub struct SendPtr(pub *const T); +pub(crate) struct SendPtr(pub *const T); impl SendPtr { // silly function to get around `clippy::redundant_locals` @@ -37,7 +37,7 @@ impl Drop for BufferFinalizer { } } -pub extern "C" fn backing_store_deleter_callback( +pub(crate) extern "C" fn backing_store_deleter_callback( data: *mut c_void, _byte_length: usize, deleter_data: *mut c_void, @@ -50,7 +50,7 @@ pub extern "C" fn backing_store_deleter_callback( drop(finalizer); } -pub fn make_external_backing_store( +pub(crate) fn make_external_backing_store( env: *mut Env, data: *mut c_void, byte_length: usize, @@ -90,9 +90,7 @@ macro_rules! check_env { macro_rules! return_error_status_if_false { ($env: expr, $condition: expr, $status: ident) => { if !$condition { - return Err( - $crate::napi::util::napi_set_last_error($env, $status).into(), - ); + return Err($crate::util::napi_set_last_error($env, $status).into()); } }; } @@ -101,7 +99,7 @@ macro_rules! return_error_status_if_false { macro_rules! return_status_if_false { ($env: expr, $condition: expr, $status: ident) => { if !$condition { - return $crate::napi::util::napi_set_last_error($env, $status); + return $crate::util::napi_set_last_error($env, $status); } }; } @@ -222,7 +220,7 @@ macro_rules! check_arg { ($env: expr, $ptr: expr) => { $crate::return_status_if_false!( $env, - !$crate::napi::util::Nullable::is_null(&$ptr), + !$crate::util::Nullable::is_null(&$ptr), napi_invalid_arg ); }; @@ -230,17 +228,17 @@ macro_rules! check_arg { #[macro_export] macro_rules! napi_wrap { - ( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $env:ident : & $( $lt:lifetime )? mut Env $( , $ident:ident : $ty:ty )* $(,)? ) -> napi_status $body:block ) => { - $( # $attr )* + ( $( # [ $attr:meta ] )* $vis:vis fn $name:ident $( < $( $x:lifetime ),* > )? ( $env:ident : & $( $lt:lifetime )? mut Env $( , $ident:ident : $ty:ty )* $(,)? ) -> napi_status $body:block ) => { + $( # [ $attr ] )* #[no_mangle] - pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( env_ptr : *mut Env , $( $ident : $ty ),* ) -> napi_status { + $vis unsafe extern "C" fn $name $( < $( $x ),* > )? ( env_ptr : *mut Env , $( $ident : $ty ),* ) -> napi_status { let env: & $( $lt )? mut Env = $crate::check_env!(env_ptr); if env.last_exception.is_some() { return napi_pending_exception; } - $crate::napi::util::napi_clear_last_error(env); + $crate::util::napi_clear_last_error(env); let scope_env = unsafe { &mut *env_ptr }; let scope = &mut scope_env.scope(); @@ -259,21 +257,21 @@ macro_rules! napi_wrap { let env = unsafe { &mut *env_ptr }; let global = v8::Global::new(env.isolate(), exception); env.last_exception = Some(global); - return $crate::napi::util::napi_set_last_error(env_ptr, napi_pending_exception); + return $crate::util::napi_set_last_error(env_ptr, napi_pending_exception); } if result != napi_ok { - return $crate::napi::util::napi_set_last_error(env_ptr, result); + return $crate::util::napi_set_last_error(env_ptr, result); } return result; } }; - ( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $( $ident:ident : $ty:ty ),* $(,)? ) -> napi_status $body:block ) => { - $( # $attr )* + ( $( # [ $attr:meta ] )* $vis:vis fn $name:ident $( < $( $x:lifetime ),* > )? ( $( $ident:ident : $ty:ty ),* $(,)? ) -> napi_status $body:block ) => { + $( # [ $attr ] )* #[no_mangle] - pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status { + $vis unsafe extern "C" fn $name $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status { #[inline(always)] fn inner $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status $body diff --git a/ext/napi/uv.rs b/ext/napi/uv.rs new file mode 100644 index 0000000000..6f728a92b3 --- /dev/null +++ b/ext/napi/uv.rs @@ -0,0 +1,231 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use crate::*; +use deno_core::parking_lot::Mutex; +use std::mem::MaybeUninit; +use std::ptr::addr_of_mut; + +#[allow(clippy::print_stderr)] +fn assert_ok(res: c_int) -> c_int { + if res != 0 { + eprintln!("bad result in uv polyfill: {res}"); + // don't panic because that might unwind into + // c/c++ + std::process::abort(); + } + res +} + +use js_native_api::napi_create_string_utf8; +use node_api::napi_create_async_work; +use node_api::napi_delete_async_work; +use node_api::napi_queue_async_work; +use std::ffi::c_int; + +const UV_MUTEX_SIZE: usize = { + #[cfg(unix)] + { + std::mem::size_of::() + } + #[cfg(windows)] + { + std::mem::size_of::( + ) + } +}; + +#[repr(C)] +struct uv_mutex_t { + mutex: Mutex<()>, + _padding: [MaybeUninit; const { + (UV_MUTEX_SIZE - size_of::>()) / size_of::() + }], +} + +#[no_mangle] +unsafe extern "C" fn uv_mutex_init(lock: *mut uv_mutex_t) -> c_int { + unsafe { + addr_of_mut!((*lock).mutex).write(Mutex::new(())); + 0 + } +} + +#[no_mangle] +unsafe extern "C" fn uv_mutex_lock(lock: *mut uv_mutex_t) { + unsafe { + let guard = (*lock).mutex.lock(); + // forget the guard so it doesn't unlock when it goes out of scope. + // we're going to unlock it manually + std::mem::forget(guard); + } +} + +#[no_mangle] +unsafe extern "C" fn uv_mutex_unlock(lock: *mut uv_mutex_t) { + unsafe { + (*lock).mutex.force_unlock(); + } +} + +#[no_mangle] +unsafe extern "C" fn uv_mutex_destroy(_lock: *mut uv_mutex_t) { + // no cleanup required +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +#[allow(dead_code)] +enum uv_handle_type { + UV_UNKNOWN_HANDLE = 0, + UV_ASYNC, + UV_CHECK, + UV_FS_EVENT, + UV_FS_POLL, + UV_HANDLE, + UV_IDLE, + UV_NAMED_PIPE, + UV_POLL, + UV_PREPARE, + UV_PROCESS, + UV_STREAM, + UV_TCP, + UV_TIMER, + UV_TTY, + UV_UDP, + UV_SIGNAL, + UV_FILE, + UV_HANDLE_TYPE_MAX, +} + +const UV_HANDLE_SIZE: usize = 96; + +#[repr(C)] +struct uv_handle_t { + // public members + pub data: *mut c_void, + pub r#loop: *mut uv_loop_t, + pub r#type: uv_handle_type, + + _padding: [MaybeUninit; const { + (UV_HANDLE_SIZE + - size_of::<*mut c_void>() + - size_of::<*mut uv_loop_t>() + - size_of::()) + / size_of::() + }], +} + +#[cfg(unix)] +const UV_ASYNC_SIZE: usize = 128; + +#[cfg(windows)] +const UV_ASYNC_SIZE: usize = 224; + +#[repr(C)] +struct uv_async_t { + // public members + pub data: *mut c_void, + pub r#loop: *mut uv_loop_t, + pub r#type: uv_handle_type, + // private + async_cb: uv_async_cb, + work: napi_async_work, + _padding: [MaybeUninit; const { + (UV_ASYNC_SIZE + - size_of::<*mut c_void>() + - size_of::<*mut uv_loop_t>() + - size_of::() + - size_of::() + - size_of::()) + / size_of::() + }], +} + +type uv_loop_t = Env; +type uv_async_cb = extern "C" fn(handle: *mut uv_async_t); +#[no_mangle] +unsafe extern "C" fn uv_async_init( + r#loop: *mut uv_loop_t, + // probably uninitialized + r#async: *mut uv_async_t, + async_cb: uv_async_cb, +) -> c_int { + unsafe { + addr_of_mut!((*r#async).r#loop).write(r#loop); + addr_of_mut!((*r#async).r#type).write(uv_handle_type::UV_ASYNC); + addr_of_mut!((*r#async).async_cb).write(async_cb); + + let mut resource_name: MaybeUninit = MaybeUninit::uninit(); + assert_ok(napi_create_string_utf8( + r#loop, + c"uv_async".as_ptr(), + usize::MAX, + resource_name.as_mut_ptr(), + )); + let resource_name = resource_name.assume_init(); + + let res = napi_create_async_work( + r#loop, + None::>.into(), + resource_name, + Some(async_exec_wrap), + None, + r#async.cast(), + addr_of_mut!((*r#async).work), + ); + -res + } +} + +#[no_mangle] +unsafe extern "C" fn uv_async_send(handle: *mut uv_async_t) -> c_int { + unsafe { -napi_queue_async_work((*handle).r#loop, (*handle).work) } +} + +type uv_close_cb = unsafe extern "C" fn(*mut uv_handle_t); + +#[no_mangle] +unsafe extern "C" fn uv_close(handle: *mut uv_handle_t, close: uv_close_cb) { + unsafe { + if handle.is_null() { + close(handle); + return; + } + if let uv_handle_type::UV_ASYNC = (*handle).r#type { + let handle: *mut uv_async_t = handle.cast(); + napi_delete_async_work((*handle).r#loop, (*handle).work); + } + close(handle); + } +} + +unsafe extern "C" fn async_exec_wrap(_env: napi_env, data: *mut c_void) { + let data: *mut uv_async_t = data.cast(); + unsafe { + ((*data).async_cb)(data); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sizes() { + assert_eq!( + std::mem::size_of::(), + UV_MUTEX_SIZE + ); + assert_eq!( + std::mem::size_of::(), + UV_HANDLE_SIZE + ); + assert_eq!( + std::mem::size_of::(), + UV_ASYNC_SIZE + ); + assert_eq!(std::mem::size_of::(), UV_MUTEX_SIZE); + assert_eq!(std::mem::size_of::(), UV_HANDLE_SIZE); + assert_eq!(std::mem::size_of::(), UV_ASYNC_SIZE); + } +} diff --git a/ext/net/01_net.js b/ext/net/01_net.js index 536f79bbfa..c3e5f9e5ca 100644 --- a/ext/net/01_net.js +++ b/ext/net/01_net.js @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { core, internals, primordials } from "ext:core/mod.js"; +import { core, primordials } from "ext:core/mod.js"; const { BadResourcePrototype, InterruptedPrototype, @@ -33,9 +33,12 @@ const UDP_DGRAM_MAXSIZE = 65507; const { Error, Number, + NumberIsNaN, + NumberIsInteger, ObjectPrototypeIsPrototypeOf, ObjectDefineProperty, PromiseResolve, + RangeError, SafeSet, SetPrototypeAdd, SetPrototypeDelete, @@ -60,10 +63,6 @@ async function write(rid, data) { return await core.write(rid, data); } -function shutdown(rid) { - return core.shutdown(rid); -} - async function resolveDns(query, recordType, options) { let cancelRid; let abortHandler; @@ -102,13 +101,8 @@ class Conn { #writable; constructor(rid, remoteAddr, localAddr) { - if (internals.future) { - ObjectDefineProperty(this, "rid", { - enumerable: false, - value: undefined, - }); - } ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); @@ -117,15 +111,6 @@ class Conn { this.#localAddr = localAddr; } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.Conn.rid", - new Error().stack, - "Use `Deno.Conn` instance methods instead.", - ); - return this.#rid; - } - get remoteAddr() { return this.#remoteAddr; } @@ -161,7 +146,7 @@ class Conn { } closeWrite() { - return shutdown(this.#rid); + return core.shutdown(this.#rid); } get readable() { @@ -209,27 +194,33 @@ class Conn { } } +class UpgradedConn extends Conn { + #rid = 0; + + constructor(rid, remoteAddr, localAddr) { + super(rid, remoteAddr, localAddr); + ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, + enumerable: false, + value: rid, + }); + this.#rid = rid; + } +} + class TcpConn extends Conn { #rid = 0; constructor(rid, remoteAddr, localAddr) { super(rid, remoteAddr, localAddr); ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); this.#rid = rid; } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.TcpConn.rid", - new Error().stack, - "Use `Deno.TcpConn` instance methods instead.", - ); - return this.#rid; - } - setNoDelay(noDelay = true) { return op_set_nodelay(this.#rid, noDelay); } @@ -245,20 +236,12 @@ class UnixConn extends Conn { constructor(rid, remoteAddr, localAddr) { super(rid, remoteAddr, localAddr); ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); this.#rid = rid; } - - get rid() { - internals.warnOnDeprecatedApi( - "Deno.UnixConn.rid", - new Error().stack, - "Use `Deno.UnixConn` instance methods instead.", - ); - return this.#rid; - } } class Listener { @@ -268,13 +251,8 @@ class Listener { #promise = null; constructor(rid, addr) { - if (internals.future) { - ObjectDefineProperty(this, "rid", { - enumerable: false, - value: undefined, - }); - } ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); @@ -282,15 +260,6 @@ class Listener { this.#addr = addr; } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.Listener.rid", - new Error().stack, - "Use `Deno.Listener` instance methods instead.", - ); - return this.#rid; - } - get addr() { return this.#addr; } @@ -531,10 +500,11 @@ const listenOptionApiName = Symbol("listenOptionApiName"); function listen(args) { switch (args.transport ?? "tcp") { case "tcp": { + const port = validatePort(args.port); const { 0: rid, 1: addr } = op_net_listen_tcp( { hostname: args.hostname ?? "0.0.0.0", - port: Number(args.port), + port, }, args.reusePort, args.loadBalanced ?? false, @@ -558,14 +528,33 @@ function listen(args) { } } +function validatePort(maybePort) { + if (typeof maybePort !== "number" && typeof maybePort !== "string") { + throw new TypeError(`Invalid port (expected number): ${maybePort}`); + } + if (maybePort === "") throw new TypeError("Invalid port: ''"); + const port = Number(maybePort); + if (!NumberIsInteger(port)) { + if (NumberIsNaN(port) && !NumberIsNaN(maybePort)) { + throw new TypeError(`Invalid port: '${maybePort}'`); + } else { + throw new TypeError(`Invalid port: ${maybePort}`); + } + } else if (port < 0 || port > 65535) { + throw new RangeError(`Invalid port (out of range): ${maybePort}`); + } + return port; +} + function createListenDatagram(udpOpFn, unixOpFn) { return function listenDatagram(args) { switch (args.transport) { case "udp": { + const port = validatePort(args.port); const { 0: rid, 1: addr } = udpOpFn( { hostname: args.hostname ?? "127.0.0.1", - port: args.port, + port, }, args.reuseAddress ?? false, args.loopback ?? false, @@ -590,10 +579,11 @@ function createListenDatagram(udpOpFn, unixOpFn) { async function connect(args) { switch (args.transport ?? "tcp") { case "tcp": { + const port = validatePort(args.port); const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tcp( { hostname: args.hostname ?? "127.0.0.1", - port: args.port, + port, }, ); localAddr.transport = "tcp"; @@ -623,7 +613,8 @@ export { Listener, listenOptionApiName, resolveDns, - shutdown, TcpConn, UnixConn, + UpgradedConn, + validatePort, }; diff --git a/ext/net/02_tls.js b/ext/net/02_tls.js index 81bcfb3bd1..6dad965590 100644 --- a/ext/net/02_tls.js +++ b/ext/net/02_tls.js @@ -13,17 +13,15 @@ import { op_tls_handshake, op_tls_key_null, op_tls_key_static, - op_tls_key_static_from_file, op_tls_start, } from "ext:core/ops"; const { - Number, ObjectDefineProperty, TypeError, SymbolFor, } = primordials; -import { Conn, Listener } from "ext:deno_net/01_net.js"; +import { Conn, Listener, validatePort } from "ext:deno_net/01_net.js"; class TlsConn extends Conn { #rid = 0; @@ -31,21 +29,13 @@ class TlsConn extends Conn { constructor(rid, remoteAddr, localAddr) { super(rid, remoteAddr, localAddr); ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); this.#rid = rid; } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.TlsConn.rid", - new Error().stack, - "Use `Deno.TlsConn` instance methods instead.", - ); - return this.#rid; - } - handshake() { return op_tls_handshake(this.#rid); } @@ -59,45 +49,23 @@ async function connectTls({ alpnProtocols = undefined, keyFormat = undefined, cert = undefined, - certFile = undefined, - certChain = undefined, key = undefined, - keyFile = undefined, - privateKey = undefined, }) { if (transport !== "tcp") { throw new TypeError(`Unsupported transport: '${transport}'`); } - let deprecatedCertFile = undefined; - - // Deno.connectTls has an irregular option where you can just pass `certFile` and - // not `keyFile`. In this case it's used for `caCerts` rather than the client key. - if (certFile !== undefined && keyFile === undefined) { - internals.warnOnDeprecatedApi( - "Deno.ConnectTlsOptions.certFile", - new Error().stack, - "Pass the cert file's contents to the `Deno.ConnectTlsOptions.caCerts` option instead.", - ); - - deprecatedCertFile = certFile; - certFile = undefined; - } const keyPair = loadTlsKeyPair("Deno.connectTls", { keyFormat, cert, - certFile, - certChain, key, - keyFile, - privateKey, }); // TODO(mmastrac): We only expose this feature via symbol for now. This should actually be a feature // in Deno.connectTls, however. const serverName = arguments[0][serverNameSymbol] ?? null; const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tls( { hostname, port }, - { certFile: deprecatedCertFile, caCerts, alpnProtocols, serverName }, + { caCerts, alpnProtocols, serverName }, keyPair, ); localAddr.transport = "tcp"; @@ -111,21 +79,13 @@ class TlsListener extends Listener { constructor(rid, addr) { super(rid, addr); ObjectDefineProperty(this, internalRidSymbol, { + __proto__: null, enumerable: false, value: rid, }); this.#rid = rid; } - get rid() { - internals.warnOnDeprecatedApi( - "Deno.TlsListener.rid", - new Error().stack, - "Use `Deno.TlsListener` instance methods instead.", - ); - return this.#rid; - } - async accept() { const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_accept_tls( this.#rid, @@ -145,10 +105,7 @@ function hasTlsKeyPairOptions(options) { if (options[resolverSymbol] !== undefined) { return true; } - return (options.cert !== undefined || options.key !== undefined || - options.certFile !== undefined || - options.keyFile !== undefined || options.privateKey !== undefined || - options.certChain !== undefined); + return (options.cert !== undefined || options.key !== undefined); } /** @@ -158,19 +115,8 @@ function hasTlsKeyPairOptions(options) { function loadTlsKeyPair(api, { keyFormat, cert, - certFile, - certChain, key, - keyFile, - privateKey, }) { - if (internals.future) { - certFile = undefined; - certChain = undefined; - keyFile = undefined; - privateKey = undefined; - } - // TODO(mmastrac): remove this temporary symbol when the API lands if (arguments[1][resolverSymbol] !== undefined) { return createTlsKeyResolver(arguments[1][resolverSymbol]); @@ -178,71 +124,23 @@ function loadTlsKeyPair(api, { // Check for "pem" format if (keyFormat !== undefined && keyFormat !== "pem") { - throw new TypeError('If `keyFormat` is specified, it must be "pem"'); + throw new TypeError( + `If "keyFormat" is specified, it must be "pem": received "${keyFormat}"`, + ); } - function exclusive(a1, a1v, a2, a2v) { - if (a1v !== undefined && a2v !== undefined) { - throw new TypeError( - `Cannot specify both \`${a1}\` and \`${a2}\` for \`${api}\`.`, - ); - } + if (cert !== undefined && key === undefined) { + throw new TypeError( + `If \`cert\` is specified, \`key\` must be specified as well for \`${api}\``, + ); + } + if (cert === undefined && key !== undefined) { + throw new TypeError( + `If \`key\` is specified, \`cert\` must be specified as well for \`${api}\``, + ); } - // Ensure that only one pair is valid - exclusive("certChain", certChain, "cert", cert); - exclusive("certChain", certChain, "certFile", certFile); - exclusive("key", key, "keyFile", keyFile); - exclusive("key", key, "privateKey", privateKey); - - function both(a1, a1v, a2, a2v) { - if (a1v !== undefined && a2v === undefined) { - throw new TypeError( - `If \`${a1}\` is specified, \`${a2}\` must be specified as well for \`${api}\`.`, - ); - } - if (a1v === undefined && a2v !== undefined) { - throw new TypeError( - `If \`${a2}\` is specified, \`${a1}\` must be specified as well for \`${api}\`.`, - ); - } - } - - // Pick one pair of cert/key, certFile/keyFile or certChain/privateKey - both("cert", cert, "key", key); - both("certFile", certFile, "keyFile", keyFile); - both("certChain", certChain, "privateKey", privateKey); - - if (certFile !== undefined) { - internals.warnOnDeprecatedApi( - "Deno.TlsCertifiedKeyOptions.keyFile", - new Error().stack, - "Pass the key file's contents to the `Deno.TlsCertifiedKeyPem.key` option instead.", - ); - internals.warnOnDeprecatedApi( - "Deno.TlsCertifiedKeyOptions.certFile", - new Error().stack, - "Pass the cert file's contents to the `Deno.TlsCertifiedKeyPem.cert` option instead.", - ); - return op_tls_key_static_from_file(api, certFile, keyFile); - } else if (certChain !== undefined) { - if (api !== "Deno.connectTls") { - throw new TypeError( - `Invalid options 'certChain' and 'privateKey' for ${api}`, - ); - } - internals.warnOnDeprecatedApi( - "Deno.TlsCertifiedKeyOptions.privateKey", - new Error().stack, - "Use the `Deno.TlsCertifiedKeyPem.key` option instead.", - ); - internals.warnOnDeprecatedApi( - "Deno.TlsCertifiedKeyOptions.certChain", - new Error().stack, - "Use the `Deno.TlsCertifiedKeyPem.cert` option instead.", - ); - return op_tls_key_static(certChain, privateKey); - } else if (cert !== undefined) { + if (cert !== undefined) { return op_tls_key_static(cert, key); } else { return op_tls_key_null(); @@ -259,6 +157,7 @@ function listenTls({ if (transport !== "tcp") { throw new TypeError(`Unsupported transport: '${transport}'`); } + port = validatePort(port); if (!hasTlsKeyPairOptions(arguments[0])) { throw new TypeError( @@ -267,7 +166,7 @@ function listenTls({ } const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]); const { 0: rid, 1: localAddr } = op_net_listen_tls( - { hostname, port: Number(port) }, + { hostname, port }, { alpnProtocols, reusePort }, keyPair, ); diff --git a/ext/net/Cargo.toml b/ext/net/Cargo.toml index 9ac13b28b1..a458dbe9e3 100644 --- a/ext/net/Cargo.toml +++ b/ext/net/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_net" -version = "0.156.0" +version = "0.166.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,6 +21,7 @@ pin-project.workspace = true rustls-tokio-stream.workspace = true serde.workspace = true socket2.workspace = true +thiserror.workspace = true tokio.workspace = true trust-dns-proto = "0.23" trust-dns-resolver = { version = "0.23", features = ["tokio-runtime", "serde-config"] } diff --git a/ext/net/io.rs b/ext/net/io.rs index f3aed3fcbd..2907fa398b 100644 --- a/ext/net/io.rs +++ b/ext/net/io.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::generic_error; -use deno_core::error::AnyError; +use deno_core::futures::TryFutureExt; use deno_core::AsyncMutFuture; use deno_core::AsyncRefCell; use deno_core::AsyncResult; @@ -69,25 +68,36 @@ where pub async fn read( self: Rc, data: &mut [u8], - ) -> Result { + ) -> Result { let mut rd = self.rd_borrow_mut().await; let nread = rd.read(data).try_or_cancel(self.cancel_handle()).await?; Ok(nread) } - pub async fn write(self: Rc, data: &[u8]) -> Result { + pub async fn write( + self: Rc, + data: &[u8], + ) -> Result { let mut wr = self.wr_borrow_mut().await; let nwritten = wr.write(data).await?; Ok(nwritten) } - pub async fn shutdown(self: Rc) -> Result<(), AnyError> { + pub async fn shutdown(self: Rc) -> Result<(), std::io::Error> { let mut wr = self.wr_borrow_mut().await; wr.shutdown().await?; Ok(()) } } +#[derive(Debug, thiserror::Error)] +pub enum MapError { + #[error("{0}")] + Io(std::io::Error), + #[error("Unable to get resources")] + NoResources, +} + pub type TcpStreamResource = FullDuplexResource; @@ -100,7 +110,7 @@ impl Resource for TcpStreamResource { } fn shutdown(self: Rc) -> AsyncResult<()> { - Box::pin(self.shutdown()) + Box::pin(self.shutdown().map_err(Into::into)) } fn close(self: Rc) { @@ -109,31 +119,30 @@ impl Resource for TcpStreamResource { } impl TcpStreamResource { - pub fn set_nodelay(self: Rc, nodelay: bool) -> Result<(), AnyError> { - self.map_socket(Box::new(move |socket| Ok(socket.set_nodelay(nodelay)?))) + pub fn set_nodelay(self: Rc, nodelay: bool) -> Result<(), MapError> { + self.map_socket(Box::new(move |socket| socket.set_nodelay(nodelay))) } pub fn set_keepalive( self: Rc, keepalive: bool, - ) -> Result<(), AnyError> { - self - .map_socket(Box::new(move |socket| Ok(socket.set_keepalive(keepalive)?))) + ) -> Result<(), MapError> { + self.map_socket(Box::new(move |socket| socket.set_keepalive(keepalive))) } #[allow(clippy::type_complexity)] fn map_socket( self: Rc, - map: Box Result<(), AnyError>>, - ) -> Result<(), AnyError> { + map: Box Result<(), std::io::Error>>, + ) -> Result<(), MapError> { if let Some(wr) = RcRef::map(self, |r| &r.wr).try_borrow() { let stream = wr.as_ref().as_ref(); let socket = socket2::SockRef::from(stream); - return map(socket); + return map(socket).map_err(MapError::Io); } - Err(generic_error("Unable to get resources")) + Err(MapError::NoResources) } } @@ -153,7 +162,9 @@ impl UnixStreamResource { unreachable!() } #[allow(clippy::unused_async)] - pub async fn shutdown(self: Rc) -> Result<(), AnyError> { + pub async fn shutdown( + self: Rc, + ) -> Result<(), deno_core::error::AnyError> { unreachable!() } pub fn cancel_read_ops(&self) { @@ -170,7 +181,7 @@ impl Resource for UnixStreamResource { } fn shutdown(self: Rc) -> AsyncResult<()> { - Box::pin(self.shutdown()) + Box::pin(self.shutdown().map_err(Into::into)) } fn close(self: Rc) { diff --git a/ext/net/lib.deno_net.d.ts b/ext/net/lib.deno_net.d.ts index 13fbd35148..827081f2a4 100644 --- a/ext/net/lib.deno_net.d.ts +++ b/ext/net/lib.deno_net.d.ts @@ -35,15 +35,6 @@ declare namespace Deno { /** Return the address of the `Listener`. */ readonly addr: A; - /** - * Return the rid of the `Listener`. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; - [Symbol.asyncIterator](): AsyncIterableIterator; /** @@ -77,20 +68,61 @@ declare namespace Deno { export type UnixListener = Listener; /** @category Network */ - export interface Conn - extends Reader, Writer, Closer, Disposable { + export interface Conn extends Disposable { + /** Read the incoming data from the connection into an array buffer (`p`). + * + * Resolves to either the number of bytes read during the operation or EOF + * (`null`) if there was nothing more to read. + * + * It is possible for a read to successfully return with `0` bytes. This + * does not indicate EOF. + * + * **It is not guaranteed that the full buffer will be read in a single + * call.** + * + * ```ts + * // If the text "hello world" is received by the client: + * const conn = await Deno.connect({ hostname: "example.com", port: 80 }); + * const buf = new Uint8Array(100); + * const numberOfBytesRead = await conn.read(buf); // 11 bytes + * const text = new TextDecoder().decode(buf); // "hello world" + * ``` + * + * @category I/O + */ + read(p: Uint8Array): Promise; + /** Write the contents of the array buffer (`p`) to the connection. + * + * Resolves to the number of bytes written. + * + * **It is not guaranteed that the full buffer will be written in a single + * call.** + * + * ```ts + * const conn = await Deno.connect({ hostname: "example.com", port: 80 }); + * const encoder = new TextEncoder(); + * const data = encoder.encode("Hello world"); + * const bytesWritten = await conn.write(data); // 11 + * ``` + * + * @category I/O + */ + write(p: Uint8Array): Promise; + /** Closes the connection, freeing the resource. + * + * ```ts + * const conn = await Deno.connect({ hostname: "example.com", port: 80 }); + * + * // ... + * + * conn.close(); + * ``` + */ + close(): void; /** The local address of the connection. */ readonly localAddr: A; /** The remote address of the connection. */ readonly remoteAddr: A; - /** - * The resource ID of the connection. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; /** Shuts down (`shutdown(2)`) the write side of the connection. Most * callers should just use `close()`. */ closeWrite(): Promise; @@ -123,14 +155,6 @@ declare namespace Deno { * not happened yet. Calling this method is optional; the TLS handshake * will be completed automatically as soon as data is sent or received. */ handshake(): Promise; - /** - * The resource ID of the connection. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; } /** @category Network */ @@ -199,16 +223,6 @@ declare namespace Deno { options: UnixListenOptions & { transport: "unix" }, ): UnixListener; - /** Provides TLS certified keys, ie: a key that has been certified by a trusted certificate authority. - * A certified key generally consists of a private key and certificate part. - * - * @category Network - */ - export type TlsCertifiedKeyOptions = - | TlsCertifiedKeyPem - | TlsCertifiedKeyFromFile - | TlsCertifiedKeyConnectTls; - /** * Provides certified key material from strings. The key material is provided in * `PEM`-format (Privacy Enhanced Mail, https://www.rfc-editor.org/rfc/rfc1422) which can be identified by having @@ -235,59 +249,6 @@ declare namespace Deno { cert: string; } - /** - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Network - */ - export interface TlsCertifiedKeyFromFile { - /** Path to a file containing a PEM formatted CA certificate. Requires - * `--allow-read`. - * - * @tags allow-read - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - certFile: string; - /** Path to a file containing a private key file. Requires `--allow-read`. - * - * @tags allow-read - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - keyFile: string; - } - - /** - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Network - */ - export interface TlsCertifiedKeyConnectTls { - /** - * Certificate chain in `PEM` format. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - certChain: string; - /** - * Private key in `PEM` format. RSA, EC, and PKCS8-format keys are supported. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - privateKey: string; - } - /** @category Network */ export interface ListenTlsOptions extends TcpListenOptions { transport?: "tcp"; @@ -316,7 +277,7 @@ declare namespace Deno { * @category Network */ export function listenTls( - options: ListenTlsOptions & TlsCertifiedKeyOptions, + options: ListenTlsOptions & TlsCertifiedKeyPem, ): TlsListener; /** @category Network */ @@ -359,14 +320,6 @@ declare namespace Deno { setNoDelay(noDelay?: boolean): void; /** Enable/disable keep-alive functionality. */ setKeepAlive(keepAlive?: boolean): void; - /** - * The resource ID of the connection. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; } /** @category Network */ @@ -376,16 +329,7 @@ declare namespace Deno { } /** @category Network */ - export interface UnixConn extends Conn { - /** - * The resource ID of the connection. - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - readonly rid: number; - } + export interface UnixConn extends Conn {} /** Connects to the hostname (default is "127.0.0.1") and port on the named * transport (default is "tcp"), and resolves to the connection (`Conn`). @@ -414,16 +358,6 @@ declare namespace Deno { * * @default {"127.0.0.1"} */ hostname?: string; - /** Path to a file containing a PEM formatted list of root certificates that will - * be used in addition to the default root certificates to verify the peer's certificate. Requires - * `--allow-read`. - * - * @tags allow-read - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - */ - certFile?: string; /** A list of root certificates that will be used in addition to the * default root certificates to verify the peer's certificate. * @@ -437,9 +371,14 @@ declare namespace Deno { } /** Establishes a secure connection over TLS (transport layer security) using - * an optional cert file, hostname (default is "127.0.0.1") and port. The - * cert file is optional and if not included Mozilla's root certificates will - * be used (see also https://github.com/ctz/webpki-roots for specifics) + * an optional list of CA certs, hostname (default is "127.0.0.1") and port. + * + * The CA cert list is optional and if not included Mozilla's root + * certificates will be used (see also https://github.com/ctz/webpki-roots for + * specifics). + * + * Mutual TLS (mTLS or client certificates) are supported by providing a + * `key` and `cert` in the options as PEM-encoded strings. * * ```ts * const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem"); @@ -447,28 +386,10 @@ declare namespace Deno { * const conn2 = await Deno.connectTls({ caCerts: [caCert], hostname: "192.0.2.1", port: 80 }); * const conn3 = await Deno.connectTls({ hostname: "[2001:db8::1]", port: 80 }); * const conn4 = await Deno.connectTls({ caCerts: [caCert], hostname: "golang.org", port: 80}); - * ``` * - * Requires `allow-net` permission. - * - * @tags allow-net - * @category Network - */ - export function connectTls(options: ConnectTlsOptions): Promise; - - /** Establishes a secure connection over TLS (transport layer security) using - * an optional cert file, client certificate, hostname (default is "127.0.0.1") and - * port. The cert file is optional and if not included Mozilla's root certificates will - * be used (see also https://github.com/ctz/webpki-roots for specifics) - * - * ```ts - * const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem"); * const key = "----BEGIN PRIVATE KEY----..."; * const cert = "----BEGIN CERTIFICATE----..."; - * const conn1 = await Deno.connectTls({ port: 80, key, cert }); - * const conn2 = await Deno.connectTls({ caCerts: [caCert], hostname: "192.0.2.1", port: 80, key, cert }); - * const conn3 = await Deno.connectTls({ hostname: "[2001:db8::1]", port: 80, key, cert }); - * const conn4 = await Deno.connectTls({ caCerts: [caCert], hostname: "golang.org", port: 80, key, cert }); + * const conn5 = await Deno.connectTls({ port: 80, key, cert }); * ``` * * Requires `allow-net` permission. @@ -477,7 +398,7 @@ declare namespace Deno { * @category Network */ export function connectTls( - options: ConnectTlsOptions & TlsCertifiedKeyOptions, + options: ConnectTlsOptions | (ConnectTlsOptions & TlsCertifiedKeyPem), ): Promise; /** @category Network */ @@ -529,21 +450,5 @@ declare namespace Deno { options?: StartTlsOptions, ): Promise; - /** Shutdown socket send operations. - * - * Matches behavior of POSIX shutdown(3). - * - * ```ts - * const listener = Deno.listen({ port: 80 }); - * const conn = await listener.accept(); - * Deno.shutdown(conn.rid); - * ``` - * - * @deprecated This will be removed in Deno 2.0. See the - * {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide} - * for migration instructions. - * - * @category Network - */ - export function shutdown(rid: number): Promise; + export {}; // only export exports } diff --git a/ext/net/lib.rs b/ext/net/lib.rs index c0f94ce1c7..b039965d4c 100644 --- a/ext/net/lib.rs +++ b/ext/net/lib.rs @@ -13,6 +13,7 @@ use deno_core::error::AnyError; use deno_core::OpState; use deno_tls::rustls::RootCertStore; use deno_tls::RootCertStoreProvider; +use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -22,12 +23,27 @@ pub const UNSTABLE_FEATURE_NAME: &str = "net"; pub trait NetPermissions { fn check_net>( &mut self, - _host: &(T, Option), - _api_name: &str, + host: &(T, Option), + api_name: &str, ) -> Result<(), AnyError>; - fn check_read(&mut self, _p: &Path, _api_name: &str) -> Result<(), AnyError>; - fn check_write(&mut self, _p: &Path, _api_name: &str) - -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read( + &mut self, + p: &str, + api_name: &str, + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_write( + &mut self, + p: &str, + api_name: &str, + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_write_path<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result, AnyError>; } impl NetPermissions for deno_permissions::PermissionsContainer { @@ -43,29 +59,38 @@ impl NetPermissions for deno_permissions::PermissionsContainer { #[inline(always)] fn check_read( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_read(self, path, api_name) } #[inline(always)] fn check_write( &mut self, - path: &Path, + path: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_write(self, path, api_name) } + + #[inline(always)] + fn check_write_path<'a>( + &mut self, + path: &'a Path, + api_name: &str, + ) -> Result, AnyError> { + deno_permissions::PermissionsContainer::check_write_path( + self, path, api_name, + ) + } } /// Helper for checking unstable features. Used for sync ops. fn check_unstable(state: &OpState, api_name: &str) { - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` state .feature_checker - .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, api_name); + .check_or_exit(UNSTABLE_FEATURE_NAME, api_name); } pub fn get_declaration() -> PathBuf { @@ -115,7 +140,6 @@ deno_core::extension!(deno_net, ops_tls::op_tls_key_null, ops_tls::op_tls_key_static, - ops_tls::op_tls_key_static_from_file

, ops_tls::op_tls_cert_resolver_create, ops_tls::op_tls_cert_resolver_poll, ops_tls::op_tls_cert_resolver_resolve, diff --git a/ext/net/ops.rs b/ext/net/ops.rs index b74dc8d755..0f92dead0c 100644 --- a/ext/net/ops.rs +++ b/ext/net/ops.rs @@ -6,10 +6,6 @@ use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr_sync; use crate::tcp::TcpListener; use crate::NetPermissions; -use deno_core::error::bad_resource; -use deno_core::error::custom_error; -use deno_core::error::generic_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::CancelFuture; @@ -43,6 +39,7 @@ use trust_dns_proto::rr::record_type::RecordType; use trust_dns_resolver::config::NameServerConfigGroup; use trust_dns_resolver::config::ResolverConfig; use trust_dns_resolver::config::ResolverOpts; +use trust_dns_resolver::error::ResolveError; use trust_dns_resolver::error::ResolveErrorKind; use trust_dns_resolver::system_conf; use trust_dns_resolver::AsyncResolver; @@ -68,12 +65,69 @@ impl From for IpAddr { } } -pub(crate) fn accept_err(e: std::io::Error) -> AnyError { - // FIXME(bartlomieju): compatibility with current JS implementation +#[derive(Debug, thiserror::Error)] +pub enum NetError { + #[error("Listener has been closed")] + ListenerClosed, + #[error("Listener already in use")] + ListenerBusy, + #[error("Socket has been closed")] + SocketClosed, + #[error("Socket has been closed")] + SocketClosedNotConnected, + #[error("Socket already in use")] + SocketBusy, + #[error("{0}")] + Io(#[from] std::io::Error), + #[error("Another accept task is ongoing")] + AcceptTaskOngoing, + #[error("{0}")] + Permission(deno_core::error::AnyError), + #[error("{0}")] + Resource(deno_core::error::AnyError), + #[error("No resolved address found")] + NoResolvedAddress, + #[error("{0}")] + AddrParse(#[from] std::net::AddrParseError), + #[error("{0}")] + Map(crate::io::MapError), + #[error("{0}")] + Canceled(#[from] deno_core::Canceled), + #[error("{0}")] + DnsNotFound(ResolveError), + #[error("{0}")] + DnsNotConnected(ResolveError), + #[error("{0}")] + DnsTimedOut(ResolveError), + #[error("{0}")] + Dns(#[from] ResolveError), + #[error("Provided record type is not supported")] + UnsupportedRecordType, + #[error("File name or path {0:?} is not valid UTF-8")] + InvalidUtf8(std::ffi::OsString), + #[error("unexpected key type")] + UnexpectedKeyType, + #[error("Invalid hostname: '{0}'")] + InvalidHostname(String), // TypeError + #[error("TCP stream is currently in use")] + TcpStreamBusy, + #[error("{0}")] + Rustls(#[from] deno_tls::rustls::Error), + #[error("{0}")] + Tls(#[from] deno_tls::TlsError), + #[error("Error creating TLS certificate: Deno.listenTls requires a key")] + ListenTlsRequiresKey, // InvalidData + #[error("{0}")] + RootCertStore(deno_core::anyhow::Error), + #[error("{0}")] + Reunite(tokio::net::tcp::ReuniteError), +} + +pub(crate) fn accept_err(e: std::io::Error) -> NetError { if let std::io::ErrorKind::Interrupted = e.kind() { - bad_resource("Listener has been closed") + NetError::ListenerClosed } else { - e.into() + NetError::Io(e) } } @@ -82,15 +136,15 @@ pub(crate) fn accept_err(e: std::io::Error) -> AnyError { pub async fn op_net_accept_tcp( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> { +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> { let resource = state .borrow() .resource_table .get::>(rid) - .map_err(|_| bad_resource("Listener has been closed"))?; + .map_err(|_| NetError::ListenerClosed)?; let listener = RcRef::map(&resource, |r| &r.listener) .try_borrow_mut() - .ok_or_else(|| custom_error("Busy", "Another accept task is ongoing"))?; + .ok_or_else(|| NetError::AcceptTaskOngoing)?; let cancel = RcRef::map(resource, |r| &r.cancel); let (tcp_stream, _socket_addr) = listener .accept() @@ -113,12 +167,12 @@ pub async fn op_net_recv_udp( state: Rc>, #[smi] rid: ResourceId, #[buffer] mut buf: JsBuffer, -) -> Result<(usize, IpAddr), AnyError> { +) -> Result<(usize, IpAddr), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let cancel_handle = RcRef::map(&resource, |r| &r.cancel); let (nread, remote_addr) = socket @@ -135,27 +189,29 @@ pub async fn op_net_send_udp( #[smi] rid: ResourceId, #[serde] addr: IpAddr, #[buffer] zero_copy: JsBuffer, -) -> Result +) -> Result where NP: NetPermissions + 'static, { { let mut s = state.borrow_mut(); - s.borrow_mut::().check_net( - &(&addr.hostname, Some(addr.port)), - "Deno.DatagramConn.send()", - )?; + s.borrow_mut::() + .check_net( + &(&addr.hostname, Some(addr.port)), + "Deno.DatagramConn.send()", + ) + .map_err(NetError::Permission)?; } let addr = resolve_addr(&addr.hostname, addr.port) .await? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or(NetError::NoResolvedAddress)?; let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let nwritten = socket.send_to(&zero_copy, &addr).await?; @@ -168,12 +224,12 @@ pub async fn op_net_join_multi_v4_udp( #[smi] rid: ResourceId, #[string] address: String, #[string] multi_interface: String, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let addr = Ipv4Addr::from_str(address.as_str())?; @@ -190,12 +246,12 @@ pub async fn op_net_join_multi_v6_udp( #[smi] rid: ResourceId, #[string] address: String, #[smi] multi_interface: u32, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let addr = Ipv6Addr::from_str(address.as_str())?; @@ -211,12 +267,12 @@ pub async fn op_net_leave_multi_v4_udp( #[smi] rid: ResourceId, #[string] address: String, #[string] multi_interface: String, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let addr = Ipv4Addr::from_str(address.as_str())?; @@ -233,12 +289,12 @@ pub async fn op_net_leave_multi_v6_udp( #[smi] rid: ResourceId, #[string] address: String, #[smi] multi_interface: u32, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; let addr = Ipv6Addr::from_str(address.as_str())?; @@ -254,16 +310,16 @@ pub async fn op_net_set_multi_loopback_udp( #[smi] rid: ResourceId, is_v4_membership: bool, loopback: bool, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; if is_v4_membership { - socket.set_multicast_loop_v4(loopback)? + socket.set_multicast_loop_v4(loopback)?; } else { socket.set_multicast_loop_v6(loopback)?; } @@ -276,12 +332,12 @@ pub async fn op_net_set_multi_ttl_udp( state: Rc>, #[smi] rid: ResourceId, #[smi] ttl: u32, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let resource = state .borrow_mut() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket).borrow().await; socket.set_multicast_ttl_v4(ttl)?; @@ -294,7 +350,7 @@ pub async fn op_net_set_multi_ttl_udp( pub async fn op_net_connect_tcp( state: Rc>, #[serde] addr: IpAddr, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -305,7 +361,7 @@ where pub async fn op_net_connect_tcp_inner( state: Rc>, addr: IpAddr, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -313,13 +369,14 @@ where let mut state_ = state.borrow_mut(); state_ .borrow_mut::() - .check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()")?; + .check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()") + .map_err(NetError::Permission)?; } let addr = resolve_addr(&addr.hostname, addr.port) .await? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or_else(|| NetError::NoResolvedAddress)?; let tcp_stream = TcpStream::connect(&addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; @@ -354,7 +411,7 @@ pub fn op_net_listen_tcp( #[serde] addr: IpAddr, reuse_port: bool, load_balanced: bool, -) -> Result<(ResourceId, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -363,10 +420,11 @@ where } state .borrow_mut::() - .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()")?; + .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()") + .map_err(NetError::Permission)?; let addr = resolve_addr_sync(&addr.hostname, addr.port)? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or_else(|| NetError::NoResolvedAddress)?; let listener = if load_balanced { TcpListener::bind_load_balanced(addr) @@ -385,16 +443,17 @@ fn net_listen_udp( addr: IpAddr, reuse_address: bool, loopback: bool, -) -> Result<(ResourceId, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr), NetError> where NP: NetPermissions + 'static, { state .borrow_mut::() - .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")?; + .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()") + .map_err(NetError::Permission)?; let addr = resolve_addr_sync(&addr.hostname, addr.port)? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or_else(|| NetError::NoResolvedAddress)?; let domain = if addr.is_ipv4() { Domain::IPV4 @@ -454,7 +513,7 @@ pub fn op_net_listen_udp( #[serde] addr: IpAddr, reuse_address: bool, loopback: bool, -) -> Result<(ResourceId, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -469,7 +528,7 @@ pub fn op_node_unstable_net_listen_udp( #[serde] addr: IpAddr, reuse_address: bool, loopback: bool, -) -> Result<(ResourceId, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -552,7 +611,7 @@ pub struct NameServer { pub async fn op_dns_resolve( state: Rc>, #[serde] args: ResolveAddrArgs, -) -> Result, AnyError> +) -> Result, NetError> where NP: NetPermissions + 'static, { @@ -588,7 +647,9 @@ where let socker_addr = &ns.socket_addr; let ip = socker_addr.ip().to_string(); let port = socker_addr.port(); - perm.check_net(&(ip, Some(port)), "Deno.resolveDns()")?; + perm + .check_net(&(ip, Some(port)), "Deno.resolveDns()") + .map_err(NetError::Permission)?; } } @@ -619,22 +680,17 @@ where }; lookup - .map_err(|e| { - let message = format!("{e}"); - match e.kind() { - ResolveErrorKind::NoRecordsFound { .. } => { - custom_error("NotFound", message) - } - ResolveErrorKind::Message("No connections available") => { - custom_error("NotConnected", message) - } - ResolveErrorKind::Timeout => custom_error("TimedOut", message), - _ => generic_error(message), + .map_err(|e| match e.kind() { + ResolveErrorKind::NoRecordsFound { .. } => NetError::DnsNotFound(e), + ResolveErrorKind::Message("No connections available") => { + NetError::DnsNotConnected(e) } + ResolveErrorKind::Timeout => NetError::DnsTimedOut(e), + _ => NetError::Dns(e), })? .iter() .filter_map(|rdata| rdata_to_return_record(record_type)(rdata).transpose()) - .collect::, AnyError>>() + .collect::, NetError>>() } #[op2(fast)] @@ -642,7 +698,7 @@ pub fn op_set_nodelay( state: &mut OpState, #[smi] rid: ResourceId, nodelay: bool, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { op_set_nodelay_inner(state, rid, nodelay) } @@ -651,10 +707,12 @@ pub fn op_set_nodelay_inner( state: &mut OpState, rid: ResourceId, nodelay: bool, -) -> Result<(), AnyError> { - let resource: Rc = - state.resource_table.get::(rid)?; - resource.set_nodelay(nodelay) +) -> Result<(), NetError> { + let resource: Rc = state + .resource_table + .get::(rid) + .map_err(NetError::Resource)?; + resource.set_nodelay(nodelay).map_err(NetError::Map) } #[op2(fast)] @@ -662,7 +720,7 @@ pub fn op_set_keepalive( state: &mut OpState, #[smi] rid: ResourceId, keepalive: bool, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { op_set_keepalive_inner(state, rid, keepalive) } @@ -671,17 +729,19 @@ pub fn op_set_keepalive_inner( state: &mut OpState, rid: ResourceId, keepalive: bool, -) -> Result<(), AnyError> { - let resource: Rc = - state.resource_table.get::(rid)?; - resource.set_keepalive(keepalive) +) -> Result<(), NetError> { + let resource: Rc = state + .resource_table + .get::(rid) + .map_err(NetError::Resource)?; + resource.set_keepalive(keepalive).map_err(NetError::Map) } fn rdata_to_return_record( ty: RecordType, -) -> impl Fn(&RData) -> Result, AnyError> { +) -> impl Fn(&RData) -> Result, NetError> { use RecordType::*; - move |r: &RData| -> Result, AnyError> { + move |r: &RData| -> Result, NetError> { let record = match ty { A => r.as_a().map(ToString::to_string).map(DnsReturnRecord::A), AAAA => r @@ -762,12 +822,7 @@ fn rdata_to_return_record( .collect(); DnsReturnRecord::Txt(texts) }), - _ => { - return Err(custom_error( - "NotSupported", - "Provided record type is not supported", - )) - } + _ => return Err(NetError::UnsupportedRecordType), }; Ok(record) } @@ -784,6 +839,7 @@ mod tests { use std::net::Ipv6Addr; use std::net::ToSocketAddrs; use std::path::Path; + use std::path::PathBuf; use std::sync::Arc; use std::sync::Mutex; use trust_dns_proto::rr::rdata::a::A; @@ -985,24 +1041,32 @@ mod tests { &mut self, _host: &(T, Option), _api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), deno_core::error::AnyError> { Ok(()) } fn check_read( &mut self, - _p: &Path, + p: &str, _api_name: &str, - ) -> Result<(), AnyError> { - Ok(()) + ) -> Result { + Ok(PathBuf::from(p)) } fn check_write( &mut self, - _p: &Path, + p: &str, _api_name: &str, - ) -> Result<(), AnyError> { - Ok(()) + ) -> Result { + Ok(PathBuf::from(p)) + } + + fn check_write_path<'a>( + &mut self, + p: &'a Path, + _api_name: &str, + ) -> Result, deno_core::error::AnyError> { + Ok(Cow::Borrowed(p)) } } @@ -1054,12 +1118,9 @@ mod tests { } ); - let mut feature_checker = deno_core::FeatureChecker::default(); - feature_checker.enable_legacy_unstable(); - let mut runtime = JsRuntime::new(RuntimeOptions { extensions: vec![test_ext::init_ops()], - feature_checker: Some(Arc::new(feature_checker)), + feature_checker: Some(Arc::new(Default::default())), ..Default::default() }); @@ -1086,7 +1147,7 @@ mod tests { let vals = result.unwrap(); rid = rid.or(Some(vals.0)); } - }; + } let rid = rid.unwrap(); let state = runtime.op_state(); diff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs index 8483e7e668..c7d65dd85e 100644 --- a/ext/net/ops_tls.rs +++ b/ext/net/ops_tls.rs @@ -2,6 +2,7 @@ use crate::io::TcpStreamResource; use crate::ops::IpAddr; +use crate::ops::NetError; use crate::ops::TlsHandshakeInfo; use crate::raw::NetworkListenerResource; use crate::resolve_addr::resolve_addr; @@ -10,13 +11,7 @@ use crate::tcp::TcpListener; use crate::DefaultTlsOptions; use crate::NetPermissions; use crate::UnsafelyIgnoreCertificateErrors; -use deno_core::anyhow::anyhow; -use deno_core::anyhow::bail; -use deno_core::error::bad_resource; -use deno_core::error::custom_error; -use deno_core::error::generic_error; -use deno_core::error::invalid_hostname; -use deno_core::error::AnyError; +use deno_core::futures::TryFutureExt; use deno_core::op2; use deno_core::v8; use deno_core::AsyncRefCell; @@ -34,8 +29,6 @@ use deno_tls::new_resolver; use deno_tls::rustls::pki_types::ServerName; use deno_tls::rustls::ClientConnection; use deno_tls::rustls::ServerConfig; -use deno_tls::webpki::types::CertificateDer; -use deno_tls::webpki::types::PrivateKeyDer; use deno_tls::ServerConfigProvider; use deno_tls::SocketUse; use deno_tls::TlsKey; @@ -54,7 +47,6 @@ use std::io::ErrorKind; use std::io::Read; use std::net::SocketAddr; use std::num::NonZeroUsize; -use std::path::Path; use std::rc::Rc; use std::sync::Arc; use tokio::io::AsyncReadExt; @@ -121,20 +113,23 @@ impl TlsStreamResource { pub async fn read( self: Rc, data: &mut [u8], - ) -> Result { + ) -> Result { let mut rd = RcRef::map(&self, |r| &r.rd).borrow_mut().await; let cancel_handle = RcRef::map(&self, |r| &r.cancel_handle); - Ok(rd.read(data).try_or_cancel(cancel_handle).await?) + rd.read(data).try_or_cancel(cancel_handle).await } - pub async fn write(self: Rc, data: &[u8]) -> Result { + pub async fn write( + self: Rc, + data: &[u8], + ) -> Result { let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await; let nwritten = wr.write(data).await?; wr.flush().await?; Ok(nwritten) } - pub async fn shutdown(self: Rc) -> Result<(), AnyError> { + pub async fn shutdown(self: Rc) -> Result<(), std::io::Error> { let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await; wr.shutdown().await?; Ok(()) @@ -142,7 +137,7 @@ impl TlsStreamResource { pub async fn handshake( self: &Rc, - ) -> Result { + ) -> Result { if let Some(tls_info) = &*self.handshake_info.borrow() { return Ok(tls_info.clone()); } @@ -167,7 +162,7 @@ impl Resource for TlsStreamResource { } fn shutdown(self: Rc) -> AsyncResult<()> { - Box::pin(self.shutdown()) + Box::pin(self.shutdown().map_err(Into::into)) } fn close(self: Rc) { @@ -204,7 +199,7 @@ pub fn op_tls_key_null() -> TlsKeysHolder { pub fn op_tls_key_static( #[string] cert: &str, #[string] key: &str, -) -> Result { +) -> Result { let cert = load_certs(&mut BufReader::new(cert.as_bytes()))?; let key = load_private_keys(key.as_bytes())? .into_iter() @@ -213,32 +208,6 @@ pub fn op_tls_key_static( Ok(TlsKeysHolder::from(TlsKeys::Static(TlsKey(cert, key)))) } -/// Legacy op -- will be removed in Deno 2.0. -#[op2] -#[cppgc] -pub fn op_tls_key_static_from_file( - state: &mut OpState, - #[string] api: String, - #[string] cert_file: String, - #[string] key_file: String, -) -> Result -where - NP: NetPermissions + 'static, -{ - { - let permissions = state.borrow_mut::(); - permissions.check_read(Path::new(&cert_file), &api)?; - permissions.check_read(Path::new(&key_file), &api)?; - } - - let cert = load_certs_from_file(&cert_file)?; - let key = load_private_keys_from_file(&key_file)? - .into_iter() - .next() - .unwrap(); - Ok(TlsKeysHolder::from(TlsKeys::Static(TlsKey(cert, key)))) -} - #[op2] pub fn op_tls_cert_resolver_create<'s>( scope: &mut v8::HandleScope<'s>, @@ -265,9 +234,9 @@ pub fn op_tls_cert_resolver_resolve( #[cppgc] lookup: &TlsKeyLookup, #[string] sni: String, #[cppgc] key: &TlsKeysHolder, -) -> Result<(), AnyError> { +) -> Result<(), NetError> { let TlsKeys::Static(key) = key.take() else { - bail!("unexpected key type"); + return Err(NetError::UnexpectedKeyType); }; lookup.resolve(sni, Ok(key)); Ok(()) @@ -279,7 +248,7 @@ pub fn op_tls_cert_resolver_resolve_error( #[string] sni: String, #[string] error: String, ) { - lookup.resolve(sni, Err(anyhow!(error))) + lookup.resolve(sni, Err(error)) } #[op2] @@ -287,7 +256,7 @@ pub fn op_tls_cert_resolver_resolve_error( pub fn op_tls_start( state: Rc>, #[serde] args: StartTlsArgs, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -300,7 +269,9 @@ where { let mut s = state.borrow_mut(); let permissions = s.borrow_mut::(); - permissions.check_net(&(&hostname, Some(0)), "Deno.startTls()")?; + permissions + .check_net(&(&hostname, Some(0)), "Deno.startTls()") + .map_err(NetError::Permission)?; } let ca_certs = args @@ -310,7 +281,7 @@ where .collect::>(); let hostname_dns = ServerName::try_from(hostname.to_string()) - .map_err(|_| invalid_hostname(&hostname))?; + .map_err(|_| NetError::InvalidHostname(hostname))?; let unsafely_ignore_certificate_errors = state .borrow() @@ -320,19 +291,21 @@ where let root_cert_store = state .borrow() .borrow::() - .root_cert_store()?; + .root_cert_store() + .map_err(NetError::RootCertStore)?; let resource_rc = state .borrow_mut() .resource_table - .take::(rid)?; + .take::(rid) + .map_err(NetError::Resource)?; // This TCP connection might be used somewhere else. If it's the case, we cannot proceed with the - // process of starting a TLS connection on top of this TCP connection, so we just return a bad - // resource error. See also: https://github.com/denoland/deno/pull/16242 - let resource = Rc::try_unwrap(resource_rc) - .map_err(|_| bad_resource("TCP stream is currently in use"))?; + // process of starting a TLS connection on top of this TCP connection, so we just return a Busy error. + // See also: https://github.com/denoland/deno/pull/16242 + let resource = + Rc::try_unwrap(resource_rc).map_err(|_| NetError::TcpStreamBusy)?; let (read_half, write_half) = resource.into_inner(); - let tcp_stream = read_half.reunite(write_half)?; + let tcp_stream = read_half.reunite(write_half).map_err(NetError::Reunite)?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; @@ -374,7 +347,7 @@ pub async fn op_net_connect_tls( #[serde] addr: IpAddr, #[serde] args: ConnectTlsArgs, #[cppgc] key_pair: &TlsKeysHolder, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -384,15 +357,22 @@ where .try_borrow::() .and_then(|it| it.0.clone()); - { + let cert_file = { let mut s = state.borrow_mut(); let permissions = s.borrow_mut::(); permissions - .check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()")?; + .check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()") + .map_err(NetError::Permission)?; if let Some(path) = cert_file { - permissions.check_read(Path::new(path), "Deno.connectTls()")?; + Some( + permissions + .check_read(path, "Deno.connectTls()") + .map_err(NetError::Permission)?, + ) + } else { + None } - } + }; let mut ca_certs = args .ca_certs @@ -409,17 +389,18 @@ where let root_cert_store = state .borrow() .borrow::() - .root_cert_store()?; + .root_cert_store() + .map_err(NetError::RootCertStore)?; let hostname_dns = if let Some(server_name) = args.server_name { ServerName::try_from(server_name) } else { ServerName::try_from(addr.hostname.clone()) } - .map_err(|_| invalid_hostname(&addr.hostname))?; + .map_err(|_| NetError::InvalidHostname(addr.hostname.clone()))?; let connect_addr = resolve_addr(&addr.hostname, addr.port) .await? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or_else(|| NetError::NoResolvedAddress)?; let tcp_stream = TcpStream::connect(connect_addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; @@ -455,21 +436,6 @@ where Ok((rid, IpAddr::from(local_addr), IpAddr::from(remote_addr))) } -fn load_certs_from_file( - path: &str, -) -> Result>, AnyError> { - let cert_file = File::open(path)?; - let reader = &mut BufReader::new(cert_file); - load_certs(reader) -} - -fn load_private_keys_from_file( - path: &str, -) -> Result>, AnyError> { - let key_bytes = std::fs::read(path)?; - load_private_keys(&key_bytes) -} - #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct ListenTlsArgs { @@ -486,7 +452,7 @@ pub fn op_net_listen_tls( #[serde] addr: IpAddr, #[serde] args: ListenTlsArgs, #[cppgc] keys: &TlsKeysHolder, -) -> Result<(ResourceId, IpAddr), AnyError> +) -> Result<(ResourceId, IpAddr), NetError> where NP: NetPermissions + 'static, { @@ -497,12 +463,13 @@ where { let permissions = state.borrow_mut::(); permissions - .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenTls()")?; + .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenTls()") + .map_err(NetError::Permission)?; } let bind_addr = resolve_addr_sync(&addr.hostname, addr.port)? .next() - .ok_or_else(|| generic_error("No resolved address found"))?; + .ok_or(NetError::NoResolvedAddress)?; let tcp_listener = if args.load_balanced { TcpListener::bind_load_balanced(bind_addr) @@ -517,28 +484,24 @@ where .map(|s| s.into_bytes()) .collect(); let listener = match keys.take() { - TlsKeys::Null => Err(anyhow!("Deno.listenTls requires a key")), + TlsKeys::Null => return Err(NetError::ListenTlsRequiresKey), TlsKeys::Static(TlsKey(cert, key)) => { let mut tls_config = ServerConfig::builder() .with_no_client_auth() - .with_single_cert(cert, key) - .map_err(|e| anyhow!(e))?; + .with_single_cert(cert, key)?; tls_config.alpn_protocols = alpn; - Ok(TlsListener { + TlsListener { tcp_listener, tls_config: Some(tls_config.into()), server_config_provider: None, - }) + } } - TlsKeys::Resolver(resolver) => Ok(TlsListener { + TlsKeys::Resolver(resolver) => TlsListener { tcp_listener, tls_config: None, server_config_provider: Some(resolver.into_server_config_provider(alpn)), - }), - } - .map_err(|e| { - custom_error("InvalidData", "Error creating TLS certificate").context(e) - })?; + }, + }; let tls_listener_resource = NetworkListenerResource::new(listener); @@ -552,24 +515,23 @@ where pub async fn op_net_accept_tls( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> { +) -> Result<(ResourceId, IpAddr, IpAddr), NetError> { let resource = state .borrow() .resource_table .get::>(rid) - .map_err(|_| bad_resource("Listener has been closed"))?; + .map_err(|_| NetError::ListenerClosed)?; let cancel_handle = RcRef::map(&resource, |r| &r.cancel); let listener = RcRef::map(&resource, |r| &r.listener) .try_borrow_mut() - .ok_or_else(|| custom_error("Busy", "Another accept task is ongoing"))?; + .ok_or_else(|| NetError::AcceptTaskOngoing)?; let (tls_stream, remote_addr) = match listener.accept().try_or_cancel(&cancel_handle).await { Ok(tuple) => tuple, Err(err) if err.kind() == ErrorKind::Interrupted => { - // FIXME(bartlomieju): compatibility with current JS implementation. - return Err(bad_resource("Listener has been closed")); + return Err(NetError::ListenerClosed); } Err(err) => return Err(err.into()), }; @@ -590,11 +552,11 @@ pub async fn op_net_accept_tls( pub async fn op_tls_handshake( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let resource = state .borrow() .resource_table .get::(rid) - .map_err(|_| bad_resource("Listener has been closed"))?; - resource.handshake().await + .map_err(|_| NetError::ListenerClosed)?; + resource.handshake().await.map_err(Into::into) } diff --git a/ext/net/ops_unix.rs b/ext/net/ops_unix.rs index 7d2f6af3cb..04ae84906f 100644 --- a/ext/net/ops_unix.rs +++ b/ext/net/ops_unix.rs @@ -1,11 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::io::UnixStreamResource; +use crate::ops::NetError; use crate::raw::NetworkListenerResource; use crate::NetPermissions; -use deno_core::error::bad_resource; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::AsyncRefCell; use deno_core::CancelHandle; @@ -26,11 +24,8 @@ use tokio::net::UnixListener; pub use tokio::net::UnixStream; /// A utility function to map OsStrings to Strings -pub fn into_string(s: std::ffi::OsString) -> Result { - s.into_string().map_err(|s| { - let message = format!("File name or path {s:?} is not valid UTF-8"); - custom_error("InvalidData", message) - }) +pub fn into_string(s: std::ffi::OsString) -> Result { + s.into_string().map_err(NetError::InvalidUtf8) } pub struct UnixDatagramResource { @@ -63,15 +58,15 @@ pub struct UnixListenArgs { pub async fn op_net_accept_unix( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(ResourceId, Option, Option), AnyError> { +) -> Result<(ResourceId, Option, Option), NetError> { let resource = state .borrow() .resource_table .get::>(rid) - .map_err(|_| bad_resource("Listener has been closed"))?; + .map_err(|_| NetError::ListenerClosed)?; let listener = RcRef::map(&resource, |r| &r.listener) .try_borrow_mut() - .ok_or_else(|| custom_error("Busy", "Listener already in use"))?; + .ok_or(NetError::ListenerBusy)?; let cancel = RcRef::map(resource, |r| &r.cancel); let (unix_stream, _socket_addr) = listener .accept() @@ -94,22 +89,24 @@ pub async fn op_net_accept_unix( #[serde] pub async fn op_net_connect_unix( state: Rc>, - #[string] path: String, -) -> Result<(ResourceId, Option, Option), AnyError> + #[string] address_path: String, +) -> Result<(ResourceId, Option, Option), NetError> where NP: NetPermissions + 'static, { - let address_path = Path::new(&path); - { + let address_path = { let mut state_ = state.borrow_mut(); - state_ + let address_path = state_ .borrow_mut::() - .check_read(address_path, "Deno.connect()")?; - state_ + .check_read(&address_path, "Deno.connect()") + .map_err(NetError::Permission)?; + _ = state_ .borrow_mut::() - .check_write(address_path, "Deno.connect()")?; - } - let unix_stream = UnixStream::connect(Path::new(&path)).await?; + .check_write_path(&address_path, "Deno.connect()") + .map_err(NetError::Permission)?; + address_path + }; + let unix_stream = UnixStream::connect(&address_path).await?; let local_addr = unix_stream.local_addr()?; let remote_addr = unix_stream.peer_addr()?; let local_addr_path = local_addr.as_pathname().map(pathstring).transpose()?; @@ -127,15 +124,15 @@ pub async fn op_net_recv_unixpacket( state: Rc>, #[smi] rid: ResourceId, #[buffer] mut buf: JsBuffer, -) -> Result<(usize, Option), AnyError> { +) -> Result<(usize, Option), NetError> { let resource = state .borrow() .resource_table .get::(rid) - .map_err(|_| bad_resource("Socket has been closed"))?; + .map_err(|_| NetError::SocketClosed)?; let socket = RcRef::map(&resource, |r| &r.socket) .try_borrow_mut() - .ok_or_else(|| custom_error("Busy", "Socket already in use"))?; + .ok_or(NetError::SocketBusy)?; let cancel = RcRef::map(resource, |r| &r.cancel); let (nread, remote_addr) = socket.recv_from(&mut buf).try_or_cancel(cancel).await?; @@ -148,27 +145,27 @@ pub async fn op_net_recv_unixpacket( pub async fn op_net_send_unixpacket( state: Rc>, #[smi] rid: ResourceId, - #[string] path: String, + #[string] address_path: String, #[buffer] zero_copy: JsBuffer, -) -> Result +) -> Result where NP: NetPermissions + 'static, { - let address_path = Path::new(&path); - { + let address_path = { let mut s = state.borrow_mut(); s.borrow_mut::() - .check_write(address_path, "Deno.DatagramConn.send()")?; - } + .check_write(&address_path, "Deno.DatagramConn.send()") + .map_err(NetError::Permission)? + }; let resource = state .borrow() .resource_table .get::(rid) - .map_err(|_| custom_error("NotConnected", "Socket has been closed"))?; + .map_err(|_| NetError::SocketClosedNotConnected)?; let socket = RcRef::map(&resource, |r| &r.socket) .try_borrow_mut() - .ok_or_else(|| custom_error("Busy", "Socket already in use"))?; + .ok_or(NetError::SocketBusy)?; let nwritten = socket.send_to(&zero_copy, address_path).await?; Ok(nwritten) @@ -178,17 +175,20 @@ where #[serde] pub fn op_net_listen_unix( state: &mut OpState, - #[string] path: String, + #[string] address_path: String, #[string] api_name: String, -) -> Result<(ResourceId, Option), AnyError> +) -> Result<(ResourceId, Option), NetError> where NP: NetPermissions + 'static, { - let address_path = Path::new(&path); let permissions = state.borrow_mut::(); let api_call_expr = format!("{}()", api_name); - permissions.check_read(address_path, &api_call_expr)?; - permissions.check_write(address_path, &api_call_expr)?; + let address_path = permissions + .check_read(&address_path, &api_call_expr) + .map_err(NetError::Permission)?; + _ = permissions + .check_write_path(&address_path, &api_call_expr) + .map_err(NetError::Permission)?; let listener = UnixListener::bind(address_path)?; let local_addr = listener.local_addr()?; let pathname = local_addr.as_pathname().map(pathstring).transpose()?; @@ -199,15 +199,18 @@ where pub fn net_listen_unixpacket( state: &mut OpState, - path: String, -) -> Result<(ResourceId, Option), AnyError> + address_path: String, +) -> Result<(ResourceId, Option), NetError> where NP: NetPermissions + 'static, { - let address_path = Path::new(&path); let permissions = state.borrow_mut::(); - permissions.check_read(address_path, "Deno.listenDatagram()")?; - permissions.check_write(address_path, "Deno.listenDatagram()")?; + let address_path = permissions + .check_read(&address_path, "Deno.listenDatagram()") + .map_err(NetError::Permission)?; + _ = permissions + .check_write_path(&address_path, "Deno.listenDatagram()") + .map_err(NetError::Permission)?; let socket = UnixDatagram::bind(address_path)?; let local_addr = socket.local_addr()?; let pathname = local_addr.as_pathname().map(pathstring).transpose()?; @@ -224,7 +227,7 @@ where pub fn op_net_listen_unixpacket( state: &mut OpState, #[string] path: String, -) -> Result<(ResourceId, Option), AnyError> +) -> Result<(ResourceId, Option), NetError> where NP: NetPermissions + 'static, { @@ -237,13 +240,13 @@ where pub fn op_node_unstable_net_listen_unixpacket( state: &mut OpState, #[string] path: String, -) -> Result<(ResourceId, Option), AnyError> +) -> Result<(ResourceId, Option), NetError> where NP: NetPermissions + 'static, { net_listen_unixpacket::(state, path) } -pub fn pathstring(pathname: &Path) -> Result { +pub fn pathstring(pathname: &Path) -> Result { into_string(pathname.into()) } diff --git a/ext/net/raw.rs b/ext/net/raw.rs index f2de760652..a2ebfb5acb 100644 --- a/ext/net/raw.rs +++ b/ext/net/raw.rs @@ -1,8 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::io::TcpStreamResource; use crate::ops_tls::TlsStreamResource; -use deno_core::error::bad_resource; use deno_core::error::bad_resource_id; +use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::AsyncRefCell; use deno_core::CancelHandle; @@ -70,7 +70,7 @@ impl NetworkListenerResource { ) -> Result, AnyError> { if let Ok(resource_rc) = resource_table.take::(listener_rid) { let resource = Rc::try_unwrap(resource_rc) - .map_err(|_| bad_resource("Listener is currently in use"))?; + .map_err(|_| custom_error("Busy", "Listener is currently in use"))?; return Ok(Some(resource.listener.into_inner().into())); } Ok(None) @@ -334,7 +334,7 @@ pub fn take_network_stream_resource( { // This TCP connection might be used somewhere else. let resource = Rc::try_unwrap(resource_rc) - .map_err(|_| bad_resource("TCP stream is currently in use"))?; + .map_err(|_| custom_error("Busy", "TCP stream is currently in use"))?; let (read_half, write_half) = resource.into_inner(); let tcp_stream = read_half.reunite(write_half)?; return Ok(NetworkStream::Tcp(tcp_stream)); @@ -344,7 +344,7 @@ pub fn take_network_stream_resource( { // This TLS connection might be used somewhere else. let resource = Rc::try_unwrap(resource_rc) - .map_err(|_| bad_resource("TLS stream is currently in use"))?; + .map_err(|_| custom_error("Busy", "TLS stream is currently in use"))?; let (read_half, write_half) = resource.into_inner(); let tls_stream = read_half.unsplit(write_half); return Ok(NetworkStream::Tls(tls_stream)); @@ -356,7 +356,7 @@ pub fn take_network_stream_resource( { // This UNIX socket might be used somewhere else. let resource = Rc::try_unwrap(resource_rc) - .map_err(|_| bad_resource("UNIX stream is currently in use"))?; + .map_err(|_| custom_error("Busy", "Unix socket is currently in use"))?; let (read_half, write_half) = resource.into_inner(); let unix_stream = read_half.reunite(write_half)?; return Ok(NetworkStream::Unix(unix_stream)); diff --git a/ext/net/resolve_addr.rs b/ext/net/resolve_addr.rs index 8bbdd5192c..3a97081eac 100644 --- a/ext/net/resolve_addr.rs +++ b/ext/net/resolve_addr.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use std::net::SocketAddr; use std::net::ToSocketAddrs; use tokio::net::lookup_host; @@ -9,7 +8,7 @@ use tokio::net::lookup_host; pub async fn resolve_addr( hostname: &str, port: u16, -) -> Result + '_, AnyError> { +) -> Result + '_, std::io::Error> { let addr_port_pair = make_addr_port_pair(hostname, port); let result = lookup_host(addr_port_pair).await?; Ok(result) @@ -19,7 +18,7 @@ pub async fn resolve_addr( pub fn resolve_addr_sync( hostname: &str, port: u16, -) -> Result, AnyError> { +) -> Result, std::io::Error> { let addr_port_pair = make_addr_port_pair(hostname, port); let result = addr_port_pair.to_socket_addrs()?; Ok(result) diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index b33540b024..3743e6a85e 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_node" -version = "0.101.0" +version = "0.111.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -17,7 +17,7 @@ path = "lib.rs" sync_fs = ["deno_package_json/sync", "node_resolver/sync"] [dependencies] -aead-gcm-stream = "0.1" +aead-gcm-stream = "0.3" aes.workspace = true async-trait.workspace = true base64.workspace = true @@ -34,11 +34,12 @@ deno_io.workspace = true deno_media_type.workspace = true deno_net.workspace = true deno_package_json.workspace = true +deno_path_util.workspace = true deno_permissions.workspace = true deno_whoami = "0.1.0" der = { version = "0.7.9", features = ["derive"] } digest = { version = "0.10.5", features = ["core-api", "std"] } -dsa = "0.6.1" +dsa = "0.6.3" ecb.workspace = true ecdsa = "0.16.9" ed25519-dalek = { version = "2.1.1", features = ["digest", "pkcs8", "rand_core", "signature"] } @@ -81,23 +82,24 @@ ring.workspace = true ripemd = { version = "0.1.3", features = ["oid"] } rsa.workspace = true scrypt = "0.11.0" -sec1 = "0.7" +sec1.workspace = true serde = "1.0.149" sha1.workspace = true sha2.workspace = true sha3 = { version = "0.10.8", features = ["oid"] } signature.workspace = true -simd-json = "0.13.4" +simd-json = "0.14.0" sm3 = "0.4.2" spki.workspace = true stable_deref_trait = "1.2.0" thiserror.workspace = true tokio.workspace = true url.workspace = true +webpki-root-certs.workspace = true winapi.workspace = true x25519-dalek = { version = "2.0.0", features = ["static_secrets"] } x509-parser = "0.15.0" -yoke = { version = "0.7.4", features = ["derive"] } +yoke.workspace = true [target.'cfg(windows)'.dependencies] windows-sys.workspace = true diff --git a/ext/node/benchmarks/child_process_ipc.mjs b/ext/node/benchmarks/child_process_ipc.mjs index 7a5c992bd3..fa671d76f7 100644 --- a/ext/node/benchmarks/child_process_ipc.mjs +++ b/ext/node/benchmarks/child_process_ipc.mjs @@ -29,6 +29,7 @@ if (process.env.CHILD) { const start = performance.now(); const options = { + __proto__: null, "stdio": ["inherit", "inherit", "inherit", "ipc"], "env": { "CHILD": len.toString() }, }; diff --git a/ext/node/global.rs b/ext/node/global.rs index 0b4adfc7d1..4d6695431d 100644 --- a/ext/node/global.rs +++ b/ext/node/global.rs @@ -52,10 +52,8 @@ const fn str_to_utf16(s: &str) -> [u16; N] { // - clearImmediate (node only) // - clearInterval (both, but different implementation) // - clearTimeout (both, but different implementation) -// - console (both, but different implementation) // - global (node only) // - performance (both, but different implementation) -// - process (node only) // - setImmediate (node only) // - setInterval (both, but different implementation) // - setTimeout (both, but different implementation) @@ -63,16 +61,14 @@ const fn str_to_utf16(s: &str) -> [u16; N] { // UTF-16 encodings of the managed globals. THIS LIST MUST BE SORTED. #[rustfmt::skip] -const MANAGED_GLOBALS: [&[u16]; 14] = [ +const MANAGED_GLOBALS: [&[u16]; 12] = [ &str_to_utf16::<6>("Buffer"), &str_to_utf16::<17>("WorkerGlobalScope"), &str_to_utf16::<14>("clearImmediate"), &str_to_utf16::<13>("clearInterval"), &str_to_utf16::<12>("clearTimeout"), - &str_to_utf16::<7>("console"), &str_to_utf16::<6>("global"), &str_to_utf16::<11>("performance"), - &str_to_utf16::<7>("process"), &str_to_utf16::<4>("self"), &str_to_utf16::<12>("setImmediate"), &str_to_utf16::<11>("setInterval"), diff --git a/ext/node/lib.rs b/ext/node/lib.rs index a820c4476f..32624f38b7 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -3,8 +3,10 @@ #![deny(clippy::print_stderr)] #![deny(clippy::print_stdout)] +use std::borrow::Cow; use std::collections::HashSet; use std::path::Path; +use std::path::PathBuf; use deno_core::error::AnyError; use deno_core::located_script_name; @@ -14,7 +16,6 @@ use deno_core::url::Url; use deno_core::v8; use deno_core::v8::ExternalReference; use deno_core::JsRuntime; -use deno_core::OpState; use deno_fs::sync::MaybeSend; use deno_fs::sync::MaybeSync; use node_resolver::NpmResolverRc; @@ -23,7 +24,7 @@ use once_cell::sync::Lazy; extern crate libz_sys as zlib; mod global; -mod ops; +pub mod ops; mod polyfill; pub use deno_package_json::PackageJson; @@ -49,54 +50,30 @@ pub trait NodePermissions { url: &Url, api_name: &str, ) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] #[inline(always)] - fn check_read(&mut self, path: &Path) -> Result<(), AnyError> { + fn check_read(&mut self, path: &str) -> Result { self.check_read_with_api_name(path, None) } + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] fn check_read_with_api_name( &mut self, - path: &Path, + path: &str, api_name: Option<&str>, - ) -> Result<(), AnyError>; + ) -> Result; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read_path<'a>( + &mut self, + path: &'a Path, + ) -> Result, AnyError>; + fn query_read_all(&mut self) -> bool; fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] fn check_write_with_api_name( &mut self, - path: &Path, + path: &str, api_name: Option<&str>, - ) -> Result<(), AnyError>; -} - -pub struct AllowAllNodePermissions; - -impl NodePermissions for AllowAllNodePermissions { - fn check_net_url( - &mut self, - _url: &Url, - _api_name: &str, - ) -> Result<(), AnyError> { - Ok(()) - } - fn check_read_with_api_name( - &mut self, - _path: &Path, - _api_name: Option<&str>, - ) -> Result<(), AnyError> { - Ok(()) - } - fn check_write_with_api_name( - &mut self, - _path: &Path, - _api_name: Option<&str>, - ) -> Result<(), AnyError> { - Ok(()) - } - fn check_sys( - &mut self, - _kind: &str, - _api_name: &str, - ) -> Result<(), AnyError> { - Ok(()) - } + ) -> Result; } impl NodePermissions for deno_permissions::PermissionsContainer { @@ -112,20 +89,31 @@ impl NodePermissions for deno_permissions::PermissionsContainer { #[inline(always)] fn check_read_with_api_name( &mut self, - path: &Path, + path: &str, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_read_with_api_name( self, path, api_name, ) } + fn check_read_path<'a>( + &mut self, + path: &'a Path, + ) -> Result, AnyError> { + deno_permissions::PermissionsContainer::check_read_path(self, path, None) + } + + fn query_read_all(&mut self) -> bool { + deno_permissions::PermissionsContainer::query_read_all(self) + } + #[inline(always)] fn check_write_with_api_name( &mut self, - path: &Path, + path: &str, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result { deno_permissions::PermissionsContainer::check_write_with_api_name( self, path, api_name, ) @@ -136,34 +124,17 @@ impl NodePermissions for deno_permissions::PermissionsContainer { } } -#[allow(clippy::disallowed_types)] -pub type NpmProcessStateProviderRc = - deno_fs::sync::MaybeArc; - -pub trait NpmProcessStateProvider: - std::fmt::Debug + MaybeSend + MaybeSync -{ - /// Gets a string containing the serialized npm state of the process. - /// - /// This will be set on the `DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE` environment - /// variable when doing a `child_process.fork`. The implementor can then check this environment - /// variable on startup to repopulate the internal npm state. - fn get_npm_process_state(&self) -> String { - // This method is only used in the CLI. - String::new() - } -} - #[allow(clippy::disallowed_types)] pub type NodeRequireResolverRc = deno_fs::sync::MaybeArc; pub trait NodeRequireResolver: std::fmt::Debug + MaybeSend + MaybeSync { - fn ensure_read_permission( + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn ensure_read_permission<'a>( &self, permissions: &mut dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError>; + path: &'a Path, + ) -> Result, AnyError>; } pub static NODE_ENV_VAR_ALLOWLIST: Lazy> = Lazy::new(|| { @@ -181,26 +152,9 @@ fn op_node_build_os() -> String { env!("TARGET").split('-').nth(2).unwrap().to_string() } -#[op2(fast)] -fn op_node_is_promise_rejected(value: v8::Local) -> bool { - let Ok(promise) = v8::Local::::try_from(value) else { - return false; - }; - - promise.state() == v8::PromiseState::Rejected -} - -#[op2] -#[string] -fn op_npm_process_state(state: &mut OpState) -> Result { - let npm_resolver = state.borrow_mut::(); - Ok(npm_resolver.get_npm_process_state()) -} - pub struct NodeExtInitServices { pub node_require_resolver: NodeRequireResolverRc, pub node_resolver: NodeResolverRc, - pub npm_process_state_provider: NpmProcessStateProviderRc, pub npm_resolver: NpmResolverRc, } @@ -219,6 +173,7 @@ deno_core::extension!(deno_node, ops::buffer::op_is_ascii, ops::buffer::op_is_utf8, + ops::buffer::op_transcode, ops::crypto::op_node_check_prime_async, ops::crypto::op_node_check_prime_bytes_async, ops::crypto::op_node_check_prime_bytes, @@ -265,6 +220,9 @@ deno_core::extension!(deno_node, ops::crypto::op_node_verify, ops::crypto::op_node_verify_ed25519, ops::crypto::keys::op_node_create_private_key, + ops::crypto::keys::op_node_create_ed_raw, + ops::crypto::keys::op_node_create_rsa_jwk, + ops::crypto::keys::op_node_create_ec_jwk, ops::crypto::keys::op_node_create_public_key, ops::crypto::keys::op_node_create_secret_key, ops::crypto::keys::op_node_derive_public_key_from_private_key, @@ -273,6 +231,7 @@ deno_core::extension!(deno_node, ops::crypto::keys::op_node_export_private_key_pem, ops::crypto::keys::op_node_export_public_key_der, ops::crypto::keys::op_node_export_public_key_pem, + ops::crypto::keys::op_node_export_public_key_jwk, ops::crypto::keys::op_node_export_secret_key_b64url, ops::crypto::keys::op_node_export_secret_key, ops::crypto::keys::op_node_generate_dh_group_key_async, @@ -324,6 +283,25 @@ deno_core::extension!(deno_node, ops::winerror::op_node_sys_to_uv_error, ops::v8::op_v8_cached_data_version_tag, ops::v8::op_v8_get_heap_statistics, + ops::v8::op_v8_get_wire_format_version, + ops::v8::op_v8_new_deserializer, + ops::v8::op_v8_new_serializer, + ops::v8::op_v8_read_double, + ops::v8::op_v8_read_header, + ops::v8::op_v8_read_raw_bytes, + ops::v8::op_v8_read_uint32, + ops::v8::op_v8_read_uint64, + ops::v8::op_v8_read_value, + ops::v8::op_v8_release_buffer, + ops::v8::op_v8_set_treat_array_buffer_views_as_host_objects, + ops::v8::op_v8_transfer_array_buffer, + ops::v8::op_v8_transfer_array_buffer_de, + ops::v8::op_v8_write_double, + ops::v8::op_v8_write_header, + ops::v8::op_v8_write_raw_bytes, + ops::v8::op_v8_write_uint32, + ops::v8::op_v8_write_uint64, + ops::v8::op_v8_write_value, ops::vm::op_vm_create_script, ops::vm::op_vm_create_context, ops::vm::op_vm_script_run_in_context, @@ -376,8 +354,7 @@ deno_core::extension!(deno_node, ops::os::op_cpus

, ops::os::op_homedir

, op_node_build_os, - op_node_is_promise_rejected, - op_npm_process_state, + ops::require::op_require_can_parse_as_esm, ops::require::op_require_init_paths, ops::require::op_require_node_module_paths

, ops::require::op_require_proxy_path, @@ -409,6 +386,7 @@ deno_core::extension!(deno_node, ops::ipc::op_node_ipc_unref, ops::process::op_node_process_kill, ops::process::op_process_abort, + ops::tls::op_get_root_certificates, ], esm_entry_point = "ext:deno_node/02_init.js", esm = [ @@ -461,17 +439,12 @@ deno_core::extension!(deno_node, "_fs/_fs_write.mjs", "_fs/_fs_writeFile.ts", "_fs/_fs_writev.mjs", - "_http_agent.mjs", - "_http_common.ts", - "_http_outgoing.ts", "_next_tick.ts", "_process/exiting.ts", "_process/process.ts", "_process/streams.mjs", "_readline.mjs", "_stream.mjs", - "_tls_common.ts", - "_tls_wrap.ts", "_util/_util_callbackify.js", "_util/asserts.ts", "_util/async.ts", @@ -496,6 +469,7 @@ deno_core::extension!(deno_node, "internal_binding/constants.ts", "internal_binding/crypto.ts", "internal_binding/handle_wrap.ts", + "internal_binding/http_parser.ts", "internal_binding/mod.ts", "internal_binding/node_file.ts", "internal_binding/node_options.ts", @@ -541,6 +515,7 @@ deno_core::extension!(deno_node, "internal/error_codes.ts", "internal/errors.ts", "internal/event_target.mjs", + "internal/events/abort_listener.mjs", "internal/fixed_queue.ts", "internal/fs/streams.mjs", "internal/fs/utils.mjs", @@ -565,15 +540,10 @@ deno_core::extension!(deno_node, "internal/streams/add-abort-signal.mjs", "internal/streams/buffer_list.mjs", "internal/streams/destroy.mjs", - "internal/streams/duplex.mjs", "internal/streams/end-of-stream.mjs", "internal/streams/lazy_transform.mjs", - "internal/streams/passthrough.mjs", - "internal/streams/readable.mjs", "internal/streams/state.mjs", - "internal/streams/transform.mjs", "internal/streams/utils.mjs", - "internal/streams/writable.mjs", "internal/test/binding.ts", "internal/timers.mjs", "internal/url.ts", @@ -594,7 +564,17 @@ deno_core::extension!(deno_node, "path/mod.ts", "path/separator.ts", "readline/promises.ts", - "wasi.ts", + "node:_http_agent" = "_http_agent.mjs", + "node:_http_common" = "_http_common.ts", + "node:_http_outgoing" = "_http_outgoing.ts", + "node:_http_server" = "_http_server.ts", + "node:_stream_duplex" = "internal/streams/duplex.mjs", + "node:_stream_passthrough" = "internal/streams/passthrough.mjs", + "node:_stream_readable" = "internal/streams/readable.mjs", + "node:_stream_transform" = "internal/streams/transform.mjs", + "node:_stream_writable" = "internal/streams/writable.mjs", + "node:_tls_common" = "_tls_common.ts", + "node:_tls_wrap" = "_tls_wrap.ts", "node:assert" = "assert.ts", "node:assert/strict" = "assert/strict.ts", "node:async_hooks" = "async_hooks.ts", @@ -616,6 +596,7 @@ deno_core::extension!(deno_node, "node:http2" = "http2.ts", "node:https" = "https.ts", "node:inspector" = "inspector.ts", + "node:inspector/promises" = "inspector.ts", "node:module" = "01_require.js", "node:net" = "net.ts", "node:os" = "os.ts", @@ -639,12 +620,14 @@ deno_core::extension!(deno_node, "node:timers" = "timers.ts", "node:timers/promises" = "timers/promises.ts", "node:tls" = "tls.ts", + "node:trace_events" = "trace_events.ts", "node:tty" = "tty.js", "node:url" = "url.ts", "node:util" = "util.ts", "node:util/types" = "util/types.ts", "node:v8" = "v8.ts", "node:vm" = "vm.js", + "node:wasi" = "wasi.ts", "node:worker_threads" = "worker_threads.ts", "node:zlib" = "zlib.ts", ], @@ -659,121 +642,121 @@ deno_core::extension!(deno_node, state.put(init.node_require_resolver.clone()); state.put(init.node_resolver.clone()); state.put(init.npm_resolver.clone()); - state.put(init.npm_process_state_provider.clone()); } }, global_template_middleware = global_template_middleware, global_object_middleware = global_object_middleware, customizer = |ext: &mut deno_core::Extension| { - let mut external_references = Vec::with_capacity(14); + let external_references = [ + vm::QUERY_MAP_FN.with(|query| { + ExternalReference { + named_query: *query, + } + }), + vm::GETTER_MAP_FN.with(|getter| { + ExternalReference { + named_getter: *getter, + } + }), + vm::SETTER_MAP_FN.with(|setter| { + ExternalReference { + named_setter: *setter, + } + }), + vm::DESCRIPTOR_MAP_FN.with(|descriptor| { + ExternalReference { + named_getter: *descriptor, + } + }), + vm::DELETER_MAP_FN.with(|deleter| { + ExternalReference { + named_deleter: *deleter, + } + }), + vm::ENUMERATOR_MAP_FN.with(|enumerator| { + ExternalReference { + enumerator: *enumerator, + } + }), + vm::DEFINER_MAP_FN.with(|definer| { + ExternalReference { + named_definer: *definer, + } + }), - vm::QUERY_MAP_FN.with(|query| { - external_references.push(ExternalReference { - named_query: *query, - }); - }); - vm::GETTER_MAP_FN.with(|getter| { - external_references.push(ExternalReference { - named_getter: *getter, - }); - }); - vm::SETTER_MAP_FN.with(|setter| { - external_references.push(ExternalReference { - named_setter: *setter, - }); - }); - vm::DESCRIPTOR_MAP_FN.with(|descriptor| { - external_references.push(ExternalReference { - named_getter: *descriptor, - }); - }); - vm::DELETER_MAP_FN.with(|deleter| { - external_references.push(ExternalReference { - named_deleter: *deleter, - }); - }); - vm::ENUMERATOR_MAP_FN.with(|enumerator| { - external_references.push(ExternalReference { - enumerator: *enumerator, - }); - }); - vm::DEFINER_MAP_FN.with(|definer| { - external_references.push(ExternalReference { - named_definer: *definer, - }); - }); + vm::INDEXED_QUERY_MAP_FN.with(|query| { + ExternalReference { + indexed_query: *query, + } + }), + vm::INDEXED_GETTER_MAP_FN.with(|getter| { + ExternalReference { + indexed_getter: *getter, + } + }), + vm::INDEXED_SETTER_MAP_FN.with(|setter| { + ExternalReference { + indexed_setter: *setter, + } + }), + vm::INDEXED_DESCRIPTOR_MAP_FN.with(|descriptor| { + ExternalReference { + indexed_getter: *descriptor, + } + }), + vm::INDEXED_DELETER_MAP_FN.with(|deleter| { + ExternalReference { + indexed_deleter: *deleter, + } + }), + vm::INDEXED_DEFINER_MAP_FN.with(|definer| { + ExternalReference { + indexed_definer: *definer, + } + }), + vm::INDEXED_ENUMERATOR_MAP_FN.with(|enumerator| { + ExternalReference { + enumerator: *enumerator, + } + }), - vm::INDEXED_QUERY_MAP_FN.with(|query| { - external_references.push(ExternalReference { - indexed_query: *query, - }); - }); - vm::INDEXED_GETTER_MAP_FN.with(|getter| { - external_references.push(ExternalReference { - indexed_getter: *getter, - }); - }); - vm::INDEXED_SETTER_MAP_FN.with(|setter| { - external_references.push(ExternalReference { - indexed_setter: *setter, - }); - }); - vm::INDEXED_DESCRIPTOR_MAP_FN.with(|descriptor| { - external_references.push(ExternalReference { - indexed_getter: *descriptor, - }); - }); - vm::INDEXED_DELETER_MAP_FN.with(|deleter| { - external_references.push(ExternalReference { - indexed_deleter: *deleter, - }); - }); - vm::INDEXED_DEFINER_MAP_FN.with(|definer| { - external_references.push(ExternalReference { - indexed_definer: *definer, - }); - }); - vm::INDEXED_ENUMERATOR_MAP_FN.with(|enumerator| { - external_references.push(ExternalReference { - enumerator: *enumerator, - }); - }); + global::GETTER_MAP_FN.with(|getter| { + ExternalReference { + named_getter: *getter, + } + }), + global::SETTER_MAP_FN.with(|setter| { + ExternalReference { + named_setter: *setter, + } + }), + global::QUERY_MAP_FN.with(|query| { + ExternalReference { + named_query: *query, + } + }), + global::DELETER_MAP_FN.with(|deleter| { + ExternalReference { + named_deleter: *deleter, + } + }), + global::ENUMERATOR_MAP_FN.with(|enumerator| { + ExternalReference { + enumerator: *enumerator, + } + }), + global::DEFINER_MAP_FN.with(|definer| { + ExternalReference { + named_definer: *definer, + } + }), + global::DESCRIPTOR_MAP_FN.with(|descriptor| { + ExternalReference { + named_getter: *descriptor, + } + }), + ]; - global::GETTER_MAP_FN.with(|getter| { - external_references.push(ExternalReference { - named_getter: *getter, - }); - }); - global::SETTER_MAP_FN.with(|setter| { - external_references.push(ExternalReference { - named_setter: *setter, - }); - }); - global::QUERY_MAP_FN.with(|query| { - external_references.push(ExternalReference { - named_query: *query, - }); - }); - global::DELETER_MAP_FN.with(|deleter| { - external_references.push(ExternalReference { - named_deleter: *deleter, - }); - }); - global::ENUMERATOR_MAP_FN.with(|enumerator| { - external_references.push(ExternalReference { - enumerator: *enumerator, - }); - }); - global::DEFINER_MAP_FN.with(|definer| { - external_references.push(ExternalReference { - named_definer: *definer, - }); - }); - global::DESCRIPTOR_MAP_FN.with(|descriptor| { - external_references.push(ExternalReference { - named_getter: *descriptor, - }); - }); ext.external_references.to_mut().extend(external_references); }, ); diff --git a/ext/node/ops/blocklist.rs b/ext/node/ops/blocklist.rs index 332cdda8f9..6c64d68eca 100644 --- a/ext/node/ops/blocklist.rs +++ b/ext/node/ops/blocklist.rs @@ -7,9 +7,6 @@ use std::net::Ipv4Addr; use std::net::Ipv6Addr; use std::net::SocketAddr; -use deno_core::anyhow::anyhow; -use deno_core::anyhow::bail; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; @@ -27,13 +24,25 @@ impl deno_core::GarbageCollected for BlockListResource {} #[derive(Serialize)] struct SocketAddressSerialization(String, String); +#[derive(Debug, thiserror::Error)] +pub enum BlocklistError { + #[error("{0}")] + AddrParse(#[from] std::net::AddrParseError), + #[error("{0}")] + IpNetwork(#[from] ipnetwork::IpNetworkError), + #[error("Invalid address")] + InvalidAddress, + #[error("IP version mismatch between start and end addresses")] + IpVersionMismatch, +} + #[op2(fast)] pub fn op_socket_address_parse( state: &mut OpState, #[string] addr: &str, #[smi] port: u16, #[string] family: &str, -) -> Result { +) -> Result { let ip = addr.parse::()?; let parsed: SocketAddr = SocketAddr::new(ip, port); let parsed_ip_str = parsed.ip().to_string(); @@ -52,7 +61,7 @@ pub fn op_socket_address_parse( Ok(false) } } else { - Err(anyhow!("Invalid address")) + Err(BlocklistError::InvalidAddress) } } @@ -60,8 +69,8 @@ pub fn op_socket_address_parse( #[serde] pub fn op_socket_address_get_serialization( state: &mut OpState, -) -> Result { - Ok(state.take::()) +) -> SocketAddressSerialization { + state.take::() } #[op2] @@ -77,7 +86,7 @@ pub fn op_blocklist_new() -> BlockListResource { pub fn op_blocklist_add_address( #[cppgc] wrap: &BlockListResource, #[string] addr: &str, -) -> Result<(), AnyError> { +) -> Result<(), BlocklistError> { wrap.blocklist.borrow_mut().add_address(addr) } @@ -86,7 +95,7 @@ pub fn op_blocklist_add_range( #[cppgc] wrap: &BlockListResource, #[string] start: &str, #[string] end: &str, -) -> Result { +) -> Result { wrap.blocklist.borrow_mut().add_range(start, end) } @@ -95,7 +104,7 @@ pub fn op_blocklist_add_subnet( #[cppgc] wrap: &BlockListResource, #[string] addr: &str, #[smi] prefix: u8, -) -> Result<(), AnyError> { +) -> Result<(), BlocklistError> { wrap.blocklist.borrow_mut().add_subnet(addr, prefix) } @@ -104,7 +113,7 @@ pub fn op_blocklist_check( #[cppgc] wrap: &BlockListResource, #[string] addr: &str, #[string] r#type: &str, -) -> Result { +) -> Result { wrap.blocklist.borrow().check(addr, r#type) } @@ -123,7 +132,7 @@ impl BlockList { &mut self, addr: IpAddr, prefix: Option, - ) -> Result<(), AnyError> { + ) -> Result<(), BlocklistError> { match addr { IpAddr::V4(addr) => { let ipv4_prefix = prefix.unwrap_or(32); @@ -154,7 +163,7 @@ impl BlockList { Ok(()) } - pub fn add_address(&mut self, address: &str) -> Result<(), AnyError> { + pub fn add_address(&mut self, address: &str) -> Result<(), BlocklistError> { let ip: IpAddr = address.parse()?; self.map_addr_add_network(ip, None)?; Ok(()) @@ -164,7 +173,7 @@ impl BlockList { &mut self, start: &str, end: &str, - ) -> Result { + ) -> Result { let start_ip: IpAddr = start.parse()?; let end_ip: IpAddr = end.parse()?; @@ -193,25 +202,33 @@ impl BlockList { self.map_addr_add_network(IpAddr::V6(addr), None)?; } } - _ => bail!("IP version mismatch between start and end addresses"), + _ => return Err(BlocklistError::IpVersionMismatch), } Ok(true) } - pub fn add_subnet(&mut self, addr: &str, prefix: u8) -> Result<(), AnyError> { + pub fn add_subnet( + &mut self, + addr: &str, + prefix: u8, + ) -> Result<(), BlocklistError> { let ip: IpAddr = addr.parse()?; self.map_addr_add_network(ip, Some(prefix))?; Ok(()) } - pub fn check(&self, addr: &str, r#type: &str) -> Result { + pub fn check( + &self, + addr: &str, + r#type: &str, + ) -> Result { let addr: IpAddr = addr.parse()?; let family = r#type.to_lowercase(); if family == "ipv4" && addr.is_ipv4() || family == "ipv6" && addr.is_ipv6() { Ok(self.rules.iter().any(|net| net.contains(addr))) } else { - Err(anyhow!("Invalid address")) + Err(BlocklistError::InvalidAddress) } } } diff --git a/ext/node/ops/buffer.rs b/ext/node/ops/buffer.rs index 74a011ab80..01f878ec15 100644 --- a/ext/node/ops/buffer.rs +++ b/ext/node/ops/buffer.rs @@ -1,5 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use deno_core::anyhow::anyhow; +use deno_core::anyhow::Result; use deno_core::op2; #[op2(fast)] @@ -11,3 +13,107 @@ pub fn op_is_ascii(#[buffer] buf: &[u8]) -> bool { pub fn op_is_utf8(#[buffer] buf: &[u8]) -> bool { std::str::from_utf8(buf).is_ok() } + +#[op2] +#[buffer] +pub fn op_transcode( + #[buffer] source: &[u8], + #[string] from_encoding: &str, + #[string] to_encoding: &str, +) -> Result> { + match (from_encoding, to_encoding) { + ("utf8", "ascii") => Ok(utf8_to_ascii(source)), + ("utf8", "latin1") => Ok(utf8_to_latin1(source)), + ("utf8", "utf16le") => utf8_to_utf16le(source), + ("utf16le", "utf8") => utf16le_to_utf8(source), + ("latin1", "utf16le") | ("ascii", "utf16le") => { + Ok(latin1_ascii_to_utf16le(source)) + } + (from, to) => Err(anyhow!("Unable to transcode Buffer {from}->{to}")), + } +} + +fn latin1_ascii_to_utf16le(source: &[u8]) -> Vec { + let mut result = Vec::with_capacity(source.len() * 2); + for &byte in source { + result.push(byte); + result.push(0); + } + result +} + +fn utf16le_to_utf8(source: &[u8]) -> Result> { + let ucs2_vec: Vec = source + .chunks(2) + .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) + .collect(); + String::from_utf16(&ucs2_vec) + .map(|utf8_string| utf8_string.into_bytes()) + .map_err(|e| anyhow!("Invalid UTF-16 sequence: {}", e)) +} + +fn utf8_to_utf16le(source: &[u8]) -> Result> { + let utf8_string = std::str::from_utf8(source)?; + let ucs2_vec: Vec = utf8_string.encode_utf16().collect(); + let bytes: Vec = ucs2_vec.iter().flat_map(|&x| x.to_le_bytes()).collect(); + Ok(bytes) +} + +fn utf8_to_latin1(source: &[u8]) -> Vec { + let mut latin1_bytes = Vec::with_capacity(source.len()); + let mut i = 0; + while i < source.len() { + match source[i] { + byte if byte <= 0x7F => { + // ASCII character + latin1_bytes.push(byte); + i += 1; + } + byte if (0xC2..=0xDF).contains(&byte) && i + 1 < source.len() => { + // 2-byte UTF-8 sequence + let codepoint = + ((byte as u16 & 0x1F) << 6) | (source[i + 1] as u16 & 0x3F); + latin1_bytes.push(if codepoint <= 0xFF { + codepoint as u8 + } else { + b'?' + }); + i += 2; + } + _ => { + // 3-byte or 4-byte UTF-8 sequence, or invalid UTF-8 + latin1_bytes.push(b'?'); + // Skip to the next valid UTF-8 start byte + i += 1; + while i < source.len() && (source[i] & 0xC0) == 0x80 { + i += 1; + } + } + } + } + latin1_bytes +} + +fn utf8_to_ascii(source: &[u8]) -> Vec { + let mut ascii_bytes = Vec::with_capacity(source.len()); + let mut i = 0; + while i < source.len() { + match source[i] { + byte if byte <= 0x7F => { + // ASCII character + ascii_bytes.push(byte); + i += 1; + } + _ => { + // Non-ASCII character + ascii_bytes.push(b'?'); + // Skip to the next valid UTF-8 start byte + i += 1; + while i < source.len() && (source[i] & 0xC0) == 0x80 { + i += 1; + } + } + } + } + ascii_bytes +} diff --git a/ext/node/ops/crypto/cipher.rs b/ext/node/ops/crypto/cipher.rs index ca13fdcd8f..b80aa33fe8 100644 --- a/ext/node/ops/crypto/cipher.rs +++ b/ext/node/ops/crypto/cipher.rs @@ -4,6 +4,7 @@ use aes::cipher::block_padding::Pkcs7; use aes::cipher::BlockDecryptMut; use aes::cipher::BlockEncryptMut; use aes::cipher::KeyIvInit; +use deno_core::error::range_error; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::Resource; @@ -137,20 +138,33 @@ impl Cipher { "aes-192-ecb" => Aes192Ecb(Box::new(ecb::Encryptor::new(key.into()))), "aes-256-ecb" => Aes256Ecb(Box::new(ecb::Encryptor::new(key.into()))), "aes-128-gcm" => { - let mut cipher = - aead_gcm_stream::AesGcm::::new(key.into()); - cipher.init(iv.try_into()?); + if iv.len() != 12 { + return Err(type_error("IV length must be 12 bytes")); + } + + let cipher = + aead_gcm_stream::AesGcm::::new(key.into(), iv); Aes128Gcm(Box::new(cipher)) } "aes-256-gcm" => { - let mut cipher = - aead_gcm_stream::AesGcm::::new(key.into()); - cipher.init(iv.try_into()?); + if iv.len() != 12 { + return Err(type_error("IV length must be 12 bytes")); + } + + let cipher = + aead_gcm_stream::AesGcm::::new(key.into(), iv); Aes256Gcm(Box::new(cipher)) } "aes256" | "aes-256-cbc" => { + if key.len() != 32 { + return Err(range_error("Invalid key length")); + } + if iv.len() != 16 { + return Err(type_error("Invalid initialization vector")); + } + Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into()))) } _ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), @@ -320,20 +334,33 @@ impl Decipher { "aes-192-ecb" => Aes192Ecb(Box::new(ecb::Decryptor::new(key.into()))), "aes-256-ecb" => Aes256Ecb(Box::new(ecb::Decryptor::new(key.into()))), "aes-128-gcm" => { - let mut decipher = - aead_gcm_stream::AesGcm::::new(key.into()); - decipher.init(iv.try_into()?); + if iv.len() != 12 { + return Err(type_error("IV length must be 12 bytes")); + } + + let decipher = + aead_gcm_stream::AesGcm::::new(key.into(), iv); Aes128Gcm(Box::new(decipher)) } "aes-256-gcm" => { - let mut decipher = - aead_gcm_stream::AesGcm::::new(key.into()); - decipher.init(iv.try_into()?); + if iv.len() != 12 { + return Err(type_error("IV length must be 12 bytes")); + } + + let decipher = + aead_gcm_stream::AesGcm::::new(key.into(), iv); Aes256Gcm(Box::new(decipher)) } "aes256" | "aes-256-cbc" => { + if key.len() != 32 { + return Err(range_error("Invalid key length")); + } + if iv.len() != 16 { + return Err(type_error("Invalid initialization vector")); + } + Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into()))) } _ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), diff --git a/ext/node/ops/crypto/digest.rs b/ext/node/ops/crypto/digest.rs index 1bb028155c..293e8e0637 100644 --- a/ext/node/ops/crypto/digest.rs +++ b/ext/node/ops/crypto/digest.rs @@ -80,6 +80,10 @@ macro_rules! match_fixed_digest_with_eager_block_buffer { type $type = ::sm3::Sm3; $body } + "rsa-md4" | "md4" | "md4withrsaencryption" => { + type $type = ::md4::Md4; + $body + } "md5-sha1" => { type $type = crate::ops::crypto::md5_sha1::Md5Sha1; $body @@ -260,6 +264,7 @@ impl Hash { pub fn get_hashes() -> Vec<&'static str> { vec![ + "RSA-MD4", "RSA-MD5", "RSA-RIPEMD160", "RSA-SHA1", @@ -281,6 +286,8 @@ impl Hash { "id-rsassa-pkcs1-v1_5-with-sha3-256", "id-rsassa-pkcs1-v1_5-with-sha3-384", "id-rsassa-pkcs1-v1_5-with-sha3-512", + "md4", + "md4WithRSAEncryption", "md5", "md5-sha1", "md5WithRSAEncryption", diff --git a/ext/node/ops/crypto/keys.rs b/ext/node/ops/crypto/keys.rs index 45849cbd93..ac62f5ccae 100644 --- a/ext/node/ops/crypto/keys.rs +++ b/ext/node/ops/crypto/keys.rs @@ -13,6 +13,7 @@ use deno_core::unsync::spawn_blocking; use deno_core::GarbageCollected; use deno_core::ToJsBuffer; use ed25519_dalek::pkcs8::BitStringRef; +use elliptic_curve::JwkEcKey; use num_bigint::BigInt; use num_traits::FromPrimitive as _; use pkcs8::DecodePrivateKey as _; @@ -234,6 +235,16 @@ impl RsaPssPrivateKey { } } +impl EcPublicKey { + pub fn to_jwk(&self) -> Result { + match self { + EcPublicKey::P224(_) => Err(type_error("Unsupported JWK EC curve: P224")), + EcPublicKey::P256(key) => Ok(key.to_jwk()), + EcPublicKey::P384(key) => Ok(key.to_jwk()), + } + } +} + impl EcPrivateKey { /// Derives the public key from the private key. pub fn to_public_key(&self) -> EcPublicKey { @@ -571,6 +582,135 @@ impl KeyObjectHandle { Ok(KeyObjectHandle::AsymmetricPublic(key)) } + pub fn new_rsa_jwk( + jwk: RsaJwkKey, + is_public: bool, + ) -> Result { + use base64::prelude::BASE64_URL_SAFE_NO_PAD; + + let n = BASE64_URL_SAFE_NO_PAD.decode(jwk.n.as_bytes())?; + let e = BASE64_URL_SAFE_NO_PAD.decode(jwk.e.as_bytes())?; + + if is_public { + let public_key = RsaPublicKey::new( + rsa::BigUint::from_bytes_be(&n), + rsa::BigUint::from_bytes_be(&e), + )?; + + Ok(KeyObjectHandle::AsymmetricPublic(AsymmetricPublicKey::Rsa( + public_key, + ))) + } else { + let d = BASE64_URL_SAFE_NO_PAD.decode( + jwk + .d + .ok_or_else(|| type_error("missing RSA private component"))? + .as_bytes(), + )?; + let p = BASE64_URL_SAFE_NO_PAD.decode( + jwk + .p + .ok_or_else(|| type_error("missing RSA private component"))? + .as_bytes(), + )?; + let q = BASE64_URL_SAFE_NO_PAD.decode( + jwk + .q + .ok_or_else(|| type_error("missing RSA private component"))? + .as_bytes(), + )?; + + let mut private_key = RsaPrivateKey::from_components( + rsa::BigUint::from_bytes_be(&n), + rsa::BigUint::from_bytes_be(&e), + rsa::BigUint::from_bytes_be(&d), + vec![ + rsa::BigUint::from_bytes_be(&p), + rsa::BigUint::from_bytes_be(&q), + ], + )?; + private_key.precompute()?; // precompute CRT params + + Ok(KeyObjectHandle::AsymmetricPrivate( + AsymmetricPrivateKey::Rsa(private_key), + )) + } + } + + pub fn new_ec_jwk( + jwk: &JwkEcKey, + is_public: bool, + ) -> Result { + // https://datatracker.ietf.org/doc/html/rfc7518#section-6.2.1.1 + let handle = match jwk.crv() { + "P-256" if is_public => { + KeyObjectHandle::AsymmetricPublic(AsymmetricPublicKey::Ec( + EcPublicKey::P256(p256::PublicKey::from_jwk(jwk)?), + )) + } + "P-256" => KeyObjectHandle::AsymmetricPrivate(AsymmetricPrivateKey::Ec( + EcPrivateKey::P256(p256::SecretKey::from_jwk(jwk)?), + )), + "P-384" if is_public => { + KeyObjectHandle::AsymmetricPublic(AsymmetricPublicKey::Ec( + EcPublicKey::P384(p384::PublicKey::from_jwk(jwk)?), + )) + } + "P-384" => KeyObjectHandle::AsymmetricPrivate(AsymmetricPrivateKey::Ec( + EcPrivateKey::P384(p384::SecretKey::from_jwk(jwk)?), + )), + _ => { + return Err(type_error(format!("unsupported curve: {}", jwk.crv()))); + } + }; + + Ok(handle) + } + + pub fn new_ed_raw( + curve: &str, + data: &[u8], + is_public: bool, + ) -> Result { + match curve { + "Ed25519" => { + let data = data + .try_into() + .map_err(|_| type_error("invalid Ed25519 key"))?; + if !is_public { + Ok(KeyObjectHandle::AsymmetricPrivate( + AsymmetricPrivateKey::Ed25519( + ed25519_dalek::SigningKey::from_bytes(data), + ), + )) + } else { + Ok(KeyObjectHandle::AsymmetricPublic( + AsymmetricPublicKey::Ed25519( + ed25519_dalek::VerifyingKey::from_bytes(data)?, + ), + )) + } + } + "X25519" => { + let data: [u8; 32] = data + .try_into() + .map_err(|_| type_error("invalid x25519 key"))?; + if !is_public { + Ok(KeyObjectHandle::AsymmetricPrivate( + AsymmetricPrivateKey::X25519(x25519_dalek::StaticSecret::from( + data, + )), + )) + } else { + Ok(KeyObjectHandle::AsymmetricPublic( + AsymmetricPublicKey::X25519(x25519_dalek::PublicKey::from(data)), + )) + } + } + _ => Err(type_error("unsupported curve")), + } + } + pub fn new_asymmetric_public_key_from_js( key: &[u8], format: &str, @@ -612,7 +752,15 @@ impl KeyObjectHandle { | KeyObjectHandle::Secret(_) => unreachable!(), } } - // TODO: handle x509 certificates as public keys + "CERTIFICATE" => { + let (_, pem) = x509_parser::pem::parse_x509_pem(pem.as_bytes()) + .map_err(|_| type_error("invalid x509 certificate"))?; + + let cert = pem.parse_x509()?; + let public_key = cert.tbs_certificate.subject_pki; + + return KeyObjectHandle::new_x509_public_key(&public_key); + } _ => { return Err(type_error(format!("unsupported PEM label: {}", label))) } @@ -773,7 +921,63 @@ fn parse_rsa_pss_params( Ok(details) } +use base64::prelude::BASE64_URL_SAFE_NO_PAD; + +fn bytes_to_b64(bytes: &[u8]) -> String { + BASE64_URL_SAFE_NO_PAD.encode(bytes) +} + impl AsymmetricPublicKey { + fn export_jwk(&self) -> Result { + match self { + AsymmetricPublicKey::Ec(key) => { + let jwk = key.to_jwk()?; + Ok(deno_core::serde_json::json!(jwk)) + } + AsymmetricPublicKey::X25519(key) => { + let bytes = key.as_bytes(); + let jwk = deno_core::serde_json::json!({ + "kty": "OKP", + "crv": "X25519", + "x": bytes_to_b64(bytes), + }); + Ok(jwk) + } + AsymmetricPublicKey::Ed25519(key) => { + let bytes = key.to_bytes(); + let jwk = deno_core::serde_json::json!({ + "kty": "OKP", + "crv": "Ed25519", + "x": bytes_to_b64(&bytes), + }); + Ok(jwk) + } + AsymmetricPublicKey::Rsa(key) => { + let n = key.n(); + let e = key.e(); + + let jwk = deno_core::serde_json::json!({ + "kty": "RSA", + "n": bytes_to_b64(&n.to_bytes_be()), + "e": bytes_to_b64(&e.to_bytes_be()), + }); + Ok(jwk) + } + AsymmetricPublicKey::RsaPss(key) => { + let n = key.key.n(); + let e = key.key.e(); + + let jwk = deno_core::serde_json::json!({ + "kty": "RSA", + "n": bytes_to_b64(&n.to_bytes_be()), + "e": bytes_to_b64(&e.to_bytes_be()), + }); + Ok(jwk) + } + _ => Err(type_error("jwk export not implemented for this key type")), + } + } + fn export_der(&self, typ: &str) -> Result, AnyError> { match typ { "pkcs1" => match self { @@ -1027,6 +1231,43 @@ pub fn op_node_create_private_key( ) } +#[op2] +#[cppgc] +pub fn op_node_create_ed_raw( + #[string] curve: &str, + #[buffer] key: &[u8], + is_public: bool, +) -> Result { + KeyObjectHandle::new_ed_raw(curve, key, is_public) +} + +#[derive(serde::Deserialize)] +pub struct RsaJwkKey { + n: String, + e: String, + d: Option, + p: Option, + q: Option, +} + +#[op2] +#[cppgc] +pub fn op_node_create_rsa_jwk( + #[serde] jwk: RsaJwkKey, + is_public: bool, +) -> Result { + KeyObjectHandle::new_rsa_jwk(jwk, is_public) +} + +#[op2] +#[cppgc] +pub fn op_node_create_ec_jwk( + #[serde] jwk: elliptic_curve::JwkEcKey, + is_public: bool, +) -> Result { + KeyObjectHandle::new_ec_jwk(&jwk, is_public) +} + #[op2] #[cppgc] pub fn op_node_create_public_key( @@ -1754,6 +1995,18 @@ pub fn op_node_export_secret_key_b64url( Ok(base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(key)) } +#[op2] +#[serde] +pub fn op_node_export_public_key_jwk( + #[cppgc] handle: &KeyObjectHandle, +) -> Result { + let public_key = handle + .as_public_key() + .ok_or_else(|| type_error("key is not an asymmetric public key"))?; + + public_key.export_jwk() +} + #[op2] #[string] pub fn op_node_export_public_key_pem( @@ -1771,7 +2024,9 @@ pub fn op_node_export_public_key_pem( _ => unreachable!("export_der would have errored"), }; - let mut out = vec![0; 2048]; + let pem_len = der::pem::encapsulated_len(label, LineEnding::LF, data.len()) + .map_err(|_| type_error("very large data"))?; + let mut out = vec![0; pem_len]; let mut writer = PemWriter::new(label, LineEnding::LF, &mut out)?; writer.write(&data)?; let len = writer.finish()?; @@ -1810,7 +2065,9 @@ pub fn op_node_export_private_key_pem( _ => unreachable!("export_der would have errored"), }; - let mut out = vec![0; 2048]; + let pem_len = der::pem::encapsulated_len(label, LineEnding::LF, data.len()) + .map_err(|_| type_error("very large data"))?; + let mut out = vec![0; pem_len]; let mut writer = PemWriter::new(label, LineEnding::LF, &mut out)?; writer.write(&data)?; let len = writer.finish()?; diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 7384375773..600d315587 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -220,13 +220,9 @@ pub fn op_node_create_cipheriv( #[string] algorithm: &str, #[buffer] key: &[u8], #[buffer] iv: &[u8], -) -> u32 { - state.resource_table.add( - match cipher::CipherContext::new(algorithm, key, iv) { - Ok(context) => context, - Err(_) => return 0, - }, - ) +) -> Result { + let context = cipher::CipherContext::new(algorithm, key, iv)?; + Ok(state.resource_table.add(context)) } #[op2(fast)] @@ -292,13 +288,9 @@ pub fn op_node_create_decipheriv( #[string] algorithm: &str, #[buffer] key: &[u8], #[buffer] iv: &[u8], -) -> u32 { - state.resource_table.add( - match cipher::DecipherContext::new(algorithm, key, iv) { - Ok(context) => context, - Err(_) => return 0, - }, - ) +) -> Result { + let context = cipher::DecipherContext::new(algorithm, key, iv)?; + Ok(state.resource_table.add(context)) } #[op2(fast)] diff --git a/ext/node/ops/fs.rs b/ext/node/ops/fs.rs index 687903325b..6645792e74 100644 --- a/ext/node/ops/fs.rs +++ b/ext/node/ops/fs.rs @@ -1,11 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::cell::RefCell; -use std::path::Path; -use std::path::PathBuf; use std::rc::Rc; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_fs::FileSystemRc; @@ -13,16 +10,31 @@ use serde::Serialize; use crate::NodePermissions; +#[derive(Debug, thiserror::Error)] +pub enum FsError { + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error("{0}")] + Io(#[from] std::io::Error), + #[cfg(windows)] + #[error("Path has no root.")] + PathHasNoRoot, + #[cfg(not(any(unix, windows)))] + #[error("Unsupported platform.")] + UnsupportedPlatform, + #[error(transparent)] + Fs(#[from] deno_io::fs::FsError), +} + #[op2(fast)] pub fn op_node_fs_exists_sync

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() .check_read_with_api_name(&path, Some("node:fs.existsSync()"))?; let fs = state.borrow::(); @@ -33,18 +45,17 @@ where pub async fn op_node_fs_exists

( state: Rc>, #[string] path: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_read_with_api_name(&path, Some("node:fs.exists()"))?; - state.borrow::().clone() + .check_read_with_api_name(&path, Some("node:fs.exists()")) + .map_err(FsError::Permission)?; + (state.borrow::().clone(), path) }; Ok(fs.exists_async(path).await?) @@ -55,22 +66,21 @@ pub fn op_node_cp_sync

( state: &mut OpState, #[string] path: &str, #[string] new_path: &str, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = Path::new(path); - let new_path = Path::new(new_path); - - state + let path = state .borrow_mut::

() - .check_read_with_api_name(path, Some("node:fs.cpSync"))?; - state + .check_read_with_api_name(path, Some("node:fs.cpSync")) + .map_err(FsError::Permission)?; + let new_path = state .borrow_mut::

() - .check_write_with_api_name(new_path, Some("node:fs.cpSync"))?; + .check_write_with_api_name(new_path, Some("node:fs.cpSync")) + .map_err(FsError::Permission)?; let fs = state.borrow::(); - fs.cp_sync(path, new_path)?; + fs.cp_sync(&path, &new_path)?; Ok(()) } @@ -79,22 +89,21 @@ pub async fn op_node_cp

( state: Rc>, #[string] path: String, #[string] new_path: String, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - let new_path = PathBuf::from(new_path); - - let fs = { + let (fs, path, new_path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_read_with_api_name(&path, Some("node:fs.cpSync"))?; - state + .check_read_with_api_name(&path, Some("node:fs.cpSync")) + .map_err(FsError::Permission)?; + let new_path = state .borrow_mut::

() - .check_write_with_api_name(&new_path, Some("node:fs.cpSync"))?; - state.borrow::().clone() + .check_write_with_api_name(&new_path, Some("node:fs.cpSync")) + .map_err(FsError::Permission)?; + (state.borrow::().clone(), path, new_path) }; fs.cp_async(path, new_path).await?; @@ -119,25 +128,27 @@ pub fn op_node_statfs

( state: Rc>, #[string] path: String, bigint: bool, -) -> Result +) -> Result where P: NodePermissions + 'static, { - { + let path = { let mut state = state.borrow_mut(); + let path = state + .borrow_mut::

() + .check_read_with_api_name(&path, Some("node:fs.statfs")) + .map_err(FsError::Permission)?; state .borrow_mut::

() - .check_read_with_api_name(Path::new(&path), Some("node:fs.statfs"))?; - state - .borrow_mut::

() - .check_sys("statfs", "node:fs.statfs")?; - } + .check_sys("statfs", "node:fs.statfs") + .map_err(FsError::Permission)?; + path + }; #[cfg(unix)] { - use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; - let path = OsStr::new(&path); + let path = path.as_os_str(); let mut cpath = path.as_bytes().to_vec(); cpath.push(0); if bigint { @@ -187,7 +198,6 @@ where } #[cfg(windows)] { - use deno_core::anyhow::anyhow; use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; use windows_sys::Win32::Storage::FileSystem::GetDiskFreeSpaceW; @@ -196,11 +206,8 @@ where // Using a vfs here doesn't make sense, it won't align with the windows API // call below. #[allow(clippy::disallowed_methods)] - let path = Path::new(&path).canonicalize()?; - let root = path - .ancestors() - .last() - .ok_or(anyhow!("Path has no root."))?; + let path = path.canonicalize()?; + let root = path.ancestors().last().ok_or(FsError::PathHasNoRoot)?; let mut root = OsStr::new(root).encode_wide().collect::>(); root.push(0); let mut sectors_per_cluster = 0; @@ -240,7 +247,7 @@ where { let _ = path; let _ = bigint; - Err(anyhow!("Unsupported platform.")) + Err(FsError::UnsupportedPlatform) } } @@ -252,18 +259,17 @@ pub fn op_node_lutimes_sync

( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = Path::new(path); - - state + let path = state .borrow_mut::

() - .check_write_with_api_name(path, Some("node:fs.lutimes"))?; + .check_write_with_api_name(path, Some("node:fs.lutimes")) + .map_err(FsError::Permission)?; let fs = state.borrow::(); - fs.lutime_sync(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?; + fs.lutime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?; Ok(()) } @@ -275,18 +281,17 @@ pub async fn op_node_lutimes

( #[smi] atime_nanos: u32, #[number] mtime_secs: i64, #[smi] mtime_nanos: u32, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_write_with_api_name(&path, Some("node:fs.lutimesSync"))?; - state.borrow::().clone() + .check_write_with_api_name(&path, Some("node:fs.lutimesSync")) + .map_err(FsError::Permission)?; + (state.borrow::().clone(), path) }; fs.lutime_async(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos) @@ -301,14 +306,14 @@ pub fn op_node_lchown_sync

( #[string] path: String, uid: Option, gid: Option, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - state + let path = state .borrow_mut::

() - .check_write_with_api_name(&path, Some("node:fs.lchownSync"))?; + .check_write_with_api_name(&path, Some("node:fs.lchownSync")) + .map_err(FsError::Permission)?; let fs = state.borrow::(); fs.lchown_sync(&path, uid, gid)?; Ok(()) @@ -320,17 +325,17 @@ pub async fn op_node_lchown

( #[string] path: String, uid: Option, gid: Option, -) -> Result<(), AnyError> +) -> Result<(), FsError> where P: NodePermissions + 'static, { - let path = PathBuf::from(path); - let fs = { + let (fs, path) = { let mut state = state.borrow_mut(); - state + let path = state .borrow_mut::

() - .check_write_with_api_name(&path, Some("node:fs.lchown"))?; - state.borrow::().clone() + .check_write_with_api_name(&path, Some("node:fs.lchown")) + .map_err(FsError::Permission)?; + (state.borrow::().clone(), path) }; fs.lchown_async(path, uid, gid).await?; Ok(()) diff --git a/ext/node/ops/http.rs b/ext/node/ops/http.rs index 4b1f99ec04..730e1e482b 100644 --- a/ext/node/ops/http.rs +++ b/ext/node/ops/http.rs @@ -8,14 +8,12 @@ use std::task::Context; use std::task::Poll; use bytes::Bytes; -use deno_core::anyhow; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures::stream::Peekable; use deno_core::futures::Future; use deno_core::futures::FutureExt; use deno_core::futures::Stream; use deno_core::futures::StreamExt; +use deno_core::futures::TryFutureExt; use deno_core::op2; use deno_core::serde::Serialize; use deno_core::unsync::spawn; @@ -33,6 +31,7 @@ use deno_core::Resource; use deno_core::ResourceId; use deno_fetch::get_or_create_client_from_state; use deno_fetch::FetchCancelHandle; +use deno_fetch::FetchError; use deno_fetch::FetchRequestResource; use deno_fetch::FetchReturn; use deno_fetch::HttpClientResource; @@ -59,12 +58,15 @@ pub fn op_node_http_request

( #[serde] headers: Vec<(ByteString, ByteString)>, #[smi] client_rid: Option, #[smi] body: Option, -) -> Result +) -> Result where P: crate::NodePermissions + 'static, { let client = if let Some(rid) = client_rid { - let r = state.resource_table.get::(rid)?; + let r = state + .resource_table + .get::(rid) + .map_err(FetchError::Resource)?; r.client.clone() } else { get_or_create_client_from_state(state)? @@ -76,15 +78,15 @@ where { let permissions = state.borrow_mut::

(); - permissions.check_net_url(&url, "ClientRequest")?; + permissions + .check_net_url(&url, "ClientRequest") + .map_err(FetchError::Permission)?; } let mut header_map = HeaderMap::new(); for (key, value) in headers { - let name = HeaderName::from_bytes(&key) - .map_err(|err| type_error(err.to_string()))?; - let v = HeaderValue::from_bytes(&value) - .map_err(|err| type_error(err.to_string()))?; + let name = HeaderName::from_bytes(&key)?; + let v = HeaderValue::from_bytes(&value)?; header_map.append(name, v); } @@ -92,7 +94,10 @@ where let (body, con_len) = if let Some(body) = body { ( BodyExt::boxed(NodeHttpResourceToBodyAdapter::new( - state.resource_table.take_any(body)?, + state + .resource_table + .take_any(body) + .map_err(FetchError::Resource)?, )), None, ) @@ -117,7 +122,7 @@ where *request.uri_mut() = url .as_str() .parse() - .map_err(|_| type_error("Invalid URL"))?; + .map_err(|_| FetchError::InvalidUrl(url.clone()))?; *request.headers_mut() = header_map; if let Some((username, password)) = maybe_authority { @@ -136,9 +141,9 @@ where let fut = async move { client .send(request) + .map_err(Into::into) .or_cancel(cancel_handle_) .await - .map(|res| res.map_err(|err| type_error(err.to_string()))) }; let request_rid = state.resource_table.add(FetchRequestResource { @@ -174,11 +179,12 @@ pub struct NodeHttpFetchResponse { pub async fn op_node_http_fetch_send( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let request = state .borrow_mut() .resource_table - .take::(rid)?; + .take::(rid) + .map_err(FetchError::Resource)?; let request = Rc::try_unwrap(request) .ok() @@ -191,22 +197,23 @@ pub async fn op_node_http_fetch_send( // If any error in the chain is a hyper body error, return that as a special result we can use to // reconstruct an error chain (eg: `new TypeError(..., { cause: new Error(...) })`). // TODO(mmastrac): it would be a lot easier if we just passed a v8::Global through here instead - let mut err_ref: &dyn std::error::Error = err.as_ref(); - while let Some(err) = std::error::Error::source(err_ref) { - if let Some(err) = err.downcast_ref::() { - if let Some(err) = std::error::Error::source(err) { - return Ok(NodeHttpFetchResponse { - error: Some(err.to_string()), - ..Default::default() - }); + + if let FetchError::ClientSend(err_src) = &err { + if let Some(client_err) = std::error::Error::source(&err_src.source) { + if let Some(err_src) = client_err.downcast_ref::() { + if let Some(err_src) = std::error::Error::source(err_src) { + return Ok(NodeHttpFetchResponse { + error: Some(err_src.to_string()), + ..Default::default() + }); + } } } - err_ref = err; } - return Err(type_error(err.to_string())); + return Err(err); } - Err(_) => return Err(type_error("request was cancelled")), + Err(_) => return Err(FetchError::RequestCanceled), }; let status = res.status(); @@ -250,11 +257,12 @@ pub async fn op_node_http_fetch_send( pub async fn op_node_http_fetch_response_upgrade( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let raw_response = state .borrow_mut() .resource_table - .take::(rid)?; + .take::(rid) + .map_err(FetchError::Resource)?; let raw_response = Rc::try_unwrap(raw_response) .expect("Someone is holding onto NodeHttpFetchResponseResource"); @@ -272,11 +280,12 @@ pub async fn op_node_http_fetch_response_upgrade( loop { let read = upgraded_rx.read(&mut buf).await?; if read == 0 { + read_tx.shutdown().await?; break; } read_tx.write_all(&buf[..read]).await?; } - Ok::<_, AnyError>(()) + Ok::<_, FetchError>(()) }); spawn(async move { let mut buf = [0; 1024]; @@ -287,7 +296,7 @@ pub async fn op_node_http_fetch_response_upgrade( } upgraded_tx.write_all(&buf[..read]).await?; } - Ok::<_, AnyError>(()) + Ok::<_, FetchError>(()) }); } @@ -317,23 +326,26 @@ impl UpgradeStream { } } - async fn read(self: Rc, buf: &mut [u8]) -> Result { + async fn read( + self: Rc, + buf: &mut [u8], + ) -> Result { let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); async { let read = RcRef::map(self, |this| &this.read); let mut read = read.borrow_mut().await; - Ok(Pin::new(&mut *read).read(buf).await?) + Pin::new(&mut *read).read(buf).await } .try_or_cancel(cancel_handle) .await } - async fn write(self: Rc, buf: &[u8]) -> Result { + async fn write(self: Rc, buf: &[u8]) -> Result { let cancel_handle = RcRef::map(self.clone(), |this| &this.cancel_handle); async { let write = RcRef::map(self, |this| &this.write); let mut write = write.borrow_mut().await; - Ok(Pin::new(&mut *write).write(buf).await?) + Pin::new(&mut *write).write(buf).await } .try_or_cancel(cancel_handle) .await @@ -386,7 +398,7 @@ impl NodeHttpFetchResponseResource { } } - pub async fn upgrade(self) -> Result { + pub async fn upgrade(self) -> Result { let reader = self.response_reader.into_inner(); match reader { NodeHttpFetchResponseReader::Start(resp) => { @@ -444,7 +456,9 @@ impl Resource for NodeHttpFetchResponseResource { // safely call `await` on it without creating a race condition. Some(_) => match reader.as_mut().next().await.unwrap() { Ok(chunk) => assert!(chunk.is_empty()), - Err(err) => break Err(type_error(err.to_string())), + Err(err) => { + break Err(deno_core::error::type_error(err.to_string())) + } }, None => break Ok(BufView::empty()), } @@ -452,7 +466,7 @@ impl Resource for NodeHttpFetchResponseResource { }; let cancel_handle = RcRef::map(self, |r| &r.cancel); - fut.try_or_cancel(cancel_handle).await + fut.try_or_cancel(cancel_handle).await.map_err(Into::into) }) } @@ -468,7 +482,9 @@ impl Resource for NodeHttpFetchResponseResource { #[allow(clippy::type_complexity)] pub struct NodeHttpResourceToBodyAdapter( Rc, - Option>>>>, + Option< + Pin>>>, + >, ); impl NodeHttpResourceToBodyAdapter { @@ -484,7 +500,7 @@ unsafe impl Send for NodeHttpResourceToBodyAdapter {} unsafe impl Sync for NodeHttpResourceToBodyAdapter {} impl Stream for NodeHttpResourceToBodyAdapter { - type Item = Result; + type Item = Result; fn poll_next( self: Pin<&mut Self>, @@ -514,7 +530,7 @@ impl Stream for NodeHttpResourceToBodyAdapter { impl hyper::body::Body for NodeHttpResourceToBodyAdapter { type Data = Bytes; - type Error = anyhow::Error; + type Error = deno_core::anyhow::Error; fn poll_frame( self: Pin<&mut Self>, diff --git a/ext/node/ops/http2.rs b/ext/node/ops/http2.rs index 9595cb33d6..53dada9f41 100644 --- a/ext/node/ops/http2.rs +++ b/ext/node/ops/http2.rs @@ -7,7 +7,6 @@ use std::rc::Rc; use std::task::Poll; use bytes::Bytes; -use deno_core::error::AnyError; use deno_core::futures::future::poll_fn; use deno_core::op2; use deno_core::serde::Serialize; @@ -110,17 +109,28 @@ impl Resource for Http2ServerSendResponse { } } +#[derive(Debug, thiserror::Error)] +pub enum Http2Error { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + UrlParse(#[from] url::ParseError), + #[error(transparent)] + H2(#[from] h2::Error), +} + #[op2(async)] #[serde] pub async fn op_http2_connect( state: Rc>, #[smi] rid: ResourceId, #[string] url: String, -) -> Result<(ResourceId, ResourceId), AnyError> { +) -> Result<(ResourceId, ResourceId), Http2Error> { // No permission check necessary because we're using an existing connection let network_stream = { let mut state = state.borrow_mut(); - take_network_stream_resource(&mut state.resource_table, rid)? + take_network_stream_resource(&mut state.resource_table, rid) + .map_err(Http2Error::Resource)? }; let url = Url::parse(&url)?; @@ -144,9 +154,10 @@ pub async fn op_http2_connect( pub async fn op_http2_listen( state: Rc>, #[smi] rid: ResourceId, -) -> Result { +) -> Result { let stream = - take_network_stream_resource(&mut state.borrow_mut().resource_table, rid)?; + take_network_stream_resource(&mut state.borrow_mut().resource_table, rid) + .map_err(Http2Error::Resource)?; let conn = h2::server::Builder::new().handshake(stream).await?; Ok( @@ -166,12 +177,13 @@ pub async fn op_http2_accept( #[smi] rid: ResourceId, ) -> Result< Option<(Vec<(ByteString, ByteString)>, ResourceId, ResourceId)>, - AnyError, + Http2Error, > { let resource = state .borrow() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(Http2Error::Resource)?; let mut conn = RcRef::map(&resource, |r| &r.conn).borrow_mut().await; if let Some(res) = conn.accept().await { let (req, resp) = res?; @@ -233,11 +245,12 @@ pub async fn op_http2_send_response( #[smi] rid: ResourceId, #[smi] status: u16, #[serde] headers: Vec<(ByteString, ByteString)>, -) -> Result<(ResourceId, u32), AnyError> { +) -> Result<(ResourceId, u32), Http2Error> { let resource = state .borrow() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(Http2Error::Resource)?; let mut send_response = RcRef::map(resource, |r| &r.send_response) .borrow_mut() .await; @@ -262,8 +275,12 @@ pub async fn op_http2_send_response( pub async fn op_http2_poll_client_connection( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { - let resource = state.borrow().resource_table.get::(rid)?; +) -> Result<(), Http2Error> { + let resource = state + .borrow() + .resource_table + .get::(rid) + .map_err(Http2Error::Resource)?; let cancel_handle = RcRef::map(resource.clone(), |this| &this.cancel_handle); let mut conn = RcRef::map(resource, |this| &this.conn).borrow_mut().await; @@ -289,11 +306,12 @@ pub async fn op_http2_client_request( // 4 strings of keys? #[serde] mut pseudo_headers: HashMap, #[serde] headers: Vec<(ByteString, ByteString)>, -) -> Result<(ResourceId, u32), AnyError> { +) -> Result<(ResourceId, u32), Http2Error> { let resource = state .borrow() .resource_table - .get::(client_rid)?; + .get::(client_rid) + .map_err(Http2Error::Resource)?; let url = resource.url.clone(); @@ -326,7 +344,10 @@ pub async fn op_http2_client_request( let resource = { let state = state.borrow(); - state.resource_table.get::(client_rid)? + state + .resource_table + .get::(client_rid) + .map_err(Http2Error::Resource)? }; let mut client = RcRef::map(&resource, |r| &r.client).borrow_mut().await; poll_fn(|cx| client.poll_ready(cx)).await?; @@ -345,11 +366,12 @@ pub async fn op_http2_client_send_data( #[smi] stream_rid: ResourceId, #[buffer] data: JsBuffer, end_of_stream: bool, -) -> Result<(), AnyError> { +) -> Result<(), Http2Error> { let resource = state .borrow() .resource_table - .get::(stream_rid)?; + .get::(stream_rid) + .map_err(Http2Error::Resource)?; let mut stream = RcRef::map(&resource, |r| &r.stream).borrow_mut().await; stream.send_data(data.to_vec().into(), end_of_stream)?; @@ -361,7 +383,7 @@ pub async fn op_http2_client_reset_stream( state: Rc>, #[smi] stream_rid: ResourceId, #[smi] code: u32, -) -> Result<(), AnyError> { +) -> Result<(), deno_core::error::AnyError> { let resource = state .borrow() .resource_table @@ -376,11 +398,12 @@ pub async fn op_http2_client_send_trailers( state: Rc>, #[smi] stream_rid: ResourceId, #[serde] trailers: Vec<(ByteString, ByteString)>, -) -> Result<(), AnyError> { +) -> Result<(), Http2Error> { let resource = state .borrow() .resource_table - .get::(stream_rid)?; + .get::(stream_rid) + .map_err(Http2Error::Resource)?; let mut stream = RcRef::map(&resource, |r| &r.stream).borrow_mut().await; let mut trailers_map = http::HeaderMap::new(); @@ -408,11 +431,12 @@ pub struct Http2ClientResponse { pub async fn op_http2_client_get_response( state: Rc>, #[smi] stream_rid: ResourceId, -) -> Result<(Http2ClientResponse, bool), AnyError> { +) -> Result<(Http2ClientResponse, bool), Http2Error> { let resource = state .borrow() .resource_table - .get::(stream_rid)?; + .get::(stream_rid) + .map_err(Http2Error::Resource)?; let mut response_future = RcRef::map(&resource, |r| &r.response).borrow_mut().await; @@ -478,23 +502,22 @@ fn poll_data_or_trailers( pub async fn op_http2_client_get_response_body_chunk( state: Rc>, #[smi] body_rid: ResourceId, -) -> Result<(Option>, bool, bool), AnyError> { +) -> Result<(Option>, bool, bool), Http2Error> { let resource = state .borrow() .resource_table - .get::(body_rid)?; + .get::(body_rid) + .map_err(Http2Error::Resource)?; let mut body = RcRef::map(&resource, |r| &r.body).borrow_mut().await; loop { let result = poll_fn(|cx| poll_data_or_trailers(cx, &mut body)).await; if let Err(err) = result { - let reason = err.reason(); - if let Some(reason) = reason { - if reason == Reason::CANCEL { - return Ok((None, false, true)); - } + match err.reason() { + Some(Reason::NO_ERROR) => return Ok((None, true, false)), + Some(Reason::CANCEL) => return Ok((None, false, true)), + _ => return Err(err.into()), } - return Err(err.into()); } match result.unwrap() { DataOrTrailers::Data(data) => { @@ -527,7 +550,7 @@ pub async fn op_http2_client_get_response_body_chunk( pub async fn op_http2_client_get_response_trailers( state: Rc>, #[smi] body_rid: ResourceId, -) -> Result>, AnyError> { +) -> Result>, deno_core::error::AnyError> { let resource = state .borrow() .resource_table diff --git a/ext/node/ops/idna.rs b/ext/node/ops/idna.rs index 9c9450c70f..a3d85e77c2 100644 --- a/ext/node/ops/idna.rs +++ b/ext/node/ops/idna.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::anyhow::Error; -use deno_core::error::range_error; use deno_core::op2; use std::borrow::Cow; @@ -11,19 +9,21 @@ use std::borrow::Cow; const PUNY_PREFIX: &str = "xn--"; -fn invalid_input_err() -> Error { - range_error("Invalid input") -} - -fn not_basic_err() -> Error { - range_error("Illegal input >= 0x80 (not a basic code point)") +#[derive(Debug, thiserror::Error)] +pub enum IdnaError { + #[error("Invalid input")] + InvalidInput, + #[error("Input would take more than 63 characters to encode")] + InputTooLong, + #[error("Illegal input >= 0x80 (not a basic code point)")] + IllegalInput, } /// map a domain by mapping each label with the given function -fn map_domain( +fn map_domain( domain: &str, - f: impl Fn(&str) -> Result, E>, -) -> Result { + f: impl Fn(&str) -> Result, IdnaError>, +) -> Result { let mut result = String::with_capacity(domain.len()); let mut domain = domain; @@ -48,7 +48,7 @@ fn map_domain( /// Maps a unicode domain to ascii by punycode encoding each label /// /// Note this is not IDNA2003 or IDNA2008 compliant, rather it matches node.js's punycode implementation -fn to_ascii(input: &str) -> Result { +fn to_ascii(input: &str) -> Result { if input.is_ascii() { return Ok(input.into()); } @@ -61,9 +61,7 @@ fn to_ascii(input: &str) -> Result { } else { idna::punycode::encode_str(label) .map(|encoded| [PUNY_PREFIX, &encoded].join("").into()) // add the prefix - .ok_or_else(|| { - Error::msg("Input would take more than 63 characters to encode") // only error possible per the docs - }) + .ok_or(IdnaError::InputTooLong) // only error possible per the docs } })?; @@ -74,13 +72,13 @@ fn to_ascii(input: &str) -> Result { /// Maps an ascii domain to unicode by punycode decoding each label /// /// Note this is not IDNA2003 or IDNA2008 compliant, rather it matches node.js's punycode implementation -fn to_unicode(input: &str) -> Result { +fn to_unicode(input: &str) -> Result { map_domain(input, |s| { if let Some(puny) = s.strip_prefix(PUNY_PREFIX) { // it's a punycode encoded label Ok( idna::punycode::decode_to_string(&puny.to_lowercase()) - .ok_or_else(invalid_input_err)? + .ok_or(IdnaError::InvalidInput)? .into(), ) } else { @@ -95,7 +93,7 @@ fn to_unicode(input: &str) -> Result { #[string] pub fn op_node_idna_punycode_to_ascii( #[string] domain: String, -) -> Result { +) -> Result { to_ascii(&domain) } @@ -105,7 +103,7 @@ pub fn op_node_idna_punycode_to_ascii( #[string] pub fn op_node_idna_punycode_to_unicode( #[string] domain: String, -) -> Result { +) -> Result { to_unicode(&domain) } @@ -115,8 +113,8 @@ pub fn op_node_idna_punycode_to_unicode( #[string] pub fn op_node_idna_domain_to_ascii( #[string] domain: String, -) -> Result { - idna::domain_to_ascii(&domain).map_err(|e| e.into()) +) -> Result { + idna::domain_to_ascii(&domain) } /// Converts a domain to Unicode as per the IDNA spec @@ -131,7 +129,7 @@ pub fn op_node_idna_domain_to_unicode(#[string] domain: String) -> String { #[string] pub fn op_node_idna_punycode_decode( #[string] domain: String, -) -> Result { +) -> Result { if domain.is_empty() { return Ok(domain); } @@ -147,11 +145,10 @@ pub fn op_node_idna_punycode_decode( .unwrap_or(domain.len() - 1); if !domain[..last_dash].is_ascii() { - return Err(not_basic_err()); + return Err(IdnaError::IllegalInput); } - idna::punycode::decode_to_string(&domain) - .ok_or_else(|| deno_core::error::range_error("Invalid input")) + idna::punycode::decode_to_string(&domain).ok_or(IdnaError::InvalidInput) } #[op2] diff --git a/ext/node/ops/ipc.rs b/ext/node/ops/ipc.rs index 59b6fece14..672cf0d707 100644 --- a/ext/node/ops/ipc.rs +++ b/ext/node/ops/ipc.rs @@ -17,8 +17,6 @@ mod impl_ { use std::task::Context; use std::task::Poll; - use deno_core::error::bad_resource_id; - use deno_core::error::AnyError; use deno_core::op2; use deno_core::serde; use deno_core::serde::Serializer; @@ -167,7 +165,7 @@ mod impl_ { #[smi] pub fn op_node_child_ipc_pipe( state: &mut OpState, - ) -> Result, AnyError> { + ) -> Result, io::Error> { let fd = match state.try_borrow_mut::() { Some(child_pipe_fd) => child_pipe_fd.0, None => return Ok(None), @@ -180,6 +178,18 @@ mod impl_ { )) } + #[derive(Debug, thiserror::Error)] + pub enum IpcError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + IpcJsonStream(#[from] IpcJsonStreamError), + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), + #[error("failed to serialize json value: {0}")] + SerdeJson(serde_json::Error), + } + #[op2(async)] pub fn op_node_ipc_write<'a>( scope: &mut v8::HandleScope<'a>, @@ -192,34 +202,37 @@ mod impl_ { // ideally we would just return `Result<(impl Future, bool), ..>`, but that's not // supported by `op2` currently. queue_ok: v8::Local<'a, v8::Array>, - ) -> Result>, AnyError> { + ) -> Result>, IpcError> { let mut serialized = Vec::with_capacity(64); let mut ser = serde_json::Serializer::new(&mut serialized); - serialize_v8_value(scope, value, &mut ser).map_err(|e| { - deno_core::error::type_error(format!( - "failed to serialize json value: {e}" - )) - })?; + serialize_v8_value(scope, value, &mut ser).map_err(IpcError::SerdeJson)?; serialized.push(b'\n'); let stream = state .borrow() .resource_table .get::(rid) - .map_err(|_| bad_resource_id())?; + .map_err(IpcError::Resource)?; let old = stream .queued_bytes .fetch_add(serialized.len(), std::sync::atomic::Ordering::Relaxed); if old + serialized.len() > 2 * INITIAL_CAPACITY { // sending messages too fast - let v = false.to_v8(scope)?; + let v = false.to_v8(scope).unwrap(); // Infallible queue_ok.set_index(scope, 0, v); } Ok(async move { - stream.clone().write_msg_bytes(&serialized).await?; + let cancel = stream.cancel.clone(); + let result = stream + .clone() + .write_msg_bytes(&serialized) + .or_cancel(cancel) + .await; + // adjust count even on error stream .queued_bytes .fetch_sub(serialized.len(), std::sync::atomic::Ordering::Relaxed); + result??; Ok(()) }) } @@ -239,12 +252,12 @@ mod impl_ { pub async fn op_node_ipc_read( state: Rc>, #[smi] rid: ResourceId, - ) -> Result { + ) -> Result { let stream = state .borrow() .resource_table .get::(rid) - .map_err(|_| bad_resource_id())?; + .map_err(IpcError::Resource)?; let cancel = stream.cancel.clone(); let mut stream = RcRef::map(stream, |r| &r.read_half).borrow_mut().await; @@ -400,7 +413,7 @@ mod impl_ { async fn write_msg_bytes( self: Rc, msg: &[u8], - ) -> Result<(), AnyError> { + ) -> Result<(), io::Error> { let mut write_half = RcRef::map(self, |r| &r.write_half).borrow_mut().await; write_half.write_all(msg).await?; @@ -455,6 +468,14 @@ mod impl_ { } } + #[derive(Debug, thiserror::Error)] + pub enum IpcJsonStreamError { + #[error("{0}")] + Io(#[source] std::io::Error), + #[error("{0}")] + SimdJson(#[source] simd_json::Error), + } + // JSON serialization stream over IPC pipe. // // `\n` is used as a delimiter between messages. @@ -475,7 +496,7 @@ mod impl_ { async fn read_msg( &mut self, - ) -> Result, AnyError> { + ) -> Result, IpcJsonStreamError> { let mut json = None; let nread = read_msg_inner( &mut self.pipe, @@ -483,7 +504,8 @@ mod impl_ { &mut json, &mut self.read_buffer, ) - .await?; + .await + .map_err(IpcJsonStreamError::Io)?; if nread == 0 { // EOF. return Ok(None); @@ -493,7 +515,8 @@ mod impl_ { Some(v) => v, None => { // Took more than a single read and some buffering. - simd_json::from_slice(&mut self.buffer[..nread])? + simd_json::from_slice(&mut self.buffer[..nread]) + .map_err(IpcJsonStreamError::SimdJson)? } }; diff --git a/ext/node/ops/mod.rs b/ext/node/ops/mod.rs index d11cc7461b..b562261f39 100644 --- a/ext/node/ops/mod.rs +++ b/ext/node/ops/mod.rs @@ -11,6 +11,7 @@ pub mod ipc; pub mod os; pub mod process; pub mod require; +pub mod tls; pub mod util; pub mod v8; pub mod vm; diff --git a/ext/node/ops/os/cpus.rs b/ext/node/ops/os/cpus.rs index f57e84a1c7..3f5f430f65 100644 --- a/ext/node/ops/os/cpus.rs +++ b/ext/node/ops/os/cpus.rs @@ -294,6 +294,54 @@ pub fn cpu_info() -> Option> { Some(cpus) } +#[cfg(target_os = "openbsd")] +pub fn cpu_info() -> Option> { + // Stub implementation for OpenBSD that returns an array of the correct size + // but with dummy values. + // Rust's OpenBSD libc bindings don't contain all the symbols needed for a + // full implementation, and including them is not planned. + let mut mib = [libc::CTL_HW, libc::HW_NCPUONLINE]; + + // SAFETY: Assumes correct behavior of platform-specific + // sysctls and data structures. Relies on specific sysctl + // names and parameter existence. + unsafe { + let mut ncpu: libc::c_uint = 0; + let mut size = std::mem::size_of_val(&ncpu) as libc::size_t; + + // Get number of CPUs online + let res = libc::sysctl( + mib.as_mut_ptr(), + mib.len() as _, + &mut ncpu as *mut _ as *mut _, + &mut size, + std::ptr::null_mut(), + 0, + ); + // If res == 0, the sysctl call was succesful and + // ncpuonline contains the number of online CPUs. + if res != 0 { + return None; + } else { + let mut cpus = vec![CpuInfo::new(); ncpu as usize]; + + for (_, cpu) in cpus.iter_mut().enumerate() { + cpu.model = "Undisclosed CPU".to_string(); + // Return 1 as a dummy value so the tests won't + // fail. + cpu.speed = 1; + cpu.times.user = 1; + cpu.times.nice = 1; + cpu.times.sys = 1; + cpu.times.idle = 1; + cpu.times.irq = 1; + } + + return Some(cpus); + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/ext/node/ops/os/mod.rs b/ext/node/ops/os/mod.rs index ca91895f22..b4c9eaa8ca 100644 --- a/ext/node/ops/os/mod.rs +++ b/ext/node/ops/os/mod.rs @@ -1,28 +1,38 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::NodePermissions; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; mod cpus; -mod priority; +pub mod priority; + +#[derive(Debug, thiserror::Error)] +pub enum OsError { + #[error(transparent)] + Priority(priority::PriorityError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error("Failed to get cpu info")] + FailedToGetCpuInfo, +} #[op2(fast)] pub fn op_node_os_get_priority

( state: &mut OpState, pid: u32, -) -> Result +) -> Result where P: NodePermissions + 'static, { { let permissions = state.borrow_mut::

(); - permissions.check_sys("getPriority", "node:os.getPriority()")?; + permissions + .check_sys("getPriority", "node:os.getPriority()") + .map_err(OsError::Permission)?; } - priority::get_priority(pid) + priority::get_priority(pid).map_err(OsError::Priority) } #[op2(fast)] @@ -30,21 +40,25 @@ pub fn op_node_os_set_priority

( state: &mut OpState, pid: u32, priority: i32, -) -> Result<(), AnyError> +) -> Result<(), OsError> where P: NodePermissions + 'static, { { let permissions = state.borrow_mut::

(); - permissions.check_sys("setPriority", "node:os.setPriority()")?; + permissions + .check_sys("setPriority", "node:os.setPriority()") + .map_err(OsError::Permission)?; } - priority::set_priority(pid, priority) + priority::set_priority(pid, priority).map_err(OsError::Priority) } #[op2] #[string] -pub fn op_node_os_username

(state: &mut OpState) -> Result +pub fn op_node_os_username

( + state: &mut OpState, +) -> Result where P: NodePermissions + 'static, { @@ -57,7 +71,9 @@ where } #[op2(fast)] -pub fn op_geteuid

(state: &mut OpState) -> Result +pub fn op_geteuid

( + state: &mut OpState, +) -> Result where P: NodePermissions + 'static, { @@ -76,7 +92,9 @@ where } #[op2(fast)] -pub fn op_getegid

(state: &mut OpState) -> Result +pub fn op_getegid

( + state: &mut OpState, +) -> Result where P: NodePermissions + 'static, { @@ -96,21 +114,25 @@ where #[op2] #[serde] -pub fn op_cpus

(state: &mut OpState) -> Result, AnyError> +pub fn op_cpus

(state: &mut OpState) -> Result, OsError> where P: NodePermissions + 'static, { { let permissions = state.borrow_mut::

(); - permissions.check_sys("cpus", "node:os.cpus()")?; + permissions + .check_sys("cpus", "node:os.cpus()") + .map_err(OsError::Permission)?; } - cpus::cpu_info().ok_or_else(|| type_error("Failed to get cpu info")) + cpus::cpu_info().ok_or(OsError::FailedToGetCpuInfo) } #[op2] #[string] -pub fn op_homedir

(state: &mut OpState) -> Result, AnyError> +pub fn op_homedir

( + state: &mut OpState, +) -> Result, deno_core::error::AnyError> where P: NodePermissions + 'static, { diff --git a/ext/node/ops/os/priority.rs b/ext/node/ops/os/priority.rs index 043928e2a6..9a1ebcca70 100644 --- a/ext/node/ops/os/priority.rs +++ b/ext/node/ops/os/priority.rs @@ -1,12 +1,18 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; - pub use impl_::*; +#[derive(Debug, thiserror::Error)] +pub enum PriorityError { + #[error("{0}")] + Io(#[from] std::io::Error), + #[cfg(windows)] + #[error("Invalid priority")] + InvalidPriority, +} + #[cfg(unix)] mod impl_ { - use super::*; use errno::errno; use errno::set_errno; use errno::Errno; @@ -16,7 +22,7 @@ mod impl_ { const PRIORITY_HIGH: i32 = -14; // Ref: https://github.com/libuv/libuv/blob/55376b044b74db40772e8a6e24d67a8673998e02/src/unix/core.c#L1533-L1547 - pub fn get_priority(pid: u32) -> Result { + pub fn get_priority(pid: u32) -> Result { set_errno(Errno(0)); match ( // SAFETY: libc::getpriority is unsafe @@ -29,7 +35,10 @@ mod impl_ { } } - pub fn set_priority(pid: u32, priority: i32) -> Result<(), AnyError> { + pub fn set_priority( + pid: u32, + priority: i32, + ) -> Result<(), super::PriorityError> { // SAFETY: libc::setpriority is unsafe match unsafe { libc::setpriority(PRIO_PROCESS, pid as id_t, priority) } { -1 => Err(std::io::Error::last_os_error().into()), @@ -40,8 +49,6 @@ mod impl_ { #[cfg(windows)] mod impl_ { - use super::*; - use deno_core::error::type_error; use winapi::shared::minwindef::DWORD; use winapi::shared::minwindef::FALSE; use winapi::shared::ntdef::NULL; @@ -67,7 +74,7 @@ mod impl_ { const PRIORITY_HIGHEST: i32 = -20; // Ported from: https://github.com/libuv/libuv/blob/a877ca2435134ef86315326ef4ef0c16bdbabf17/src/win/util.c#L1649-L1685 - pub fn get_priority(pid: u32) -> Result { + pub fn get_priority(pid: u32) -> Result { // SAFETY: Windows API calls unsafe { let handle = if pid == 0 { @@ -95,7 +102,10 @@ mod impl_ { } // Ported from: https://github.com/libuv/libuv/blob/a877ca2435134ef86315326ef4ef0c16bdbabf17/src/win/util.c#L1688-L1719 - pub fn set_priority(pid: u32, priority: i32) -> Result<(), AnyError> { + pub fn set_priority( + pid: u32, + priority: i32, + ) -> Result<(), super::PriorityError> { // SAFETY: Windows API calls unsafe { let handle = if pid == 0 { @@ -109,7 +119,7 @@ mod impl_ { #[allow(clippy::manual_range_contains)] let priority_class = if priority < PRIORITY_HIGHEST || priority > PRIORITY_LOW { - return Err(type_error("Invalid priority")); + return Err(super::PriorityError::InvalidPriority); } else if priority < PRIORITY_HIGH { REALTIME_PRIORITY_CLASS } else if priority < PRIORITY_ABOVE_NORMAL { diff --git a/ext/node/ops/process.rs b/ext/node/ops/process.rs index 0992c46c62..282567226e 100644 --- a/ext/node/ops/process.rs +++ b/ext/node/ops/process.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_permissions::PermissionsContainer; @@ -51,7 +50,7 @@ pub fn op_node_process_kill( state: &mut OpState, #[smi] pid: i32, #[smi] sig: i32, -) -> Result { +) -> Result { state .borrow_mut::() .check_run_all("process.kill")?; diff --git a/ext/node/ops/require.rs b/ext/node/ops/require.rs index d074234c39..f4607f4e8a 100644 --- a/ext/node/ops/require.rs +++ b/ext/node/ops/require.rs @@ -1,18 +1,18 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::anyhow::Context; -use deno_core::error::generic_error; -use deno_core::error::AnyError; -use deno_core::normalize_path; use deno_core::op2; use deno_core::url::Url; +use deno_core::v8; use deno_core::JsRuntimeInspector; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_fs::FileSystemRc; +use deno_package_json::PackageJsonRc; +use deno_path_util::normalize_path; use node_resolver::NodeModuleKind; use node_resolver::NodeResolutionMode; use node_resolver::REQUIRE_CONDITIONS; +use std::borrow::Cow; use std::cell::RefCell; use std::path::Path; use std::path::PathBuf; @@ -22,12 +22,12 @@ use crate::NodePermissions; use crate::NodeRequireResolverRc; use crate::NodeResolverRc; use crate::NpmResolverRc; -use crate::PackageJson; -fn ensure_read_permission

( +#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] +fn ensure_read_permission<'a, P>( state: &mut OpState, - file_path: &Path, -) -> Result<(), AnyError> + file_path: &'a Path, +) -> Result, deno_core::error::AnyError> where P: NodePermissions + 'static, { @@ -36,6 +36,32 @@ where resolver.ensure_read_permission(permissions, file_path) } +#[derive(Debug, thiserror::Error)] +pub enum RequireError { + #[error(transparent)] + UrlParse(#[from] url::ParseError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + PackageExportsResolve( + #[from] node_resolver::errors::PackageExportsResolveError, + ), + #[error(transparent)] + PackageJsonLoad(#[from] node_resolver::errors::PackageJsonLoadError), + #[error(transparent)] + ClosestPkgJson(#[from] node_resolver::errors::ClosestPkgJsonError), + #[error(transparent)] + PackageImportsResolve( + #[from] node_resolver::errors::PackageImportsResolveError, + ), + #[error("failed to convert '{0}' to file path")] + FilePathConversion(Url), + #[error(transparent)] + Fs(#[from] deno_io::fs::FsError), + #[error("Unable to get CWD: {0}")] + UnableToGetCwd(deno_io::fs::FsError), +} + #[op2] #[serde] pub fn op_require_init_paths() -> Vec { @@ -70,7 +96,7 @@ pub fn op_require_init_paths() -> Vec { // let mut paths = paths // .into_iter() - // .map(|p| p.to_string_lossy().to_string()) + // .map(|p| p.to_string_lossy().into_owned()) // .collect(); // if !node_path.is_empty() { @@ -92,23 +118,21 @@ pub fn op_require_init_paths() -> Vec { pub fn op_require_node_module_paths

( state: &mut OpState, #[string] from: String, -) -> Result, AnyError> +) -> Result, RequireError> where P: NodePermissions + 'static, { let fs = state.borrow::(); // Guarantee that "from" is absolute. - let from_url = if from.starts_with("file:///") { - Url::parse(&from)? + let from = if from.starts_with("file:///") { + url_to_file_path(&Url::parse(&from)?)? } else { - deno_core::resolve_path( - &from, - &(fs.cwd().map_err(AnyError::from)).context("Unable to get CWD")?, - )? + let current_dir = &fs.cwd().map_err(RequireError::UnableToGetCwd)?; + normalize_path(current_dir.join(from)) }; - let from = url_to_file_path(&from_url)?; - ensure_read_permission::

(state, &from)?; + let from = ensure_read_permission::

(state, &from) + .map_err(RequireError::Permission)?; if cfg!(windows) { // return root node_modules when path is 'D:\\'. @@ -117,7 +141,7 @@ where let bytes = from_str.as_bytes(); if bytes[from_str.len() - 1] == b'\\' && bytes[from_str.len() - 2] == b':' { - let p = from_str.to_owned() + "node_modules"; + let p = format!("{}node_modules", from_str); return Ok(vec![p]); } } @@ -129,12 +153,12 @@ where } } - let mut paths = vec![]; - let mut current_path = from.as_path(); + let mut paths = Vec::with_capacity(from.components().count()); + let mut current_path = from.as_ref(); let mut maybe_parent = Some(current_path); while let Some(parent) = maybe_parent { if !parent.ends_with("node_modules") { - paths.push(parent.join("node_modules").to_string_lossy().to_string()); + paths.push(parent.join("node_modules").to_string_lossy().into_owned()); } current_path = parent; maybe_parent = current_path.parent(); @@ -158,7 +182,7 @@ pub fn op_require_proxy_path(#[string] filename: String) -> String { if trailing_slash { let p = PathBuf::from(filename); - p.join("noop.js").to_string_lossy().to_string() + p.join("noop.js").to_string_lossy().into_owned() } else { filename } @@ -200,7 +224,7 @@ pub fn op_require_resolve_deno_dir( }), ) .ok() - .map(|p| p.to_string_lossy().to_string()) + .map(|p| p.to_string_lossy().into_owned()) } #[op2(fast)] @@ -251,7 +275,7 @@ pub fn op_require_resolve_lookup_paths( // } let p = PathBuf::from(parent_filename); - Some(vec![p.parent().unwrap().to_string_lossy().to_string()]) + Some(vec![p.parent().unwrap().to_string_lossy().into_owned()]) } #[op2(fast)] @@ -263,12 +287,12 @@ pub fn op_require_path_is_absolute(#[string] p: String) -> bool { pub fn op_require_stat

( state: &mut OpState, #[string] path: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { let path = PathBuf::from(path); - ensure_read_permission::

(state, &path)?; + let path = ensure_read_permission::

(state, &path)?; let fs = state.borrow::(); if let Ok(metadata) = fs.stat_sync(&path) { if metadata.is_file { @@ -286,45 +310,47 @@ where pub fn op_require_real_path

( state: &mut OpState, #[string] request: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { let path = PathBuf::from(request); - ensure_read_permission::

(state, &path)?; + let path = ensure_read_permission::

(state, &path) + .map_err(RequireError::Permission)?; let fs = state.borrow::(); let canonicalized_path = - deno_core::strip_unc_prefix(fs.realpath_sync(&path)?); - Ok(canonicalized_path.to_string_lossy().to_string()) + deno_path_util::strip_unc_prefix(fs.realpath_sync(&path)?); + Ok(canonicalized_path.to_string_lossy().into_owned()) } -fn path_resolve(parts: Vec) -> String { - assert!(!parts.is_empty()); - let mut p = PathBuf::from(&parts[0]); - if parts.len() > 1 { - for part in &parts[1..] { - p = p.join(part); - } +fn path_resolve<'a>(mut parts: impl Iterator) -> PathBuf { + let mut p = PathBuf::from(parts.next().unwrap()); + for part in parts { + p = p.join(part); } - normalize_path(p).to_string_lossy().to_string() + normalize_path(p) } #[op2] #[string] pub fn op_require_path_resolve(#[serde] parts: Vec) -> String { - path_resolve(parts) + path_resolve(parts.iter().map(|s| s.as_str())) + .to_string_lossy() + .into_owned() } #[op2] #[string] pub fn op_require_path_dirname( #[string] request: String, -) -> Result { +) -> Result { let p = PathBuf::from(request); if let Some(parent) = p.parent() { - Ok(parent.to_string_lossy().to_string()) + Ok(parent.to_string_lossy().into_owned()) } else { - Err(generic_error("Path doesn't have a parent")) + Err(deno_core::error::generic_error( + "Path doesn't have a parent", + )) } } @@ -332,12 +358,14 @@ pub fn op_require_path_dirname( #[string] pub fn op_require_path_basename( #[string] request: String, -) -> Result { +) -> Result { let p = PathBuf::from(request); if let Some(path) = p.file_name() { - Ok(path.to_string_lossy().to_string()) + Ok(path.to_string_lossy().into_owned()) } else { - Err(generic_error("Path doesn't have a file name")) + Err(deno_core::error::generic_error( + "Path doesn't have a file name", + )) } } @@ -348,7 +376,7 @@ pub fn op_require_try_self_parent_path

( has_parent: bool, #[string] maybe_parent_filename: Option, #[string] maybe_parent_id: Option, -) -> Result, AnyError> +) -> Result, deno_core::error::AnyError> where P: NodePermissions + 'static, { @@ -364,8 +392,8 @@ where if parent_id == "" || parent_id == "internal/preload" { let fs = state.borrow::(); if let Ok(cwd) = fs.cwd() { - ensure_read_permission::

(state, &cwd)?; - return Ok(Some(cwd.to_string_lossy().to_string())); + let cwd = ensure_read_permission::

(state, &cwd)?; + return Ok(Some(cwd.to_string_lossy().into_owned())); } } } @@ -378,7 +406,7 @@ pub fn op_require_try_self

( state: &mut OpState, #[string] parent_path: Option, #[string] request: String, -) -> Result, AnyError> +) -> Result, RequireError> where P: NodePermissions + 'static, { @@ -388,9 +416,7 @@ where let node_resolver = state.borrow::(); let pkg = node_resolver - .get_closest_package_json( - &Url::from_file_path(parent_path.unwrap()).unwrap(), - ) + .get_closest_package_json_from_path(&PathBuf::from(parent_path.unwrap())) .ok() .flatten(); if pkg.is_none() { @@ -442,12 +468,13 @@ where pub fn op_require_read_file

( state: &mut OpState, #[string] file_path: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { let file_path = PathBuf::from(file_path); - ensure_read_permission::

(state, &file_path)?; + let file_path = ensure_read_permission::

(state, &file_path) + .map_err(RequireError::Permission)?; let fs = state.borrow::(); Ok(fs.read_text_file_lossy_sync(&file_path, None)?) } @@ -457,7 +484,7 @@ where pub fn op_require_as_file_path(#[string] file_or_url: String) -> String { if let Ok(url) = Url::parse(&file_or_url) { if let Ok(p) = url.to_file_path() { - return p.to_string_lossy().to_string(); + return p.to_string_lossy().into_owned(); } } @@ -469,12 +496,12 @@ pub fn op_require_as_file_path(#[string] file_or_url: String) -> String { pub fn op_require_resolve_exports

( state: &mut OpState, uses_local_node_modules_dir: bool, - #[string] modules_path: String, + #[string] modules_path_str: String, #[string] _request: String, #[string] name: String, #[string] expansion: String, #[string] parent_path: String, -) -> Result, AnyError> +) -> Result, RequireError> where P: NodePermissions + 'static, { @@ -482,22 +509,22 @@ where let npm_resolver = state.borrow::(); let node_resolver = state.borrow::(); - let pkg_path = if npm_resolver - .in_npm_package_at_file_path(&PathBuf::from(&modules_path)) + let modules_path = PathBuf::from(&modules_path_str); + let pkg_path = if npm_resolver.in_npm_package_at_file_path(&modules_path) && !uses_local_node_modules_dir { modules_path } else { - let original = modules_path.clone(); - let mod_dir = path_resolve(vec![modules_path, name]); - if fs.is_dir_sync(Path::new(&mod_dir)) { + let mod_dir = + path_resolve([modules_path_str.as_str(), name.as_str()].into_iter()); + if fs.is_dir_sync(&mod_dir) { mod_dir } else { - original + modules_path } }; - let Some(pkg) = node_resolver - .load_package_json(&PathBuf::from(&pkg_path).join("package.json"))? + let Some(pkg) = + node_resolver.load_package_json(&pkg_path.join("package.json"))? else { return Ok(None); }; @@ -527,19 +554,14 @@ where pub fn op_require_read_closest_package_json

( state: &mut OpState, #[string] filename: String, -) -> Result, AnyError> +) -> Result, node_resolver::errors::ClosestPkgJsonError> where P: NodePermissions + 'static, { - ensure_read_permission::

( - state, - PathBuf::from(&filename).parent().unwrap(), - )?; + let filename = PathBuf::from(filename); + // permissions: allow reading the closest package.json files let node_resolver = state.borrow::().clone(); - node_resolver - .get_closest_package_json(&Url::from_file_path(filename).unwrap()) - .map(|maybe_pkg| maybe_pkg.map(|pkg| (*pkg).clone())) - .map_err(AnyError::from) + node_resolver.get_closest_package_json_from_path(&filename) } #[op2] @@ -547,7 +569,7 @@ where pub fn op_require_read_package_scope

( state: &mut OpState, #[string] package_json_path: String, -) -> Option +) -> Option where P: NodePermissions + 'static, { @@ -561,7 +583,6 @@ where .load_package_json(&package_json_path) .ok() .flatten() - .map(|pkg| (*pkg).clone()) } #[op2] @@ -570,12 +591,13 @@ pub fn op_require_package_imports_resolve

( state: &mut OpState, #[string] referrer_filename: String, #[string] request: String, -) -> Result, AnyError> +) -> Result, RequireError> where P: NodePermissions + 'static, { let referrer_path = PathBuf::from(&referrer_filename); - ensure_read_permission::

(state, &referrer_path)?; + let referrer_path = ensure_read_permission::

(state, &referrer_path) + .map_err(RequireError::Permission)?; let node_resolver = state.borrow::(); let Some(pkg) = node_resolver.get_closest_package_json_from_path(&referrer_path)? @@ -584,8 +606,7 @@ where }; if pkg.imports.is_some() { - let referrer_url = - deno_core::url::Url::from_file_path(&referrer_filename).unwrap(); + let referrer_url = Url::from_file_path(&referrer_filename).unwrap(); let url = node_resolver.package_imports_resolve( &request, Some(&referrer_url), @@ -600,24 +621,50 @@ where } } -#[op2(fast)] -pub fn op_require_break_on_next_statement(state: &mut OpState) { - let inspector = state.borrow::>>(); - inspector - .borrow_mut() - .wait_for_session_and_break_on_next_statement() +#[op2(fast, reentrant)] +pub fn op_require_break_on_next_statement(state: Rc>) { + let inspector_rc = { + let state = state.borrow(); + state.borrow::>>().clone() + }; + let mut inspector = inspector_rc.borrow_mut(); + inspector.wait_for_session_and_break_on_next_statement() } -fn url_to_file_path_string(url: &Url) -> Result { +fn url_to_file_path_string(url: &Url) -> Result { let file_path = url_to_file_path(url)?; - Ok(file_path.to_string_lossy().to_string()) + Ok(file_path.to_string_lossy().into_owned()) } -fn url_to_file_path(url: &Url) -> Result { +fn url_to_file_path(url: &Url) -> Result { match url.to_file_path() { Ok(file_path) => Ok(file_path), - Err(()) => { - deno_core::anyhow::bail!("failed to convert '{}' to file path", url) - } + Err(()) => Err(RequireError::FilePathConversion(url.clone())), } } + +#[op2(fast)] +pub fn op_require_can_parse_as_esm( + scope: &mut v8::HandleScope, + #[string] source: &str, +) -> bool { + let scope = &mut v8::TryCatch::new(scope); + let Some(source) = v8::String::new(scope, source) else { + return false; + }; + let origin = v8::ScriptOrigin::new( + scope, + source.into(), + 0, + 0, + false, + 0, + None, + true, + false, + true, + None, + ); + let mut source = v8::script_compiler::Source::new(source, Some(&origin)); + v8::script_compiler::compile_module(scope, &mut source).is_some() +} diff --git a/ext/node/ops/tls.rs b/ext/node/ops/tls.rs new file mode 100644 index 0000000000..86b1779601 --- /dev/null +++ b/ext/node/ops/tls.rs @@ -0,0 +1,29 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use base64::Engine; +use deno_core::op2; +use webpki_root_certs; + +#[op2] +#[serde] +pub fn op_get_root_certificates() -> Vec { + let certs = webpki_root_certs::TLS_SERVER_ROOT_CERTS + .iter() + .map(|cert| { + let b64 = base64::engine::general_purpose::STANDARD.encode(cert); + let pem_lines = b64 + .chars() + .collect::>() + // Node uses 72 characters per line, so we need to follow node even though + // it's not spec compliant https://datatracker.ietf.org/doc/html/rfc7468#section-2 + .chunks(72) + .map(|c| c.iter().collect::()) + .collect::>() + .join("\n"); + let pem = format!( + "-----BEGIN CERTIFICATE-----\n{pem_lines}\n-----END CERTIFICATE-----\n", + ); + pem + }) + .collect::>(); + certs +} diff --git a/ext/node/ops/util.rs b/ext/node/ops/util.rs index 533d51c92c..1c177ac043 100644 --- a/ext/node/ops/util.rs +++ b/ext/node/ops/util.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::ResourceHandle; @@ -22,7 +21,7 @@ enum HandleType { pub fn op_node_guess_handle_type( state: &mut OpState, rid: u32, -) -> Result { +) -> Result { let handle = state.resource_table.get_handle(rid)?; let handle_type = match handle { diff --git a/ext/node/ops/v8.rs b/ext/node/ops/v8.rs index 5520784f35..61f67f11f7 100644 --- a/ext/node/ops/v8.rs +++ b/ext/node/ops/v8.rs @@ -1,13 +1,20 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + use deno_core::op2; use deno_core::v8; +use deno_core::FastString; +use deno_core::GarbageCollected; +use deno_core::ToJsBuffer; +use std::ptr::NonNull; +use v8::ValueDeserializerHelper; +use v8::ValueSerializerHelper; #[op2(fast)] pub fn op_v8_cached_data_version_tag() -> u32 { v8::script_compiler::cached_data_version_tag() } -#[op2] +#[op2(fast)] pub fn op_v8_get_heap_statistics( scope: &mut v8::HandleScope, #[buffer] buffer: &mut [f64], @@ -30,3 +37,356 @@ pub fn op_v8_get_heap_statistics( buffer[12] = stats.used_global_handles_size() as f64; buffer[13] = stats.external_memory() as f64; } + +pub struct Serializer<'a> { + inner: v8::ValueSerializer<'a>, +} + +pub struct SerializerDelegate { + obj: v8::Global, +} + +impl<'a> v8::cppgc::GarbageCollected for Serializer<'a> { + fn trace(&self, _visitor: &v8::cppgc::Visitor) {} +} + +impl SerializerDelegate { + fn obj<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + ) -> v8::Local<'s, v8::Object> { + v8::Local::new(scope, &self.obj) + } +} + +impl v8::ValueSerializerImpl for SerializerDelegate { + fn get_shared_array_buffer_id<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>, + ) -> Option { + let obj = self.obj(scope); + let key = FastString::from_static("_getSharedArrayBufferId") + .v8_string(scope) + .into(); + if let Some(v) = obj.get(scope, key) { + if let Ok(fun) = v.try_cast::() { + return fun + .call(scope, obj.into(), &[shared_array_buffer.into()]) + .and_then(|ret| ret.uint32_value(scope)); + } + } + None + } + fn has_custom_host_object(&self, _isolate: &mut v8::Isolate) -> bool { + false + } + fn throw_data_clone_error<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + message: v8::Local<'s, v8::String>, + ) { + let obj = self.obj(scope); + let key = FastString::from_static("_getDataCloneError") + .v8_string(scope) + .into(); + if let Some(v) = obj.get(scope, key) { + let fun = v + .try_cast::() + .expect("_getDataCloneError should be a function"); + if let Some(error) = fun.call(scope, obj.into(), &[message.into()]) { + scope.throw_exception(error); + return; + } + } + let error = v8::Exception::type_error(scope, message); + scope.throw_exception(error); + } + + fn write_host_object<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + object: v8::Local<'s, v8::Object>, + _value_serializer: &dyn ValueSerializerHelper, + ) -> Option { + let obj = self.obj(scope); + let key = FastString::from_static("_writeHostObject") + .v8_string(scope) + .into(); + if let Some(v) = obj.get(scope, key) { + if let Ok(v) = v.try_cast::() { + v.call(scope, obj.into(), &[object.into()])?; + return Some(true); + } + } + + None + } + + fn is_host_object<'s>( + &self, + _scope: &mut v8::HandleScope<'s>, + _object: v8::Local<'s, v8::Object>, + ) -> Option { + // should never be called because has_custom_host_object returns false + None + } +} + +#[op2] +#[cppgc] +pub fn op_v8_new_serializer( + scope: &mut v8::HandleScope, + obj: v8::Local, +) -> Serializer<'static> { + let obj = v8::Global::new(scope, obj); + let inner = + v8::ValueSerializer::new(scope, Box::new(SerializerDelegate { obj })); + Serializer { inner } +} + +#[op2(fast)] +pub fn op_v8_set_treat_array_buffer_views_as_host_objects( + #[cppgc] ser: &Serializer, + value: bool, +) { + ser + .inner + .set_treat_array_buffer_views_as_host_objects(value); +} + +#[op2] +#[serde] +pub fn op_v8_release_buffer(#[cppgc] ser: &Serializer) -> ToJsBuffer { + ser.inner.release().into() +} + +#[op2(fast)] +pub fn op_v8_transfer_array_buffer( + #[cppgc] ser: &Serializer, + #[smi] id: u32, + array_buffer: v8::Local, +) { + ser.inner.transfer_array_buffer(id, array_buffer); +} + +#[op2(fast)] +pub fn op_v8_write_double(#[cppgc] ser: &Serializer, double: f64) { + ser.inner.write_double(double); +} + +#[op2(fast)] +pub fn op_v8_write_header(#[cppgc] ser: &Serializer) { + ser.inner.write_header(); +} + +#[op2] +pub fn op_v8_write_raw_bytes( + #[cppgc] ser: &Serializer, + #[anybuffer] source: &[u8], +) { + ser.inner.write_raw_bytes(source); +} + +#[op2(fast)] +pub fn op_v8_write_uint32(#[cppgc] ser: &Serializer, num: u32) { + ser.inner.write_uint32(num); +} + +#[op2(fast)] +pub fn op_v8_write_uint64(#[cppgc] ser: &Serializer, hi: u32, lo: u32) { + let num = ((hi as u64) << 32) | (lo as u64); + ser.inner.write_uint64(num); +} + +#[op2(nofast, reentrant)] +pub fn op_v8_write_value( + scope: &mut v8::HandleScope, + #[cppgc] ser: &Serializer, + value: v8::Local, +) { + let context = scope.get_current_context(); + ser.inner.write_value(context, value); +} + +struct DeserBuffer { + ptr: Option>, + // Hold onto backing store to keep the underlying buffer + // alive while we hold a reference to it. + _backing_store: v8::SharedRef, +} + +pub struct Deserializer<'a> { + buf: DeserBuffer, + inner: v8::ValueDeserializer<'a>, +} + +impl<'a> deno_core::GarbageCollected for Deserializer<'a> {} + +pub struct DeserializerDelegate { + obj: v8::Global, +} + +impl GarbageCollected for DeserializerDelegate { + fn trace(&self, _visitor: &v8::cppgc::Visitor) {} +} + +impl v8::ValueDeserializerImpl for DeserializerDelegate { + fn read_host_object<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + _value_deserializer: &dyn v8::ValueDeserializerHelper, + ) -> Option> { + let obj = v8::Local::new(scope, &self.obj); + let key = FastString::from_static("_readHostObject") + .v8_string(scope) + .into(); + let scope = &mut v8::AllowJavascriptExecutionScope::new(scope); + if let Some(v) = obj.get(scope, key) { + if let Ok(v) = v.try_cast::() { + let result = v.call(scope, obj.into(), &[])?; + match result.try_cast() { + Ok(res) => return Some(res), + Err(_) => { + let msg = + FastString::from_static("readHostObject must return an object") + .v8_string(scope); + let error = v8::Exception::type_error(scope, msg); + scope.throw_exception(error); + return None; + } + } + } + } + None + } +} + +#[op2] +#[cppgc] +pub fn op_v8_new_deserializer( + scope: &mut v8::HandleScope, + obj: v8::Local, + buffer: v8::Local, +) -> Result, deno_core::error::AnyError> { + let offset = buffer.byte_offset(); + let len = buffer.byte_length(); + let backing_store = buffer.get_backing_store().ok_or_else(|| { + deno_core::error::generic_error( + "deserialization buffer has no backing store", + ) + })?; + let (buf_slice, buf_ptr) = if let Some(data) = backing_store.data() { + // SAFETY: the offset is valid for the underlying buffer because we're getting it directly from v8 + let data_ptr = unsafe { data.as_ptr().cast::().add(offset) }; + ( + // SAFETY: the len is valid, from v8, and the data_ptr is valid (as above) + unsafe { std::slice::from_raw_parts(data_ptr.cast_const().cast(), len) }, + Some(data.cast()), + ) + } else { + (&[] as &[u8], None::>) + }; + let obj = v8::Global::new(scope, obj); + let inner = v8::ValueDeserializer::new( + scope, + Box::new(DeserializerDelegate { obj }), + buf_slice, + ); + Ok(Deserializer { + inner, + buf: DeserBuffer { + _backing_store: backing_store, + ptr: buf_ptr, + }, + }) +} + +#[op2(fast)] +pub fn op_v8_transfer_array_buffer_de( + #[cppgc] deser: &Deserializer, + #[smi] id: u32, + array_buffer: v8::Local, +) { + // TODO(nathanwhit): also need binding for TransferSharedArrayBuffer, then call that if + // array_buffer is shared + deser.inner.transfer_array_buffer(id, array_buffer); +} + +#[op2(fast)] +pub fn op_v8_read_double( + #[cppgc] deser: &Deserializer, +) -> Result { + let mut double = 0f64; + if !deser.inner.read_double(&mut double) { + return Err(deno_core::error::type_error("ReadDouble() failed")); + } + Ok(double) +} + +#[op2(nofast)] +pub fn op_v8_read_header( + scope: &mut v8::HandleScope, + #[cppgc] deser: &Deserializer, +) -> bool { + let context = scope.get_current_context(); + let res = deser.inner.read_header(context); + res.unwrap_or_default() +} + +#[op2(fast)] +#[number] +pub fn op_v8_read_raw_bytes( + #[cppgc] deser: &Deserializer, + #[number] length: usize, +) -> usize { + let Some(buf_ptr) = deser.buf.ptr else { + return 0; + }; + if let Some(buf) = deser.inner.read_raw_bytes(length) { + let ptr = buf.as_ptr(); + (ptr as usize) - (buf_ptr.as_ptr() as usize) + } else { + 0 + } +} + +#[op2(fast)] +pub fn op_v8_read_uint32( + #[cppgc] deser: &Deserializer, +) -> Result { + let mut value = 0; + if !deser.inner.read_uint32(&mut value) { + return Err(deno_core::error::type_error("ReadUint32() failed")); + } + + Ok(value) +} + +#[op2] +#[serde] +pub fn op_v8_read_uint64( + #[cppgc] deser: &Deserializer, +) -> Result<(u32, u32), deno_core::error::AnyError> { + let mut val = 0; + if !deser.inner.read_uint64(&mut val) { + return Err(deno_core::error::type_error("ReadUint64() failed")); + } + + Ok(((val >> 32) as u32, val as u32)) +} + +#[op2(fast)] +pub fn op_v8_get_wire_format_version(#[cppgc] deser: &Deserializer) -> u32 { + deser.inner.get_wire_format_version() +} + +#[op2(reentrant)] +pub fn op_v8_read_value<'s>( + scope: &mut v8::HandleScope<'s>, + #[cppgc] deser: &Deserializer, +) -> v8::Local<'s, v8::Value> { + let context = scope.get_current_context(); + let val = deser.inner.read_value(context); + val.unwrap_or_else(|| v8::null(scope).into()) +} diff --git a/ext/node/ops/vm.rs b/ext/node/ops/vm.rs index e75e05651e..25881cbaed 100644 --- a/ext/node/ops/vm.rs +++ b/ext/node/ops/vm.rs @@ -410,8 +410,8 @@ impl ContextifyContext { fn sandbox<'a>( &self, scope: &mut v8::HandleScope<'a>, - ) -> v8::Local<'a, v8::Object> { - self.sandbox.get(scope).unwrap() + ) -> Option> { + self.sandbox.get(scope) } fn microtask_queue(&self) -> Option<&v8::MicrotaskQueue> { @@ -600,7 +600,9 @@ fn property_query<'s>( let context = ctx.context(scope); let scope = &mut v8::ContextScope::new(scope, context); - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; match sandbox.has_real_named_property(scope, property) { None => v8::Intercepted::No, @@ -645,7 +647,9 @@ fn property_getter<'s>( return v8::Intercepted::No; }; - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; let tc_scope = &mut v8::TryCatch::new(scope); let maybe_rv = sandbox.get_real_named_property(tc_scope, key).or_else(|| { @@ -689,14 +693,14 @@ fn property_setter<'s>( None => (v8::PropertyAttribute::NONE, false), }; let mut read_only = attributes.is_read_only(); - - let (attributes, is_declared_on_sandbox) = match ctx - .sandbox(scope) - .get_real_named_property_attributes(scope, key) - { - Some(attr) => (attr, true), - None => (v8::PropertyAttribute::NONE, false), + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; }; + let (attributes, is_declared_on_sandbox) = + match sandbox.get_real_named_property_attributes(scope, key) { + Some(attr) => (attr, true), + None => (v8::PropertyAttribute::NONE, false), + }; read_only |= attributes.is_read_only(); if read_only { @@ -731,14 +735,12 @@ fn property_setter<'s>( return v8::Intercepted::No; }; - if ctx.sandbox(scope).set(scope, key.into(), value).is_none() { + if sandbox.set(scope, key.into(), value).is_none() { return v8::Intercepted::No; } if is_declared_on_sandbox { - if let Some(desc) = - ctx.sandbox(scope).get_own_property_descriptor(scope, key) - { + if let Some(desc) = sandbox.get_own_property_descriptor(scope, key) { if !desc.is_undefined() { let desc_obj: v8::Local = desc.try_into().unwrap(); // We have to specify the return value for any contextual or get/set @@ -774,7 +776,9 @@ fn property_descriptor<'s>( }; let context = ctx.context(scope); - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; let scope = &mut v8::ContextScope::new(scope, context); if sandbox.has_own_property(scope, key).unwrap_or(false) { @@ -818,7 +822,9 @@ fn property_definer<'s>( return v8::Intercepted::No; } - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; let define_prop_on_sandbox = |scope: &mut v8::HandleScope, @@ -880,7 +886,10 @@ fn property_deleter<'s>( }; let context = ctx.context(scope); - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; + let context_scope = &mut v8::ContextScope::new(scope, context); if sandbox.delete(context_scope, key.into()).unwrap_or(false) { return v8::Intercepted::No; @@ -900,7 +909,10 @@ fn property_enumerator<'s>( }; let context = ctx.context(scope); - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return; + }; + let context_scope = &mut v8::ContextScope::new(scope, context); let Some(properties) = sandbox .get_property_names(context_scope, v8::GetPropertyNamesArgs::default()) @@ -921,12 +933,14 @@ fn indexed_property_enumerator<'s>( }; let context = ctx.context(scope); let scope = &mut v8::ContextScope::new(scope, context); + let Some(sandbox) = ctx.sandbox(scope) else { + return; + }; // By default, GetPropertyNames returns string and number property names, and // doesn't convert the numbers to strings. - let Some(properties) = ctx - .sandbox(scope) - .get_property_names(scope, v8::GetPropertyNamesArgs::default()) + let Some(properties) = + sandbox.get_property_names(scope, v8::GetPropertyNamesArgs::default()) else { return; }; @@ -1019,7 +1033,10 @@ fn indexed_property_deleter<'s>( }; let context = ctx.context(scope); - let sandbox = ctx.sandbox(scope); + let Some(sandbox) = ctx.sandbox(scope) else { + return v8::Intercepted::No; + }; + let context_scope = &mut v8::ContextScope::new(scope, context); if !sandbox.delete_index(context_scope, index).unwrap_or(false) { return v8::Intercepted::No; @@ -1074,7 +1091,7 @@ pub fn op_vm_script_run_in_context<'a>( ) } -#[op2] +#[op2(fast)] pub fn op_vm_create_context( scope: &mut v8::HandleScope, sandbox_obj: v8::Local, @@ -1101,7 +1118,7 @@ pub fn op_vm_create_context( ); } -#[op2] +#[op2(fast)] pub fn op_vm_is_context( scope: &mut v8::HandleScope, sandbox_obj: v8::Local, diff --git a/ext/node/ops/winerror.rs b/ext/node/ops/winerror.rs index c0d66f7d0b..cb053774ef 100644 --- a/ext/node/ops/winerror.rs +++ b/ext/node/ops/winerror.rs @@ -62,10 +62,11 @@ pub fn op_node_sys_to_uv_error(err: i32) -> String { WSAEHOSTUNREACH => "EHOSTUNREACH", ERROR_INSUFFICIENT_BUFFER => "EINVAL", ERROR_INVALID_DATA => "EINVAL", - ERROR_INVALID_NAME => "EINVAL", + ERROR_INVALID_NAME => "ENOENT", ERROR_INVALID_PARAMETER => "EINVAL", WSAEINVAL => "EINVAL", WSAEPFNOSUPPORT => "EINVAL", + ERROR_NOT_A_REPARSE_POINT => "EINVAL", ERROR_BEGINNING_OF_MEDIA => "EIO", ERROR_BUS_RESET => "EIO", ERROR_CRC => "EIO", diff --git a/ext/node/ops/worker_threads.rs b/ext/node/ops/worker_threads.rs index c7ea4c52c2..e33cf91574 100644 --- a/ext/node/ops/worker_threads.rs +++ b/ext/node/ops/worker_threads.rs @@ -1,12 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::generic_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::url::Url; use deno_core::OpState; use deno_fs::FileSystemRc; use node_resolver::NodeResolution; +use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; @@ -14,10 +13,11 @@ use crate::NodePermissions; use crate::NodeRequireResolverRc; use crate::NodeResolverRc; -fn ensure_read_permission

( +#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] +fn ensure_read_permission<'a, P>( state: &mut OpState, - file_path: &Path, -) -> Result<(), AnyError> + file_path: &'a Path, +) -> Result, deno_core::error::AnyError> where P: NodePermissions + 'static, { @@ -26,12 +26,36 @@ where resolver.ensure_read_permission(permissions, file_path) } +#[derive(Debug, thiserror::Error)] +pub enum WorkerThreadsFilenameError { + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error("{0}")] + UrlParse(#[from] url::ParseError), + #[error("Relative path entries must start with '.' or '..'")] + InvalidRelativeUrl, + #[error("URL from Path-String")] + UrlFromPathString, + #[error("URL to Path-String")] + UrlToPathString, + #[error("URL to Path")] + UrlToPath, + #[error("File not found [{0:?}]")] + FileNotFound(PathBuf), + #[error("Neither ESM nor CJS")] + NeitherEsmNorCjs, + #[error("{0}")] + UrlToNodeResolution(node_resolver::errors::UrlToNodeResolutionError), + #[error(transparent)] + Fs(#[from] deno_io::fs::FsError), +} + #[op2] #[string] pub fn op_worker_threads_filename

( state: &mut OpState, #[string] specifier: String, -) -> Result +) -> Result where P: NodePermissions + 'static, { @@ -43,40 +67,47 @@ where } else { let path = PathBuf::from(&specifier); if path.is_relative() && !specifier.starts_with('.') { - return Err(generic_error( - "Relative path entries must start with '.' or '..'", - )); + return Err(WorkerThreadsFilenameError::InvalidRelativeUrl); } - ensure_read_permission::

(state, &path)?; + let path = ensure_read_permission::

(state, &path) + .map_err(WorkerThreadsFilenameError::Permission)?; let fs = state.borrow::(); let canonicalized_path = - deno_core::strip_unc_prefix(fs.realpath_sync(&path)?); + deno_path_util::strip_unc_prefix(fs.realpath_sync(&path)?); Url::from_file_path(canonicalized_path) - .map_err(|e| generic_error(format!("URL from Path-String: {:#?}", e)))? + .map_err(|_| WorkerThreadsFilenameError::UrlFromPathString)? }; let url_path = url .to_file_path() - .map_err(|e| generic_error(format!("URL to Path-String: {:#?}", e)))?; - ensure_read_permission::

(state, &url_path)?; + .map_err(|_| WorkerThreadsFilenameError::UrlToPathString)?; + let url_path = ensure_read_permission::

(state, &url_path) + .map_err(WorkerThreadsFilenameError::Permission)?; let fs = state.borrow::(); if !fs.exists_sync(&url_path) { - return Err(generic_error(format!("File not found [{:?}]", url_path))); + return Err(WorkerThreadsFilenameError::FileNotFound( + url_path.to_path_buf(), + )); } let node_resolver = state.borrow::(); - match node_resolver.url_to_node_resolution(url)? { + match node_resolver + .url_to_node_resolution(url) + .map_err(WorkerThreadsFilenameError::UrlToNodeResolution)? + { NodeResolution::Esm(u) => Ok(u.to_string()), NodeResolution::CommonJs(u) => wrap_cjs(u), - NodeResolution::BuiltIn(_) => Err(generic_error("Neither ESM nor CJS")), + NodeResolution::BuiltIn(_) => { + Err(WorkerThreadsFilenameError::NeitherEsmNorCjs) + } } } /// /// Wrap a CJS file-URL and the required setup in a stringified `data:`-URL /// -fn wrap_cjs(url: Url) -> Result { +fn wrap_cjs(url: Url) -> Result { let path = url .to_file_path() - .map_err(|e| generic_error(format!("URL to Path: {:#?}", e)))?; + .map_err(|_| WorkerThreadsFilenameError::UrlToPath)?; let filename = path.file_name().unwrap().to_string_lossy(); Ok(format!( "data:text/javascript,import {{ createRequire }} from \"node:module\";\ diff --git a/ext/node/ops/zlib/brotli.rs b/ext/node/ops/zlib/brotli.rs index 3e3905fc3d..1a681ff7f7 100644 --- a/ext/node/ops/zlib/brotli.rs +++ b/ext/node/ops/zlib/brotli.rs @@ -9,8 +9,6 @@ use brotli::BrotliDecompressStream; use brotli::BrotliResult; use brotli::BrotliState; use brotli::Decompressor; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::JsBuffer; use deno_core::OpState; @@ -19,7 +17,23 @@ use deno_core::ToJsBuffer; use std::cell::RefCell; use std::io::Read; -fn encoder_mode(mode: u32) -> Result { +#[derive(Debug, thiserror::Error)] +pub enum BrotliError { + #[error("Invalid encoder mode")] + InvalidEncoderMode, + #[error("Failed to compress")] + CompressFailed, + #[error("Failed to decompress")] + DecompressFailed, + #[error(transparent)] + Join(#[from] tokio::task::JoinError), + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("{0}")] + Io(std::io::Error), +} + +fn encoder_mode(mode: u32) -> Result { Ok(match mode { 0 => BrotliEncoderMode::BROTLI_MODE_GENERIC, 1 => BrotliEncoderMode::BROTLI_MODE_TEXT, @@ -28,7 +42,7 @@ fn encoder_mode(mode: u32) -> Result { 4 => BrotliEncoderMode::BROTLI_FORCE_MSB_PRIOR, 5 => BrotliEncoderMode::BROTLI_FORCE_UTF8_PRIOR, 6 => BrotliEncoderMode::BROTLI_FORCE_SIGNED_PRIOR, - _ => return Err(type_error("Invalid encoder mode")), + _ => return Err(BrotliError::InvalidEncoderMode), }) } @@ -40,7 +54,7 @@ pub fn op_brotli_compress( #[smi] quality: i32, #[smi] lgwin: i32, #[smi] mode: u32, -) -> Result { +) -> Result { let mode = encoder_mode(mode)?; let mut out_size = out.len(); @@ -57,7 +71,7 @@ pub fn op_brotli_compress( &mut |_, _, _, _| (), ); if result != 1 { - return Err(type_error("Failed to compress")); + return Err(BrotliError::CompressFailed); } Ok(out_size) @@ -87,7 +101,7 @@ pub async fn op_brotli_compress_async( #[smi] quality: i32, #[smi] lgwin: i32, #[smi] mode: u32, -) -> Result { +) -> Result { let mode = encoder_mode(mode)?; tokio::task::spawn_blocking(move || { let input = &*input; @@ -107,7 +121,7 @@ pub async fn op_brotli_compress_async( &mut |_, _, _, _| (), ); if result != 1 { - return Err(type_error("Failed to compress")); + return Err(BrotliError::CompressFailed); } out.truncate(out_size); @@ -151,8 +165,11 @@ pub fn op_brotli_compress_stream( #[smi] rid: u32, #[buffer] input: &[u8], #[buffer] output: &mut [u8], -) -> Result { - let ctx = state.resource_table.get::(rid)?; +) -> Result { + let ctx = state + .resource_table + .get::(rid) + .map_err(BrotliError::Resource)?; let mut inst = ctx.inst.borrow_mut(); let mut output_offset = 0; @@ -168,7 +185,7 @@ pub fn op_brotli_compress_stream( &mut |_, _, _, _| (), ); if !result { - return Err(type_error("Failed to compress")); + return Err(BrotliError::CompressFailed); } Ok(output_offset) @@ -180,8 +197,11 @@ pub fn op_brotli_compress_stream_end( state: &mut OpState, #[smi] rid: u32, #[buffer] output: &mut [u8], -) -> Result { - let ctx = state.resource_table.get::(rid)?; +) -> Result { + let ctx = state + .resource_table + .get::(rid) + .map_err(BrotliError::Resource)?; let mut inst = ctx.inst.borrow_mut(); let mut output_offset = 0; @@ -197,13 +217,13 @@ pub fn op_brotli_compress_stream_end( &mut |_, _, _, _| (), ); if !result { - return Err(type_error("Failed to compress")); + return Err(BrotliError::CompressFailed); } Ok(output_offset) } -fn brotli_decompress(buffer: &[u8]) -> Result { +fn brotli_decompress(buffer: &[u8]) -> Result { let mut output = Vec::with_capacity(4096); let mut decompressor = Decompressor::new(buffer, buffer.len()); decompressor.read_to_end(&mut output)?; @@ -214,7 +234,7 @@ fn brotli_decompress(buffer: &[u8]) -> Result { #[serde] pub fn op_brotli_decompress( #[buffer] buffer: &[u8], -) -> Result { +) -> Result { brotli_decompress(buffer) } @@ -222,8 +242,11 @@ pub fn op_brotli_decompress( #[serde] pub async fn op_brotli_decompress_async( #[buffer] buffer: JsBuffer, -) -> Result { - tokio::task::spawn_blocking(move || brotli_decompress(&buffer)).await? +) -> Result { + tokio::task::spawn_blocking(move || { + brotli_decompress(&buffer).map_err(BrotliError::Io) + }) + .await? } struct BrotliDecompressCtx { @@ -252,8 +275,11 @@ pub fn op_brotli_decompress_stream( #[smi] rid: u32, #[buffer] input: &[u8], #[buffer] output: &mut [u8], -) -> Result { - let ctx = state.resource_table.get::(rid)?; +) -> Result { + let ctx = state + .resource_table + .get::(rid) + .map_err(BrotliError::Resource)?; let mut inst = ctx.inst.borrow_mut(); let mut output_offset = 0; @@ -268,7 +294,7 @@ pub fn op_brotli_decompress_stream( &mut inst, ); if matches!(result, BrotliResult::ResultFailure) { - return Err(type_error("Failed to decompress")); + return Err(BrotliError::DecompressFailed); } Ok(output_offset) @@ -280,8 +306,11 @@ pub fn op_brotli_decompress_stream_end( state: &mut OpState, #[smi] rid: u32, #[buffer] output: &mut [u8], -) -> Result { - let ctx = state.resource_table.get::(rid)?; +) -> Result { + let ctx = state + .resource_table + .get::(rid) + .map_err(BrotliError::Resource)?; let mut inst = ctx.inst.borrow_mut(); let mut output_offset = 0; @@ -296,7 +325,7 @@ pub fn op_brotli_decompress_stream_end( &mut inst, ); if matches!(result, BrotliResult::ResultFailure) { - return Err(type_error("Failed to decompress")); + return Err(BrotliError::DecompressFailed); } Ok(output_offset) diff --git a/ext/node/ops/zlib/mod.rs b/ext/node/ops/zlib/mod.rs index b1d6d21d22..e75ef050d2 100644 --- a/ext/node/ops/zlib/mod.rs +++ b/ext/node/ops/zlib/mod.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; + use deno_core::op2; use std::borrow::Cow; use std::cell::RefCell; @@ -8,7 +7,7 @@ use zlib::*; mod alloc; pub mod brotli; -mod mode; +pub mod mode; mod stream; use mode::Flush; @@ -17,11 +16,11 @@ use mode::Mode; use self::stream::StreamWrapper; #[inline] -fn check(condition: bool, msg: &str) -> Result<(), AnyError> { +fn check(condition: bool, msg: &str) -> Result<(), deno_core::error::AnyError> { if condition { Ok(()) } else { - Err(type_error(msg.to_string())) + Err(deno_core::error::type_error(msg.to_string())) } } @@ -56,7 +55,7 @@ impl ZlibInner { out_off: u32, out_len: u32, flush: Flush, - ) -> Result<(), AnyError> { + ) -> Result<(), deno_core::error::AnyError> { check(self.init_done, "write before init")?; check(!self.write_in_progress, "write already in progress")?; check(!self.pending_close, "close already in progress")?; @@ -65,11 +64,11 @@ impl ZlibInner { let next_in = input .get(in_off as usize..in_off as usize + in_len as usize) - .ok_or_else(|| type_error("invalid input range"))? + .ok_or_else(|| deno_core::error::type_error("invalid input range"))? .as_ptr() as *mut _; let next_out = out .get_mut(out_off as usize..out_off as usize + out_len as usize) - .ok_or_else(|| type_error("invalid output range"))? + .ok_or_else(|| deno_core::error::type_error("invalid output range"))? .as_mut_ptr(); self.strm.avail_in = in_len; @@ -81,7 +80,10 @@ impl ZlibInner { Ok(()) } - fn do_write(&mut self, flush: Flush) -> Result<(), AnyError> { + fn do_write( + &mut self, + flush: Flush, + ) -> Result<(), deno_core::error::AnyError> { self.flush = flush; match self.mode { Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => { @@ -127,7 +129,7 @@ impl ZlibInner { self.mode = Mode::Inflate; } } else if next_expected_header_byte.is_some() { - return Err(type_error( + return Err(deno_core::error::type_error( "invalid number of gzip magic number bytes read", )); } @@ -181,7 +183,7 @@ impl ZlibInner { Ok(()) } - fn init_stream(&mut self) -> Result<(), AnyError> { + fn init_stream(&mut self) -> Result<(), deno_core::error::AnyError> { match self.mode { Mode::Gzip | Mode::Gunzip => self.window_bits += 16, Mode::Unzip => self.window_bits += 32, @@ -199,7 +201,7 @@ impl ZlibInner { Mode::Inflate | Mode::Gunzip | Mode::InflateRaw | Mode::Unzip => { self.strm.inflate_init(self.window_bits) } - Mode::None => return Err(type_error("Unknown mode")), + Mode::None => return Err(deno_core::error::type_error("Unknown mode")), }; self.write_in_progress = false; @@ -208,7 +210,7 @@ impl ZlibInner { Ok(()) } - fn close(&mut self) -> Result { + fn close(&mut self) -> Result { if self.write_in_progress { self.pending_close = true; return Ok(false); @@ -222,10 +224,8 @@ impl ZlibInner { Ok(true) } - fn reset_stream(&mut self) -> Result<(), AnyError> { + fn reset_stream(&mut self) { self.err = self.strm.reset(self.mode); - - Ok(()) } } @@ -243,7 +243,7 @@ impl deno_core::Resource for Zlib { #[op2] #[cppgc] -pub fn op_zlib_new(#[smi] mode: i32) -> Result { +pub fn op_zlib_new(#[smi] mode: i32) -> Result { let mode = Mode::try_from(mode)?; let inner = ZlibInner { @@ -256,12 +256,20 @@ pub fn op_zlib_new(#[smi] mode: i32) -> Result { }) } +#[derive(Debug, thiserror::Error)] +pub enum ZlibError { + #[error("zlib not initialized")] + NotInitialized, + #[error(transparent)] + Mode(#[from] mode::ModeError), + #[error(transparent)] + Other(#[from] deno_core::error::AnyError), +} + #[op2(fast)] -pub fn op_zlib_close(#[cppgc] resource: &Zlib) -> Result<(), AnyError> { +pub fn op_zlib_close(#[cppgc] resource: &Zlib) -> Result<(), ZlibError> { let mut resource = resource.inner.borrow_mut(); - let zlib = resource - .as_mut() - .ok_or_else(|| type_error("zlib not initialized"))?; + let zlib = resource.as_mut().ok_or(ZlibError::NotInitialized)?; // If there is a pending write, defer the close until the write is done. zlib.close()?; @@ -282,11 +290,9 @@ pub fn op_zlib_write( #[smi] out_off: u32, #[smi] out_len: u32, #[buffer] result: &mut [u32], -) -> Result { +) -> Result { let mut zlib = resource.inner.borrow_mut(); - let zlib = zlib - .as_mut() - .ok_or_else(|| type_error("zlib not initialized"))?; + let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?; let flush = Flush::try_from(flush)?; zlib.start_write(input, in_off, in_len, out, out_off, out_len, flush)?; @@ -307,11 +313,9 @@ pub fn op_zlib_init( #[smi] mem_level: i32, #[smi] strategy: i32, #[buffer] dictionary: &[u8], -) -> Result { +) -> Result { let mut zlib = resource.inner.borrow_mut(); - let zlib = zlib - .as_mut() - .ok_or_else(|| type_error("zlib not initialized"))?; + let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?; check((8..=15).contains(&window_bits), "invalid windowBits")?; check((-1..=9).contains(&level), "invalid level")?; @@ -348,13 +352,11 @@ pub fn op_zlib_init( #[op2(fast)] #[smi] -pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result { +pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result { let mut zlib = resource.inner.borrow_mut(); - let zlib = zlib - .as_mut() - .ok_or_else(|| type_error("zlib not initialized"))?; + let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?; - zlib.reset_stream()?; + zlib.reset_stream(); Ok(zlib.err) } @@ -362,12 +364,10 @@ pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result { #[op2(fast)] pub fn op_zlib_close_if_pending( #[cppgc] resource: &Zlib, -) -> Result<(), AnyError> { +) -> Result<(), ZlibError> { let pending_close = { let mut zlib = resource.inner.borrow_mut(); - let zlib = zlib - .as_mut() - .ok_or_else(|| type_error("zlib not initialized"))?; + let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?; zlib.write_in_progress = false; zlib.pending_close diff --git a/ext/node/ops/zlib/mode.rs b/ext/node/ops/zlib/mode.rs index 753300cc49..41565f9b11 100644 --- a/ext/node/ops/zlib/mode.rs +++ b/ext/node/ops/zlib/mode.rs @@ -1,19 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -#[derive(Debug)] -pub enum Error { - BadArgument, -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Error::BadArgument => write!(f, "bad argument"), - } - } -} - -impl std::error::Error for Error {} +#[derive(Debug, thiserror::Error)] +#[error("bad argument")] +pub struct ModeError; macro_rules! repr_i32 { ($(#[$meta:meta])* $vis:vis enum $name:ident { @@ -25,12 +14,12 @@ macro_rules! repr_i32 { } impl core::convert::TryFrom for $name { - type Error = Error; + type Error = ModeError; fn try_from(v: i32) -> Result { match v { $(x if x == $name::$vname as i32 => Ok($name::$vname),)* - _ => Err(Error::BadArgument), + _ => Err(ModeError), } } } diff --git a/ext/node/polyfill.rs b/ext/node/polyfill.rs index 175228a258..a14b75bac0 100644 --- a/ext/node/polyfill.rs +++ b/ext/node/polyfill.rs @@ -75,6 +75,7 @@ generate_builtin_node_module_lists! { "util/types", "v8", "vm", + "wasi", "worker_threads", "zlib", } diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js index 40bb7f2963..5b0980c310 100644 --- a/ext/node/polyfills/01_require.js +++ b/ext/node/polyfills/01_require.js @@ -4,9 +4,11 @@ import { core, internals, primordials } from "ext:core/mod.js"; import { + op_import_sync, op_napi_open, op_require_as_file_path, op_require_break_on_next_statement, + op_require_can_parse_as_esm, op_require_init_paths, op_require_is_deno_dir_package, op_require_is_request_relative, @@ -65,13 +67,17 @@ const { import { nodeGlobals } from "ext:deno_node/00_globals.js"; -import _httpAgent from "ext:deno_node/_http_agent.mjs"; -import _httpOutgoing from "ext:deno_node/_http_outgoing.ts"; -import _streamDuplex from "ext:deno_node/internal/streams/duplex.mjs"; -import _streamPassthrough from "ext:deno_node/internal/streams/passthrough.mjs"; -import _streamReadable from "ext:deno_node/internal/streams/readable.mjs"; -import _streamTransform from "ext:deno_node/internal/streams/transform.mjs"; -import _streamWritable from "ext:deno_node/internal/streams/writable.mjs"; +import _httpAgent from "node:_http_agent"; +import _httpCommon from "node:_http_common"; +import _httpOutgoing from "node:_http_outgoing"; +import _httpServer from "node:_http_server"; +import _streamDuplex from "node:_stream_duplex"; +import _streamPassthrough from "node:_stream_passthrough"; +import _streamReadable from "node:_stream_readable"; +import _streamTransform from "node:_stream_transform"; +import _streamWritable from "node:_stream_writable"; +import _tlsCommon from "node:_tls_common"; +import _tlsWrap from "node:_tls_wrap"; import assert from "node:assert"; import assertStrict from "node:assert/strict"; import asyncHooks from "node:async_hooks"; @@ -93,6 +99,7 @@ import http from "node:http"; import http2 from "node:http2"; import https from "node:https"; import inspector from "node:inspector"; +import inspectorPromises from "node:inspector/promises"; import internalCp from "ext:deno_node/internal/child_process.ts"; import internalCryptoCertificate from "ext:deno_node/internal/crypto/certificate.ts"; import internalCryptoCipher from "ext:deno_node/internal/crypto/cipher.ts"; @@ -122,6 +129,7 @@ import internalTestBinding from "ext:deno_node/internal/test/binding.ts"; import internalTimers from "ext:deno_node/internal/timers.mjs"; import internalUtil from "ext:deno_node/internal/util.mjs"; import internalUtilInspect from "ext:deno_node/internal/util/inspect.mjs"; +import internalConsole from "ext:deno_node/internal/console/constructor.mjs"; import net from "node:net"; import os from "node:os"; import pathPosix from "node:path/posix"; @@ -144,6 +152,7 @@ import test from "node:test"; import timers from "node:timers"; import timersPromises from "node:timers/promises"; import tls from "node:tls"; +import traceEvents from "node:trace_events"; import tty from "node:tty"; import url from "node:url"; import utilTypes from "node:util/types"; @@ -151,7 +160,7 @@ import util from "node:util"; import v8 from "node:v8"; import vm from "node:vm"; import workerThreads from "node:worker_threads"; -import wasi from "ext:deno_node/wasi.ts"; +import wasi from "node:wasi"; import zlib from "node:zlib"; const nativeModuleExports = ObjectCreate(null); @@ -161,12 +170,16 @@ const builtinModules = []; function setupBuiltinModules() { const nodeModules = { "_http_agent": _httpAgent, + "_http_common": _httpCommon, "_http_outgoing": _httpOutgoing, + "_http_server": _httpServer, "_stream_duplex": _streamDuplex, "_stream_passthrough": _streamPassthrough, "_stream_readable": _streamReadable, "_stream_transform": _streamTransform, "_stream_writable": _streamWritable, + "_tls_common": _tlsCommon, + "_tls_wrap": _tlsWrap, assert, "assert/strict": assertStrict, "async_hooks": asyncHooks, @@ -188,6 +201,8 @@ function setupBuiltinModules() { http2, https, inspector, + "inspector/promises": inspectorPromises, + "internal/console/constructor": internalConsole, "internal/child_process": internalCp, "internal/crypto/certificate": internalCryptoCertificate, "internal/crypto/cipher": internalCryptoCipher, @@ -248,6 +263,7 @@ function setupBuiltinModules() { timers, "timers/promises": timersPromises, tls, + traceEvents, tty, url, util, @@ -890,7 +906,7 @@ Module._preloadModules = function (requests) { Module.prototype.load = function (filename) { if (this.loaded) { - throw Error("Module already loaded"); + throw new Error("Module already loaded"); } // Canonicalize the path so it's not pointing to the symlinked directory @@ -900,16 +916,6 @@ Module.prototype.load = function (filename) { pathDirname(this.filename), ); const extension = findLongestRegisteredExtension(filename); - // allow .mjs to be overridden - if ( - StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"] - ) { - throw createRequireEsmError( - filename, - moduleParentCache.get(this)?.filename, - ); - } - Module._extensions[extension](this, this.filename); this.loaded = true; @@ -940,12 +946,11 @@ Module.prototype.require = function (id) { // The module wrapper looks slightly different to Node. Instead of using one // wrapper function, we use two. The first one exists to performance optimize -// access to magic node globals, like `Buffer` or `process`. The second one -// is the actual wrapper function we run the users code in. -// The only observable difference is that in Deno `arguments.callee` is not -// null. +// access to magic node globals, like `Buffer`. The second one is the actual +// wrapper function we run the users code in. The only observable difference is +// that in Deno `arguments.callee` is not null. Module.wrapper = [ - "(function (exports, require, module, __filename, __dirname, Buffer, clearImmediate, clearInterval, clearTimeout, console, global, process, setImmediate, setInterval, setTimeout, performance) { (function (exports, require, module, __filename, __dirname) {", + "(function (exports, require, module, __filename, __dirname, Buffer, clearImmediate, clearInterval, clearTimeout, global, setImmediate, setInterval, setTimeout, performance) { (function (exports, require, module, __filename, __dirname) {", "\n}).call(this, exports, require, module, __filename, __dirname); })", ]; Module.wrap = function (script) { @@ -988,27 +993,27 @@ function wrapSafe( if (process.mainModule === cjsModuleInstance) { enrichCJSError(err.thrown); } - if (isEsmSyntaxError(err.thrown)) { - throw createRequireEsmError( - filename, - moduleParentCache.get(cjsModuleInstance)?.filename, - ); - } else { - throw err.thrown; - } + throw err.thrown; } return f; } Module.prototype._compile = function (content, filename, format) { - const compiledWrapper = wrapSafe(filename, content, this, format); - if (format === "module") { - // TODO(https://github.com/denoland/deno/issues/24822): implement require esm - throw createRequireEsmError( - filename, - moduleParentCache.get(module)?.filename, - ); + return loadESMFromCJS(this, filename, content); + } + + let compiledWrapper; + try { + compiledWrapper = wrapSafe(filename, content, this, format); + } catch (err) { + if ( + format !== "commonjs" && err instanceof SyntaxError && + op_require_can_parse_as_esm(content) + ) { + return loadESMFromCJS(this, filename, content); + } + throw err; } const dirname = pathDirname(filename); @@ -1029,9 +1034,7 @@ Module.prototype._compile = function (content, filename, format) { clearImmediate, clearInterval, clearTimeout, - console, global, - process, setImmediate, setInterval, setTimeout, @@ -1049,9 +1052,7 @@ Module.prototype._compile = function (content, filename, format) { clearImmediate, clearInterval, clearTimeout, - console, global, - process, setImmediate, setInterval, setTimeout, @@ -1069,13 +1070,8 @@ Module._extensions[".js"] = function (module, filename) { let format; if (StringPrototypeEndsWith(filename, ".js")) { const pkg = op_require_read_closest_package_json(filename); - if (pkg?.typ === "module") { - // TODO(https://github.com/denoland/deno/issues/24822): implement require esm + if (pkg?.type === "module") { format = "module"; - throw createRequireEsmError( - filename, - moduleParentCache.get(module)?.filename, - ); } else if (pkg?.type === "commonjs") { format = "commonjs"; } @@ -1086,20 +1082,19 @@ Module._extensions[".js"] = function (module, filename) { module._compile(content, filename, format); }; -function createRequireEsmError(filename, parent) { - let message = `require() of ES Module ${filename}`; +function loadESMFromCJS(module, filename, code) { + const namespace = op_import_sync( + url.pathToFileURL(filename).toString(), + code, + ); - if (parent) { - message += ` from ${parent}`; - } - - message += - ` not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.`; - const err = new Error(message); - err.code = "ERR_REQUIRE_ESM"; - return err; + module.exports = namespace; } +Module._extensions[".mjs"] = function (module, filename) { + loadESMFromCJS(module, filename); +}; + function stripBOM(content) { if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) { content = StringPrototypeSlice(content, 1); @@ -1121,6 +1116,9 @@ Module._extensions[".json"] = function (module, filename) { // Native extension for .node Module._extensions[".node"] = function (module, filename) { + if (filename.endsWith("cpufeatures.node")) { + throw new Error("Using cpu-features module is currently not supported"); + } module.exports = op_napi_open( filename, globalThis, diff --git a/ext/node/polyfills/02_init.js b/ext/node/polyfills/02_init.js index 7a697abe49..b25f7ad574 100644 --- a/ext/node/polyfills/02_init.js +++ b/ext/node/polyfills/02_init.js @@ -22,7 +22,7 @@ function initialize(args) { } = args; if (!warmup) { if (initialized) { - throw Error("Node runtime already initialized"); + throw new Error("Node runtime already initialized"); } initialized = true; if (usesLocalNodeModulesDir) { @@ -76,10 +76,14 @@ nodeGlobals.Buffer = nativeModuleExports["buffer"].Buffer; nodeGlobals.clearImmediate = nativeModuleExports["timers"].clearImmediate; nodeGlobals.clearInterval = nativeModuleExports["timers"].clearInterval; nodeGlobals.clearTimeout = nativeModuleExports["timers"].clearTimeout; -nodeGlobals.console = nativeModuleExports["console"]; nodeGlobals.global = globalThis; nodeGlobals.process = nativeModuleExports["process"]; nodeGlobals.setImmediate = nativeModuleExports["timers"].setImmediate; nodeGlobals.setInterval = nativeModuleExports["timers"].setInterval; nodeGlobals.setTimeout = nativeModuleExports["timers"].setTimeout; nodeGlobals.performance = nativeModuleExports["perf_hooks"].performance; + +nativeModuleExports["internal/console/constructor"].bindStreamsLazy( + nativeModuleExports["console"], + nativeModuleExports["process"], +); diff --git a/ext/node/polyfills/_brotli.js b/ext/node/polyfills/_brotli.js index 0dcb58e047..ebd0351561 100644 --- a/ext/node/polyfills/_brotli.js +++ b/ext/node/polyfills/_brotli.js @@ -60,7 +60,7 @@ export class BrotliDecompress extends Transform { #context; // TODO(littledivy): use `options` argument - constructor(_options = {}) { + constructor(_options = { __proto__: null }) { super({ // TODO(littledivy): use `encoding` argument transform(chunk, _encoding, callback) { @@ -91,7 +91,7 @@ export class BrotliDecompress extends Transform { export class BrotliCompress extends Transform { #context; - constructor(options = {}) { + constructor(options = { __proto__: null }) { super({ // TODO(littledivy): use `encoding` argument transform(chunk, _encoding, callback) { diff --git a/ext/node/polyfills/_events.mjs b/ext/node/polyfills/_events.mjs index bb34985940..ce7a8ebf24 100644 --- a/ext/node/polyfills/_events.mjs +++ b/ext/node/polyfills/_events.mjs @@ -46,7 +46,8 @@ import { } from "ext:deno_node/internal/validators.mjs"; import { spliceOne } from "ext:deno_node/_utils.ts"; import { nextTick } from "ext:deno_node/_process/process.ts"; -import { nodeGlobals } from "ext:deno_node/00_globals.js"; + +export { addAbortListener } from "./internal/events/abort_listener.mjs"; const kCapture = Symbol("kCapture"); const kErrorMonitor = Symbol("events.errorMonitor"); @@ -55,6 +56,11 @@ const kMaxEventTargetListenersWarned = Symbol( "events.maxEventTargetListenersWarned", ); +let process; +export function setProcess(p) { + process = p; +} + /** * Creates a new `EventEmitter` instance. * @param {{ captureRejections?: boolean; }} [opts] @@ -469,7 +475,7 @@ function _addListener(target, type, listener, prepend) { w.emitter = target; w.type = type; w.count = existing.length; - nodeGlobals.process.emitWarning(w); + process.emitWarning(w); } } diff --git a/ext/node/polyfills/_fs/_fs_constants.ts b/ext/node/polyfills/_fs/_fs_constants.ts index d44f4917e6..0af75f072c 100644 --- a/ext/node/polyfills/_fs/_fs_constants.ts +++ b/ext/node/polyfills/_fs/_fs_constants.ts @@ -12,6 +12,28 @@ export const { S_IXUSR, S_IRGRP, S_IWGRP, + S_IFBLK, + S_IFCHR, + S_IFDIR, + S_IFIFO, + S_IFLNK, + S_IFMT, + S_IFREG, + S_IFSOCK, + S_IRWXG, + S_IRWXO, + S_IRWXU, + UV_DIRENT_BLOCK, + UV_DIRENT_CHAR, + UV_DIRENT_DIR, + UV_DIRENT_FIFO, + UV_DIRENT_FILE, + UV_DIRENT_LINK, + UV_DIRENT_SOCKET, + UV_DIRENT_UNKNOWN, + UV_FS_O_FILEMAP, + UV_FS_SYMLINK_DIR, + UV_FS_SYMLINK_JUNCTION, S_IXGRP, S_IROTH, S_IWOTH, diff --git a/ext/node/polyfills/_fs/_fs_copy.ts b/ext/node/polyfills/_fs/_fs_copy.ts index 2f8ddf4fcd..0434bff4d1 100644 --- a/ext/node/polyfills/_fs/_fs_copy.ts +++ b/ext/node/polyfills/_fs/_fs_copy.ts @@ -53,8 +53,9 @@ export function copyFile( }, (e) => { if (e instanceof Deno.errors.NotFound) { Deno.copyFile(srcStr, destStr).then(() => cb(null), cb); + } else { + cb(e); } - cb(e); }); } else { Deno.copyFile(srcStr, destStr).then(() => cb(null), cb); @@ -83,8 +84,9 @@ export function copyFileSync( } catch (e) { if (e instanceof Deno.errors.NotFound) { Deno.copyFileSync(srcStr, destStr); + } else { + throw e; } - throw e; } } else { Deno.copyFileSync(srcStr, destStr); diff --git a/ext/node/polyfills/_fs/_fs_read.ts b/ext/node/polyfills/_fs/_fs_read.ts index 90255195fb..df4f5e375d 100644 --- a/ext/node/polyfills/_fs/_fs_read.ts +++ b/ext/node/polyfills/_fs/_fs_read.ts @@ -6,7 +6,6 @@ import { Buffer } from "node:buffer"; import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; import * as io from "ext:deno_io/12_io.js"; -import * as fs from "ext:deno_fs/30_fs.js"; import { ReadOptions } from "ext:deno_node/_fs/_fs_common.ts"; import { arrayBufferViewToUint8Array, @@ -18,6 +17,7 @@ import { validateInteger, } from "ext:deno_node/internal/validators.mjs"; import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts"; +import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops"; type readSyncOptions = { offset: number; @@ -119,15 +119,19 @@ export function read( try { let nread: number | null; if (typeof position === "number" && position >= 0) { - const currentPosition = await fs.seek(fd, 0, io.SeekMode.Current); + const currentPosition = await op_fs_seek_async( + fd, + 0, + io.SeekMode.Current, + ); // We use sync calls below to avoid being affected by others during // these calls. - fs.seekSync(fd, position, io.SeekMode.Start); + op_fs_seek_sync(fd, position, io.SeekMode.Start); nread = io.readSync( fd, arrayBufferViewToUint8Array(buffer).subarray(offset, offset + length), ); - fs.seekSync(fd, currentPosition, io.SeekMode.Start); + op_fs_seek_sync(fd, currentPosition, io.SeekMode.Start); } else { nread = await io.read( fd, @@ -169,7 +173,7 @@ export function readSync( validateBuffer(buffer); if (length == null) { - length = 0; + length = buffer.byteLength; } if (typeof offsetOrOpt === "number") { @@ -191,8 +195,8 @@ export function readSync( let currentPosition = 0; if (typeof position === "number" && position >= 0) { - currentPosition = fs.seekSync(fd, 0, io.SeekMode.Current); - fs.seekSync(fd, position, io.SeekMode.Start); + currentPosition = op_fs_seek_sync(fd, 0, io.SeekMode.Current); + op_fs_seek_sync(fd, position, io.SeekMode.Start); } const numberOfBytesRead = io.readSync( @@ -201,7 +205,7 @@ export function readSync( ); if (typeof position === "number" && position >= 0) { - fs.seekSync(fd, currentPosition, io.SeekMode.Start); + op_fs_seek_sync(fd, currentPosition, io.SeekMode.Start); } return numberOfBytesRead ?? 0; diff --git a/ext/node/polyfills/_fs/_fs_readlink.ts b/ext/node/polyfills/_fs/_fs_readlink.ts index 5f23127982..08bea843fa 100644 --- a/ext/node/polyfills/_fs/_fs_readlink.ts +++ b/ext/node/polyfills/_fs/_fs_readlink.ts @@ -4,13 +4,10 @@ // deno-lint-ignore-file prefer-primordials import { TextEncoder } from "ext:deno_web/08_text_encoding.js"; -import { - intoCallbackAPIWithIntercept, - MaybeEmpty, - notImplemented, -} from "ext:deno_node/_utils.ts"; +import { MaybeEmpty, notImplemented } from "ext:deno_node/_utils.ts"; import { pathFromURL } from "ext:deno_web/00_infra.js"; import { promisify } from "ext:deno_node/internal/util.mjs"; +import { denoErrorToNodeError } from "ext:deno_node/internal/errors.ts"; type ReadlinkCallback = ( err: MaybeEmpty, @@ -69,12 +66,17 @@ export function readlink( const encoding = getEncoding(optOrCallback); - intoCallbackAPIWithIntercept( - Deno.readLink, - (data: string): string | Uint8Array => maybeEncode(data, encoding), - cb, - path, - ); + Deno.readLink(path).then((data: string) => { + const res = maybeEncode(data, encoding); + if (cb) cb(null, res); + }, (err: Error) => { + if (cb) { + (cb as (e: Error) => void)(denoErrorToNodeError(err, { + syscall: "readlink", + path, + })); + } + }); } export const readlinkPromise = promisify(readlink) as ( @@ -88,5 +90,12 @@ export function readlinkSync( ): string | Uint8Array { path = path instanceof URL ? pathFromURL(path) : path; - return maybeEncode(Deno.readLinkSync(path), getEncoding(opt)); + try { + return maybeEncode(Deno.readLinkSync(path), getEncoding(opt)); + } catch (error) { + throw denoErrorToNodeError(error, { + syscall: "readlink", + path, + }); + } } diff --git a/ext/node/polyfills/_fs/_fs_readv.ts b/ext/node/polyfills/_fs/_fs_readv.ts index 7d87c51f78..384f5e319a 100644 --- a/ext/node/polyfills/_fs/_fs_readv.ts +++ b/ext/node/polyfills/_fs/_fs_readv.ts @@ -14,7 +14,7 @@ import { import { maybeCallback } from "ext:deno_node/_fs/_fs_common.ts"; import { validateInteger } from "ext:deno_node/internal/validators.mjs"; import * as io from "ext:deno_io/12_io.js"; -import * as fs from "ext:deno_fs/30_fs.js"; +import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops"; type Callback = ( err: ErrnoException | null, @@ -56,7 +56,7 @@ export function readv( position: number | null, ) => { if (typeof position === "number") { - await fs.seek(fd, position, io.SeekMode.Start); + await op_fs_seek_async(fd, position, io.SeekMode.Start); } let readTotal = 0; @@ -104,7 +104,7 @@ export function readvSync( } if (typeof position === "number") { validateInteger(position, "position", 0); - fs.seekSync(fd, position, io.SeekMode.Start); + op_fs_seek_sync(fd, position, io.SeekMode.Start); } let readTotal = 0; diff --git a/ext/node/polyfills/_fs/_fs_write.mjs b/ext/node/polyfills/_fs/_fs_write.mjs index b4b133222f..254094c9ad 100644 --- a/ext/node/polyfills/_fs/_fs_write.mjs +++ b/ext/node/polyfills/_fs/_fs_write.mjs @@ -10,7 +10,6 @@ import { validateInteger, } from "ext:deno_node/internal/validators.mjs"; import * as io from "ext:deno_io/12_io.js"; -import * as fs from "ext:deno_fs/30_fs.js"; import { arrayBufferViewToUint8Array, getValidatedFd, @@ -19,6 +18,7 @@ import { } from "ext:deno_node/internal/fs/utils.mjs"; import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts"; import { maybeCallback } from "ext:deno_node/_fs/_fs_common.ts"; +import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops"; export function writeSync(fd, buffer, offset, length, position) { fd = getValidatedFd(fd); @@ -26,7 +26,7 @@ export function writeSync(fd, buffer, offset, length, position) { const innerWriteSync = (fd, buffer, offset, length, position) => { buffer = arrayBufferViewToUint8Array(buffer); if (typeof position === "number") { - fs.seekSync(fd, position, io.SeekMode.Start); + op_fs_seek_sync(fd, position, io.SeekMode.Start); } let currentOffset = offset; const end = offset + length; @@ -70,7 +70,7 @@ export function write(fd, buffer, offset, length, position, callback) { const innerWrite = async (fd, buffer, offset, length, position) => { buffer = arrayBufferViewToUint8Array(buffer); if (typeof position === "number") { - await fs.seek(fd, position, io.SeekMode.Start); + await op_fs_seek_async(fd, position, io.SeekMode.Start); } let currentOffset = offset; const end = offset + length; diff --git a/ext/node/polyfills/_fs/_fs_writeFile.ts b/ext/node/polyfills/_fs/_fs_writeFile.ts index f0014c36d2..dd324815b9 100644 --- a/ext/node/polyfills/_fs/_fs_writeFile.ts +++ b/ext/node/polyfills/_fs/_fs_writeFile.ts @@ -23,6 +23,7 @@ import { validateStringAfterArrayBufferView, } from "ext:deno_node/internal/fs/utils.mjs"; import { promisify } from "ext:deno_node/internal/util.mjs"; +import { FileHandle } from "ext:deno_node/internal/fs/handle.ts"; import { FsFile } from "ext:deno_fs/30_fs.js"; interface Writer { @@ -30,7 +31,7 @@ interface Writer { } export function writeFile( - pathOrRid: string | number | URL, + pathOrRid: string | number | URL | FileHandle, data: string | Uint8Array, optOrCallback: Encodings | CallbackWithError | WriteFileOptions | undefined, callback?: CallbackWithError, @@ -45,6 +46,7 @@ export function writeFile( } pathOrRid = pathOrRid instanceof URL ? pathFromURL(pathOrRid) : pathOrRid; + pathOrRid = pathOrRid instanceof FileHandle ? pathOrRid.fd : pathOrRid; const flag: string | undefined = isFileOptions(options) ? options.flag diff --git a/ext/node/polyfills/_fs/_fs_writev.mjs b/ext/node/polyfills/_fs/_fs_writev.mjs index 2f65c570e1..055bce0b24 100644 --- a/ext/node/polyfills/_fs/_fs_writev.mjs +++ b/ext/node/polyfills/_fs/_fs_writev.mjs @@ -9,7 +9,7 @@ import { validateBufferArray } from "ext:deno_node/internal/fs/utils.mjs"; import { getValidatedFd } from "ext:deno_node/internal/fs/utils.mjs"; import { maybeCallback } from "ext:deno_node/_fs/_fs_common.ts"; import * as io from "ext:deno_io/12_io.js"; -import * as fs from "ext:deno_fs/30_fs.js"; +import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops"; export function writev(fd, buffers, position, callback) { const innerWritev = async (fd, buffers, position) => { @@ -23,7 +23,7 @@ export function writev(fd, buffers, position, callback) { } } if (typeof position === "number") { - await fs.seekSync(fd, position, io.SeekMode.Start); + await op_fs_seek_async(fd, position, io.SeekMode.Start); } const buffer = Buffer.concat(chunks); let currentOffset = 0; @@ -64,7 +64,7 @@ export function writevSync(fd, buffers, position) { } } if (typeof position === "number") { - fs.seekSync(fd, position, io.SeekMode.Start); + op_fs_seek_sync(fd, position, io.SeekMode.Start); } const buffer = Buffer.concat(chunks); let currentOffset = 0; diff --git a/ext/node/polyfills/_http_common.ts b/ext/node/polyfills/_http_common.ts index 24dae6f300..8fb7758a55 100644 --- a/ext/node/polyfills/_http_common.ts +++ b/ext/node/polyfills/_http_common.ts @@ -2,8 +2,53 @@ // Copyright Joyent and Node contributors. All rights reserved. MIT license. import { primordials } from "ext:core/mod.js"; -const { RegExpPrototypeTest, SafeRegExp } = primordials; +const { + RegExpPrototypeTest, + SafeRegExp, + Symbol, +} = primordials; + +export const CRLF = "\r\n"; +export const kIncomingMessage = Symbol("IncomingMessage"); const tokenRegExp = new SafeRegExp(/^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/); + +export const methods = [ + "ACL", + "BIND", + "CHECKOUT", + "CONNECT", + "COPY", + "DELETE", + "GET", + "HEAD", + "LINK", + "LOCK", + "M-SEARCH", + "MERGE", + "MKACTIVITY", + "MKCALENDAR", + "MKCOL", + "MOVE", + "NOTIFY", + "OPTIONS", + "PATCH", + "POST", + "PROPFIND", + "PROPPATCH", + "PURGE", + "PUT", + "REBIND", + "REPORT", + "SEARCH", + "SOURCE", + "SUBSCRIBE", + "TRACE", + "UNBIND", + "UNLINK", + "UNLOCK", + "UNSUBSCRIBE", +]; + /** * Verifies that the given val is a valid HTTP token * per the rules defined in RFC 7230 @@ -25,7 +70,21 @@ function checkInvalidHeaderChar(val: string) { } export const chunkExpression = new SafeRegExp(/(?:^|\W)chunked(?:$|\W)/i); +export const continueExpression = new SafeRegExp( + /(?:^|\W)100-continue(?:$|\W)/i, +); + export { checkInvalidHeaderChar as _checkInvalidHeaderChar, checkIsHttpToken as _checkIsHttpToken, }; + +export default { + _checkInvalidHeaderChar: checkInvalidHeaderChar, + _checkIsHttpToken: checkIsHttpToken, + chunkExpression, + CRLF, + continueExpression, + kIncomingMessage, + methods, +}; diff --git a/ext/node/polyfills/_http_outgoing.ts b/ext/node/polyfills/_http_outgoing.ts index 3c253f5a6c..4da6b73e87 100644 --- a/ext/node/polyfills/_http_outgoing.ts +++ b/ext/node/polyfills/_http_outgoing.ts @@ -21,7 +21,7 @@ import { _checkInvalidHeaderChar as checkInvalidHeaderChar, _checkIsHttpToken as checkIsHttpToken, chunkExpression as RE_TE_CHUNKED, -} from "ext:deno_node/_http_common.ts"; +} from "node:_http_common"; import { defaultTriggerAsyncIdScope, symbols, @@ -54,6 +54,8 @@ let debug = debuglog("http", (fn) => { const HIGH_WATER_MARK = getDefaultHighWaterMark(); +export const kUniqueHeaders = Symbol("kUniqueHeaders"); +export const kHighWaterMark = Symbol("kHighWaterMark"); const kCorked = Symbol("corked"); const nop = () => {}; @@ -891,6 +893,8 @@ function _onFinish(outmsg: any) { } export default { + kUniqueHeaders, + kHighWaterMark, validateHeaderName, validateHeaderValue, parseUniqueHeadersOption, diff --git a/ext/node/polyfills/_http_server.ts b/ext/node/polyfills/_http_server.ts new file mode 100644 index 0000000000..c2867de0c6 --- /dev/null +++ b/ext/node/polyfills/_http_server.ts @@ -0,0 +1,136 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +export enum STATUS_CODES { + /** RFC 7231, 6.2.1 */ + Continue = 100, + /** RFC 7231, 6.2.2 */ + SwitchingProtocols = 101, + /** RFC 2518, 10.1 */ + Processing = 102, + /** RFC 8297 **/ + EarlyHints = 103, + + /** RFC 7231, 6.3.1 */ + OK = 200, + /** RFC 7231, 6.3.2 */ + Created = 201, + /** RFC 7231, 6.3.3 */ + Accepted = 202, + /** RFC 7231, 6.3.4 */ + NonAuthoritativeInfo = 203, + /** RFC 7231, 6.3.5 */ + NoContent = 204, + /** RFC 7231, 6.3.6 */ + ResetContent = 205, + /** RFC 7233, 4.1 */ + PartialContent = 206, + /** RFC 4918, 11.1 */ + MultiStatus = 207, + /** RFC 5842, 7.1 */ + AlreadyReported = 208, + /** RFC 3229, 10.4.1 */ + IMUsed = 226, + + /** RFC 7231, 6.4.1 */ + MultipleChoices = 300, + /** RFC 7231, 6.4.2 */ + MovedPermanently = 301, + /** RFC 7231, 6.4.3 */ + Found = 302, + /** RFC 7231, 6.4.4 */ + SeeOther = 303, + /** RFC 7232, 4.1 */ + NotModified = 304, + /** RFC 7231, 6.4.5 */ + UseProxy = 305, + /** RFC 7231, 6.4.7 */ + TemporaryRedirect = 307, + /** RFC 7538, 3 */ + PermanentRedirect = 308, + + /** RFC 7231, 6.5.1 */ + BadRequest = 400, + /** RFC 7235, 3.1 */ + Unauthorized = 401, + /** RFC 7231, 6.5.2 */ + PaymentRequired = 402, + /** RFC 7231, 6.5.3 */ + Forbidden = 403, + /** RFC 7231, 6.5.4 */ + NotFound = 404, + /** RFC 7231, 6.5.5 */ + MethodNotAllowed = 405, + /** RFC 7231, 6.5.6 */ + NotAcceptable = 406, + /** RFC 7235, 3.2 */ + ProxyAuthRequired = 407, + /** RFC 7231, 6.5.7 */ + RequestTimeout = 408, + /** RFC 7231, 6.5.8 */ + Conflict = 409, + /** RFC 7231, 6.5.9 */ + Gone = 410, + /** RFC 7231, 6.5.10 */ + LengthRequired = 411, + /** RFC 7232, 4.2 */ + PreconditionFailed = 412, + /** RFC 7231, 6.5.11 */ + RequestEntityTooLarge = 413, + /** RFC 7231, 6.5.12 */ + RequestURITooLong = 414, + /** RFC 7231, 6.5.13 */ + UnsupportedMediaType = 415, + /** RFC 7233, 4.4 */ + RequestedRangeNotSatisfiable = 416, + /** RFC 7231, 6.5.14 */ + ExpectationFailed = 417, + /** RFC 7168, 2.3.3 */ + Teapot = 418, + /** RFC 7540, 9.1.2 */ + MisdirectedRequest = 421, + /** RFC 4918, 11.2 */ + UnprocessableEntity = 422, + /** RFC 4918, 11.3 */ + Locked = 423, + /** RFC 4918, 11.4 */ + FailedDependency = 424, + /** RFC 8470, 5.2 */ + TooEarly = 425, + /** RFC 7231, 6.5.15 */ + UpgradeRequired = 426, + /** RFC 6585, 3 */ + PreconditionRequired = 428, + /** RFC 6585, 4 */ + TooManyRequests = 429, + /** RFC 6585, 5 */ + RequestHeaderFieldsTooLarge = 431, + /** RFC 7725, 3 */ + UnavailableForLegalReasons = 451, + + /** RFC 7231, 6.6.1 */ + InternalServerError = 500, + /** RFC 7231, 6.6.2 */ + NotImplemented = 501, + /** RFC 7231, 6.6.3 */ + BadGateway = 502, + /** RFC 7231, 6.6.4 */ + ServiceUnavailable = 503, + /** RFC 7231, 6.6.5 */ + GatewayTimeout = 504, + /** RFC 7231, 6.6.6 */ + HTTPVersionNotSupported = 505, + /** RFC 2295, 8.1 */ + VariantAlsoNegotiates = 506, + /** RFC 4918, 11.5 */ + InsufficientStorage = 507, + /** RFC 5842, 7.2 */ + LoopDetected = 508, + /** RFC 2774, 7 */ + NotExtended = 510, + /** RFC 6585, 6 */ + NetworkAuthenticationRequired = 511, +} + +export default { + STATUS_CODES, +}; diff --git a/ext/node/polyfills/_next_tick.ts b/ext/node/polyfills/_next_tick.ts index 5915c750ee..62470c564e 100644 --- a/ext/node/polyfills/_next_tick.ts +++ b/ext/node/polyfills/_next_tick.ts @@ -10,9 +10,15 @@ import { validateFunction } from "ext:deno_node/internal/validators.mjs"; import { _exiting } from "ext:deno_node/_process/exiting.ts"; import { FixedQueue } from "ext:deno_node/internal/fixed_queue.ts"; +const { + getAsyncContext, + setAsyncContext, +} = core; + interface Tock { callback: (...args: Array) => void; args: Array; + snapshot: unknown; } let nextTickEnabled = false; @@ -23,7 +29,7 @@ export function enableNextTick() { const queue = new FixedQueue(); export function processTicksAndRejections() { - let tock; + let tock: Tock; do { // deno-lint-ignore no-cond-assign while (tock = queue.shift()) { @@ -31,9 +37,11 @@ export function processTicksAndRejections() { // const asyncId = tock[async_id_symbol]; // emitBefore(asyncId, tock[trigger_async_id_symbol], tock); + const oldContext = getAsyncContext(); try { - const callback = (tock as Tock).callback; - if ((tock as Tock).args === undefined) { + setAsyncContext(tock.snapshot); + const callback = tock.callback; + if (tock.args === undefined) { callback(); } else { const args = (tock as Tock).args; @@ -58,6 +66,7 @@ export function processTicksAndRejections() { // FIXME(bartlomieju): Deno currently doesn't support async hooks // if (destroyHooksExist()) // emitDestroy(asyncId); + setAsyncContext(oldContext); } // FIXME(bartlomieju): Deno currently doesn't support async hooks @@ -78,8 +87,7 @@ export function runNextTicks() { // runMicrotasks(); // if (!hasTickScheduled() && !hasRejectionToWarn()) // return; - if (!core.hasTickScheduled()) { - core.runMicrotasks(); + if (queue.isEmpty() || !core.hasTickScheduled()) { return true; } @@ -143,6 +151,7 @@ export function nextTick>( // FIXME(bartlomieju): Deno currently doesn't support async hooks // [async_id_symbol]: asyncId, // [trigger_async_id_symbol]: triggerAsyncId, + snapshot: getAsyncContext(), callback, args: args_, }; diff --git a/ext/node/polyfills/_process/process.ts b/ext/node/polyfills/_process/process.ts index 5abde1cf0e..6f69139c98 100644 --- a/ext/node/polyfills/_process/process.ts +++ b/ext/node/polyfills/_process/process.ts @@ -32,7 +32,7 @@ export function arch(): string { } else if (build.arch == "riscv64gc") { return "riscv64"; } else { - throw Error("unreachable"); + throw new Error("unreachable"); } } @@ -53,8 +53,8 @@ function denoEnvGet(name: string) { } catch (e) { if ( ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e) || - // TODO(iuioiua): Use `PermissionDeniedPrototype` when it's available - ObjectPrototypeIsPrototypeOf(Deno.errors.PermissionDenied.prototype, e) + // TODO(iuioiua): Use `NotCapablePrototype` when it's available + ObjectPrototypeIsPrototypeOf(Deno.errors.NotCapable.prototype, e) ) { return undefined; } diff --git a/ext/node/polyfills/_process/streams.mjs b/ext/node/polyfills/_process/streams.mjs index fa24bd1555..3573956c9d 100644 --- a/ext/node/polyfills/_process/streams.mjs +++ b/ext/node/polyfills/_process/streams.mjs @@ -63,24 +63,41 @@ export function createWritableStdioStream(writer, name, warmup = false) { stream.destroySoon = stream.destroy; stream._isStdio = true; stream.once("close", () => writer?.close()); + + // We cannot call `writer?.isTerminal()` eagerly here + let getIsTTY = () => writer?.isTerminal(); + const getColumns = () => + stream._columns || + (writer?.isTerminal() ? Deno.consoleSize?.().columns : undefined); + ObjectDefineProperties(stream, { columns: { + __proto__: null, enumerable: true, configurable: true, - get: () => - writer?.isTerminal() ? Deno.consoleSize?.().columns : undefined, + get: () => getColumns(), + set: (value) => { + stream._columns = value; + }, }, rows: { + __proto__: null, enumerable: true, configurable: true, get: () => writer?.isTerminal() ? Deno.consoleSize?.().rows : undefined, }, isTTY: { + __proto__: null, enumerable: true, configurable: true, - get: () => writer?.isTerminal(), + // Allow users to overwrite it + get: () => getIsTTY(), + set: (value) => { + getIsTTY = () => value; + }, }, getWindowSize: { + __proto__: null, enumerable: true, configurable: true, value: () => @@ -203,6 +220,7 @@ export const initStdin = (warmup = false) => { stdin.on("close", () => io.stdin?.close()); stdin.fd = io.stdin ? io.STDIN_RID : -1; ObjectDefineProperty(stdin, "isTTY", { + __proto__: null, enumerable: true, configurable: true, get() { @@ -216,6 +234,7 @@ export const initStdin = (warmup = false) => { return stdin; }; ObjectDefineProperty(stdin, "isRaw", { + __proto__: null, enumerable: true, configurable: true, get() { diff --git a/ext/node/polyfills/_stream.mjs b/ext/node/polyfills/_stream.mjs index 7a9f3ff93f..02640abcd9 100644 --- a/ext/node/polyfills/_stream.mjs +++ b/ext/node/polyfills/_stream.mjs @@ -3,6 +3,7 @@ // deno-fmt-ignore-file // deno-lint-ignore-file import { nextTick } from "ext:deno_node/_next_tick.ts"; +import { EventEmitter as EE } from "ext:deno_node/_events.mjs"; import { AbortController } from "ext:deno_web/03_abort_signal.js"; import { Blob } from "ext:deno_web/09_file.js"; import { StringDecoder } from "node:string_decoder"; @@ -1723,446 +1724,11 @@ var require_destroy = __commonJS({ }, }); -// node_modules/events/events.js -var require_events = __commonJS({ - "node_modules/events/events.js"(exports, module) { - "use strict"; - var R = typeof Reflect === "object" ? Reflect : null; - var ReflectApply = R && typeof R.apply === "function" - ? R.apply - : function ReflectApply2(target, receiver, args) { - return Function.prototype.apply.call(target, receiver, args); - }; - var ReflectOwnKeys; - if (R && typeof R.ownKeys === "function") { - ReflectOwnKeys = R.ownKeys; - } else if (Object.getOwnPropertySymbols) { - ReflectOwnKeys = function ReflectOwnKeys2(target) { - return Object.getOwnPropertyNames(target).concat( - Object.getOwnPropertySymbols(target), - ); - }; - } else { - ReflectOwnKeys = function ReflectOwnKeys2(target) { - return Object.getOwnPropertyNames(target); - }; - } - function ProcessEmitWarning(warning) { - if (console && console.warn) { - console.warn(warning); - } - } - var NumberIsNaN = Number.isNaN || function NumberIsNaN2(value) { - return value !== value; - }; - function EventEmitter() { - EventEmitter.init.call(this); - } - module.exports = EventEmitter; - module.exports.once = once; - EventEmitter.EventEmitter = EventEmitter; - EventEmitter.prototype._events = void 0; - EventEmitter.prototype._eventsCount = 0; - EventEmitter.prototype._maxListeners = void 0; - var defaultMaxListeners = 10; - function checkListener(listener) { - if (typeof listener !== "function") { - throw new TypeError( - 'The "listener" argument must be of type Function. Received type ' + - typeof listener, - ); - } - } - Object.defineProperty(EventEmitter, "defaultMaxListeners", { - enumerable: true, - get: function () { - return defaultMaxListeners; - }, - set: function (arg) { - if (typeof arg !== "number" || arg < 0 || NumberIsNaN(arg)) { - throw new RangeError( - 'The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + - arg + ".", - ); - } - defaultMaxListeners = arg; - }, - }); - EventEmitter.init = function () { - if ( - this._events === void 0 || - this._events === Object.getPrototypeOf(this)._events - ) { - this._events = /* @__PURE__ */ Object.create(null); - this._eventsCount = 0; - } - this._maxListeners = this._maxListeners || void 0; - }; - EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) { - throw new RangeError( - 'The value of "n" is out of range. It must be a non-negative number. Received ' + - n + ".", - ); - } - this._maxListeners = n; - return this; - }; - function _getMaxListeners(that) { - if (that._maxListeners === void 0) { - return EventEmitter.defaultMaxListeners; - } - return that._maxListeners; - } - EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return _getMaxListeners(this); - }; - EventEmitter.prototype.emit = function emit(type) { - var args = []; - for (var i = 1; i < arguments.length; i++) { - args.push(arguments[i]); - } - var doError = type === "error"; - var events = this._events; - if (events !== void 0) { - doError = doError && events.error === void 0; - } else if (!doError) { - return false; - } - if (doError) { - var er; - if (args.length > 0) { - er = args[0]; - } - if (er instanceof Error) { - throw er; - } - var err = new Error( - "Unhandled error." + (er ? " (" + er.message + ")" : ""), - ); - err.context = er; - throw err; - } - var handler = events[type]; - if (handler === void 0) { - return false; - } - if (typeof handler === "function") { - ReflectApply(handler, this, args); - } else { - var len = handler.length; - var listeners = arrayClone(handler, len); - for (var i = 0; i < len; ++i) { - ReflectApply(listeners[i], this, args); - } - } - return true; - }; - function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - checkListener(listener); - events = target._events; - if (events === void 0) { - events = target._events = /* @__PURE__ */ Object.create(null); - target._eventsCount = 0; - } else { - if (events.newListener !== void 0) { - target.emit( - "newListener", - type, - listener.listener ? listener.listener : listener, - ); - events = target._events; - } - existing = events[type]; - } - if (existing === void 0) { - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === "function") { - existing = events[type] = prepend - ? [listener, existing] - : [existing, listener]; - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - var w = new Error( - "Possible EventEmitter memory leak detected. " + existing.length + - " " + String(type) + - " listeners added. Use emitter.setMaxListeners() to increase limit", - ); - w.name = "MaxListenersExceededWarning"; - w.emitter = target; - w.type = type; - w.count = existing.length; - ProcessEmitWarning(w); - } - } - return target; - } - EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); - }; - EventEmitter.prototype.on = EventEmitter.prototype.addListener; - EventEmitter.prototype.prependListener = function prependListener( - type, - listener, - ) { - return _addListener(this, type, listener, true); - }; - function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) { - return this.listener.call(this.target); - } - return this.listener.apply(this.target, arguments); - } - } - function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: void 0, target, type, listener }; - var wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; - } - EventEmitter.prototype.once = function once2(type, listener) { - checkListener(listener); - this.on(type, _onceWrap(this, type, listener)); - return this; - }; - EventEmitter.prototype.prependOnceListener = function prependOnceListener( - type, - listener, - ) { - checkListener(listener); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - EventEmitter.prototype.removeListener = function removeListener( - type, - listener, - ) { - var list, events, position, i, originalListener; - checkListener(listener); - events = this._events; - if (events === void 0) { - return this; - } - list = events[type]; - if (list === void 0) { - return this; - } - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) { - this._events = /* @__PURE__ */ Object.create(null); - } else { - delete events[type]; - if (events.removeListener) { - this.emit("removeListener", type, list.listener || listener); - } - } - } else if (typeof list !== "function") { - position = -1; - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - if (position < 0) { - return this; - } - if (position === 0) { - list.shift(); - } else { - spliceOne(list, position); - } - if (list.length === 1) { - events[type] = list[0]; - } - if (events.removeListener !== void 0) { - this.emit("removeListener", type, originalListener || listener); - } - } - return this; - }; - EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - EventEmitter.prototype.removeAllListeners = function removeAllListeners( - type, - ) { - var listeners, events, i; - events = this._events; - if (events === void 0) { - return this; - } - if (events.removeListener === void 0) { - if (arguments.length === 0) { - this._events = /* @__PURE__ */ Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== void 0) { - if (--this._eventsCount === 0) { - this._events = /* @__PURE__ */ Object.create(null); - } else { - delete events[type]; - } - } - return this; - } - if (arguments.length === 0) { - var keys = Object.keys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === "removeListener") { - continue; - } - this.removeAllListeners(key); - } - this.removeAllListeners("removeListener"); - this._events = /* @__PURE__ */ Object.create(null); - this._eventsCount = 0; - return this; - } - listeners = events[type]; - if (typeof listeners === "function") { - this.removeListener(type, listeners); - } else if (listeners !== void 0) { - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - return this; - }; - function _listeners(target, type, unwrap) { - var events = target._events; - if (events === void 0) { - return []; - } - var evlistener = events[type]; - if (evlistener === void 0) { - return []; - } - if (typeof evlistener === "function") { - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - } - return unwrap - ? unwrapListeners(evlistener) - : arrayClone(evlistener, evlistener.length); - } - EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); - }; - EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); - }; - EventEmitter.listenerCount = function (emitter, type) { - if (typeof emitter.listenerCount === "function") { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } - }; - EventEmitter.prototype.listenerCount = listenerCount; - function listenerCount(type) { - var events = this._events; - if (events !== void 0) { - var evlistener = events[type]; - if (typeof evlistener === "function") { - return 1; - } else if (evlistener !== void 0) { - return evlistener.length; - } - } - return 0; - } - EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; - }; - function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) { - copy[i] = arr[i]; - } - return copy; - } - function spliceOne(list, index) { - for (; index + 1 < list.length; index++) { - list[index] = list[index + 1]; - } - list.pop(); - } - function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; - } - function once(emitter, name) { - return new Promise(function (resolve, reject) { - function errorListener(err) { - emitter.removeListener(name, resolver); - reject(err); - } - function resolver() { - if (typeof emitter.removeListener === "function") { - emitter.removeListener("error", errorListener); - } - resolve([].slice.call(arguments)); - } - - eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); - if (name !== "error") { - addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); - } - }); - } - function addErrorHandlerIfEventEmitter(emitter, handler, flags) { - if (typeof emitter.on === "function") { - eventTargetAgnosticAddListener(emitter, "error", handler, flags); - } - } - function eventTargetAgnosticAddListener(emitter, name, listener, flags) { - if (typeof emitter.on === "function") { - if (flags.once) { - emitter.once(name, listener); - } else { - emitter.on(name, listener); - } - } else if (typeof emitter.addEventListener === "function") { - emitter.addEventListener(name, function wrapListener(arg) { - if (flags.once) { - emitter.removeEventListener(name, wrapListener); - } - listener(arg); - }); - } else { - throw new TypeError( - 'The "emitter" argument must be of type EventEmitter. Received type ' + - typeof emitter, - ); - } - } - }, -}); - // lib/internal/streams/legacy.js var require_legacy = __commonJS({ "lib/internal/streams/legacy.js"(exports, module) { "use strict"; var { ArrayIsArray, ObjectSetPrototypeOf } = require_primordials(); - var { EventEmitter: EE } = require_events(); function Stream(opts) { EE.call(this, opts); } @@ -2688,7 +2254,6 @@ var require_readable = __commonJS({ } = require_primordials(); module.exports = Readable; Readable.ReadableState = ReadableState; - var { EventEmitter: EE } = require_events(); var { Stream, prependListener } = require_legacy(); var { Buffer: Buffer2 } = require_buffer(); var { addAbortSignal } = require_add_abort_signal(); @@ -3722,7 +3287,6 @@ var require_writable = __commonJS({ } = require_primordials(); module.exports = Writable; Writable.WritableState = WritableState; - var { EventEmitter: EE } = require_events(); var Stream = require_legacy().Stream; var { Buffer: Buffer2 } = require_buffer(); var destroyImpl = require_destroy(); @@ -5713,6 +5277,7 @@ var require_stream = __commonJS({ Stream._uint8ArrayToBuffer = function _uint8ArrayToBuffer(chunk) { return Buffer2.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); }; + Stream._isArrayBufferView = isArrayBufferView; }, }); /* End esm.sh bundle */ @@ -5747,11 +5312,15 @@ export const Duplex = CustomStream.Duplex; export const PassThrough = CustomStream.PassThrough; export const Stream = CustomStream.Stream; export const Transform = CustomStream.Transform; +export const _isArrayBufferView = isArrayBufferView; export const _isUint8Array = CustomStream._isUint8Array; export const _uint8ArrayToBuffer = CustomStream._uint8ArrayToBuffer; export const addAbortSignal = CustomStream.addAbortSignal; export const pipeline = CustomStream.pipeline; -export { finished }; +export const isDisturbed = CustomStream.isDisturbed; +export const isErrored = CustomStream.isErrored; +export const compose = CustomStream.compose; +export { destroy, finished, isDestroyed, isReadable, isWritable }; function isWritableStream(object) { return object instanceof WritableStream; diff --git a/ext/node/polyfills/_tls_wrap.ts b/ext/node/polyfills/_tls_wrap.ts index ed2bdd0a39..e36fc637e7 100644 --- a/ext/node/polyfills/_tls_wrap.ts +++ b/ext/node/polyfills/_tls_wrap.ts @@ -10,7 +10,7 @@ import { } from "ext:deno_node/internal/primordials.mjs"; import assert from "ext:deno_node/internal/assert.mjs"; import * as net from "node:net"; -import { createSecureContext } from "ext:deno_node/_tls_common.ts"; +import { createSecureContext } from "node:_tls_common"; import { kStreamBaseField } from "ext:deno_node/internal_binding/stream_wrap.ts"; import { connResetException } from "ext:deno_node/internal/errors.ts"; import { emitWarning } from "node:process"; @@ -68,6 +68,7 @@ export class TLSSocket extends net.Socket { secureConnecting: boolean; _SNICallback: any; servername: string | null; + alpnProtocol: string | boolean | null; alpnProtocols: string[] | null; authorized: boolean; authorizationError: any; @@ -114,6 +115,7 @@ export class TLSSocket extends net.Socket { this.secureConnecting = true; this._SNICallback = null; this.servername = null; + this.alpnProtocol = null; this.alpnProtocols = tlsOptions.ALPNProtocols; this.authorized = false; this.authorizationError = null; @@ -151,10 +153,21 @@ export class TLSSocket extends net.Socket { handle.afterConnect = async (req: any, status: number) => { try { const conn = await Deno.startTls(handle[kStreamBaseField], options); + try { + const hs = await conn.handshake(); + if (hs.alpnProtocol) { + tlssock.alpnProtocol = hs.alpnProtocol; + } else { + tlssock.alpnProtocol = false; + } + } catch { + // Don't interrupt "secure" event to let the first read/write + // operation emit the error. + } handle[kStreamBaseField] = conn; tlssock.emit("secure"); tlssock.removeListener("end", onConnectEnd); - } catch { + } catch (_) { // TODO(kt3k): Handle this } return afterConnect.call(handle, req, status); @@ -269,6 +282,7 @@ export class ServerImpl extends EventEmitter { // Creates TCP handle and socket directly from Deno.TlsConn. // This works as TLS socket. We don't use TLSSocket class for doing // this because Deno.startTls only supports client side tcp connection. + // TODO(@satyarohith): set TLSSocket.alpnProtocol when we use TLSSocket class. const handle = new TCP(TCPConstants.SOCKET, await listener.accept()); const socket = new net.Socket({ handle }); this.emit("secureConnection", socket); diff --git a/ext/node/polyfills/_util/async.ts b/ext/node/polyfills/_util/async.ts index cc116412c1..0cacccacc7 100644 --- a/ext/node/polyfills/_util/async.ts +++ b/ext/node/polyfills/_util/async.ts @@ -13,7 +13,7 @@ import { clearTimeout, setTimeout } from "ext:deno_web/02_timers.js"; /** Resolve a Promise after a given amount of milliseconds. */ export function delay( ms: number, - options: { signal?: AbortSignal } = {}, + options: { signal?: AbortSignal } = { __proto__: null }, ): Promise { const { signal } = options; if (signal?.aborted) { diff --git a/ext/node/polyfills/_util/std_testing_diff.ts b/ext/node/polyfills/_util/std_testing_diff.ts index 74e396b0c5..5155fd242c 100644 --- a/ext/node/polyfills/_util/std_testing_diff.ts +++ b/ext/node/polyfills/_util/std_testing_diff.ts @@ -325,7 +325,10 @@ export function diffstr(A: string, B: string) { ); } - function tokenize(string: string, { wordDiff = false } = {}): string[] { + function tokenize( + string: string, + { wordDiff = false } = { __proto__: null }, + ): string[] { if (wordDiff) { // Split string on whitespace symbols const tokens = StringPrototypeSplit(string, WHITESPACE_SYMBOL_PATTERN); @@ -450,7 +453,7 @@ export function diffstr(A: string, B: string) { */ function createColor( diffType: DiffType, - { background = false } = {}, + { background = false } = { __proto__: null }, ): (s: string) => string { // TODO(@littledivy): Remove this when we can detect // true color terminals. @@ -484,7 +487,7 @@ function createSign(diffType: DiffType): string { export function buildMessage( diffResult: ReadonlyArray>, - { stringDiff = false } = {}, + { stringDiff = false } = { __proto__: null }, ): string[] { const messages: string[] = [], diffMessages: string[] = []; ArrayPrototypePush(messages, ""); diff --git a/ext/node/polyfills/_utils.ts b/ext/node/polyfills/_utils.ts index 78b9bdddc3..b50c113e14 100644 --- a/ext/node/polyfills/_utils.ts +++ b/ext/node/polyfills/_utils.ts @@ -42,6 +42,7 @@ export function warnNotImplemented(msg?: string) { const message = msg ? `Warning: Not implemented: ${msg}` : "Warning: Not implemented"; + // deno-lint-ignore no-console console.warn(message); } diff --git a/ext/node/polyfills/async_hooks.ts b/ext/node/polyfills/async_hooks.ts index f94b8d2c64..7a2f153dac 100644 --- a/ext/node/polyfills/async_hooks.ts +++ b/ext/node/polyfills/async_hooks.ts @@ -1,191 +1,35 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright Joyent and Node contributors. All rights reserved. MIT license. -// This implementation is inspired by "workerd" AsyncLocalStorage implementation: -// https://github.com/cloudflare/workerd/blob/77fd0ed6ddba184414f0216508fc62b06e716cab/src/workerd/api/node/async-hooks.c++#L9 - // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file prefer-primordials -import { core } from "ext:core/mod.js"; -import { op_node_is_promise_rejected } from "ext:core/ops"; +import { core, primordials } from "ext:core/mod.js"; import { validateFunction } from "ext:deno_node/internal/validators.mjs"; import { newAsyncId } from "ext:deno_node/internal/async_hooks.ts"; -function assert(cond: boolean) { - if (!cond) throw new Error("Assertion failed"); -} -const asyncContextStack: AsyncContextFrame[] = []; +const { + ObjectDefineProperties, + ReflectApply, + FunctionPrototypeBind, + ArrayPrototypeUnshift, + ObjectFreeze, +} = primordials; -function pushAsyncFrame(frame: AsyncContextFrame) { - asyncContextStack.push(frame); -} - -function popAsyncFrame() { - if (asyncContextStack.length > 0) { - asyncContextStack.pop(); - } -} - -let rootAsyncFrame: AsyncContextFrame | undefined = undefined; -let promiseHooksSet = false; - -const asyncContext = Symbol("asyncContext"); - -function setPromiseHooks() { - if (promiseHooksSet) { - return; - } - promiseHooksSet = true; - - const init = (promise: Promise) => { - const currentFrame = AsyncContextFrame.current(); - if (!currentFrame.isRoot()) { - if (typeof promise[asyncContext] !== "undefined") { - throw new Error("Promise already has async context"); - } - AsyncContextFrame.attachContext(promise); - } - }; - const before = (promise: Promise) => { - const maybeFrame = promise[asyncContext]; - if (maybeFrame) { - pushAsyncFrame(maybeFrame); - } else { - pushAsyncFrame(AsyncContextFrame.getRootAsyncContext()); - } - }; - const after = (promise: Promise) => { - popAsyncFrame(); - if (!op_node_is_promise_rejected(promise)) { - // @ts-ignore promise async context - promise[asyncContext] = undefined; - } - }; - const resolve = (promise: Promise) => { - const currentFrame = AsyncContextFrame.current(); - if ( - !currentFrame.isRoot() && op_node_is_promise_rejected(promise) && - typeof promise[asyncContext] === "undefined" - ) { - AsyncContextFrame.attachContext(promise); - } - }; - - core.setPromiseHooks(init, before, after, resolve); -} - -class AsyncContextFrame { - storage: StorageEntry[]; - constructor( - maybeParent?: AsyncContextFrame | null, - maybeStorageEntry?: StorageEntry | null, - isRoot = false, - ) { - this.storage = []; - - setPromiseHooks(); - - const propagate = (parent: AsyncContextFrame) => { - parent.storage = parent.storage.filter((entry) => !entry.key.isDead()); - parent.storage.forEach((entry) => this.storage.push(entry.clone())); - - if (maybeStorageEntry) { - const existingEntry = this.storage.find((entry) => - entry.key === maybeStorageEntry.key - ); - if (existingEntry) { - existingEntry.value = maybeStorageEntry.value; - } else { - this.storage.push(maybeStorageEntry); - } - } - }; - - if (!isRoot) { - if (maybeParent) { - propagate(maybeParent); - } else { - propagate(AsyncContextFrame.current()); - } - } - } - - static tryGetContext(promise: Promise) { - // @ts-ignore promise async context - return promise[asyncContext]; - } - - static attachContext(promise: Promise) { - // @ts-ignore promise async context - promise[asyncContext] = AsyncContextFrame.current(); - } - - static getRootAsyncContext() { - if (typeof rootAsyncFrame !== "undefined") { - return rootAsyncFrame; - } - - rootAsyncFrame = new AsyncContextFrame(null, null, true); - return rootAsyncFrame; - } - - static current() { - if (asyncContextStack.length === 0) { - return AsyncContextFrame.getRootAsyncContext(); - } - - return asyncContextStack[asyncContextStack.length - 1]; - } - - static create( - maybeParent?: AsyncContextFrame | null, - maybeStorageEntry?: StorageEntry | null, - ) { - return new AsyncContextFrame(maybeParent, maybeStorageEntry); - } - - static wrap( - fn: () => unknown, - maybeFrame: AsyncContextFrame | undefined, - // deno-lint-ignore no-explicit-any - thisArg: any, - ) { - // deno-lint-ignore no-explicit-any - return (...args: any) => { - const frame = maybeFrame || AsyncContextFrame.current(); - Scope.enter(frame); - try { - return fn.apply(thisArg, args); - } finally { - Scope.exit(); - } - }; - } - - get(key: StorageKey) { - assert(!key.isDead()); - this.storage = this.storage.filter((entry) => !entry.key.isDead()); - const entry = this.storage.find((entry) => entry.key === key); - if (entry) { - return entry.value; - } - return undefined; - } - - isRoot() { - return AsyncContextFrame.getRootAsyncContext() == this; - } -} +const { + AsyncVariable, + getAsyncContext, + setAsyncContext, +} = core; export class AsyncResource { - frame: AsyncContextFrame; type: string; + #snapshot: unknown; #asyncId: number; constructor(type: string) { this.type = type; - this.frame = AsyncContextFrame.current(); + this.#snapshot = getAsyncContext(); this.#asyncId = newAsyncId(); } @@ -198,35 +42,38 @@ export class AsyncResource { thisArg: unknown, ...args: unknown[] ) { - Scope.enter(this.frame); - + const previousContext = getAsyncContext(); try { - return fn.apply(thisArg, args); + setAsyncContext(this.#snapshot); + return ReflectApply(fn, thisArg, args); } finally { - Scope.exit(); + setAsyncContext(previousContext); } } emitDestroy() {} - bind(fn: (...args: unknown[]) => unknown, thisArg = this) { + bind(fn: (...args: unknown[]) => unknown, thisArg) { validateFunction(fn, "fn"); - const frame = AsyncContextFrame.current(); - const bound = AsyncContextFrame.wrap(fn, frame, thisArg); - - Object.defineProperties(bound, { + let bound; + if (thisArg === undefined) { + // deno-lint-ignore no-this-alias + const resource = this; + bound = function (...args) { + ArrayPrototypeUnshift(args, fn, this); + return ReflectApply(resource.runInAsyncScope, resource, args); + }; + } else { + bound = FunctionPrototypeBind(this.runInAsyncScope, this, fn, thisArg); + } + ObjectDefineProperties(bound, { "length": { + __proto__: null, configurable: true, enumerable: false, value: fn.length, writable: false, }, - "asyncResource": { - configurable: true, - enumerable: true, - value: this, - writable: true, - }, }); return bound; } @@ -236,95 +83,54 @@ export class AsyncResource { type?: string, thisArg?: AsyncResource, ) { - type = type || fn.name; - return (new AsyncResource(type || "AsyncResource")).bind(fn, thisArg); + type = type || fn.name || "bound-anonymous-fn"; + return (new AsyncResource(type)).bind(fn, thisArg); } } -class Scope { - static enter(maybeFrame?: AsyncContextFrame) { - if (maybeFrame) { - pushAsyncFrame(maybeFrame); - } else { - pushAsyncFrame(AsyncContextFrame.getRootAsyncContext()); - } - } - - static exit() { - popAsyncFrame(); - } -} - -class StorageEntry { - key: StorageKey; - value: unknown; - constructor(key: StorageKey, value: unknown) { - this.key = key; - this.value = value; - } - - clone() { - return new StorageEntry(this.key, this.value); - } -} - -class StorageKey { - #dead = false; - - reset() { - this.#dead = true; - } - - isDead() { - return this.#dead; - } -} - -const fnReg = new FinalizationRegistry((key: StorageKey) => { - key.reset(); -}); - export class AsyncLocalStorage { - #key; - - constructor() { - this.#key = new StorageKey(); - fnReg.register(this, this.#key); - } + #variable = new AsyncVariable(); + enabled = false; // deno-lint-ignore no-explicit-any run(store: any, callback: any, ...args: any[]): any { - const frame = AsyncContextFrame.create( - null, - new StorageEntry(this.#key, store), - ); - Scope.enter(frame); - let res; + this.enabled = true; + const previous = this.#variable.enter(store); try { - res = callback(...args); + return ReflectApply(callback, null, args); } finally { - Scope.exit(); + setAsyncContext(previous); } - return res; } // deno-lint-ignore no-explicit-any exit(callback: (...args: unknown[]) => any, ...args: any[]): any { - return this.run(undefined, callback, args); + if (!this.enabled) { + return ReflectApply(callback, null, args); + } + this.enabled = false; + try { + return ReflectApply(callback, null, args); + } finally { + this.enabled = true; + } } // deno-lint-ignore no-explicit-any getStore(): any { - const currentFrame = AsyncContextFrame.current(); - return currentFrame.get(this.#key); + if (!this.enabled) { + return undefined; + } + return this.#variable.get(); } enterWith(store: unknown) { - const frame = AsyncContextFrame.create( - null, - new StorageEntry(this.#key, store), - ); - Scope.enter(frame); + this.enabled = true; + this.#variable.enter(store); + } + + disable() { + this.enabled = false; } static bind(fn: (...args: unknown[]) => unknown) { @@ -335,14 +141,89 @@ export class AsyncLocalStorage { return AsyncLocalStorage.bind(( cb: (...args: unknown[]) => unknown, ...args: unknown[] - ) => cb(...args)); + ) => ReflectApply(cb, null, args)); } } export function executionAsyncId() { - return 1; + return 0; } +export function triggerAsyncId() { + return 0; +} + +export function executionAsyncResource() { + return {}; +} + +export const asyncWrapProviders = ObjectFreeze({ + __proto__: null, + NONE: 0, + DIRHANDLE: 1, + DNSCHANNEL: 2, + ELDHISTOGRAM: 3, + FILEHANDLE: 4, + FILEHANDLECLOSEREQ: 5, + BLOBREADER: 6, + FSEVENTWRAP: 7, + FSREQCALLBACK: 8, + FSREQPROMISE: 9, + GETADDRINFOREQWRAP: 10, + GETNAMEINFOREQWRAP: 11, + HEAPSNAPSHOT: 12, + HTTP2SESSION: 13, + HTTP2STREAM: 14, + HTTP2PING: 15, + HTTP2SETTINGS: 16, + HTTPINCOMINGMESSAGE: 17, + HTTPCLIENTREQUEST: 18, + JSSTREAM: 19, + JSUDPWRAP: 20, + MESSAGEPORT: 21, + PIPECONNECTWRAP: 22, + PIPESERVERWRAP: 23, + PIPEWRAP: 24, + PROCESSWRAP: 25, + PROMISE: 26, + QUERYWRAP: 27, + QUIC_ENDPOINT: 28, + QUIC_LOGSTREAM: 29, + QUIC_PACKET: 30, + QUIC_SESSION: 31, + QUIC_STREAM: 32, + QUIC_UDP: 33, + SHUTDOWNWRAP: 34, + SIGNALWRAP: 35, + STATWATCHER: 36, + STREAMPIPE: 37, + TCPCONNECTWRAP: 38, + TCPSERVERWRAP: 39, + TCPWRAP: 40, + TTYWRAP: 41, + UDPSENDWRAP: 42, + UDPWRAP: 43, + SIGINTWATCHDOG: 44, + WORKER: 45, + WORKERHEAPSNAPSHOT: 46, + WRITEWRAP: 47, + ZLIB: 48, + CHECKPRIMEREQUEST: 49, + PBKDF2REQUEST: 50, + KEYPAIRGENREQUEST: 51, + KEYGENREQUEST: 52, + KEYEXPORTREQUEST: 53, + CIPHERREQUEST: 54, + DERIVEBITSREQUEST: 55, + HASHREQUEST: 56, + RANDOMBYTESREQUEST: 57, + RANDOMPRIMEREQUEST: 58, + SCRYPTREQUEST: 59, + SIGNREQUEST: 60, + TLSWRAP: 61, + VERIFYREQUEST: 62, +}); + class AsyncHook { enable() { } @@ -355,12 +236,12 @@ export function createHook() { return new AsyncHook(); } -// Placing all exports down here because the exported classes won't export -// otherwise. export default { - // Embedder API - AsyncResource, - executionAsyncId, - createHook, AsyncLocalStorage, + createHook, + executionAsyncId, + triggerAsyncId, + executionAsyncResource, + asyncWrapProviders, + AsyncResource, }; diff --git a/ext/node/polyfills/buffer.ts b/ext/node/polyfills/buffer.ts index c5a910cb40..efe3b07a97 100644 --- a/ext/node/polyfills/buffer.ts +++ b/ext/node/polyfills/buffer.ts @@ -7,9 +7,11 @@ export { Buffer, constants, default, + INSPECT_MAX_BYTES, isAscii, isUtf8, kMaxLength, kStringMaxLength, SlowBuffer, + transcode, } from "ext:deno_node/internal/buffer.mjs"; diff --git a/ext/node/polyfills/child_process.ts b/ext/node/polyfills/child_process.ts index bb38b746c1..eda718ff34 100644 --- a/ext/node/polyfills/child_process.ts +++ b/ext/node/polyfills/child_process.ts @@ -10,7 +10,6 @@ import { internals } from "ext:core/mod.js"; import { op_bootstrap_unstable_args, op_node_child_ipc_pipe, - op_npm_process_state, } from "ext:core/ops"; import { @@ -54,6 +53,7 @@ import { convertToValidSignal, kEmptyObject, } from "ext:deno_node/internal/util.mjs"; +import { kNeedsNpmProcessState } from "ext:runtime/40_process.js"; const MAX_BUFFER = 1024 * 1024; @@ -132,6 +132,8 @@ export function fork( rm = 2; } execArgv.splice(index, rm); + } else if (flag.startsWith("--no-warnings")) { + execArgv[index] = "--quiet"; } else { index++; } @@ -145,7 +147,6 @@ export function fork( args = [ "run", ...op_bootstrap_unstable_args(), - "--node-modules-dir", "-A", ...stringifiedV8Flags, ...execArgv, @@ -169,9 +170,8 @@ export function fork( options.execPath = options.execPath || Deno.execPath(); options.shell = false; - Object.assign(options.env ??= {}, { - DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE: op_npm_process_state(), - }); + // deno-lint-ignore no-explicit-any + (options as any)[kNeedsNpmProcessState] = true; return spawn(options.execPath, args, options); } diff --git a/ext/node/polyfills/cluster.ts b/ext/node/polyfills/cluster.ts index 5839c1add3..8abc2fedcd 100644 --- a/ext/node/polyfills/cluster.ts +++ b/ext/node/polyfills/cluster.ts @@ -2,6 +2,7 @@ // Copyright Joyent and Node contributors. All rights reserved. MIT license. import { notImplemented } from "ext:deno_node/_utils.ts"; +import { EventEmitter } from "node:events"; /** A Worker object contains all public information and method about a worker. * In the primary it can be obtained using cluster.workers. In a worker it can @@ -13,20 +14,23 @@ export class Worker { } } /** Calls .disconnect() on each worker in cluster.workers. */ -export function disconnected() { - notImplemented("cluster.disconnected"); +export function disconnect() { + notImplemented("cluster.disconnect"); } /** Spawn a new worker process. */ -export function fork() { +// deno-lint-ignore no-explicit-any +export function fork(_env?: any): Worker { notImplemented("cluster.fork"); } /** True if the process is a primary. This is determined by * the process.env.NODE_UNIQUE_ID. If process.env.NODE_UNIQUE_ID is undefined, * then isPrimary is true. */ -export const isPrimary = undefined; +// TODO(@marvinhagemeister): Replace this with an env check once +// we properly set NODE_UNIQUE_ID +export const isPrimary = true; /** True if the process is not a primary (it is the negation of * cluster.isPrimary). */ -export const isWorker = undefined; +export const isWorker = false; /** Deprecated alias for cluster.isPrimary. details. */ export const isMaster = isPrimary; /** The scheduling policy, either cluster.SCHED_RR for round-robin or @@ -35,35 +39,54 @@ export const isMaster = isPrimary; * .setupPrimary() is called, whichever comes first. */ export const schedulingPolicy = undefined; /** The settings object */ -export const settings = undefined; -/** Deprecated alias for .setupPrimary(). */ -export function setupMaster() { - notImplemented("cluster.setupMaster"); -} +export const settings = {}; /** setupPrimary is used to change the default 'fork' behavior. Once called, * the settings will be present in cluster.settings. */ export function setupPrimary() { notImplemented("cluster.setupPrimary"); } +/** Deprecated alias for .setupPrimary(). */ +export const setupMaster = setupPrimary; /** A reference to the current worker object. Not available in the primary * process. */ export const worker = undefined; /** A hash that stores the active worker objects, keyed by id field. Makes it * easy to loop through all the workers. It is only available in the primary * process. */ -export const workers = undefined; +export const workers = {}; -export default { - Worker, - disconnected, - fork, - isPrimary, - isWorker, - isMaster, - schedulingPolicy, - settings, - setupMaster, - setupPrimary, - worker, - workers, +export const SCHED_NONE = 1; +export const SCHED_RR = 2; + +const cluster = new EventEmitter() as EventEmitter & { + isWorker: boolean; + isMaster: boolean; + isPrimary: boolean; + Worker: Worker; + workers: Record; + settings: Record; + // deno-lint-ignore no-explicit-any + setupPrimary(options?: any): void; + // deno-lint-ignore no-explicit-any + setupMaster(options?: any): void; + // deno-lint-ignore no-explicit-any + fork(env: any): Worker; + // deno-lint-ignore no-explicit-any + disconnect(cb: any): void; + SCHED_NONE: 1; + SCHED_RR: 2; }; +cluster.isWorker = isWorker; +cluster.isMaster = isMaster; +cluster.isPrimary = isPrimary; +cluster.Worker = Worker; +cluster.workers = workers; +cluster.settings = {}; +cluster.setupPrimary = setupPrimary; +cluster.setupMaster = setupMaster; +cluster.fork = fork; +cluster.disconnect = disconnect; +cluster.SCHED_NONE = SCHED_NONE; +cluster.SCHED_RR = SCHED_RR; + +export default cluster; diff --git a/ext/node/polyfills/console.ts b/ext/node/polyfills/console.ts index c72cfb1604..f74c9af165 100644 --- a/ext/node/polyfills/console.ts +++ b/ext/node/polyfills/console.ts @@ -1,15 +1,17 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials - +import { primordials } from "ext:core/mod.js"; import { Console } from "ext:deno_node/internal/console/constructor.mjs"; import { windowOrWorkerGlobalScope } from "ext:runtime/98_global_scope_shared.js"; // Don't rely on global `console` because during bootstrapping, it is pointing // to native `console` object provided by V8. const console = windowOrWorkerGlobalScope.console.value; -export default Object.assign({}, console, { Console }); +const { ObjectAssign } = primordials; + +ObjectAssign(console, { Console }); + +export default console; export { Console }; export const { diff --git a/ext/node/polyfills/constants.ts b/ext/node/polyfills/constants.ts index 691621edc4..e5004039b1 100644 --- a/ext/node/polyfills/constants.ts +++ b/ext/node/polyfills/constants.ts @@ -51,6 +51,28 @@ export const { UV_FS_COPYFILE_EXCL, UV_FS_COPYFILE_FICLONE, UV_FS_COPYFILE_FICLONE_FORCE, + S_IFBLK, + S_IFCHR, + S_IFDIR, + S_IFIFO, + S_IFLNK, + S_IFMT, + S_IFREG, + S_IFSOCK, + S_IRWXG, + S_IRWXO, + S_IRWXU, + UV_DIRENT_BLOCK, + UV_DIRENT_CHAR, + UV_DIRENT_DIR, + UV_DIRENT_FIFO, + UV_DIRENT_FILE, + UV_DIRENT_LINK, + UV_DIRENT_SOCKET, + UV_DIRENT_UNKNOWN, + UV_FS_O_FILEMAP, + UV_FS_SYMLINK_DIR, + UV_FS_SYMLINK_JUNCTION, } = fsConstants; export const { RTLD_DEEPBIND, diff --git a/ext/node/polyfills/domain.ts b/ext/node/polyfills/domain.ts index f9c99f7254..7093779966 100644 --- a/ext/node/polyfills/domain.ts +++ b/ext/node/polyfills/domain.ts @@ -15,9 +15,20 @@ function emitError(e) { this.emit("error", e); } +// TODO(bartlomieju): maybe use this one +// deno-lint-ignore prefer-const +let stack = []; +export const _stack = stack; +export const active = null; + export function create() { return new Domain(); } + +export function createDomain() { + return new Domain(); +} + export class Domain extends EventEmitter { #handler; @@ -85,6 +96,9 @@ export class Domain extends EventEmitter { } } export default { + _stack, create, + active, + createDomain, Domain, }; diff --git a/ext/node/polyfills/events.ts b/ext/node/polyfills/events.ts index 3b73814109..78f3d8768c 100644 --- a/ext/node/polyfills/events.ts +++ b/ext/node/polyfills/events.ts @@ -1,6 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // @deno-types="./_events.d.ts" export { + addAbortListener, captureRejectionSymbol, default, defaultMaxListeners, diff --git a/ext/node/polyfills/http.ts b/ext/node/polyfills/http.ts index 920f3a5b09..e7a860ff1c 100644 --- a/ext/node/polyfills/http.ts +++ b/ext/node/polyfills/http.ts @@ -34,22 +34,24 @@ import { finished, Readable as NodeReadable, Writable as NodeWritable, + WritableOptions as NodeWritableOptions, } from "node:stream"; import { + kUniqueHeaders, OutgoingMessage, parseUniqueHeadersOption, validateHeaderName, validateHeaderValue, -} from "ext:deno_node/_http_outgoing.ts"; +} from "node:_http_outgoing"; import { ok as assert } from "node:assert"; import { kOutHeaders } from "ext:deno_node/internal/http.ts"; -import { _checkIsHttpToken as checkIsHttpToken } from "ext:deno_node/_http_common.ts"; -import { Agent, globalAgent } from "ext:deno_node/_http_agent.mjs"; -// import { chunkExpression as RE_TE_CHUNKED } from "ext:deno_node/_http_common.ts"; +import { _checkIsHttpToken as checkIsHttpToken } from "node:_http_common"; +import { Agent, globalAgent } from "node:_http_agent"; import { urlToHttpOptions } from "ext:deno_node/internal/url.ts"; import { kEmptyObject } from "ext:deno_node/internal/util.mjs"; import { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts"; import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts"; +import { isWindows } from "ext:deno_node/_util/os.ts"; import { connResetException, ERR_HTTP_HEADERS_SENT, @@ -66,178 +68,13 @@ import { headersEntries } from "ext:deno_fetch/20_headers.js"; import { timerId } from "ext:deno_web/03_abort_signal.js"; import { clearTimeout as webClearTimeout } from "ext:deno_web/02_timers.js"; import { resourceForReadableStream } from "ext:deno_web/06_streams.js"; -import { TcpConn } from "ext:deno_net/01_net.js"; +import { UpgradedConn } from "ext:deno_net/01_net.js"; +import { STATUS_CODES } from "node:_http_server"; +import { methods as METHODS } from "node:_http_common"; +import { deprecate } from "node:util"; const { internalRidSymbol } = core; -const { ArrayIsArray } = primordials; - -enum STATUS_CODES { - /** RFC 7231, 6.2.1 */ - Continue = 100, - /** RFC 7231, 6.2.2 */ - SwitchingProtocols = 101, - /** RFC 2518, 10.1 */ - Processing = 102, - /** RFC 8297 **/ - EarlyHints = 103, - - /** RFC 7231, 6.3.1 */ - OK = 200, - /** RFC 7231, 6.3.2 */ - Created = 201, - /** RFC 7231, 6.3.3 */ - Accepted = 202, - /** RFC 7231, 6.3.4 */ - NonAuthoritativeInfo = 203, - /** RFC 7231, 6.3.5 */ - NoContent = 204, - /** RFC 7231, 6.3.6 */ - ResetContent = 205, - /** RFC 7233, 4.1 */ - PartialContent = 206, - /** RFC 4918, 11.1 */ - MultiStatus = 207, - /** RFC 5842, 7.1 */ - AlreadyReported = 208, - /** RFC 3229, 10.4.1 */ - IMUsed = 226, - - /** RFC 7231, 6.4.1 */ - MultipleChoices = 300, - /** RFC 7231, 6.4.2 */ - MovedPermanently = 301, - /** RFC 7231, 6.4.3 */ - Found = 302, - /** RFC 7231, 6.4.4 */ - SeeOther = 303, - /** RFC 7232, 4.1 */ - NotModified = 304, - /** RFC 7231, 6.4.5 */ - UseProxy = 305, - /** RFC 7231, 6.4.7 */ - TemporaryRedirect = 307, - /** RFC 7538, 3 */ - PermanentRedirect = 308, - - /** RFC 7231, 6.5.1 */ - BadRequest = 400, - /** RFC 7235, 3.1 */ - Unauthorized = 401, - /** RFC 7231, 6.5.2 */ - PaymentRequired = 402, - /** RFC 7231, 6.5.3 */ - Forbidden = 403, - /** RFC 7231, 6.5.4 */ - NotFound = 404, - /** RFC 7231, 6.5.5 */ - MethodNotAllowed = 405, - /** RFC 7231, 6.5.6 */ - NotAcceptable = 406, - /** RFC 7235, 3.2 */ - ProxyAuthRequired = 407, - /** RFC 7231, 6.5.7 */ - RequestTimeout = 408, - /** RFC 7231, 6.5.8 */ - Conflict = 409, - /** RFC 7231, 6.5.9 */ - Gone = 410, - /** RFC 7231, 6.5.10 */ - LengthRequired = 411, - /** RFC 7232, 4.2 */ - PreconditionFailed = 412, - /** RFC 7231, 6.5.11 */ - RequestEntityTooLarge = 413, - /** RFC 7231, 6.5.12 */ - RequestURITooLong = 414, - /** RFC 7231, 6.5.13 */ - UnsupportedMediaType = 415, - /** RFC 7233, 4.4 */ - RequestedRangeNotSatisfiable = 416, - /** RFC 7231, 6.5.14 */ - ExpectationFailed = 417, - /** RFC 7168, 2.3.3 */ - Teapot = 418, - /** RFC 7540, 9.1.2 */ - MisdirectedRequest = 421, - /** RFC 4918, 11.2 */ - UnprocessableEntity = 422, - /** RFC 4918, 11.3 */ - Locked = 423, - /** RFC 4918, 11.4 */ - FailedDependency = 424, - /** RFC 8470, 5.2 */ - TooEarly = 425, - /** RFC 7231, 6.5.15 */ - UpgradeRequired = 426, - /** RFC 6585, 3 */ - PreconditionRequired = 428, - /** RFC 6585, 4 */ - TooManyRequests = 429, - /** RFC 6585, 5 */ - RequestHeaderFieldsTooLarge = 431, - /** RFC 7725, 3 */ - UnavailableForLegalReasons = 451, - - /** RFC 7231, 6.6.1 */ - InternalServerError = 500, - /** RFC 7231, 6.6.2 */ - NotImplemented = 501, - /** RFC 7231, 6.6.3 */ - BadGateway = 502, - /** RFC 7231, 6.6.4 */ - ServiceUnavailable = 503, - /** RFC 7231, 6.6.5 */ - GatewayTimeout = 504, - /** RFC 7231, 6.6.6 */ - HTTPVersionNotSupported = 505, - /** RFC 2295, 8.1 */ - VariantAlsoNegotiates = 506, - /** RFC 4918, 11.5 */ - InsufficientStorage = 507, - /** RFC 5842, 7.2 */ - LoopDetected = 508, - /** RFC 2774, 7 */ - NotExtended = 510, - /** RFC 6585, 6 */ - NetworkAuthenticationRequired = 511, -} - -const METHODS = [ - "ACL", - "BIND", - "CHECKOUT", - "CONNECT", - "COPY", - "DELETE", - "GET", - "HEAD", - "LINK", - "LOCK", - "M-SEARCH", - "MERGE", - "MKACTIVITY", - "MKCALENDAR", - "MKCOL", - "MOVE", - "NOTIFY", - "OPTIONS", - "PATCH", - "POST", - "PROPFIND", - "PROPPATCH", - "PURGE", - "PUT", - "REBIND", - "REPORT", - "SEARCH", - "SOURCE", - "SUBSCRIBE", - "TRACE", - "UNBIND", - "UNLINK", - "UNLOCK", - "UNSUBSCRIBE", -]; +const { ArrayIsArray, StringPrototypeToLowerCase } = primordials; type Chunk = string | Buffer | Uint8Array; @@ -283,8 +120,6 @@ function validateHost(host, name) { const INVALID_PATH_REGEX = /[^\u0021-\u00ff]/; const kError = Symbol("kError"); -const kUniqueHeaders = Symbol("kUniqueHeaders"); - class FakeSocket extends EventEmitter { constructor( opts: { @@ -684,7 +519,7 @@ class ClientRequest extends OutgoingMessage { ); assert(typeof res.remoteAddrIp !== "undefined"); assert(typeof res.remoteAddrIp !== "undefined"); - const conn = new TcpConn( + const conn = new UpgradedConn( upgradeRid, { transport: "tcp", @@ -906,7 +741,7 @@ class ClientRequest extends OutgoingMessage { // https://www.rfc-editor.org/rfc/rfc6266#section-4.3 // Refs: https://github.com/nodejs/node/pull/46528 if (isContentDispositionField(key) && this._contentLength) { - value = Buffer.from(value, "latin1"); + value = Buffer.from(value).toString("latin1"); } if (Array.isArray(value)) { @@ -1351,49 +1186,95 @@ function onError(self, error, cb) { } } -export class ServerResponse extends NodeWritable { - statusCode = 200; - statusMessage?: string = undefined; - #headers: Record = { __proto__: null }; - #hasNonStringHeaders: boolean = false; - #readable: ReadableStream; - override writable = true; - // used by `npm:on-finished` - finished = false; - headersSent = false; - #resolve: (value: Response | PromiseLike) => void; +export type ServerResponse = { + statusCode: number; + statusMessage?: string; + + _headers: Record; + _hasNonStringHeaders: boolean; + + _readable: ReadableStream; + finished: boolean; + headersSent: boolean; + _resolve: (value: Response | PromiseLike) => void; // deno-lint-ignore no-explicit-any - #socketOverride: any | null = null; + _socketOverride: any | null; + // deno-lint-ignore no-explicit-any + socket: any | null; - static #enqueue(controller: ReadableStreamDefaultController, chunk: Chunk) { - try { - if (typeof chunk === "string") { - controller.enqueue(ENCODER.encode(chunk)); - } else { - controller.enqueue(chunk); - } - } catch (_) { - // The stream might have been closed. Ignore the error. - } - } + setHeader(name: string, value: string | string[]): void; + appendHeader(name: string, value: string | string[]): void; + getHeader(name: string): string | string[]; + removeHeader(name: string): void; + getHeaderNames(): string[]; + getHeaders(): Record; + hasHeader(name: string): boolean; - /** Returns true if the response body should be null with the given - * http status code */ - static #bodyShouldBeNull(status: number) { - return status === 101 || status === 204 || status === 205 || status === 304; - } + writeHead( + status: number, + statusMessage?: string, + headers?: + | Record + | Array<[string, string]>, + ): void; + writeHead( + status: number, + headers?: + | Record + | Array<[string, string]>, + ): void; - constructor( + _ensureHeaders(singleChunk?: Chunk): void; + + respond(final: boolean, singleChunk?: Chunk): void; + // deno-lint-ignore no-explicit-any + end(chunk?: any, encoding?: any, cb?: any): void; + + flushHeaders(): void; + _implicitHeader(): void; + + // Undocumented field used by `npm:light-my-request`. + _header: string; + + assignSocket(socket): void; + detachSocket(socket): void; +} & { -readonly [K in keyof NodeWritable]: NodeWritable[K] }; + +type ServerResponseStatic = { + new ( resolve: (value: Response | PromiseLike) => void, socket: FakeSocket, - ) { - let controller: ReadableByteStreamController; - const readable = new ReadableStream({ - start(c) { - controller = c as ReadableByteStreamController; - }, - }); - super({ + ): ServerResponse; + _enqueue(controller: ReadableStreamDefaultController, chunk: Chunk): void; + _bodyShouldBeNull(statusCode: number): boolean; +}; + +export const ServerResponse = function ( + this: ServerResponse, + resolve: (value: Response | PromiseLike) => void, + socket: FakeSocket, +) { + this.statusCode = 200; + this.statusMessage = undefined; + this._headers = { __proto__: null }; + this._hasNonStringHeaders = false; + this.writable = true; + + // used by `npm:on-finished` + this.finished = false; + this.headersSent = false; + this._socketOverride = null; + + let controller: ReadableByteStreamController; + const readable = new ReadableStream({ + start(c) { + controller = c as ReadableByteStreamController; + }, + }); + + NodeWritable.call( + this, + { autoDestroy: true, defaultEncoding: "utf-8", emitClose: true, @@ -1402,16 +1283,16 @@ export class ServerResponse extends NodeWritable { write: (chunk, encoding, cb) => { // Writes chunks are directly written to the socket if // one is assigned via assignSocket() - if (this.#socketOverride && this.#socketOverride.writable) { - this.#socketOverride.write(chunk, encoding); + if (this._socketOverride && this._socketOverride.writable) { + this._socketOverride.write(chunk, encoding); return cb(); } if (!this.headersSent) { - ServerResponse.#enqueue(controller, chunk); + ServerResponse._enqueue(controller, chunk); this.respond(false); return cb(); } - ServerResponse.#enqueue(controller, chunk); + ServerResponse._enqueue(controller, chunk); return cb(); }, final: (cb) => { @@ -1427,192 +1308,269 @@ export class ServerResponse extends NodeWritable { } return cb(null); }, - }); - this.#readable = readable; - this.#resolve = resolve; - this.socket = socket; - } + } satisfies NodeWritableOptions, + ); - setHeader(name: string, value: string | string[]) { - if (Array.isArray(value)) { - this.#hasNonStringHeaders = true; - } - this.#headers[name] = value; - return this; - } + this._readable = readable; + this._resolve = resolve; + this.socket = socket; - appendHeader(name: string, value: string | string[]) { - if (this.#headers[name] === undefined) { - if (Array.isArray(value)) this.#hasNonStringHeaders = true; - this.#headers[name] = value; + this._header = ""; +} as unknown as ServerResponseStatic; + +Object.setPrototypeOf(ServerResponse.prototype, NodeWritable.prototype); +Object.setPrototypeOf(ServerResponse, NodeWritable); + +ServerResponse._enqueue = function ( + this: ServerResponse, + controller: ReadableStreamDefaultController, + chunk: Chunk, +) { + try { + if (typeof chunk === "string") { + controller.enqueue(ENCODER.encode(chunk)); } else { - this.#hasNonStringHeaders = true; - if (!Array.isArray(this.#headers[name])) { - this.#headers[name] = [this.#headers[name]]; + controller.enqueue(chunk); + } + } catch (_) { + // The stream might have been closed. Ignore the error. + } +}; + +/** Returns true if the response body should be null with the given + * http status code */ +ServerResponse._bodyShouldBeNull = function ( + this: ServerResponse, + status: number, +) { + return status === 101 || status === 204 || status === 205 || status === 304; +}; + +ServerResponse.prototype.setHeader = function ( + this: ServerResponse, + name: string, + value: string | string[], +) { + if (Array.isArray(value)) { + this._hasNonStringHeaders = true; + } + this._headers[StringPrototypeToLowerCase(name)] = value; + return this; +}; + +ServerResponse.prototype.appendHeader = function ( + this: ServerResponse, + name: string, + value: string | string[], +) { + const key = StringPrototypeToLowerCase(name); + if (this._headers[key] === undefined) { + if (Array.isArray(value)) this._hasNonStringHeaders = true; + this._headers[key] = value; + } else { + this._hasNonStringHeaders = true; + if (!Array.isArray(this._headers[key])) { + this._headers[key] = [this._headers[key]]; + } + const header = this._headers[key]; + if (Array.isArray(value)) { + header.push(...value); + } else { + header.push(value); + } + } + return this; +}; + +ServerResponse.prototype.getHeader = function ( + this: ServerResponse, + name: string, +) { + return this._headers[StringPrototypeToLowerCase(name)]; +}; + +ServerResponse.prototype.removeHeader = function ( + this: ServerResponse, + name: string, +) { + delete this._headers[StringPrototypeToLowerCase(name)]; +}; + +ServerResponse.prototype.getHeaderNames = function (this: ServerResponse) { + return Object.keys(this._headers); +}; + +ServerResponse.prototype.getHeaders = function ( + this: ServerResponse, +): Record { + return { __proto__: null, ...this._headers }; +}; + +ServerResponse.prototype.hasHeader = function ( + this: ServerResponse, + name: string, +) { + return Object.hasOwn(this._headers, name); +}; + +ServerResponse.prototype.writeHead = function ( + this: ServerResponse, + status: number, + statusMessageOrHeaders?: + | string + | Record + | Array<[string, string]>, + maybeHeaders?: + | Record + | Array<[string, string]>, +) { + this.statusCode = status; + + let headers = null; + if (typeof statusMessageOrHeaders === "string") { + this.statusMessage = statusMessageOrHeaders; + if (maybeHeaders !== undefined) { + headers = maybeHeaders; + } + } else if (statusMessageOrHeaders !== undefined) { + headers = statusMessageOrHeaders; + } + + if (headers !== null) { + if (ArrayIsArray(headers)) { + headers = headers as Array<[string, string]>; + for (let i = 0; i < headers.length; i++) { + this.appendHeader(headers[i][0], headers[i][1]); } - const header = this.#headers[name]; - if (Array.isArray(value)) { - header.push(...value); - } else { - header.push(value); + } else { + headers = headers as Record; + for (const k in headers) { + if (Object.hasOwn(headers, k)) { + this.setHeader(k, headers[k]); + } } } - return this; } - getHeader(name: string) { - return this.#headers[name]; - } - removeHeader(name: string) { - delete this.#headers[name]; - } - getHeaderNames() { - return Object.keys(this.#headers); - } - getHeaders(): Record { - // @ts-ignore Ignore null __proto__ - return { __proto__: null, ...this.#headers }; - } - hasHeader(name: string) { - return Object.hasOwn(this.#headers, name); - } + return this; +}; - writeHead( - status: number, - statusMessage?: string, - headers?: - | Record - | Array<[string, string]>, - ): this; - writeHead( - status: number, - headers?: - | Record - | Array<[string, string]>, - ): this; - writeHead( - status: number, - statusMessageOrHeaders?: - | string - | Record - | Array<[string, string]>, - maybeHeaders?: - | Record - | Array<[string, string]>, - ): this { - this.statusCode = status; +ServerResponse.prototype._ensureHeaders = function ( + this: ServerResponse, + singleChunk?: Chunk, +) { + if (this.statusCode === 200 && this.statusMessage === undefined) { + this.statusMessage = "OK"; + } + if (typeof singleChunk === "string" && !this.hasHeader("content-type")) { + this.setHeader("content-type", "text/plain;charset=UTF-8"); + } +}; - let headers = null; - if (typeof statusMessageOrHeaders === "string") { - this.statusMessage = statusMessageOrHeaders; - if (maybeHeaders !== undefined) { - headers = maybeHeaders; - } - } else if (statusMessageOrHeaders !== undefined) { - headers = statusMessageOrHeaders; - } - - if (headers !== null) { - if (ArrayIsArray(headers)) { - headers = headers as Array<[string, string]>; - for (let i = 0; i < headers.length; i++) { - this.appendHeader(headers[i][0], headers[i][1]); +ServerResponse.prototype.respond = function ( + this: ServerResponse, + final: boolean, + singleChunk?: Chunk, +) { + this.headersSent = true; + this._ensureHeaders(singleChunk); + let body = singleChunk ?? (final ? null : this._readable); + if (ServerResponse._bodyShouldBeNull(this.statusCode)) { + body = null; + } + let headers: Record | [string, string][] = this + ._headers as Record; + if (this._hasNonStringHeaders) { + headers = []; + // Guard is not needed as this is a null prototype object. + // deno-lint-ignore guard-for-in + for (const key in this._headers) { + const entry = this._headers[key]; + if (Array.isArray(entry)) { + for (const value of entry) { + headers.push([key, value]); } } else { - headers = headers as Record; - for (const k in headers) { - if (Object.hasOwn(headers, k)) { - this.setHeader(k, headers[k]); - } - } + headers.push([key, entry]); } } - - return this; - } - - #ensureHeaders(singleChunk?: Chunk) { - if (this.statusCode === 200 && this.statusMessage === undefined) { - this.statusMessage = "OK"; - } - if ( - typeof singleChunk === "string" && - !this.hasHeader("content-type") - ) { - this.setHeader("content-type", "text/plain;charset=UTF-8"); - } - } - - respond(final: boolean, singleChunk?: Chunk) { - this.headersSent = true; - this.#ensureHeaders(singleChunk); - let body = singleChunk ?? (final ? null : this.#readable); - if (ServerResponse.#bodyShouldBeNull(this.statusCode)) { - body = null; - } - let headers: Record | [string, string][] = this - .#headers as Record; - if (this.#hasNonStringHeaders) { - headers = []; - // Guard is not needed as this is a null prototype object. - // deno-lint-ignore guard-for-in - for (const key in this.#headers) { - const entry = this.#headers[key]; - if (Array.isArray(entry)) { - for (const value of entry) { - headers.push([key, value]); - } - } else { - headers.push([key, entry]); - } - } - } - this.#resolve( - new Response(body, { - headers, - status: this.statusCode, - statusText: this.statusMessage, - }), - ); } + this._resolve( + new Response(body, { + headers, + status: this.statusCode, + statusText: this.statusMessage, + }), + ); +}; +ServerResponse.prototype.end = function ( + this: ServerResponse, // deno-lint-ignore no-explicit-any - override end(chunk?: any, encoding?: any, cb?: any): this { - this.finished = true; - if (!chunk && "transfer-encoding" in this.#headers) { - // FIXME(bnoordhuis) Node sends a zero length chunked body instead, i.e., - // the trailing "0\r\n", but respondWith() just hangs when I try that. - this.#headers["content-length"] = "0"; - delete this.#headers["transfer-encoding"]; - } - - // @ts-expect-error The signature for cb is stricter than the one implemented here - return super.end(chunk, encoding, cb); + chunk?: any, + // deno-lint-ignore no-explicit-any + encoding?: any, + // deno-lint-ignore no-explicit-any + cb?: any, +) { + this.finished = true; + if (!chunk && "transfer-encoding" in this._headers) { + // FIXME(bnoordhuis) Node sends a zero length chunked body instead, i.e., + // the trailing "0\r\n", but respondWith() just hangs when I try that. + this._headers["content-length"] = "0"; + delete this._headers["transfer-encoding"]; } - flushHeaders() { - // no-op - } + // @ts-expect-error The signature for cb is stricter than the one implemented here + NodeWritable.prototype.end.call(this, chunk, encoding, cb); +}; - // Undocumented API used by `npm:compression`. - _implicitHeader() { - this.writeHead(this.statusCode); - } +ServerResponse.prototype.flushHeaders = function (this: ServerResponse) { + // no-op +}; - assignSocket(socket) { - if (socket._httpMessage) { - throw new ERR_HTTP_SOCKET_ASSIGNED(); - } - socket._httpMessage = this; - this.#socketOverride = socket; - } +// Undocumented API used by `npm:compression`. +ServerResponse.prototype._implicitHeader = function (this: ServerResponse) { + this.writeHead(this.statusCode); +}; - detachSocket(socket) { - assert(socket._httpMessage === this); - socket._httpMessage = null; - this.#socketOverride = null; +ServerResponse.prototype.assignSocket = function ( + this: ServerResponse, + socket, +) { + if (socket._httpMessage) { + throw new ERR_HTTP_SOCKET_ASSIGNED(); } -} + socket._httpMessage = this; + this._socketOverride = socket; +}; + +ServerResponse.prototype.detachSocket = function ( + this: ServerResponse, + socket, +) { + assert(socket._httpMessage === this); + socket._httpMessage = null; + this._socketOverride = null; +}; + +Object.defineProperty(ServerResponse.prototype, "connection", { + get: deprecate( + function (this: ServerResponse) { + return this._socketOverride; + }, + "ServerResponse.prototype.connection is deprecated", + "DEP0066", + ), + set: deprecate( + // deno-lint-ignore no-explicit-any + function (this: ServerResponse, socket: any) { + this._socketOverride = socket; + }, + "ServerResponse.prototype.connection is deprecated", + "DEP0066", + ), +}); // TODO(@AaronO): optimize export class IncomingMessageForServer extends NodeReadable { @@ -1754,9 +1712,8 @@ export class ServerImpl extends EventEmitter { port = options.port | 0; } - // TODO(bnoordhuis) Node prefers [::] when host is omitted, - // we on the other hand default to 0.0.0.0. - let hostname = options.host ?? "0.0.0.0"; + // Use 0.0.0.0 for Windows, and [::] for other platforms. + let hostname = options.host ?? (isWindows ? "0.0.0.0" : "[::]"); if (hostname == "localhost") { hostname = "127.0.0.1"; } @@ -1836,6 +1793,7 @@ export class ServerImpl extends EventEmitter { } setTimeout() { + // deno-lint-ignore no-console console.error("Not implemented: Server.setTimeout()"); } diff --git a/ext/node/polyfills/http2.ts b/ext/node/polyfills/http2.ts index baa2c6e219..dc2379aebb 100644 --- a/ext/node/polyfills/http2.ts +++ b/ext/node/polyfills/http2.ts @@ -67,7 +67,7 @@ import { ERR_SOCKET_CLOSED, ERR_STREAM_WRITE_AFTER_END, } from "ext:deno_node/internal/errors.ts"; -import { _checkIsHttpToken } from "ext:deno_node/_http_common.ts"; +import { _checkIsHttpToken } from "node:_http_common"; const { StringPrototypeTrim, FunctionPrototypeBind, @@ -127,6 +127,7 @@ type Http2Headers = Record; const debugHttp2Enabled = false; function debugHttp2(...args) { if (debugHttp2Enabled) { + // deno-lint-ignore no-console console.log(...args); } } @@ -512,6 +513,7 @@ export class ClientHttp2Session extends Http2Session { this.emit("error", e); } })(); + this[kState].flags |= SESSION_FLAGS_READY; this.emit("connect", this, {}); })(); } @@ -838,6 +840,11 @@ async function clientHttp2Request( reqHeaders, ); + if (session.closed || session.destroyed) { + debugHttp2(">>> session closed during request promise"); + throw new ERR_HTTP2_STREAM_CANCEL(); + } + return await op_http2_client_request( session[kDenoClientRid], pseudoHeaders, @@ -875,6 +882,7 @@ export class ClientHttp2Stream extends Duplex { trailersReady: false, endAfterHeaders: false, shutdownWritableCalled: false, + serverEndedCall: false, }; this[kDenoResponse] = undefined; this[kDenoRid] = undefined; @@ -898,6 +906,12 @@ export class ClientHttp2Stream extends Duplex { session[kDenoClientRid], this.#rid, ); + + if (session.closed || session.destroyed) { + debugHttp2(">>> session closed during response promise"); + throw new ERR_HTTP2_STREAM_CANCEL(); + } + const [response, endStream] = await op_http2_client_get_response( this.#rid, ); @@ -916,7 +930,12 @@ export class ClientHttp2Stream extends Duplex { ); this[kDenoResponse] = response; this.emit("ready"); - })(); + })().catch((e) => { + if (!(e instanceof ERR_HTTP2_STREAM_CANCEL)) { + debugHttp2(">>> request/response promise error", e); + } + this.destroy(e); + }); } [kUpdateTimer]() { @@ -1091,7 +1110,9 @@ export class ClientHttp2Stream extends Duplex { } debugHttp2(">>> chunk", chunk, finished, this[kDenoResponse].bodyRid); - if (chunk === null) { + if (finished || chunk === null) { + this[kState].serverEndedCall = true; + const trailerList = await op_http2_client_get_response_trailers( this[kDenoResponse].bodyRid, ); @@ -1219,7 +1240,9 @@ export class ClientHttp2Stream extends Duplex { this[kSession] = undefined; session[kMaybeDestroy](); - callback(err); + if (callback) { + callback(err); + } } [kMaybeDestroy](code = constants.NGHTTP2_NO_ERROR) { @@ -1262,6 +1285,9 @@ function shutdownWritable(stream, callback, streamRid) { if (state.flags & STREAM_FLAGS_HAS_TRAILERS) { onStreamTrailers(stream); callback(); + } else if (state.serverEndedCall) { + debugHttp2(">>> stream finished"); + callback(); } else { op_http2_client_send_data(streamRid, new Uint8Array(), true) .then(() => { @@ -1636,16 +1662,19 @@ export class Http2Server extends Server { this.emit("stream", stream, headers); return await stream._deferred.promise; } catch (e) { + // deno-lint-ignore no-console console.log(">>> Error in serveHttpOnConnection", e); } return new Response(""); }, () => { + // deno-lint-ignore no-console console.log(">>> error"); }, () => {}, ); } catch (e) { + // deno-lint-ignore no-console console.log(">>> Error in Http2Server", e); } }, @@ -2274,7 +2303,7 @@ function onStreamTimeout(kind) { }; } -class Http2ServerRequest extends Readable { +export class Http2ServerRequest extends Readable { readableEnded = false; constructor(stream, headers, options, rawHeaders) { @@ -2502,7 +2531,7 @@ function isConnectionHeaderAllowed(name, value) { value === "trailers"; } -class Http2ServerResponse extends Stream { +export class Http2ServerResponse extends Stream { writable = false; req = null; diff --git a/ext/node/polyfills/https.ts b/ext/node/polyfills/https.ts index c1f1237b1a..dd24cf048c 100644 --- a/ext/node/polyfills/https.ts +++ b/ext/node/polyfills/https.ts @@ -1,9 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright Joyent and Node contributors. All rights reserved. MIT license. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials - import { notImplemented } from "ext:deno_node/_utils.ts"; import { urlToHttpOptions } from "ext:deno_node/internal/url.ts"; import { @@ -11,12 +8,20 @@ import { IncomingMessageForClient as IncomingMessage, type RequestOptions, } from "node:http"; -import { Agent as HttpAgent } from "ext:deno_node/_http_agent.mjs"; +import { Agent as HttpAgent } from "node:_http_agent"; import { createHttpClient } from "ext:deno_fetch/22_http_client.js"; import { type ServerHandler, ServerImpl as HttpServer } from "node:http"; import { validateObject } from "ext:deno_node/internal/validators.mjs"; import { kEmptyObject } from "ext:deno_node/internal/util.mjs"; import { Buffer } from "node:buffer"; +import { primordials } from "ext:core/mod.js"; +const { + ArrayPrototypeShift, + ArrayPrototypeUnshift, + ArrayIsArray, + ObjectPrototypeIsPrototypeOf, + ObjectAssign, +} = primordials; export class Server extends HttpServer { constructor(opts, requestListener?: ServerHandler) { @@ -29,11 +34,11 @@ export class Server extends HttpServer { validateObject(opts, "options"); } - if (opts.cert && Array.isArray(opts.cert)) { + if (opts.cert && ArrayIsArray(opts.cert)) { notImplemented("https.Server.opts.cert array type"); } - if (opts.key && Array.isArray(opts.key)) { + if (opts.key && ArrayIsArray(opts.key)) { notImplemented("https.Server.opts.key array type"); } @@ -42,10 +47,12 @@ export class Server extends HttpServer { _additionalServeOptions() { return { - cert: this._opts.cert instanceof Buffer + cert: ObjectPrototypeIsPrototypeOf(Buffer, this._opts.cert) + // deno-lint-ignore prefer-primordials ? this._opts.cert.toString() : this._opts.cert, - key: this._opts.key instanceof Buffer + key: ObjectPrototypeIsPrototypeOf(Buffer, this._opts.key) + // deno-lint-ignore prefer-primordials ? this._opts.key.toString() : this._opts.key, }; @@ -159,18 +166,18 @@ export function request(...args: any[]) { let options = {}; if (typeof args[0] === "string") { - const urlStr = args.shift(); + const urlStr = ArrayPrototypeShift(args); options = urlToHttpOptions(new URL(urlStr)); - } else if (args[0] instanceof URL) { - options = urlToHttpOptions(args.shift()); + } else if (ObjectPrototypeIsPrototypeOf(URL, args[0])) { + options = urlToHttpOptions(ArrayPrototypeShift(args)); } if (args[0] && typeof args[0] !== "function") { - Object.assign(options, args.shift()); + ObjectAssign(options, ArrayPrototypeShift(args)); } options._defaultAgent = globalAgent; - args.unshift(options); + ArrayPrototypeUnshift(args, options); return new HttpsClientRequest(args[0], args[1]); } diff --git a/ext/node/polyfills/internal/buffer.mjs b/ext/node/polyfills/internal/buffer.mjs index 4964b1956e..dd549221fa 100644 --- a/ext/node/polyfills/internal/buffer.mjs +++ b/ext/node/polyfills/internal/buffer.mjs @@ -2,11 +2,60 @@ // Copyright Joyent and Node contributors. All rights reserved. MIT license. // Copyright Feross Aboukhadijeh, and other contributors. All rights reserved. MIT license. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials - -import { core } from "ext:core/mod.js"; -import { op_is_ascii, op_is_utf8 } from "ext:core/ops"; +import { core, primordials } from "ext:core/mod.js"; +const { + isAnyArrayBuffer, + isArrayBuffer, + isDataView, + isSharedArrayBuffer, + isTypedArray, +} = core; +const { + ArrayBufferPrototypeGetByteLength, + ArrayBufferPrototypeGetDetached, + ArrayIsArray, + ArrayPrototypeSlice, + BigInt, + DataViewPrototypeGetByteLength, + Float32Array, + Float64Array, + MathFloor, + MathMin, + Number, + NumberIsInteger, + NumberIsNaN, + NumberMAX_SAFE_INTEGER, + NumberMIN_SAFE_INTEGER, + NumberPrototypeToString, + ObjectCreate, + ObjectDefineProperty, + ObjectPrototypeIsPrototypeOf, + ObjectSetPrototypeOf, + RangeError, + SafeRegExp, + String, + StringFromCharCode, + StringPrototypeCharCodeAt, + StringPrototypeIncludes, + StringPrototypeReplace, + StringPrototypeToLowerCase, + StringPrototypeTrim, + SymbolFor, + SymbolToPrimitive, + TypeError, + TypeErrorPrototype, + TypedArrayPrototypeCopyWithin, + TypedArrayPrototypeFill, + TypedArrayPrototypeGetBuffer, + TypedArrayPrototypeGetByteLength, + TypedArrayPrototypeGetByteOffset, + TypedArrayPrototypeSet, + TypedArrayPrototypeSlice, + TypedArrayPrototypeSubarray, + Uint8Array, + Uint8ArrayPrototype, +} = primordials; +import { op_is_ascii, op_is_utf8, op_transcode } from "ext:core/ops"; import { TextDecoder, TextEncoder } from "ext:deno_web/08_text_encoding.js"; import { codes } from "ext:deno_node/internal/error_codes.ts"; @@ -24,15 +73,14 @@ import { hexToBytes, utf16leToBytes, } from "ext:deno_node/internal_binding/_utils.ts"; -import { - isAnyArrayBuffer, - isArrayBufferView, - isTypedArray, -} from "ext:deno_node/internal/util/types.ts"; import { normalizeEncoding } from "ext:deno_node/internal/util.mjs"; import { validateBuffer } from "ext:deno_node/internal/validators.mjs"; import { isUint8Array } from "ext:deno_node/internal/util/types.ts"; -import { ERR_INVALID_STATE, NodeError } from "ext:deno_node/internal/errors.ts"; +import { + ERR_INVALID_STATE, + genericNodeError, + NodeError, +} from "ext:deno_node/internal/errors.ts"; import { forgivingBase64Encode, forgivingBase64UrlEncode, @@ -46,9 +94,13 @@ const utf8Encoder = new TextEncoder(); // Temporary buffers to convert numbers. const float32Array = new Float32Array(1); -const uInt8Float32Array = new Uint8Array(float32Array.buffer); +const uInt8Float32Array = new Uint8Array( + TypedArrayPrototypeGetBuffer(float32Array), +); const float64Array = new Float64Array(1); -const uInt8Float64Array = new Uint8Array(float64Array.buffer); +const uInt8Float64Array = new Uint8Array( + TypedArrayPrototypeGetBuffer(float64Array), +); // Check endianness. float32Array[0] = -1; // 0xBF800000 @@ -60,35 +112,34 @@ export const kMaxLength = 2147483647; export const kStringMaxLength = 536870888; const MAX_UINT32 = 2 ** 32; -const customInspectSymbol = - typeof Symbol === "function" && typeof Symbol["for"] === "function" - ? Symbol["for"]("nodejs.util.inspect.custom") - : null; +const customInspectSymbol = SymbolFor("nodejs.util.inspect.custom"); -const INSPECT_MAX_BYTES = 50; +export const INSPECT_MAX_BYTES = 50; export const constants = { MAX_LENGTH: kMaxLength, MAX_STRING_LENGTH: kStringMaxLength, }; -Object.defineProperty(Buffer.prototype, "parent", { +ObjectDefineProperty(Buffer.prototype, "parent", { + __proto__: null, enumerable: true, get: function () { - if (!Buffer.isBuffer(this)) { + if (!BufferIsBuffer(this)) { return void 0; } - return this.buffer; + return TypedArrayPrototypeGetBuffer(this); }, }); -Object.defineProperty(Buffer.prototype, "offset", { +ObjectDefineProperty(Buffer.prototype, "offset", { + __proto__: null, enumerable: true, get: function () { - if (!Buffer.isBuffer(this)) { + if (!BufferIsBuffer(this)) { return void 0; } - return this.byteOffset; + return TypedArrayPrototypeGetByteOffset(this); }, }); @@ -99,10 +150,21 @@ function createBuffer(length) { ); } const buf = new Uint8Array(length); - Object.setPrototypeOf(buf, Buffer.prototype); + ObjectSetPrototypeOf(buf, BufferPrototype); return buf; } +/** + * @param {ArrayBufferLike} O + * @returns {boolean} + */ +function isDetachedBuffer(O) { + if (isSharedArrayBuffer(O)) { + return false; + } + return ArrayBufferPrototypeGetDetached(O); +} + export function Buffer(arg, encodingOrOffset, length) { if (typeof arg === "number") { if (typeof encodingOrOffset === "string") { @@ -129,6 +191,7 @@ function _from(value, encodingOrOffset, length) { return fromArrayBuffer(value, encodingOrOffset, length); } + // deno-lint-ignore prefer-primordials const valueOf = value.valueOf && value.valueOf(); if ( valueOf != null && @@ -143,8 +206,8 @@ function _from(value, encodingOrOffset, length) { return b; } - if (typeof value[Symbol.toPrimitive] === "function") { - const primitive = value[Symbol.toPrimitive]("string"); + if (typeof value[SymbolToPrimitive] === "function") { + const primitive = value[SymbolToPrimitive]("string"); if (typeof primitive === "string") { return fromString(primitive, encodingOrOffset); } @@ -158,13 +221,19 @@ function _from(value, encodingOrOffset, length) { ); } -Buffer.from = function from(value, encodingOrOffset, length) { +const BufferFrom = Buffer.from = function from( + value, + encodingOrOffset, + length, +) { return _from(value, encodingOrOffset, length); }; -Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); +const BufferPrototype = Buffer.prototype; -Object.setPrototypeOf(Buffer, Uint8Array); +ObjectSetPrototypeOf(Buffer.prototype, Uint8ArrayPrototype); + +ObjectSetPrototypeOf(Buffer, Uint8Array); function assertSize(size) { validateNumber(size, "size", 0, kMaxLength); @@ -182,6 +251,7 @@ function _alloc(size, fill, encoding) { encoding, ); } + // deno-lint-ignore prefer-primordials return buffer.fill(fill, encoding); } return buffer; @@ -208,13 +278,14 @@ function fromString(string, encoding) { if (typeof encoding !== "string" || encoding === "") { encoding = "utf8"; } - if (!Buffer.isEncoding(encoding)) { + if (!BufferIsEncoding(encoding)) { throw new codes.ERR_UNKNOWN_ENCODING(encoding); } const length = byteLength(string, encoding) | 0; let buf = createBuffer(length); const actual = buf.write(string, encoding); if (actual !== length) { + // deno-lint-ignore prefer-primordials buf = buf.slice(0, actual); } return buf; @@ -222,11 +293,12 @@ function fromString(string, encoding) { function fromArrayLike(obj) { const buf = new Uint8Array(obj); - Object.setPrototypeOf(buf, Buffer.prototype); + ObjectSetPrototypeOf(buf, BufferPrototype); return buf; } function fromObject(obj) { + // deno-lint-ignore prefer-primordials if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) { if (typeof obj.length !== "number") { return createBuffer(0); @@ -235,7 +307,7 @@ function fromObject(obj) { return fromArrayLike(obj); } - if (obj.type === "Buffer" && Array.isArray(obj.data)) { + if (obj.type === "Buffer" && ArrayIsArray(obj.data)) { return fromArrayLike(obj.data); } } @@ -244,7 +316,7 @@ function checked(length) { if (length >= kMaxLength) { throw new RangeError( "Attempt to allocate Buffer larger than maximum size: 0x" + - kMaxLength.toString(16) + " bytes", + NumberPrototypeToString(kMaxLength, 16) + " bytes", ); } return length | 0; @@ -252,25 +324,33 @@ function checked(length) { export function SlowBuffer(length) { assertSize(length); - return Buffer.alloc(+length); + return _alloc(+length); } -Object.setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); +ObjectSetPrototypeOf(SlowBuffer.prototype, Uint8ArrayPrototype); -Object.setPrototypeOf(SlowBuffer, Uint8Array); +ObjectSetPrototypeOf(SlowBuffer, Uint8Array); -Buffer.isBuffer = function isBuffer(b) { - return b != null && b._isBuffer === true && b !== Buffer.prototype; +const BufferIsBuffer = Buffer.isBuffer = function isBuffer(b) { + return b != null && b._isBuffer === true && b !== BufferPrototype; }; -Buffer.compare = function compare(a, b) { - if (isInstance(a, Uint8Array)) { - a = Buffer.from(a, a.offset, a.byteLength); +const BufferCompare = Buffer.compare = function compare(a, b) { + if (isUint8Array(a)) { + a = BufferFrom( + a, + TypedArrayPrototypeGetByteOffset(a), + TypedArrayPrototypeGetByteLength(a), + ); } - if (isInstance(b, Uint8Array)) { - b = Buffer.from(b, b.offset, b.byteLength); + if (isUint8Array(b)) { + b = BufferFrom( + b, + TypedArrayPrototypeGetByteOffset(b), + TypedArrayPrototypeGetByteLength(b), + ); } - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + if (!BufferIsBuffer(a) || !BufferIsBuffer(b)) { throw new TypeError( 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array', ); @@ -280,7 +360,7 @@ Buffer.compare = function compare(a, b) { } let x = a.length; let y = b.length; - for (let i = 0, len = Math.min(x, y); i < len; ++i) { + for (let i = 0, len = MathMin(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i]; y = b[i]; @@ -296,18 +376,18 @@ Buffer.compare = function compare(a, b) { return 0; }; -Buffer.isEncoding = function isEncoding(encoding) { +const BufferIsEncoding = Buffer.isEncoding = function isEncoding(encoding) { return typeof encoding === "string" && encoding.length !== 0 && normalizeEncoding(encoding) !== undefined; }; Buffer.concat = function concat(list, length) { - if (!Array.isArray(list)) { + if (!ArrayIsArray(list)) { throw new codes.ERR_INVALID_ARG_TYPE("list", "Array", list); } if (list.length === 0) { - return Buffer.alloc(0); + return _alloc(0); } if (length === undefined) { @@ -321,7 +401,7 @@ Buffer.concat = function concat(list, length) { validateOffset(length, "length"); } - const buffer = Buffer.allocUnsafe(length); + const buffer = _allocUnsafe(length); let pos = 0; for (let i = 0; i < list.length; i++) { const buf = list[i]; @@ -342,7 +422,7 @@ Buffer.concat = function concat(list, length) { // Zero-fill the remaining bytes if the specified `length` was more than // the actual total length, i.e. if we have some remaining allocated bytes // there were not initialized. - buffer.fill(0, pos, length); + TypedArrayPrototypeFill(buffer, 0, pos, length); } return buffer; @@ -350,7 +430,18 @@ Buffer.concat = function concat(list, length) { function byteLength(string, encoding) { if (typeof string !== "string") { - if (isArrayBufferView(string) || isAnyArrayBuffer(string)) { + if (isTypedArray(string)) { + return TypedArrayPrototypeGetByteLength(string); + } + if (isDataView(string)) { + return DataViewPrototypeGetByteLength(string); + } + if (isArrayBuffer(string)) { + return ArrayBufferPrototypeGetByteLength(string); + } + if (isSharedArrayBuffer(string)) { + // TODO(petamoriken): add SharedArayBuffer to primordials + // deno-lint-ignore prefer-primordials return string.byteLength; } @@ -459,6 +550,7 @@ Buffer.prototype.toString = function toString(encoding, start, end) { throw new codes.ERR_UNKNOWN_ENCODING(encoding); } + // deno-lint-ignore prefer-primordials return ops.slice(this, start, end); }; @@ -475,22 +567,29 @@ Buffer.prototype.equals = function equals(b) { if (this === b) { return true; } - return Buffer.compare(this, b) === 0; + return BufferCompare(this, b) === 0; }; -Buffer.prototype.inspect = function inspect() { - let str = ""; - const max = INSPECT_MAX_BYTES; - str = this.toString("hex", 0, max).replace(/(.{2})/g, "$1 ").trim(); - if (this.length > max) { - str += " ... "; - } - return ""; -}; +const SPACER_PATTERN = new SafeRegExp(/(.{2})/g); -if (customInspectSymbol) { - Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect; -} +Buffer.prototype[customInspectSymbol] = + Buffer.prototype.inspect = + function inspect() { + let str = ""; + const max = INSPECT_MAX_BYTES; + str = StringPrototypeTrim( + StringPrototypeReplace( + // deno-lint-ignore prefer-primordials + this.toString("hex", 0, max), + SPACER_PATTERN, + "$1 ", + ), + ); + if (this.length > max) { + str += " ... "; + } + return ""; + }; Buffer.prototype.compare = function compare( target, @@ -499,10 +598,14 @@ Buffer.prototype.compare = function compare( thisStart, thisEnd, ) { - if (isInstance(target, Uint8Array)) { - target = Buffer.from(target, target.offset, target.byteLength); + if (isUint8Array(target)) { + target = BufferFrom( + target, + TypedArrayPrototypeGetByteOffset(target), + TypedArrayPrototypeGetByteLength(target), + ); } - if (!Buffer.isBuffer(target)) { + if (!BufferIsBuffer(target)) { throw new codes.ERR_INVALID_ARG_TYPE( "target", ["Buffer", "Uint8Array"], @@ -559,8 +662,9 @@ Buffer.prototype.compare = function compare( } let x = thisEnd - thisStart; let y = end - start; - const len = Math.min(x, y); - const thisCopy = this.slice(thisStart, thisEnd); + const len = MathMin(x, y); + const thisCopy = TypedArrayPrototypeSlice(this, thisStart, thisEnd); + // deno-lint-ignore prefer-primordials const targetCopy = target.slice(start, end); for (let i = 0; i < len; ++i) { if (thisCopy[i] !== targetCopy[i]) { @@ -590,7 +694,8 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { byteOffset = -0x80000000; } byteOffset = +byteOffset; - if (Number.isNaN(byteOffset)) { + if (NumberIsNaN(byteOffset)) { + // deno-lint-ignore prefer-primordials byteOffset = dir ? 0 : (buffer.length || buffer.byteLength); } dir = !!dir; @@ -610,6 +715,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { if (ops === undefined) { throw new codes.ERR_UNKNOWN_ENCODING(encoding); } + // deno-lint-ignore prefer-primordials return ops.indexOf(buffer, val, byteOffset, dir); } @@ -626,6 +732,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { } Buffer.prototype.includes = function includes(val, byteOffset, encoding) { + // deno-lint-ignore prefer-primordials return this.indexOf(val, byteOffset, encoding) !== -1; }; @@ -645,7 +752,7 @@ Buffer.prototype.asciiSlice = function asciiSlice(offset, length) { if (offset === 0 && length === this.length) { return bytesToAscii(this); } else { - return bytesToAscii(this.slice(offset, length)); + return bytesToAscii(TypedArrayPrototypeSlice(this, offset, length)); } }; @@ -660,7 +767,9 @@ Buffer.prototype.base64Slice = function base64Slice( if (offset === 0 && length === this.length) { return forgivingBase64Encode(this); } else { - return forgivingBase64Encode(this.slice(offset, length)); + return forgivingBase64Encode( + TypedArrayPrototypeSlice(this, offset, length), + ); } }; @@ -679,7 +788,9 @@ Buffer.prototype.base64urlSlice = function base64urlSlice( if (offset === 0 && length === this.length) { return forgivingBase64UrlEncode(this); } else { - return forgivingBase64UrlEncode(this.slice(offset, length)); + return forgivingBase64UrlEncode( + TypedArrayPrototypeSlice(this, offset, length), + ); } }; @@ -724,7 +835,7 @@ Buffer.prototype.ucs2Slice = function ucs2Slice(offset, length) { if (offset === 0 && length === this.length) { return bytesToUtf16le(this); } else { - return bytesToUtf16le(this.slice(offset, length)); + return bytesToUtf16le(TypedArrayPrototypeSlice(this, offset, length)); } }; @@ -743,9 +854,9 @@ Buffer.prototype.utf8Slice = function utf8Slice(string, offset, length) { Buffer.prototype.utf8Write = function utf8Write(string, offset, length) { offset = offset || 0; - const maxLength = Math.min(length || Infinity, this.length - offset); + const maxLength = MathMin(length || Infinity, this.length - offset); const buf = offset || maxLength < this.length - ? this.subarray(offset, maxLength + offset) + ? TypedArrayPrototypeSubarray(this, offset, maxLength + offset) : this; return utf8Encoder.encodeInto(string, buf).written; }; @@ -797,7 +908,7 @@ Buffer.prototype.write = function write(string, offset, length, encoding) { Buffer.prototype.toJSON = function toJSON() { return { type: "Buffer", - data: Array.prototype.slice.call(this._arr || this, 0), + data: ArrayPrototypeSlice(this._arr || this, 0), }; }; function fromArrayBuffer(obj, byteOffset, length) { @@ -806,11 +917,12 @@ function fromArrayBuffer(obj, byteOffset, length) { byteOffset = 0; } else { byteOffset = +byteOffset; - if (Number.isNaN(byteOffset)) { + if (NumberIsNaN(byteOffset)) { byteOffset = 0; } } + // deno-lint-ignore prefer-primordials const maxLength = obj.byteLength - byteOffset; if (maxLength < 0) { @@ -832,7 +944,7 @@ function fromArrayBuffer(obj, byteOffset, length) { } const buffer = new Uint8Array(obj, byteOffset, length); - Object.setPrototypeOf(buffer, Buffer.prototype); + ObjectSetPrototypeOf(buffer, BufferPrototype); return buffer; } @@ -840,6 +952,7 @@ function _base64Slice(buf, start, end) { if (start === 0 && end === buf.length) { return forgivingBase64Encode(buf); } else { + // deno-lint-ignore prefer-primordials return forgivingBase64Encode(buf.slice(start, end)); } } @@ -848,9 +961,10 @@ const decoder = new TextDecoder(); function _utf8Slice(buf, start, end) { try { + // deno-lint-ignore prefer-primordials return decoder.decode(buf.slice(start, end)); } catch (err) { - if (err instanceof TypeError) { + if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, err)) { throw new NodeError("ERR_STRING_TOO_LONG", "String too long"); } throw err; @@ -859,9 +973,9 @@ function _utf8Slice(buf, start, end) { function _latin1Slice(buf, start, end) { let ret = ""; - end = Math.min(buf.length, end); + end = MathMin(buf.length, end); for (let i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]); + ret += StringFromCharCode(buf[i]); } return ret; } @@ -990,42 +1104,38 @@ Buffer.prototype.readUint32BE = Buffer.prototype.readUInt32BE = readUInt32BE; Buffer.prototype.readBigUint64LE = Buffer.prototype.readBigUInt64LE = - defineBigIntMethod( - function readBigUInt64LE(offset) { - offset = offset >>> 0; - validateNumber(offset, "offset"); - const first = this[offset]; - const last = this[offset + 7]; - if (first === void 0 || last === void 0) { - boundsError(offset, this.length - 8); - } - const lo = first + this[++offset] * 2 ** 8 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 24; - const hi = this[++offset] + this[++offset] * 2 ** 8 + - this[++offset] * 2 ** 16 + last * 2 ** 24; - return BigInt(lo) + (BigInt(hi) << BigInt(32)); - }, - ); + function readBigUInt64LE(offset) { + offset = offset >>> 0; + validateNumber(offset, "offset"); + const first = this[offset]; + const last = this[offset + 7]; + if (first === void 0 || last === void 0) { + boundsError(offset, this.length - 8); + } + const lo = first + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24; + const hi = this[++offset] + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + last * 2 ** 24; + return BigInt(lo) + (BigInt(hi) << 32n); + }; Buffer.prototype.readBigUint64BE = Buffer.prototype.readBigUInt64BE = - defineBigIntMethod( - function readBigUInt64BE(offset) { - offset = offset >>> 0; - validateNumber(offset, "offset"); - const first = this[offset]; - const last = this[offset + 7]; - if (first === void 0 || last === void 0) { - boundsError(offset, this.length - 8); - } - const hi = first * 2 ** 24 + this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + this[++offset]; - const lo = this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + last; - return (BigInt(hi) << BigInt(32)) + BigInt(lo); - }, - ); + function readBigUInt64BE(offset) { + offset = offset >>> 0; + validateNumber(offset, "offset"); + const first = this[offset]; + const last = this[offset + 7]; + if (first === void 0 || last === void 0) { + boundsError(offset, this.length - 8); + } + const hi = first * 2 ** 24 + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + this[++offset]; + const lo = this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + last; + return (BigInt(hi) << 32n) + BigInt(lo); + }; Buffer.prototype.readIntLE = function readIntLE( offset, @@ -1144,43 +1254,39 @@ Buffer.prototype.readInt32BE = function readInt32BE(offset = 0) { last; }; -Buffer.prototype.readBigInt64LE = defineBigIntMethod( - function readBigInt64LE(offset) { - offset = offset >>> 0; - validateNumber(offset, "offset"); - const first = this[offset]; - const last = this[offset + 7]; - if (first === void 0 || last === void 0) { - boundsError(offset, this.length - 8); - } - const val = this[offset + 4] + this[offset + 5] * 2 ** 8 + - this[offset + 6] * 2 ** 16 + (last << 24); - return (BigInt(val) << BigInt(32)) + - BigInt( - first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 24, - ); - }, -); +Buffer.prototype.readBigInt64LE = function readBigInt64LE(offset) { + offset = offset >>> 0; + validateNumber(offset, "offset"); + const first = this[offset]; + const last = this[offset + 7]; + if (first === void 0 || last === void 0) { + boundsError(offset, this.length - 8); + } + const val = this[offset + 4] + this[offset + 5] * 2 ** 8 + + this[offset + 6] * 2 ** 16 + (last << 24); + return (BigInt(val) << 32n) + + BigInt( + first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24, + ); +}; -Buffer.prototype.readBigInt64BE = defineBigIntMethod( - function readBigInt64BE(offset) { - offset = offset >>> 0; - validateNumber(offset, "offset"); - const first = this[offset]; - const last = this[offset + 7]; - if (first === void 0 || last === void 0) { - boundsError(offset, this.length - 8); - } - const val = (first << 24) + this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + this[++offset]; - return (BigInt(val) << BigInt(32)) + - BigInt( - this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + last, - ); - }, -); +Buffer.prototype.readBigInt64BE = function readBigInt64BE(offset) { + offset = offset >>> 0; + validateNumber(offset, "offset"); + const first = this[offset]; + const last = this[offset + 7]; + if (first === void 0 || last === void 0) { + boundsError(offset, this.length - 8); + } + const val = (first << 24) + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + this[++offset]; + return (BigInt(val) << 32n) + + BigInt( + this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + last, + ); +}; Buffer.prototype.readFloatLE = function readFloatLE(offset) { return bigEndian @@ -1289,7 +1395,7 @@ Buffer.prototype.writeUint32BE = function wrtBigUInt64LE(buf, value, offset, min, max) { checkIntBI(value, min, max, buf, offset, 7); - let lo = Number(value & BigInt(4294967295)); + let lo = Number(value & 4294967295n); buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; @@ -1297,7 +1403,7 @@ function wrtBigUInt64LE(buf, value, offset, min, max) { buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; - let hi = Number(value >> BigInt(32) & BigInt(4294967295)); + let hi = Number(value >> 32n & 4294967295n); buf[offset++] = hi; hi = hi >> 8; buf[offset++] = hi; @@ -1310,7 +1416,7 @@ function wrtBigUInt64LE(buf, value, offset, min, max) { function wrtBigUInt64BE(buf, value, offset, min, max) { checkIntBI(value, min, max, buf, offset, 7); - let lo = Number(value & BigInt(4294967295)); + let lo = Number(value & 4294967295n); buf[offset + 7] = lo; lo = lo >> 8; buf[offset + 6] = lo; @@ -1318,7 +1424,7 @@ function wrtBigUInt64BE(buf, value, offset, min, max) { buf[offset + 5] = lo; lo = lo >> 8; buf[offset + 4] = lo; - let hi = Number(value >> BigInt(32) & BigInt(4294967295)); + let hi = Number(value >> 32n & 4294967295n); buf[offset + 3] = hi; hi = hi >> 8; buf[offset + 2] = hi; @@ -1331,31 +1437,27 @@ function wrtBigUInt64BE(buf, value, offset, min, max) { Buffer.prototype.writeBigUint64LE = Buffer.prototype.writeBigUInt64LE = - defineBigIntMethod( - function writeBigUInt64LE(value, offset = 0) { - return wrtBigUInt64LE( - this, - value, - offset, - BigInt(0), - BigInt("0xffffffffffffffff"), - ); - }, - ); + function writeBigUInt64LE(value, offset = 0) { + return wrtBigUInt64LE( + this, + value, + offset, + 0n, + 0xffffffffffffffffn, + ); + }; Buffer.prototype.writeBigUint64BE = Buffer.prototype.writeBigUInt64BE = - defineBigIntMethod( - function writeBigUInt64BE(value, offset = 0) { - return wrtBigUInt64BE( - this, - value, - offset, - BigInt(0), - BigInt("0xffffffffffffffff"), - ); - }, - ); + function writeBigUInt64BE(value, offset = 0) { + return wrtBigUInt64BE( + this, + value, + offset, + 0n, + 0xffffffffffffffffn, + ); + }; Buffer.prototype.writeIntLE = function writeIntLE( value, @@ -1446,29 +1548,25 @@ Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset = 0) { return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff); }; -Buffer.prototype.writeBigInt64LE = defineBigIntMethod( - function writeBigInt64LE(value, offset = 0) { - return wrtBigUInt64LE( - this, - value, - offset, - -BigInt("0x8000000000000000"), - BigInt("0x7fffffffffffffff"), - ); - }, -); +Buffer.prototype.writeBigInt64LE = function writeBigInt64LE(value, offset = 0) { + return wrtBigUInt64LE( + this, + value, + offset, + -0x8000000000000000n, + 0x7fffffffffffffffn, + ); +}; -Buffer.prototype.writeBigInt64BE = defineBigIntMethod( - function writeBigInt64BE(value, offset = 0) { - return wrtBigUInt64BE( - this, - value, - offset, - -BigInt("0x8000000000000000"), - BigInt("0x7fffffffffffffff"), - ); - }, -); +Buffer.prototype.writeBigInt64BE = function writeBigInt64BE(value, offset = 0) { + return wrtBigUInt64BE( + this, + value, + offset, + -0x8000000000000000n, + 0x7fffffffffffffffn, + ); +}; Buffer.prototype.writeFloatLE = function writeFloatLE( value, @@ -1596,14 +1694,12 @@ Buffer.prototype.copy = function copy( } const len = sourceEnd - sourceStart; - if ( - this === target && typeof Uint8Array.prototype.copyWithin === "function" - ) { - this.copyWithin(targetStart, sourceStart, sourceEnd); + if (this === target) { + TypedArrayPrototypeCopyWithin(this, targetStart, sourceStart, sourceEnd); } else { - Uint8Array.prototype.set.call( + TypedArrayPrototypeSet( target, - this.subarray(sourceStart, sourceEnd), + TypedArrayPrototypeSubarray(this, sourceStart, sourceEnd), targetStart, ); } @@ -1623,11 +1719,11 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) { if (encoding !== void 0 && typeof encoding !== "string") { throw new TypeError("encoding must be a string"); } - if (typeof encoding === "string" && !Buffer.isEncoding(encoding)) { + if (typeof encoding === "string" && !BufferIsEncoding(encoding)) { throw new TypeError("Unknown encoding: " + encoding); } if (val.length === 1) { - const code = val.charCodeAt(0); + const code = StringPrototypeCharCodeAt(val, 0); if (encoding === "utf8" && code < 128 || encoding === "latin1") { val = code; } @@ -1654,7 +1750,7 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) { this[i] = val; } } else { - const bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding); + const bytes = BufferIsBuffer(val) ? val : BufferFrom(val, encoding); const len = bytes.length; if (len === 0) { throw new codes.ERR_INVALID_ARG_VALUE( @@ -1681,7 +1777,7 @@ function checkIntBI(value, min, max, buf, offset, byteLength2) { const n = typeof min === "bigint" ? "n" : ""; let range; if (byteLength2 > 3) { - if (min === 0 || min === BigInt(0)) { + if (min === 0 || min === 0n) { range = `>= 0${n} and < 2${n} ** ${(byteLength2 + 1) * 8}${n}`; } else { range = `>= -(2${n} ** ${(byteLength2 + 1) * 8 - 1}${n}) and < 2 ** ${ @@ -1706,7 +1802,7 @@ function checkIntBI(value, min, max, buf, offset, byteLength2) { function blitBuffer(src, dst, offset, byteLength = Infinity) { const srcLength = src.length; // Establish the number of bytes to be written - const bytesToWrite = Math.min( + const bytesToWrite = MathMin( // If byte length is defined in the call, then it sets an upper bound, // otherwise it is Infinity and is never chosen. byteLength, @@ -1726,15 +1822,9 @@ function blitBuffer(src, dst, offset, byteLength = Infinity) { return bytesToWrite; } -function isInstance(obj, type) { - return obj instanceof type || - obj != null && obj.constructor != null && - obj.constructor.name != null && obj.constructor.name === type.name; -} - const hexSliceLookupTable = function () { const alphabet = "0123456789abcdef"; - const table = new Array(256); + const table = []; for (let i = 0; i < 16; ++i) { const i16 = i * 16; for (let j = 0; j < 16; ++j) { @@ -1744,14 +1834,6 @@ const hexSliceLookupTable = function () { return table; }(); -function defineBigIntMethod(fn) { - return typeof BigInt === "undefined" ? BufferBigIntNotDefined : fn; -} - -function BufferBigIntNotDefined() { - throw new Error("BigInt not supported"); -} - export function readUInt48LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; @@ -2075,10 +2157,10 @@ export function byteLengthUtf8(str) { function base64ByteLength(str, bytes) { // Handle padding - if (str.charCodeAt(bytes - 1) === 0x3D) { + if (StringPrototypeCharCodeAt(str, bytes - 1) === 0x3D) { bytes--; } - if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3D) { + if (bytes > 1 && StringPrototypeCharCodeAt(str, bytes - 1) === 0x3D) { bytes--; } @@ -2086,7 +2168,7 @@ function base64ByteLength(str, bytes) { return (bytes * 3) >>> 2; } -export const encodingsMap = Object.create(null); +export const encodingsMap = ObjectCreate(null); for (let i = 0; i < encodings.length; ++i) { encodingsMap[encodings[i]] = i; } @@ -2216,7 +2298,7 @@ export const encodingOps = { }; export function getEncodingOps(encoding) { - encoding = String(encoding).toLowerCase(); + encoding = StringPrototypeToLowerCase(String(encoding)); switch (encoding.length) { case 4: if (encoding === "utf8") return encodingOps.utf8; @@ -2256,6 +2338,14 @@ export function getEncodingOps(encoding) { } } +/** + * @param {Buffer} source + * @param {Buffer} target + * @param {number} targetStart + * @param {number} sourceStart + * @param {number} sourceEnd + * @returns {number} + */ export function _copyActual( source, target, @@ -2274,6 +2364,7 @@ export function _copyActual( } if (sourceStart !== 0 || sourceEnd < source.length) { + // deno-lint-ignore prefer-primordials source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb); } @@ -2283,7 +2374,7 @@ export function _copyActual( } export function boundsError(value, length, type) { - if (Math.floor(value) !== value) { + if (MathFloor(value) !== value) { validateNumber(value, type); throw new codes.ERR_OUT_OF_RANGE(type || "offset", "an integer", value); } @@ -2306,7 +2397,7 @@ export function validateNumber(value, name, min = undefined, max) { if ( (min != null && value < min) || (max != null && value > max) || - ((min != null || max != null) && Number.isNaN(value)) + ((min != null || max != null) && NumberIsNaN(value)) ) { throw new codes.ERR_OUT_OF_RANGE( name, @@ -2340,11 +2431,11 @@ function checkInt(value, min, max, buf, offset, byteLength) { export function toInteger(n, defaultVal) { n = +n; if ( - !Number.isNaN(n) && - n >= Number.MIN_SAFE_INTEGER && - n <= Number.MAX_SAFE_INTEGER + !NumberIsNaN(n) && + n >= NumberMIN_SAFE_INTEGER && + n <= NumberMAX_SAFE_INTEGER ) { - return ((n % 1) === 0 ? n : Math.floor(n)); + return ((n % 1) === 0 ? n : MathFloor(n)); } return defaultVal; } @@ -2417,7 +2508,7 @@ export function writeU_Int48BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 5); - const newVal = Math.floor(value * 2 ** -32); + const newVal = MathFloor(value * 2 ** -32); buf[offset++] = newVal >>> 8; buf[offset++] = newVal; buf[offset + 3] = value; @@ -2435,7 +2526,7 @@ export function writeU_Int40BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 4); - buf[offset++] = Math.floor(value * 2 ** -32); + buf[offset++] = MathFloor(value * 2 ** -32); buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; @@ -2478,12 +2569,12 @@ export function validateOffset( value, name, min = 0, - max = Number.MAX_SAFE_INTEGER, + max = NumberMAX_SAFE_INTEGER, ) { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } - if (!Number.isInteger(value)) { + if (!NumberIsInteger(value)) { throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value); } if (value < min || value > max) { @@ -2496,7 +2587,7 @@ export function writeU_Int48LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 5); - const newVal = Math.floor(value * 2 ** -32); + const newVal = MathFloor(value * 2 ** -32); buf[offset++] = value; value = value >>> 8; buf[offset++] = value; @@ -2522,7 +2613,7 @@ export function writeU_Int40LE(buf, value, offset, min, max) { buf[offset++] = value; value = value >>> 8; buf[offset++] = value; - buf[offset++] = Math.floor(newVal * 2 ** -32); + buf[offset++] = MathFloor(newVal * 2 ** -32); return offset; } @@ -2556,14 +2647,14 @@ export function writeU_Int24LE(buf, value, offset, min, max) { export function isUtf8(input) { if (isTypedArray(input)) { - if (input.buffer.detached) { + if (isDetachedBuffer(TypedArrayPrototypeGetBuffer(input))) { throw new ERR_INVALID_STATE("Cannot validate on a detached buffer"); } return op_is_utf8(input); } if (isAnyArrayBuffer(input)) { - if (input.detached) { + if (isDetachedBuffer(input)) { throw new ERR_INVALID_STATE("Cannot validate on a detached buffer"); } return op_is_utf8(new Uint8Array(input)); @@ -2578,14 +2669,14 @@ export function isUtf8(input) { export function isAscii(input) { if (isTypedArray(input)) { - if (input.buffer.detached) { + if (isDetachedBuffer(TypedArrayPrototypeGetBuffer(input))) { throw new ERR_INVALID_STATE("Cannot validate on a detached buffer"); } return op_is_ascii(input); } if (isAnyArrayBuffer(input)) { - if (input.detached) { + if (isDetachedBuffer(input)) { throw new ERR_INVALID_STATE("Cannot validate on a detached buffer"); } return op_is_ascii(new Uint8Array(input)); @@ -2598,6 +2689,48 @@ export function isAscii(input) { ], input); } +export function transcode(source, fromEnco, toEnco) { + if (!isUint8Array(source)) { + throw new codes.ERR_INVALID_ARG_TYPE( + "source", + ["Buffer", "Uint8Array"], + source, + ); + } + if (source.length === 0) { + return Buffer.alloc(0); + } + const code = "U_ILLEGAL_ARGUMENT_ERROR"; + const illegalArgumentError = genericNodeError( + `Unable to transcode Buffer [${code}]`, + { code: code, errno: 1 }, + ); + fromEnco = normalizeEncoding(fromEnco); + toEnco = normalizeEncoding(toEnco); + if (!fromEnco || !toEnco) { + throw illegalArgumentError; + } + // Return the provided source when transcode is not required + // for the from/to encoding pair. + const returnSource = fromEnco === toEnco || + fromEnco === "ascii" && toEnco === "utf8" || + fromEnco === "ascii" && toEnco === "latin1"; + if (returnSource) { + return Buffer.from(source); + } + + try { + const result = op_transcode(new Uint8Array(source), fromEnco, toEnco); + return Buffer.from(result, toEnco); + } catch (err) { + if (StringPrototypeIncludes(err.message, "Unable to transcode Buffer")) { + throw illegalArgumentError; + } else { + throw err; + } + } +} + export default { atob, btoa, @@ -2606,7 +2739,9 @@ export default { constants, isAscii, isUtf8, + INSPECT_MAX_BYTES, kMaxLength, kStringMaxLength, SlowBuffer, + transcode, }; diff --git a/ext/node/polyfills/internal/child_process.ts b/ext/node/polyfills/internal/child_process.ts index 8c2266f66f..65e09a3254 100644 --- a/ext/node/polyfills/internal/child_process.ts +++ b/ext/node/polyfills/internal/child_process.ts @@ -55,8 +55,13 @@ import process from "node:process"; import { StringPrototypeSlice } from "ext:deno_node/internal/primordials.mjs"; import { StreamBase } from "ext:deno_node/internal_binding/stream_wrap.ts"; import { Pipe, socketType } from "ext:deno_node/internal_binding/pipe_wrap.ts"; -import console from "node:console"; import { Socket } from "node:net"; +import { + kDetached, + kExtraStdio, + kIpc, + kNeedsNpmProcessState, +} from "ext:runtime/40_process.js"; export function mapValues( record: Readonly>, @@ -110,6 +115,7 @@ export function stdioStringToArray( const kClosesNeeded = Symbol("_closesNeeded"); const kClosesReceived = Symbol("_closesReceived"); +const kCanDisconnect = Symbol("_canDisconnect"); // We only want to emit a close event for the child process when all of // the writable streams have closed. The value of `child[kClosesNeeded]` should be 1 + @@ -223,7 +229,7 @@ export class ChildProcess extends EventEmitter { #spawned = Promise.withResolvers(); [kClosesNeeded] = 1; [kClosesReceived] = 0; - canDisconnect = false; + [kCanDisconnect] = false; constructor( command: string, @@ -239,6 +245,7 @@ export class ChildProcess extends EventEmitter { shell = false, signal, windowsVerbatimArguments = false, + detached, } = options || {}; const normalizedStdio = normalizeStdioOption(stdio); const [ @@ -276,8 +283,11 @@ export class ChildProcess extends EventEmitter { stdout: toDenoStdio(stdout), stderr: toDenoStdio(stderr), windowsRawArguments: windowsVerbatimArguments, - ipc, // internal - extraStdio: extraStdioNormalized, + [kIpc]: ipc, // internal + [kExtraStdio]: extraStdioNormalized, + [kDetached]: detached, + // deno-lint-ignore no-explicit-any + [kNeedsNpmProcessState]: (options ?? {} as any)[kNeedsNpmProcessState], }).spawn(); this.pid = this.#process.pid; @@ -422,7 +432,7 @@ export class ChildProcess extends EventEmitter { } /* Cancel any pending IPC I/O */ - if (this.canDisconnect) { + if (this[kCanDisconnect]) { this.disconnect?.(); } @@ -553,7 +563,7 @@ export interface ChildProcessOptions { stdio?: Array | NodeStdio; /** - * NOTE: This option is not yet implemented. + * Whether to spawn the process in a detached state. */ detached?: boolean; @@ -1100,7 +1110,6 @@ const kNodeFlagsMap = new Map([ const kDenoSubcommands = new Set([ "add", "bench", - "bundle", "cache", "check", "compile", @@ -1182,8 +1191,12 @@ function toDenoArgs(args: string[]): string[] { } if (flagInfo === undefined) { - // Not a known flag that expects a value. Just copy it to the output. - denoArgs.push(arg); + if (arg === "--no-warnings") { + denoArgs.push("--quiet"); + } else { + // Not a known flag that expects a value. Just copy it to the output. + denoArgs.push(arg); + } continue; } @@ -1326,7 +1339,7 @@ export function setupChannel(target: any, ipc: number) { } } - process.nextTick(handleMessage, msg); + nextTick(handleMessage, msg); } } catch (err) { if ( @@ -1387,8 +1400,7 @@ export function setupChannel(target: any, ipc: number) { if (!target.connected) { const err = new ERR_IPC_CHANNEL_CLOSED(); if (typeof callback === "function") { - console.error("ChildProcess.send with callback"); - process.nextTick(callback, err); + nextTick(callback, err); } else { nextTick(() => target.emit("error", err)); } @@ -1404,7 +1416,18 @@ export function setupChannel(target: any, ipc: number) { .then(() => { control.unrefCounted(); if (callback) { - process.nextTick(callback, null); + nextTick(callback, null); + } + }, (err: Error) => { + control.unrefCounted(); + if (err instanceof Deno.errors.Interrupted) { + // Channel closed on us mid-write. + } else { + if (typeof callback === "function") { + nextTick(callback, err); + } else { + nextTick(() => target.emit("error", err)); + } } }); return queueOk[0]; @@ -1419,15 +1442,15 @@ export function setupChannel(target: any, ipc: number) { } target.connected = false; - target.canDisconnect = false; + target[kCanDisconnect] = false; control[kControlDisconnect](); - process.nextTick(() => { + nextTick(() => { target.channel = null; core.close(ipc); target.emit("disconnect"); }); }; - target.canDisconnect = true; + target[kCanDisconnect] = true; // Start reading messages from the channel. readLoop(); diff --git a/ext/node/polyfills/internal/console/constructor.mjs b/ext/node/polyfills/internal/console/constructor.mjs index 8f4689962f..ebf5cbec4f 100644 --- a/ext/node/polyfills/internal/console/constructor.mjs +++ b/ext/node/polyfills/internal/console/constructor.mjs @@ -667,10 +667,15 @@ Console.prototype.dirxml = Console.prototype.log; Console.prototype.error = Console.prototype.warn; Console.prototype.groupCollapsed = Console.prototype.group; +export function bindStreamsLazy(console, object) { + Console.prototype[kBindStreamsLazy].call(console, object); +} + export { Console, formatTime, kBindProperties, kBindStreamsLazy }; export default { Console, kBindStreamsLazy, kBindProperties, formatTime, + bindStreamsLazy, }; diff --git a/ext/node/polyfills/internal/crypto/_randomInt.ts b/ext/node/polyfills/internal/crypto/_randomInt.ts index 7f4d703ad4..e08b3e9639 100644 --- a/ext/node/polyfills/internal/crypto/_randomInt.ts +++ b/ext/node/polyfills/internal/crypto/_randomInt.ts @@ -1,9 +1,15 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials - import { op_node_random_int } from "ext:core/ops"; +import { primordials } from "ext:core/mod.js"; +const { + Error, + MathCeil, + MathFloor, + MathPow, + NumberIsSafeInteger, + RangeError, +} = primordials; export default function randomInt(max: number): number; export default function randomInt(min: number, max: number): number; @@ -23,7 +29,9 @@ export default function randomInt( cb?: (err: Error | null, n?: number) => void, ): number | void { if (typeof max === "number" && typeof min === "number") { - [max, min] = [min, max]; + const temp = max; + max = min; + min = temp; } if (min === undefined) min = 0; else if (typeof min === "function") { @@ -32,13 +40,13 @@ export default function randomInt( } if ( - !Number.isSafeInteger(min) || - typeof max === "number" && !Number.isSafeInteger(max) + !NumberIsSafeInteger(min) || + typeof max === "number" && !NumberIsSafeInteger(max) ) { throw new Error("max or min is not a Safe Number"); } - if (max - min > Math.pow(2, 48)) { + if (max - min > MathPow(2, 48)) { throw new RangeError("max - min should be less than 2^48!"); } @@ -46,8 +54,8 @@ export default function randomInt( throw new Error("Min is bigger than Max!"); } - min = Math.ceil(min); - max = Math.floor(max); + min = MathCeil(min); + max = MathFloor(max); const result = op_node_random_int(min, max); if (cb) { diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index 2141edc76b..c1c5ce8901 100644 --- a/ext/node/polyfills/internal/crypto/cipher.ts +++ b/ext/node/polyfills/internal/crypto/cipher.ts @@ -242,7 +242,7 @@ export class Cipheriv extends Transform implements Cipher { ): Buffer | string { // TODO(kt3k): throw ERR_INVALID_ARG_TYPE if data is not string, Buffer, or ArrayBufferView let buf = data; - if (typeof data === "string" && typeof inputEncoding === "string") { + if (typeof data === "string") { buf = Buffer.from(data, inputEncoding); } @@ -306,6 +306,10 @@ class BlockModeCache { this.cache = this.cache.subarray(len); return out; } + + set lastChunkIsNonZero(value: boolean) { + this.#lastChunkIsNonZero = value; + } } export class Decipheriv extends Transform implements Cipher { @@ -338,7 +342,7 @@ export class Decipheriv extends Transform implements Cipher { }, ...options, }); - this.#cache = new BlockModeCache(true); + this.#cache = new BlockModeCache(this.#autoPadding); this.#context = op_node_create_decipheriv(cipher, toU8(key), toU8(iv)); this.#needsBlockCache = !(cipher == "aes-128-gcm" || cipher == "aes-256-gcm"); @@ -386,6 +390,7 @@ export class Decipheriv extends Transform implements Cipher { setAutoPadding(autoPadding?: boolean): this { this.#autoPadding = Boolean(autoPadding); + this.#cache.lastChunkIsNonZero = this.#autoPadding; return this; } @@ -396,7 +401,7 @@ export class Decipheriv extends Transform implements Cipher { ): Buffer | string { // TODO(kt3k): throw ERR_INVALID_ARG_TYPE if data is not string, Buffer, or ArrayBufferView let buf = data; - if (typeof data === "string" && typeof inputEncoding === "string") { + if (typeof data === "string") { buf = Buffer.from(data, inputEncoding); } diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index 62cec47d67..c91c23cc3d 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -12,13 +12,17 @@ const { } = primordials; import { + op_node_create_ec_jwk, + op_node_create_ed_raw, op_node_create_private_key, op_node_create_public_key, + op_node_create_rsa_jwk, op_node_create_secret_key, op_node_derive_public_key_from_private_key, op_node_export_private_key_der, op_node_export_private_key_pem, op_node_export_public_key_der, + op_node_export_public_key_jwk, op_node_export_public_key_pem, op_node_export_secret_key, op_node_export_secret_key_b64url, @@ -32,6 +36,7 @@ import { kHandle } from "ext:deno_node/internal/crypto/constants.ts"; import { isStringOrBuffer } from "ext:deno_node/internal/crypto/cipher.ts"; import { ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS, + ERR_CRYPTO_INVALID_JWK, ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, @@ -56,6 +61,7 @@ import { import { validateObject, validateOneOf, + validateString, } from "ext:deno_node/internal/validators.mjs"; import { BufferEncoding } from "ext:deno_node/_global.d.ts"; @@ -256,6 +262,97 @@ export function getKeyObjectHandle(key: KeyObject, ctx: KeyHandleContext) { return key[kHandle]; } +function getKeyObjectHandleFromJwk(key, ctx) { + validateObject(key, "key"); + validateOneOf( + key.kty, + "key.kty", + ["RSA", "EC", "OKP"], + ); + const isPublic = ctx === kConsumePublic || ctx === kCreatePublic; + + if (key.kty === "OKP") { + validateString(key.crv, "key.crv"); + validateOneOf( + key.crv, + "key.crv", + ["Ed25519", "Ed448", "X25519", "X448"], + ); + validateString(key.x, "key.x"); + + if (!isPublic) { + validateString(key.d, "key.d"); + } + + let keyData; + if (isPublic) { + keyData = Buffer.from(key.x, "base64"); + } else { + keyData = Buffer.from(key.d, "base64"); + } + + switch (key.crv) { + case "Ed25519": + case "X25519": + if (keyData.byteLength !== 32) { + throw new ERR_CRYPTO_INVALID_JWK(); + } + break; + case "Ed448": + if (keyData.byteLength !== 57) { + throw new ERR_CRYPTO_INVALID_JWK(); + } + break; + case "X448": + if (keyData.byteLength !== 56) { + throw new ERR_CRYPTO_INVALID_JWK(); + } + break; + } + + return op_node_create_ed_raw(key.crv, keyData, isPublic); + } + + if (key.kty === "EC") { + validateString(key.crv, "key.crv"); + validateString(key.x, "key.x"); + validateString(key.y, "key.y"); + + if (!isPublic) { + validateString(key.d, "key.d"); + } + + return op_node_create_ec_jwk(key, isPublic); + } + + // RSA + validateString(key.n, "key.n"); + validateString(key.e, "key.e"); + + const jwk = { + kty: key.kty, + n: key.n, + e: key.e, + }; + + if (!isPublic) { + validateString(key.d, "key.d"); + validateString(key.p, "key.p"); + validateString(key.q, "key.q"); + validateString(key.dp, "key.dp"); + validateString(key.dq, "key.dq"); + validateString(key.qi, "key.qi"); + jwk.d = key.d; + jwk.p = key.p; + jwk.q = key.q; + jwk.dp = key.dp; + jwk.dq = key.dq; + jwk.qi = key.qi; + } + + return op_node_create_rsa_jwk(jwk, isPublic); +} + export function prepareAsymmetricKey( key: | string @@ -306,7 +403,12 @@ export function prepareAsymmetricKey( } else if (isCryptoKey(data)) { notImplemented("using CryptoKey as input"); } else if (isJwk(data) && format === "jwk") { - notImplemented("using JWK as input"); + return { + // @ts-ignore __proto__ is magic + __proto__: null, + handle: getKeyObjectHandleFromJwk(data, ctx), + format, + }; } // Either PEM or DER using PKCS#1 or SPKI. if (!isStringOrBuffer(data)) { @@ -711,8 +813,9 @@ export class PublicKeyObject extends AsymmetricKeyObject { export(options: JwkKeyExportOptions | KeyExportOptions) { if (options && options.format === "jwk") { - notImplemented("jwk public key export not implemented"); + return op_node_export_public_key_jwk(this[kHandle]); } + const { format, type, diff --git a/ext/node/polyfills/internal/crypto/sig.ts b/ext/node/polyfills/internal/crypto/sig.ts index bcbcb469b9..a05f16478d 100644 --- a/ext/node/polyfills/internal/crypto/sig.ts +++ b/ext/node/polyfills/internal/crypto/sig.ts @@ -20,7 +20,7 @@ import { } from "ext:deno_node/internal/validators.mjs"; import { Buffer } from "node:buffer"; import type { WritableOptions } from "ext:deno_node/_stream.d.ts"; -import Writable from "ext:deno_node/internal/streams/writable.mjs"; +import Writable from "node:_stream_writable"; import type { BinaryLike, BinaryToTextEncoding, diff --git a/ext/node/polyfills/internal/dns/utils.ts b/ext/node/polyfills/internal/dns/utils.ts index 226fce93dd..1e0c3d9ed6 100644 --- a/ext/node/polyfills/internal/dns/utils.ts +++ b/ext/node/polyfills/internal/dns/utils.ts @@ -416,20 +416,10 @@ export function emitInvalidHostnameWarning(hostname: string) { ); } -let dnsOrder = getOptionValue("--dns-result-order") || "ipv4first"; +let dnsOrder = getOptionValue("--dns-result-order") || "verbatim"; export function getDefaultVerbatim() { - switch (dnsOrder) { - case "verbatim": { - return true; - } - case "ipv4first": { - return false; - } - default: { - return false; - } - } + return dnsOrder !== "ipv4first"; } /** diff --git a/ext/node/polyfills/internal/errors.ts b/ext/node/polyfills/internal/errors.ts index 9ec9f99491..51bd7a0250 100644 --- a/ext/node/polyfills/internal/errors.ts +++ b/ext/node/polyfills/internal/errors.ts @@ -927,6 +927,12 @@ export class ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE extends NodeTypeError { } } +export class ERR_CRYPTO_INVALID_JWK extends NodeError { + constructor() { + super("ERR_CRYPTO_INVALID_JWK", "Invalid JWK"); + } +} + export class ERR_CRYPTO_INVALID_STATE extends NodeError { constructor(x: string) { super("ERR_CRYPTO_INVALID_STATE", `Invalid state for operation ${x}`); @@ -2289,10 +2295,10 @@ export class ERR_HTTP2_INVALID_SETTING_VALUE extends NodeRangeError { } export class ERR_HTTP2_STREAM_CANCEL extends NodeError { override cause?: Error; - constructor(error: Error) { + constructor(error?: Error) { super( "ERR_HTTP2_STREAM_CANCEL", - typeof error.message === "string" + error && typeof error.message === "string" ? `The pending stream has been canceled (caused by: ${error.message})` : "The pending stream has been canceled", ); @@ -2733,6 +2739,7 @@ export default { ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS, ERR_CRYPTO_INVALID_DIGEST, ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, + ERR_CRYPTO_INVALID_JWK, ERR_CRYPTO_INVALID_STATE, ERR_CRYPTO_PBKDF2_ERROR, ERR_CRYPTO_SCRYPT_INVALID_PARAMETER, diff --git a/ext/node/polyfills/internal/events/abort_listener.mjs b/ext/node/polyfills/internal/events/abort_listener.mjs new file mode 100644 index 0000000000..f1430489fa --- /dev/null +++ b/ext/node/polyfills/internal/events/abort_listener.mjs @@ -0,0 +1,44 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// Copyright Joyent, Inc. and Node.js contributors. All rights reserved. MIT license. + +import { primordials } from "ext:deno_node/internal/test/binding.ts"; +const { queueMicrotask } = primordials; +import { SymbolDispose } from "ext:deno_web/00_infra.js"; +import * as abortSignal from "ext:deno_web/03_abort_signal.js"; +import { validateAbortSignal, validateFunction } from "../validators.mjs"; +import { codes } from "../errors.ts"; +const { ERR_INVALID_ARG_TYPE } = codes; + +/** + * @param {AbortSignal} signal + * @param {EventListener} listener + * @returns {Disposable} + */ +function addAbortListener(signal, listener) { + if (signal === undefined) { + throw new ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal); + } + validateAbortSignal(signal, "signal"); + validateFunction(listener, "listener"); + + let removeEventListener; + if (signal.aborted) { + queueMicrotask(() => listener()); + } else { + signal[abortSignal.add](() => { + removeEventListener?.(); + listener(); + }); + removeEventListener = () => { + signal[abortSignal.remove](listener); + }; + } + return { + __proto__: null, + [SymbolDispose]() { + removeEventListener?.(); + }, + }; +} + +export { addAbortListener }; diff --git a/ext/node/polyfills/internal/fs/handle.ts b/ext/node/polyfills/internal/fs/handle.ts index e422e2ba08..fc3a7ae205 100644 --- a/ext/node/polyfills/internal/fs/handle.ts +++ b/ext/node/polyfills/internal/fs/handle.ts @@ -133,12 +133,28 @@ export class FileHandle extends EventEmitter { } } + writeFile(data, options): Promise { + return fsCall(promises.writeFile, this, data, options); + } + close(): Promise { // Note that Deno.close is not async return Promise.resolve(core.close(this.fd)); } } +function fsCall(fn, handle, ...args) { + if (handle.fd === -1) { + const err = new Error("file closed"); + throw Object.assign(err, { + code: "EBADF", + syscall: fn.name, + }); + } + + return fn(handle, ...args); +} + export default { FileHandle, }; diff --git a/ext/node/polyfills/internal/streams/state.mjs b/ext/node/polyfills/internal/streams/state.mjs index 7bedcb3f32..428492306b 100644 --- a/ext/node/polyfills/internal/streams/state.mjs +++ b/ext/node/polyfills/internal/streams/state.mjs @@ -2,9 +2,24 @@ // Copyright Joyent and Node contributors. All rights reserved. MIT license. // deno-lint-ignore-file +// TODO(bartlomieju): this should be 64? +let defaultHighWaterMarkBytes = 16 * 1024; +let defaultHighWaterMarkObjectMode = 16; + function getDefaultHighWaterMark(objectMode) { - return objectMode ? 16 : 16 * 1024; + return objectMode + ? defaultHighWaterMarkObjectMode + : defaultHighWaterMarkBytes; } -export default { getDefaultHighWaterMark }; -export { getDefaultHighWaterMark }; +function setDefaultHighWaterMark(objectMode, value) { + validateInteger(value, "value", 0); + if (objectMode) { + defaultHighWaterMarkObjectMode = value; + } else { + defaultHighWaterMarkBytes = value; + } +} + +export default { getDefaultHighWaterMark, setDefaultHighWaterMark }; +export { getDefaultHighWaterMark, setDefaultHighWaterMark }; diff --git a/ext/node/polyfills/internal/util/comparisons.ts b/ext/node/polyfills/internal/util/comparisons.ts index 65350a8136..39e30c69aa 100644 --- a/ext/node/polyfills/internal/util/comparisons.ts +++ b/ext/node/polyfills/internal/util/comparisons.ts @@ -432,7 +432,7 @@ function isEqualBoxedPrimitive(a: any, b: any): boolean { } // assert.fail(`Unknown boxed type ${val1}`); // return false; - throw Error(`Unknown boxed type`); + throw new Error(`Unknown boxed type`); } function getEnumerables(val: any, keys: any) { diff --git a/ext/node/polyfills/internal/util/debuglog.ts b/ext/node/polyfills/internal/util/debuglog.ts index 9bbaed606f..bbaba7b6fc 100644 --- a/ext/node/polyfills/internal/util/debuglog.ts +++ b/ext/node/polyfills/internal/util/debuglog.ts @@ -30,6 +30,7 @@ export function initializeDebugEnv(debugEnv: string) { // NODE_DEBUG=http or NODE_DEBUG=http2. function emitWarningIfNeeded(set: string) { if ("HTTP" === set || "HTTP2" === set) { + // deno-lint-ignore no-console console.warn( "Setting the NODE_DEBUG environment variable " + "to '" + set.toLowerCase() + "' can expose sensitive " + @@ -50,6 +51,7 @@ function debuglogImpl( emitWarningIfNeeded(set); debugImpls[set] = function debug(...args: unknown[]) { const msg = args.map((arg) => inspect(arg)).join(" "); + // deno-lint-ignore no-console console.error("%s %s: %s", set, String(Deno.pid), msg); }; } else { diff --git a/ext/node/polyfills/internal/util/inspect.mjs b/ext/node/polyfills/internal/util/inspect.mjs index 3a61c387c0..ae797449bf 100644 --- a/ext/node/polyfills/internal/util/inspect.mjs +++ b/ext/node/polyfills/internal/util/inspect.mjs @@ -565,6 +565,19 @@ export function stripVTControlCharacters(str) { export function styleText(format, text) { validateString(text, "text"); + + if (Array.isArray(format)) { + for (let i = 0; i < format.length; i++) { + const item = format[i]; + const formatCodes = inspect.colors[item]; + if (formatCodes == null) { + validateOneOf(item, "format", Object.keys(inspect.colors)); + } + text = `\u001b[${formatCodes[0]}m${text}\u001b[${formatCodes[1]}m`; + } + return text; + } + const formatCodes = inspect.colors[format]; if (formatCodes == null) { validateOneOf(format, "format", Object.keys(inspect.colors)); diff --git a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts index ff141fdbfc..559b7685b8 100644 --- a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts +++ b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts @@ -5,10 +5,11 @@ import { Buffer } from "node:buffer"; -function assert(cond) { - if (!cond) { - throw new Error("assertion failed"); +function toDataView(ab: ArrayBufferLike | ArrayBufferView): DataView { + if (ArrayBuffer.isView(ab)) { + return new DataView(ab.buffer, ab.byteOffset, ab.byteLength); } + return new DataView(ab); } /** Compare to array buffers or data views in a way that timing based attacks @@ -21,13 +22,11 @@ function stdTimingSafeEqual( return false; } if (!(a instanceof DataView)) { - a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a); + a = toDataView(a); } if (!(b instanceof DataView)) { - b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b); + b = toDataView(b); } - assert(a instanceof DataView); - assert(b instanceof DataView); const length = a.byteLength; let out = 0; let i = -1; @@ -41,7 +40,11 @@ export const timingSafeEqual = ( a: Buffer | DataView | ArrayBuffer, b: Buffer | DataView | ArrayBuffer, ): boolean => { - if (a instanceof Buffer) a = new DataView(a.buffer); - if (a instanceof Buffer) b = new DataView(a.buffer); + if (a instanceof Buffer) { + a = new DataView(a.buffer, a.byteOffset, a.byteLength); + } + if (b instanceof Buffer) { + b = new DataView(b.buffer, b.byteOffset, b.byteLength); + } return stdTimingSafeEqual(a, b); }; diff --git a/ext/node/polyfills/internal_binding/cares_wrap.ts b/ext/node/polyfills/internal_binding/cares_wrap.ts index ee8d19befb..cbfea40b22 100644 --- a/ext/node/polyfills/internal_binding/cares_wrap.ts +++ b/ext/node/polyfills/internal_binding/cares_wrap.ts @@ -75,11 +75,18 @@ export function getaddrinfo( const recordTypes: ("A" | "AAAA")[] = []; - if (family === 0 || family === 4) { - recordTypes.push("A"); - } - if (family === 0 || family === 6) { + if (family === 6) { recordTypes.push("AAAA"); + } else if (family === 4) { + recordTypes.push("A"); + } else if (family === 0 && hostname === "localhost") { + // Ipv6 is preferred over Ipv4 for localhost + recordTypes.push("AAAA"); + recordTypes.push("A"); + } else if (family === 0) { + // Only get Ipv4 addresses for the other hostnames + // This simulates what `getaddrinfo` does when the family is not specified + recordTypes.push("A"); } (async () => { @@ -270,7 +277,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { ); }), this.#query(name, "CAA").then(({ ret }) => { - (ret as Deno.CAARecord[]).forEach(({ critical, tag, value }) => + (ret as Deno.CaaRecord[]).forEach(({ critical, tag, value }) => records.push({ type: "CAA", [tag]: value, @@ -284,7 +291,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { ); }), this.#query(name, "MX").then(({ ret }) => { - (ret as Deno.MXRecord[]).forEach(({ preference, exchange }) => + (ret as Deno.MxRecord[]).forEach(({ preference, exchange }) => records.push({ type: "MX", priority: preference, @@ -293,7 +300,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { ); }), this.#query(name, "NAPTR").then(({ ret }) => { - (ret as Deno.NAPTRRecord[]).forEach( + (ret as Deno.NaptrRecord[]).forEach( ({ order, preference, flags, services, regexp, replacement }) => records.push({ type: "NAPTR", @@ -317,7 +324,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { ); }), this.#query(name, "SOA").then(({ ret }) => { - (ret as Deno.SOARecord[]).forEach( + (ret as Deno.SoaRecord[]).forEach( ({ mname, rname, serial, refresh, retry, expire, minimum }) => records.push({ type: "SOA", @@ -332,7 +339,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { ); }), this.#query(name, "SRV").then(({ ret }) => { - (ret as Deno.SRVRecord[]).forEach( + (ret as Deno.SrvRecord[]).forEach( ({ priority, weight, port, target }) => records.push({ type: "SRV", @@ -378,7 +385,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { queryCaa(req: QueryReqWrap, name: string): number { this.#query(name, "CAA").then(({ code, ret }) => { - const records = (ret as Deno.CAARecord[]).map( + const records = (ret as Deno.CaaRecord[]).map( ({ critical, tag, value }) => ({ [tag]: value, critical: +critical && 128, @@ -401,7 +408,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { queryMx(req: QueryReqWrap, name: string): number { this.#query(name, "MX").then(({ code, ret }) => { - const records = (ret as Deno.MXRecord[]).map( + const records = (ret as Deno.MxRecord[]).map( ({ preference, exchange }) => ({ priority: preference, exchange: fqdnToHostname(exchange), @@ -416,7 +423,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { queryNaptr(req: QueryReqWrap, name: string): number { this.#query(name, "NAPTR").then(({ code, ret }) => { - const records = (ret as Deno.NAPTRRecord[]).map( + const records = (ret as Deno.NaptrRecord[]).map( ({ order, preference, flags, services, regexp, replacement }) => ({ flags, service: services, @@ -459,7 +466,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { if (ret.length) { const { mname, rname, serial, refresh, retry, expire, minimum } = - ret[0] as Deno.SOARecord; + ret[0] as Deno.SoaRecord; record = { nsname: fqdnToHostname(mname), @@ -480,7 +487,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery { querySrv(req: QueryReqWrap, name: string): number { this.#query(name, "SRV").then(({ code, ret }) => { - const records = (ret as Deno.SRVRecord[]).map( + const records = (ret as Deno.SrvRecord[]).map( ({ priority, weight, port, target }) => ({ priority, weight, diff --git a/ext/node/polyfills/internal_binding/http_parser.ts b/ext/node/polyfills/internal_binding/http_parser.ts new file mode 100644 index 0000000000..ca4f896e20 --- /dev/null +++ b/ext/node/polyfills/internal_binding/http_parser.ts @@ -0,0 +1,159 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// 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. + +import { primordials } from "ext:core/mod.js"; +import { AsyncWrap } from "ext:deno_node/internal_binding/async_wrap.ts"; + +const { + ObjectDefineProperty, + ObjectEntries, + ObjectSetPrototypeOf, + SafeArrayIterator, +} = primordials; + +export const methods = [ + "DELETE", + "GET", + "HEAD", + "POST", + "PUT", + "CONNECT", + "OPTIONS", + "TRACE", + "COPY", + "LOCK", + "MKCOL", + "MOVE", + "PROPFIND", + "PROPPATCH", + "SEARCH", + "UNLOCK", + "BIND", + "REBIND", + "UNBIND", + "ACL", + "REPORT", + "MKACTIVITY", + "CHECKOUT", + "MERGE", + "M-SEARCH", + "NOTIFY", + "SUBSCRIBE", + "UNSUBSCRIBE", + "PATCH", + "PURGE", + "MKCALENDAR", + "LINK", + "UNLINK", + "SOURCE", + "QUERY", +]; + +export const allMethods = [ + "DELETE", + "GET", + "HEAD", + "POST", + "PUT", + "CONNECT", + "OPTIONS", + "TRACE", + "COPY", + "LOCK", + "MKCOL", + "MOVE", + "PROPFIND", + "PROPPATCH", + "SEARCH", + "UNLOCK", + "BIND", + "REBIND", + "UNBIND", + "ACL", + "REPORT", + "MKACTIVITY", + "CHECKOUT", + "MERGE", + "M-SEARCH", + "NOTIFY", + "SUBSCRIBE", + "UNSUBSCRIBE", + "PATCH", + "PURGE", + "MKCALENDAR", + "LINK", + "UNLINK", + "SOURCE", + "PRI", + "DESCRIBE", + "ANNOUNCE", + "SETUP", + "PLAY", + "PAUSE", + "TEARDOWN", + "GET_PARAMETER", + "SET_PARAMETER", + "REDIRECT", + "RECORD", + "FLUSH", + "QUERY", +]; + +export function HTTPParser() { +} + +ObjectSetPrototypeOf(HTTPParser.prototype, AsyncWrap.prototype); + +function defineProps(obj: object, props: Record) { + for (const entry of new SafeArrayIterator(ObjectEntries(props))) { + ObjectDefineProperty(obj, entry[0], { + value: entry[1], + enumerable: true, + writable: true, + configurable: true, + }); + } +} + +defineProps(HTTPParser, { + REQUEST: 1, + RESPONSE: 2, + kOnMessageBegin: 0, + kOnHeaders: 1, + kOnHeadersComplete: 2, + kOnBody: 3, + kOnMessageComplete: 4, + kOnExecute: 5, + kOnTimeout: 6, + kLenientNone: 0, + kLenientHeaders: 1, + kLenientChunkedLength: 2, + kLenientKeepAlive: 4, + kLenientTransferEncoding: 8, + kLenientVersion: 16, + kLenientDataAfterClose: 32, + kLenientOptionalLFAfterCR: 64, + kLenientOptionalCRLFAfterChunk: 128, + kLenientOptionalCRBeforeLF: 256, + kLenientSpacesAfterChunkSize: 512, + kLenientAll: 1023, +}); diff --git a/ext/node/polyfills/internal_binding/mod.ts b/ext/node/polyfills/internal_binding/mod.ts index f2d7f55bc7..ebbfc629f1 100644 --- a/ext/node/polyfills/internal_binding/mod.ts +++ b/ext/node/polyfills/internal_binding/mod.ts @@ -17,6 +17,7 @@ import * as types from "ext:deno_node/internal_binding/types.ts"; import * as udpWrap from "ext:deno_node/internal_binding/udp_wrap.ts"; import * as util from "ext:deno_node/internal_binding/util.ts"; import * as uv from "ext:deno_node/internal_binding/uv.ts"; +import * as httpParser from "ext:deno_node/internal_binding/http_parser.ts"; const modules = { "async_wrap": asyncWrap, @@ -32,7 +33,7 @@ const modules = { "fs_dir": {}, "fs_event_wrap": {}, "heap_utils": {}, - "http_parser": {}, + "http_parser": httpParser, icu: {}, inspector: {}, "js_stream": {}, diff --git a/ext/node/polyfills/internal_binding/node_file.ts b/ext/node/polyfills/internal_binding/node_file.ts index c7b0bb7e6e..6c134ec4bc 100644 --- a/ext/node/polyfills/internal_binding/node_file.ts +++ b/ext/node/polyfills/internal_binding/node_file.ts @@ -30,7 +30,7 @@ import { assert } from "ext:deno_node/_util/asserts.ts"; import * as io from "ext:deno_io/12_io.js"; -import * as fs from "ext:deno_fs/30_fs.js"; +import { op_fs_seek_sync } from "ext:core/ops"; /** * Write to the given file from the given buffer synchronously. @@ -63,7 +63,7 @@ export function writeBuffer( ); if (position) { - fs.seekSync(fd, position, io.SeekMode.Current); + op_fs_seek_sync(fd, position, io.SeekMode.Current); } const subarray = buffer.subarray(offset, offset + length); diff --git a/ext/node/polyfills/internal_binding/pipe_wrap.ts b/ext/node/polyfills/internal_binding/pipe_wrap.ts index f5c3c54396..3e366b3c76 100644 --- a/ext/node/polyfills/internal_binding/pipe_wrap.ts +++ b/ext/node/polyfills/internal_binding/pipe_wrap.ts @@ -160,16 +160,8 @@ export class Pipe extends ConnectionWrap { } }, (e) => { - // TODO(cmorten): correct mapping of connection error to status code. - let code: number; - - if (e instanceof Deno.errors.NotFound) { - code = codeMap.get("ENOENT")!; - } else if (e instanceof Deno.errors.PermissionDenied) { - code = codeMap.get("EACCES")!; - } else { - code = codeMap.get("ECONNREFUSED")!; - } + const code = codeMap.get(e.code ?? "UNKNOWN") ?? + codeMap.get("UNKNOWN")!; try { this.afterConnect(req, code); @@ -207,16 +199,10 @@ export class Pipe extends ConnectionWrap { try { listener = Deno.listen(listenOptions); } catch (e) { - if (e instanceof Deno.errors.AddrInUse) { - return codeMap.get("EADDRINUSE")!; - } else if (e instanceof Deno.errors.AddrNotAvailable) { - return codeMap.get("EADDRNOTAVAIL")!; - } else if (e instanceof Deno.errors.PermissionDenied) { + if (e instanceof Deno.errors.NotCapable) { throw e; } - - // TODO(cmorten): map errors to appropriate error codes. - return codeMap.get("UNKNOWN")!; + return codeMap.get(e.code ?? "UNKNOWN") ?? codeMap.get("UNKNOWN")!; } const address = listener.addr as Deno.UnixAddr; diff --git a/ext/node/polyfills/internal_binding/stream_wrap.ts b/ext/node/polyfills/internal_binding/stream_wrap.ts index dc30bfdfe0..7aea83d6f5 100644 --- a/ext/node/polyfills/internal_binding/stream_wrap.ts +++ b/ext/node/polyfills/internal_binding/stream_wrap.ts @@ -38,6 +38,7 @@ import { TextEncoder } from "ext:deno_web/08_text_encoding.js"; import { Buffer } from "node:buffer"; import { notImplemented } from "ext:deno_node/_utils.ts"; import { HandleWrap } from "ext:deno_node/internal_binding/handle_wrap.ts"; +import { ownerSymbol } from "ext:deno_node/internal/async_hooks.ts"; import { AsyncWrap, providerType, @@ -343,7 +344,8 @@ export class LibuvStreamWrap extends HandleWrap { ) { nread = codeMap.get("ECONNRESET")!; } else { - nread = codeMap.get("UNKNOWN")!; + this[ownerSymbol].destroy(e); + return; } } diff --git a/ext/node/polyfills/internal_binding/tcp_wrap.ts b/ext/node/polyfills/internal_binding/tcp_wrap.ts index 9897bccd06..d9f1c5356a 100644 --- a/ext/node/polyfills/internal_binding/tcp_wrap.ts +++ b/ext/node/polyfills/internal_binding/tcp_wrap.ts @@ -45,6 +45,7 @@ import { INITIAL_ACCEPT_BACKOFF_DELAY, MAX_ACCEPT_BACKOFF_DELAY, } from "ext:deno_node/internal_binding/_listen.ts"; +import { nextTick } from "ext:deno_node/_next_tick.ts"; /** The type of TCP socket. */ enum socketType { @@ -211,16 +212,10 @@ export class TCP extends ConnectionWrap { try { listener = Deno.listen(listenOptions); } catch (e) { - if (e instanceof Deno.errors.AddrInUse) { - return codeMap.get("EADDRINUSE")!; - } else if (e instanceof Deno.errors.AddrNotAvailable) { - return codeMap.get("EADDRNOTAVAIL")!; - } else if (e instanceof Deno.errors.PermissionDenied) { + if (e instanceof Deno.errors.NotCapable) { throw e; } - - // TODO(cmorten): map errors to appropriate error codes. - return codeMap.get("UNKNOWN")!; + return codeMap.get(e.code ?? "UNKNOWN") ?? codeMap.get("UNKNOWN")!; } const address = listener.addr as Deno.NetAddr; @@ -228,7 +223,14 @@ export class TCP extends ConnectionWrap { this.#port = address.port; this.#listener = listener; - this.#accept(); + + // TODO(kt3k): Delays the accept() call 2 ticks. Deno.Listener can't be closed + // synchronously when accept() is called. By delaying the accept() call, + // the user can close the server synchronously in the callback of listen(). + // This workaround enables `npm:detect-port` to work correctly. + // Remove these nextTick calls when the below issue resolved: + // https://github.com/denoland/deno/issues/25480 + nextTick(nextTick, () => this.#accept()); return 0; } @@ -297,8 +299,10 @@ export class TCP extends ConnectionWrap { * @param noDelay * @return An error status code. */ - setNoDelay(_noDelay: boolean): number { - // TODO(bnoordhuis) https://github.com/denoland/deno/pull/13103 + setNoDelay(noDelay: boolean): number { + if (this[kStreamBaseField] && "setNoDelay" in this[kStreamBaseField]) { + this[kStreamBaseField].setNoDelay(noDelay); + } return 0; } diff --git a/ext/node/polyfills/internal_binding/udp_wrap.ts b/ext/node/polyfills/internal_binding/udp_wrap.ts index 7cbd6cabe3..db6961ddb7 100644 --- a/ext/node/polyfills/internal_binding/udp_wrap.ts +++ b/ext/node/polyfills/internal_binding/udp_wrap.ts @@ -337,16 +337,10 @@ export class UDP extends HandleWrap { try { listener = DenoListenDatagram(listenOptions); } catch (e) { - if (e instanceof Deno.errors.AddrInUse) { - return codeMap.get("EADDRINUSE")!; - } else if (e instanceof Deno.errors.AddrNotAvailable) { - return codeMap.get("EADDRNOTAVAIL")!; - } else if (e instanceof Deno.errors.PermissionDenied) { + if (e instanceof Deno.errors.NotCapable) { throw e; } - - // TODO(cmorten): map errors to appropriate error codes. - return codeMap.get("UNKNOWN")!; + return codeMap.get(e.code ?? "UNKNOWN") ?? codeMap.get("UNKNOWN")!; } const address = listener.addr as Deno.NetAddr; diff --git a/ext/node/polyfills/net.ts b/ext/node/polyfills/net.ts index 6625ce7b50..35d273be93 100644 --- a/ext/node/polyfills/net.ts +++ b/ext/node/polyfills/net.ts @@ -951,7 +951,6 @@ export class Socket extends Duplex { */ override pause(): this { if ( - this[kBuffer] && !this.connecting && this._handle && this._handle.reading @@ -1872,23 +1871,13 @@ function _setupListenHandle( // Try to bind to the unspecified IPv6 address, see if IPv6 is available if (!address && typeof fd !== "number") { - // TODO(@bartlomieju): differs from Node which tries to bind to IPv6 first - // when no address is provided. - // - // Forcing IPv4 as a workaround for Deno not aligning with Node on - // implicit binding on Windows. - // - // REF: https://github.com/denoland/deno/issues/10762 - // rval = _createServerHandle(DEFAULT_IPV6_ADDR, port, 6, fd, flags); - - // if (typeof rval === "number") { - // rval = null; - address = DEFAULT_IPV4_ADDR; - addressType = 4; - // } else { - // address = DEFAULT_IPV6_ADDR; - // addressType = 6; - // } + if (isWindows) { + address = DEFAULT_IPV4_ADDR; + addressType = 4; + } else { + address = DEFAULT_IPV6_ADDR; + addressType = 6; + } } if (rval === null) { diff --git a/ext/node/polyfills/os.ts b/ext/node/polyfills/os.ts index 1cd466ec21..e47e8679ec 100644 --- a/ext/node/polyfills/os.ts +++ b/ext/node/polyfills/os.ts @@ -311,7 +311,7 @@ export function type(): string { case "openbsd": return "OpenBSD"; default: - throw Error("unreachable"); + throw new Error("unreachable"); } } diff --git a/ext/node/polyfills/path/_posix.ts b/ext/node/polyfills/path/_posix.ts index 555b7dc6d9..bf0b91d488 100644 --- a/ext/node/polyfills/path/_posix.ts +++ b/ext/node/polyfills/path/_posix.ts @@ -478,6 +478,9 @@ export function parse(path: string): ParsedPath { return ret; } + +export const _makeLong = toNamespacedPath; + export default { basename, delimiter, @@ -492,4 +495,5 @@ export default { resolve, sep, toNamespacedPath, + _makeLong, }; diff --git a/ext/node/polyfills/path/_win32.ts b/ext/node/polyfills/path/_win32.ts index b8fe241bbf..11c82e0eee 100644 --- a/ext/node/polyfills/path/_win32.ts +++ b/ext/node/polyfills/path/_win32.ts @@ -953,6 +953,8 @@ export function parse(path: string): ParsedPath { return ret; } +export const _makeLong = toNamespacedPath; + export default { basename, delimiter, @@ -967,4 +969,5 @@ export default { resolve, sep, toNamespacedPath, + _makeLong, }; diff --git a/ext/node/polyfills/path/mod.ts b/ext/node/polyfills/path/mod.ts index 56d21d2e0b..e74c1da4db 100644 --- a/ext/node/polyfills/path/mod.ts +++ b/ext/node/polyfills/path/mod.ts @@ -36,6 +36,7 @@ export const { resolve, sep, toNamespacedPath, + _makeLong, } = path; export default path; export * from "ext:deno_node/path/common.ts"; diff --git a/ext/node/polyfills/path/posix.ts b/ext/node/polyfills/path/posix.ts index 8e95ba124c..2b6582ff6d 100644 --- a/ext/node/polyfills/path/posix.ts +++ b/ext/node/polyfills/path/posix.ts @@ -18,6 +18,9 @@ export const { resolve, sep, toNamespacedPath, + _makeLong, } = path.posix; +export const posix = path.posix; +export const win32 = path.win32; export default path.posix; diff --git a/ext/node/polyfills/path/win32.ts b/ext/node/polyfills/path/win32.ts index 06806e81b6..02e6f97c5a 100644 --- a/ext/node/polyfills/path/win32.ts +++ b/ext/node/polyfills/path/win32.ts @@ -18,6 +18,9 @@ export const { resolve, sep, toNamespacedPath, + _makeLong, } = path.win32; +export const posix = path.posix; +export const win32 = path.win32; export default path.win32; diff --git a/ext/node/polyfills/process.ts b/ext/node/polyfills/process.ts index 8d54429354..2605fa6d1a 100644 --- a/ext/node/polyfills/process.ts +++ b/ext/node/polyfills/process.ts @@ -69,6 +69,7 @@ import * as constants from "ext:deno_node/internal_binding/constants.ts"; import * as uv from "ext:deno_node/internal_binding/uv.ts"; import type { BindingName } from "ext:deno_node/internal_binding/mod.ts"; import { buildAllowedFlags } from "ext:deno_node/internal/process/per_thread.mjs"; +import { setProcess } from "ext:deno_node/_events.mjs"; const notImplementedEvents = [ "multipleResolves", @@ -81,6 +82,8 @@ export const argv: string[] = ["", ""]; // And retains any value as long as it's nullish or number-ish. let ProcessExitCode: undefined | null | string | number; +export const execArgv: string[] = []; + /** https://nodejs.org/api/process.html#process_process_exit_code */ export const exit = (code?: number | string) => { if (code || code === 0) { @@ -264,9 +267,11 @@ memoryUsage.rss = function (): number { // Returns a negative error code than can be recognized by errnoException function _kill(pid: number, sig: number): number { + const maybeMapErrno = (res: number) => + res === 0 ? res : uv.mapSysErrnoToUvErrno(res); // signal 0 does not exist in constants.os.signals, thats why it have to be handled explicitly if (sig === 0) { - return op_node_process_kill(pid, 0); + return maybeMapErrno(op_node_process_kill(pid, 0)); } const maybeSignal = Object.entries(constants.os.signals).find(( [_, numericCode], @@ -275,7 +280,7 @@ function _kill(pid: number, sig: number): number { if (!maybeSignal) { return uv.codeMap.get("EINVAL"); } - return op_node_process_kill(pid, sig); + return maybeMapErrno(op_node_process_kill(pid, sig)); } export function dlopen(module, filename, _flags) { @@ -336,7 +341,20 @@ function uncaughtExceptionHandler(err: any, origin: string) { process.emit("uncaughtException", err, origin); } -let execPath: string | null = null; +export let execPath: string = Object.freeze({ + __proto__: String.prototype, + toString() { + execPath = Deno.execPath(); + return execPath; + }, + get length() { + return this.toString().length; + }, + [Symbol.for("Deno.customInspect")](inspect, options) { + return inspect(this.toString(), options); + }, + // deno-lint-ignore no-explicit-any +}) as any as string; // The process class needs to be an ES5 class because it can be instantiated // in Node without the `new` keyword. It's not a true class in Node. Popular @@ -414,6 +432,14 @@ Process.prototype.config = { }, }; +Process.prototype.cpuUsage = function () { + warnNotImplemented("process.cpuUsage()"); + return { + user: 0, + system: 0, + }; +}; + /** https://nodejs.org/api/process.html#process_process_cwd */ Process.prototype.cwd = cwd; @@ -424,7 +450,7 @@ Process.prototype.cwd = cwd; Process.prototype.env = env; /** https://nodejs.org/api/process.html#process_process_execargv */ -Process.prototype.execArgv = []; +Process.prototype.execArgv = execArgv; /** https://nodejs.org/api/process.html#process_process_exit_code */ Process.prototype.exit = exit; @@ -491,6 +517,10 @@ Process.prototype.on = function ( // Ignores SIGBREAK if the platform is not windows. } else if (event === "SIGTERM" && Deno.build.os === "windows") { // Ignores SIGTERM on windows. + } else if ( + event !== "SIGBREAK" && event !== "SIGINT" && Deno.build.os === "windows" + ) { + // TODO(#26331): Ignores all signals except SIGBREAK and SIGINT on windows. } else { EventEmitter.prototype.on.call(this, event, listener); Deno.addSignalListener(event as Deno.Signal, listener); @@ -515,8 +545,10 @@ Process.prototype.off = function ( } else if (event.startsWith("SIG")) { if (event === "SIGBREAK" && Deno.build.os !== "windows") { // Ignores SIGBREAK if the platform is not windows. - } else if (event === "SIGTERM" && Deno.build.os === "windows") { - // Ignores SIGTERM on windows. + } else if ( + event !== "SIGBREAK" && event !== "SIGINT" && Deno.build.os === "windows" + ) { + // Ignores all signals except SIGBREAK and SIGINT on windows. } else { EventEmitter.prototype.off.call(this, event, listener); Deno.removeSignalListener(event as Deno.Signal, listener); @@ -703,11 +735,7 @@ Process.prototype._eval = undefined; Object.defineProperty(Process.prototype, "execPath", { get() { - if (execPath) { - return execPath; - } - execPath = Deno.execPath(); - return execPath; + return String(execPath); }, set(path: string) { execPath = path; @@ -726,6 +754,8 @@ Object.defineProperty(Process.prototype, "allowedNodeEnvironmentFlags", { }, }); +export const allowedNodeEnvironmentFlags = ALLOWED_FLAGS; + Process.prototype.features = { inspector: false }; // TODO(kt3k): Get the value from --no-deprecation flag. @@ -960,4 +990,6 @@ internals.__bootstrapNodeProcess = function ( } }; +setProcess(process); + export default process; diff --git a/ext/node/polyfills/punycode.ts b/ext/node/polyfills/punycode.ts index e89be15a22..adecdf4f9a 100644 --- a/ext/node/polyfills/punycode.ts +++ b/ext/node/polyfills/punycode.ts @@ -11,6 +11,8 @@ import { deprecate } from "node:util"; import { ucs2 } from "ext:deno_node/internal/idna.ts"; +const version = "2.1.0"; + // deno-lint-ignore no-explicit-any function punyDeprecated(fn: any) { return deprecate( @@ -37,7 +39,7 @@ function encode(domain) { return punyDeprecated(op_node_idna_punycode_encode)(domain); } -export { decode, encode, toASCII, toUnicode, ucs2 }; +export { decode, encode, toASCII, toUnicode, ucs2, version }; export default { decode, @@ -45,4 +47,5 @@ export default { toASCII, toUnicode, ucs2, + version, }; diff --git a/ext/node/polyfills/repl.ts b/ext/node/polyfills/repl.ts index 70fe52ce4f..a7acc5b19a 100644 --- a/ext/node/polyfills/repl.ts +++ b/ext/node/polyfills/repl.ts @@ -1,7 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright Joyent and Node contributors. All rights reserved. MIT license. +import { primordials } from "ext:core/mod.js"; import { notImplemented } from "ext:deno_node/_utils.ts"; +const { Symbol } = primordials; + +export const REPL_MODE_SLOPPY = Symbol("repl-sloppy"); +export const REPL_MODE_STRICT = Symbol("repl-strict"); export class REPLServer { constructor() { @@ -61,4 +66,6 @@ export default { builtinModules, _builtinLibs, start, + REPL_MODE_SLOPPY, + REPL_MODE_STRICT, }; diff --git a/ext/node/polyfills/stream.ts b/ext/node/polyfills/stream.ts index 42f83fa289..96262428f0 100644 --- a/ext/node/polyfills/stream.ts +++ b/ext/node/polyfills/stream.ts @@ -4,14 +4,19 @@ // @deno-types="./_stream.d.ts" import { + _isArrayBufferView, _isUint8Array, _uint8ArrayToBuffer, addAbortSignal, - // compose, - // destroy, + compose, + destroy, Duplex, finished, - // isDisturbed, + isDestroyed, + isDisturbed, + isErrored, + isReadable, + isWritable, PassThrough, pipeline, Readable, @@ -19,16 +24,30 @@ import { Transform, Writable, } from "ext:deno_node/_stream.mjs"; +import { + getDefaultHighWaterMark, + setDefaultHighWaterMark, +} from "ext:deno_node/internal/streams/state.mjs"; export { + _isArrayBufferView, _isUint8Array, _uint8ArrayToBuffer, addAbortSignal, + compose, + destroy, Duplex, finished, + getDefaultHighWaterMark, + isDestroyed, + isDisturbed, + isErrored, + isReadable, + isWritable, PassThrough, pipeline, Readable, + setDefaultHighWaterMark, Stream, Transform, Writable, diff --git a/ext/node/polyfills/stream/web.ts b/ext/node/polyfills/stream/web.ts index 5c6127ca6c..9cb361f862 100644 --- a/ext/node/polyfills/stream/web.ts +++ b/ext/node/polyfills/stream/web.ts @@ -19,10 +19,16 @@ import { TextDecoderStream, TextEncoderStream, } from "ext:deno_web/08_text_encoding.js"; +import { + CompressionStream, + DecompressionStream, +} from "ext:deno_web/14_compression.js"; export { ByteLengthQueuingStrategy, + CompressionStream, CountQueuingStrategy, + DecompressionStream, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, @@ -39,19 +45,21 @@ export { }; export default { + ByteLengthQueuingStrategy, + CompressionStream, + CountQueuingStrategy, + DecompressionStream, + ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, - ReadableStreamDefaultReader, - ReadableByteStreamController, ReadableStreamDefaultController, + ReadableStreamDefaultReader, + TextDecoderStream, + TextEncoderStream, TransformStream, TransformStreamDefaultController, WritableStream, - WritableStreamDefaultWriter, WritableStreamDefaultController, - ByteLengthQueuingStrategy, - CountQueuingStrategy, - TextEncoderStream, - TextDecoderStream, + WritableStreamDefaultWriter, }; diff --git a/ext/node/polyfills/string_decoder.ts b/ext/node/polyfills/string_decoder.ts index 4a49c2e3e6..b4a422e4b6 100644 --- a/ext/node/polyfills/string_decoder.ts +++ b/ext/node/polyfills/string_decoder.ts @@ -403,6 +403,7 @@ StringDecoder.prototype.text = function text( ObjectDefineProperties(StringDecoder.prototype, { lastNeed: { + __proto__: null, configurable: true, enumerable: true, get(this: StringDecoder): number { @@ -410,6 +411,7 @@ ObjectDefineProperties(StringDecoder.prototype, { }, }, lastTotal: { + __proto__: null, configurable: true, enumerable: true, get(this: StringDecoder): number { diff --git a/ext/node/polyfills/testing.ts b/ext/node/polyfills/testing.ts index 92900e6323..901c38ed36 100644 --- a/ext/node/polyfills/testing.ts +++ b/ext/node/polyfills/testing.ts @@ -28,6 +28,7 @@ class NodeTestContext { } diagnostic(message) { + // deno-lint-ignore no-console console.log("DIAGNOSTIC:", message); } diff --git a/ext/node/polyfills/timers.ts b/ext/node/polyfills/timers.ts index b96f448da4..02f69466ee 100644 --- a/ext/node/polyfills/timers.ts +++ b/ext/node/polyfills/timers.ts @@ -33,6 +33,7 @@ export function setTimeout( } ObjectDefineProperty(setTimeout, promisify.custom, { + __proto__: null, value: (timeout: number, ...args: unknown[]) => { return new Promise((cb) => setTimeout(cb, timeout, ...new SafeArrayIterator(args)) @@ -88,6 +89,22 @@ export function clearImmediate(immediate: Immediate) { clearTimeout_(immediate._immediateId); } +export const promises = { + setTimeout: promisify(setTimeout), + setImmediate: promisify(setImmediate), + setInterval: promisify(setInterval), +}; + +promises.scheduler = { + async wait( + delay: number, + options?: { signal?: AbortSignal }, + ): Promise { + return await promises.setTimeout(delay, undefined, options); + }, + yield: promises.setImmediate, +}; + export default { setTimeout, clearTimeout, @@ -96,4 +113,5 @@ export default { setImmediate, setUnrefTimeout, clearImmediate, + promises, }; diff --git a/ext/node/polyfills/timers/promises.ts b/ext/node/polyfills/timers/promises.ts index 2ab2384dc2..b2896fe809 100644 --- a/ext/node/polyfills/timers/promises.ts +++ b/ext/node/polyfills/timers/promises.ts @@ -1,20 +1,15 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { promisify } from "node:util"; import timers from "node:timers"; -export const setTimeout = promisify(timers.setTimeout), - setImmediate = promisify(timers.setImmediate), - setInterval = promisify(timers.setInterval); +export const setTimeout = timers.promises.setTimeout; +export const setImmediate = timers.promises.setImmediate; +export const setInterval = timers.promises.setInterval; -export const scheduler = { - async wait(delay: number, options?: { signal?: AbortSignal }): Promise { - return await setTimeout(delay, undefined, options); - }, - yield: setImmediate, -}; +export const scheduler = timers.promises.scheduler; export default { setTimeout, setImmediate, setInterval, + scheduler, }; diff --git a/ext/node/polyfills/tls.ts b/ext/node/polyfills/tls.ts index 6db2bc68c2..4cfe9ebd63 100644 --- a/ext/node/polyfills/tls.ts +++ b/ext/node/polyfills/tls.ts @@ -5,8 +5,12 @@ // deno-lint-ignore-file prefer-primordials import { notImplemented } from "ext:deno_node/_utils.ts"; -import tlsCommon from "ext:deno_node/_tls_common.ts"; -import tlsWrap from "ext:deno_node/_tls_wrap.ts"; +import tlsCommon from "node:_tls_common"; +import tlsWrap from "node:_tls_wrap"; +import { op_get_root_certificates } from "ext:core/ops"; +import { primordials } from "ext:core/mod.js"; + +const { ObjectFreeze } = primordials; // openssl -> rustls const cipherMap = { @@ -30,10 +34,63 @@ export function getCiphers() { return Object.keys(cipherMap).map((name) => name.toLowerCase()); } -export const rootCertificates = undefined; +let lazyRootCertificates: string[] | null = null; +function ensureLazyRootCertificates(target: string[]) { + if (lazyRootCertificates === null) { + lazyRootCertificates = op_get_root_certificates() as string[]; + lazyRootCertificates.forEach((v) => target.push(v)); + ObjectFreeze(target); + } +} +export const rootCertificates = new Proxy([] as string[], { + // @ts-ignore __proto__ is not in the types + __proto__: null, + get(target, prop) { + ensureLazyRootCertificates(target); + return Reflect.get(target, prop); + }, + ownKeys(target) { + ensureLazyRootCertificates(target); + return Reflect.ownKeys(target); + }, + has(target, prop) { + ensureLazyRootCertificates(target); + return Reflect.has(target, prop); + }, + getOwnPropertyDescriptor(target, prop) { + ensureLazyRootCertificates(target); + return Reflect.getOwnPropertyDescriptor(target, prop); + }, + set(target, prop, value) { + ensureLazyRootCertificates(target); + return Reflect.set(target, prop, value); + }, + defineProperty(target, prop, descriptor) { + ensureLazyRootCertificates(target); + return Reflect.defineProperty(target, prop, descriptor); + }, + deleteProperty(target, prop) { + ensureLazyRootCertificates(target); + return Reflect.deleteProperty(target, prop); + }, + isExtensible(target) { + ensureLazyRootCertificates(target); + return Reflect.isExtensible(target); + }, + preventExtensions(target) { + ensureLazyRootCertificates(target); + return Reflect.preventExtensions(target); + }, + setPrototypeOf() { + return false; + }, +}); + export const DEFAULT_ECDH_CURVE = "auto"; export const DEFAULT_MAX_VERSION = "TLSv1.3"; export const DEFAULT_MIN_VERSION = "TLSv1.2"; +export const CLIENT_RENEG_LIMIT = 3; +export const CLIENT_RENEG_WINDOW = 600; export class CryptoStream {} export class SecurePair {} @@ -58,6 +115,8 @@ export default { DEFAULT_ECDH_CURVE, DEFAULT_MAX_VERSION, DEFAULT_MIN_VERSION, + CLIENT_RENEG_LIMIT, + CLIENT_RENEG_WINDOW, }; export const checkServerIdentity = tlsWrap.checkServerIdentity; diff --git a/ext/node/polyfills/trace_events.ts b/ext/node/polyfills/trace_events.ts new file mode 100644 index 0000000000..bb3ea97459 --- /dev/null +++ b/ext/node/polyfills/trace_events.ts @@ -0,0 +1,27 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; + +class Tracing { + enabled = false; + categories = ""; +} + +function createTracing(opts) { + if (typeof opts !== "object" || opts == null) { + throw new ERR_INVALID_ARG_TYPE("options", "Object", opts); + } + + return new Tracing(opts); +} + +function getEnabledCategories() { + return ""; +} + +export { createTracing, getEnabledCategories }; + +export default { + createTracing, + getEnabledCategories, +}; diff --git a/ext/node/polyfills/util.ts b/ext/node/polyfills/util.ts index eee171ccf0..d82b288b03 100644 --- a/ext/node/polyfills/util.ts +++ b/ext/node/polyfills/util.ts @@ -25,9 +25,13 @@ const { StringPrototypeIsWellFormed, StringPrototypePadStart, StringPrototypeToWellFormed, + PromiseResolve, } = primordials; -import { promisify } from "ext:deno_node/internal/util.mjs"; +import { + createDeferredPromise, + promisify, +} from "ext:deno_node/internal/util.mjs"; import { callbackify } from "ext:deno_node/_util/_util_callbackify.js"; import { debuglog } from "ext:deno_node/internal/util/debuglog.ts"; import { @@ -35,14 +39,20 @@ import { formatWithOptions, inspect, stripVTControlCharacters, + styleText, } from "ext:deno_node/internal/util/inspect.mjs"; import { codes } from "ext:deno_node/internal/error_codes.ts"; import types from "node:util/types"; import { Buffer } from "node:buffer"; import { isDeepStrictEqual } from "ext:deno_node/internal/util/comparisons.ts"; import process from "node:process"; -import { validateString } from "ext:deno_node/internal/validators.mjs"; +import { + validateAbortSignal, + validateString, +} from "ext:deno_node/internal/validators.mjs"; import { parseArgs } from "ext:deno_node/internal/util/parse_args/parse_args.js"; +import * as abortSignal from "ext:deno_web/03_abort_signal.js"; +import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; export { callbackify, @@ -54,6 +64,7 @@ export { parseArgs, promisify, stripVTControlCharacters, + styleText, types, }; @@ -168,6 +179,7 @@ export function inherits( ); } ObjectDefineProperty(ctor, "super_", { + __proto__: null, value: superCtor, writable: true, configurable: true, @@ -234,6 +246,7 @@ function timestamp(): string { */ // deno-lint-ignore no-explicit-any export function log(...args: any[]) { + // deno-lint-ignore no-console console.log("%s - %s", timestamp(), ReflectApply(format, undefined, args)); } @@ -287,6 +300,24 @@ export function deprecate(fn: any, msg: string, code?: any) { return deprecated; } +// deno-lint-ignore require-await +export async function aborted( + signal: AbortSignal, + // deno-lint-ignore no-explicit-any + _resource: any, +): Promise { + if (signal === undefined) { + throw new ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal); + } + validateAbortSignal(signal, "signal"); + if (signal.aborted) { + return PromiseResolve(); + } + const abortPromise = createDeferredPromise(); + signal[abortSignal.add](abortPromise.resolve); + return abortPromise.promise; +} + export { getSystemErrorName, isDeepStrictEqual }; export default { @@ -310,6 +341,7 @@ export default { isBuffer, _extend, getSystemErrorName, + aborted, deprecate, callbackify, parseArgs, @@ -324,4 +356,5 @@ export default { debuglog, debug: debuglog, isDeepStrictEqual, + styleText, }; diff --git a/ext/node/polyfills/v8.ts b/ext/node/polyfills/v8.ts index f06227cd54..9df199865e 100644 --- a/ext/node/polyfills/v8.ts +++ b/ext/node/polyfills/v8.ts @@ -6,15 +6,36 @@ // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file prefer-primordials -import { core } from "ext:core/mod.js"; +import { primordials } from "ext:core/mod.js"; +const { ObjectPrototypeToString } = primordials; import { op_v8_cached_data_version_tag, op_v8_get_heap_statistics, + op_v8_get_wire_format_version, + op_v8_new_deserializer, + op_v8_new_serializer, + op_v8_read_double, + op_v8_read_header, + op_v8_read_raw_bytes, + op_v8_read_uint32, + op_v8_read_uint64, + op_v8_read_value, + op_v8_release_buffer, + op_v8_set_treat_array_buffer_views_as_host_objects, + op_v8_transfer_array_buffer, + op_v8_transfer_array_buffer_de, + op_v8_write_double, + op_v8_write_header, + op_v8_write_raw_bytes, + op_v8_write_uint32, + op_v8_write_uint64, + op_v8_write_value, } from "ext:core/ops"; import { Buffer } from "node:buffer"; -import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts"; +import { notImplemented } from "ext:deno_node/_utils.ts"; +import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts"; export function cachedDataVersionTag() { return op_v8_cached_data_version_tag(); @@ -71,81 +92,227 @@ export function takeCoverage() { export function writeHeapSnapshot() { notImplemented("v8.writeHeapSnapshot"); } -export function serialize(value) { - return Buffer.from(core.serialize(value)); +// deno-lint-ignore no-explicit-any +export function serialize(value: any) { + const ser = new DefaultSerializer(); + ser.writeHeader(); + ser.writeValue(value); + return ser.releaseBuffer(); } -export function deserialize(data) { - return core.deserialize(data); +export function deserialize(buffer: Buffer | ArrayBufferView | DataView) { + if (!isArrayBufferView(buffer)) { + throw new TypeError( + "buffer must be a TypedArray or a DataView", + ); + } + const der = new DefaultDeserializer(buffer); + der.readHeader(); + return der.readValue(); } + +const kHandle = Symbol("kHandle"); + export class Serializer { + [kHandle]: object; constructor() { - warnNotImplemented("v8.Serializer.prototype.constructor"); + this[kHandle] = op_v8_new_serializer(this); + } + + _setTreatArrayBufferViewsAsHostObjects(value: boolean): void { + op_v8_set_treat_array_buffer_views_as_host_objects(this[kHandle], value); } releaseBuffer(): Buffer { - warnNotImplemented("v8.DefaultSerializer.prototype.releaseBuffer"); - return Buffer.from(""); + return Buffer.from(op_v8_release_buffer(this[kHandle])); } transferArrayBuffer(_id: number, _arrayBuffer: ArrayBuffer): void { - warnNotImplemented("v8.DefaultSerializer.prototype.transferArrayBuffer"); + op_v8_transfer_array_buffer(this[kHandle], _id, _arrayBuffer); } - writeDouble(_value: number): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeDouble"); + writeDouble(value: number): void { + op_v8_write_double(this[kHandle], value); } writeHeader(): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeHeader"); + op_v8_write_header(this[kHandle]); } - writeRawBytes(_value: ArrayBufferView): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeRawBytes"); + writeRawBytes(source: ArrayBufferView): void { + if (!isArrayBufferView(source)) { + throw new TypeError( + "source must be a TypedArray or a DataView", + ); + } + op_v8_write_raw_bytes(this[kHandle], source); } - writeUint32(_value: number): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeUint32"); + writeUint32(value: number): void { + op_v8_write_uint32(this[kHandle], value); } - writeUint64(_hi: number, _lo: number): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeUint64"); + writeUint64(hi: number, lo: number): void { + op_v8_write_uint64(this[kHandle], hi, lo); } // deno-lint-ignore no-explicit-any - writeValue(_value: any): void { - warnNotImplemented("v8.DefaultSerializer.prototype.writeValue"); + writeValue(value: any): void { + op_v8_write_value(this[kHandle], value); + } + + _getDataCloneError = Error; +} + +export class Deserializer { + buffer: ArrayBufferView; + [kHandle]: object; + constructor(buffer: ArrayBufferView) { + if (!isArrayBufferView(buffer)) { + throw new TypeError( + "buffer must be a TypedArray or a DataView", + ); + } + this.buffer = buffer; + this[kHandle] = op_v8_new_deserializer(this, buffer); + } + readRawBytes(length: number): Buffer { + const offset = this._readRawBytes(length); + return Buffer.from( + this.buffer.buffer, + this.buffer.byteOffset + offset, + length, + ); + } + _readRawBytes(length: number): number { + return op_v8_read_raw_bytes(this[kHandle], length); + } + getWireFormatVersion(): number { + return op_v8_get_wire_format_version(this[kHandle]); + } + readDouble(): number { + return op_v8_read_double(this[kHandle]); + } + readHeader(): boolean { + return op_v8_read_header(this[kHandle]); + } + + readUint32(): number { + return op_v8_read_uint32(this[kHandle]); + } + readUint64(): [hi: number, lo: number] { + return op_v8_read_uint64(this[kHandle]); + } + readValue(): unknown { + return op_v8_read_value(this[kHandle]); + } + transferArrayBuffer( + id: number, + arrayBuffer: ArrayBuffer | SharedArrayBuffer, + ): void { + return op_v8_transfer_array_buffer_de(this[kHandle], id, arrayBuffer); } } -export class Deserializer { - constructor() { - notImplemented("v8.Deserializer.prototype.constructor"); - } +function arrayBufferViewTypeToIndex(abView: ArrayBufferView) { + const type = ObjectPrototypeToString(abView); + if (type === "[object Int8Array]") return 0; + if (type === "[object Uint8Array]") return 1; + if (type === "[object Uint8ClampedArray]") return 2; + if (type === "[object Int16Array]") return 3; + if (type === "[object Uint16Array]") return 4; + if (type === "[object Int32Array]") return 5; + if (type === "[object Uint32Array]") return 6; + if (type === "[object Float32Array]") return 7; + if (type === "[object Float64Array]") return 8; + if (type === "[object DataView]") return 9; + // Index 10 is FastBuffer. + if (type === "[object BigInt64Array]") return 11; + if (type === "[object BigUint64Array]") return 12; + return -1; } export class DefaultSerializer extends Serializer { constructor() { - warnNotImplemented("v8.DefaultSerializer.prototype.constructor"); super(); + this._setTreatArrayBufferViewsAsHostObjects(true); + } + + // deno-lint-ignore no-explicit-any + _writeHostObject(abView: any) { + // Keep track of how to handle different ArrayBufferViews. The default + // Serializer for Node does not use the V8 methods for serializing those + // objects because Node's `Buffer` objects use pooled allocation in many + // cases, and their underlying `ArrayBuffer`s would show up in the + // serialization. Because a) those may contain sensitive data and the user + // may not be aware of that and b) they are often much larger than the + // `Buffer` itself, custom serialization is applied. + let i = 10; // FastBuffer + if (abView.constructor !== Buffer) { + i = arrayBufferViewTypeToIndex(abView); + if (i === -1) { + throw new this._getDataCloneError( + `Unserializable host object: ${abView}`, + ); + } + } + this.writeUint32(i); + this.writeUint32(abView.byteLength); + this.writeRawBytes( + new Uint8Array(abView.buffer, abView.byteOffset, abView.byteLength), + ); } } -export class DefaultDeserializer { - constructor() { - notImplemented("v8.DefaultDeserializer.prototype.constructor"); + +// deno-lint-ignore no-explicit-any +function arrayBufferViewIndexToType(index: number): any { + if (index === 0) return Int8Array; + if (index === 1) return Uint8Array; + if (index === 2) return Uint8ClampedArray; + if (index === 3) return Int16Array; + if (index === 4) return Uint16Array; + if (index === 5) return Int32Array; + if (index === 6) return Uint32Array; + if (index === 7) return Float32Array; + if (index === 8) return Float64Array; + if (index === 9) return DataView; + if (index === 10) return Buffer; + if (index === 11) return BigInt64Array; + if (index === 12) return BigUint64Array; + return undefined; +} + +export class DefaultDeserializer extends Deserializer { + constructor(buffer: ArrayBufferView) { + super(buffer); + } + + _readHostObject() { + const typeIndex = this.readUint32(); + const ctor = arrayBufferViewIndexToType(typeIndex); + const byteLength = this.readUint32(); + const byteOffset = this._readRawBytes(byteLength); + const BYTES_PER_ELEMENT = ctor?.BYTES_PER_ELEMENT ?? 1; + + const offset = this.buffer.byteOffset + byteOffset; + if (offset % BYTES_PER_ELEMENT === 0) { + return new ctor( + this.buffer.buffer, + offset, + byteLength / BYTES_PER_ELEMENT, + ); + } + // Copy to an aligned buffer first. + const bufferCopy = Buffer.allocUnsafe(byteLength); + Buffer.from( + this.buffer.buffer, + byteOffset, + byteLength, + ).copy(bufferCopy); + return new ctor( + bufferCopy.buffer, + bufferCopy.byteOffset, + byteLength / BYTES_PER_ELEMENT, + ); } } -export const promiseHooks = { - onInit() { - notImplemented("v8.promiseHooks.onInit"); - }, - onSettled() { - notImplemented("v8.promiseHooks.onSetttled"); - }, - onBefore() { - notImplemented("v8.promiseHooks.onBefore"); - }, - createHook() { - notImplemented("v8.promiseHooks.createHook"); - }, -}; export default { cachedDataVersionTag, getHeapCodeStatistics, @@ -162,5 +329,4 @@ export default { Deserializer, DefaultSerializer, DefaultDeserializer, - promiseHooks, }; diff --git a/ext/node/polyfills/vm.js b/ext/node/polyfills/vm.js index bc1a250456..183ddad2f4 100644 --- a/ext/node/polyfills/vm.js +++ b/ext/node/polyfills/vm.js @@ -27,14 +27,14 @@ import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; import { primordials } from "ext:core/mod.js"; -const { Symbol, ArrayPrototypeForEach } = primordials; +const { Symbol, ArrayPrototypeForEach, ObjectFreeze } = primordials; const kParsingContext = Symbol("script parsing context"); export class Script { #inner; - constructor(code, options = {}) { + constructor(code, options = { __proto__: null }) { code = `${code}`; if (typeof options === "string") { options = { filename: options }; @@ -80,7 +80,7 @@ export class Script { : undefined; } - #runInContext(contextifiedObject, options = {}) { + #runInContext(contextifiedObject, options = { __proto__: null }) { validateObject(options, "options"); let timeout = options.timeout; @@ -181,7 +181,10 @@ function getContextOptions(options) { } let defaultContextNameIndex = 1; -export function createContext(contextObject = {}, options = {}) { +export function createContext( + contextObject = {}, + options = { __proto__: null }, +) { if (isContext(contextObject)) { return contextObject; } @@ -276,7 +279,7 @@ export function isContext(object) { return op_vm_is_context(object); } -export function compileFunction(code, params, options = {}) { +export function compileFunction(code, params, options = { __proto__: null }) { validateString(code, "code"); if (params !== undefined) { validateStringArray(params, "params"); @@ -346,8 +349,22 @@ export function measureMemory(_options) { notImplemented("measureMemory"); } +const USE_MAIN_CONTEXT_DEFAULT_LOADER = Symbol( + "USE_MAIN_CONTEXT_DEFAULT_LOADER", +); +const DONT_CONTEXTIFY = Symbol("DONT_CONTEXTIFY"); + +export const constants = { + __proto__: null, + USE_MAIN_CONTEXT_DEFAULT_LOADER, + DONT_CONTEXTIFY, +}; + +ObjectFreeze(constants); + export default { Script, + constants, createContext, createScript, runInContext, diff --git a/ext/node/polyfills/wasi.ts b/ext/node/polyfills/wasi.ts index eba955d9ca..4bdc776a4c 100644 --- a/ext/node/polyfills/wasi.ts +++ b/ext/node/polyfills/wasi.ts @@ -1,7 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials +import { primordials } from "ext:core/mod.js"; + +const { Error } = primordials; class Context { constructor() { diff --git a/ext/node/polyfills/worker_threads.ts b/ext/node/polyfills/worker_threads.ts index 3519ae217a..d4b75fb30c 100644 --- a/ext/node/polyfills/worker_threads.ts +++ b/ext/node/polyfills/worker_threads.ts @@ -47,11 +47,21 @@ const { const debugWorkerThreads = false; function debugWT(...args) { if (debugWorkerThreads) { - // deno-lint-ignore prefer-primordials + // deno-lint-ignore prefer-primordials no-console console.log(...args); } } +interface WorkerOnlineMsg { + type: "WORKER_ONLINE"; +} + +function isWorkerOnlineMsg(data: unknown): data is WorkerOnlineMsg { + return typeof data === "object" && data !== null && + ObjectHasOwn(data, "type") && + (data as { "type": unknown })["type"] === "WORKER_ONLINE"; +} + export interface WorkerOptions { // only for typings argv?: unknown[]; @@ -81,6 +91,7 @@ class NodeWorker extends EventEmitter { #refCount = 1; #messagePromise = undefined; #controlPromise = undefined; + #workerOnline = false; // "RUNNING" | "CLOSED" | "TERMINATED" // "TERMINATED" means that any controls or messages received will be // discarded. "CLOSED" means that we have received a control @@ -141,6 +152,7 @@ class NodeWorker extends EventEmitter { workerData: options?.workerData, environmentData: environmentData, env: env_, + isWorkerThread: true, }, options?.transferList ?? []); const id = op_create_worker( { @@ -159,8 +171,6 @@ class NodeWorker extends EventEmitter { this.threadId = id; this.#pollControl(); this.#pollMessages(); - // https://nodejs.org/api/worker_threads.html#event-online - this.emit("online"); } [privateWorkerRef](ref) { @@ -243,11 +253,21 @@ class NodeWorker extends EventEmitter { this.emit("messageerror", err); return; } - this.emit("message", message); + if ( + // only emit "online" event once, and since the message + // has to come before user messages, we are safe to assume + // it came from us + !this.#workerOnline && isWorkerOnlineMsg(message) + ) { + this.#workerOnline = true; + this.emit("online"); + } else { + this.emit("message", message); + } } }; - postMessage(message, transferOrOptions = {}) { + postMessage(message, transferOrOptions = { __proto__: null }) { const prefix = "Failed to execute 'postMessage' on 'MessagePort'"; webidl.requiredArguments(arguments.length, 1, prefix); message = webidl.converters.any(message); @@ -282,8 +302,8 @@ class NodeWorker extends EventEmitter { if (this.#status !== "TERMINATED") { this.#status = "TERMINATED"; op_host_terminate_worker(this.#id); + this.emit("exit", 0); } - this.emit("exit", 0); return PromiseResolve(0); } @@ -358,10 +378,12 @@ internals.__initWorkerThreads = ( parentPort = globalThis as ParentPort; threadId = workerId; + let isWorkerThread = false; if (maybeWorkerMetadata) { const { 0: metadata, 1: _ } = maybeWorkerMetadata; workerData = metadata.workerData; environmentData = metadata.environmentData; + isWorkerThread = metadata.isWorkerThread; const env = metadata.env; if (env) { process.env = env; @@ -400,7 +422,11 @@ internals.__initWorkerThreads = ( parentPort.once = function (this: ParentPort, name, listener) { // deno-lint-ignore no-explicit-any - const _listener = (ev: any) => listener(ev.data); + const _listener = (ev: any) => { + const message = ev.data; + patchMessagePortIfFound(message); + return listener(message); + }; listeners.set(listener, _listener); this.addEventListener(name, _listener); return this; @@ -425,6 +451,15 @@ internals.__initWorkerThreads = ( parentPort.ref = () => { parentPort[unrefPollForMessages] = false; }; + + if (isWorkerThread) { + // Notify the host that the worker is online + parentPort.postMessage( + { + type: "WORKER_ONLINE", + } satisfies WorkerOnlineMsg, + ); + } } }; @@ -463,7 +498,9 @@ export function receiveMessageOnPort(port: MessagePort): object | undefined { port[MessagePortReceiveMessageOnPortSymbol] = true; const data = op_message_port_recv_message_sync(port[MessagePortIdSymbol]); if (data === null) return undefined; - return { message: deserializeJsMessageData(data)[0] }; + const message = deserializeJsMessageData(data)[0]; + patchMessagePortIfFound(message); + return { message }; } class NodeMessageChannel { diff --git a/ext/node/polyfills/zlib.ts b/ext/node/polyfills/zlib.ts index a19474cfc8..3fe5f8bbd9 100644 --- a/ext/node/polyfills/zlib.ts +++ b/ext/node/polyfills/zlib.ts @@ -78,20 +78,15 @@ export class ZlibBase { export { constants }; export default { - Options, - BrotliOptions, + brotliCompress, BrotliCompress, + brotliCompressSync, + brotliDecompress, BrotliDecompress, - Deflate, - DeflateRaw, - Gunzip, - Gzip, - Inflate, - InflateRaw, - Unzip, - ZlibBase, - constants, + brotliDecompressSync, + BrotliOptions, codes, + constants, createBrotliCompress, createBrotliDecompress, createDeflate, @@ -101,24 +96,73 @@ export default { createInflate, createInflateRaw, createUnzip, - brotliCompress, - brotliCompressSync, - brotliDecompress, - brotliDecompressSync, deflate, - deflateSync, + Deflate, + DEFLATE: constants.DEFLATE, deflateRaw, + DeflateRaw, + DEFLATERAW: constants.DEFLATERAW, deflateRawSync, + deflateSync, gunzip, + Gunzip, + GUNZIP: constants.GUNZIP, gunzipSync, gzip, + Gzip, + GZIP: constants.GZIP, gzipSync, inflate, - inflateSync, + Inflate, + INFLATE: constants.INFLATE, inflateRaw, + InflateRaw, + INFLATERAW: constants.INFLATERAW, inflateRawSync, + inflateSync, + Options, unzip, + Unzip, + UNZIP: constants.UNZIP, unzipSync, + Z_BEST_COMPRESSION: constants.Z_BEST_COMPRESSION, + Z_BEST_SPEED: constants.Z_BEST_SPEED, + Z_BLOCK: constants.Z_BLOCK, + Z_BUF_ERROR: constants.Z_BUF_ERROR, + Z_DATA_ERROR: constants.Z_DATA_ERROR, + Z_DEFAULT_CHUNK: constants.Z_DEFAULT_CHUNK, + Z_DEFAULT_COMPRESSION: constants.Z_DEFAULT_COMPRESSION, + Z_DEFAULT_LEVEL: constants.Z_DEFAULT_LEVEL, + Z_DEFAULT_MEMLEVEL: constants.Z_DEFAULT_MEMLEVEL, + Z_DEFAULT_STRATEGY: constants.Z_DEFAULT_STRATEGY, + Z_DEFAULT_WINDOWBITS: constants.Z_DEFAULT_WINDOWBITS, + Z_ERRNO: constants.Z_ERRNO, + Z_FILTERED: constants.Z_FILTERED, + Z_FINISH: constants.Z_FINISH, + Z_FIXED: constants.Z_FIXED, + Z_FULL_FLUSH: constants.Z_FULL_FLUSH, + Z_HUFFMAN_ONLY: constants.Z_HUFFMAN_ONLY, + Z_MAX_CHUNK: constants.Z_MAX_CHUNK, + Z_MAX_LEVEL: constants.Z_MAX_LEVEL, + Z_MAX_MEMLEVEL: constants.Z_MAX_MEMLEVEL, + Z_MAX_WINDOWBITS: constants.Z_MAX_WINDOWBITS, + Z_MEM_ERROR: constants.Z_MEM_ERROR, + Z_MIN_CHUNK: constants.Z_MIN_CHUNK, + Z_MIN_LEVEL: constants.Z_MIN_LEVEL, + Z_MIN_MEMLEVEL: constants.Z_MIN_MEMLEVEL, + Z_MIN_WINDOWBITS: constants.Z_MIN_WINDOWBITS, + Z_NEED_DICT: constants.Z_NEED_DICT, + Z_NO_COMPRESSION: constants.Z_NO_COMPRESSION, + Z_NO_FLUSH: constants.Z_NO_FLUSH, + Z_OK: constants.Z_OK, + Z_PARTIAL_FLUSH: constants.Z_PARTIAL_FLUSH, + Z_RLE: constants.Z_RLE, + Z_STREAM_END: constants.Z_STREAM_END, + Z_STREAM_ERROR: constants.Z_STREAM_ERROR, + Z_SYNC_FLUSH: constants.Z_SYNC_FLUSH, + Z_VERSION_ERROR: constants.Z_VERSION_ERROR, + ZLIB_VERNUM: constants.ZLIB_VERNUM, + ZlibBase, }; export { diff --git a/ext/node_resolver/path.rs b/ext/node_resolver/path.rs deleted file mode 100644 index ece270cd91..0000000000 --- a/ext/node_resolver/path.rs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::path::Component; -use std::path::Path; -use std::path::PathBuf; - -use url::Url; - -/// Extension to path_clean::PathClean -pub trait PathClean { - fn clean(&self) -> T; -} - -impl PathClean for PathBuf { - fn clean(&self) -> PathBuf { - fn is_clean_path(path: &Path) -> bool { - let path = path.to_string_lossy(); - let mut current_index = 0; - while let Some(index) = path[current_index..].find("\\.") { - let trailing_index = index + current_index + 2; - let mut trailing_chars = path[trailing_index..].chars(); - match trailing_chars.next() { - Some('.') => match trailing_chars.next() { - Some('/') | Some('\\') | None => { - return false; - } - _ => {} - }, - Some('/') | Some('\\') => { - return false; - } - _ => {} - } - current_index = trailing_index; - } - true - } - - let path = path_clean::PathClean::clean(self); - if cfg!(windows) && !is_clean_path(&path) { - // temporary workaround because path_clean::PathClean::clean is - // not good enough on windows - let mut components = Vec::new(); - - for component in path.components() { - match component { - Component::CurDir => { - // skip - } - Component::ParentDir => { - let maybe_last_component = components.pop(); - if !matches!(maybe_last_component, Some(Component::Normal(_))) { - panic!("Error normalizing: {}", path.display()); - } - } - Component::Normal(_) | Component::RootDir | Component::Prefix(_) => { - components.push(component); - } - } - } - components.into_iter().collect::() - } else { - path - } - } -} - -pub(crate) fn to_file_specifier(path: &Path) -> Url { - match Url::from_file_path(path) { - Ok(url) => url, - Err(_) => panic!("Invalid path: {}", path.display()), - } -} - -// todo(dsherret): we have the below code also in deno_core and it -// would be good to somehow re-use it in both places (we don't want -// to create a dependency on deno_core here) - -#[cfg(not(windows))] -#[inline] -pub fn strip_unc_prefix(path: PathBuf) -> PathBuf { - path -} - -/// Strips the unc prefix (ex. \\?\) from Windows paths. -#[cfg(windows)] -pub fn strip_unc_prefix(path: PathBuf) -> PathBuf { - use std::path::Component; - use std::path::Prefix; - - let mut components = path.components(); - match components.next() { - Some(Component::Prefix(prefix)) => { - match prefix.kind() { - // \\?\device - Prefix::Verbatim(device) => { - let mut path = PathBuf::new(); - path.push(format!(r"\\{}\", device.to_string_lossy())); - path.extend(components.filter(|c| !matches!(c, Component::RootDir))); - path - } - // \\?\c:\path - Prefix::VerbatimDisk(_) => { - let mut path = PathBuf::new(); - path.push(prefix.as_os_str().to_string_lossy().replace(r"\\?\", "")); - path.extend(components); - path - } - // \\?\UNC\hostname\share_name\path - Prefix::VerbatimUNC(hostname, share_name) => { - let mut path = PathBuf::new(); - path.push(format!( - r"\\{}\{}\", - hostname.to_string_lossy(), - share_name.to_string_lossy() - )); - path.extend(components.filter(|c| !matches!(c, Component::RootDir))); - path - } - _ => path, - } - } - _ => path, - } -} - -#[cfg(test)] -mod test { - #[cfg(windows)] - #[test] - fn test_path_clean() { - use super::*; - - run_test("C:\\test\\./file.txt", "C:\\test\\file.txt"); - run_test("C:\\test\\../other/file.txt", "C:\\other\\file.txt"); - run_test("C:\\test\\../other\\file.txt", "C:\\other\\file.txt"); - - fn run_test(input: &str, expected: &str) { - assert_eq!(PathBuf::from(input).clean(), PathBuf::from(expected)); - } - } - - #[cfg(windows)] - #[test] - fn test_strip_unc_prefix() { - use std::path::PathBuf; - - run_test(r"C:\", r"C:\"); - run_test(r"C:\test\file.txt", r"C:\test\file.txt"); - - run_test(r"\\?\C:\", r"C:\"); - run_test(r"\\?\C:\test\file.txt", r"C:\test\file.txt"); - - run_test(r"\\.\C:\", r"\\.\C:\"); - run_test(r"\\.\C:\Test\file.txt", r"\\.\C:\Test\file.txt"); - - run_test(r"\\?\UNC\localhost\", r"\\localhost"); - run_test(r"\\?\UNC\localhost\c$\", r"\\localhost\c$"); - run_test( - r"\\?\UNC\localhost\c$\Windows\file.txt", - r"\\localhost\c$\Windows\file.txt", - ); - run_test(r"\\?\UNC\wsl$\deno.json", r"\\wsl$\deno.json"); - - run_test(r"\\?\server1", r"\\server1"); - run_test(r"\\?\server1\e$\", r"\\server1\e$\"); - run_test( - r"\\?\server1\e$\test\file.txt", - r"\\server1\e$\test\file.txt", - ); - - fn run_test(input: &str, expected: &str) { - assert_eq!( - super::strip_unc_prefix(PathBuf::from(input)), - PathBuf::from(expected) - ); - } - } -} diff --git a/ext/tls/Cargo.toml b/ext/tls/Cargo.toml index ed306182ee..d163fd7eb4 100644 --- a/ext/tls/Cargo.toml +++ b/ext/tls/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_tls" -version = "0.151.0" +version = "0.161.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,5 +21,6 @@ rustls-pemfile.workspace = true rustls-tokio-stream.workspace = true rustls-webpki.workspace = true serde.workspace = true +thiserror.workspace = true tokio.workspace = true webpki-roots.workspace = true diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index c4d548ccf2..883d2995e4 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -9,17 +9,12 @@ pub use rustls_tokio_stream::*; pub use webpki; pub use webpki_roots; -use deno_core::anyhow::anyhow; -use deno_core::error::custom_error; -use deno_core::error::AnyError; - use rustls::client::danger::HandshakeSignatureValid; use rustls::client::danger::ServerCertVerified; use rustls::client::danger::ServerCertVerifier; use rustls::client::WebPkiServerVerifier; use rustls::ClientConfig; use rustls::DigitallySignedStruct; -use rustls::Error; use rustls::RootCertStore; use rustls_pemfile::certs; use rustls_pemfile::ec_private_keys; @@ -35,12 +30,30 @@ use std::sync::Arc; mod tls_key; pub use tls_key::*; +#[derive(Debug, thiserror::Error)] +pub enum TlsError { + #[error(transparent)] + Rustls(#[from] rustls::Error), + #[error("Unable to add pem file to certificate store: {0}")] + UnableAddPemFileToCert(std::io::Error), + #[error("Unable to decode certificate")] + CertInvalid, + #[error("No certificates found in certificate data")] + CertsNotFound, + #[error("No keys found in key data")] + KeysNotFound, + #[error("Unable to decode key")] + KeyDecode, +} + /// Lazily resolves the root cert store. /// /// This was done because the root cert store is not needed in all cases /// and takes a bit of time to initialize. pub trait RootCertStoreProvider: Send + Sync { - fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError>; + fn get_or_try_init( + &self, + ) -> Result<&RootCertStore, deno_core::error::AnyError>; } // This extension has no runtime apis, it only exports some shared native functions. @@ -77,7 +90,7 @@ impl ServerCertVerifier for NoCertificateVerification { server_name: &rustls::pki_types::ServerName<'_>, ocsp_response: &[u8], now: rustls::pki_types::UnixTime, - ) -> Result { + ) -> Result { if self.ic_allowlist.is_empty() { return Ok(ServerCertVerified::assertion()); } @@ -89,7 +102,9 @@ impl ServerCertVerifier for NoCertificateVerification { _ => { // NOTE(bartlomieju): `ServerName` is a non-exhaustive enum // so we have this catch all errors here. - return Err(Error::General("Unknown `ServerName` variant".to_string())); + return Err(rustls::Error::General( + "Unknown `ServerName` variant".to_string(), + )); } }; if self.ic_allowlist.contains(&dns_name_or_ip_address) { @@ -110,7 +125,7 @@ impl ServerCertVerifier for NoCertificateVerification { message: &[u8], cert: &rustls::pki_types::CertificateDer, dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { if self.ic_allowlist.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } @@ -126,7 +141,7 @@ impl ServerCertVerifier for NoCertificateVerification { message: &[u8], cert: &rustls::pki_types::CertificateDer, dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { if self.ic_allowlist.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } @@ -178,7 +193,7 @@ pub fn create_client_config( unsafely_ignore_certificate_errors: Option>, maybe_cert_chain_and_key: TlsKeys, socket_use: SocketUse, -) -> Result { +) -> Result { if let Some(ic_allowlist) = unsafely_ignore_certificate_errors { let client_config = ClientConfig::builder() .dangerous() @@ -214,10 +229,7 @@ pub fn create_client_config( root_cert_store.add(cert)?; } Err(e) => { - return Err(anyhow!( - "Unable to add pem file to certificate store: {}", - e - )); + return Err(TlsError::UnableAddPemFileToCert(e)); } } } @@ -255,74 +267,61 @@ fn add_alpn(client: &mut ClientConfig, socket_use: SocketUse) { pub fn load_certs( reader: &mut dyn BufRead, -) -> Result>, AnyError> { +) -> Result>, TlsError> { let certs: Result, _> = certs(reader).collect(); - let certs = certs - .map_err(|_| custom_error("InvalidData", "Unable to decode certificate"))?; + let certs = certs.map_err(|_| TlsError::CertInvalid)?; if certs.is_empty() { - return Err(cert_not_found_err()); + return Err(TlsError::CertsNotFound); } Ok(certs) } -fn key_decode_err() -> AnyError { - custom_error("InvalidData", "Unable to decode key") -} - -fn key_not_found_err() -> AnyError { - custom_error("InvalidData", "No keys found in key data") -} - -fn cert_not_found_err() -> AnyError { - custom_error("InvalidData", "No certificates found in certificate data") -} - /// Starts with -----BEGIN RSA PRIVATE KEY----- fn load_rsa_keys( mut bytes: &[u8], -) -> Result>, AnyError> { +) -> Result>, TlsError> { let keys: Result, _> = rsa_private_keys(&mut bytes).collect(); - let keys = keys.map_err(|_| key_decode_err())?; + let keys = keys.map_err(|_| TlsError::KeyDecode)?; Ok(keys.into_iter().map(PrivateKeyDer::Pkcs1).collect()) } /// Starts with -----BEGIN EC PRIVATE KEY----- fn load_ec_keys( mut bytes: &[u8], -) -> Result>, AnyError> { +) -> Result>, TlsError> { let keys: Result, std::io::Error> = ec_private_keys(&mut bytes).collect(); - let keys2 = keys.map_err(|_| key_decode_err())?; + let keys2 = keys.map_err(|_| TlsError::KeyDecode)?; Ok(keys2.into_iter().map(PrivateKeyDer::Sec1).collect()) } /// Starts with -----BEGIN PRIVATE KEY----- fn load_pkcs8_keys( mut bytes: &[u8], -) -> Result>, AnyError> { +) -> Result>, TlsError> { let keys: Result, std::io::Error> = pkcs8_private_keys(&mut bytes).collect(); - let keys2 = keys.map_err(|_| key_decode_err())?; + let keys2 = keys.map_err(|_| TlsError::KeyDecode)?; Ok(keys2.into_iter().map(PrivateKeyDer::Pkcs8).collect()) } fn filter_invalid_encoding_err( - to_be_filtered: Result, -) -> Result { + to_be_filtered: Result, +) -> Result { match to_be_filtered { - Err(Error::InvalidCertificate(rustls::CertificateError::BadEncoding)) => { - Ok(HandshakeSignatureValid::assertion()) - } + Err(rustls::Error::InvalidCertificate( + rustls::CertificateError::BadEncoding, + )) => Ok(HandshakeSignatureValid::assertion()), res => res, } } pub fn load_private_keys( bytes: &[u8], -) -> Result>, AnyError> { +) -> Result>, TlsError> { let mut keys = load_rsa_keys(bytes)?; if keys.is_empty() { @@ -334,7 +333,7 @@ pub fn load_private_keys( } if keys.is_empty() { - return Err(key_not_found_err()); + return Err(TlsError::KeysNotFound); } Ok(keys) diff --git a/ext/tls/tls_key.rs b/ext/tls/tls_key.rs index 66fac86f87..b7baa604b9 100644 --- a/ext/tls/tls_key.rs +++ b/ext/tls/tls_key.rs @@ -11,8 +11,6 @@ //! key lookup can handle closing one end of the pair, in which case they will just //! attempt to clean up the associated resources. -use deno_core::anyhow::anyhow; -use deno_core::error::AnyError; use deno_core::futures::future::poll_fn; use deno_core::futures::future::Either; use deno_core::futures::FutureExt; @@ -33,7 +31,19 @@ use tokio::sync::oneshot; use webpki::types::CertificateDer; use webpki::types::PrivateKeyDer; -type ErrorType = Rc; +#[derive(Debug, thiserror::Error)] +pub enum TlsKeyError { + #[error(transparent)] + Rustls(#[from] rustls::Error), + #[error("Failed: {0}")] + Failed(ErrorType), + #[error(transparent)] + JoinError(#[from] tokio::task::JoinError), + #[error(transparent)] + RecvError(#[from] tokio::sync::broadcast::error::RecvError), +} + +type ErrorType = Arc>; /// A TLS certificate/private key pair. /// see https://docs.rs/rustls-pki-types/latest/rustls_pki_types/#cloning-private-keys @@ -114,7 +124,7 @@ impl TlsKeyResolver { &self, sni: String, alpn: Vec>, - ) -> Result, AnyError> { + ) -> Result, TlsKeyError> { let key = self.resolve(sni).await?; let mut tls_config = ServerConfig::builder() @@ -183,7 +193,7 @@ impl TlsKeyResolver { pub fn resolve( &self, sni: String, - ) -> impl Future> { + ) -> impl Future> { let mut cache = self.inner.cache.borrow_mut(); let mut recv = match cache.get(&sni) { None => { @@ -194,7 +204,7 @@ impl TlsKeyResolver { } Some(TlsKeyState::Resolving(recv)) => recv.resubscribe(), Some(TlsKeyState::Resolved(res)) => { - return Either::Left(ready(res.clone().map_err(|_| anyhow!("Failed")))); + return Either::Left(ready(res.clone().map_err(TlsKeyError::Failed))); } }; drop(cache); @@ -212,7 +222,7 @@ impl TlsKeyResolver { // Someone beat us to it } } - res.map_err(|_| anyhow!("Failed")) + res.map_err(TlsKeyError::Failed) }); Either::Right(async move { handle.await? }) } @@ -247,13 +257,13 @@ impl TlsKeyLookup { } /// Resolve a previously polled item. - pub fn resolve(&self, sni: String, res: Result) { + pub fn resolve(&self, sni: String, res: Result) { _ = self .pending .borrow_mut() .remove(&sni) .unwrap() - .send(res.map_err(Rc::new)); + .send(res.map_err(|e| Arc::new(e.into_boxed_str()))); } } diff --git a/ext/url/00_url.js b/ext/url/00_url.js index 577caba902..ec875da768 100644 --- a/ext/url/00_url.js +++ b/ext/url/00_url.js @@ -139,7 +139,7 @@ class URLSearchParams { throw new TypeError( `${prefix}: Item ${ i + 0 - } in the parameter list does have length 2 exactly.`, + } in the parameter list does have length 2 exactly`, ); } return [pair[0], pair[1]]; diff --git a/ext/url/01_urlpattern.js b/ext/url/01_urlpattern.js index 0bba59cf0e..6e27563089 100644 --- a/ext/url/01_urlpattern.js +++ b/ext/url/01_urlpattern.js @@ -31,6 +31,7 @@ import * as webidl from "ext:deno_webidl/00_webidl.js"; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; const _components = Symbol("components"); +const urlPatternSettings = { groupStringFallback: false }; /** * @typedef Components @@ -349,7 +350,11 @@ class URLPattern { const groups = res.groups; for (let i = 0; i < groupList.length; ++i) { // TODO(lucacasonato): this is vulnerable to override mistake - groups[groupList[i]] = match[i + 1]; + if (urlPatternSettings.groupStringFallback) { + groups[groupList[i]] = match[i + 1] ?? ""; + } else { + groups[groupList[i]] = match[i + 1]; + } } break; } @@ -422,4 +427,4 @@ webidl.converters.URLPatternOptions = webidl }, ]); -export { URLPattern }; +export { URLPattern, urlPatternSettings }; diff --git a/ext/url/Cargo.toml b/ext/url/Cargo.toml index be62718eff..ef7890e2ae 100644 --- a/ext/url/Cargo.toml +++ b/ext/url/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_url" -version = "0.164.0" +version = "0.174.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -15,6 +15,7 @@ path = "lib.rs" [dependencies] deno_core.workspace = true +thiserror.workspace = true urlpattern = "0.3.0" [dev-dependencies] diff --git a/ext/url/lib.deno_url.d.ts b/ext/url/lib.deno_url.d.ts index 71a781636a..946c70607f 100644 --- a/ext/url/lib.deno_url.d.ts +++ b/ext/url/lib.deno_url.d.ts @@ -6,7 +6,7 @@ /// /** @category URL */ -declare interface URLSearchParams { +interface URLSearchParams { /** Appends a specified key/value pair as a new search parameter. * * ```ts @@ -170,7 +170,7 @@ declare var URLSearchParams: { * * @category URL */ -declare interface URL { +interface URL { hash: string; host: string; hostname: string; @@ -202,7 +202,7 @@ declare var URL: { }; /** @category URL */ -declare interface URLPatternInit { +interface URLPatternInit { protocol?: string; username?: string; password?: string; @@ -215,10 +215,10 @@ declare interface URLPatternInit { } /** @category URL */ -declare type URLPatternInput = string | URLPatternInit; +type URLPatternInput = string | URLPatternInit; /** @category URL */ -declare interface URLPatternComponentResult { +interface URLPatternComponentResult { input: string; groups: Record; } @@ -227,7 +227,7 @@ declare interface URLPatternComponentResult { * * @category URL */ -declare interface URLPatternResult { +interface URLPatternResult { /** The inputs provided when matching. */ inputs: [URLPatternInit] | [URLPatternInit, string]; @@ -254,7 +254,7 @@ declare interface URLPatternResult { * * @category URL */ -declare interface URLPatternOptions { +interface URLPatternOptions { /** * Enables case-insensitive matching. * @@ -293,7 +293,7 @@ declare interface URLPatternOptions { * * @category URL */ -declare interface URLPattern { +interface URLPattern { /** * Test if the given input matches the stored pattern. * diff --git a/ext/url/lib.rs b/ext/url/lib.rs index 6869d656b5..f8946532ae 100644 --- a/ext/url/lib.rs +++ b/ext/url/lib.rs @@ -15,6 +15,8 @@ use std::path::PathBuf; use crate::urlpattern::op_urlpattern_parse; use crate::urlpattern::op_urlpattern_process_match_input; +pub use urlpattern::UrlPatternError; + deno_core::extension!( deno_url, deps = [deno_webidl], diff --git a/ext/url/urlpattern.rs b/ext/url/urlpattern.rs index b6d9a13828..7d4e8ee71b 100644 --- a/ext/url/urlpattern.rs +++ b/ext/url/urlpattern.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use urlpattern::quirks; @@ -9,21 +7,23 @@ use urlpattern::quirks::MatchInput; use urlpattern::quirks::StringOrInit; use urlpattern::quirks::UrlPattern; +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct UrlPatternError(urlpattern::Error); + #[op2] #[serde] pub fn op_urlpattern_parse( #[serde] input: StringOrInit, #[string] base_url: Option, #[serde] options: urlpattern::UrlPatternOptions, -) -> Result { - let init = urlpattern::quirks::process_construct_pattern_input( - input, - base_url.as_deref(), - ) - .map_err(|e| type_error(e.to_string()))?; +) -> Result { + let init = + quirks::process_construct_pattern_input(input, base_url.as_deref()) + .map_err(UrlPatternError)?; - let pattern = urlpattern::quirks::parse_pattern(init, options) - .map_err(|e| type_error(e.to_string()))?; + let pattern = + quirks::parse_pattern(init, options).map_err(UrlPatternError)?; Ok(pattern) } @@ -33,14 +33,14 @@ pub fn op_urlpattern_parse( pub fn op_urlpattern_process_match_input( #[serde] input: StringOrInit, #[string] base_url: Option, -) -> Result, AnyError> { - let res = urlpattern::quirks::process_match_input(input, base_url.as_deref()) - .map_err(|e| type_error(e.to_string()))?; +) -> Result, UrlPatternError> { + let res = quirks::process_match_input(input, base_url.as_deref()) + .map_err(UrlPatternError)?; let (input, inputs) = match res { Some((input, inputs)) => (input, inputs), None => return Ok(None), }; - Ok(urlpattern::quirks::parse_match_input(input).map(|input| (input, inputs))) + Ok(quirks::parse_match_input(input).map(|input| (input, inputs))) } diff --git a/ext/web/00_infra.js b/ext/web/00_infra.js index e42f2cc931..4b241ab5d7 100644 --- a/ext/web/00_infra.js +++ b/ext/web/00_infra.js @@ -133,7 +133,7 @@ function regexMatcher(chars) { ); return `\\u${a}-\\u${b}`; } else { - throw TypeError("unreachable"); + throw new TypeError("unreachable"); } }); return ArrayPrototypeJoin(matchers, ""); diff --git a/ext/web/01_dom_exception.js b/ext/web/01_dom_exception.js index f49337db59..38e4d088e5 100644 --- a/ext/web/01_dom_exception.js +++ b/ext/web/01_dom_exception.js @@ -186,7 +186,7 @@ const entries = ObjectEntries({ }); for (let i = 0; i < entries.length; ++i) { const { 0: key, 1: value } = entries[i]; - const desc = { value, enumerable: true }; + const desc = { __proto__: null, value, enumerable: true }; ObjectDefineProperty(DOMException, key, desc); ObjectDefineProperty(DOMException.prototype, key, desc); } diff --git a/ext/web/02_event.js b/ext/web/02_event.js index 985578bcc2..a3e40ab996 100644 --- a/ext/web/02_event.js +++ b/ext/web/02_event.js @@ -7,7 +7,6 @@ import { core, primordials } from "ext:core/mod.js"; const { - ArrayPrototypeFilter, ArrayPrototypeIncludes, ArrayPrototypeIndexOf, ArrayPrototypeMap, @@ -392,6 +391,7 @@ const EventPrototype = Event.prototype; // Not spec compliant. The spec defines it as [LegacyUnforgeable] // but doing so has a big performance hit ReflectDefineProperty(Event.prototype, "isTrusted", { + __proto__: null, enumerable: true, get: isTrusted, }); @@ -402,7 +402,10 @@ function defineEnumerableProps( ) { for (let i = 0; i < props.length; ++i) { const prop = props[i]; - ReflectDefineProperty(Ctor.prototype, prop, { enumerable: true }); + ReflectDefineProperty(Ctor.prototype, prop, { + __proto__: null, + enumerable: true, + }); } } @@ -978,12 +981,7 @@ class EventTarget { ); const { listeners } = self[eventTargetData]; - if (callback !== null && listeners[type]) { - listeners[type] = ArrayPrototypeFilter( - listeners[type], - (listener) => listener.callback !== callback, - ); - } else if (callback === null || !listeners[type]) { + if (callback === null || !listeners[type]) { return; } @@ -1274,6 +1272,7 @@ class CustomEvent extends Event { const CustomEventPrototype = CustomEvent.prototype; ReflectDefineProperty(CustomEvent.prototype, "detail", { + __proto__: null, enumerable: true, }); @@ -1417,6 +1416,7 @@ function defineEventHandler( ) { // HTML specification section 8.1.7.1 ObjectDefineProperty(emitter, `on${name}`, { + __proto__: null, get() { if (!this[_eventHandlers]) { return null; diff --git a/ext/web/02_timers.js b/ext/web/02_timers.js index 5591478619..89acaca42b 100644 --- a/ext/web/02_timers.js +++ b/ext/web/02_timers.js @@ -11,6 +11,10 @@ const { indirectEval, ReflectApply, } = primordials; +const { + getAsyncContext, + setAsyncContext, +} = core; import * as webidl from "ext:deno_webidl/00_webidl.js"; @@ -33,14 +37,16 @@ function checkThis(thisArg) { * Call a callback function immediately. */ function setImmediate(callback, ...args) { - if (args.length > 0) { - const unboundCallback = callback; - callback = () => ReflectApply(unboundCallback, globalThis, args); - } - - return core.queueImmediate( - callback, - ); + const asyncContext = getAsyncContext(); + return core.queueImmediate(() => { + const oldContext = getAsyncContext(); + try { + setAsyncContext(asyncContext); + return ReflectApply(callback, globalThis, args); + } finally { + setAsyncContext(oldContext); + } + }); } /** @@ -53,10 +59,17 @@ function setTimeout(callback, timeout = 0, ...args) { const unboundCallback = webidl.converters.DOMString(callback); callback = () => indirectEval(unboundCallback); } - if (args.length > 0) { - const unboundCallback = callback; - callback = () => ReflectApply(unboundCallback, globalThis, args); - } + const unboundCallback = callback; + const asyncContext = getAsyncContext(); + callback = () => { + const oldContext = getAsyncContext(); + try { + setAsyncContext(asyncContext); + ReflectApply(unboundCallback, globalThis, args); + } finally { + setAsyncContext(oldContext); + } + }; timeout = webidl.converters.long(timeout); return core.queueUserTimer( core.getTimerDepth() + 1, @@ -75,10 +88,17 @@ function setInterval(callback, timeout = 0, ...args) { const unboundCallback = webidl.converters.DOMString(callback); callback = () => indirectEval(unboundCallback); } - if (args.length > 0) { - const unboundCallback = callback; - callback = () => ReflectApply(unboundCallback, globalThis, args); - } + const unboundCallback = callback; + const asyncContext = getAsyncContext(); + callback = () => { + const oldContext = getAsyncContext(asyncContext); + try { + setAsyncContext(asyncContext); + ReflectApply(unboundCallback, globalThis, args); + } finally { + setAsyncContext(oldContext); + } + }; timeout = webidl.converters.long(timeout); return core.queueUserTimer( core.getTimerDepth() + 1, diff --git a/ext/web/03_abort_signal.js b/ext/web/03_abort_signal.js index 81844d53fc..ae0701451b 100644 --- a/ext/web/03_abort_signal.js +++ b/ext/web/03_abort_signal.js @@ -71,6 +71,7 @@ class WeakRefSet { const add = Symbol("[[add]]"); const signalAbort = Symbol("[[signalAbort]]"); const remove = Symbol("[[remove]]"); +const runAbortSteps = Symbol("[[runAbortSteps]]"); const abortReason = Symbol("[[abortReason]]"); const abortAlgos = Symbol("[[abortAlgos]]"); const dependent = Symbol("[[dependent]]"); @@ -149,26 +150,43 @@ class AbortSignal extends EventTarget { return; } this[abortReason] = reason; + + const dependentSignalsToAbort = []; + if (this[dependentSignals] !== null) { + const dependentSignalArray = this[dependentSignals].toArray(); + for (let i = 0; i < dependentSignalArray.length; ++i) { + const dependentSignal = dependentSignalArray[i]; + if (dependentSignal[abortReason] === undefined) { + dependentSignal[abortReason] = this[abortReason]; + ArrayPrototypePush(dependentSignalsToAbort, dependentSignal); + } + } + } + + this[runAbortSteps](); + + if (dependentSignalsToAbort.length !== 0) { + for (let i = 0; i < dependentSignalsToAbort.length; ++i) { + const dependentSignal = dependentSignalsToAbort[i]; + dependentSignal[runAbortSteps](); + } + } + } + + [runAbortSteps]() { const algos = this[abortAlgos]; this[abortAlgos] = null; - if (listenerCount(this, "abort") > 0) { - const event = new Event("abort"); - setIsTrusted(event, true); - super.dispatchEvent(event); - } if (algos !== null) { for (const algorithm of new SafeSetIterator(algos)) { algorithm(); } } - if (this[dependentSignals] !== null) { - const dependentSignalArray = this[dependentSignals].toArray(); - for (let i = 0; i < dependentSignalArray.length; ++i) { - const dependentSignal = dependentSignalArray[i]; - dependentSignal[signalAbort](reason); - } + if (listenerCount(this, "abort") > 0) { + const event = new Event("abort"); + setIsTrusted(event, true); + super.dispatchEvent(event); } } diff --git a/ext/web/06_streams.js b/ext/web/06_streams.js index ea3a3110f6..a4f2275c52 100644 --- a/ext/web/06_streams.js +++ b/ext/web/06_streams.js @@ -70,6 +70,7 @@ const { String, Symbol, SymbolAsyncIterator, + SymbolIterator, SymbolFor, TypeError, TypedArrayPrototypeGetBuffer, @@ -164,6 +165,7 @@ function resolvePromiseWith(value) { function rethrowAssertionErrorRejection(e) { if (e && ObjectPrototypeIsPrototypeOf(AssertionError.prototype, e)) { queueMicrotask(() => { + // deno-lint-ignore no-console console.error(`Internal Error: ${e.stack}`); }); } @@ -522,10 +524,10 @@ function dequeueValue(container) { function enqueueValueWithSize(container, value, size) { assert(container[_queue] && typeof container[_queueTotalSize] === "number"); if (isNonNegativeNumber(size) === false) { - throw RangeError("chunk size isn't a positive number"); + throw new RangeError("chunk size isn't a positive number"); } if (size === Infinity) { - throw RangeError("chunk size is invalid"); + throw new RangeError("chunk size is invalid"); } container[_queue].enqueue({ value, size }); container[_queueTotalSize] += size; @@ -541,7 +543,7 @@ function extractHighWaterMark(strategy, defaultHWM) { } const highWaterMark = strategy.highWaterMark; if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { - throw RangeError( + throw new RangeError( `Expected highWaterMark to be a positive number or Infinity, got "${highWaterMark}".`, ); } @@ -1052,7 +1054,7 @@ async function readableStreamCollectIntoUint8Array(stream) { getReadableStreamResourceBackingUnrefable(stream); const reader = acquireReadableStreamDefaultReader(stream); - if (resourceBacking) { + if (resourceBacking && !isReadableStreamDisturbed(stream)) { // fast path, read whole body in a single op call try { readableStreamDisturb(stream); @@ -5082,6 +5084,34 @@ function initializeCountSizeFunction(globalObject) { WeakMapPrototypeSet(countSizeFunctionWeakMap, globalObject, size); } +// Ref: https://tc39.es/ecma262/#sec-getiterator +function getAsyncOrSyncIterator(obj) { + let iterator; + if (obj[SymbolAsyncIterator] != null) { + iterator = obj[SymbolAsyncIterator](); + if (!isObject(iterator)) { + throw new TypeError( + "[Symbol.asyncIterator] returned a non-object value", + ); + } + } else if (obj[SymbolIterator] != null) { + iterator = obj[SymbolIterator](); + if (!isObject(iterator)) { + throw new TypeError("[Symbol.iterator] returned a non-object value"); + } + } else { + throw new TypeError("No iterator found"); + } + if (typeof iterator.next !== "function") { + throw new TypeError("iterator.next is not a function"); + } + return iterator; +} + +function isObject(x) { + return (typeof x === "object" && x != null) || typeof x === "function"; +} + const _resourceBacking = Symbol("[[resourceBacking]]"); // This distinction exists to prevent unrefable streams being used in // regular fast streams that are unaware of refability @@ -5167,22 +5197,21 @@ class ReadableStream { } static from(asyncIterable) { - const prefix = "Failed to execute 'ReadableStream.from'"; webidl.requiredArguments( arguments.length, 1, - prefix, + "Failed to execute 'ReadableStream.from'", ); - asyncIterable = webidl.converters["async iterable"]( - asyncIterable, - prefix, - "Argument 1", - ); - const iter = asyncIterable.open(); + asyncIterable = webidl.converters.any(asyncIterable); + + const iterator = getAsyncOrSyncIterator(asyncIterable); const stream = createReadableStream(noop, async () => { // deno-lint-ignore prefer-primordials - const res = await iter.next(); + const res = await iterator.next(); + if (!isObject(res)) { + throw new TypeError("iterator.next value is not an object"); + } if (res.done) { readableStreamDefaultControllerClose(stream[_controller]); } else { @@ -5192,8 +5221,17 @@ class ReadableStream { ); } }, async (reason) => { - // deno-lint-ignore prefer-primordials - await iter.return(reason); + if (iterator.return == null) { + return undefined; + } else { + // deno-lint-ignore prefer-primordials + const res = await iterator.return(reason); + if (!isObject(res)) { + throw new TypeError("iterator.return value is not an object"); + } else { + return undefined; + } + } }, 0); return stream; } @@ -5382,6 +5420,7 @@ class ReadableStream { // TODO(lucacasonato): should be moved to webidl crate ReadableStream.prototype[SymbolAsyncIterator] = ReadableStream.prototype.values; ObjectDefineProperty(ReadableStream.prototype, SymbolAsyncIterator, { + __proto__: null, writable: true, enumerable: false, configurable: true, @@ -6853,10 +6892,6 @@ webidl.converters.StreamPipeOptions = webidl { key: "signal", converter: webidl.converters.AbortSignal }, ]); -webidl.converters["async iterable"] = webidl.createAsyncIterableConverter( - webidl.converters.any, -); - internals.resourceForReadableStream = resourceForReadableStream; export { diff --git a/ext/web/06_streams_types.d.ts b/ext/web/06_streams_types.d.ts index 19eb597d2e..e04f568d26 100644 --- a/ext/web/06_streams_types.d.ts +++ b/ext/web/06_streams_types.d.ts @@ -71,5 +71,10 @@ interface ReadableStreamGenericReader { declare function queueMicrotask(callback: VoidFunction): void; declare namespace Deno { - function inspect(value: unknown, options?: Record): string; + export function inspect( + value: unknown, + options?: Record, + ): string; + + export {}; // only export exports } diff --git a/ext/web/10_filereader.js b/ext/web/10_filereader.js index 05f5771143..05b45202d6 100644 --- a/ext/web/10_filereader.js +++ b/ext/web/10_filereader.js @@ -454,36 +454,42 @@ webidl.configureInterface(FileReader); const FileReaderPrototype = FileReader.prototype; ObjectDefineProperty(FileReader, "EMPTY", { + __proto__: null, writable: false, enumerable: true, configurable: false, value: 0, }); ObjectDefineProperty(FileReader, "LOADING", { + __proto__: null, writable: false, enumerable: true, configurable: false, value: 1, }); ObjectDefineProperty(FileReader, "DONE", { + __proto__: null, writable: false, enumerable: true, configurable: false, value: 2, }); ObjectDefineProperty(FileReader.prototype, "EMPTY", { + __proto__: null, writable: false, enumerable: true, configurable: false, value: 0, }); ObjectDefineProperty(FileReader.prototype, "LOADING", { + __proto__: null, writable: false, enumerable: true, configurable: false, value: 1, }); ObjectDefineProperty(FileReader.prototype, "DONE", { + __proto__: null, writable: false, enumerable: true, configurable: false, diff --git a/ext/web/12_location.js b/ext/web/12_location.js index a819f6a07c..2cda9f719c 100644 --- a/ext/web/12_location.js +++ b/ext/web/12_location.js @@ -35,6 +35,7 @@ class Location { url.password = ""; ObjectDefineProperties(this, { hash: { + __proto__: null, get() { return url.hash; }, @@ -47,6 +48,7 @@ class Location { enumerable: true, }, host: { + __proto__: null, get() { return url.host; }, @@ -59,6 +61,7 @@ class Location { enumerable: true, }, hostname: { + __proto__: null, get() { return url.hostname; }, @@ -71,6 +74,7 @@ class Location { enumerable: true, }, href: { + __proto__: null, get() { return url.href; }, @@ -83,12 +87,14 @@ class Location { enumerable: true, }, origin: { + __proto__: null, get() { return url.origin; }, enumerable: true, }, pathname: { + __proto__: null, get() { return url.pathname; }, @@ -101,6 +107,7 @@ class Location { enumerable: true, }, port: { + __proto__: null, get() { return url.port; }, @@ -113,6 +120,7 @@ class Location { enumerable: true, }, protocol: { + __proto__: null, get() { return url.protocol; }, @@ -125,6 +133,7 @@ class Location { enumerable: true, }, search: { + __proto__: null, get() { return url.search; }, @@ -137,6 +146,7 @@ class Location { enumerable: true, }, ancestorOrigins: { + __proto__: null, get() { // TODO(nayeemrmn): Replace with a `DOMStringList` instance. return { @@ -148,6 +158,7 @@ class Location { enumerable: true, }, assign: { + __proto__: null, value: function assign() { throw new DOMException( `Cannot call "location.assign()".`, @@ -157,6 +168,7 @@ class Location { enumerable: true, }, reload: { + __proto__: null, value: function reload() { throw new DOMException( `Cannot call "location.reload()".`, @@ -166,6 +178,7 @@ class Location { enumerable: true, }, replace: { + __proto__: null, value: function replace() { throw new DOMException( `Cannot call "location.replace()".`, @@ -175,12 +188,14 @@ class Location { enumerable: true, }, toString: { + __proto__: null, value: function toString() { return url.href; }, enumerable: true, }, [SymbolFor("Deno.privateCustomInspect")]: { + __proto__: null, value: function (inspect, inspectOptions) { return `${this.constructor.name} ${ inspect({ @@ -203,6 +218,7 @@ class Location { ObjectDefineProperties(Location.prototype, { [SymbolToStringTag]: { + __proto__: null, value: "Location", configurable: true, }, @@ -224,6 +240,7 @@ class WorkerLocation { ObjectDefineProperties(WorkerLocation.prototype, { hash: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -235,6 +252,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, host: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -246,6 +264,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, hostname: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -257,6 +276,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, href: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -268,6 +288,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, origin: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -279,6 +300,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, pathname: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -290,6 +312,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, port: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -301,6 +324,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, protocol: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -312,6 +336,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, search: { + __proto__: null, get() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -323,6 +348,7 @@ ObjectDefineProperties(WorkerLocation.prototype, { enumerable: true, }, toString: { + __proto__: null, value: function toString() { const url = WeakMapPrototypeGet(workerLocationUrls, this); if (url == null) { @@ -335,10 +361,12 @@ ObjectDefineProperties(WorkerLocation.prototype, { writable: true, }, [SymbolToStringTag]: { + __proto__: null, value: "WorkerLocation", configurable: true, }, [SymbolFor("Deno.privateCustomInspect")]: { + __proto__: null, value: function (inspect, inspectOptions) { return `${this.constructor.name} ${ inspect({ diff --git a/ext/web/13_message_port.js b/ext/web/13_message_port.js index d94ca13826..cf72c43e6f 100644 --- a/ext/web/13_message_port.js +++ b/ext/web/13_message_port.js @@ -22,6 +22,7 @@ const { Symbol, SymbolFor, SymbolIterator, + PromiseResolve, SafeArrayIterator, TypeError, } = primordials; @@ -41,7 +42,10 @@ import { import { isDetachedBuffer } from "./06_streams.js"; import { DOMException } from "./01_dom_exception.js"; -let messageEventListenerCount = 0; +// counter of how many message ports are actively refed +// either due to the existence of "message" event listeners or +// explicit calls to ref/unref (in the case of node message ports) +let refedMessagePortsCount = 0; class MessageChannel { /** @type {MessagePort} */ @@ -93,6 +97,7 @@ const MessagePortReceiveMessageOnPortSymbol = Symbol( ); const _enabled = Symbol("enabled"); const _refed = Symbol("refed"); +const _messageEventListenerCount = Symbol("messageEventListenerCount"); const nodeWorkerThreadCloseCb = Symbol("nodeWorkerThreadCloseCb"); const nodeWorkerThreadCloseCbInvoked = Symbol("nodeWorkerThreadCloseCbInvoked"); export const refMessagePort = Symbol("refMessagePort"); @@ -109,6 +114,9 @@ function createMessagePort(id) { port[core.hostObjectBrand] = core.hostObjectBrand; setEventTargetData(port); port[_id] = id; + port[_enabled] = false; + port[_messageEventListenerCount] = 0; + port[_refed] = false; return port; } @@ -122,24 +130,33 @@ function nodeWorkerThreadMaybeInvokeCloseCb(port) { } } +const _isRefed = Symbol("isRefed"); +const _dataPromise = Symbol("dataPromise"); + class MessagePort extends EventTarget { /** @type {number | null} */ [_id] = null; /** @type {boolean} */ [_enabled] = false; [_refed] = false; + /** @type {Promise | undefined} */ + [_dataPromise] = undefined; + [_messageEventListenerCount] = 0; constructor() { super(); ObjectDefineProperty(this, MessagePortReceiveMessageOnPortSymbol, { + __proto__: null, value: false, enumerable: false, }); ObjectDefineProperty(this, nodeWorkerThreadCloseCb, { + __proto__: null, value: null, enumerable: false, }); ObjectDefineProperty(this, nodeWorkerThreadCloseCbInvoked, { + __proto__: null, value: false, enumerable: false, }); @@ -190,24 +207,21 @@ class MessagePort extends EventTarget { this[_enabled] = true; while (true) { if (this[_id] === null) break; - // Exit if no message event listeners are present in Node compat mode. - if ( - typeof this[nodeWorkerThreadCloseCb] == "function" && - messageEventListenerCount === 0 - ) break; let data; try { - data = await op_message_port_recv_message( + this[_dataPromise] = op_message_port_recv_message( this[_id], ); + if ( + typeof this[nodeWorkerThreadCloseCb] === "function" && + !this[_refed] + ) { + core.unrefOpPromise(this[_dataPromise]); + } + data = await this[_dataPromise]; + this[_dataPromise] = undefined; } catch (err) { if (ObjectPrototypeIsPrototypeOf(InterruptedPrototype, err)) { - // If we were interrupted, check if the interruption is coming - // from `receiveMessageOnPort` API from Node compat, if so, continue. - if (this[MessagePortReceiveMessageOnPortSymbol]) { - this[MessagePortReceiveMessageOnPortSymbol] = false; - continue; - } break; } nodeWorkerThreadMaybeInvokeCloseCb(this); @@ -243,12 +257,26 @@ class MessagePort extends EventTarget { } [refMessagePort](ref) { - if (ref && !this[_refed]) { - this[_refed] = true; - messageEventListenerCount++; - } else if (!ref && this[_refed]) { - this[_refed] = false; - messageEventListenerCount = 0; + if (ref) { + if (!this[_refed]) { + refedMessagePortsCount++; + if ( + this[_dataPromise] + ) { + core.refOpPromise(this[_dataPromise]); + } + this[_refed] = true; + } + } else if (!ref) { + if (this[_refed]) { + refedMessagePortsCount--; + if ( + this[_dataPromise] + ) { + core.unrefOpPromise(this[_dataPromise]); + } + this[_refed] = false; + } } } @@ -263,15 +291,20 @@ class MessagePort extends EventTarget { removeEventListener(...args) { if (args[0] == "message") { - messageEventListenerCount--; + if (--this[_messageEventListenerCount] === 0 && this[_refed]) { + refedMessagePortsCount--; + this[_refed] = false; + } } super.removeEventListener(...new SafeArrayIterator(args)); } addEventListener(...args) { if (args[0] == "message") { - messageEventListenerCount++; - if (!this[_refed]) this[_refed] = true; + if (++this[_messageEventListenerCount] === 1 && !this[_refed]) { + refedMessagePortsCount++; + this[_refed] = true; + } } super.addEventListener(...new SafeArrayIterator(args)); } @@ -292,7 +325,17 @@ class MessagePort extends EventTarget { } defineEventHandler(MessagePort.prototype, "message", function (self) { - self.start(); + if (self[nodeWorkerThreadCloseCb]) { + (async () => { + // delay `start()` until he end of this event loop turn, to give `receiveMessageOnPort` + // a chance to receive a message first. this is primarily to resolve an issue with + // a pattern used in `npm:piscina` that results in an indefinite hang + await PromiseResolve(); + self.start(); + })(); + } else { + self.start(); + } }); defineEventHandler(MessagePort.prototype, "messageerror"); @@ -460,12 +503,12 @@ function structuredClone(value, options) { export { deserializeJsMessageData, MessageChannel, - messageEventListenerCount, MessagePort, MessagePortIdSymbol, MessagePortPrototype, MessagePortReceiveMessageOnPortSymbol, nodeWorkerThreadCloseCb, + refedMessagePortsCount, serializeJsMessageData, structuredClone, }; diff --git a/ext/web/15_performance.js b/ext/web/15_performance.js index 5045c0d318..ea55572781 100644 --- a/ext/web/15_performance.js +++ b/ext/web/15_performance.js @@ -3,10 +3,7 @@ import { primordials } from "ext:core/mod.js"; const { ArrayPrototypeFilter, - ArrayPrototypeFind, ArrayPrototypePush, - ArrayPrototypeReverse, - ArrayPrototypeSlice, ObjectKeys, ObjectPrototypeIsPrototypeOf, ReflectHas, @@ -101,10 +98,12 @@ function findMostRecent( name, type, ) { - return ArrayPrototypeFind( - ArrayPrototypeReverse(ArrayPrototypeSlice(performanceEntries)), - (entry) => entry.name === name && entry.entryType === type, - ); + for (let i = performanceEntries.length - 1; i >= 0; --i) { + const entry = performanceEntries[i]; + if (entry.name === name && entry.entryType === type) { + return entry; + } + } } function convertMarkToTimestamp(mark) { diff --git a/ext/web/Cargo.toml b/ext/web/Cargo.toml index f5948685e5..0cb08e19c1 100644 --- a/ext/web/Cargo.toml +++ b/ext/web/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_web" -version = "0.195.0" +version = "0.205.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -23,6 +23,7 @@ encoding_rs.workspace = true flate2 = { workspace = true, features = ["default"] } futures.workspace = true serde = "1.0.149" +thiserror.workspace = true tokio.workspace = true uuid = { workspace = true, features = ["serde"] } diff --git a/ext/web/blob.rs b/ext/web/blob.rs index 392f36acb8..bc64a0f27e 100644 --- a/ext/web/blob.rs +++ b/ext/web/blob.rs @@ -7,8 +7,6 @@ use std::rc::Rc; use std::sync::Arc; use async_trait::async_trait; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::parking_lot::Mutex; use deno_core::url::Url; @@ -19,6 +17,18 @@ use serde::Deserialize; use serde::Serialize; use uuid::Uuid; +#[derive(Debug, thiserror::Error)] +pub enum BlobError { + #[error("Blob part not found")] + BlobPartNotFound, + #[error("start + len can not be larger than blob part size")] + SizeLargerThanBlobPart, + #[error("Blob URLs are not supported in this context")] + BlobURLsNotSupported, + #[error(transparent)] + Url(#[from] deno_core::url::ParseError), +} + use crate::Location; pub type PartMap = HashMap>; @@ -96,18 +106,18 @@ pub struct Blob { impl Blob { // TODO(lucacsonato): this should be a stream! - pub async fn read_all(&self) -> Result, AnyError> { + pub async fn read_all(&self) -> Vec { let size = self.size(); let mut bytes = Vec::with_capacity(size); for part in &self.parts { - let chunk = part.read().await?; + let chunk = part.read().await; bytes.extend_from_slice(chunk); } assert_eq!(bytes.len(), size); - Ok(bytes) + bytes } fn size(&self) -> usize { @@ -122,7 +132,7 @@ impl Blob { #[async_trait] pub trait BlobPart: Debug { // TODO(lucacsonato): this should be a stream! - async fn read(&self) -> Result<&[u8], AnyError>; + async fn read(&self) -> &[u8]; fn size(&self) -> usize; } @@ -137,8 +147,8 @@ impl From> for InMemoryBlobPart { #[async_trait] impl BlobPart for InMemoryBlobPart { - async fn read(&self) -> Result<&[u8], AnyError> { - Ok(&self.0) + async fn read(&self) -> &[u8] { + &self.0 } fn size(&self) -> usize { @@ -155,9 +165,9 @@ pub struct SlicedBlobPart { #[async_trait] impl BlobPart for SlicedBlobPart { - async fn read(&self) -> Result<&[u8], AnyError> { - let original = self.part.read().await?; - Ok(&original[self.start..self.start + self.len]) + async fn read(&self) -> &[u8] { + let original = self.part.read().await; + &original[self.start..self.start + self.len] } fn size(&self) -> usize { @@ -189,19 +199,17 @@ pub fn op_blob_slice_part( state: &mut OpState, #[serde] id: Uuid, #[serde] options: SliceOptions, -) -> Result { +) -> Result { let blob_store = state.borrow::>(); let part = blob_store .get_part(&id) - .ok_or_else(|| type_error("Blob part not found"))?; + .ok_or(BlobError::BlobPartNotFound)?; let SliceOptions { start, len } = options; let size = part.size(); if start + len > size { - return Err(type_error( - "start + len can not be larger than blob part size", - )); + return Err(BlobError::SizeLargerThanBlobPart); } let sliced_part = SlicedBlobPart { part, start, len }; @@ -215,14 +223,14 @@ pub fn op_blob_slice_part( pub async fn op_blob_read_part( state: Rc>, #[serde] id: Uuid, -) -> Result { +) -> Result { let part = { let state = state.borrow(); let blob_store = state.borrow::>(); blob_store.get_part(&id) } - .ok_or_else(|| type_error("Blob part not found"))?; - let buf = part.read().await?; + .ok_or(BlobError::BlobPartNotFound)?; + let buf = part.read().await; Ok(ToJsBuffer::from(buf.to_vec())) } @@ -238,13 +246,13 @@ pub fn op_blob_create_object_url( state: &mut OpState, #[string] media_type: String, #[serde] part_ids: Vec, -) -> Result { +) -> Result { let mut parts = Vec::with_capacity(part_ids.len()); let blob_store = state.borrow::>(); for part_id in part_ids { let part = blob_store .get_part(&part_id) - .ok_or_else(|| type_error("Blob part not found"))?; + .ok_or(BlobError::BlobPartNotFound)?; parts.push(part); } @@ -263,7 +271,7 @@ pub fn op_blob_create_object_url( pub fn op_blob_revoke_object_url( state: &mut OpState, #[string] url: &str, -) -> Result<(), AnyError> { +) -> Result<(), BlobError> { let url = Url::parse(url)?; let blob_store = state.borrow::>(); blob_store.remove_object_url(&url); @@ -287,15 +295,15 @@ pub struct ReturnBlobPart { pub fn op_blob_from_object_url( state: &mut OpState, #[string] url: String, -) -> Result, AnyError> { +) -> Result, BlobError> { let url = Url::parse(&url)?; if url.scheme() != "blob" { return Ok(None); } - let blob_store = state.try_borrow::>().ok_or_else(|| { - type_error("Blob URLs are not supported in this context.") - })?; + let blob_store = state + .try_borrow::>() + .ok_or(BlobError::BlobURLsNotSupported)?; if let Some(blob) = blob_store.get_object_url(url) { let parts = blob .parts diff --git a/ext/web/compression.rs b/ext/web/compression.rs index b9ae12ef17..6967009915 100644 --- a/ext/web/compression.rs +++ b/ext/web/compression.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use flate2::write::DeflateDecoder; use flate2::write::DeflateEncoder; @@ -13,6 +11,18 @@ use flate2::Compression; use std::cell::RefCell; use std::io::Write; +#[derive(Debug, thiserror::Error)] +pub enum CompressionError { + #[error("Unsupported format")] + UnsupportedFormat, + #[error("resource is closed")] + ResourceClosed, + #[error(transparent)] + IoTypeError(std::io::Error), + #[error(transparent)] + Io(std::io::Error), +} + #[derive(Debug)] struct CompressionResource(RefCell>); @@ -34,7 +44,7 @@ enum Inner { pub fn op_compression_new( #[string] format: &str, is_decoder: bool, -) -> Result { +) -> Result { let w = Vec::new(); let inner = match (format, is_decoder) { ("deflate", true) => Inner::DeflateDecoder(ZlibDecoder::new(w)), @@ -49,7 +59,7 @@ pub fn op_compression_new( ("gzip", false) => { Inner::GzEncoder(GzEncoder::new(w, Compression::default())) } - _ => return Err(type_error("Unsupported format")), + _ => return Err(CompressionError::UnsupportedFormat), }; Ok(CompressionResource(RefCell::new(Some(inner)))) } @@ -59,40 +69,38 @@ pub fn op_compression_new( pub fn op_compression_write( #[cppgc] resource: &CompressionResource, #[anybuffer] input: &[u8], -) -> Result, AnyError> { +) -> Result, CompressionError> { let mut inner = resource.0.borrow_mut(); - let inner = inner - .as_mut() - .ok_or_else(|| type_error("resource is closed"))?; + let inner = inner.as_mut().ok_or(CompressionError::ResourceClosed)?; let out: Vec = match &mut *inner { Inner::DeflateDecoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } Inner::DeflateEncoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } Inner::DeflateRawDecoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } Inner::DeflateRawEncoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } Inner::GzDecoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } Inner::GzEncoder(d) => { - d.write_all(input).map_err(|e| type_error(e.to_string()))?; - d.flush()?; + d.write_all(input).map_err(CompressionError::IoTypeError)?; + d.flush().map_err(CompressionError::Io)?; d.get_mut().drain(..) } } @@ -105,27 +113,27 @@ pub fn op_compression_write( pub fn op_compression_finish( #[cppgc] resource: &CompressionResource, report_errors: bool, -) -> Result, AnyError> { +) -> Result, CompressionError> { let inner = resource .0 .borrow_mut() .take() - .ok_or_else(|| type_error("resource is closed"))?; + .ok_or(CompressionError::ResourceClosed)?; let out = match inner { Inner::DeflateDecoder(d) => { - d.finish().map_err(|e| type_error(e.to_string())) + d.finish().map_err(CompressionError::IoTypeError) } Inner::DeflateEncoder(d) => { - d.finish().map_err(|e| type_error(e.to_string())) + d.finish().map_err(CompressionError::IoTypeError) } Inner::DeflateRawDecoder(d) => { - d.finish().map_err(|e| type_error(e.to_string())) + d.finish().map_err(CompressionError::IoTypeError) } Inner::DeflateRawEncoder(d) => { - d.finish().map_err(|e| type_error(e.to_string())) + d.finish().map_err(CompressionError::IoTypeError) } - Inner::GzDecoder(d) => d.finish().map_err(|e| type_error(e.to_string())), - Inner::GzEncoder(d) => d.finish().map_err(|e| type_error(e.to_string())), + Inner::GzDecoder(d) => d.finish().map_err(CompressionError::IoTypeError), + Inner::GzEncoder(d) => d.finish().map_err(CompressionError::IoTypeError), }; match out { Err(err) => { diff --git a/ext/web/lib.deno_web.d.ts b/ext/web/lib.deno_web.d.ts index 3fadfa4291..2ad97ac7d1 100644 --- a/ext/web/lib.deno_web.d.ts +++ b/ext/web/lib.deno_web.d.ts @@ -6,7 +6,7 @@ /// /** @category Platform */ -declare interface DOMException extends Error { +interface DOMException extends Error { readonly name: string; readonly message: string; /** @deprecated */ @@ -70,7 +70,7 @@ declare var DOMException: { }; /** @category Events */ -declare interface EventInit { +interface EventInit { bubbles?: boolean; cancelable?: boolean; composed?: boolean; @@ -80,7 +80,7 @@ declare interface EventInit { * * @category Events */ -declare interface Event { +interface Event { /** Returns true or false depending on how event was initialized. True if * event goes through its target's ancestors in reverse tree order, and * false otherwise. */ @@ -163,7 +163,7 @@ declare var Event: { * * @category Events */ -declare interface EventTarget { +interface EventTarget { /** Appends an event listener for events whose type attribute value is type. * The callback argument sets the callback that will be invoked when the event * is dispatched. @@ -217,34 +217,34 @@ declare var EventTarget: { }; /** @category Events */ -declare interface EventListener { +interface EventListener { (evt: Event): void; } /** @category Events */ -declare interface EventListenerObject { +interface EventListenerObject { handleEvent(evt: Event): void; } /** @category Events */ -declare type EventListenerOrEventListenerObject = +type EventListenerOrEventListenerObject = | EventListener | EventListenerObject; /** @category Events */ -declare interface AddEventListenerOptions extends EventListenerOptions { +interface AddEventListenerOptions extends EventListenerOptions { once?: boolean; passive?: boolean; signal?: AbortSignal; } /** @category Events */ -declare interface EventListenerOptions { +interface EventListenerOptions { capture?: boolean; } /** @category Events */ -declare interface ProgressEventInit extends EventInit { +interface ProgressEventInit extends EventInit { lengthComputable?: boolean; loaded?: number; total?: number; @@ -256,8 +256,7 @@ declare interface ProgressEventInit extends EventInit { * * @category Events */ -declare interface ProgressEvent - extends Event { +interface ProgressEvent extends Event { readonly lengthComputable: boolean; readonly loaded: number; readonly target: T | null; @@ -296,13 +295,13 @@ declare function atob(s: string): string; declare function btoa(s: string): string; /** @category Encoding */ -declare interface TextDecoderOptions { +interface TextDecoderOptions { fatal?: boolean; ignoreBOM?: boolean; } /** @category Encoding */ -declare interface TextDecodeOptions { +interface TextDecodeOptions { stream?: boolean; } @@ -320,7 +319,7 @@ declare interface TextDecodeOptions { * * @category Encoding */ -declare interface TextDecoder extends TextDecoderCommon { +interface TextDecoder extends TextDecoderCommon { /** Turns binary data, often in the form of a Uint8Array, into a string given * the encoding. */ @@ -334,7 +333,7 @@ declare var TextDecoder: { }; /** @category Encoding */ -declare interface TextDecoderCommon { +interface TextDecoderCommon { /** Returns encoding's name, lowercased. */ readonly encoding: string; /** Returns true if error mode is "fatal", otherwise false. */ @@ -344,13 +343,13 @@ declare interface TextDecoderCommon { } /** @category Encoding */ -declare interface TextEncoderEncodeIntoResult { +interface TextEncoderEncodeIntoResult { read: number; written: number; } /** @category Encoding */ -declare interface TextEncoder extends TextEncoderCommon { +interface TextEncoder extends TextEncoderCommon { /** Returns the result of running UTF-8's encoder. */ encode(input?: string): Uint8Array; encodeInto(input: string, dest: Uint8Array): TextEncoderEncodeIntoResult; @@ -369,7 +368,7 @@ declare interface TextEncoder extends TextEncoderCommon { * * @category Encoding */ -declare interface TextEncoder extends TextEncoderCommon { +interface TextEncoder extends TextEncoderCommon { /** Turns a string into binary data (in the form of a Uint8Array) using UTF-8 encoding. */ encode(input?: string): Uint8Array; @@ -384,14 +383,13 @@ declare var TextEncoder: { }; /** @category Encoding */ -declare interface TextEncoderCommon { +interface TextEncoderCommon { /** Returns "utf-8". */ readonly encoding: string; } /** @category Encoding */ -declare interface TextDecoderStream - extends GenericTransformStream, TextDecoderCommon { +interface TextDecoderStream extends GenericTransformStream, TextDecoderCommon { readonly readable: ReadableStream; readonly writable: WritableStream; } @@ -403,8 +401,7 @@ declare var TextDecoderStream: { }; /** @category Encoding */ -declare interface TextEncoderStream - extends GenericTransformStream, TextEncoderCommon { +interface TextEncoderStream extends GenericTransformStream, TextEncoderCommon { readonly readable: ReadableStream; readonly writable: WritableStream; } @@ -420,7 +417,7 @@ declare var TextEncoderStream: { * * @category Platform */ -declare interface AbortController { +interface AbortController { /** Returns the AbortSignal object associated with this object. */ readonly signal: AbortSignal; /** Invoking this method will set this object's AbortSignal's aborted flag and @@ -439,7 +436,7 @@ declare var AbortController: { }; /** @category Platform */ -declare interface AbortSignalEventMap { +interface AbortSignalEventMap { abort: Event; } @@ -448,7 +445,7 @@ declare interface AbortSignalEventMap { * * @category Platform */ -declare interface AbortSignal extends EventTarget { +interface AbortSignal extends EventTarget { /** Returns true if this AbortSignal's AbortController has signaled to abort, * and false otherwise. */ readonly aborted: boolean; @@ -490,7 +487,7 @@ declare var AbortSignal: { }; /** @category File */ -declare interface FileReaderEventMap { +interface FileReaderEventMap { "abort": ProgressEvent; "error": ProgressEvent; "load": ProgressEvent; @@ -505,7 +502,7 @@ declare interface FileReaderEventMap { * * @category File */ -declare interface FileReader extends EventTarget { +interface FileReader extends EventTarget { readonly error: DOMException | null; onabort: ((this: FileReader, ev: ProgressEvent) => any) | null; onerror: ((this: FileReader, ev: ProgressEvent) => any) | null; @@ -561,13 +558,13 @@ declare var FileReader: { }; /** @category File */ -declare type BlobPart = BufferSource | Blob | string; +type BlobPart = BufferSource | Blob | string; /** @category File */ -declare type EndingType = "transparent" | "native"; +type EndingType = "transparent" | "native"; /** @category File */ -declare interface BlobPropertyBag { +interface BlobPropertyBag { type?: string; endings?: EndingType; } @@ -579,7 +576,7 @@ declare interface BlobPropertyBag { * * @category File */ -declare interface Blob { +interface Blob { readonly size: number; readonly type: string; arrayBuffer(): Promise; @@ -602,7 +599,7 @@ declare var Blob: { }; /** @category File */ -declare interface FilePropertyBag extends BlobPropertyBag { +interface FilePropertyBag extends BlobPropertyBag { lastModified?: number; } @@ -611,7 +608,7 @@ declare interface FilePropertyBag extends BlobPropertyBag { * * @category File */ -declare interface File extends Blob { +interface File extends Blob { readonly lastModified: number; readonly name: string; readonly webkitRelativePath: string; @@ -628,40 +625,40 @@ declare var File: { }; /** @category Streams */ -declare type ReadableStreamReader = +type ReadableStreamReader = | ReadableStreamDefaultReader | ReadableStreamBYOBReader; /** @category Streams */ -declare type ReadableStreamController = +type ReadableStreamController = | ReadableStreamDefaultController | ReadableByteStreamController; /** @category Streams */ -declare interface ReadableStreamGenericReader { +interface ReadableStreamGenericReader { readonly closed: Promise; cancel(reason?: any): Promise; } /** @category Streams */ -declare interface ReadableStreamReadDoneResult { +interface ReadableStreamReadDoneResult { done: true; value?: T; } /** @category Streams */ -declare interface ReadableStreamReadValueResult { +interface ReadableStreamReadValueResult { done: false; value: T; } /** @category Streams */ -declare type ReadableStreamReadResult = +type ReadableStreamReadResult = | ReadableStreamReadValueResult | ReadableStreamReadDoneResult; /** @category Streams */ -declare interface ReadableStreamDefaultReader +interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { read(): Promise>; releaseLock(): void; @@ -674,12 +671,12 @@ declare var ReadableStreamDefaultReader: { }; /** @category Streams */ -declare interface ReadableStreamBYOBReaderReadOptions { +interface ReadableStreamBYOBReaderReadOptions { min?: number; } /** @category Streams */ -declare interface ReadableStreamBYOBReader extends ReadableStreamGenericReader { +interface ReadableStreamBYOBReader extends ReadableStreamGenericReader { read( view: T, options?: ReadableStreamBYOBReaderReadOptions, @@ -694,7 +691,7 @@ declare var ReadableStreamBYOBReader: { }; /** @category Streams */ -declare interface ReadableStreamBYOBRequest { +interface ReadableStreamBYOBRequest { readonly view: ArrayBufferView | null; respond(bytesWritten: number): void; respondWithNewView(view: ArrayBufferView): void; @@ -706,17 +703,8 @@ declare var ReadableStreamBYOBRequest: { new (): never; }; -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingByteSource["pull"]` instead. - * @category Streams - */ -declare interface ReadableByteStreamControllerCallback { - (controller: ReadableByteStreamController): void | PromiseLike; -} - /** @category Streams */ -declare interface UnderlyingByteSource { +interface UnderlyingByteSource { autoAllocateChunkSize?: number; cancel?: UnderlyingSourceCancelCallback; pull?: (controller: ReadableByteStreamController) => void | PromiseLike; @@ -725,7 +713,7 @@ declare interface UnderlyingByteSource { } /** @category Streams */ -declare interface UnderlyingDefaultSource { +interface UnderlyingDefaultSource { cancel?: UnderlyingSourceCancelCallback; pull?: ( controller: ReadableStreamDefaultController, @@ -735,7 +723,7 @@ declare interface UnderlyingDefaultSource { } /** @category Streams */ -declare interface UnderlyingSink { +interface UnderlyingSink { abort?: UnderlyingSinkAbortCallback; close?: UnderlyingSinkCloseCallback; start?: UnderlyingSinkStartCallback; @@ -744,10 +732,10 @@ declare interface UnderlyingSink { } /** @category Streams */ -declare type ReadableStreamType = "bytes"; +type ReadableStreamType = "bytes"; /** @category Streams */ -declare interface UnderlyingSource { +interface UnderlyingSource { autoAllocateChunkSize?: number; cancel?: UnderlyingSourceCancelCallback; pull?: UnderlyingSourcePullCallback; @@ -755,39 +743,23 @@ declare interface UnderlyingSource { type?: ReadableStreamType; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingSourceCancelCallback` instead. - * @category Streams - */ -declare type ReadableStreamErrorCallback = UnderlyingSourceCancelCallback; - /** @category Streams */ -declare interface UnderlyingSourceCancelCallback { +interface UnderlyingSourceCancelCallback { (reason?: any): void | PromiseLike; } /** @category Streams */ -declare interface UnderlyingSourcePullCallback { +interface UnderlyingSourcePullCallback { (controller: ReadableStreamController): void | PromiseLike; } /** @category Streams */ -declare interface UnderlyingSourceStartCallback { +interface UnderlyingSourceStartCallback { (controller: ReadableStreamController): any; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `(controller: ReadableStreamDefaultController) => void | PromiseLike` type instead. - * @category Streams - */ -declare type ReadableStreamDefaultControllerCallback = ( - controller: ReadableStreamDefaultController, -) => void | PromiseLike; - /** @category Streams */ -declare interface ReadableStreamDefaultController { +interface ReadableStreamDefaultController { readonly desiredSize: number | null; close(): void; enqueue(chunk?: R): void; @@ -801,7 +773,7 @@ declare var ReadableStreamDefaultController: { }; /** @category Streams */ -declare interface ReadableByteStreamController { +interface ReadableByteStreamController { readonly byobRequest: ReadableStreamBYOBRequest | null; readonly desiredSize: number | null; close(): void; @@ -815,35 +787,21 @@ declare var ReadableByteStreamController: { new (): never; }; -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `StreamPipeOptions` instead. - * @category Streams - */ -declare type PipeOptions = StreamPipeOptions; - /** @category Streams */ -declare interface StreamPipeOptions { +interface StreamPipeOptions { preventAbort?: boolean; preventCancel?: boolean; preventClose?: boolean; signal?: AbortSignal; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `QueuingStrategySize` instead. - * @category Streams - */ -declare type QueuingStrategySizeCallback = QueuingStrategySize; - /** @category Streams */ -declare interface QueuingStrategySize { +interface QueuingStrategySize { (chunk: T): number; } /** @category Streams */ -declare interface QueuingStrategy { +interface QueuingStrategy { highWaterMark?: number; size?: QueuingStrategySize; } @@ -853,7 +811,7 @@ declare interface QueuingStrategy { * * @category Streams */ -declare interface CountQueuingStrategy extends QueuingStrategy { +interface CountQueuingStrategy extends QueuingStrategy { readonly highWaterMark: number; readonly size: QueuingStrategySize; } @@ -865,8 +823,7 @@ declare var CountQueuingStrategy: { }; /** @category Streams */ -declare interface ByteLengthQueuingStrategy - extends QueuingStrategy { +interface ByteLengthQueuingStrategy extends QueuingStrategy { readonly highWaterMark: number; readonly size: QueuingStrategySize; } @@ -878,7 +835,7 @@ declare var ByteLengthQueuingStrategy: { }; /** @category Streams */ -declare interface QueuingStrategyInit { +interface QueuingStrategyInit { highWaterMark: number; } @@ -888,7 +845,7 @@ declare interface QueuingStrategyInit { * * @category Streams */ -declare interface ReadableStream { +interface ReadableStream { readonly locked: boolean; cancel(reason?: any): Promise; getReader(options: { mode: "byob" }): ReadableStreamBYOBReader; @@ -930,75 +887,44 @@ declare var ReadableStream: { }; /** @category Streams */ -declare interface ReadableStreamIteratorOptions { +interface ReadableStreamIteratorOptions { preventCancel?: boolean; } /** @category Streams */ -declare type ReadableStreamReaderMode = "byob"; +type ReadableStreamReaderMode = "byob"; /** @category Streams */ -declare interface ReadableStreamGetReaderOptions { +interface ReadableStreamGetReaderOptions { mode?: ReadableStreamReaderMode; } /** @category Streams */ -declare interface ReadableWritablePair { +interface ReadableWritablePair { readable: ReadableStream; writable: WritableStream; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingSinkCloseCallback` instead. - * @category Streams - */ -declare type WritableStreamDefaultControllerCloseCallback = - UnderlyingSinkCloseCallback; - /** @category Streams */ -declare interface UnderlyingSinkCloseCallback { +interface UnderlyingSinkCloseCallback { (): void | PromiseLike; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingSinkStartCallback` instead. - * @category Streams - */ -declare type WritableStreamDefaultControllerStartCallback = - UnderlyingSinkStartCallback; - /** @category Streams */ -declare interface UnderlyingSinkStartCallback { +interface UnderlyingSinkStartCallback { (controller: WritableStreamDefaultController): any; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingSinkWriteCallback` instead. - * @category Streams - */ -declare type WritableStreamDefaultControllerWriteCallback = - UnderlyingSinkWriteCallback; - /** @category Streams */ -declare interface UnderlyingSinkWriteCallback { +interface UnderlyingSinkWriteCallback { ( chunk: W, controller: WritableStreamDefaultController, ): void | PromiseLike; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `UnderlyingSinkAbortCallback` instead. - * @category Streams - */ -declare type WritableStreamErrorCallback = UnderlyingSinkAbortCallback; - /** @category Streams */ -declare interface UnderlyingSinkAbortCallback { +interface UnderlyingSinkAbortCallback { (reason?: any): void | PromiseLike; } @@ -1008,7 +934,7 @@ declare interface UnderlyingSinkAbortCallback { * * @category Streams */ -declare interface WritableStream { +interface WritableStream { readonly locked: boolean; abort(reason?: any): Promise; close(): Promise; @@ -1031,7 +957,7 @@ declare var WritableStream: { * * @category Streams */ -declare interface WritableStreamDefaultController { +interface WritableStreamDefaultController { readonly signal: AbortSignal; error(e?: any): void; } @@ -1049,7 +975,7 @@ declare var WritableStreamDefaultController: { * * @category Streams */ -declare interface WritableStreamDefaultWriter { +interface WritableStreamDefaultWriter { readonly closed: Promise; readonly desiredSize: number | null; readonly ready: Promise; @@ -1066,7 +992,7 @@ declare var WritableStreamDefaultWriter: { }; /** @category Streams */ -declare interface TransformStream { +interface TransformStream { readonly readable: ReadableStream; readonly writable: WritableStream; } @@ -1082,7 +1008,7 @@ declare var TransformStream: { }; /** @category Streams */ -declare interface TransformStreamDefaultController { +interface TransformStreamDefaultController { readonly desiredSize: number | null; enqueue(chunk?: O): void; error(reason?: any): void; @@ -1096,7 +1022,7 @@ declare var TransformStreamDefaultController: { }; /** @category Streams */ -declare interface Transformer { +interface Transformer { flush?: TransformerFlushCallback; readableType?: undefined; start?: TransformerStartCallback; @@ -1105,34 +1031,18 @@ declare interface Transformer { writableType?: undefined; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `TransformerFlushCallback` instead. - * @category Streams - */ -declare type TransformStreamDefaultControllerCallback = - TransformerFlushCallback; - /** @category Streams */ -declare interface TransformerFlushCallback { +interface TransformerFlushCallback { (controller: TransformStreamDefaultController): void | PromiseLike; } /** @category Streams */ -declare interface TransformerStartCallback { +interface TransformerStartCallback { (controller: TransformStreamDefaultController): any; } -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `TransformerTransformCallback` instead. - * @category Streams - */ -declare type TransformStreamDefaultControllerTransformCallback = - TransformerTransformCallback; - /** @category Streams */ -declare interface TransformerTransformCallback { +interface TransformerTransformCallback { ( chunk: I, controller: TransformStreamDefaultController, @@ -1140,21 +1050,21 @@ declare interface TransformerTransformCallback { } /** @category Streams */ -declare interface TransformerCancelCallback { +interface TransformerCancelCallback { (reason: any): void | PromiseLike; } /** @category Streams */ -declare interface GenericTransformStream { +interface GenericTransformStream { readonly readable: ReadableStream; readonly writable: WritableStream; } /** @category Events */ -declare type MessageEventSource = Window | MessagePort; +type MessageEventSource = Window | MessagePort; /** @category Events */ -declare interface MessageEventInit extends EventInit { +interface MessageEventInit extends EventInit { data?: T; lastEventId?: string; origin?: string; @@ -1163,7 +1073,7 @@ declare interface MessageEventInit extends EventInit { } /** @category Events */ -declare interface MessageEvent extends Event { +interface MessageEvent extends Event { /** * Returns the data of the message. */ @@ -1201,17 +1111,10 @@ declare var MessageEvent: { }; /** @category Events */ -declare type Transferable = MessagePort | ArrayBuffer; - -// TODO(petamoriken): Will be removed in v2.0. -/** - * @deprecated use `StructuredSerializeOptions` instead. - * @category Events - */ -declare type PostMessageOptions = StructuredSerializeOptions; +type Transferable = MessagePort | ArrayBuffer; /** @category Platform */ -declare interface StructuredSerializeOptions { +interface StructuredSerializeOptions { transfer?: Transferable[]; } @@ -1221,7 +1124,7 @@ declare interface StructuredSerializeOptions { * * @category Messaging */ -declare interface MessageChannel { +interface MessageChannel { readonly port1: MessagePort; readonly port2: MessagePort; } @@ -1238,7 +1141,7 @@ declare var MessageChannel: { }; /** @category Messaging */ -declare interface MessagePortEventMap { +interface MessagePortEventMap { "message": MessageEvent; "messageerror": MessageEvent; } @@ -1249,7 +1152,7 @@ declare interface MessagePortEventMap { * * @category Messaging */ -declare interface MessagePort extends EventTarget { +interface MessagePort extends EventTarget { onmessage: ((this: MessagePort, ev: MessageEvent) => any) | null; onmessageerror: ((this: MessagePort, ev: MessageEvent) => any) | null; /** @@ -1348,13 +1251,13 @@ declare function structuredClone( * * @category Streams */ -declare interface CompressionStream extends GenericTransformStream { +interface CompressionStream extends GenericTransformStream { readonly readable: ReadableStream; readonly writable: WritableStream; } /** @category Streams */ -declare type CompressionFormat = "deflate" | "deflate-raw" | "gzip"; +type CompressionFormat = "deflate" | "deflate-raw" | "gzip"; /** * An API for compressing a stream of data. @@ -1395,7 +1298,7 @@ declare var CompressionStream: { * * @category Streams */ -declare interface DecompressionStream extends GenericTransformStream { +interface DecompressionStream extends GenericTransformStream { readonly readable: ReadableStream; readonly writable: WritableStream; } @@ -1449,15 +1352,15 @@ declare function reportError( ): void; /** @category Platform */ -declare type PredefinedColorSpace = "srgb" | "display-p3"; +type PredefinedColorSpace = "srgb" | "display-p3"; /** @category Platform */ -declare interface ImageDataSettings { +interface ImageDataSettings { readonly colorSpace?: PredefinedColorSpace; } /** @category Platform */ -declare interface ImageData { +interface ImageData { readonly colorSpace: PredefinedColorSpace; readonly data: Uint8ClampedArray; readonly height: number; diff --git a/ext/web/lib.rs b/ext/web/lib.rs index 3977379a5d..4935af5bd3 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -6,9 +6,6 @@ mod message_port; mod stream_resource; mod timers; -use deno_core::error::range_error; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::url::Url; use deno_core::v8; @@ -22,10 +19,14 @@ use encoding_rs::DecoderResult; use encoding_rs::Encoding; use std::borrow::Cow; use std::cell::RefCell; -use std::fmt; use std::path::PathBuf; use std::sync::Arc; +pub use blob::BlobError; +pub use compression::CompressionError; +pub use message_port::MessagePortError; +pub use stream_resource::StreamResourceError; + use crate::blob::op_blob_create_object_url; use crate::blob::op_blob_create_part; use crate::blob::op_blob_from_object_url; @@ -126,9 +127,27 @@ deno_core::extension!(deno_web, } ); +#[derive(Debug, thiserror::Error)] +pub enum WebError { + #[error("Failed to decode base64")] + Base64Decode, + #[error("The encoding label provided ('{0}') is invalid.")] + InvalidEncodingLabel(String), + #[error("buffer exceeds maximum length")] + BufferTooLong, + #[error("Value too large to decode")] + ValueTooLarge, + #[error("Provided buffer too small")] + BufferTooSmall, + #[error("The encoded data is not valid")] + DataInvalid, + #[error(transparent)] + DataError(#[from] v8::DataError), +} + #[op2] #[serde] -fn op_base64_decode(#[string] input: String) -> Result { +fn op_base64_decode(#[string] input: String) -> Result { let mut s = input.into_bytes(); let decoded_len = forgiving_base64_decode_inplace(&mut s)?; s.truncate(decoded_len); @@ -137,7 +156,7 @@ fn op_base64_decode(#[string] input: String) -> Result { #[op2] #[serde] -fn op_base64_atob(#[serde] mut s: ByteString) -> Result { +fn op_base64_atob(#[serde] mut s: ByteString) -> Result { let decoded_len = forgiving_base64_decode_inplace(&mut s)?; s.truncate(decoded_len); Ok(s) @@ -147,11 +166,9 @@ fn op_base64_atob(#[serde] mut s: ByteString) -> Result { #[inline] fn forgiving_base64_decode_inplace( input: &mut [u8], -) -> Result { - let error = - || DomExceptionInvalidCharacterError::new("Failed to decode base64"); - let decoded = - base64_simd::forgiving_decode_inplace(input).map_err(|_| error())?; +) -> Result { + let decoded = base64_simd::forgiving_decode_inplace(input) + .map_err(|_| WebError::Base64Decode)?; Ok(decoded.len()) } @@ -177,13 +194,9 @@ fn forgiving_base64_encode(s: &[u8]) -> String { #[string] fn op_encoding_normalize_label( #[string] label: String, -) -> Result { +) -> Result { let encoding = Encoding::for_label_no_replacement(label.as_bytes()) - .ok_or_else(|| { - range_error(format!( - "The encoding label provided ('{label}') is invalid." - )) - })?; + .ok_or(WebError::InvalidEncodingLabel(label))?; Ok(encoding.name().to_lowercase()) } @@ -192,7 +205,7 @@ fn op_encoding_decode_utf8<'a>( scope: &mut v8::HandleScope<'a>, #[anybuffer] zero_copy: &[u8], ignore_bom: bool, -) -> Result, AnyError> { +) -> Result, WebError> { let buf = &zero_copy; let buf = if !ignore_bom @@ -216,7 +229,7 @@ fn op_encoding_decode_utf8<'a>( // - https://github.com/v8/v8/blob/d68fb4733e39525f9ff0a9222107c02c28096e2a/include/v8.h#L3277-L3278 match v8::String::new_from_utf8(scope, buf, v8::NewStringType::Normal) { Some(text) => Ok(text), - None => Err(type_error("buffer exceeds maximum length")), + None => Err(WebError::BufferTooLong), } } @@ -227,12 +240,9 @@ fn op_encoding_decode_single( #[string] label: String, fatal: bool, ignore_bom: bool, -) -> Result { - let encoding = Encoding::for_label(label.as_bytes()).ok_or_else(|| { - range_error(format!( - "The encoding label provided ('{label}') is invalid." - )) - })?; +) -> Result { + let encoding = Encoding::for_label(label.as_bytes()) + .ok_or(WebError::InvalidEncodingLabel(label))?; let mut decoder = if ignore_bom { encoding.new_decoder_without_bom_handling() @@ -242,7 +252,7 @@ fn op_encoding_decode_single( let max_buffer_length = decoder .max_utf16_buffer_length(data.len()) - .ok_or_else(|| range_error("Value too large to decode."))?; + .ok_or(WebError::ValueTooLarge)?; let mut output = vec![0; max_buffer_length]; @@ -254,12 +264,8 @@ fn op_encoding_decode_single( output.truncate(written); Ok(output.into()) } - DecoderResult::OutputFull => { - Err(range_error("Provided buffer too small.")) - } - DecoderResult::Malformed(_, _) => { - Err(type_error("The encoded data is not valid.")) - } + DecoderResult::OutputFull => Err(WebError::BufferTooSmall), + DecoderResult::Malformed(_, _) => Err(WebError::DataInvalid), } } else { let (result, _, written, _) = @@ -269,7 +275,7 @@ fn op_encoding_decode_single( output.truncate(written); Ok(output.into()) } - CoderResult::OutputFull => Err(range_error("Provided buffer too small.")), + CoderResult::OutputFull => Err(WebError::BufferTooSmall), } } } @@ -280,12 +286,9 @@ fn op_encoding_new_decoder( #[string] label: &str, fatal: bool, ignore_bom: bool, -) -> Result { - let encoding = Encoding::for_label(label.as_bytes()).ok_or_else(|| { - range_error(format!( - "The encoding label provided ('{label}') is invalid." - )) - })?; +) -> Result { + let encoding = Encoding::for_label(label.as_bytes()) + .ok_or_else(|| WebError::InvalidEncodingLabel(label.to_string()))?; let decoder = if ignore_bom { encoding.new_decoder_without_bom_handling() @@ -305,13 +308,13 @@ fn op_encoding_decode( #[anybuffer] data: &[u8], #[cppgc] resource: &TextDecoderResource, stream: bool, -) -> Result { +) -> Result { let mut decoder = resource.decoder.borrow_mut(); let fatal = resource.fatal; let max_buffer_length = decoder .max_utf16_buffer_length(data.len()) - .ok_or_else(|| range_error("Value too large to decode."))?; + .ok_or(WebError::ValueTooLarge)?; let mut output = vec![0; max_buffer_length]; @@ -323,12 +326,8 @@ fn op_encoding_decode( output.truncate(written); Ok(output.into()) } - DecoderResult::OutputFull => { - Err(range_error("Provided buffer too small.")) - } - DecoderResult::Malformed(_, _) => { - Err(type_error("The encoded data is not valid.")) - } + DecoderResult::OutputFull => Err(WebError::BufferTooSmall), + DecoderResult::Malformed(_, _) => Err(WebError::DataInvalid), } } else { let (result, _, written, _) = @@ -338,7 +337,7 @@ fn op_encoding_decode( output.truncate(written); Ok(output.into()) } - CoderResult::OutputFull => Err(range_error("Provided buffer too small.")), + CoderResult::OutputFull => Err(WebError::BufferTooSmall), } } } @@ -356,7 +355,7 @@ fn op_encoding_encode_into( input: v8::Local, #[buffer] buffer: &mut [u8], #[buffer] out_buf: &mut [u32], -) -> Result<(), AnyError> { +) -> Result<(), WebError> { let s = v8::Local::::try_from(input)?; let mut nchars = 0; @@ -414,53 +413,4 @@ pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_web.d.ts") } -#[derive(Debug)] -pub struct DomExceptionQuotaExceededError { - pub msg: String, -} - -impl DomExceptionQuotaExceededError { - pub fn new(msg: &str) -> Self { - DomExceptionQuotaExceededError { - msg: msg.to_string(), - } - } -} - -#[derive(Debug)] -pub struct DomExceptionInvalidCharacterError { - pub msg: String, -} - -impl DomExceptionInvalidCharacterError { - pub fn new(msg: &str) -> Self { - DomExceptionInvalidCharacterError { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for DomExceptionQuotaExceededError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} -impl fmt::Display for DomExceptionInvalidCharacterError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} - -impl std::error::Error for DomExceptionQuotaExceededError {} - -impl std::error::Error for DomExceptionInvalidCharacterError {} - -pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { - e.downcast_ref::() - .map(|_| "DOMExceptionQuotaExceededError") - .or_else(|| { - e.downcast_ref::() - .map(|_| "DOMExceptionInvalidCharacterError") - }) -} pub struct Location(pub Url); diff --git a/ext/web/message_port.rs b/ext/web/message_port.rs index c069037f81..1a4a09073d 100644 --- a/ext/web/message_port.rs +++ b/ext/web/message_port.rs @@ -4,8 +4,6 @@ use std::borrow::Cow; use std::cell::RefCell; use std::rc::Rc; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::CancelFuture; @@ -23,6 +21,20 @@ use tokio::sync::mpsc::unbounded_channel; use tokio::sync::mpsc::UnboundedReceiver; use tokio::sync::mpsc::UnboundedSender; +#[derive(Debug, thiserror::Error)] +pub enum MessagePortError { + #[error("Invalid message port transfer")] + InvalidTransfer, + #[error("Message port is not ready for transfer")] + NotReady, + #[error("Can not transfer self message port")] + TransferSelf, + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), + #[error(transparent)] + Resource(deno_core::error::AnyError), +} + pub enum Transferable { MessagePort(MessagePort), ArrayBuffer(u32), @@ -40,7 +52,7 @@ impl MessagePort { &self, state: &mut OpState, data: JsMessageData, - ) -> Result<(), AnyError> { + ) -> Result<(), MessagePortError> { let transferables = deserialize_js_transferables(state, data.transferables)?; @@ -56,7 +68,7 @@ impl MessagePort { pub async fn recv( &self, state: Rc>, - ) -> Result, AnyError> { + ) -> Result, MessagePortError> { let rx = &self.rx; let maybe_data = poll_fn(|cx| { @@ -147,7 +159,7 @@ pub enum JsTransferable { pub fn deserialize_js_transferables( state: &mut OpState, js_transferables: Vec, -) -> Result, AnyError> { +) -> Result, MessagePortError> { let mut transferables = Vec::with_capacity(js_transferables.len()); for js_transferable in js_transferables { match js_transferable { @@ -155,10 +167,10 @@ pub fn deserialize_js_transferables( let resource = state .resource_table .take::(id) - .map_err(|_| type_error("Invalid message port transfer"))?; + .map_err(|_| MessagePortError::InvalidTransfer)?; resource.cancel.cancel(); - let resource = Rc::try_unwrap(resource) - .map_err(|_| type_error("Message port is not ready for transfer"))?; + let resource = + Rc::try_unwrap(resource).map_err(|_| MessagePortError::NotReady)?; transferables.push(Transferable::MessagePort(resource.port)); } JsTransferable::ArrayBuffer(id) => { @@ -202,16 +214,19 @@ pub fn op_message_port_post_message( state: &mut OpState, #[smi] rid: ResourceId, #[serde] data: JsMessageData, -) -> Result<(), AnyError> { +) -> Result<(), MessagePortError> { for js_transferable in &data.transferables { if let JsTransferable::MessagePort(id) = js_transferable { if *id == rid { - return Err(type_error("Can not transfer self message port")); + return Err(MessagePortError::TransferSelf); } } } - let resource = state.resource_table.get::(rid)?; + let resource = state + .resource_table + .get::(rid) + .map_err(MessagePortError::Resource)?; resource.port.send(state, data) } @@ -220,7 +235,7 @@ pub fn op_message_port_post_message( pub async fn op_message_port_recv_message( state: Rc>, #[smi] rid: ResourceId, -) -> Result, AnyError> { +) -> Result, MessagePortError> { let resource = { let state = state.borrow(); match state.resource_table.get::(rid) { @@ -237,9 +252,11 @@ pub async fn op_message_port_recv_message( pub fn op_message_port_recv_message_sync( state: &mut OpState, // Rc>, #[smi] rid: ResourceId, -) -> Result, AnyError> { - let resource = state.resource_table.get::(rid)?; - resource.cancel.cancel(); +) -> Result, MessagePortError> { + let resource = state + .resource_table + .get::(rid) + .map_err(MessagePortError::Resource)?; let mut rx = resource.port.rx.borrow_mut(); match rx.try_recv() { diff --git a/ext/web/stream_resource.rs b/ext/web/stream_resource.rs index 78487883b6..c44a385ea9 100644 --- a/ext/web/stream_resource.rs +++ b/ext/web/stream_resource.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use bytes::BytesMut; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::external; use deno_core::op2; use deno_core::serde_v8::V8Slice; @@ -18,6 +16,7 @@ use deno_core::RcRef; use deno_core::Resource; use deno_core::ResourceId; use futures::future::poll_fn; +use futures::TryFutureExt; use std::borrow::Cow; use std::cell::RefCell; use std::cell::RefMut; @@ -31,6 +30,14 @@ use std::task::Context; use std::task::Poll; use std::task::Waker; +#[derive(Debug, thiserror::Error)] +pub enum StreamResourceError { + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), + #[error("{0}")] + Js(String), +} + // How many buffers we'll allow in the channel before we stop allowing writes. const BUFFER_CHANNEL_SIZE: u16 = 1024; @@ -48,7 +55,7 @@ struct BoundedBufferChannelInner { buffers: [MaybeUninit>; BUFFER_CHANNEL_SIZE as _], ring_producer: u16, ring_consumer: u16, - error: Option, + error: Option, current_size: usize, // TODO(mmastrac): we can math this field instead of accounting for it len: usize, @@ -141,7 +148,10 @@ impl BoundedBufferChannelInner { self.len = 0; } - pub fn read(&mut self, limit: usize) -> Result, AnyError> { + pub fn read( + &mut self, + limit: usize, + ) -> Result, StreamResourceError> { // Empty buffers will return the error, if one exists, or None if self.len == 0 { if let Some(error) = self.error.take() { @@ -230,7 +240,7 @@ impl BoundedBufferChannelInner { Ok(()) } - pub fn write_error(&mut self, error: AnyError) { + pub fn write_error(&mut self, error: StreamResourceError) { self.error = Some(error); if let Some(waker) = self.read_waker.take() { waker.wake(); @@ -306,7 +316,10 @@ impl BoundedBufferChannel { self.inner.borrow_mut() } - pub fn read(&self, limit: usize) -> Result, AnyError> { + pub fn read( + &self, + limit: usize, + ) -> Result, StreamResourceError> { self.inner().read(limit) } @@ -314,7 +327,7 @@ impl BoundedBufferChannel { self.inner().write(buffer) } - pub fn write_error(&self, error: AnyError) { + pub fn write_error(&self, error: StreamResourceError) { self.inner().write_error(error) } @@ -358,7 +371,10 @@ impl ReadableStreamResource { RcRef::map(self, |s| &s.cancel_handle).clone() } - async fn read(self: Rc, limit: usize) -> Result { + async fn read( + self: Rc, + limit: usize, + ) -> Result { let cancel_handle = self.cancel_handle(); // Serialize all the reads using a task queue. let _read_permit = self.read_queue.acquire().await; @@ -387,7 +403,7 @@ impl Resource for ReadableStreamResource { } fn read(self: Rc, limit: usize) -> AsyncResult { - Box::pin(ReadableStreamResource::read(self, limit)) + Box::pin(ReadableStreamResource::read(self, limit).map_err(|e| e.into())) } fn close(self: Rc) { @@ -550,7 +566,7 @@ pub fn op_readable_stream_resource_write_error( ) -> bool { let sender = get_sender(sender); // We can always write an error, no polling required - sender.write_error(type_error(Cow::Owned(error))); + sender.write_error(StreamResourceError::Js(error)); !sender.closed() } diff --git a/ext/web/timers.rs b/ext/web/timers.rs index 648be57155..a9ab7c97e4 100644 --- a/ext/web/timers.rs +++ b/ext/web/timers.rs @@ -13,7 +13,7 @@ pub trait TimersPermission { impl TimersPermission for deno_permissions::PermissionsContainer { #[inline(always)] fn allow_hrtime(&mut self) -> bool { - deno_permissions::PermissionsContainer::allow_hrtime(self) + true } } diff --git a/ext/webgpu/01_webgpu.js b/ext/webgpu/01_webgpu.js index 36b35072c6..719877750b 100644 --- a/ext/webgpu/01_webgpu.js +++ b/ext/webgpu/01_webgpu.js @@ -175,7 +175,7 @@ function assertDevice(self, prefix, context) { const deviceRid = device?.rid; if (deviceRid === undefined) { throw new DOMException( - `${prefix}: ${context} references an invalid or destroyed device.`, + `${prefix}: ${context} references an invalid or destroyed device`, "OperationError", ); } @@ -196,7 +196,7 @@ function assertDeviceMatch( const resourceDevice = assertDevice(resource, prefix, resourceContext); if (resourceDevice.rid !== self.rid) { throw new DOMException( - `${prefix}: ${resourceContext} belongs to a different device than ${selfContext}.`, + `${prefix}: ${resourceContext} belongs to a different device than ${selfContext}`, "OperationError", ); } @@ -213,7 +213,7 @@ function assertResource(self, prefix, context) { const rid = self[_rid]; if (rid === undefined) { throw new DOMException( - `${prefix}: ${context} an invalid or destroyed resource.`, + `${prefix}: ${context} an invalid or destroyed resource`, "OperationError", ); } @@ -469,7 +469,7 @@ class GPUAdapter { !SetPrototypeHas(this[_adapter].features[webidl.setlikeInner], feature) ) { throw new TypeError( - `${prefix}: requiredFeatures must be a subset of the adapter features.`, + `${prefix}: requiredFeatures must be a subset of the adapter features`, ); } } @@ -907,6 +907,7 @@ const GPUDeviceLostInfoPrototype = GPUDeviceLostInfo.prototype; function GPUObjectBaseMixin(name, type) { type.prototype[_label] = null; ObjectDefineProperty(type.prototype, "label", { + __proto__: null, /** * @return {string | null} */ @@ -1818,12 +1819,12 @@ class GPUDevice extends EventTarget { const prefix = "Failed to execute 'popErrorScope' on 'GPUDevice'"; const device = assertDevice(this, prefix, "this"); if (device.isLost) { - throw new DOMException("Device has been lost.", "OperationError"); + throw new DOMException("Device has been lost", "OperationError"); } const scope = ArrayPrototypePop(device.errorScopeStack); if (!scope) { throw new DOMException( - "There are no error scopes on the error scope stack.", + "There are no error scopes on the error scope stack", "OperationError", ); } @@ -2194,25 +2195,25 @@ class GPUBuffer { } if ((offset % 8) !== 0) { throw new DOMException( - `${prefix}: offset must be a multiple of 8.`, + `${prefix}: offset must be a multiple of 8, received ${offset}`, "OperationError", ); } if ((rangeSize % 4) !== 0) { throw new DOMException( - `${prefix}: rangeSize must be a multiple of 4.`, + `${prefix}: rangeSize must be a multiple of 4, received ${rangeSize}`, "OperationError", ); } if ((offset + rangeSize) > this[_size]) { throw new DOMException( - `${prefix}: offset + rangeSize must be less than or equal to buffer size.`, + `${prefix}: offset + rangeSize must be less than or equal to buffer size`, "OperationError", ); } if (this[_state] !== "unmapped") { throw new DOMException( - `${prefix}: GPUBuffer is not currently unmapped.`, + `${prefix}: GPUBuffer is not currently unmapped`, "OperationError", ); } @@ -2220,19 +2221,19 @@ class GPUBuffer { const writeMode = (mode & 0x0002) === 0x0002; if ((readMode && writeMode) || (!readMode && !writeMode)) { throw new DOMException( - `${prefix}: exactly one of READ or WRITE map mode must be set.`, + `${prefix}: exactly one of READ or WRITE map mode must be set`, "OperationError", ); } if (readMode && !((this[_usage] && 0x0001) === 0x0001)) { throw new DOMException( - `${prefix}: READ map mode not valid because buffer does not have MAP_READ usage.`, + `${prefix}: READ map mode not valid because buffer does not have MAP_READ usage`, "OperationError", ); } if (writeMode && !((this[_usage] && 0x0002) === 0x0002)) { throw new DOMException( - `${prefix}: WRITE map mode not valid because buffer does not have MAP_WRITE usage.`, + `${prefix}: WRITE map mode not valid because buffer does not have MAP_WRITE usage`, "OperationError", ); } @@ -2279,7 +2280,7 @@ class GPUBuffer { const mappedRanges = this[_mappedRanges]; if (!mappedRanges) { - throw new DOMException(`${prefix}: invalid state.`, "OperationError"); + throw new DOMException(`${prefix}: invalid state`, "OperationError"); } for (let i = 0; i < mappedRanges.length; ++i) { const { 0: buffer, 1: _rid, 2: start } = mappedRanges[i]; @@ -2290,7 +2291,7 @@ class GPUBuffer { (end >= offset && end < (offset + rangeSize)) ) { throw new DOMException( - `${prefix}: requested buffer overlaps with another mapped range.`, + `${prefix}: requested buffer overlaps with another mapped range`, "OperationError", ); } @@ -2316,14 +2317,14 @@ class GPUBuffer { const bufferRid = assertResource(this, prefix, "this"); if (this[_state] === "unmapped" || this[_state] === "destroyed") { throw new DOMException( - `${prefix}: buffer is not ready to be unmapped.`, + `${prefix}: buffer is not ready to be unmapped`, "OperationError", ); } if (this[_state] === "pending") { // TODO(lucacasonato): this is not spec compliant. throw new DOMException( - `${prefix}: can not unmap while mapping. This is a Deno limitation.`, + `${prefix}: can not unmap while mapping, this is a Deno limitation`, "OperationError", ); } else if ( @@ -2337,7 +2338,7 @@ class GPUBuffer { const mapMode = this[_mapMode]; if (mapMode === undefined) { throw new DOMException( - `${prefix}: invalid state.`, + `${prefix}: invalid state`, "OperationError", ); } @@ -2348,7 +2349,7 @@ class GPUBuffer { const mappedRanges = this[_mappedRanges]; if (!mappedRanges) { - throw new DOMException(`${prefix}: invalid state.`, "OperationError"); + throw new DOMException(`${prefix}: invalid state`, "OperationError"); } for (let i = 0; i < mappedRanges.length; ++i) { const { 0: buffer, 1: mappedRid } = mappedRanges[i]; @@ -5539,7 +5540,7 @@ webidl.converters["GPUExtent3D"] = (V, opts) => { if (V.length < min || V.length > max) { throw webidl.makeException( TypeError, - `A sequence of number used as a GPUExtent3D must have between ${min} and ${max} elements.`, + `A sequence of number used as a GPUExtent3D must have between ${min} and ${max} elements, received ${V.length} elements`, opts, ); } @@ -5549,7 +5550,7 @@ webidl.converters["GPUExtent3D"] = (V, opts) => { } throw webidl.makeException( TypeError, - "can not be converted to sequence or GPUExtent3DDict.", + "can not be converted to sequence or GPUExtent3DDict", opts, ); }; @@ -6883,7 +6884,7 @@ webidl.converters["GPUOrigin3D"] = (V, opts) => { if (V.length > length) { throw webidl.makeException( TypeError, - `A sequence of number used as a GPUOrigin3D must have at most ${length} elements.`, + `A sequence of number used as a GPUOrigin3D must have at most ${length} elements, received ${V.length} elements`, opts, ); } @@ -6893,7 +6894,7 @@ webidl.converters["GPUOrigin3D"] = (V, opts) => { } throw webidl.makeException( TypeError, - "can not be converted to sequence or GPUOrigin3DDict.", + "can not be converted to sequence or GPUOrigin3DDict", opts, ); }; @@ -6960,7 +6961,7 @@ webidl.converters["GPUOrigin2D"] = (V, opts) => { if (V.length > length) { throw webidl.makeException( TypeError, - `A sequence of number used as a GPUOrigin2D must have at most ${length} elements.`, + `A sequence of number used as a GPUOrigin2D must have at most ${length} elements, received ${V.length} elements`, opts, ); } @@ -6970,7 +6971,7 @@ webidl.converters["GPUOrigin2D"] = (V, opts) => { } throw webidl.makeException( TypeError, - "can not be converted to sequence or GPUOrigin2DDict.", + "can not be converted to sequence or GPUOrigin2DDict", opts, ); }; @@ -7054,7 +7055,7 @@ webidl.converters["GPUColor"] = (V, opts) => { if (V.length !== length) { throw webidl.makeException( TypeError, - `A sequence of number used as a GPUColor must have exactly ${length} elements.`, + `A sequence of number used as a GPUColor must have exactly ${length} elements, received ${V.length} elements`, opts, ); } @@ -7064,7 +7065,7 @@ webidl.converters["GPUColor"] = (V, opts) => { } throw webidl.makeException( TypeError, - "can not be converted to sequence or GPUColorDict.", + "can not be converted to sequence or GPUColorDict", opts, ); }; @@ -7433,16 +7434,6 @@ const dictMembersGPUCanvasConfiguration = [ key: "presentMode", converter: webidl.converters["GPUPresentMode"], }, - { - key: "width", - converter: webidl.converters["long"], - required: true, - }, - { - key: "height", - converter: webidl.converters["long"], - required: true, - }, { key: "viewFormats", converter: webidl.createSequenceConverter( diff --git a/ext/webgpu/02_surface.js b/ext/webgpu/02_surface.js index f35f745af4..ce723b891f 100644 --- a/ext/webgpu/02_surface.js +++ b/ext/webgpu/02_surface.js @@ -29,6 +29,8 @@ const _configuration = Symbol("[[configuration]]"); const _canvas = Symbol("[[canvas]]"); const _currentTexture = Symbol("[[currentTexture]]"); const _present = Symbol("[[present]]"); +const _dim = Symbol("[[dimensions]]"); + class GPUCanvasContext { /** @type {number} */ [_surfaceRid]; @@ -36,6 +38,7 @@ class GPUCanvasContext { [_canvas]; /** @type {GPUTexture | undefined} */ [_currentTexture]; + [_dim]; get canvas() { webidl.assertBranded(this, GPUCanvasContextPrototype); @@ -69,8 +72,8 @@ class GPUCanvasContext { format: configuration.format, viewFormats: configuration.viewFormats, usage: configuration.usage, - width: configuration.width, - height: configuration.height, + width: this[_dim].width, + height: this[_dim].height, alphaMode: configuration.alphaMode, }); @@ -92,7 +95,7 @@ class GPUCanvasContext { "Failed to execute 'getCurrentTexture' on 'GPUCanvasContext'"; if (this[_configuration] === null) { - throw new DOMException("context is not configured.", "InvalidStateError"); + throw new DOMException("Context is not configured", "InvalidStateError"); } const { createGPUTexture, assertDevice } = loadWebGPU(); @@ -110,8 +113,8 @@ class GPUCanvasContext { const texture = createGPUTexture( { size: { - width: this[_configuration].width, - height: this[_configuration].height, + width: this[_dim].width, + height: this[_dim].height, depthOrArrayLayers: 1, }, mipLevelCount: 1, @@ -163,6 +166,8 @@ function createCanvasContext(options) { const canvasContext = webidl.createBranded(GPUCanvasContext); canvasContext[_surfaceRid] = options.surfaceRid; canvasContext[_canvas] = options.canvas; + canvasContext[_dim] = { width: options.width, height: options.height }; + return canvasContext; } @@ -172,16 +177,34 @@ function createCanvasContext(options) { class UnsafeWindowSurface { #ctx; #surfaceRid; + #options; - constructor(system, win, display) { - this.#surfaceRid = op_webgpu_surface_create(system, win, display); + constructor(options) { + if (typeof options !== "object") { + throw new TypeError("options must be provided."); + } + if ( + typeof options.width !== "number" || typeof options.height !== "number" + ) { + throw new TypeError("width and height must be provided."); + } + + this.#surfaceRid = op_webgpu_surface_create( + options.system, + options.windowHandle, + options.displayHandle, + ); + this.#options = options; } getContext(context) { if (context !== "webgpu") { - throw new TypeError("Only 'webgpu' context is supported."); + throw new TypeError("Only 'webgpu' context is supported"); } - this.#ctx = createCanvasContext({ surfaceRid: this.#surfaceRid }); + this.#ctx = createCanvasContext({ + surfaceRid: this.#surfaceRid, + ...this.#options, + }); return this.#ctx; } diff --git a/ext/webgpu/Cargo.toml b/ext/webgpu/Cargo.toml index 5f87e27bc4..84ee4a012f 100644 --- a/ext/webgpu/Cargo.toml +++ b/ext/webgpu/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webgpu" -version = "0.131.0" +version = "0.141.0" authors = ["the Deno authors"] edition.workspace = true license = "MIT" @@ -25,6 +25,7 @@ serde = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = ["full"] } wgpu-types = { workspace = true, features = ["serde"] } raw-window-handle = { workspace = true } +thiserror.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgpu-core] workspace = true diff --git a/ext/webgpu/buffer.rs b/ext/webgpu/buffer.rs index c6cd6f0a74..c2b53890e0 100644 --- a/ext/webgpu/buffer.rs +++ b/ext/webgpu/buffer.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -13,9 +11,18 @@ use std::sync::Arc; use std::sync::Mutex; use std::time::Duration; -use super::error::DomExceptionOperationError; use super::error::WebGpuResult; +#[derive(Debug, thiserror::Error)] +pub enum BufferError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("usage is not valid")] + InvalidUsage, + #[error(transparent)] + Access(wgpu_core::resource::BufferAccessError), +} + pub(crate) struct WebGpuBuffer( pub(crate) super::Instance, pub(crate) wgpu_core::id::BufferId, @@ -46,18 +53,19 @@ pub fn op_webgpu_create_buffer( #[number] size: u64, usage: u32, mapped_at_creation: bool, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(device_rid)?; + .get::(device_rid) + .map_err(BufferError::Resource)?; let device = device_resource.1; let descriptor = wgpu_core::resource::BufferDescriptor { label: Some(label), size, usage: wgpu_types::BufferUsages::from_bits(usage) - .ok_or_else(|| type_error("usage is not valid"))?, + .ok_or(BufferError::InvalidUsage)?, mapped_at_creation, }; @@ -77,18 +85,21 @@ pub async fn op_webgpu_buffer_get_map_async( mode: u32, #[number] offset: u64, #[number] size: u64, -) -> Result { +) -> Result { let device; let done = Arc::new(Mutex::new(None)); { let state_ = state.borrow(); let instance = state_.borrow::(); - let buffer_resource = - state_.resource_table.get::(buffer_rid)?; + let buffer_resource = state_ + .resource_table + .get::(buffer_rid) + .map_err(BufferError::Resource)?; let buffer = buffer_resource.1; let device_resource = state_ .resource_table - .get::(device_rid)?; + .get::(device_rid) + .map_err(BufferError::Resource)?; device = device_resource.1; let done_ = done.clone(); @@ -120,9 +131,7 @@ pub async fn op_webgpu_buffer_get_map_async( let result = done.lock().unwrap().take(); match result { Some(Ok(())) => return Ok(WebGpuResult::empty()), - Some(Err(e)) => { - return Err(DomExceptionOperationError::new(&e.to_string()).into()) - } + Some(Err(e)) => return Err(BufferError::Access(e)), None => { { let state = state.borrow(); @@ -143,9 +152,12 @@ pub fn op_webgpu_buffer_get_mapped_range( #[number] offset: u64, #[number] size: Option, #[buffer] buf: &mut [u8], -) -> Result { +) -> Result { let instance = state.borrow::(); - let buffer_resource = state.resource_table.get::(buffer_rid)?; + let buffer_resource = state + .resource_table + .get::(buffer_rid) + .map_err(BufferError::Resource)?; let buffer = buffer_resource.1; let (slice_pointer, range_size) = @@ -154,7 +166,7 @@ pub fn op_webgpu_buffer_get_mapped_range( offset, size )) - .map_err(|e| DomExceptionOperationError::new(&e.to_string()))?; + .map_err(BufferError::Access)?; // SAFETY: guarantee to be safe from wgpu let slice = unsafe { @@ -176,12 +188,16 @@ pub fn op_webgpu_buffer_unmap( #[smi] buffer_rid: ResourceId, #[smi] mapped_rid: ResourceId, #[buffer] buf: Option<&[u8]>, -) -> Result { +) -> Result { let mapped_resource = state .resource_table - .take::(mapped_rid)?; + .take::(mapped_rid) + .map_err(BufferError::Resource)?; let instance = state.borrow::(); - let buffer_resource = state.resource_table.get::(buffer_rid)?; + let buffer_resource = state + .resource_table + .get::(buffer_rid) + .map_err(BufferError::Resource)?; let buffer = buffer_resource.1; if let Some(buf) = buf { diff --git a/ext/webgpu/bundle.rs b/ext/webgpu/bundle.rs index 57158271cc..d9a5b29539 100644 --- a/ext/webgpu/bundle.rs +++ b/ext/webgpu/bundle.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -13,6 +11,14 @@ use std::rc::Rc; use super::error::WebGpuResult; +#[derive(Debug, thiserror::Error)] +pub enum BundleError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("size must be larger than 0")] + InvalidSize, +} + struct WebGpuRenderBundleEncoder( RefCell, ); @@ -53,7 +59,7 @@ pub struct CreateRenderBundleEncoderArgs { pub fn op_webgpu_create_render_bundle_encoder( state: &mut OpState, #[serde] args: CreateRenderBundleEncoderArgs, -) -> Result { +) -> Result { let device_resource = state .resource_table .get::(args.device_rid)?; @@ -100,7 +106,7 @@ pub fn op_webgpu_render_bundle_encoder_finish( state: &mut OpState, #[smi] render_bundle_encoder_rid: ResourceId, #[string] label: Cow, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -131,7 +137,7 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group( #[buffer] dynamic_offsets_data: &[u32], #[number] dynamic_offsets_data_start: usize, #[number] dynamic_offsets_data_length: usize, -) -> Result { +) -> Result { let bind_group_resource = state .resource_table @@ -171,7 +177,7 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group( state: &mut OpState, #[smi] render_bundle_encoder_rid: ResourceId, #[string] group_label: &str, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -195,7 +201,7 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group( pub fn op_webgpu_render_bundle_encoder_pop_debug_group( state: &mut OpState, #[smi] render_bundle_encoder_rid: ResourceId, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -214,7 +220,7 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker( state: &mut OpState, #[smi] render_bundle_encoder_rid: ResourceId, #[string] marker_label: &str, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -239,7 +245,7 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline( state: &mut OpState, #[smi] render_bundle_encoder_rid: ResourceId, #[smi] pipeline: ResourceId, -) -> Result { +) -> Result { let render_pipeline_resource = state .resource_table @@ -266,18 +272,17 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer( #[serde] index_format: wgpu_types::IndexFormat, #[number] offset: u64, #[number] size: u64, -) -> Result { +) -> Result { let buffer_resource = state .resource_table - .get::(buffer)?; - let render_bundle_encoder_resource = - state - .resource_table - .get::(render_bundle_encoder_rid)?; - let size = Some( - std::num::NonZeroU64::new(size) - .ok_or_else(|| type_error("size must be larger than 0"))?, - ); + .get::(buffer) + .map_err(BundleError::Resource)?; + let render_bundle_encoder_resource = state + .resource_table + .get::(render_bundle_encoder_rid) + .map_err(BundleError::Resource)?; + let size = + Some(std::num::NonZeroU64::new(size).ok_or(BundleError::InvalidSize)?); render_bundle_encoder_resource .0 @@ -296,19 +301,17 @@ pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer( #[smi] buffer: ResourceId, #[number] offset: u64, #[number] size: Option, -) -> Result { +) -> Result { let buffer_resource = state .resource_table - .get::(buffer)?; - let render_bundle_encoder_resource = - state - .resource_table - .get::(render_bundle_encoder_rid)?; + .get::(buffer) + .map_err(BundleError::Resource)?; + let render_bundle_encoder_resource = state + .resource_table + .get::(render_bundle_encoder_rid) + .map_err(BundleError::Resource)?; let size = if let Some(size) = size { - Some( - std::num::NonZeroU64::new(size) - .ok_or_else(|| type_error("size must be larger than 0"))?, - ) + Some(std::num::NonZeroU64::new(size).ok_or(BundleError::InvalidSize)?) } else { None }; @@ -333,7 +336,7 @@ pub fn op_webgpu_render_bundle_encoder_draw( instance_count: u32, first_vertex: u32, first_instance: u32, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -360,7 +363,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indexed( first_index: u32, base_vertex: i32, first_instance: u32, -) -> Result { +) -> Result { let render_bundle_encoder_resource = state .resource_table @@ -385,7 +388,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indirect( #[smi] render_bundle_encoder_rid: ResourceId, #[smi] indirect_buffer: ResourceId, #[number] indirect_offset: u64, -) -> Result { +) -> Result { let buffer_resource = state .resource_table .get::(indirect_buffer)?; diff --git a/ext/webgpu/byow.rs b/ext/webgpu/byow.rs index fa3ce2d966..c9e1177b1e 100644 --- a/ext/webgpu/byow.rs +++ b/ext/webgpu/byow.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::ResourceId; @@ -16,6 +14,47 @@ use std::ptr::NonNull; use crate::surface::WebGpuSurface; +#[derive(Debug, thiserror::Error)] +pub enum ByowError { + #[error("Cannot create surface outside of WebGPU context. Did you forget to call `navigator.gpu.requestAdapter()`?")] + WebGPUNotInitiated, + #[error("Invalid parameters")] + InvalidParameters, + #[error(transparent)] + CreateSurface(wgpu_core::instance::CreateSurfaceError), + #[cfg(target_os = "windows")] + #[error("Invalid system on Windows")] + InvalidSystem, + #[cfg(target_os = "macos")] + #[error("Invalid system on macOS")] + InvalidSystem, + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd" + ))] + #[error("Invalid system on Linux/BSD")] + InvalidSystem, + #[cfg(any( + target_os = "windows", + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd" + ))] + #[error("window is null")] + NullWindow, + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd" + ))] + #[error("display is null")] + NullDisplay, + #[cfg(target_os = "macos")] + #[error("ns_view is null")] + NSViewDisplay, +} + #[op2(fast)] #[smi] pub fn op_webgpu_surface_create( @@ -23,10 +62,10 @@ pub fn op_webgpu_surface_create( #[string] system: &str, p1: *const c_void, p2: *const c_void, -) -> Result { - let instance = state.try_borrow::().ok_or_else(|| { - type_error("Cannot create surface outside of WebGPU context. Did you forget to call `navigator.gpu.requestAdapter()`?") - })?; +) -> Result { + let instance = state + .try_borrow::() + .ok_or(ByowError::WebGPUNotInitiated)?; // Security note: // // The `p1` and `p2` parameters are pointers to platform-specific window @@ -41,13 +80,15 @@ pub fn op_webgpu_surface_create( // // - Only FFI can export v8::External to user code. if p1.is_null() { - return Err(type_error("Invalid parameters")); + return Err(ByowError::InvalidParameters); } let (win_handle, display_handle) = raw_window(system, p1, p2)?; // SAFETY: see above comment let surface = unsafe { - instance.instance_create_surface(display_handle, win_handle, None)? + instance + .instance_create_surface(display_handle, win_handle, None) + .map_err(ByowError::CreateSurface)? }; let rid = state @@ -66,15 +107,14 @@ fn raw_window( system: &str, _ns_window: *const c_void, ns_view: *const c_void, -) -> Result { +) -> Result { if system != "cocoa" { - return Err(type_error("Invalid system on macOS")); + return Err(ByowError::InvalidSystem); } let win_handle = raw_window_handle::RawWindowHandle::AppKit( raw_window_handle::AppKitWindowHandle::new( - NonNull::new(ns_view as *mut c_void) - .ok_or(type_error("ns_view is null"))?, + NonNull::new(ns_view as *mut c_void).ok_or(ByowError::NSViewDisplay)?, ), ); @@ -89,16 +129,16 @@ fn raw_window( system: &str, window: *const c_void, hinstance: *const c_void, -) -> Result { +) -> Result { use raw_window_handle::WindowsDisplayHandle; if system != "win32" { - return Err(type_error("Invalid system on Windows")); + return Err(ByowError::InvalidSystem); } let win_handle = { let mut handle = raw_window_handle::Win32WindowHandle::new( std::num::NonZeroIsize::new(window as isize) - .ok_or(type_error("window is null"))?, + .ok_or(ByowError::NullWindow)?, ); handle.hinstance = std::num::NonZeroIsize::new(hinstance as isize); @@ -115,7 +155,7 @@ fn raw_window( system: &str, window: *const c_void, display: *const c_void, -) -> Result { +) -> Result { let (win_handle, display_handle); if system == "x11" { win_handle = raw_window_handle::RawWindowHandle::Xlib( @@ -131,20 +171,33 @@ fn raw_window( } else if system == "wayland" { win_handle = raw_window_handle::RawWindowHandle::Wayland( raw_window_handle::WaylandWindowHandle::new( - NonNull::new(window as *mut c_void) - .ok_or(type_error("window is null"))?, + NonNull::new(window as *mut c_void).ok_or(ByowError::NullWindow)?, ), ); display_handle = raw_window_handle::RawDisplayHandle::Wayland( raw_window_handle::WaylandDisplayHandle::new( - NonNull::new(display as *mut c_void) - .ok_or(type_error("display is null"))?, + NonNull::new(display as *mut c_void).ok_or(ByowError::NullDisplay)?, ), ); } else { - return Err(type_error("Invalid system on Linux/BSD")); + return Err(ByowError::InvalidSystem); } Ok((win_handle, display_handle)) } + +#[cfg(not(any( + target_os = "macos", + target_os = "windows", + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd", +)))] +fn raw_window( + _system: &str, + _window: *const c_void, + _display: *const c_void, +) -> Result { + Err(deno_core::error::type_error("Unsupported platform")) +} diff --git a/ext/webgpu/error.rs b/ext/webgpu/error.rs index 5b55d506ad..f08f765386 100644 --- a/ext/webgpu/error.rs +++ b/ext/webgpu/error.rs @@ -1,11 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::ResourceId; use serde::Serialize; use std::convert::From; use std::error::Error; -use std::fmt; use wgpu_core::binding_model::CreateBindGroupError; use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreatePipelineLayoutError; @@ -286,29 +284,3 @@ impl From for WebGpuError { WebGpuError::Validation(fmt_err(&err)) } } - -#[derive(Debug)] -pub struct DomExceptionOperationError { - pub msg: String, -} - -impl DomExceptionOperationError { - pub fn new(msg: &str) -> Self { - DomExceptionOperationError { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for DomExceptionOperationError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} - -impl std::error::Error for DomExceptionOperationError {} - -pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { - e.downcast_ref::() - .map(|_| "DOMExceptionOperationError") -} diff --git a/ext/webgpu/lib.rs b/ext/webgpu/lib.rs index df01c5ff97..5dc8278e41 100644 --- a/ext/webgpu/lib.rs +++ b/ext/webgpu/lib.rs @@ -2,7 +2,6 @@ #![cfg(not(target_arch = "wasm32"))] #![warn(unsafe_op_in_unsafe_fn)] -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -16,7 +15,6 @@ use std::rc::Rc; pub use wgpu_core; pub use wgpu_types; -use error::DomExceptionOperationError; use error::WebGpuResult; pub const UNSTABLE_FEATURE_NAME: &str = "webgpu"; @@ -44,7 +42,7 @@ mod macros { #[cfg(all(not(target_arch = "wasm32"), windows))] wgpu_types::Backend::Dx12 => $($c)*.$method:: $params, #[cfg(any( - all(unix, not(target_os = "macos"), not(target_os = "ios")), + all(not(target_os = "macos"), not(target_os = "ios")), feature = "angle", target_arch = "wasm32" ))] @@ -85,6 +83,18 @@ pub mod shader; pub mod surface; pub mod texture; +#[derive(Debug, thiserror::Error)] +pub enum InitError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + InvalidAdapter(wgpu_core::instance::InvalidAdapter), + #[error(transparent)] + RequestDevice(wgpu_core::instance::RequestDeviceError), + #[error(transparent)] + InvalidDevice(wgpu_core::device::InvalidDevice), +} + pub type Instance = std::sync::Arc; struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId); @@ -400,16 +410,9 @@ pub fn op_webgpu_request_adapter( state: Rc>, #[serde] power_preference: Option, force_fallback_adapter: bool, -) -> Result { +) -> Result { let mut state = state.borrow_mut(); - // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` - // once we phase out `check_or_exit_with_legacy_fallback` - state.feature_checker.check_or_exit_with_legacy_fallback( - UNSTABLE_FEATURE_NAME, - "navigator.gpu.requestAdapter", - ); - let backends = std::env::var("DENO_WEBGPU_BACKEND").map_or_else( |_| wgpu_types::Backends::all(), |s| wgpu_core::instance::parse_backends_from_comma_list(&s), @@ -448,10 +451,11 @@ pub fn op_webgpu_request_adapter( } }; let adapter_features = - gfx_select!(adapter => instance.adapter_features(adapter))?; + gfx_select!(adapter => instance.adapter_features(adapter)) + .map_err(InitError::InvalidAdapter)?; let features = deserialize_features(&adapter_features); - let adapter_limits = - gfx_select!(adapter => instance.adapter_limits(adapter))?; + let adapter_limits = gfx_select!(adapter => instance.adapter_limits(adapter)) + .map_err(InitError::InvalidAdapter)?; let instance = instance.clone(); @@ -670,10 +674,12 @@ pub fn op_webgpu_request_device( #[string] label: String, #[serde] required_features: GpuRequiredFeatures, #[serde] required_limits: Option, -) -> Result { +) -> Result { let mut state = state.borrow_mut(); - let adapter_resource = - state.resource_table.take::(adapter_rid)?; + let adapter_resource = state + .resource_table + .take::(adapter_rid) + .map_err(InitError::Resource)?; let adapter = adapter_resource.1; let instance = state.borrow::(); @@ -692,13 +698,14 @@ pub fn op_webgpu_request_device( )); adapter_resource.close(); if let Some(err) = maybe_err { - return Err(DomExceptionOperationError::new(&err.to_string()).into()); + return Err(InitError::RequestDevice(err)); } - let device_features = - gfx_select!(device => instance.device_features(device))?; + let device_features = gfx_select!(device => instance.device_features(device)) + .map_err(InitError::InvalidDevice)?; let features = deserialize_features(&device_features); - let limits = gfx_select!(device => instance.device_limits(device))?; + let limits = gfx_select!(device => instance.device_limits(device)) + .map_err(InitError::InvalidDevice)?; let instance = instance.clone(); let instance2 = instance.clone(); @@ -729,14 +736,17 @@ pub struct GPUAdapterInfo { pub fn op_webgpu_request_adapter_info( state: Rc>, #[smi] adapter_rid: ResourceId, -) -> Result { +) -> Result { let state = state.borrow_mut(); - let adapter_resource = - state.resource_table.get::(adapter_rid)?; + let adapter_resource = state + .resource_table + .get::(adapter_rid) + .map_err(InitError::Resource)?; let adapter = adapter_resource.1; let instance = state.borrow::(); - let info = gfx_select!(adapter => instance.adapter_get_info(adapter))?; + let info = gfx_select!(adapter => instance.adapter_get_info(adapter)) + .map_err(InitError::InvalidAdapter)?; Ok(GPUAdapterInfo { vendor: info.vendor.to_string(), @@ -777,9 +787,11 @@ impl From for wgpu_types::QueryType { pub fn op_webgpu_create_query_set( state: &mut OpState, #[serde] args: CreateQuerySetArgs, -) -> Result { - let device_resource = - state.resource_table.get::(args.device_rid)?; +) -> Result { + let device_resource = state + .resource_table + .get::(args.device_rid) + .map_err(InitError::Resource)?; let device = device_resource.1; let instance = state.borrow::(); diff --git a/ext/webgpu/render_pass.rs b/ext/webgpu/render_pass.rs index c68be3d99a..9b9d87d9fc 100644 --- a/ext/webgpu/render_pass.rs +++ b/ext/webgpu/render_pass.rs @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -12,6 +10,14 @@ use std::cell::RefCell; use super::error::WebGpuResult; +#[derive(Debug, thiserror::Error)] +pub enum RenderPassError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("size must be larger than 0")] + InvalidSize, +} + pub(crate) struct WebGpuRenderPass( pub(crate) RefCell, ); @@ -38,7 +44,7 @@ pub struct RenderPassSetViewportArgs { pub fn op_webgpu_render_pass_set_viewport( state: &mut OpState, #[serde] args: RenderPassSetViewportArgs, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(args.render_pass_rid)?; @@ -65,7 +71,7 @@ pub fn op_webgpu_render_pass_set_scissor_rect( y: u32, width: u32, height: u32, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -87,7 +93,7 @@ pub fn op_webgpu_render_pass_set_blend_constant( state: &mut OpState, #[smi] render_pass_rid: ResourceId, #[serde] color: wgpu_types::Color, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -106,7 +112,7 @@ pub fn op_webgpu_render_pass_set_stencil_reference( state: &mut OpState, #[smi] render_pass_rid: ResourceId, reference: u32, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -125,7 +131,7 @@ pub fn op_webgpu_render_pass_begin_occlusion_query( state: &mut OpState, #[smi] render_pass_rid: ResourceId, query_index: u32, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -143,7 +149,7 @@ pub fn op_webgpu_render_pass_begin_occlusion_query( pub fn op_webgpu_render_pass_end_occlusion_query( state: &mut OpState, #[smi] render_pass_rid: ResourceId, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -161,7 +167,7 @@ pub fn op_webgpu_render_pass_execute_bundles( state: &mut OpState, #[smi] render_pass_rid: ResourceId, #[serde] bundles: Vec, -) -> Result { +) -> Result { let bundles = bundles .iter() .map(|rid| { @@ -171,7 +177,7 @@ pub fn op_webgpu_render_pass_execute_bundles( .get::(*rid)?; Ok(render_bundle_resource.1) }) - .collect::, AnyError>>()?; + .collect::, deno_core::error::AnyError>>()?; let render_pass_resource = state .resource_table @@ -191,7 +197,7 @@ pub fn op_webgpu_render_pass_end( state: &mut OpState, #[smi] command_encoder_rid: ResourceId, #[smi] render_pass_rid: ResourceId, -) -> Result { +) -> Result { let command_encoder_resource = state .resource_table .get::( @@ -217,7 +223,7 @@ pub fn op_webgpu_render_pass_set_bind_group( #[buffer] dynamic_offsets_data: &[u32], #[number] dynamic_offsets_data_start: usize, #[number] dynamic_offsets_data_length: usize, -) -> Result { +) -> Result { let bind_group_resource = state .resource_table @@ -251,7 +257,7 @@ pub fn op_webgpu_render_pass_push_debug_group( state: &mut OpState, #[smi] render_pass_rid: ResourceId, #[string] group_label: &str, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -270,7 +276,7 @@ pub fn op_webgpu_render_pass_push_debug_group( pub fn op_webgpu_render_pass_pop_debug_group( state: &mut OpState, #[smi] render_pass_rid: ResourceId, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -288,7 +294,7 @@ pub fn op_webgpu_render_pass_insert_debug_marker( state: &mut OpState, #[smi] render_pass_rid: ResourceId, #[string] marker_label: &str, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -308,7 +314,7 @@ pub fn op_webgpu_render_pass_set_pipeline( state: &mut OpState, #[smi] render_pass_rid: ResourceId, pipeline: u32, -) -> Result { +) -> Result { let render_pipeline_resource = state .resource_table @@ -334,19 +340,18 @@ pub fn op_webgpu_render_pass_set_index_buffer( #[serde] index_format: wgpu_types::IndexFormat, #[number] offset: u64, #[number] size: Option, -) -> Result { +) -> Result { let buffer_resource = state .resource_table - .get::(buffer)?; + .get::(buffer) + .map_err(RenderPassError::Resource)?; let render_pass_resource = state .resource_table - .get::(render_pass_rid)?; + .get::(render_pass_rid) + .map_err(RenderPassError::Resource)?; let size = if let Some(size) = size { - Some( - std::num::NonZeroU64::new(size) - .ok_or_else(|| type_error("size must be larger than 0"))?, - ) + Some(std::num::NonZeroU64::new(size).ok_or(RenderPassError::InvalidSize)?) } else { None }; @@ -370,19 +375,18 @@ pub fn op_webgpu_render_pass_set_vertex_buffer( buffer: u32, #[number] offset: u64, #[number] size: Option, -) -> Result { +) -> Result { let buffer_resource = state .resource_table - .get::(buffer)?; + .get::(buffer) + .map_err(RenderPassError::Resource)?; let render_pass_resource = state .resource_table - .get::(render_pass_rid)?; + .get::(render_pass_rid) + .map_err(RenderPassError::Resource)?; let size = if let Some(size) = size { - Some( - std::num::NonZeroU64::new(size) - .ok_or_else(|| type_error("size must be larger than 0"))?, - ) + Some(std::num::NonZeroU64::new(size).ok_or(RenderPassError::InvalidSize)?) } else { None }; @@ -407,7 +411,7 @@ pub fn op_webgpu_render_pass_draw( instance_count: u32, first_vertex: u32, first_instance: u32, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -433,7 +437,7 @@ pub fn op_webgpu_render_pass_draw_indexed( first_index: u32, base_vertex: i32, first_instance: u32, -) -> Result { +) -> Result { let render_pass_resource = state .resource_table .get::(render_pass_rid)?; @@ -457,7 +461,7 @@ pub fn op_webgpu_render_pass_draw_indirect( #[smi] render_pass_rid: ResourceId, indirect_buffer: u32, #[number] indirect_offset: u64, -) -> Result { +) -> Result { let buffer_resource = state .resource_table .get::(indirect_buffer)?; @@ -481,7 +485,7 @@ pub fn op_webgpu_render_pass_draw_indexed_indirect( #[smi] render_pass_rid: ResourceId, indirect_buffer: u32, #[number] indirect_offset: u64, -) -> Result { +) -> Result { let buffer_resource = state .resource_table .get::(indirect_buffer)?; diff --git a/ext/webgpu/sampler.rs b/ext/webgpu/sampler.rs index 27c36802e6..9fc1269ea7 100644 --- a/ext/webgpu/sampler.rs +++ b/ext/webgpu/sampler.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -47,7 +46,7 @@ pub struct CreateSamplerArgs { pub fn op_webgpu_create_sampler( state: &mut OpState, #[serde] args: CreateSamplerArgs, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table diff --git a/ext/webgpu/shader.rs b/ext/webgpu/shader.rs index 0b3991c5de..4653bd85bf 100644 --- a/ext/webgpu/shader.rs +++ b/ext/webgpu/shader.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -31,7 +30,7 @@ pub fn op_webgpu_create_shader_module( #[smi] device_rid: ResourceId, #[string] label: Cow, #[string] code: Cow, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table diff --git a/ext/webgpu/surface.rs b/ext/webgpu/surface.rs index 1f6d2c87d2..297eaeb008 100644 --- a/ext/webgpu/surface.rs +++ b/ext/webgpu/surface.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use super::WebGpuResult; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -11,6 +10,16 @@ use std::borrow::Cow; use std::rc::Rc; use wgpu_types::SurfaceStatus; +#[derive(Debug, thiserror::Error)] +pub enum SurfaceError { + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error("Invalid Surface Status")] + InvalidStatus, + #[error(transparent)] + Surface(wgpu_core::present::SurfaceError), +} + pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId); impl Resource for WebGpuSurface { fn name(&self) -> Cow { @@ -41,7 +50,7 @@ pub struct SurfaceConfigureArgs { pub fn op_webgpu_surface_configure( state: &mut OpState, #[serde] args: SurfaceConfigureArgs, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table @@ -75,18 +84,22 @@ pub fn op_webgpu_surface_get_current_texture( state: &mut OpState, #[smi] device_rid: ResourceId, #[smi] surface_rid: ResourceId, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(device_rid)?; + .get::(device_rid) + .map_err(SurfaceError::Resource)?; let device = device_resource.1; - let surface_resource = - state.resource_table.get::(surface_rid)?; + let surface_resource = state + .resource_table + .get::(surface_rid) + .map_err(SurfaceError::Resource)?; let surface = surface_resource.1; let output = - gfx_select!(device => instance.surface_get_current_texture(surface, None))?; + gfx_select!(device => instance.surface_get_current_texture(surface, None)) + .map_err(SurfaceError::Surface)?; match output.status { SurfaceStatus::Good | SurfaceStatus::Suboptimal => { @@ -98,7 +111,7 @@ pub fn op_webgpu_surface_get_current_texture( }); Ok(WebGpuResult::rid(rid)) } - _ => Err(AnyError::msg("Invalid Surface Status")), + _ => Err(SurfaceError::InvalidStatus), } } @@ -107,17 +120,21 @@ pub fn op_webgpu_surface_present( state: &mut OpState, #[smi] device_rid: ResourceId, #[smi] surface_rid: ResourceId, -) -> Result<(), AnyError> { +) -> Result<(), SurfaceError> { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(device_rid)?; + .get::(device_rid) + .map_err(SurfaceError::Resource)?; let device = device_resource.1; - let surface_resource = - state.resource_table.get::(surface_rid)?; + let surface_resource = state + .resource_table + .get::(surface_rid) + .map_err(SurfaceError::Resource)?; let surface = surface_resource.1; - let _ = gfx_select!(device => instance.surface_present(surface))?; + let _ = gfx_select!(device => instance.surface_present(surface)) + .map_err(SurfaceError::Surface)?; Ok(()) } diff --git a/ext/webgpu/texture.rs b/ext/webgpu/texture.rs index 44edd1a887..f8a5e05a3e 100644 --- a/ext/webgpu/texture.rs +++ b/ext/webgpu/texture.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; @@ -62,7 +61,7 @@ pub struct CreateTextureArgs { pub fn op_webgpu_create_texture( state: &mut OpState, #[serde] args: CreateTextureArgs, -) -> Result { +) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table @@ -111,7 +110,7 @@ pub struct CreateTextureViewArgs { pub fn op_webgpu_create_texture_view( state: &mut OpState, #[serde] args: CreateTextureViewArgs, -) -> Result { +) -> Result { let instance = state.borrow::(); let texture_resource = state .resource_table diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js index 7440e47e7b..1d05aae5fa 100644 --- a/ext/webidl/00_webidl.js +++ b/ext/webidl/00_webidl.js @@ -26,7 +26,6 @@ const { Float32Array, Float64Array, FunctionPrototypeBind, - FunctionPrototypeCall, Int16Array, Int32Array, Int8Array, @@ -78,7 +77,6 @@ const { StringPrototypeToWellFormed, Symbol, SymbolIterator, - SymbolAsyncIterator, SymbolToStringTag, TypedArrayPrototypeGetBuffer, TypedArrayPrototypeGetSymbolToStringTag, @@ -97,7 +95,7 @@ function makeException(ErrorType, message, prefix, context) { function toNumber(value) { if (typeof value === "bigint") { - throw TypeError("Cannot convert a BigInt value to a number"); + throw new TypeError("Cannot convert a BigInt value to a number"); } return Number(value); } @@ -714,7 +712,7 @@ function requiredArguments(length, required, prefix) { if (length < required) { const errMsg = `${prefix ? prefix + ": " : ""}${required} argument${ required === 1 ? "" : "s" - } required, but only ${length} present.`; + } required, but only ${length} present`; throw new TypeError(errMsg); } } @@ -755,6 +753,7 @@ function createDictionaryConverter(name, ...dictionaries) { defaultValues[member.key] = member.converter(idlMemberValue, {}); } else { ObjectDefineProperty(defaultValues, member.key, { + __proto__: null, get() { return member.converter(idlMemberValue, member.defaultValue); }, @@ -819,7 +818,7 @@ function createDictionaryConverter(name, ...dictionaries) { } else if (member.required) { throw makeException( TypeError, - `can not be converted to '${name}' because '${key}' is required in '${name}'.`, + `can not be converted to '${name}' because '${key}' is required in '${name}'`, prefix, context, ); @@ -846,7 +845,7 @@ function createEnumConverter(name, values) { throw new TypeError( `${ prefix ? prefix + ": " : "" - }The provided value '${S}' is not a valid enum value of type ${name}.`, + }The provided value '${S}' is not a valid enum value of type ${name}`, ); } @@ -921,133 +920,12 @@ function createSequenceConverter(converter) { }; } -function isAsyncIterator(obj) { - if (obj[SymbolAsyncIterator] === undefined) { - if (obj[SymbolIterator] === undefined) { - return false; - } - } - - return true; -} - -const AsyncIterable = Symbol("[[asyncIterable]]"); - -function createAsyncIterableConverter(converter) { - return function ( - V, - prefix = undefined, - context = undefined, - opts = { __proto__: null }, - ) { - if (type(V) !== "Object") { - throw makeException( - TypeError, - "can not be converted to async iterable.", - prefix, - context, - ); - } - - let isAsync = true; - let method = V[SymbolAsyncIterator]; - if (method === undefined) { - method = V[SymbolIterator]; - - if (method === undefined) { - throw makeException( - TypeError, - "is not iterable.", - prefix, - context, - ); - } - - isAsync = false; - } - - return { - value: V, - [AsyncIterable]: AsyncIterable, - open(context) { - const iter = FunctionPrototypeCall(method, V); - if (type(iter) !== "Object") { - throw new TypeError( - `${context} could not be iterated because iterator method did not return object, but ${ - type(iter) - }.`, - ); - } - - let asyncIterator = iter; - - if (!isAsync) { - asyncIterator = { - // deno-lint-ignore require-await - async next() { - // deno-lint-ignore prefer-primordials - return iter.next(); - }, - }; - } - - return { - async next() { - // deno-lint-ignore prefer-primordials - const iterResult = await asyncIterator.next(); - if (type(iterResult) !== "Object") { - throw TypeError( - `${context} failed to iterate next value because the next() method did not return an object, but ${ - type(iterResult) - }.`, - ); - } - - if (iterResult.done) { - return { done: true }; - } - - const iterValue = converter( - iterResult.value, - `${context} failed to iterate next value`, - `The value returned from the next() method`, - opts, - ); - - return { done: false, value: iterValue }; - }, - async return(reason) { - if (asyncIterator.return === undefined) { - return undefined; - } - - // deno-lint-ignore prefer-primordials - const returnPromiseResult = await asyncIterator.return(reason); - if (type(returnPromiseResult) !== "Object") { - throw TypeError( - `${context} failed to close iterator because the return() method did not return an object, but ${ - type(returnPromiseResult) - }.`, - ); - } - - return undefined; - }, - [SymbolAsyncIterator]() { - return this; - }, - }; - }, - }; - }; -} - function createRecordConverter(keyConverter, valueConverter) { return (V, prefix, context, opts) => { if (type(V) !== "Object") { throw makeException( TypeError, - "can not be converted to dictionary.", + "can not be converted to dictionary", prefix, context, ); @@ -1118,7 +996,7 @@ function createInterfaceConverter(name, prototype) { if (!ObjectPrototypeIsPrototypeOf(prototype, V) || V[brand] !== brand) { throw makeException( TypeError, - `is not of type ${name}.`, + `is not of type ${name}`, prefix, context, ); @@ -1199,6 +1077,7 @@ function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) { function createDefaultIterator(target, kind) { const iterator = ObjectCreate(iteratorPrototype); ObjectDefineProperty(iterator, _iteratorInternal, { + __proto__: null, value: { target, kind, index: 0 }, configurable: true, }); @@ -1272,6 +1151,7 @@ function configureInterface(interface_) { configureProperties(interface_); configureProperties(interface_.prototype); ObjectDefineProperty(interface_.prototype, SymbolToStringTag, { + __proto__: null, value: interface_.name, enumerable: false, configurable: true, @@ -1293,12 +1173,14 @@ function configureProperties(obj) { typeof descriptor.value === "function" ) { ObjectDefineProperty(obj, key, { + __proto__: null, enumerable: true, writable: true, configurable: true, }); } else if (ReflectHas(descriptor, "get")) { ObjectDefineProperty(obj, key, { + __proto__: null, enumerable: true, configurable: true, }); @@ -1312,6 +1194,7 @@ const setlikeInner = Symbol("[[set]]"); function setlike(obj, objPrototype, readonly) { ObjectDefineProperties(obj, { size: { + __proto__: null, configurable: true, enumerable: true, get() { @@ -1320,6 +1203,7 @@ function setlike(obj, objPrototype, readonly) { }, }, [SymbolIterator]: { + __proto__: null, configurable: true, enumerable: false, writable: true, @@ -1329,6 +1213,7 @@ function setlike(obj, objPrototype, readonly) { }, }, entries: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1338,6 +1223,7 @@ function setlike(obj, objPrototype, readonly) { }, }, keys: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1347,6 +1233,7 @@ function setlike(obj, objPrototype, readonly) { }, }, values: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1356,6 +1243,7 @@ function setlike(obj, objPrototype, readonly) { }, }, forEach: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1365,6 +1253,7 @@ function setlike(obj, objPrototype, readonly) { }, }, has: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1378,6 +1267,7 @@ function setlike(obj, objPrototype, readonly) { if (!readonly) { ObjectDefineProperties(obj, { add: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1387,6 +1277,7 @@ function setlike(obj, objPrototype, readonly) { }, }, delete: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1396,6 +1287,7 @@ function setlike(obj, objPrototype, readonly) { }, }, clear: { + __proto__: null, configurable: true, enumerable: true, writable: true, @@ -1410,11 +1302,9 @@ function setlike(obj, objPrototype, readonly) { export { assertBranded, - AsyncIterable, brand, configureInterface, converters, - createAsyncIterableConverter, createBranded, createDictionaryConverter, createEnumConverter, @@ -1425,7 +1315,6 @@ export { createSequenceConverter, illegalConstructor, invokeCallbackFunction, - isAsyncIterator, makeException, mixinPairIterable, requiredArguments, diff --git a/ext/webidl/Cargo.toml b/ext/webidl/Cargo.toml index fb4e788f7a..a403db2fea 100644 --- a/ext/webidl/Cargo.toml +++ b/ext/webidl/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webidl" -version = "0.164.0" +version = "0.174.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/webidl/internal.d.ts b/ext/webidl/internal.d.ts index d9266f5f54..1ce45463ec 100644 --- a/ext/webidl/internal.d.ts +++ b/ext/webidl/internal.d.ts @@ -438,27 +438,6 @@ declare module "ext:deno_webidl/00_webidl.js" { opts?: any, ) => T[]; - /** - * Create a converter that converts an async iterable of the inner type. - */ - function createAsyncIterableConverter( - converter: ( - v: V, - prefix?: string, - context?: string, - opts?: any, - ) => T, - ): ( - v: any, - prefix?: string, - context?: string, - opts?: any, - ) => ConvertedAsyncIterable; - - interface ConvertedAsyncIterable extends AsyncIterableIterator { - value: V; - } - /** * Create a converter that converts a Promise of the inner type. */ diff --git a/ext/websocket/01_websocket.js b/ext/websocket/01_websocket.js index 60580a56ce..58f4773101 100644 --- a/ext/websocket/01_websocket.js +++ b/ext/websocket/01_websocket.js @@ -161,14 +161,14 @@ class WebSocket extends EventTarget { if (wsURL.protocol !== "ws:" && wsURL.protocol !== "wss:") { throw new DOMException( - "Only ws & wss schemes are allowed in a WebSocket URL.", + `Only ws & wss schemes are allowed in a WebSocket URL: received ${wsURL.protocol}`, "SyntaxError", ); } if (wsURL.hash !== "" || StringPrototypeEndsWith(wsURL.href, "#")) { throw new DOMException( - "Fragments are not allowed in a WebSocket URL.", + "Fragments are not allowed in a WebSocket URL", "SyntaxError", ); } @@ -195,7 +195,7 @@ class WebSocket extends EventTarget { ) ) { throw new DOMException( - "Can't supply multiple times the same protocol.", + "Cannot supply multiple times the same protocol", "SyntaxError", ); } @@ -208,7 +208,7 @@ class WebSocket extends EventTarget { ) ) { throw new DOMException( - "Invalid protocol value.", + "Invalid protocol value", "SyntaxError", ); } @@ -330,7 +330,7 @@ class WebSocket extends EventTarget { data = webidl.converters.WebSocketSend(data, prefix, "Argument 1"); if (this[_readyState] !== OPEN) { - throw new DOMException("readyState not OPEN", "InvalidStateError"); + throw new DOMException("'readyState' not OPEN", "InvalidStateError"); } if (this[_sendQueue].length === 0) { @@ -376,7 +376,7 @@ class WebSocket extends EventTarget { !(code === 1000 || (3000 <= code && code < 5000)) ) { throw new DOMException( - "The close code must be either 1000 or in the range of 3000 to 4999.", + `The close code must be either 1000 or in the range of 3000 to 4999: received ${code}`, "InvalidAccessError", ); } @@ -387,7 +387,7 @@ class WebSocket extends EventTarget { TypedArrayPrototypeGetByteLength(core.encode(reason)) > 123 ) { throw new DOMException( - "The close reason may not be longer than 123 bytes.", + "The close reason may not be longer than 123 bytes", "SyntaxError", ); } @@ -627,15 +627,19 @@ class WebSocket extends EventTarget { ObjectDefineProperties(WebSocket, { CONNECTING: { + __proto__: null, value: 0, }, OPEN: { + __proto__: null, value: 1, }, CLOSING: { + __proto__: null, value: 2, }, CLOSED: { + __proto__: null, value: 3, }, }); diff --git a/ext/websocket/02_websocketstream.js b/ext/websocket/02_websocketstream.js index 92b1c6eae5..838ae3d4ce 100644 --- a/ext/websocket/02_websocketstream.js +++ b/ext/websocket/02_websocketstream.js @@ -323,6 +323,8 @@ class WebSocketStream { } catch (_) { // needed to ignore warnings & assertions } + }, () => { + // needed to ignore warnings & assertions }); PromisePrototypeThen(this[_closeSent].promise, () => { @@ -335,7 +337,6 @@ class WebSocketStream { cancel: async (reason) => { let closeCode = null; let reasonString = ""; - if ( ObjectPrototypeIsPrototypeOf(WebSocketErrorPrototype, reason) ) { diff --git a/ext/websocket/Cargo.toml b/ext/websocket/Cargo.toml index 5012a9ab22..b48b39c99f 100644 --- a/ext/websocket/Cargo.toml +++ b/ext/websocket/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_websocket" -version = "0.169.0" +version = "0.179.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -28,4 +28,5 @@ hyper-util.workspace = true once_cell.workspace = true rustls-tokio-stream.workspace = true serde.workspace = true +thiserror.workspace = true tokio.workspace = true diff --git a/ext/websocket/autobahn/fuzzingclient.js b/ext/websocket/autobahn/fuzzingclient.js index a8cf0c2b76..fed0fd6aa9 100644 --- a/ext/websocket/autobahn/fuzzingclient.js +++ b/ext/websocket/autobahn/fuzzingclient.js @@ -11,7 +11,7 @@ const AUTOBAHN_TESTSUITE_DOCKER = "crossbario/autobahn-testsuite:0.8.2@sha256:5d4ba3aa7d6ab2fdbf6606f3f4ecbe4b66f205ce1cbc176d6cdf650157e52242"; const self = Deno.execPath(); -$`${self} run -A --unstable --config ${pwd}/../../../tests/config/deno.json ${pwd}/autobahn_server.js` +$`${self} run -A --config ${pwd}/../../../tests/config/deno.json ${pwd}/autobahn_server.js` .spawn(); for (let i = 0; i < 6; i++) { diff --git a/ext/websocket/lib.deno_websocket.d.ts b/ext/websocket/lib.deno_websocket.d.ts index c1bdf35421..fb7ea6070c 100644 --- a/ext/websocket/lib.deno_websocket.d.ts +++ b/ext/websocket/lib.deno_websocket.d.ts @@ -6,14 +6,14 @@ /// /** @category WebSockets */ -declare interface CloseEventInit extends EventInit { +interface CloseEventInit extends EventInit { code?: number; reason?: string; wasClean?: boolean; } /** @category WebSockets */ -declare interface CloseEvent extends Event { +interface CloseEvent extends Event { /** * Returns the WebSocket connection close code provided by the server. */ @@ -35,7 +35,7 @@ declare var CloseEvent: { }; /** @category WebSockets */ -declare interface WebSocketEventMap { +interface WebSocketEventMap { close: CloseEvent; error: Event; message: MessageEvent; @@ -52,7 +52,7 @@ declare interface WebSocketEventMap { * @tags allow-net * @category WebSockets */ -declare interface WebSocket extends EventTarget { +interface WebSocket extends EventTarget { /** * Returns a string that indicates how binary data from the WebSocket object is exposed to scripts: * @@ -130,4 +130,4 @@ declare var WebSocket: { }; /** @category WebSockets */ -declare type BinaryType = "arraybuffer" | "blob"; +type BinaryType = "arraybuffer" | "blob"; diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs index 9e320040b9..2a67ac5a17 100644 --- a/ext/websocket/lib.rs +++ b/ext/websocket/lib.rs @@ -1,10 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::stream::WebSocketStream; use bytes::Bytes; -use deno_core::anyhow::bail; -use deno_core::error::invalid_hostname; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures::TryFutureExt; use deno_core::op2; use deno_core::unsync::spawn; @@ -43,7 +39,6 @@ use serde::Serialize; use std::borrow::Cow; use std::cell::Cell; use std::cell::RefCell; -use std::fmt; use std::future::Future; use std::num::NonZeroUsize; use std::path::PathBuf; @@ -75,11 +70,33 @@ static USE_WRITEV: Lazy = Lazy::new(|| { false }); +#[derive(Debug, thiserror::Error)] +pub enum WebsocketError { + #[error(transparent)] + Url(url::ParseError), + #[error(transparent)] + Permission(deno_core::error::AnyError), + #[error(transparent)] + Resource(deno_core::error::AnyError), + #[error(transparent)] + Uri(#[from] http::uri::InvalidUri), + #[error("{0}")] + Io(#[from] std::io::Error), + #[error(transparent)] + WebSocket(#[from] fastwebsockets::WebSocketError), + #[error("failed to connect to WebSocket: {0}")] + ConnectionFailed(#[from] HandshakeError), + #[error(transparent)] + Canceled(#[from] deno_core::Canceled), +} + #[derive(Clone)] pub struct WsRootStoreProvider(Option>); impl WsRootStoreProvider { - pub fn get_or_try_init(&self) -> Result, AnyError> { + pub fn get_or_try_init( + &self, + ) -> Result, deno_core::error::AnyError> { Ok(match &self.0 { Some(provider) => Some(provider.get_or_try_init()?.clone()), None => None, @@ -95,7 +112,7 @@ pub trait WebSocketPermissions { &mut self, _url: &url::Url, _api_name: &str, - ) -> Result<(), AnyError>; + ) -> Result<(), deno_core::error::AnyError>; } impl WebSocketPermissions for deno_permissions::PermissionsContainer { @@ -104,7 +121,7 @@ impl WebSocketPermissions for deno_permissions::PermissionsContainer { &mut self, url: &url::Url, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), deno_core::error::AnyError> { deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) } } @@ -137,13 +154,17 @@ pub fn op_ws_check_permission_and_cancel_handle( #[string] api_name: String, #[string] url: String, cancel_handle: bool, -) -> Result, AnyError> +) -> Result, WebsocketError> where WP: WebSocketPermissions + 'static, { state .borrow_mut::() - .check_net_url(&url::Url::parse(&url)?, &api_name)?; + .check_net_url( + &url::Url::parse(&url).map_err(WebsocketError::Url)?, + &api_name, + ) + .map_err(WebsocketError::Permission)?; if cancel_handle { let rid = state @@ -163,16 +184,46 @@ pub struct CreateResponse { extensions: String, } +#[derive(Debug, thiserror::Error)] +pub enum HandshakeError { + #[error("Missing path in url")] + MissingPath, + #[error("Invalid status code {0}")] + InvalidStatusCode(StatusCode), + #[error(transparent)] + Http(#[from] http::Error), + #[error(transparent)] + WebSocket(#[from] fastwebsockets::WebSocketError), + #[error("Didn't receive h2 alpn, aborting connection")] + NoH2Alpn, + #[error(transparent)] + Rustls(#[from] deno_tls::rustls::Error), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + H2(#[from] h2::Error), + #[error("Invalid hostname: '{0}'")] + InvalidHostname(String), + #[error(transparent)] + RootStoreError(deno_core::error::AnyError), + #[error(transparent)] + Tls(deno_tls::TlsError), + #[error(transparent)] + HeaderName(#[from] http::header::InvalidHeaderName), + #[error(transparent)] + HeaderValue(#[from] http::header::InvalidHeaderValue), +} + async fn handshake_websocket( state: &Rc>, uri: &Uri, protocols: &str, headers: Option>, -) -> Result<(WebSocket, http::HeaderMap), AnyError> { +) -> Result<(WebSocket, http::HeaderMap), HandshakeError> { let mut request = Request::builder().method(Method::GET).uri( uri .path_and_query() - .ok_or(type_error("Missing path in url".to_string()))? + .ok_or(HandshakeError::MissingPath)? .as_str(), ); @@ -194,7 +245,9 @@ async fn handshake_websocket( request = populate_common_request_headers(request, &user_agent, protocols, &headers)?; - let request = request.body(http_body_util::Empty::new())?; + let request = request + .body(http_body_util::Empty::new()) + .map_err(HandshakeError::Http)?; let domain = &uri.host().unwrap().to_string(); let port = &uri.port_u16().unwrap_or(match uri.scheme_str() { Some("wss") => 443, @@ -231,7 +284,7 @@ async fn handshake_websocket( async fn handshake_http1_ws( request: Request>, addr: &String, -) -> Result<(WebSocket, http::HeaderMap), AnyError> { +) -> Result<(WebSocket, http::HeaderMap), HandshakeError> { let tcp_socket = TcpStream::connect(addr).await?; handshake_connection(request, tcp_socket).await } @@ -241,11 +294,11 @@ async fn handshake_http1_wss( request: Request>, domain: &str, addr: &str, -) -> Result<(WebSocket, http::HeaderMap), AnyError> { +) -> Result<(WebSocket, http::HeaderMap), HandshakeError> { let tcp_socket = TcpStream::connect(addr).await?; let tls_config = create_ws_client_config(state, SocketUse::Http1Only)?; let dnsname = ServerName::try_from(domain.to_string()) - .map_err(|_| invalid_hostname(domain))?; + .map_err(|_| HandshakeError::InvalidHostname(domain.to_string()))?; let mut tls_connector = TlsStream::new_client_side( tcp_socket, ClientConnection::new(tls_config.into(), dnsname)?, @@ -266,11 +319,11 @@ async fn handshake_http2_wss( domain: &str, headers: &Option>, addr: &str, -) -> Result<(WebSocket, http::HeaderMap), AnyError> { +) -> Result<(WebSocket, http::HeaderMap), HandshakeError> { let tcp_socket = TcpStream::connect(addr).await?; let tls_config = create_ws_client_config(state, SocketUse::Http2Only)?; let dnsname = ServerName::try_from(domain.to_string()) - .map_err(|_| invalid_hostname(domain))?; + .map_err(|_| HandshakeError::InvalidHostname(domain.to_string()))?; // We need to better expose the underlying errors here let mut tls_connector = TlsStream::new_client_side( tcp_socket, @@ -279,7 +332,7 @@ async fn handshake_http2_wss( ); let handshake = tls_connector.handshake().await?; if handshake.alpn.is_none() { - bail!("Didn't receive h2 alpn, aborting connection"); + return Err(HandshakeError::NoH2Alpn); } let h2 = h2::client::Builder::new(); let (mut send, conn) = h2.handshake::<_, Bytes>(tls_connector).await?; @@ -298,7 +351,7 @@ async fn handshake_http2_wss( let (resp, send) = send.send_request(request.body(())?, false)?; let resp = resp.await?; if resp.status() != StatusCode::OK { - bail!("Invalid status code: {}", resp.status()); + return Err(HandshakeError::InvalidStatusCode(resp.status())); } let (http::response::Parts { headers, .. }, recv) = resp.into_parts(); let mut stream = WebSocket::after_handshake( @@ -317,7 +370,7 @@ async fn handshake_connection< >( request: Request>, socket: S, -) -> Result<(WebSocket, http::HeaderMap), AnyError> { +) -> Result<(WebSocket, http::HeaderMap), HandshakeError> { let (upgraded, response) = fastwebsockets::handshake::client(&LocalExecutor, request, socket).await?; @@ -332,7 +385,7 @@ async fn handshake_connection< pub fn create_ws_client_config( state: &Rc>, socket_use: SocketUse, -) -> Result { +) -> Result { let unsafely_ignore_certificate_errors: Option> = state .borrow() .try_borrow::() @@ -340,7 +393,8 @@ pub fn create_ws_client_config( let root_cert_store = state .borrow() .borrow::() - .get_or_try_init()?; + .get_or_try_init() + .map_err(HandshakeError::RootStoreError)?; create_client_config( root_cert_store, @@ -349,6 +403,7 @@ pub fn create_ws_client_config( TlsKeys::Null, socket_use, ) + .map_err(HandshakeError::Tls) } /// Headers common to both http/1.1 and h2 requests. @@ -357,7 +412,7 @@ fn populate_common_request_headers( user_agent: &str, protocols: &str, headers: &Option>, -) -> Result { +) -> Result { request = request .header("User-Agent", user_agent) .header("Sec-WebSocket-Version", "13"); @@ -368,10 +423,8 @@ fn populate_common_request_headers( if let Some(headers) = headers { for (key, value) in headers { - let name = HeaderName::from_bytes(key) - .map_err(|err| type_error(err.to_string()))?; - let v = HeaderValue::from_bytes(value) - .map_err(|err| type_error(err.to_string()))?; + let name = HeaderName::from_bytes(key)?; + let v = HeaderValue::from_bytes(value)?; let is_disallowed_header = matches!( name, @@ -401,14 +454,17 @@ pub async fn op_ws_create( #[string] protocols: String, #[smi] cancel_handle: Option, #[serde] headers: Option>, -) -> Result +) -> Result where WP: WebSocketPermissions + 'static, { { let mut s = state.borrow_mut(); s.borrow_mut::() - .check_net_url(&url::Url::parse(&url)?, &api_name) + .check_net_url( + &url::Url::parse(&url).map_err(WebsocketError::Url)?, + &api_name, + ) .expect( "Permission check should have been done in op_ws_check_permission", ); @@ -418,7 +474,8 @@ where let r = state .borrow_mut() .resource_table - .get::(cancel_rid)?; + .get::(cancel_rid) + .map_err(WebsocketError::Resource)?; Some(r.0.clone()) } else { None @@ -427,15 +484,11 @@ where let uri: Uri = url.parse()?; let handshake = handshake_websocket(&state, &uri, &protocols, headers) - .map_err(|err| { - AnyError::from(DomExceptionNetworkError::new(&format!( - "failed to connect to WebSocket: {err}" - ))) - }); + .map_err(WebsocketError::ConnectionFailed); let (stream, response) = match cancel_resource { - Some(rc) => handshake.try_or_cancel(rc).await, - None => handshake.await, - }?; + Some(rc) => handshake.try_or_cancel(rc).await?, + None => handshake.await?, + }; if let Some(cancel_rid) = cancel_handle { if let Ok(res) = state.borrow_mut().resource_table.take_any(cancel_rid) { @@ -520,14 +573,12 @@ impl ServerWebSocket { self: &Rc, lock: AsyncMutFuture>>, frame: Frame<'_>, - ) -> Result<(), AnyError> { + ) -> Result<(), WebsocketError> { let mut ws = lock.await; if ws.is_closed() { return Ok(()); } - ws.write_frame(frame) - .await - .map_err(|err| type_error(err.to_string()))?; + ws.write_frame(frame).await?; Ok(()) } } @@ -542,7 +593,7 @@ pub fn ws_create_server_stream( state: &mut OpState, transport: NetworkStream, read_buf: Bytes, -) -> Result { +) -> ResourceId { let mut ws = WebSocket::after_handshake( WebSocketStream::new( stream::WsStreamKind::Network(transport), @@ -554,8 +605,7 @@ pub fn ws_create_server_stream( ws.set_auto_close(true); ws.set_auto_pong(true); - let rid = state.resource_table.add(ServerWebSocket::new(ws)); - Ok(rid) + state.resource_table.add(ServerWebSocket::new(ws)) } fn send_binary(state: &mut OpState, rid: ResourceId, data: &[u8]) { @@ -625,11 +675,12 @@ pub async fn op_ws_send_binary_async( state: Rc>, #[smi] rid: ResourceId, #[buffer] data: JsBuffer, -) -> Result<(), AnyError> { +) -> Result<(), WebsocketError> { let resource = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(WebsocketError::Resource)?; let data = data.to_vec(); let lock = resource.reserve_lock(); resource @@ -643,11 +694,12 @@ pub async fn op_ws_send_text_async( state: Rc>, #[smi] rid: ResourceId, #[string] data: String, -) -> Result<(), AnyError> { +) -> Result<(), WebsocketError> { let resource = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(WebsocketError::Resource)?; let lock = resource.reserve_lock(); resource .write_frame( @@ -677,11 +729,12 @@ pub fn op_ws_get_buffered_amount( pub async fn op_ws_send_ping( state: Rc>, #[smi] rid: ResourceId, -) -> Result<(), AnyError> { +) -> Result<(), WebsocketError> { let resource = state .borrow_mut() .resource_table - .get::(rid)?; + .get::(rid) + .map_err(WebsocketError::Resource)?; let lock = resource.reserve_lock(); resource .write_frame( @@ -697,7 +750,7 @@ pub async fn op_ws_close( #[smi] rid: ResourceId, #[smi] code: Option, #[string] reason: Option, -) -> Result<(), AnyError> { +) -> Result<(), WebsocketError> { let Ok(resource) = state .borrow_mut() .resource_table @@ -712,8 +765,7 @@ pub async fn op_ws_close( resource.closed.set(true); let lock = resource.reserve_lock(); - resource.write_frame(lock, frame).await?; - Ok(()) + resource.write_frame(lock, frame).await } #[op2] @@ -867,32 +919,6 @@ pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_websocket.d.ts") } -#[derive(Debug)] -pub struct DomExceptionNetworkError { - pub msg: String, -} - -impl DomExceptionNetworkError { - pub fn new(msg: &str) -> Self { - DomExceptionNetworkError { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for DomExceptionNetworkError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} - -impl std::error::Error for DomExceptionNetworkError {} - -pub fn get_network_error_class_name(e: &AnyError) -> Option<&'static str> { - e.downcast_ref::() - .map(|_| "DOMExceptionNetworkError") -} - // Needed so hyper can use non Send futures #[derive(Clone)] struct LocalExecutor; diff --git a/ext/webstorage/01_webstorage.js b/ext/webstorage/01_webstorage.js index 635e80d6ec..9e86366563 100644 --- a/ext/webstorage/01_webstorage.js +++ b/ext/webstorage/01_webstorage.js @@ -119,6 +119,7 @@ function createStorage(persistent) { set(target, key, value) { if (typeof key === "symbol") { return ReflectDefineProperty(target, key, { + __proto__: null, value, configurable: true, }); @@ -142,6 +143,9 @@ function createStorage(persistent) { if (ReflectHas(target, key)) { return undefined; } + if (typeof key === "symbol") { + return undefined; + } const value = target.getItem(key); if (value === null) { return undefined; diff --git a/ext/webstorage/Cargo.toml b/ext/webstorage/Cargo.toml index 360f30b38c..911e252414 100644 --- a/ext/webstorage/Cargo.toml +++ b/ext/webstorage/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webstorage" -version = "0.159.0" +version = "0.169.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -17,3 +17,4 @@ path = "lib.rs" deno_core.workspace = true deno_web.workspace = true rusqlite.workspace = true +thiserror.workspace = true diff --git a/ext/webstorage/lib.deno_webstorage.d.ts b/ext/webstorage/lib.deno_webstorage.d.ts index a3a4d6cd10..fa6d403dea 100644 --- a/ext/webstorage/lib.deno_webstorage.d.ts +++ b/ext/webstorage/lib.deno_webstorage.d.ts @@ -11,7 +11,7 @@ * * @category Storage */ -declare interface Storage { +interface Storage { /** * Returns the number of key/value pairs currently present in the list associated with the object. */ diff --git a/ext/webstorage/lib.rs b/ext/webstorage/lib.rs index 99e61a1804..40946f05a7 100644 --- a/ext/webstorage/lib.rs +++ b/ext/webstorage/lib.rs @@ -2,10 +2,8 @@ // NOTE to all: use **cached** prepared statements when interfacing with SQLite. -use std::fmt; use std::path::PathBuf; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use rusqlite::params; @@ -14,6 +12,18 @@ use rusqlite::OptionalExtension; pub use rusqlite; +#[derive(Debug, thiserror::Error)] +pub enum WebStorageError { + #[error("LocalStorage is not supported in this context.")] + ContextNotSupported, + #[error(transparent)] + Sqlite(#[from] rusqlite::Error), + #[error(transparent)] + Io(std::io::Error), + #[error("Exceeded maximum storage size")] + StorageExceeded, +} + #[derive(Clone)] struct OriginStorageDir(PathBuf); @@ -51,15 +61,13 @@ struct SessionStorage(Connection); fn get_webstorage( state: &mut OpState, persistent: bool, -) -> Result<&Connection, AnyError> { +) -> Result<&Connection, WebStorageError> { let conn = if persistent { if state.try_borrow::().is_none() { - let path = state.try_borrow::().ok_or_else(|| { - DomExceptionNotSupportedError::new( - "LocalStorage is not supported in this context.", - ) - })?; - std::fs::create_dir_all(&path.0)?; + let path = state + .try_borrow::() + .ok_or(WebStorageError::ContextNotSupported)?; + std::fs::create_dir_all(&path.0).map_err(WebStorageError::Io)?; let conn = Connection::open(path.0.join("local_storage"))?; // Enable write-ahead-logging and tweak some other stuff. let initial_pragmas = " @@ -106,7 +114,7 @@ fn get_webstorage( pub fn op_webstorage_length( state: &mut OpState, persistent: bool, -) -> Result { +) -> Result { let conn = get_webstorage(state, persistent)?; let mut stmt = conn.prepare_cached("SELECT COUNT(*) FROM data")?; @@ -121,7 +129,7 @@ pub fn op_webstorage_key( state: &mut OpState, #[smi] index: u32, persistent: bool, -) -> Result, AnyError> { +) -> Result, WebStorageError> { let conn = get_webstorage(state, persistent)?; let mut stmt = @@ -135,14 +143,9 @@ pub fn op_webstorage_key( } #[inline] -fn size_check(input: usize) -> Result<(), AnyError> { +fn size_check(input: usize) -> Result<(), WebStorageError> { if input >= MAX_STORAGE_BYTES { - return Err( - deno_web::DomExceptionQuotaExceededError::new( - "Exceeded maximum storage size", - ) - .into(), - ); + return Err(WebStorageError::StorageExceeded); } Ok(()) @@ -154,7 +157,7 @@ pub fn op_webstorage_set( #[string] key: &str, #[string] value: &str, persistent: bool, -) -> Result<(), AnyError> { +) -> Result<(), WebStorageError> { let conn = get_webstorage(state, persistent)?; size_check(key.len() + value.len())?; @@ -178,7 +181,7 @@ pub fn op_webstorage_get( state: &mut OpState, #[string] key_name: String, persistent: bool, -) -> Result, AnyError> { +) -> Result, WebStorageError> { let conn = get_webstorage(state, persistent)?; let mut stmt = conn.prepare_cached("SELECT value FROM data WHERE key = ?")?; @@ -194,7 +197,7 @@ pub fn op_webstorage_remove( state: &mut OpState, #[string] key_name: &str, persistent: bool, -) -> Result<(), AnyError> { +) -> Result<(), WebStorageError> { let conn = get_webstorage(state, persistent)?; let mut stmt = conn.prepare_cached("DELETE FROM data WHERE key = ?")?; @@ -207,7 +210,7 @@ pub fn op_webstorage_remove( pub fn op_webstorage_clear( state: &mut OpState, persistent: bool, -) -> Result<(), AnyError> { +) -> Result<(), WebStorageError> { let conn = get_webstorage(state, persistent)?; let mut stmt = conn.prepare_cached("DELETE FROM data")?; @@ -221,7 +224,7 @@ pub fn op_webstorage_clear( pub fn op_webstorage_iterate_keys( state: &mut OpState, persistent: bool, -) -> Result, AnyError> { +) -> Result, WebStorageError> { let conn = get_webstorage(state, persistent)?; let mut stmt = conn.prepare_cached("SELECT key FROM data")?; @@ -232,31 +235,3 @@ pub fn op_webstorage_iterate_keys( Ok(keys) } - -#[derive(Debug)] -pub struct DomExceptionNotSupportedError { - pub msg: String, -} - -impl DomExceptionNotSupportedError { - pub fn new(msg: &str) -> Self { - DomExceptionNotSupportedError { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for DomExceptionNotSupportedError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} - -impl std::error::Error for DomExceptionNotSupportedError {} - -pub fn get_not_supported_error_class_name( - e: &AnyError, -) -> Option<&'static str> { - e.downcast_ref::() - .map(|_| "DOMExceptionNotSupportedError") -} diff --git a/import_map.json b/import_map.json index d3fa27e61c..c01c0bb01b 100644 --- a/import_map.json +++ b/import_map.json @@ -17,6 +17,7 @@ "@std/assert/less": "./tests/util/std/assert/less.ts", "@std/assert/less-or-equal": "./tests/util/std/assert/less_or_equal.ts", "@std/assert/match": "./tests/util/std/assert/match.ts", + "@std/assert/unstable-never": "./tests/util/std/assert/unstable_never.ts", "@std/assert/not-equals": "./tests/util/std/assert/not_equals.ts", "@std/assert/not-instance-of": "./tests/util/std/assert/not_instance_of.ts", "@std/assert/not-match": "./tests/util/std/assert/not_match.ts", @@ -50,10 +51,14 @@ "@std/bytes/last-index-of-needle": "./tests/util/std/bytes/last_index_of_needle.ts", "@std/bytes/repeat": "./tests/util/std/bytes/repeat.ts", "@std/bytes/starts-with": "./tests/util/std/bytes/starts_with.ts", + "@std/cache": "./tests/util/std/cache/mod.ts", + "@std/cache/lru-cache": "./tests/util/std/cache/lru_cache.ts", + "@std/cache/memoize": "./tests/util/std/cache/memoize.ts", + "@std/cache/ttl-cache": "./tests/util/std/cache/ttl_cache.ts", "@std/cli": "./tests/util/std/cli/mod.ts", "@std/cli/parse-args": "./tests/util/std/cli/parse_args.ts", "@std/cli/prompt-secret": "./tests/util/std/cli/prompt_secret.ts", - "@std/cli/spinner": "./tests/util/std/cli/spinner.ts", + "@std/cli/unstable-spinner": "./tests/util/std/cli/unstable_spinner.ts", "@std/cli/unicode-width": "./tests/util/std/cli/unicode_width.ts", "@std/collections": "./tests/util/std/collections/mod.ts", "@std/collections/aggregate-groups": "./tests/util/std/collections/aggregate_groups.ts", @@ -111,6 +116,7 @@ "@std/csv/stringify": "./tests/util/std/csv/stringify.ts", "@std/csv/stringify-stream": "./tests/util/std/csv/stringify_stream.ts", "@std/data-structures": "./tests/util/std/data_structures/mod.ts", + "@std/data-structures/unstable-bidirectional-map": "./tests/util/std/data_structures/unstable_bidirectional_map.ts", "@std/data-structures/binary-heap": "./tests/util/std/data_structures/binary_heap.ts", "@std/data-structures/binary-search-tree": "./tests/util/std/data_structures/binary_search_tree.ts", "@std/data-structures/comparators": "./tests/util/std/data_structures/comparators.ts", @@ -130,10 +136,16 @@ "@std/encoding": "./tests/util/std/encoding/mod.ts", "@std/encoding/ascii85": "./tests/util/std/encoding/ascii85.ts", "@std/encoding/base32": "./tests/util/std/encoding/base32.ts", + "@std/encoding/unstable-base32-stream": "./tests/util/std/encoding/unstable_base32_stream.ts", + "@std/encoding/unstable-base32hex": "./tests/util/std/encoding/unstable_base32hex.ts", + "@std/encoding/unstable-base32hex-stream": "./tests/util/std/encoding/unstable_base32hex_stream.ts", "@std/encoding/base58": "./tests/util/std/encoding/base58.ts", "@std/encoding/base64": "./tests/util/std/encoding/base64.ts", + "@std/encoding/unstable-base64-stream": "./tests/util/std/encoding/unstable_base64_stream.ts", "@std/encoding/base64url": "./tests/util/std/encoding/base64url.ts", + "@std/encoding/unstable-base64url-stream": "./tests/util/std/encoding/unstable_base64url_stream.ts", "@std/encoding/hex": "./tests/util/std/encoding/hex.ts", + "@std/encoding/unstable-hex-stream": "./tests/util/std/encoding/unstable_hex_stream.ts", "@std/encoding/varint": "./tests/util/std/encoding/varint.ts", "@std/expect": "./tests/util/std/expect/mod.ts", "@std/expect/expect": "./tests/util/std/expect/expect.ts", @@ -148,6 +160,7 @@ "@std/front-matter/test": "./tests/util/std/front_matter/test.ts", "@std/front-matter/toml": "./tests/util/std/front_matter/toml.ts", "@std/front-matter/yaml": "./tests/util/std/front_matter/yaml.ts", + "@std/front-matter/unstable-yaml": "./tests/util/std/front_matter/unstable_yaml.ts", "@std/front-matter/types": "./tests/util/std/front_matter/types.ts", "@std/fs": "./tests/util/std/fs/mod.ts", "@std/fs/copy": "./tests/util/std/fs/copy.ts", @@ -163,16 +176,20 @@ "@std/fs/walk": "./tests/util/std/fs/walk.ts", "@std/html": "./tests/util/std/html/mod.ts", "@std/html/entities": "./tests/util/std/html/entities.ts", + "@std/html/unstable-is-valid-custom-element-name": "./tests/util/std/html/unstable_is_valid_custom_element_name.ts", "@std/html/named-entity-list.json": "./tests/util/std/html/named_entity_list.json", "@std/http": "./tests/util/std/http/mod.ts", "@std/http/cookie": "./tests/util/std/http/cookie.ts", "@std/http/etag": "./tests/util/std/http/etag.ts", "@std/http/file-server": "./tests/util/std/http/file_server.ts", + "@std/http/unstable-header": "./tests/util/std/http/unstable_header.ts", + "@std/http/unstable-method": "./tests/util/std/http/unstable_method.ts", "@std/http/negotiation": "./tests/util/std/http/negotiation.ts", "@std/http/server-sent-event-stream": "./tests/util/std/http/server_sent_event_stream.ts", "@std/http/status": "./tests/util/std/http/status.ts", - "@std/http/signed-cookie": "./tests/util/std/http/signed_cookie.ts", + "@std/http/unstable-signed-cookie": "./tests/util/std/http/unstable_signed_cookie.ts", "@std/http/user-agent": "./tests/util/std/http/user_agent.ts", + "@std/http/unstable-route": "./tests/util/std/http/unstable_route.ts", "@std/ini": "./tests/util/std/ini/mod.ts", "@std/ini/parse": "./tests/util/std/ini/parse.ts", "@std/ini/stringify": "./tests/util/std/ini/stringify.ts", @@ -243,7 +260,7 @@ "@std/msgpack/encode": "./tests/util/std/msgpack/encode.ts", "@std/net": "./tests/util/std/net/mod.ts", "@std/net/get-available-port": "./tests/util/std/net/get_available_port.ts", - "@std/net/get-network-address": "./tests/util/std/net/get_network_address.ts", + "@std/net/unstable-get-network-address": "./tests/util/std/net/unstable_get_network_address.ts", "@std/path": "./tests/util/std/path/mod.ts", "@std/path/basename": "./tests/util/std/path/basename.ts", "@std/path/common": "./tests/util/std/path/common.ts", @@ -280,11 +297,21 @@ "@std/path/posix/resolve": "./tests/util/std/path/posix/resolve.ts", "@std/path/posix/to-file-url": "./tests/util/std/path/posix/to_file_url.ts", "@std/path/posix/to-namespaced-path": "./tests/util/std/path/posix/to_namespaced_path.ts", + "@std/path/posix/unstable-basename": "./tests/util/std/path/posix/unstable_basename.ts", + "@std/path/posix/unstable-dirname": "./tests/util/std/path/posix/unstable_dirname.ts", + "@std/path/posix/unstable-extname": "./tests/util/std/path/posix/unstable_extname.ts", + "@std/path/posix/unstable-join": "./tests/util/std/path/posix/unstable_join.ts", + "@std/path/posix/unstable-normalize": "./tests/util/std/path/posix/unstable_normalize.ts", "@std/path/relative": "./tests/util/std/path/relative.ts", "@std/path/resolve": "./tests/util/std/path/resolve.ts", "@std/path/to-file-url": "./tests/util/std/path/to_file_url.ts", "@std/path/to-namespaced-path": "./tests/util/std/path/to_namespaced_path.ts", "@std/path/types": "./tests/util/std/path/types.ts", + "@std/path/unstable-basename": "./tests/util/std/path/unstable_basename.ts", + "@std/path/unstable-dirname": "./tests/util/std/path/unstable_dirname.ts", + "@std/path/unstable-extname": "./tests/util/std/path/unstable_extname.ts", + "@std/path/unstable-join": "./tests/util/std/path/unstable_join.ts", + "@std/path/unstable-normalize": "./tests/util/std/path/unstable_normalize.ts", "@std/path/windows": "./tests/util/std/path/windows/mod.ts", "@std/path/windows/basename": "./tests/util/std/path/windows/basename.ts", "@std/path/windows/common": "./tests/util/std/path/windows/common.ts", @@ -305,6 +332,17 @@ "@std/path/windows/resolve": "./tests/util/std/path/windows/resolve.ts", "@std/path/windows/to-file-url": "./tests/util/std/path/windows/to_file_url.ts", "@std/path/windows/to-namespaced-path": "./tests/util/std/path/windows/to_namespaced_path.ts", + "@std/path/windows/unstable-basename": "./tests/util/std/path/windows/unstable_basename.ts", + "@std/path/windows/unstable-dirname": "./tests/util/std/path/windows/unstable_dirname.ts", + "@std/path/windows/unstable-extname": "./tests/util/std/path/windows/unstable_extname.ts", + "@std/path/windows/unstable-join": "./tests/util/std/path/windows/unstable_join.ts", + "@std/path/windows/unstable-normalize": "./tests/util/std/path/windows/unstable_normalize.ts", + "@std/random": "./tests/util/std/random/mod.ts", + "@std/random/between": "./tests/util/std/random/between.ts", + "@std/random/integer-between": "./tests/util/std/random/integer_between.ts", + "@std/random/sample": "./tests/util/std/random/sample.ts", + "@std/random/seeded": "./tests/util/std/random/seeded.ts", + "@std/random/shuffle": "./tests/util/std/random/shuffle.ts", "@std/regexp": "./tests/util/std/regexp/mod.ts", "@std/regexp/escape": "./tests/util/std/regexp/escape.ts", "@std/semver": "./tests/util/std/semver/mod.ts", @@ -342,14 +380,19 @@ "@std/streams/limited-bytes-transform-stream": "./tests/util/std/streams/limited_bytes_transform_stream.ts", "@std/streams/limited-transform-stream": "./tests/util/std/streams/limited_transform_stream.ts", "@std/streams/merge-readable-streams": "./tests/util/std/streams/merge_readable_streams.ts", + "@std/streams/unstable-fixed-chunk-stream": "./tests/util/std/streams/unstable_fixed_chunk_stream.ts", "@std/streams/text-delimiter-stream": "./tests/util/std/streams/text_delimiter_stream.ts", "@std/streams/text-line-stream": "./tests/util/std/streams/text_line_stream.ts", "@std/streams/to-array-buffer": "./tests/util/std/streams/to_array_buffer.ts", "@std/streams/to-blob": "./tests/util/std/streams/to_blob.ts", "@std/streams/to-json": "./tests/util/std/streams/to_json.ts", + "@std/streams/unstable-to-lines": "./tests/util/std/streams/unstable_to_lines.ts", "@std/streams/to-text": "./tests/util/std/streams/to_text.ts", "@std/streams/to-transform-stream": "./tests/util/std/streams/to_transform_stream.ts", "@std/streams/zip-readable-streams": "./tests/util/std/streams/zip_readable_streams.ts", + "@std/tar": "./tests/util/std/tar/mod.ts", + "@std/tar/tar-stream": "./tests/util/std/tar/tar_stream.ts", + "@std/tar/untar-stream": "./tests/util/std/tar/untar_stream.ts", "@std/testing/bdd": "./tests/util/std/testing/bdd.ts", "@std/testing/mock": "./tests/util/std/testing/mock.ts", "@std/testing/snapshot": "./tests/util/std/testing/snapshot.ts", @@ -359,8 +402,9 @@ "@std/text/closest-string": "./tests/util/std/text/closest_string.ts", "@std/text/compare-similarity": "./tests/util/std/text/compare_similarity.ts", "@std/text/levenshtein-distance": "./tests/util/std/text/levenshtein_distance.ts", + "@std/text/unstable-slugify": "./tests/util/std/text/unstable_slugify.ts", "@std/text/to-camel-case": "./tests/util/std/text/to_camel_case.ts", - "@std/text/to-constant-case": "./tests/util/std/text/to_constant_case.ts", + "@std/text/unstable-to-constant-case": "./tests/util/std/text/unstable_to_constant_case.ts", "@std/text/to-kebab-case": "./tests/util/std/text/to_kebab_case.ts", "@std/text/to-pascal-case": "./tests/util/std/text/to_pascal_case.ts", "@std/text/to-snake-case": "./tests/util/std/text/to_snake_case.ts", @@ -372,12 +416,6 @@ "@std/ulid/decode-time": "./tests/util/std/ulid/decode_time.ts", "@std/ulid/monotonic-ulid": "./tests/util/std/ulid/monotonic_ulid.ts", "@std/ulid/ulid": "./tests/util/std/ulid/ulid.ts", - "@std/url": "./tests/util/std/url/mod.ts", - "@std/url/basename": "./tests/util/std/url/basename.ts", - "@std/url/dirname": "./tests/util/std/url/dirname.ts", - "@std/url/extname": "./tests/util/std/url/extname.ts", - "@std/url/join": "./tests/util/std/url/join.ts", - "@std/url/normalize": "./tests/util/std/url/normalize.ts", "@std/uuid": "./tests/util/std/uuid/mod.ts", "@std/uuid/common": "./tests/util/std/uuid/common.ts", "@std/uuid/constants": "./tests/util/std/uuid/constants.ts", @@ -385,6 +423,7 @@ "@std/uuid/v3": "./tests/util/std/uuid/v3.ts", "@std/uuid/v4": "./tests/util/std/uuid/v4.ts", "@std/uuid/v5": "./tests/util/std/uuid/v5.ts", + "@std/uuid/unstable-v7": "./tests/util/std/uuid/unstable_v7.ts", "@std/webgpu": "./tests/util/std/webgpu/mod.ts", "@std/webgpu/create-capture": "./tests/util/std/webgpu/create_capture.ts", "@std/webgpu/describe-texture-format": "./tests/util/std/webgpu/describe_texture_format.ts", diff --git a/resolvers/deno/Cargo.toml b/resolvers/deno/Cargo.toml new file mode 100644 index 0000000000..418e1cb522 --- /dev/null +++ b/resolvers/deno/Cargo.toml @@ -0,0 +1,29 @@ +# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +[package] +name = "deno_resolver" +version = "0.6.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +readme = "README.md" +repository.workspace = true +description = "Deno resolution algorithm" + +[lib] +path = "lib.rs" + +[dependencies] +anyhow.workspace = true +base32.workspace = true +deno_media_type.workspace = true +deno_package_json.workspace = true +deno_package_json.features = ["sync"] +deno_path_util.workspace = true +deno_semver.workspace = true +node_resolver.workspace = true +thiserror.workspace = true +url.workspace = true + +[dev-dependencies] +test_util.workspace = true diff --git a/resolvers/deno/README.md b/resolvers/deno/README.md new file mode 100644 index 0000000000..f51619a314 --- /dev/null +++ b/resolvers/deno/README.md @@ -0,0 +1,3 @@ +# deno_resolver + +Deno resolution algorithm. diff --git a/resolvers/deno/clippy.toml b/resolvers/deno/clippy.toml new file mode 100644 index 0000000000..733ac83da1 --- /dev/null +++ b/resolvers/deno/clippy.toml @@ -0,0 +1,52 @@ +disallowed-methods = [ + { path = "std::env::current_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::canonicalize", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::is_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::is_file", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::is_symlink", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::read_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::read_link", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::symlink_metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::try_exists", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::exists", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::canonicalize", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::is_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::is_file", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::is_symlink", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::read_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::read_link", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::symlink_metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::PathBuf::try_exists", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::env::set_current_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::env::temp_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::canonicalize", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::copy", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::create_dir_all", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::create_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::DirBuilder::new", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::hard_link", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::OpenOptions::new", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::read_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::read_link", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::read_to_string", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::read", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::remove_dir_all", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::remove_dir", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::remove_file", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::rename", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::set_permissions", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::symlink_metadata", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::fs::write", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::canonicalize", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "std::path::Path::exists", reason = "File system operations should be done using DenoResolverFs trait" }, + { path = "url::Url::to_file_path", reason = "Use deno_path_util instead so it works in Wasm" }, + { path = "url::Url::from_file_path", reason = "Use deno_path_util instead so it works in Wasm" }, + { path = "url::Url::from_directory_path", reason = "Use deno_path_util instead so it works in Wasm" }, +] +disallowed-types = [ + # todo(dsherret): consider for the future + # { path = "std::sync::Arc", reason = "use crate::sync::MaybeArc instead" }, +] diff --git a/resolvers/deno/fs.rs b/resolvers/deno/fs.rs new file mode 100644 index 0000000000..b08be37982 --- /dev/null +++ b/resolvers/deno/fs.rs @@ -0,0 +1,27 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::path::Path; +use std::path::PathBuf; + +pub struct DirEntry { + pub name: String, + pub is_file: bool, + pub is_directory: bool, +} + +pub trait DenoResolverFs { + fn read_to_string_lossy(&self, path: &Path) -> std::io::Result; + fn realpath_sync(&self, path: &Path) -> std::io::Result; + fn is_dir_sync(&self, path: &Path) -> bool; + fn read_dir_sync(&self, dir_path: &Path) -> std::io::Result>; +} + +pub(crate) struct DenoPkgJsonFsAdapter<'a, Fs: DenoResolverFs>(pub &'a Fs); + +impl<'a, Fs: DenoResolverFs> deno_package_json::fs::DenoPkgJsonFs + for DenoPkgJsonFsAdapter<'a, Fs> +{ + fn read_to_string_lossy(&self, path: &Path) -> std::io::Result { + self.0.read_to_string_lossy(path) + } +} diff --git a/resolvers/deno/lib.rs b/resolvers/deno/lib.rs new file mode 100644 index 0000000000..57fa67512a --- /dev/null +++ b/resolvers/deno/lib.rs @@ -0,0 +1,5 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +pub mod fs; +pub mod npm; +pub mod sloppy_imports; diff --git a/resolvers/deno/npm/byonm.rs b/resolvers/deno/npm/byonm.rs new file mode 100644 index 0000000000..3394b3e501 --- /dev/null +++ b/resolvers/deno/npm/byonm.rs @@ -0,0 +1,362 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::borrow::Cow; +use std::path::Path; +use std::path::PathBuf; +use std::sync::Arc; + +use deno_package_json::PackageJson; +use deno_package_json::PackageJsonDepValue; +use deno_path_util::url_to_file_path; +use deno_semver::package::PackageReq; +use deno_semver::Version; +use node_resolver::errors::PackageFolderResolveError; +use node_resolver::errors::PackageFolderResolveIoError; +use node_resolver::errors::PackageJsonLoadError; +use node_resolver::errors::PackageNotFoundError; +use node_resolver::load_pkg_json; +use node_resolver::NpmResolver; +use thiserror::Error; +use url::Url; + +use crate::fs::DenoPkgJsonFsAdapter; +use crate::fs::DenoResolverFs; + +use super::local::normalize_pkg_name_for_node_modules_deno_folder; + +#[derive(Debug, Error)] +pub enum ByonmResolvePkgFolderFromDenoReqError { + #[error("Could not find \"{}\" in a node_modules folder. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?", .0)] + MissingAlias(String), + #[error(transparent)] + PackageJson(#[from] PackageJsonLoadError), + #[error("Could not find a matching package for 'npm:{}' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `\"nodeModulesDir\": \"auto\"` in your deno.json file.", .0)] + UnmatchedReq(PackageReq), + #[error(transparent)] + Io(#[from] std::io::Error), +} + +pub struct ByonmNpmResolverCreateOptions { + pub fs: Fs, + // todo(dsherret): investigate removing this + pub root_node_modules_dir: Option, +} + +#[derive(Debug)] +pub struct ByonmNpmResolver { + fs: Fs, + root_node_modules_dir: Option, +} + +impl Clone for ByonmNpmResolver { + fn clone(&self) -> Self { + Self { + fs: self.fs.clone(), + root_node_modules_dir: self.root_node_modules_dir.clone(), + } + } +} + +impl ByonmNpmResolver { + pub fn new(options: ByonmNpmResolverCreateOptions) -> Self { + Self { + fs: options.fs, + root_node_modules_dir: options.root_node_modules_dir, + } + } + + pub fn root_node_modules_dir(&self) -> Option<&Path> { + self.root_node_modules_dir.as_deref() + } + + fn load_pkg_json( + &self, + path: &Path, + ) -> Result>, PackageJsonLoadError> { + load_pkg_json(&DenoPkgJsonFsAdapter(&self.fs), path) + } + + /// Finds the ancestor package.json that contains the specified dependency. + pub fn find_ancestor_package_json_with_dep( + &self, + dep_name: &str, + referrer: &Url, + ) -> Option> { + let referrer_path = url_to_file_path(referrer).ok()?; + let mut current_folder = referrer_path.parent()?; + loop { + let pkg_json_path = current_folder.join("package.json"); + if let Ok(Some(pkg_json)) = self.load_pkg_json(&pkg_json_path) { + if let Some(deps) = &pkg_json.dependencies { + if deps.contains_key(dep_name) { + return Some(pkg_json); + } + } + if let Some(deps) = &pkg_json.dev_dependencies { + if deps.contains_key(dep_name) { + return Some(pkg_json); + } + } + } + + if let Some(parent) = current_folder.parent() { + current_folder = parent; + } else { + return None; + } + } + } + + pub fn resolve_pkg_folder_from_deno_module_req( + &self, + req: &PackageReq, + referrer: &Url, + ) -> Result { + fn node_resolve_dir( + fs: &Fs, + alias: &str, + start_dir: &Path, + ) -> std::io::Result> { + for ancestor in start_dir.ancestors() { + let node_modules_folder = ancestor.join("node_modules"); + let sub_dir = join_package_name(&node_modules_folder, alias); + if fs.is_dir_sync(&sub_dir) { + return Ok(Some(deno_path_util::canonicalize_path_maybe_not_exists( + &sub_dir, + &|path| fs.realpath_sync(path), + )?)); + } + } + Ok(None) + } + + // now attempt to resolve if it's found in any package.json + let maybe_pkg_json_and_alias = + self.resolve_pkg_json_and_alias_for_req(req, referrer)?; + match maybe_pkg_json_and_alias { + Some((pkg_json, alias)) => { + // now try node resolution + if let Some(resolved) = + node_resolve_dir(&self.fs, &alias, pkg_json.dir_path())? + { + return Ok(resolved); + } + + Err(ByonmResolvePkgFolderFromDenoReqError::MissingAlias(alias)) + } + None => { + // now check if node_modules/.deno/ matches this constraint + if let Some(folder) = self.resolve_folder_in_root_node_modules(req) { + return Ok(folder); + } + + Err(ByonmResolvePkgFolderFromDenoReqError::UnmatchedReq( + req.clone(), + )) + } + } + } + + fn resolve_pkg_json_and_alias_for_req( + &self, + req: &PackageReq, + referrer: &Url, + ) -> Result, String)>, PackageJsonLoadError> { + fn resolve_alias_from_pkg_json( + req: &PackageReq, + pkg_json: &PackageJson, + ) -> Option { + let deps = pkg_json.resolve_local_package_json_deps(); + for (key, value) in deps { + if let Ok(value) = value { + match value { + PackageJsonDepValue::Req(dep_req) => { + if dep_req.name == req.name + && dep_req.version_req.intersects(&req.version_req) + { + return Some(key); + } + } + PackageJsonDepValue::Workspace(_workspace) => { + if key == req.name && req.version_req.tag() == Some("workspace") { + return Some(key); + } + } + } + } + } + None + } + + // attempt to resolve the npm specifier from the referrer's package.json, + if let Ok(file_path) = url_to_file_path(referrer) { + let mut current_path = file_path.as_path(); + while let Some(dir_path) = current_path.parent() { + let package_json_path = dir_path.join("package.json"); + if let Some(pkg_json) = self.load_pkg_json(&package_json_path)? { + if let Some(alias) = + resolve_alias_from_pkg_json(req, pkg_json.as_ref()) + { + return Ok(Some((pkg_json, alias))); + } + } + current_path = dir_path; + } + } + + // otherwise, fall fallback to the project's package.json + if let Some(root_node_modules_dir) = &self.root_node_modules_dir { + let root_pkg_json_path = + root_node_modules_dir.parent().unwrap().join("package.json"); + if let Some(pkg_json) = self.load_pkg_json(&root_pkg_json_path)? { + if let Some(alias) = resolve_alias_from_pkg_json(req, pkg_json.as_ref()) + { + return Ok(Some((pkg_json, alias))); + } + } + } + + Ok(None) + } + + fn resolve_folder_in_root_node_modules( + &self, + req: &PackageReq, + ) -> Option { + // now check if node_modules/.deno/ matches this constraint + let root_node_modules_dir = self.root_node_modules_dir.as_ref()?; + let node_modules_deno_dir = root_node_modules_dir.join(".deno"); + let Ok(entries) = self.fs.read_dir_sync(&node_modules_deno_dir) else { + return None; + }; + let search_prefix = format!( + "{}@", + normalize_pkg_name_for_node_modules_deno_folder(&req.name) + ); + let mut best_version = None; + + // example entries: + // - @denotest+add@1.0.0 + // - @denotest+add@1.0.0_1 + for entry in entries { + if !entry.is_directory { + continue; + } + let Some(version_and_copy_idx) = entry.name.strip_prefix(&search_prefix) + else { + continue; + }; + let version = version_and_copy_idx + .rsplit_once('_') + .map(|(v, _)| v) + .unwrap_or(version_and_copy_idx); + let Ok(version) = Version::parse_from_npm(version) else { + continue; + }; + if let Some(tag) = req.version_req.tag() { + let initialized_file = + node_modules_deno_dir.join(&entry.name).join(".initialized"); + let Ok(contents) = self.fs.read_to_string_lossy(&initialized_file) + else { + continue; + }; + let mut tags = contents.split(',').map(str::trim); + if tags.any(|t| t == tag) { + if let Some((best_version_version, _)) = &best_version { + if version > *best_version_version { + best_version = Some((version, entry.name)); + } + } else { + best_version = Some((version, entry.name)); + } + } + } else if req.version_req.matches(&version) { + if let Some((best_version_version, _)) = &best_version { + if version > *best_version_version { + best_version = Some((version, entry.name)); + } + } else { + best_version = Some((version, entry.name)); + } + } + } + + best_version.map(|(_version, entry_name)| { + join_package_name( + &node_modules_deno_dir.join(entry_name).join("node_modules"), + &req.name, + ) + }) + } +} + +impl NpmResolver + for ByonmNpmResolver +{ + fn resolve_package_folder_from_package( + &self, + name: &str, + referrer: &Url, + ) -> Result { + fn inner( + fs: &Fs, + name: &str, + referrer: &Url, + ) -> Result { + let maybe_referrer_file = url_to_file_path(referrer).ok(); + let maybe_start_folder = + maybe_referrer_file.as_ref().and_then(|f| f.parent()); + if let Some(start_folder) = maybe_start_folder { + for current_folder in start_folder.ancestors() { + let node_modules_folder = if current_folder.ends_with("node_modules") + { + Cow::Borrowed(current_folder) + } else { + Cow::Owned(current_folder.join("node_modules")) + }; + + let sub_dir = join_package_name(&node_modules_folder, name); + if fs.is_dir_sync(&sub_dir) { + return Ok(sub_dir); + } + } + } + + Err( + PackageNotFoundError { + package_name: name.to_string(), + referrer: referrer.clone(), + referrer_extra: None, + } + .into(), + ) + } + + let path = inner(&self.fs, name, referrer)?; + self.fs.realpath_sync(&path).map_err(|err| { + PackageFolderResolveIoError { + package_name: name.to_string(), + referrer: referrer.clone(), + source: err, + } + .into() + }) + } + + fn in_npm_package(&self, specifier: &Url) -> bool { + specifier.scheme() == "file" + && specifier + .path() + .to_ascii_lowercase() + .contains("/node_modules/") + } +} + +fn join_package_name(path: &Path, package_name: &str) -> PathBuf { + let mut path = path.to_path_buf(); + // ensure backslashes are used on windows + for part in package_name.split('/') { + path = path.join(part); + } + path +} diff --git a/resolvers/deno/npm/local.rs b/resolvers/deno/npm/local.rs new file mode 100644 index 0000000000..aef476ad94 --- /dev/null +++ b/resolvers/deno/npm/local.rs @@ -0,0 +1,27 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::borrow::Cow; + +/// Normalizes a package name for use at `node_modules/.deno/@[_]` +pub fn normalize_pkg_name_for_node_modules_deno_folder(name: &str) -> Cow { + let name = if name.to_lowercase() == name { + Cow::Borrowed(name) + } else { + Cow::Owned(format!("_{}", mixed_case_package_name_encode(name))) + }; + if name.starts_with('@') { + name.replace('/', "+").into() + } else { + name + } +} + +fn mixed_case_package_name_encode(name: &str) -> String { + // use base32 encoding because it's reversible and the character set + // only includes the characters within 0-9 and A-Z so it can be lower cased + base32::encode( + base32::Alphabet::Rfc4648Lower { padding: false }, + name.as_bytes(), + ) + .to_lowercase() +} diff --git a/resolvers/deno/npm/mod.rs b/resolvers/deno/npm/mod.rs new file mode 100644 index 0000000000..9d885cad31 --- /dev/null +++ b/resolvers/deno/npm/mod.rs @@ -0,0 +1,9 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +mod byonm; +mod local; + +pub use byonm::ByonmNpmResolver; +pub use byonm::ByonmNpmResolverCreateOptions; +pub use byonm::ByonmResolvePkgFolderFromDenoReqError; +pub use local::normalize_pkg_name_for_node_modules_deno_folder; diff --git a/resolvers/deno/sloppy_imports.rs b/resolvers/deno/sloppy_imports.rs new file mode 100644 index 0000000000..e215e87686 --- /dev/null +++ b/resolvers/deno/sloppy_imports.rs @@ -0,0 +1,513 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::borrow::Cow; +use std::path::Path; +use std::path::PathBuf; + +use deno_media_type::MediaType; +use deno_path_util::url_from_file_path; +use deno_path_util::url_to_file_path; +use url::Url; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SloppyImportsFsEntry { + File, + Dir, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SloppyImportsResolution { + /// Ex. `./file.js` to `./file.ts` + JsToTs(Url), + /// Ex. `./file` to `./file.ts` + NoExtension(Url), + /// Ex. `./dir` to `./dir/index.ts` + Directory(Url), +} + +impl SloppyImportsResolution { + pub fn as_specifier(&self) -> &Url { + match self { + Self::JsToTs(specifier) => specifier, + Self::NoExtension(specifier) => specifier, + Self::Directory(specifier) => specifier, + } + } + + pub fn into_specifier(self) -> Url { + match self { + Self::JsToTs(specifier) => specifier, + Self::NoExtension(specifier) => specifier, + Self::Directory(specifier) => specifier, + } + } + + pub fn as_suggestion_message(&self) -> String { + format!("Maybe {}", self.as_base_message()) + } + + pub fn as_quick_fix_message(&self) -> String { + let message = self.as_base_message(); + let mut chars = message.chars(); + format!( + "{}{}.", + chars.next().unwrap().to_uppercase(), + chars.as_str() + ) + } + + fn as_base_message(&self) -> String { + match self { + SloppyImportsResolution::JsToTs(specifier) => { + let media_type = MediaType::from_specifier(specifier); + format!("change the extension to '{}'", media_type.as_ts_extension()) + } + SloppyImportsResolution::NoExtension(specifier) => { + let media_type = MediaType::from_specifier(specifier); + format!("add a '{}' extension", media_type.as_ts_extension()) + } + SloppyImportsResolution::Directory(specifier) => { + let file_name = specifier + .path() + .rsplit_once('/') + .map(|(_, file_name)| file_name) + .unwrap_or(specifier.path()); + format!("specify path to '{}' file in directory instead", file_name) + } + } + } +} + +/// The kind of resolution currently being done. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SloppyImportsResolutionMode { + /// Resolving for code that will be executed. + Execution, + /// Resolving for code that will be used for type information. + Types, +} + +impl SloppyImportsResolutionMode { + pub fn is_types(&self) -> bool { + *self == SloppyImportsResolutionMode::Types + } +} + +pub trait SloppyImportResolverFs { + fn stat_sync(&self, path: &Path) -> Option; + + fn is_file(&self, path: &Path) -> bool { + self.stat_sync(path) == Some(SloppyImportsFsEntry::File) + } +} + +#[derive(Debug)] +pub struct SloppyImportsResolver { + fs: Fs, +} + +impl SloppyImportsResolver { + pub fn new(fs: Fs) -> Self { + Self { fs } + } + + pub fn resolve( + &self, + specifier: &Url, + mode: SloppyImportsResolutionMode, + ) -> Option { + fn path_without_ext( + path: &Path, + media_type: MediaType, + ) -> Option> { + let old_path_str = path.to_string_lossy(); + match media_type { + MediaType::Unknown => Some(old_path_str), + _ => old_path_str + .strip_suffix(media_type.as_ts_extension()) + .map(|s| Cow::Owned(s.to_string())), + } + } + + fn media_types_to_paths( + path_no_ext: &str, + original_media_type: MediaType, + probe_media_type_types: Vec, + reason: SloppyImportsResolutionReason, + ) -> Vec<(PathBuf, SloppyImportsResolutionReason)> { + probe_media_type_types + .into_iter() + .filter(|media_type| *media_type != original_media_type) + .map(|media_type| { + ( + PathBuf::from(format!( + "{}{}", + path_no_ext, + media_type.as_ts_extension() + )), + reason, + ) + }) + .collect::>() + } + + if specifier.scheme() != "file" { + return None; + } + + let path = url_to_file_path(specifier).ok()?; + + #[derive(Clone, Copy)] + enum SloppyImportsResolutionReason { + JsToTs, + NoExtension, + Directory, + } + + let probe_paths: Vec<(PathBuf, SloppyImportsResolutionReason)> = + match self.fs.stat_sync(&path) { + Some(SloppyImportsFsEntry::File) => { + if mode.is_types() { + let media_type = MediaType::from_specifier(specifier); + // attempt to resolve the .d.ts file before the .js file + let probe_media_type_types = match media_type { + MediaType::JavaScript => { + vec![(MediaType::Dts), MediaType::JavaScript] + } + MediaType::Mjs => { + vec![MediaType::Dmts, MediaType::Dts, MediaType::Mjs] + } + MediaType::Cjs => { + vec![MediaType::Dcts, MediaType::Dts, MediaType::Cjs] + } + _ => return None, + }; + let path_no_ext = path_without_ext(&path, media_type)?; + media_types_to_paths( + &path_no_ext, + media_type, + probe_media_type_types, + SloppyImportsResolutionReason::JsToTs, + ) + } else { + return None; + } + } + entry @ None | entry @ Some(SloppyImportsFsEntry::Dir) => { + let media_type = MediaType::from_specifier(specifier); + let probe_media_type_types = match media_type { + MediaType::JavaScript => ( + if mode.is_types() { + vec![MediaType::TypeScript, MediaType::Tsx, MediaType::Dts] + } else { + vec![MediaType::TypeScript, MediaType::Tsx] + }, + SloppyImportsResolutionReason::JsToTs, + ), + MediaType::Jsx => { + (vec![MediaType::Tsx], SloppyImportsResolutionReason::JsToTs) + } + MediaType::Mjs => ( + if mode.is_types() { + vec![MediaType::Mts, MediaType::Dmts, MediaType::Dts] + } else { + vec![MediaType::Mts] + }, + SloppyImportsResolutionReason::JsToTs, + ), + MediaType::Cjs => ( + if mode.is_types() { + vec![MediaType::Cts, MediaType::Dcts, MediaType::Dts] + } else { + vec![MediaType::Cts] + }, + SloppyImportsResolutionReason::JsToTs, + ), + MediaType::TypeScript + | MediaType::Mts + | MediaType::Cts + | MediaType::Dts + | MediaType::Dmts + | MediaType::Dcts + | MediaType::Tsx + | MediaType::Json + | MediaType::Wasm + | MediaType::TsBuildInfo + | MediaType::SourceMap => { + return None; + } + MediaType::Unknown => ( + if mode.is_types() { + vec![ + MediaType::TypeScript, + MediaType::Tsx, + MediaType::Mts, + MediaType::Dts, + MediaType::Dmts, + MediaType::Dcts, + MediaType::JavaScript, + MediaType::Jsx, + MediaType::Mjs, + ] + } else { + vec![ + MediaType::TypeScript, + MediaType::JavaScript, + MediaType::Tsx, + MediaType::Jsx, + MediaType::Mts, + MediaType::Mjs, + ] + }, + SloppyImportsResolutionReason::NoExtension, + ), + }; + let mut probe_paths = match path_without_ext(&path, media_type) { + Some(path_no_ext) => media_types_to_paths( + &path_no_ext, + media_type, + probe_media_type_types.0, + probe_media_type_types.1, + ), + None => vec![], + }; + + if matches!(entry, Some(SloppyImportsFsEntry::Dir)) { + // try to resolve at the index file + if mode.is_types() { + probe_paths.push(( + path.join("index.ts"), + SloppyImportsResolutionReason::Directory, + )); + + probe_paths.push(( + path.join("index.mts"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.d.ts"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.d.mts"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.js"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.mjs"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.tsx"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.jsx"), + SloppyImportsResolutionReason::Directory, + )); + } else { + probe_paths.push(( + path.join("index.ts"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.mts"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.tsx"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.js"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.mjs"), + SloppyImportsResolutionReason::Directory, + )); + probe_paths.push(( + path.join("index.jsx"), + SloppyImportsResolutionReason::Directory, + )); + } + } + if probe_paths.is_empty() { + return None; + } + probe_paths + } + }; + + for (probe_path, reason) in probe_paths { + if self.fs.is_file(&probe_path) { + if let Ok(specifier) = url_from_file_path(&probe_path) { + match reason { + SloppyImportsResolutionReason::JsToTs => { + return Some(SloppyImportsResolution::JsToTs(specifier)); + } + SloppyImportsResolutionReason::NoExtension => { + return Some(SloppyImportsResolution::NoExtension(specifier)); + } + SloppyImportsResolutionReason::Directory => { + return Some(SloppyImportsResolution::Directory(specifier)); + } + } + } + } + } + + None + } +} + +#[cfg(test)] +mod test { + use test_util::TestContext; + + use super::*; + + #[test] + fn test_unstable_sloppy_imports() { + fn resolve(specifier: &Url) -> Option { + resolve_with_mode(specifier, SloppyImportsResolutionMode::Execution) + } + + fn resolve_types(specifier: &Url) -> Option { + resolve_with_mode(specifier, SloppyImportsResolutionMode::Types) + } + + fn resolve_with_mode( + specifier: &Url, + mode: SloppyImportsResolutionMode, + ) -> Option { + struct RealSloppyImportsResolverFs; + impl SloppyImportResolverFs for RealSloppyImportsResolverFs { + fn stat_sync(&self, path: &Path) -> Option { + #[allow(clippy::disallowed_methods)] + let stat = std::fs::metadata(path).ok()?; + if stat.is_dir() { + Some(SloppyImportsFsEntry::Dir) + } else if stat.is_file() { + Some(SloppyImportsFsEntry::File) + } else { + None + } + } + } + + SloppyImportsResolver::new(RealSloppyImportsResolverFs) + .resolve(specifier, mode) + } + + let context = TestContext::default(); + let temp_dir = context.temp_dir().path(); + + // scenarios like resolving ./example.js to ./example.ts + for (ext_from, ext_to) in [("js", "ts"), ("js", "tsx"), ("mjs", "mts")] { + let ts_file = temp_dir.join(format!("file.{}", ext_to)); + ts_file.write(""); + assert_eq!(resolve(&ts_file.url_file()), None); + assert_eq!( + resolve( + &temp_dir + .url_dir() + .join(&format!("file.{}", ext_from)) + .unwrap() + ), + Some(SloppyImportsResolution::JsToTs(ts_file.url_file())), + ); + ts_file.remove_file(); + } + + // no extension scenarios + for ext in ["js", "ts", "js", "tsx", "jsx", "mjs", "mts"] { + let file = temp_dir.join(format!("file.{}", ext)); + file.write(""); + assert_eq!( + resolve( + &temp_dir + .url_dir() + .join("file") // no ext + .unwrap() + ), + Some(SloppyImportsResolution::NoExtension(file.url_file())) + ); + file.remove_file(); + } + + // .ts and .js exists, .js specified (goes to specified) + { + let ts_file = temp_dir.join("file.ts"); + ts_file.write(""); + let js_file = temp_dir.join("file.js"); + js_file.write(""); + assert_eq!(resolve(&js_file.url_file()), None); + } + + // only js exists, .js specified + { + let js_only_file = temp_dir.join("js_only.js"); + js_only_file.write(""); + assert_eq!(resolve(&js_only_file.url_file()), None); + assert_eq!(resolve_types(&js_only_file.url_file()), None); + } + + // resolving a directory to an index file + { + let routes_dir = temp_dir.join("routes"); + routes_dir.create_dir_all(); + let index_file = routes_dir.join("index.ts"); + index_file.write(""); + assert_eq!( + resolve(&routes_dir.url_file()), + Some(SloppyImportsResolution::Directory(index_file.url_file())), + ); + } + + // both a directory and a file with specifier is present + { + let api_dir = temp_dir.join("api"); + api_dir.create_dir_all(); + let bar_file = api_dir.join("bar.ts"); + bar_file.write(""); + let api_file = temp_dir.join("api.ts"); + api_file.write(""); + assert_eq!( + resolve(&api_dir.url_file()), + Some(SloppyImportsResolution::NoExtension(api_file.url_file())), + ); + } + } + + #[test] + fn test_sloppy_import_resolution_suggestion_message() { + // directory + assert_eq!( + SloppyImportsResolution::Directory( + Url::parse("file:///dir/index.js").unwrap() + ) + .as_suggestion_message(), + "Maybe specify path to 'index.js' file in directory instead" + ); + // no ext + assert_eq!( + SloppyImportsResolution::NoExtension( + Url::parse("file:///dir/index.mjs").unwrap() + ) + .as_suggestion_message(), + "Maybe add a '.mjs' extension" + ); + // js to ts + assert_eq!( + SloppyImportsResolution::JsToTs( + Url::parse("file:///dir/index.mts").unwrap() + ) + .as_suggestion_message(), + "Maybe change the extension to '.mts'" + ); + } +} diff --git a/ext/node_resolver/Cargo.toml b/resolvers/node/Cargo.toml similarity index 93% rename from ext/node_resolver/Cargo.toml rename to resolvers/node/Cargo.toml index f472b5fe07..9638899209 100644 --- a/ext/node_resolver/Cargo.toml +++ b/resolvers/node/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "node_resolver" -version = "0.3.0" +version = "0.13.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -21,6 +21,7 @@ anyhow.workspace = true async-trait.workspace = true deno_media_type.workspace = true deno_package_json.workspace = true +deno_path_util.workspace = true futures.workspace = true lazy-regex.workspace = true once_cell.workspace = true diff --git a/ext/node_resolver/README.md b/resolvers/node/README.md similarity index 100% rename from ext/node_resolver/README.md rename to resolvers/node/README.md diff --git a/ext/node_resolver/analyze.rs b/resolvers/node/analyze.rs similarity index 88% rename from ext/node_resolver/analyze.rs rename to resolvers/node/analyze.rs index 8d6a734241..009296006a 100644 --- a/ext/node_resolver/analyze.rs +++ b/resolvers/node/analyze.rs @@ -1,10 +1,13 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; use std::collections::BTreeSet; use std::collections::HashSet; use std::path::Path; use std::path::PathBuf; +use deno_path_util::url_from_file_path; +use deno_path_util::url_to_file_path; use futures::future::LocalBoxFuture; use futures::stream::FuturesUnordered; use futures::FutureExt; @@ -17,7 +20,6 @@ use url::Url; use crate::env::NodeResolverEnv; use crate::package_json::load_pkg_json; -use crate::path::to_file_specifier; use crate::resolution::NodeResolverRc; use crate::NodeModuleKind; use crate::NodeResolutionMode; @@ -134,8 +136,7 @@ impl source.push(format!( "const mod = require(\"{}\");", - entry_specifier - .to_file_path() + url_to_file_path(entry_specifier) .unwrap() .to_str() .unwrap() @@ -195,11 +196,12 @@ impl &referrer, // FIXME(bartlomieju): check if these conditions are okay, probably // should be `deno-require`, because `deno` is already used in `esm_resolver.rs` - &["deno", "require", "default"], + &["deno", "node", "require", "default"], NodeResolutionMode::Execution, ); let reexport_specifier = match result { - Ok(specifier) => specifier, + Ok(Some(specifier)) => specifier, + Ok(None) => continue, Err(err) => { errors.push(err); continue; @@ -290,17 +292,18 @@ impl referrer: &Url, conditions: &[&str], mode: NodeResolutionMode, - ) -> Result { + ) -> Result, AnyError> { if specifier.starts_with('/') { todo!(); } - let referrer_path = referrer.to_file_path().unwrap(); + let referrer_path = url_to_file_path(referrer).unwrap(); if specifier.starts_with("./") || specifier.starts_with("../") { if let Some(parent) = referrer_path.parent() { return self .file_extension_probe(parent.join(specifier), &referrer_path) - .map(|p| to_file_specifier(&p)); + .and_then(|p| url_from_file_path(&p).map_err(AnyError::from)) + .map(Some); } else { todo!(); } @@ -310,28 +313,41 @@ impl let (package_specifier, package_subpath) = parse_specifier(specifier).unwrap(); - let module_dir = self.npm_resolver.resolve_package_folder_from_package( - package_specifier.as_str(), - referrer, - )?; + let module_dir = match self + .npm_resolver + .resolve_package_folder_from_package(package_specifier.as_str(), referrer) + { + Err(err) + if matches!( + err.as_kind(), + crate::errors::PackageFolderResolveErrorKind::PackageNotFound(..) + ) => + { + return Ok(None); + } + other => other, + }?; let package_json_path = module_dir.join("package.json"); let maybe_package_json = load_pkg_json(self.env.pkg_json_fs(), &package_json_path)?; if let Some(package_json) = maybe_package_json { if let Some(exports) = &package_json.exports { - return self - .node_resolver - .package_exports_resolve( - &package_json_path, - &package_subpath, - exports, - Some(referrer), - NodeModuleKind::Esm, - conditions, - mode, - ) - .map_err(AnyError::from); + return Some( + self + .node_resolver + .package_exports_resolve( + &package_json_path, + &package_subpath, + exports, + Some(referrer), + NodeModuleKind::Esm, + conditions, + mode, + ) + .map_err(AnyError::from), + ) + .transpose(); } // old school @@ -344,19 +360,22 @@ impl load_pkg_json(self.env.pkg_json_fs(), &package_json_path)?; if let Some(package_json) = maybe_package_json { if let Some(main) = package_json.main(NodeModuleKind::Cjs) { - return Ok(to_file_specifier(&d.join(main).clean())); + return Ok(Some(url_from_file_path(&d.join(main).clean())?)); } } - return Ok(to_file_specifier(&d.join("index.js").clean())); + return Ok(Some(url_from_file_path(&d.join("index.js").clean())?)); } return self .file_extension_probe(d, &referrer_path) - .map(|p| to_file_specifier(&p)); + .and_then(|p| url_from_file_path(&p).map_err(AnyError::from)) + .map(Some); } else if let Some(main) = package_json.main(NodeModuleKind::Cjs) { - return Ok(to_file_specifier(&module_dir.join(main).clean())); + return Ok(Some(url_from_file_path(&module_dir.join(main).clean())?)); } else { - return Ok(to_file_specifier(&module_dir.join("index.js").clean())); + return Ok(Some(url_from_file_path( + &module_dir.join("index.js").clean(), + )?)); } } @@ -372,7 +391,7 @@ impl parent.join("node_modules").join(specifier) }; if let Ok(path) = self.file_extension_probe(path, &referrer_path) { - return Ok(to_file_specifier(&path)); + return Ok(Some(url_from_file_path(&path)?)); } last = parent; } @@ -583,9 +602,16 @@ fn not_found(path: &str, referrer: &Path) -> AnyError { std::io::Error::new(std::io::ErrorKind::NotFound, msg).into() } -fn escape_for_double_quote_string(text: &str) -> String { - text.replace('\\', "\\\\").replace('"', "\\\"") +fn escape_for_double_quote_string(text: &str) -> Cow { + // this should be rare, so doing a scan first before allocating is ok + if text.chars().any(|c| matches!(c, '"' | '\\')) { + // don't bother making this more complex for perf because it's rare + Cow::Owned(text.replace('\\', "\\\\").replace('"', "\\\"")) + } else { + Cow::Borrowed(text) + } } + #[cfg(test)] mod tests { use super::*; diff --git a/ext/node_resolver/clippy.toml b/resolvers/node/clippy.toml similarity index 94% rename from ext/node_resolver/clippy.toml rename to resolvers/node/clippy.toml index 86150781bb..90eaba3fae 100644 --- a/ext/node_resolver/clippy.toml +++ b/resolvers/node/clippy.toml @@ -42,6 +42,9 @@ disallowed-methods = [ { path = "std::fs::write", reason = "File system operations should be done using NodeResolverFs trait" }, { path = "std::path::Path::canonicalize", reason = "File system operations should be done using NodeResolverFs trait" }, { path = "std::path::Path::exists", reason = "File system operations should be done using NodeResolverFs trait" }, + { path = "url::Url::to_file_path", reason = "Use deno_path_util instead so it works in Wasm" }, + { path = "url::Url::from_file_path", reason = "Use deno_path_util instead so it works in Wasm" }, + { path = "url::Url::from_directory_path", reason = "Use deno_path_util instead so it works in Wasm" }, ] disallowed-types = [ { path = "std::sync::Arc", reason = "use crate::sync::MaybeArc instead" }, diff --git a/ext/node_resolver/env.rs b/resolvers/node/env.rs similarity index 100% rename from ext/node_resolver/env.rs rename to resolvers/node/env.rs diff --git a/ext/node_resolver/errors.rs b/resolvers/node/errors.rs similarity index 100% rename from ext/node_resolver/errors.rs rename to resolvers/node/errors.rs diff --git a/ext/node_resolver/lib.rs b/resolvers/node/lib.rs similarity index 94% rename from ext/node_resolver/lib.rs rename to resolvers/node/lib.rs index 1ab972ccfd..f03f770486 100644 --- a/ext/node_resolver/lib.rs +++ b/resolvers/node/lib.rs @@ -18,6 +18,7 @@ pub use npm::NpmResolverRc; pub use package_json::load_pkg_json; pub use package_json::PackageJsonThreadLocalCache; pub use path::PathClean; +pub use resolution::parse_npm_pkg_name; pub use resolution::NodeModuleKind; pub use resolution::NodeResolution; pub use resolution::NodeResolutionMode; diff --git a/ext/node_resolver/npm.rs b/resolvers/node/npm.rs similarity index 82% rename from ext/node_resolver/npm.rs rename to resolvers/node/npm.rs index 77df57c489..6b5f21db62 100644 --- a/ext/node_resolver/npm.rs +++ b/resolvers/node/npm.rs @@ -3,6 +3,8 @@ use std::path::Path; use std::path::PathBuf; +use deno_path_util::url_from_directory_path; +use deno_path_util::url_from_file_path; use url::Url; use crate::errors; @@ -24,7 +26,7 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync { fn in_npm_package(&self, specifier: &Url) -> bool; fn in_npm_package_at_dir_path(&self, path: &Path) -> bool { - let specifier = match Url::from_directory_path(path.to_path_buf().clean()) { + let specifier = match url_from_directory_path(&path.to_path_buf().clean()) { Ok(p) => p, Err(_) => return false, }; @@ -32,7 +34,7 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync { } fn in_npm_package_at_file_path(&self, path: &Path) -> bool { - let specifier = match Url::from_file_path(path.to_path_buf().clean()) { + let specifier = match url_from_file_path(&path.to_path_buf().clean()) { Ok(p) => p, Err(_) => return false, }; diff --git a/ext/node_resolver/package_json.rs b/resolvers/node/package_json.rs similarity index 100% rename from ext/node_resolver/package_json.rs rename to resolvers/node/package_json.rs diff --git a/resolvers/node/path.rs b/resolvers/node/path.rs new file mode 100644 index 0000000000..8c2d35fadf --- /dev/null +++ b/resolvers/node/path.rs @@ -0,0 +1,81 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::path::Component; +use std::path::Path; +use std::path::PathBuf; + +/// Extension to path_clean::PathClean +pub trait PathClean { + fn clean(&self) -> T; +} + +impl PathClean for PathBuf { + fn clean(&self) -> PathBuf { + fn is_clean_path(path: &Path) -> bool { + let path = path.to_string_lossy(); + let mut current_index = 0; + while let Some(index) = path[current_index..].find("\\.") { + let trailing_index = index + current_index + 2; + let mut trailing_chars = path[trailing_index..].chars(); + match trailing_chars.next() { + Some('.') => match trailing_chars.next() { + Some('/') | Some('\\') | None => { + return false; + } + _ => {} + }, + Some('/') | Some('\\') => { + return false; + } + _ => {} + } + current_index = trailing_index; + } + true + } + + let path = path_clean::PathClean::clean(self); + if cfg!(windows) && !is_clean_path(&path) { + // temporary workaround because path_clean::PathClean::clean is + // not good enough on windows + let mut components = Vec::new(); + + for component in path.components() { + match component { + Component::CurDir => { + // skip + } + Component::ParentDir => { + let maybe_last_component = components.pop(); + if !matches!(maybe_last_component, Some(Component::Normal(_))) { + panic!("Error normalizing: {}", path.display()); + } + } + Component::Normal(_) | Component::RootDir | Component::Prefix(_) => { + components.push(component); + } + } + } + components.into_iter().collect::() + } else { + path + } + } +} + +#[cfg(test)] +mod test { + #[cfg(windows)] + #[test] + fn test_path_clean() { + use super::*; + + run_test("C:\\test\\./file.txt", "C:\\test\\file.txt"); + run_test("C:\\test\\../other/file.txt", "C:\\other\\file.txt"); + run_test("C:\\test\\../other\\file.txt", "C:\\other\\file.txt"); + + fn run_test(input: &str, expected: &str) { + assert_eq!(PathBuf::from(input).clean(), PathBuf::from(expected)); + } + } +} diff --git a/ext/node_resolver/resolution.rs b/resolvers/node/resolution.rs similarity index 97% rename from ext/node_resolver/resolution.rs rename to resolvers/node/resolution.rs index ae791e312b..811583a5ee 100644 --- a/ext/node_resolver/resolution.rs +++ b/resolvers/node/resolution.rs @@ -8,6 +8,8 @@ use anyhow::bail; use anyhow::Error as AnyError; use deno_media_type::MediaType; use deno_package_json::PackageJsonRc; +use deno_path_util::strip_unc_prefix; +use deno_path_util::url_from_file_path; use serde_json::Map; use serde_json::Value; use url::Url; @@ -47,8 +49,6 @@ use crate::errors::TypesNotFoundErrorData; use crate::errors::UnsupportedDirImportError; use crate::errors::UnsupportedEsmUrlSchemeError; use crate::errors::UrlToNodeResolutionError; -use crate::path::strip_unc_prefix; -use crate::path::to_file_specifier; use crate::NpmResolverRc; use crate::PathClean; use deno_package_json::PackageJson; @@ -367,6 +367,7 @@ impl NodeResolver { pkg_json_path, }); }; + let name = name.split("/").last().unwrap(); vec![name.to_string()] } Some(Value::Object(o)) => { @@ -393,7 +394,7 @@ impl NodeResolver { message: err.to_string(), } })?; - let url = to_file_specifier(&package_folder.join(bin_entry)); + let url = url_from_file_path(&package_folder.join(bin_entry)).unwrap(); let resolve_response = self.url_to_node_resolution(url)?; // TODO(bartlomieju): skipped checking errors for commonJS resolution and @@ -484,12 +485,12 @@ impl NodeResolver { || lowercase_path.ends_with(".d.cts") || lowercase_path.ends_with(".d.mts") { - return Ok(to_file_specifier(path)); + return Ok(url_from_file_path(path).unwrap()); } if let Some(path) = probe_extensions(&self.env, path, &lowercase_path, referrer_kind) { - return Ok(to_file_specifier(&path)); + return Ok(url_from_file_path(&path).unwrap()); } if self.env.is_dir_sync(path) { let resolution_result = self.resolve_package_dir_subpath( @@ -513,15 +514,15 @@ impl NodeResolver { &index_path.to_string_lossy().to_lowercase(), referrer_kind, ) { - return Ok(to_file_specifier(&path)); + return Ok(url_from_file_path(&path).unwrap()); } } // allow resolving .css files for types resolution if lowercase_path.ends_with(".css") { - return Ok(to_file_specifier(path)); + return Ok(url_from_file_path(path).unwrap()); } Err(TypesNotFoundError(Box::new(TypesNotFoundErrorData { - code_specifier: to_file_specifier(path), + code_specifier: url_from_file_path(path).unwrap(), maybe_referrer: maybe_referrer.cloned(), }))) } @@ -672,7 +673,8 @@ impl NodeResolver { } else { format!("{target}{subpath}") }; - let package_json_url = to_file_specifier(package_json_path); + let package_json_url = + url_from_file_path(package_json_path).unwrap(); let result = match self.package_resolve( &export_target, &package_json_url, @@ -759,7 +761,7 @@ impl NodeResolver { ); } if subpath.is_empty() { - return Ok(to_file_specifier(&resolved_path)); + return Ok(url_from_file_path(&resolved_path).unwrap()); } if invalid_segment_re.is_match(subpath) { let request = if pattern { @@ -781,9 +783,11 @@ impl NodeResolver { let resolved_path_str = resolved_path.to_string_lossy(); let replaced = pattern_re .replace(&resolved_path_str, |_caps: ®ex::Captures| subpath); - return Ok(to_file_specifier(&PathBuf::from(replaced.to_string()))); + return Ok( + url_from_file_path(&PathBuf::from(replaced.to_string())).unwrap(), + ); } - Ok(to_file_specifier(&resolved_path.join(subpath).clean())) + Ok(url_from_file_path(&resolved_path.join(subpath).clean()).unwrap()) } #[allow(clippy::too_many_arguments)] @@ -870,7 +874,7 @@ impl NodeResolver { mode, )?; if mode.is_types() && url.scheme() == "file" { - let path = url.to_file_path().unwrap(); + let path = deno_path_util::url_to_file_path(&url).unwrap(); return Ok(Some(self.path_to_declaration_url( &path, maybe_referrer, @@ -1306,7 +1310,7 @@ impl NodeResolver { if mode.is_types() { Ok(self.path_to_declaration_url(&file_path, referrer, referrer_kind)?) } else { - Ok(to_file_specifier(&file_path)) + Ok(url_from_file_path(&file_path).unwrap()) } } @@ -1337,7 +1341,7 @@ impl NodeResolver { &self, url: &Url, ) -> Result, ClosestPkgJsonError> { - let Ok(file_path) = url.to_file_path() else { + let Ok(file_path) = deno_path_util::url_to_file_path(url) else { return Ok(None); }; self.get_closest_package_json_from_path(&file_path) @@ -1432,7 +1436,7 @@ impl NodeResolver { if let Some(main) = maybe_main { let guess = package_json.path.parent().unwrap().join(main).clean(); if self.env.is_file_sync(&guess) { - return Ok(to_file_specifier(&guess)); + return Ok(url_from_file_path(&guess).unwrap()); } // todo(dsherret): investigate exactly how node and typescript handles this @@ -1462,7 +1466,7 @@ impl NodeResolver { .clean(); if self.env.is_file_sync(&guess) { // TODO(bartlomieju): emitLegacyIndexDeprecation() - return Ok(to_file_specifier(&guess)); + return Ok(url_from_file_path(&guess).unwrap()); } } } @@ -1495,14 +1499,15 @@ impl NodeResolver { let guess = directory.join(index_file_name).clean(); if self.env.is_file_sync(&guess) { // TODO(bartlomieju): emitLegacyIndexDeprecation() - return Ok(to_file_specifier(&guess)); + return Ok(url_from_file_path(&guess).unwrap()); } } if mode.is_types() { Err( TypesNotFoundError(Box::new(TypesNotFoundErrorData { - code_specifier: to_file_specifier(&directory.join("index.js")), + code_specifier: url_from_file_path(&directory.join("index.js")) + .unwrap(), maybe_referrer: maybe_referrer.cloned(), })) .into(), @@ -1510,7 +1515,7 @@ impl NodeResolver { } else { Err( ModuleNotFoundError { - specifier: to_file_specifier(&directory.join("index.js")), + specifier: url_from_file_path(&directory.join("index.js")).unwrap(), typ: "module", maybe_referrer: maybe_referrer.cloned(), } @@ -1610,9 +1615,7 @@ fn resolve_bin_entry_value<'a>( } fn to_file_path(url: &Url) -> PathBuf { - url - .to_file_path() - .unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {url}")) + deno_path_util::url_to_file_path(url).unwrap() } fn to_file_path_string(url: &Url) -> String { @@ -1691,7 +1694,7 @@ fn with_known_extension(path: &Path, ext: &str) -> PathBuf { } fn to_specifier_display_string(url: &Url) -> String { - if let Ok(path) = url.to_file_path() { + if let Ok(path) = deno_path_util::url_to_file_path(url) { path.display().to_string() } else { url.to_string() diff --git a/ext/node_resolver/sync.rs b/resolvers/node/sync.rs similarity index 100% rename from ext/node_resolver/sync.rs rename to resolvers/node/sync.rs diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8c1d07a1e4..703bd5a432 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_runtime" -version = "0.173.0" +version = "0.183.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -88,6 +88,7 @@ deno_kv.workspace = true deno_napi.workspace = true deno_net.workspace = true deno_node.workspace = true +deno_path_util.workspace = true deno_permissions.workspace = true deno_terminal.workspace = true deno_tls.workspace = true @@ -99,6 +100,7 @@ deno_websocket.workspace = true deno_webstorage.workspace = true node_resolver = { workspace = true, features = ["sync"] } +color-print.workspace = true dlopen2.workspace = true encoding_rs.workspace = true fastwebsockets.workspace = true @@ -115,9 +117,12 @@ once_cell.workspace = true percent-encoding.workspace = true regex.workspace = true rustyline = { workspace = true, features = ["custom-bindings"] } +same-file = "1.0.6" serde.workspace = true signal-hook = "0.3.17" signal-hook-registry = "1.4.0" +tempfile.workspace = true +thiserror.workspace = true tokio.workspace = true tokio-metrics.workspace = true twox-hash.workspace = true diff --git a/runtime/errors.rs b/runtime/errors.rs index 694402773e..07bf694dc1 100644 --- a/runtime/errors.rs +++ b/runtime/errors.rs @@ -9,10 +9,55 @@ //! Diagnostics are compile-time type errors, whereas JsErrors are runtime //! exceptions. +use crate::ops::fs_events::FsEventsError; +use crate::ops::http::HttpStartError; +use crate::ops::os::OsError; +use crate::ops::process::ProcessError; +use crate::ops::signal::SignalError; +use crate::ops::tty::TtyError; +use crate::ops::web_worker::SyncFetchError; +use crate::ops::worker_host::CreateWorkerError; +use deno_broadcast_channel::BroadcastChannelError; +use deno_cache::CacheError; +use deno_canvas::CanvasError; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url; use deno_core::ModuleResolutionError; +use deno_cron::CronError; +use deno_crypto::DecryptError; +use deno_crypto::EncryptError; +use deno_crypto::ExportKeyError; +use deno_crypto::GenerateKeyError; +use deno_crypto::ImportKeyError; +use deno_fetch::FetchError; +use deno_fetch::HttpClientCreateError; +use deno_ffi::CallError; +use deno_ffi::CallbackError; +use deno_ffi::DlfcnError; +use deno_ffi::IRError; +use deno_ffi::ReprError; +use deno_ffi::StaticError; +use deno_fs::FsOpsError; +use deno_http::HttpError; +use deno_http::HttpNextError; +use deno_http::WebSocketUpgradeError; +use deno_io::fs::FsError; +use deno_kv::KvCheckError; +use deno_kv::KvError; +use deno_kv::KvMutationError; +use deno_napi::NApiError; +use deno_net::ops::NetError; +use deno_tls::TlsError; +use deno_web::BlobError; +use deno_web::CompressionError; +use deno_web::MessagePortError; +use deno_web::StreamResourceError; +use deno_web::WebError; +use deno_websocket::HandshakeError; +use deno_websocket::WebsocketError; +use deno_webstorage::WebStorageError; +use rustyline::error::ReadlineError; use std::env; use std::error::Error; use std::io; @@ -153,12 +198,1136 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str { } } +fn get_webgpu_error_class(e: &deno_webgpu::InitError) -> &'static str { + match e { + deno_webgpu::InitError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + deno_webgpu::InitError::InvalidAdapter(_) => "Error", + deno_webgpu::InitError::RequestDevice(_) => "DOMExceptionOperationError", + deno_webgpu::InitError::InvalidDevice(_) => "Error", + } +} + +fn get_webgpu_buffer_error_class( + e: &deno_webgpu::buffer::BufferError, +) -> &'static str { + match e { + deno_webgpu::buffer::BufferError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + deno_webgpu::buffer::BufferError::InvalidUsage => "TypeError", + deno_webgpu::buffer::BufferError::Access(_) => "DOMExceptionOperationError", + } +} + +fn get_webgpu_bundle_error_class( + e: &deno_webgpu::bundle::BundleError, +) -> &'static str { + match e { + deno_webgpu::bundle::BundleError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + deno_webgpu::bundle::BundleError::InvalidSize => "TypeError", + } +} + +fn get_webgpu_byow_error_class( + e: &deno_webgpu::byow::ByowError, +) -> &'static str { + match e { + deno_webgpu::byow::ByowError::WebGPUNotInitiated => "TypeError", + deno_webgpu::byow::ByowError::InvalidParameters => "TypeError", + deno_webgpu::byow::ByowError::CreateSurface(_) => "Error", + deno_webgpu::byow::ByowError::InvalidSystem => "TypeError", + #[cfg(any( + target_os = "windows", + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd" + ))] + deno_webgpu::byow::ByowError::NullWindow => "TypeError", + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "openbsd" + ))] + deno_webgpu::byow::ByowError::NullDisplay => "TypeError", + #[cfg(target_os = "macos")] + deno_webgpu::byow::ByowError::NSViewDisplay => "TypeError", + } +} + +fn get_webgpu_render_pass_error_class( + e: &deno_webgpu::render_pass::RenderPassError, +) -> &'static str { + match e { + deno_webgpu::render_pass::RenderPassError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + deno_webgpu::render_pass::RenderPassError::InvalidSize => "TypeError", + } +} + +fn get_webgpu_surface_error_class( + e: &deno_webgpu::surface::SurfaceError, +) -> &'static str { + match e { + deno_webgpu::surface::SurfaceError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + deno_webgpu::surface::SurfaceError::Surface(_) => "Error", + deno_webgpu::surface::SurfaceError::InvalidStatus => "Error", + } +} + +fn get_crypto_decrypt_error_class(e: &DecryptError) -> &'static str { + match e { + DecryptError::General(e) => get_crypto_shared_error_class(e), + DecryptError::Pkcs1(_) => "Error", + DecryptError::Failed => "DOMExceptionOperationError", + DecryptError::InvalidLength => "TypeError", + DecryptError::InvalidCounterLength => "TypeError", + DecryptError::InvalidTagLength => "TypeError", + DecryptError::InvalidKeyOrIv => "DOMExceptionOperationError", + DecryptError::TooMuchData => "DOMExceptionOperationError", + DecryptError::InvalidIvLength => "TypeError", + DecryptError::Rsa(_) => "DOMExceptionOperationError", + } +} + +fn get_crypto_encrypt_error_class(e: &EncryptError) -> &'static str { + match e { + EncryptError::General(e) => get_crypto_shared_error_class(e), + EncryptError::InvalidKeyOrIv => "DOMExceptionOperationError", + EncryptError::Failed => "DOMExceptionOperationError", + EncryptError::InvalidLength => "TypeError", + EncryptError::InvalidIvLength => "TypeError", + EncryptError::InvalidCounterLength => "TypeError", + EncryptError::TooMuchData => "DOMExceptionOperationError", + } +} + +fn get_crypto_shared_error_class(e: &deno_crypto::SharedError) -> &'static str { + match e { + deno_crypto::SharedError::ExpectedValidPrivateKey => "TypeError", + deno_crypto::SharedError::ExpectedValidPublicKey => "TypeError", + deno_crypto::SharedError::ExpectedValidPrivateECKey => "TypeError", + deno_crypto::SharedError::ExpectedValidPublicECKey => "TypeError", + deno_crypto::SharedError::ExpectedPrivateKey => "TypeError", + deno_crypto::SharedError::ExpectedPublicKey => "TypeError", + deno_crypto::SharedError::ExpectedSecretKey => "TypeError", + deno_crypto::SharedError::FailedDecodePrivateKey => { + "DOMExceptionOperationError" + } + deno_crypto::SharedError::FailedDecodePublicKey => { + "DOMExceptionOperationError" + } + deno_crypto::SharedError::UnsupportedFormat => { + "DOMExceptionNotSupportedError" + } + } +} + +fn get_crypto_ed25519_error_class( + e: &deno_crypto::Ed25519Error, +) -> &'static str { + match e { + deno_crypto::Ed25519Error::FailedExport => "DOMExceptionOperationError", + deno_crypto::Ed25519Error::Der(_) => "Error", + deno_crypto::Ed25519Error::KeyRejected(_) => "Error", + } +} + +fn get_crypto_export_key_error_class(e: &ExportKeyError) -> &'static str { + match e { + ExportKeyError::General(e) => get_crypto_shared_error_class(e), + ExportKeyError::Der(_) => "Error", + ExportKeyError::UnsupportedNamedCurve => "DOMExceptionNotSupportedError", + } +} + +fn get_crypto_generate_key_error_class(e: &GenerateKeyError) -> &'static str { + match e { + GenerateKeyError::General(e) => get_crypto_shared_error_class(e), + GenerateKeyError::BadPublicExponent => "DOMExceptionOperationError", + GenerateKeyError::InvalidHMACKeyLength => "DOMExceptionOperationError", + GenerateKeyError::FailedRSAKeySerialization => "DOMExceptionOperationError", + GenerateKeyError::InvalidAESKeyLength => "DOMExceptionOperationError", + GenerateKeyError::FailedRSAKeyGeneration => "DOMExceptionOperationError", + GenerateKeyError::FailedECKeyGeneration => "DOMExceptionOperationError", + GenerateKeyError::FailedKeyGeneration => "DOMExceptionOperationError", + } +} + +fn get_crypto_import_key_error_class(e: &ImportKeyError) -> &'static str { + match e { + ImportKeyError::General(e) => get_crypto_shared_error_class(e), + ImportKeyError::InvalidModulus => "DOMExceptionDataError", + ImportKeyError::InvalidPublicExponent => "DOMExceptionDataError", + ImportKeyError::InvalidPrivateExponent => "DOMExceptionDataError", + ImportKeyError::InvalidFirstPrimeFactor => "DOMExceptionDataError", + ImportKeyError::InvalidSecondPrimeFactor => "DOMExceptionDataError", + ImportKeyError::InvalidFirstCRTExponent => "DOMExceptionDataError", + ImportKeyError::InvalidSecondCRTExponent => "DOMExceptionDataError", + ImportKeyError::InvalidCRTCoefficient => "DOMExceptionDataError", + ImportKeyError::InvalidB64Coordinate => "DOMExceptionDataError", + ImportKeyError::InvalidRSAPublicKey => "DOMExceptionDataError", + ImportKeyError::InvalidRSAPrivateKey => "DOMExceptionDataError", + ImportKeyError::UnsupportedAlgorithm => "DOMExceptionDataError", + ImportKeyError::PublicKeyTooLong => "DOMExceptionDataError", + ImportKeyError::PrivateKeyTooLong => "DOMExceptionDataError", + ImportKeyError::InvalidP256ECPoint => "DOMExceptionDataError", + ImportKeyError::InvalidP384ECPoint => "DOMExceptionDataError", + ImportKeyError::InvalidP521ECPoint => "DOMExceptionDataError", + ImportKeyError::UnsupportedNamedCurve => "DOMExceptionDataError", + ImportKeyError::CurveMismatch => "DOMExceptionDataError", + ImportKeyError::InvalidKeyData => "DOMExceptionDataError", + ImportKeyError::InvalidJWKPrivateKey => "DOMExceptionDataError", + ImportKeyError::EllipticCurve(_) => "DOMExceptionDataError", + ImportKeyError::ExpectedValidPkcs8Data => "DOMExceptionDataError", + ImportKeyError::MalformedParameters => "DOMExceptionDataError", + ImportKeyError::Spki(_) => "DOMExceptionDataError", + ImportKeyError::InvalidP256ECSPKIData => "DOMExceptionDataError", + ImportKeyError::InvalidP384ECSPKIData => "DOMExceptionDataError", + ImportKeyError::InvalidP521ECSPKIData => "DOMExceptionDataError", + ImportKeyError::Der(_) => "DOMExceptionDataError", + } +} + +fn get_crypto_x448_error_class(e: &deno_crypto::X448Error) -> &'static str { + match e { + deno_crypto::X448Error::FailedExport => "DOMExceptionOperationError", + deno_crypto::X448Error::Der(_) => "Error", + } +} + +fn get_crypto_x25519_error_class(e: &deno_crypto::X25519Error) -> &'static str { + match e { + deno_crypto::X25519Error::FailedExport => "DOMExceptionOperationError", + deno_crypto::X25519Error::Der(_) => "Error", + } +} + +fn get_crypto_error_class(e: &deno_crypto::Error) -> &'static str { + match e { + deno_crypto::Error::Der(_) => "Error", + deno_crypto::Error::JoinError(_) => "Error", + deno_crypto::Error::MissingArgumentHash => "TypeError", + deno_crypto::Error::MissingArgumentSaltLength => "TypeError", + deno_crypto::Error::Other(e) => get_error_class_name(e).unwrap_or("Error"), + deno_crypto::Error::UnsupportedAlgorithm => "TypeError", + deno_crypto::Error::KeyRejected(_) => "Error", + deno_crypto::Error::RSA(_) => "Error", + deno_crypto::Error::Pkcs1(_) => "Error", + deno_crypto::Error::Unspecified(_) => "Error", + deno_crypto::Error::InvalidKeyFormat => "TypeError", + deno_crypto::Error::MissingArgumentPublicKey => "TypeError", + deno_crypto::Error::P256Ecdsa(_) => "Error", + deno_crypto::Error::DecodePrivateKey => "TypeError", + deno_crypto::Error::MissingArgumentNamedCurve => "TypeError", + deno_crypto::Error::MissingArgumentInfo => "TypeError", + deno_crypto::Error::HKDFLengthTooLarge => "DOMExceptionOperationError", + deno_crypto::Error::General(e) => get_crypto_shared_error_class(e), + deno_crypto::Error::Base64Decode(_) => "Error", + deno_crypto::Error::DataInvalidSize => "TypeError", + deno_crypto::Error::InvalidKeyLength => "TypeError", + deno_crypto::Error::EncryptionError => "DOMExceptionOperationError", + deno_crypto::Error::DecryptionError => "DOMExceptionOperationError", + deno_crypto::Error::ArrayBufferViewLengthExceeded(_) => { + "DOMExceptionQuotaExceededError" + } + } +} + +fn get_napi_error_class(e: &NApiError) -> &'static str { + match e { + NApiError::InvalidPath + | NApiError::LibLoading(_) + | NApiError::ModuleNotFound(_) => "TypeError", + NApiError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_web_error_class(e: &WebError) -> &'static str { + match e { + WebError::Base64Decode => "DOMExceptionInvalidCharacterError", + WebError::InvalidEncodingLabel(_) => "RangeError", + WebError::BufferTooLong => "TypeError", + WebError::ValueTooLarge => "RangeError", + WebError::BufferTooSmall => "RangeError", + WebError::DataInvalid => "TypeError", + WebError::DataError(_) => "Error", + } +} + +fn get_web_compression_error_class(e: &CompressionError) -> &'static str { + match e { + CompressionError::UnsupportedFormat => "TypeError", + CompressionError::ResourceClosed => "TypeError", + CompressionError::IoTypeError(_) => "TypeError", + CompressionError::Io(e) => get_io_error_class(e), + } +} + +fn get_web_message_port_error_class(e: &MessagePortError) -> &'static str { + match e { + MessagePortError::InvalidTransfer => "TypeError", + MessagePortError::NotReady => "TypeError", + MessagePortError::TransferSelf => "TypeError", + MessagePortError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + MessagePortError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_web_stream_resource_error_class( + e: &StreamResourceError, +) -> &'static str { + match e { + StreamResourceError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + StreamResourceError::Js(_) => "TypeError", + } +} + +fn get_web_blob_error_class(e: &BlobError) -> &'static str { + match e { + BlobError::BlobPartNotFound => "TypeError", + BlobError::SizeLargerThanBlobPart => "TypeError", + BlobError::BlobURLsNotSupported => "TypeError", + BlobError::Url(_) => "Error", + } +} + +fn get_ffi_repr_error_class(e: &ReprError) -> &'static str { + match e { + ReprError::InvalidOffset => "TypeError", + ReprError::InvalidArrayBuffer => "TypeError", + ReprError::DestinationLengthTooShort => "RangeError", + ReprError::InvalidCString => "TypeError", + ReprError::CStringTooLong => "TypeError", + ReprError::InvalidBool => "TypeError", + ReprError::InvalidU8 => "TypeError", + ReprError::InvalidI8 => "TypeError", + ReprError::InvalidU16 => "TypeError", + ReprError::InvalidI16 => "TypeError", + ReprError::InvalidU32 => "TypeError", + ReprError::InvalidI32 => "TypeError", + ReprError::InvalidU64 => "TypeError", + ReprError::InvalidI64 => "TypeError", + ReprError::InvalidF32 => "TypeError", + ReprError::InvalidF64 => "TypeError", + ReprError::InvalidPointer => "TypeError", + ReprError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_ffi_dlfcn_error_class(e: &DlfcnError) -> &'static str { + match e { + DlfcnError::RegisterSymbol { .. } => "Error", + DlfcnError::Dlopen(_) => "Error", + DlfcnError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + DlfcnError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_ffi_static_error_class(e: &StaticError) -> &'static str { + match e { + StaticError::Dlfcn(e) => get_ffi_dlfcn_error_class(e), + StaticError::InvalidTypeVoid => "TypeError", + StaticError::InvalidTypeStruct => "TypeError", + StaticError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_ffi_callback_error_class(e: &CallbackError) -> &'static str { + match e { + CallbackError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + CallbackError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + CallbackError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_ffi_call_error_class(e: &CallError) -> &'static str { + match e { + CallError::IR(_) => "TypeError", + CallError::NonblockingCallFailure(_) => "Error", + CallError::InvalidSymbol(_) => "TypeError", + CallError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + CallError::Callback(e) => get_ffi_callback_error_class(e), + } +} + +fn get_webstorage_class_name(e: &WebStorageError) -> &'static str { + match e { + WebStorageError::ContextNotSupported => "DOMExceptionNotSupportedError", + WebStorageError::Sqlite(_) => todo!(), + WebStorageError::Io(e) => get_io_error_class(e), + WebStorageError::StorageExceeded => "DOMExceptionQuotaExceededError", + } +} + +fn get_tls_error_class(e: &TlsError) -> &'static str { + match e { + TlsError::Rustls(_) => "Error", + TlsError::UnableAddPemFileToCert(e) => get_io_error_class(e), + TlsError::CertInvalid + | TlsError::CertsNotFound + | TlsError::KeysNotFound + | TlsError::KeyDecode => "InvalidData", + } +} + +pub fn get_cron_error_class(e: &CronError) -> &'static str { + match e { + CronError::Resource(e) => { + deno_core::error::get_custom_error_class(e).unwrap_or("Error") + } + CronError::NameExceeded(_) => "TypeError", + CronError::NameInvalid => "TypeError", + CronError::AlreadyExists => "TypeError", + CronError::TooManyCrons => "TypeError", + CronError::InvalidCron => "TypeError", + CronError::InvalidBackoff => "TypeError", + CronError::AcquireError(_) => "Error", + CronError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_canvas_error(e: &CanvasError) -> &'static str { + match e { + CanvasError::UnsupportedColorType(_) => "TypeError", + CanvasError::Image(_) => "Error", + } +} + +pub fn get_cache_error(error: &CacheError) -> &'static str { + match error { + CacheError::Sqlite(_) => "Error", + CacheError::JoinError(_) => "Error", + CacheError::Resource(err) => { + deno_core::error::get_custom_error_class(err).unwrap_or("Error") + } + CacheError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + CacheError::Io(err) => get_io_error_class(err), + } +} + +fn get_broadcast_channel_error(error: &BroadcastChannelError) -> &'static str { + match error { + BroadcastChannelError::Resource(err) => { + deno_core::error::get_custom_error_class(err).unwrap() + } + BroadcastChannelError::MPSCSendError(_) => "Error", + BroadcastChannelError::BroadcastSendError(_) => "Error", + BroadcastChannelError::Other(err) => { + get_error_class_name(err).unwrap_or("Error") + } + } +} + +fn get_fetch_error(error: &FetchError) -> &'static str { + match error { + FetchError::Resource(e) | FetchError::Permission(e) => { + get_error_class_name(e).unwrap_or("Error") + } + FetchError::NetworkError => "TypeError", + FetchError::FsNotGet(_) => "TypeError", + FetchError::InvalidUrl(_) => "TypeError", + FetchError::InvalidHeaderName(_) => "TypeError", + FetchError::InvalidHeaderValue(_) => "TypeError", + FetchError::DataUrl(_) => "TypeError", + FetchError::Base64(_) => "TypeError", + FetchError::BlobNotFound => "TypeError", + FetchError::SchemeNotSupported(_) => "TypeError", + FetchError::RequestCanceled => "TypeError", + FetchError::Http(_) => "Error", + FetchError::ClientCreate(e) => get_http_client_create_error(e), + FetchError::Url(e) => get_url_parse_error_class(e), + FetchError::Method(_) => "TypeError", + FetchError::ClientSend(_) => "TypeError", + FetchError::RequestBuilderHook(_) => "TypeError", + FetchError::Io(e) => get_io_error_class(e), + FetchError::Hyper(e) => get_hyper_error_class(e), + } +} + +fn get_http_client_create_error(error: &HttpClientCreateError) -> &'static str { + match error { + HttpClientCreateError::Tls(_) => "TypeError", + HttpClientCreateError::InvalidUserAgent(_) => "TypeError", + HttpClientCreateError::InvalidProxyUrl => "TypeError", + HttpClientCreateError::HttpVersionSelectionInvalid => "TypeError", + HttpClientCreateError::RootCertStore(_) => "TypeError", + } +} + +fn get_websocket_error(error: &WebsocketError) -> &'static str { + match error { + WebsocketError::Permission(e) | WebsocketError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + WebsocketError::Url(e) => get_url_parse_error_class(e), + WebsocketError::Io(e) => get_io_error_class(e), + WebsocketError::WebSocket(_) => "TypeError", + WebsocketError::ConnectionFailed(_) => "DOMExceptionNetworkError", + WebsocketError::Uri(_) => "Error", + WebsocketError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + } +} + +fn get_websocket_handshake_error(error: &HandshakeError) -> &'static str { + match error { + HandshakeError::RootStoreError(e) => { + get_error_class_name(e).unwrap_or("Error") + } + HandshakeError::Tls(e) => get_tls_error_class(e), + HandshakeError::MissingPath => "TypeError", + HandshakeError::Http(_) => "Error", + HandshakeError::InvalidHostname(_) => "TypeError", + HandshakeError::Io(e) => get_io_error_class(e), + HandshakeError::Rustls(_) => "Error", + HandshakeError::H2(_) => "Error", + HandshakeError::NoH2Alpn => "Error", + HandshakeError::InvalidStatusCode(_) => "Error", + HandshakeError::WebSocket(_) => "TypeError", + HandshakeError::HeaderName(_) => "TypeError", + HandshakeError::HeaderValue(_) => "TypeError", + } +} + +fn get_fs_ops_error(error: &FsOpsError) -> &'static str { + match error { + FsOpsError::Io(e) => get_io_error_class(e), + FsOpsError::OperationError(e) => get_fs_error(&e.err), + FsOpsError::Permission(e) + | FsOpsError::Resource(e) + | FsOpsError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + FsOpsError::InvalidUtf8(_) => "InvalidData", + FsOpsError::StripPrefix(_) => "Error", + FsOpsError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + FsOpsError::InvalidSeekMode(_) => "TypeError", + FsOpsError::InvalidControlCharacter(_) => "Error", + FsOpsError::InvalidCharacter(_) => "Error", + #[cfg(windows)] + FsOpsError::InvalidTrailingCharacter => "Error", + FsOpsError::NotCapableAccess { .. } => "NotCapable", + FsOpsError::NotCapable(_) => "NotCapable", + } +} + +fn get_kv_error(error: &KvError) -> &'static str { + match error { + KvError::DatabaseHandler(e) | KvError::Resource(e) | KvError::Kv(e) => { + get_error_class_name(e).unwrap_or("Error") + } + KvError::TooManyRanges(_) => "TypeError", + KvError::TooManyEntries(_) => "TypeError", + KvError::TooManyChecks(_) => "TypeError", + KvError::TooManyMutations(_) => "TypeError", + KvError::TooManyKeys(_) => "TypeError", + KvError::InvalidLimit => "TypeError", + KvError::InvalidBoundaryKey => "TypeError", + KvError::KeyTooLargeToRead(_) => "TypeError", + KvError::KeyTooLargeToWrite(_) => "TypeError", + KvError::TotalMutationTooLarge(_) => "TypeError", + KvError::TotalKeyTooLarge(_) => "TypeError", + KvError::Io(e) => get_io_error_class(e), + KvError::QueueMessageNotFound => "TypeError", + KvError::StartKeyNotInKeyspace => "TypeError", + KvError::EndKeyNotInKeyspace => "TypeError", + KvError::StartKeyGreaterThanEndKey => "TypeError", + KvError::InvalidCheck(e) => match e { + KvCheckError::InvalidVersionstamp => "TypeError", + KvCheckError::Io(e) => get_io_error_class(e), + }, + KvError::InvalidMutation(e) => match e { + KvMutationError::BigInt(_) => "Error", + KvMutationError::Io(e) => get_io_error_class(e), + KvMutationError::InvalidMutationWithValue(_) => "TypeError", + KvMutationError::InvalidMutationWithoutValue(_) => "TypeError", + }, + KvError::InvalidEnqueue(e) => get_io_error_class(e), + KvError::EmptyKey => "TypeError", + KvError::ValueTooLarge(_) => "TypeError", + KvError::EnqueuePayloadTooLarge(_) => "TypeError", + KvError::InvalidCursor => "TypeError", + KvError::CursorOutOfBounds => "TypeError", + KvError::InvalidRange => "TypeError", + } +} + +fn get_net_error(error: &NetError) -> &'static str { + match error { + NetError::ListenerClosed => "BadResource", + NetError::ListenerBusy => "Busy", + NetError::SocketClosed => "BadResource", + NetError::SocketClosedNotConnected => "NotConnected", + NetError::SocketBusy => "Busy", + NetError::Io(e) => get_io_error_class(e), + NetError::AcceptTaskOngoing => "Busy", + NetError::RootCertStore(e) + | NetError::Permission(e) + | NetError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + NetError::NoResolvedAddress => "Error", + NetError::AddrParse(_) => "Error", + NetError::Map(e) => get_net_map_error(e), + NetError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + NetError::DnsNotFound(_) => "NotFound", + NetError::DnsNotConnected(_) => "NotConnected", + NetError::DnsTimedOut(_) => "TimedOut", + NetError::Dns(_) => "Error", + NetError::UnsupportedRecordType => "NotSupported", + NetError::InvalidUtf8(_) => "InvalidData", + NetError::UnexpectedKeyType => "Error", + NetError::InvalidHostname(_) => "TypeError", + NetError::TcpStreamBusy => "Busy", + NetError::Rustls(_) => "Error", + NetError::Tls(e) => get_tls_error_class(e), + NetError::ListenTlsRequiresKey => "InvalidData", + NetError::Reunite(_) => "Error", + } +} + +fn get_net_map_error(error: &deno_net::io::MapError) -> &'static str { + match error { + deno_net::io::MapError::Io(e) => get_io_error_class(e), + deno_net::io::MapError::NoResources => "Error", + } +} + +fn get_create_worker_error(error: &CreateWorkerError) -> &'static str { + match error { + CreateWorkerError::ClassicWorkers => "DOMExceptionNotSupportedError", + CreateWorkerError::Permission(e) => { + get_error_class_name(e).unwrap_or("Error") + } + CreateWorkerError::ModuleResolution(e) => { + get_module_resolution_error_class(e) + } + CreateWorkerError::Io(e) => get_io_error_class(e), + CreateWorkerError::MessagePort(e) => get_web_message_port_error_class(e), + } +} + +fn get_tty_error(error: &TtyError) -> &'static str { + match error { + TtyError::Resource(e) | TtyError::Other(e) => { + get_error_class_name(e).unwrap_or("Error") + } + TtyError::Io(e) => get_io_error_class(e), + #[cfg(unix)] + TtyError::Nix(e) => get_nix_error_class(e), + } +} + +fn get_readline_error(error: &ReadlineError) -> &'static str { + match error { + ReadlineError::Io(e) => get_io_error_class(e), + ReadlineError::Eof => "Error", + ReadlineError::Interrupted => "Error", + #[cfg(unix)] + ReadlineError::Errno(e) => get_nix_error_class(e), + ReadlineError::WindowResized => "Error", + #[cfg(windows)] + ReadlineError::Decode(_) => "Error", + #[cfg(windows)] + ReadlineError::SystemError(_) => "Error", + _ => "Error", + } +} + +fn get_signal_error(error: &SignalError) -> &'static str { + match error { + SignalError::InvalidSignalStr(_) => "TypeError", + SignalError::InvalidSignalInt(_) => "TypeError", + SignalError::SignalNotAllowed(_) => "TypeError", + SignalError::Io(e) => get_io_error_class(e), + } +} + +fn get_fs_events_error(error: &FsEventsError) -> &'static str { + match error { + FsEventsError::Resource(e) | FsEventsError::Permission(e) => { + get_error_class_name(e).unwrap_or("Error") + } + FsEventsError::Notify(e) => get_notify_error_class(e), + FsEventsError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + } +} + +fn get_http_start_error(error: &HttpStartError) -> &'static str { + match error { + HttpStartError::TcpStreamInUse => "Busy", + HttpStartError::TlsStreamInUse => "Busy", + HttpStartError::UnixSocketInUse => "Busy", + HttpStartError::ReuniteTcp(_) => "Error", + #[cfg(unix)] + HttpStartError::ReuniteUnix(_) => "Error", + HttpStartError::Io(e) => get_io_error_class(e), + HttpStartError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + +fn get_process_error(error: &ProcessError) -> &'static str { + match error { + ProcessError::SpawnFailed { error, .. } => get_process_error(error), + ProcessError::FailedResolvingCwd(e) | ProcessError::Io(e) => { + get_io_error_class(e) + } + ProcessError::Permission(e) | ProcessError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + ProcessError::BorrowMut(_) => "Error", + ProcessError::Which(_) => "Error", + ProcessError::ChildProcessAlreadyTerminated => "TypeError", + ProcessError::Signal(e) => get_signal_error(e), + ProcessError::MissingCmd => "Error", + ProcessError::InvalidPid => "TypeError", + #[cfg(unix)] + ProcessError::Nix(e) => get_nix_error_class(e), + } +} + +fn get_http_error(error: &HttpError) -> &'static str { + match error { + HttpError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + HttpError::HyperV014(e) => get_hyper_v014_error_class(e), + HttpError::InvalidHeaderName(_) => "Error", + HttpError::InvalidHeaderValue(_) => "Error", + HttpError::Http(_) => "Error", + HttpError::ResponseHeadersAlreadySent => "Http", + HttpError::ConnectionClosedWhileSendingResponse => "Http", + HttpError::AlreadyInUse => "Http", + HttpError::Io(e) => get_io_error_class(e), + HttpError::NoResponseHeaders => "Http", + HttpError::ResponseAlreadyCompleted => "Http", + HttpError::UpgradeBodyUsed => "Http", + HttpError::Resource(e) | HttpError::Other(e) => { + get_error_class_name(e).unwrap_or("Error") + } + } +} + +fn get_http_next_error(error: &HttpNextError) -> &'static str { + match error { + HttpNextError::Io(e) => get_io_error_class(e), + HttpNextError::WebSocketUpgrade(e) => get_websocket_upgrade_error(e), + HttpNextError::Hyper(e) => get_hyper_error_class(e), + HttpNextError::JoinError(_) => "Error", + HttpNextError::Canceled(e) => { + let io_err: io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + HttpNextError::UpgradeUnavailable(_) => "Error", + HttpNextError::HttpPropertyExtractor(e) | HttpNextError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + } +} + +fn get_websocket_upgrade_error(error: &WebSocketUpgradeError) -> &'static str { + match error { + WebSocketUpgradeError::InvalidHeaders => "Http", + WebSocketUpgradeError::HttpParse(_) => "Error", + WebSocketUpgradeError::Http(_) => "Error", + WebSocketUpgradeError::Utf8(_) => "Error", + WebSocketUpgradeError::InvalidHeaderName(_) => "Error", + WebSocketUpgradeError::InvalidHeaderValue(_) => "Error", + WebSocketUpgradeError::InvalidHttpStatusLine => "Http", + WebSocketUpgradeError::UpgradeBufferAlreadyCompleted => "Http", + } +} + +fn get_fs_error(e: &FsError) -> &'static str { + match &e { + FsError::Io(e) => get_io_error_class(e), + FsError::FileBusy => "Busy", + FsError::NotSupported => "NotSupported", + FsError::NotCapable(_) => "NotCapable", + } +} + +mod node { + use super::get_error_class_name; + use super::get_io_error_class; + use super::get_serde_json_error_class; + use super::get_url_parse_error_class; + pub use deno_node::ops::blocklist::BlocklistError; + pub use deno_node::ops::fs::FsError; + pub use deno_node::ops::http2::Http2Error; + pub use deno_node::ops::idna::IdnaError; + pub use deno_node::ops::ipc::IpcError; + pub use deno_node::ops::ipc::IpcJsonStreamError; + use deno_node::ops::os::priority::PriorityError; + pub use deno_node::ops::os::OsError; + pub use deno_node::ops::require::RequireError; + pub use deno_node::ops::worker_threads::WorkerThreadsFilenameError; + pub use deno_node::ops::zlib::brotli::BrotliError; + pub use deno_node::ops::zlib::mode::ModeError; + pub use deno_node::ops::zlib::ZlibError; + + pub fn get_blocklist_error(error: &BlocklistError) -> &'static str { + match error { + BlocklistError::AddrParse(_) => "Error", + BlocklistError::IpNetwork(_) => "Error", + BlocklistError::InvalidAddress => "Error", + BlocklistError::IpVersionMismatch => "Error", + } + } + + pub fn get_fs_error(error: &FsError) -> &'static str { + match error { + FsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + FsError::Io(e) => get_io_error_class(e), + #[cfg(windows)] + FsError::PathHasNoRoot => "Error", + #[cfg(not(any(unix, windows)))] + FsError::UnsupportedPlatform => "Error", + FsError::Fs(e) => super::get_fs_error(e), + } + } + + pub fn get_idna_error(error: &IdnaError) -> &'static str { + match error { + IdnaError::InvalidInput => "RangeError", + IdnaError::InputTooLong => "Error", + IdnaError::IllegalInput => "RangeError", + } + } + + pub fn get_ipc_json_stream_error(error: &IpcJsonStreamError) -> &'static str { + match error { + IpcJsonStreamError::Io(e) => get_io_error_class(e), + IpcJsonStreamError::SimdJson(_) => "Error", + } + } + + pub fn get_ipc_error(error: &IpcError) -> &'static str { + match error { + IpcError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + IpcError::IpcJsonStream(e) => get_ipc_json_stream_error(e), + IpcError::Canceled(e) => { + let io_err: std::io::Error = e.to_owned().into(); + get_io_error_class(&io_err) + } + IpcError::SerdeJson(e) => get_serde_json_error_class(e), + } + } + + pub fn get_worker_threads_filename_error( + error: &WorkerThreadsFilenameError, + ) -> &'static str { + match error { + WorkerThreadsFilenameError::Permission(e) => { + get_error_class_name(e).unwrap_or("Error") + } + WorkerThreadsFilenameError::UrlParse(e) => get_url_parse_error_class(e), + WorkerThreadsFilenameError::InvalidRelativeUrl => "Error", + WorkerThreadsFilenameError::UrlFromPathString => "Error", + WorkerThreadsFilenameError::UrlToPathString => "Error", + WorkerThreadsFilenameError::UrlToPath => "Error", + WorkerThreadsFilenameError::FileNotFound(_) => "Error", + WorkerThreadsFilenameError::NeitherEsmNorCjs => "Error", + WorkerThreadsFilenameError::UrlToNodeResolution(_) => "Error", + WorkerThreadsFilenameError::Fs(e) => super::get_fs_error(e), + } + } + + pub fn get_require_error(error: &RequireError) -> &'static str { + match error { + RequireError::UrlParse(e) => get_url_parse_error_class(e), + RequireError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + RequireError::PackageExportsResolve(_) => "Error", + RequireError::PackageJsonLoad(_) => "Error", + RequireError::ClosestPkgJson(_) => "Error", + RequireError::FilePathConversion(_) => "Error", + RequireError::PackageImportsResolve(_) => "Error", + RequireError::Fs(e) | RequireError::UnableToGetCwd(e) => { + super::get_fs_error(e) + } + } + } + + pub fn get_http2_error(error: &Http2Error) -> &'static str { + match error { + Http2Error::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + Http2Error::UrlParse(e) => get_url_parse_error_class(e), + Http2Error::H2(_) => "Error", + } + } + + pub fn get_os_error(error: &OsError) -> &'static str { + match error { + OsError::Priority(e) => match e { + PriorityError::Io(e) => get_io_error_class(e), + #[cfg(windows)] + PriorityError::InvalidPriority => "TypeError", + }, + OsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + OsError::FailedToGetCpuInfo => "TypeError", + } + } + + pub fn get_brotli_error(error: &BrotliError) -> &'static str { + match error { + BrotliError::InvalidEncoderMode => "TypeError", + BrotliError::CompressFailed => "TypeError", + BrotliError::DecompressFailed => "TypeError", + BrotliError::Join(_) => "Error", + BrotliError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + BrotliError::Io(e) => get_io_error_class(e), + } + } + + pub fn get_mode_error(_: &ModeError) -> &'static str { + "Error" + } + + pub fn get_zlib_error(e: &ZlibError) -> &'static str { + match e { + ZlibError::NotInitialized => "TypeError", + ZlibError::Mode(e) => get_mode_error(e), + ZlibError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + } + } +} + +fn get_os_error(error: &OsError) -> &'static str { + match error { + OsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + OsError::InvalidUtf8(_) => "InvalidData", + OsError::EnvEmptyKey => "TypeError", + OsError::EnvInvalidKey(_) => "TypeError", + OsError::EnvInvalidValue(_) => "TypeError", + OsError::Io(e) => get_io_error_class(e), + OsError::Var(e) => get_env_var_error_class(e), + } +} + +fn get_sync_fetch_error(error: &SyncFetchError) -> &'static str { + match error { + SyncFetchError::BlobUrlsNotSupportedInContext => "TypeError", + SyncFetchError::Io(e) => get_io_error_class(e), + SyncFetchError::InvalidScriptUrl => "TypeError", + SyncFetchError::InvalidStatusCode(_) => "TypeError", + SyncFetchError::ClassicScriptSchemeUnsupportedInWorkers(_) => "TypeError", + SyncFetchError::InvalidUri(_) => "Error", + SyncFetchError::InvalidMimeType(_) => "DOMExceptionNetworkError", + SyncFetchError::MissingMimeType => "DOMExceptionNetworkError", + SyncFetchError::Fetch(e) => get_fetch_error(e), + SyncFetchError::Join(_) => "Error", + SyncFetchError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + } +} + pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { deno_core::error::get_custom_error_class(e) - .or_else(|| deno_webgpu::error::get_error_class_name(e)) - .or_else(|| deno_web::get_error_class_name(e)) - .or_else(|| deno_webstorage::get_not_supported_error_class_name(e)) - .or_else(|| deno_websocket::get_network_error_class_name(e)) + .or_else(|| e.downcast_ref::().map(get_fs_error)) + .or_else(|| { + e.downcast_ref::() + .map(node::get_blocklist_error) + }) + .or_else(|| e.downcast_ref::().map(node::get_fs_error)) + .or_else(|| { + e.downcast_ref::() + .map(node::get_idna_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(node::get_ipc_json_stream_error) + }) + .or_else(|| e.downcast_ref::().map(node::get_ipc_error)) + .or_else(|| { + e.downcast_ref::() + .map(node::get_worker_threads_filename_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(node::get_require_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(node::get_http2_error) + }) + .or_else(|| e.downcast_ref::().map(node::get_os_error)) + .or_else(|| { + e.downcast_ref::() + .map(node::get_brotli_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(node::get_mode_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(node::get_zlib_error) + }) + .or_else(|| e.downcast_ref::().map(get_napi_error_class)) + .or_else(|| e.downcast_ref::().map(get_web_error_class)) + .or_else(|| { + e.downcast_ref::() + .map(get_create_worker_error) + }) + .or_else(|| e.downcast_ref::().map(get_tty_error)) + .or_else(|| e.downcast_ref::().map(get_readline_error)) + .or_else(|| e.downcast_ref::().map(get_signal_error)) + .or_else(|| e.downcast_ref::().map(get_fs_events_error)) + .or_else(|| e.downcast_ref::().map(get_http_start_error)) + .or_else(|| e.downcast_ref::().map(get_process_error)) + .or_else(|| e.downcast_ref::().map(get_os_error)) + .or_else(|| e.downcast_ref::().map(get_sync_fetch_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_web_compression_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_web_message_port_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_web_stream_resource_error_class) + }) + .or_else(|| e.downcast_ref::().map(get_web_blob_error_class)) + .or_else(|| e.downcast_ref::().map(|_| "TypeError")) + .or_else(|| e.downcast_ref::().map(get_ffi_repr_error_class)) + .or_else(|| e.downcast_ref::().map(get_http_error)) + .or_else(|| e.downcast_ref::().map(get_http_next_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_websocket_upgrade_error) + }) + .or_else(|| e.downcast_ref::().map(get_fs_ops_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_ffi_dlfcn_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_ffi_static_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_ffi_callback_error_class) + }) + .or_else(|| e.downcast_ref::().map(get_ffi_call_error_class)) + .or_else(|| e.downcast_ref::().map(get_tls_error_class)) + .or_else(|| e.downcast_ref::().map(get_cron_error_class)) + .or_else(|| e.downcast_ref::().map(get_canvas_error)) + .or_else(|| e.downcast_ref::().map(get_cache_error)) + .or_else(|| e.downcast_ref::().map(get_websocket_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_websocket_handshake_error) + }) + .or_else(|| e.downcast_ref::().map(get_kv_error)) + .or_else(|| e.downcast_ref::().map(get_fetch_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_http_client_create_error) + }) + .or_else(|| e.downcast_ref::().map(get_net_error)) + .or_else(|| { + e.downcast_ref::() + .map(get_net_map_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_broadcast_channel_error) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_buffer_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_bundle_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_byow_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_render_pass_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webgpu_surface_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_decrypt_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_encrypt_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_shared_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_ed25519_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_export_key_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_generate_key_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_import_key_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_x448_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_x25519_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_crypto_error_class) + }) + .or_else(|| { + e.downcast_ref::() + .map(get_webstorage_class_name) + }) + .or_else(|| { + e.downcast_ref::() + .map(|_| "TypeError") + }) .or_else(|| { e.downcast_ref::() .map(get_dlopen_error_class) diff --git a/runtime/examples/extension/main.rs b/runtime/examples/extension/main.rs index 4339bdf679..9889b28dcf 100644 --- a/runtime/examples/extension/main.rs +++ b/runtime/examples/extension/main.rs @@ -5,14 +5,18 @@ use std::path::Path; use std::rc::Rc; +use std::sync::Arc; use deno_core::error::AnyError; use deno_core::op2; use deno_core::FsModuleLoader; use deno_core::ModuleSpecifier; +use deno_fs::RealFs; use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::worker::MainWorker; use deno_runtime::worker::WorkerOptions; +use deno_runtime::worker::WorkerServiceOptions; #[op2(fast)] fn op_hello(#[string] text: &str) { @@ -32,11 +36,26 @@ async fn main() -> Result<(), AnyError> { Path::new(env!("CARGO_MANIFEST_DIR")).join("examples/extension/main.js"); let main_module = ModuleSpecifier::from_file_path(js_path).unwrap(); eprintln!("Running {main_module}..."); + let fs = Arc::new(RealFs); + let permission_desc_parser = + Arc::new(RuntimePermissionDescriptorParser::new(fs.clone())); let mut worker = MainWorker::bootstrap_from_options( main_module.clone(), - PermissionsContainer::allow_all(), - WorkerOptions { + WorkerServiceOptions { module_loader: Rc::new(FsModuleLoader), + permissions: PermissionsContainer::allow_all(permission_desc_parser), + blob_store: Default::default(), + broadcast_channel: Default::default(), + feature_checker: Default::default(), + node_services: Default::default(), + npm_process_state_provider: Default::default(), + root_cert_store_provider: Default::default(), + shared_array_buffer_store: Default::default(), + compiled_wasm_module_store: Default::default(), + v8_code_cache: Default::default(), + fs, + }, + WorkerOptions { extensions: vec![hello_runtime::init_ops_and_esm()], ..Default::default() }, diff --git a/runtime/fmt_errors.rs b/runtime/fmt_errors.rs index 4687dbd475..7c6cf6d397 100644 --- a/runtime/fmt_errors.rs +++ b/runtime/fmt_errors.rs @@ -1,11 +1,10 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. //! This mod provides DenoError to unify errors across Deno. +use color_print::cformat; +use color_print::cstr; use deno_core::error::format_frame; use deno_core::error::JsError; -use deno_terminal::colors::cyan; -use deno_terminal::colors::italic_bold; -use deno_terminal::colors::red; -use deno_terminal::colors::yellow; +use deno_terminal::colors; use std::fmt::Write as _; #[derive(Debug, Clone)] @@ -20,6 +19,62 @@ struct IndexedErrorReference<'a> { index: usize, } +#[derive(Debug)] +enum FixSuggestionKind { + Info, + Hint, + Docs, +} + +#[derive(Debug)] +enum FixSuggestionMessage<'a> { + Single(&'a str), + Multiline(&'a [&'a str]), +} + +#[derive(Debug)] +pub struct FixSuggestion<'a> { + kind: FixSuggestionKind, + message: FixSuggestionMessage<'a>, +} + +impl<'a> FixSuggestion<'a> { + pub fn info(message: &'a str) -> Self { + Self { + kind: FixSuggestionKind::Info, + message: FixSuggestionMessage::Single(message), + } + } + + pub fn info_multiline(messages: &'a [&'a str]) -> Self { + Self { + kind: FixSuggestionKind::Info, + message: FixSuggestionMessage::Multiline(messages), + } + } + + pub fn hint(message: &'a str) -> Self { + Self { + kind: FixSuggestionKind::Hint, + message: FixSuggestionMessage::Single(message), + } + } + + pub fn hint_multiline(messages: &'a [&'a str]) -> Self { + Self { + kind: FixSuggestionKind::Hint, + message: FixSuggestionMessage::Multiline(messages), + } + } + + pub fn docs(url: &'a str) -> Self { + Self { + kind: FixSuggestionKind::Docs, + message: FixSuggestionMessage::Single(url), + } + } +} + struct AnsiColors; impl deno_core::error::ErrorFormat for AnsiColors { @@ -30,10 +85,10 @@ impl deno_core::error::ErrorFormat for AnsiColors { use deno_core::error::ErrorElement::*; match element { Anonymous | NativeFrame | FileName | EvalOrigin => { - cyan(s).to_string().into() + colors::cyan(s).to_string().into() } - LineNumber | ColumnNumber => yellow(s).to_string().into(), - FunctionName | PromiseAll => italic_bold(s).to_string().into(), + LineNumber | ColumnNumber => colors::yellow(s).to_string().into(), + FunctionName | PromiseAll => colors::italic_bold(s).to_string().into(), } } } @@ -66,7 +121,7 @@ fn format_maybe_source_line( if column_number as usize > source_line.len() { return format!( "\n{} Couldn't format source line: Column {} is out of bounds (source may have changed at runtime)", - yellow("Warning"), column_number, + colors::yellow("Warning"), column_number, ); } @@ -79,9 +134,9 @@ fn format_maybe_source_line( } s.push('^'); let color_underline = if is_error { - red(&s).to_string() + colors::red(&s).to_string() } else { - cyan(&s).to_string() + colors::cyan(&s).to_string() }; let indent = format!("{:indent$}", "", indent = level); @@ -129,6 +184,7 @@ fn format_aggregated_error( index: nested_circular_reference_index, }), false, + vec![], ); for line in error_string.trim_start_matches("Uncaught ").lines() { @@ -143,6 +199,7 @@ fn format_js_error_inner( js_error: &JsError, circular: Option, include_source_code: bool, + suggestions: Vec, ) -> String { let mut s = String::new(); @@ -150,7 +207,8 @@ fn format_js_error_inner( if let Some(circular) = &circular { if js_error.is_same_error(circular.reference.to) { - write!(s, " {}", cyan(format!("", circular.index))).unwrap(); + write!(s, " {}", colors::cyan(format!("", circular.index))) + .unwrap(); } } @@ -188,9 +246,10 @@ fn format_js_error_inner( .unwrap_or(false); let error_string = if is_caused_by_circular { - cyan(format!("[Circular *{}]", circular.unwrap().index)).to_string() + colors::cyan(format!("[Circular *{}]", circular.unwrap().index)) + .to_string() } else { - format_js_error_inner(cause, circular, false) + format_js_error_inner(cause, circular, false, vec![]) }; write!( @@ -200,9 +259,156 @@ fn format_js_error_inner( ) .unwrap(); } + if !suggestions.is_empty() { + write!(s, "\n\n").unwrap(); + for (index, suggestion) in suggestions.iter().enumerate() { + write!(s, " ").unwrap(); + match suggestion.kind { + FixSuggestionKind::Hint => { + write!(s, "{} ", colors::cyan("hint:")).unwrap() + } + FixSuggestionKind::Info => { + write!(s, "{} ", colors::yellow("info:")).unwrap() + } + FixSuggestionKind::Docs => { + write!(s, "{} ", colors::green("docs:")).unwrap() + } + }; + match suggestion.message { + FixSuggestionMessage::Single(msg) => { + if matches!(suggestion.kind, FixSuggestionKind::Docs) { + write!(s, "{}", cformat!("{}", msg)).unwrap(); + } else { + write!(s, "{}", msg).unwrap(); + } + } + FixSuggestionMessage::Multiline(messages) => { + for (idx, message) in messages.iter().enumerate() { + if idx != 0 { + writeln!(s).unwrap(); + write!(s, " ").unwrap(); + } + write!(s, "{}", message).unwrap(); + } + } + } + + if index != (suggestions.len() - 1) { + writeln!(s).unwrap(); + } + } + } + s } +fn get_suggestions_for_terminal_errors(e: &JsError) -> Vec { + if let Some(msg) = &e.message { + if msg.contains("module is not defined") + || msg.contains("exports is not defined") + || msg.contains("require is not defined") + { + return vec![ + FixSuggestion::info_multiline(&[ + cstr!("Deno supports CommonJS modules in .cjs files, or when there's a package.json"), + cstr!("with \"type\": \"commonjs\" option and --unstable-detect-cjs flag is used.") + ]), + FixSuggestion::hint_multiline(&[ + "Rewrite this module to ESM,", + cstr!("or change the file extension to .cjs,"), + cstr!("or add package.json next to the file with \"type\": \"commonjs\" option"), + cstr!("and pass --unstable-detect-cjs flag."), + ]), + FixSuggestion::docs("https://docs.deno.com/go/commonjs"), + ]; + } else if msg.contains("openKv is not a function") { + return vec![ + FixSuggestion::info("Deno.openKv() is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-kv` flag to enable this API.", + ), + ]; + } else if msg.contains("cron is not a function") { + return vec![ + FixSuggestion::info("Deno.cron() is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-cron` flag to enable this API.", + ), + ]; + } else if msg.contains("WebSocketStream is not defined") { + return vec![ + FixSuggestion::info("new WebSocketStream() is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-net` flag to enable this API.", + ), + ]; + } else if msg.contains("Temporal is not defined") { + return vec![ + FixSuggestion::info("Temporal is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-temporal` flag to enable this API.", + ), + ]; + } else if msg.contains("BroadcastChannel is not defined") { + return vec![ + FixSuggestion::info("BroadcastChannel is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-broadcast-channel` flag to enable this API.", + ), + ]; + } else if msg.contains("window is not defined") { + return vec![ + FixSuggestion::info("window global is not available in Deno 2."), + FixSuggestion::hint("Replace `window` with `globalThis`."), + ]; + } else if msg.contains("UnsafeWindowSurface is not a constructor") { + return vec![ + FixSuggestion::info("Deno.UnsafeWindowSurface is an unstable API."), + FixSuggestion::hint( + "Run again with `--unstable-webgpu` flag to enable this API.", + ), + ]; + // Try to capture errors like: + // ``` + // Uncaught Error: Cannot find module '../build/Release/canvas.node' + // Require stack: + // - /.../deno/npm/registry.npmjs.org/canvas/2.11.2/lib/bindings.js + // - /.../.cache/deno/npm/registry.npmjs.org/canvas/2.11.2/lib/canvas.js + // ``` + } else if msg.contains("Cannot find module") + && msg.contains("Require stack") + && msg.contains(".node'") + { + return vec![ + FixSuggestion::info_multiline( + &[ + "Trying to execute an npm package using Node-API addons,", + "these packages require local `node_modules` directory to be present." + ] + ), + FixSuggestion::hint_multiline( + &[ + "Add `\"nodeModulesDir\": \"auto\" option to `deno.json`, and then run", + "`deno install --allow-scripts=npm: --entrypoint \n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\nAjv is tested with these browsers:\n\n[![Sauce Test Status](https://saucelabs.com/browser-matrix/epoberezkin.svg)](https://saucelabs.com/u/epoberezkin)\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n### Ajv and Content Security Policies (CSP)\n\nIf you're using Ajv to compile a schema (the typical use) in a browser document that is loaded with a Content Security Policy (CSP), that policy will require a `script-src` directive that includes the value `'unsafe-eval'`.\n:warning: NOTE, however, that `unsafe-eval` is NOT recommended in a secure CSP[[1]](https://developer.chrome.com/extensions/contentSecurityPolicy#relaxing-eval), as it has the potential to open the document to cross-site scripting (XSS) attacks.\n\nIn order to make use of Ajv without easing your CSP, you can [pre-compile a schema using the CLI](https://github.com/ajv-validator/ajv-cli#compile-schemas). This will transpile the schema JSON into a JavaScript file that exports a `validate` function that works simlarly to a schema compiled at runtime.\n\nNote that pre-compilation of schemas is performed using [ajv-pack](https://github.com/ajv-validator/ajv-pack) and there are [some limitations to the schema features it can compile](https://github.com/ajv-validator/ajv-pack#limitations). A successfully pre-compiled schema is equivalent to the same schema compiled at runtime.\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Strict mode\n\nStrict mode intends to prevent any unexpected behaviours or silently ignored mistakes in user schemas. It does not change any validation results compared with JSON Schema specification, but it makes some schemas invalid and throws exception or logs warning (with `strict: \"log\"` option) in case any restriction is violated.\n\nThe strict mode restrictions are below. To disable these restrictions use option `strict: false`.\n\n##### Prohibit unknown keywords\n\nJSON Schema [section 6.5](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-6.5) requires to ignore unknown keywords. The motivation is to increase cross-platform portability of schemas, so that implementations that do not support certain keywords can still do partial validation.\n\nThe problems with this approach are:\n\n- Different validation results with the same schema and data, leading to bugs and inconsistent behaviours.\n- Typos in keywords resulting in keywords being quietly ignored, requiring extensive test coverage of schemas to avoid these mistakes.\n\nBy default Ajv fails schema compilation when unknown keywords are used. Users can explicitly define the keywords that should be allowed and ignored:\n\n```javascript\najv.addKeyword(\"allowedKeyword\")\n```\n\nor\n\n```javascript\najv.addVocabulary([\"allowed1\", \"allowed2\"])\n```\n\n#### Prohibit ignored \"additionalItems\" keyword\n\nJSON Schema section [9.3.1.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2) requires to ignore \"additionalItems\" keyword if \"items\" keyword is absent. This is inconsistent with the interaction of \"additionalProperties\" and \"properties\", and may cause unexpected results.\n\nBy default Ajv fails schema compilation when \"additionalItems\" is used without \"items.\n\n#### Prohibit ignored \"if\", \"then\", \"else\" keywords\n\nJSON Schema section [9.2.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2) requires to ignore \"if\" (only annotations are collected) if both \"then\" and \"else\" are absent, and ignore \"then\"/\"else\" if \"if\" is absent.\n\nBy default Ajv fails schema compilation in these cases.\n\n#### Prohibit overlap between \"properties\" and \"patternProperties\" keywords\n\nThe expectation of users (see #196, #286) is that \"patternProperties\" only apply to properties not already defined in \"properties\" keyword, but JSON Schema section [9.3.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2) defines these two keywords as independent. It means that to some properties two subschemas can be applied - one defined in \"properties\" keyword and another defined in \"patternProperties\" for the pattern matching this property.\n\nBy default Ajv fails schema compilation if a pattern in \"patternProperties\" matches a property in \"properties\" in the same schema.\n\nIn addition to allowing such patterns by using option `strict: false`, there is an option `allowMatchingProperties: true` to only allow this case without disabling other strict mode restrictions - there are some rare cases when this is necessary.\n\nTo reiterate, neither this nor other strict mode restrictions change the validation results - they only restrict which schemas are valid.\n\n#### Prohibit unknown formats\n\nTODO\n\nThis will supercede unknownFormats option.\n\n#### Prohibit ignored defaults\n\nWith `useDefaults` option Ajv modifies validated data by assigning defaults from the schema, but there are different limitations when the defaults can be ignored (see [Assigning defaults](#assigning-defaults)). In strict mode Ajv fails schema compilation if such defaults are used in the schema.\n\n#### Number validation\n\nStrict mode also affects number validation. By default Ajv fails `{\"type\": \"number\"}` (or `\"integer\"`) validation for `Infinity` and `NaN`.\n\n## Validation keywords\n\nAjv supports all validation keywords from draft-07 of JSON Schema standard:\n\n- [type](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#type)\n- [for numbers](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-numbers) - maximum, minimum, exclusiveMaximum, exclusiveMinimum, multipleOf\n- [for strings](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-strings) - maxLength, minLength, pattern, format\n- [for arrays](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-arrays) - maxItems, minItems, uniqueItems, items, additionalItems, [contains](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#contains)\n- [for objects](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-objects) - maxProperties, minProperties, required, properties, patternProperties, additionalProperties, dependencies, [propertyNames](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#propertynames)\n- [for all types](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-all-types) - enum, [const](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#const)\n- [compound keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#compound-keywords) - not, oneOf, anyOf, allOf, [if/then/else](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#ifthenelse)\n\nWith [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package Ajv also supports validation keywords from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) for JSON Schema standard:\n\n- [patternRequired](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#patternrequired-proposed) - like `required` but with patterns that some property should match.\n- [formatMaximum, formatMinimum, formatExclusiveMaximum, formatExclusiveMinimum](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#formatmaximum--formatminimum-and-exclusiveformatmaximum--exclusiveformatminimum-proposed) - setting limits for date, time, etc.\n\nSee [JSON Schema validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md) for more details.\n\n## Annotation keywords\n\nJSON Schema specification defines several annotation keywords that describe schema itself but do not perform any validation.\n\n- `title` and `description`: information about the data represented by that schema\n- `$comment` (NEW in draft-07): information for developers. With option `$comment` Ajv logs or passes the comment string to the user-supplied function. See [Options](#options).\n- `default`: a default value of the data instance, see [Assigning defaults](#assigning-defaults).\n- `examples` (NEW in draft-06): an array of data instances. Ajv does not check the validity of these instances against the schema.\n- `readOnly` and `writeOnly` (NEW in draft-07): marks data-instance as read-only or write-only in relation to the source of the data (database, api, etc.).\n- `contentEncoding`: [RFC 2045](https://tools.ietf.org/html/rfc2045#section-6.1), e.g., \"base64\".\n- `contentMediaType`: [RFC 2046](https://tools.ietf.org/html/rfc2046), e.g., \"image/png\".\n\n**Please note**: Ajv does not implement validation of the keywords `examples`, `contentEncoding` and `contentMediaType` but it reserves them. If you want to create a plugin that implements some of them, it should remove these keywords from the instance.\n\n## Formats\n\nFrom version 7 Ajv does not include formats defined by JSON Schema specification - these and several others formats are provided by [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin.\n\nTo add all formats from this plugin:\n\n```javascript\nconst ajv = new Ajv()\nrequire(\"ajv-formats\")(ajv)\n```\n\nSee ajv-formats documentation for further details.\n\nIt is recommended NOT to use \"format\" keyword implementations with untrusted data, as they use potentially unsafe regular expressions - see [ReDoS attack](#redos-attack).\n\n**Please note**: if you need to use \"format\" keyword to validate untrusted data, you MUST assess their suitability and safety for your validation scenarios.\n\nThe following formats are defined in [ajv-formats](https://github.com/ajv-validator/ajv-formats) for string validation with \"format\" keyword:\n\n- _date_: full-date according to [RFC3339](http://tools.ietf.org/html/rfc3339#section-5.6).\n- _time_: time with optional time-zone.\n- _date-time_: date-time from the same source (time-zone is mandatory). `date`, `time` and `date-time` validate ranges in `full` mode and only regexp in `fast` mode (see [options](#options)).\n- _uri_: full URI.\n- _uri-reference_: URI reference, including full and relative URIs.\n- _uri-template_: URI template according to [RFC6570](https://tools.ietf.org/html/rfc6570)\n- _url_ (deprecated): [URL record](https://url.spec.whatwg.org/#concept-url).\n- _email_: email address.\n- _hostname_: host name according to [RFC1034](http://tools.ietf.org/html/rfc1034#section-3.5).\n- _ipv4_: IP address v4.\n- _ipv6_: IP address v6.\n- _regex_: tests whether a string is a valid regular expression by passing it to RegExp constructor.\n- _uuid_: Universally Unique IDentifier according to [RFC4122](http://tools.ietf.org/html/rfc4122).\n- _json-pointer_: JSON-pointer according to [RFC6901](https://tools.ietf.org/html/rfc6901).\n- _relative-json-pointer_: relative JSON-pointer according to [this draft](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00).\n\n**Please note**: JSON Schema draft-07 also defines formats `iri`, `iri-reference`, `idn-hostname` and `idn-email` for URLs, hostnames and emails with international characters. These formats are available in [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) plugin.\n\nYou can add (and replace) any formats using [addFormat](#api-addformat) method.\n\nThe option `unknownFormats` allows changing the default behaviour when an unknown format is encountered. In this case Ajv can either fail schema compilation (default) or ignore it (default in versions before 5.0.0). You also can allow specific format(s) that will be ignored. See [Options](#options) for details.\n\nYou can find regular expressions used for format validation and the sources that were used in [formats.js](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js).\n\n## Combining schemas with \\$ref\n\nYou can structure your validation logic across multiple schema files and have schemas reference each other using `$ref` keyword.\n\nExample:\n\n```javascript\nvar schema = {\n $id: \"http://example.com/schemas/schema.json\",\n type: \"object\",\n properties: {\n foo: {$ref: \"defs.json#/definitions/int\"},\n bar: {$ref: \"defs.json#/definitions/str\"},\n },\n}\n\nvar defsSchema = {\n $id: \"http://example.com/schemas/defs.json\",\n definitions: {\n int: {type: \"integer\"},\n str: {type: \"string\"},\n },\n}\n```\n\nNow to compile your schema you can either pass all schemas to Ajv instance:\n\n```javascript\nvar ajv = new Ajv({schemas: [schema, defsSchema]})\nvar validate = ajv.getSchema(\"http://example.com/schemas/schema.json\")\n```\n\nor use `addSchema` method:\n\n```javascript\nvar ajv = new Ajv()\nvar validate = ajv.addSchema(defsSchema).compile(schema)\n```\n\nSee [Options](#options) and [addSchema](#api) method.\n\n**Please note**:\n\n- `$ref` is resolved as the uri-reference using schema \\$id as the base URI (see the example).\n- References can be recursive (and mutually recursive) to implement the schemas for different data structures (such as linked lists, trees, graphs, etc.).\n- You don't have to host your schema files at the URIs that you use as schema \\$id. These URIs are only used to identify the schemas, and according to JSON Schema specification validators should not expect to be able to download the schemas from these URIs.\n- The actual location of the schema file in the file system is not used.\n- You can pass the identifier of the schema as the second parameter of `addSchema` method or as a property name in `schemas` option. This identifier can be used instead of (or in addition to) schema \\$id.\n- You cannot have the same \\$id (or the schema identifier) used for more than one schema - the exception will be thrown.\n- You can implement dynamic resolution of the referenced schemas using `compileAsync` method. In this way you can store schemas in any system (files, web, database, etc.) and reference them without explicitly adding to Ajv instance. See [Asynchronous schema compilation](#asynchronous-schema-compilation).\n\n## \\$data reference\n\nWith `$data` option you can use values from the validated data as the values for the schema keywords. See [proposal](https://github.com/json-schema-org/json-schema-spec/issues/51) for more information about how it works.\n\n`$data` reference is supported in the keywords: const, enum, format, maximum/minimum, exclusiveMaximum / exclusiveMinimum, maxLength / minLength, maxItems / minItems, maxProperties / minProperties, formatMaximum / formatMinimum, formatExclusiveMaximum / formatExclusiveMinimum, multipleOf, pattern, required, uniqueItems.\n\nThe value of \"$data\" should be a [JSON-pointer](https://tools.ietf.org/html/rfc6901) to the data (the root is always the top level data object, even if the $data reference is inside a referenced subschema) or a [relative JSON-pointer](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00) (it is relative to the current point in data; if the \\$data reference is inside a referenced subschema it cannot point to the data outside of the root level for this subschema).\n\nExamples.\n\nThis schema requires that the value in property `smaller` is less or equal than the value in the property larger:\n\n```javascript\nvar ajv = new Ajv({$data: true})\n\nvar schema = {\n properties: {\n smaller: {\n type: \"number\",\n maximum: {$data: \"1/larger\"},\n },\n larger: {type: \"number\"},\n },\n}\n\nvar validData = {\n smaller: 5,\n larger: 7,\n}\n\najv.validate(schema, validData) // true\n```\n\nThis schema requires that the properties have the same format as their field names:\n\n```javascript\nvar schema = {\n additionalProperties: {\n type: \"string\",\n format: {$data: \"0#\"},\n },\n}\n\nvar validData = {\n \"date-time\": \"1963-06-19T08:30:06.283185Z\",\n email: \"joe.bloggs@example.com\",\n}\n```\n\n`$data` reference is resolved safely - it won't throw even if some property is undefined. If `$data` resolves to `undefined` the validation succeeds (with the exclusion of `const` keyword). If `$data` resolves to incorrect type (e.g. not \"number\" for maximum keyword) the validation fails.\n\n## $merge and $patch keywords\n\nWith the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) you can use the keywords `$merge` and `$patch` that allow extending JSON Schemas with patches using formats [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) and [JSON Patch (RFC 6902)](https://tools.ietf.org/html/rfc6902).\n\nTo add keywords `$merge` and `$patch` to Ajv instance use this code:\n\n```javascript\nrequire(\"ajv-merge-patch\")(ajv)\n```\n\nExamples.\n\nUsing `$merge`:\n\n```json\n{\n \"$merge\": {\n \"source\": {\n \"type\": \"object\",\n \"properties\": {\"p\": {\"type\": \"string\"}},\n \"additionalProperties\": false\n },\n \"with\": {\n \"properties\": {\"q\": {\"type\": \"number\"}}\n }\n }\n}\n```\n\nUsing `$patch`:\n\n```json\n{\n \"$patch\": {\n \"source\": {\n \"type\": \"object\",\n \"properties\": {\"p\": {\"type\": \"string\"}},\n \"additionalProperties\": false\n },\n \"with\": [{\"op\": \"add\", \"path\": \"/properties/q\", \"value\": {\"type\": \"number\"}}]\n }\n}\n```\n\nThe schemas above are equivalent to this schema:\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"p\": {\"type\": \"string\"},\n \"q\": {\"type\": \"number\"}\n },\n \"additionalProperties\": false\n}\n```\n\nThe properties `source` and `with` in the keywords `$merge` and `$patch` can use absolute or relative `$ref` to point to other schemas previously added to the Ajv instance or to the fragments of the current schema.\n\nSee the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) for more information.\n\n## User-defined keywords\n\nThe advantages of defining keywords are:\n\n- allow creating validation scenarios that cannot be expressed using pre-defined keywords\n- simplify your schemas\n- help bringing a bigger part of the validation logic to your schemas\n- make your schemas more expressive, less verbose and closer to your application domain\n- implement data processors that modify your data (`modifying` option MUST be used in keyword definition) and/or create side effects while the data is being validated\n\nIf a keyword is used only for side-effects and its validation result is pre-defined, use option `valid: true/false` in keyword definition to simplify both generated code (no error handling in case of `valid: true`) and your keyword functions (no need to return any validation result).\n\nThe concerns you have to be aware of when extending JSON Schema standard with additional keywords are the portability and understanding of your schemas. You will have to support these keywords on other platforms and to properly document them so that everybody can understand and use your schemas.\n\nYou can define keywords with [addKeyword](#api-addkeyword) method. Keywords are defined on the `ajv` instance level - new instances will not have previously defined keywords.\n\nAjv allows defining keywords with:\n\n- code generation function (used by all pre-defined keywords)\n- validation function\n- compilation function\n- macro function\n\nExample. `range` and `exclusiveRange` keywords using compiled schema:\n\n```javascript\najv.addKeyword({\n keyword: \"range\",\n type: \"number\",\n schemaType: \"array\",\n implements: \"exclusiveRange\",\n compile: ([min, max], parentSchema) =>\n parentSchema.exclusiveRange === true\n ? (data) => data > min && data < max\n : (data) => data >= min && data <= max,\n})\n\nconst schema = {range: [2, 4], exclusiveRange: true}\nconst validate = ajv.compile(schema)\nconsole.log(validate(2.01)) // true\nconsole.log(validate(3.99)) // true\nconsole.log(validate(2)) // false\nconsole.log(validate(4)) // false\n```\n\nSeveral keywords (typeof, instanceof, range and propertyNames) are defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package - they can be used for your schemas and as a starting point for your own keywords.\n\nSee [User-defined keywords](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md) for more details.\n\n## Asynchronous schema compilation\n\nDuring asynchronous compilation remote references are loaded using supplied function. See `compileAsync` [method](#api-compileAsync) and `loadSchema` [option](#options).\n\nExample:\n\n```javascript\nvar ajv = new Ajv({loadSchema: loadSchema})\n\najv.compileAsync(schema).then(function (validate) {\n var valid = validate(data)\n // ...\n})\n\nfunction loadSchema(uri) {\n return request.json(uri).then(function (res) {\n if (res.statusCode >= 400) throw new Error(\"Loading error: \" + res.statusCode)\n return res.body\n })\n}\n```\n\n**Please note**: [Option](#options) `missingRefs` should NOT be set to `\"ignore\"` or `\"fail\"` for asynchronous compilation to work.\n\n## Asynchronous validation\n\nExample in Node.js REPL: https://runkit.com/esp/ajv-asynchronous-validation\n\nYou can define formats and keywords that perform validation asynchronously by accessing database or some other service. You should add `async: true` in the keyword or format definition (see [addFormat](#api-addformat), [addKeyword](#api-addkeyword) and [User-defined keywords](user-defined-keywords)).\n\nIf your schema uses asynchronous formats/keywords or refers to some schema that contains them it should have `\"$async\": true` keyword so that Ajv can compile it correctly. If asynchronous format/keyword or reference to asynchronous schema is used in the schema without `$async` keyword Ajv will throw an exception during schema compilation.\n\n**Please note**: all asynchronous subschemas that are referenced from the current or other schemas should have `\"$async\": true` keyword as well, otherwise the schema compilation will fail.\n\nValidation function for an asynchronous format/keyword should return a promise that resolves with `true` or `false` (or rejects with `new Ajv.ValidationError(errors)` if you want to return errors from the keyword function).\n\nAjv compiles asynchronous schemas to [async functions](http://tc39.github.io/ecmascript-asyncawait/). Async functions are supported in Node.js 7+ and all modern browsers. You can supply a transpiler as a function via `processCode` option. See [Options](#options).\n\nThe compiled validation function has `$async: true` property (if the schema is asynchronous), so you can differentiate these functions if you are using both synchronous and asynchronous schemas.\n\nValidation result will be a promise that resolves with validated data or rejects with an exception `Ajv.ValidationError` that contains the array of validation errors in `errors` property.\n\nExample:\n\n```javascript\nconst ajv = new Ajv()\n\najv.addKeyword({\n keyword: \"idExists\"\n async: true,\n type: \"number\",\n validate: checkIdExists,\n})\n\nfunction checkIdExists(schema, data) {\n return knex(schema.table)\n .select(\"id\")\n .where(\"id\", data)\n .then(function (rows) {\n return !!rows.length // true if record is found\n })\n}\n\nvar schema = {\n $async: true,\n properties: {\n userId: {\n type: \"integer\",\n idExists: {table: \"users\"},\n },\n postId: {\n type: \"integer\",\n idExists: {table: \"posts\"},\n },\n },\n}\n\nvar validate = ajv.compile(schema)\n\nvalidate({userId: 1, postId: 19})\n .then(function (data) {\n console.log(\"Data is valid\", data) // { userId: 1, postId: 19 }\n })\n .catch(function (err) {\n if (!(err instanceof Ajv.ValidationError)) throw err\n // data is invalid\n console.log(\"Validation errors:\", err.errors)\n })\n```\n\n#### Using transpilers\n\n```javascript\nvar ajv = new Ajv({processCode: transpileFunc})\nvar validate = ajv.compile(schema) // transpiled es7 async function\nvalidate(data).then(successFunc).catch(errorFunc)\n```\n\nSee [Options](#options).\n\n## Security considerations\n\nJSON Schema, if properly used, can replace data sanitisation. It doesn't replace other API security considerations. It also introduces additional security aspects to consider.\n\n##### Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n##### Untrusted schemas\n\nAjv treats JSON schemas as trusted as your application code. This security model is based on the most common use case, when the schemas are static and bundled together with the application.\n\nIf your schemas are received from untrusted sources (or generated from untrusted data) there are several scenarios you need to prevent:\n\n- compiling schemas can cause stack overflow (if they are too deep)\n- compiling schemas can be slow (e.g. [#557](https://github.com/ajv-validator/ajv/issues/557))\n- validating certain data can be slow\n\nIt is difficult to predict all the scenarios, but at the very least it may help to limit the size of untrusted schemas (e.g. limit JSON string length) and also the maximum schema object depth (that can be high for relatively small JSON strings). You also may want to mitigate slow regular expressions in `pattern` and `patternProperties` keywords.\n\nRegardless the measures you take, using untrusted schemas increases security risks.\n\n##### Circular references in JavaScript objects\n\nAjv does not support schemas and validated data that have circular references in objects. See [issue #802](https://github.com/ajv-validator/ajv/issues/802).\n\nAn attempt to compile such schemas or validate such data would cause stack overflow (or will not complete in case of asynchronous validation). Depending on the parser you use, untrusted data can lead to circular references.\n\n##### Security risks of trusted schemas\n\nSome keywords in JSON Schemas can lead to very slow validation for certain data. These keywords include (but may be not limited to):\n\n- `pattern` and `format` for large strings - in some cases using `maxLength` can help mitigate it, but certain regular expressions can lead to exponential validation time even with relatively short strings (see [ReDoS attack](#redos-attack)).\n- `patternProperties` for large property names - use `propertyNames` to mitigate, but some regular expressions can have exponential evaluation time as well.\n- `uniqueItems` for large non-scalar arrays - use `maxItems` to mitigate\n\n**Please note**: The suggestions above to prevent slow validation would only work if you do NOT use `allErrors: true` in production code (using it would continue validation after validation errors).\n\nYou can validate your JSON schemas against [this meta-schema](https://github.com/ajv-validator/ajv/blob/master/lib/refs/json-schema-secure.json) to check that these recommendations are followed:\n\n```javascript\nconst isSchemaSecure = ajv.compile(require(\"ajv/lib/refs/json-schema-secure.json\"))\n\nconst schema1 = {format: \"email\"}\nisSchemaSecure(schema1) // false\n\nconst schema2 = {format: \"email\", maxLength: MAX_LENGTH}\nisSchemaSecure(schema2) // true\n```\n\n**Please note**: following all these recommendation is not a guarantee that validation of untrusted data is safe - it can still lead to some undesirable results.\n\n##### Content Security Policies (CSP)\n\nSee [Ajv and Content Security Policies (CSP)](#ajv-and-content-security-policies-csp)\n\n## ReDoS attack\n\nCertain regular expressions can lead to the exponential evaluation time even with relatively short strings.\n\nPlease assess the regular expressions you use in the schemas on their vulnerability to this attack - see [safe-regex](https://github.com/substack/safe-regex), for example.\n\n**Please note**: some formats that Ajv implements use [regular expressions](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js) that can be vulnerable to ReDoS attack, so if you use Ajv to validate data from untrusted sources **it is strongly recommended** to consider the following:\n\n- making assessment of \"format\" implementations in Ajv.\n- using `format: 'fast'` option that simplifies some of the regular expressions (although it does not guarantee that they are safe).\n- replacing format implementations provided by Ajv with your own implementations of \"format\" keyword that either uses different regular expressions or another approach to format validation. Please see [addFormat](#api-addformat) method.\n- disabling format validation by ignoring \"format\" keyword with option `format: false`\n\nWhatever mitigation you choose, please assume all formats provided by Ajv as potentially unsafe and make your own assessment of their suitability for your validation scenarios.\n\n## Filtering data\n\nWith [option `removeAdditional`](#options) (added by [andyscott](https://github.com/andyscott)) you can filter data during the validation.\n\nThis option modifies original data.\n\nExample:\n\n```javascript\nvar ajv = new Ajv({removeAdditional: true})\nvar schema = {\n additionalProperties: false,\n properties: {\n foo: {type: \"number\"},\n bar: {\n additionalProperties: {type: \"number\"},\n properties: {\n baz: {type: \"string\"},\n },\n },\n },\n}\n\nvar data = {\n foo: 0,\n additional1: 1, // will be removed; `additionalProperties` == false\n bar: {\n baz: \"abc\",\n additional2: 2, // will NOT be removed; `additionalProperties` != false\n },\n}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 0, \"bar\": { \"baz\": \"abc\", \"additional2\": 2 }\n```\n\nIf `removeAdditional` option in the example above were `\"all\"` then both `additional1` and `additional2` properties would have been removed.\n\nIf the option were `\"failing\"` then property `additional1` would have been removed regardless of its value and property `additional2` would have been removed only if its value were failing the schema in the inner `additionalProperties` (so in the example above it would have stayed because it passes the schema, but any non-number would have been removed).\n\n**Please note**: If you use `removeAdditional` option with `additionalProperties` keyword inside `anyOf`/`oneOf` keywords your validation can fail with this schema, for example:\n\n```json\n{\n \"type\": \"object\",\n \"oneOf\": [\n {\n \"properties\": {\n \"foo\": {\"type\": \"string\"}\n },\n \"required\": [\"foo\"],\n \"additionalProperties\": false\n },\n {\n \"properties\": {\n \"bar\": {\"type\": \"integer\"}\n },\n \"required\": [\"bar\"],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\nThe intention of the schema above is to allow objects with either the string property \"foo\" or the integer property \"bar\", but not with both and not with any other properties.\n\nWith the option `removeAdditional: true` the validation will pass for the object `{ \"foo\": \"abc\"}` but will fail for the object `{\"bar\": 1}`. It happens because while the first subschema in `oneOf` is validated, the property `bar` is removed because it is an additional property according to the standard (because it is not included in `properties` keyword in the same schema).\n\nWhile this behaviour is unexpected (issues [#129](https://github.com/ajv-validator/ajv/issues/129), [#134](https://github.com/ajv-validator/ajv/issues/134)), it is correct. To have the expected behaviour (both objects are allowed and additional properties are removed) the schema has to be refactored in this way:\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"foo\": {\"type\": \"string\"},\n \"bar\": {\"type\": \"integer\"}\n },\n \"additionalProperties\": false,\n \"oneOf\": [{\"required\": [\"foo\"]}, {\"required\": [\"bar\"]}]\n}\n```\n\nThe schema above is also more efficient - it will compile into a faster function.\n\n## Assigning defaults\n\nWith [option `useDefaults`](#options) Ajv will assign values from `default` keyword in the schemas of `properties` and `items` (when it is the array of schemas) to the missing properties and items.\n\nWith the option value `\"empty\"` properties and items equal to `null` or `\"\"` (empty string) will be considered missing and assigned defaults.\n\nThis option modifies original data.\n\n**Please note**: the default value is inserted in the generated validation code as a literal, so the value inserted in the data will be the deep clone of the default in the schema.\n\nExample 1 (`default` in `properties`):\n\n```javascript\nvar ajv = new Ajv({useDefaults: true})\nvar schema = {\n type: \"object\",\n properties: {\n foo: {type: \"number\"},\n bar: {type: \"string\", default: \"baz\"},\n },\n required: [\"foo\", \"bar\"],\n}\n\nvar data = {foo: 1}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 1, \"bar\": \"baz\" }\n```\n\nExample 2 (`default` in `items`):\n\n```javascript\nvar schema = {\n type: \"array\",\n items: [{type: \"number\"}, {type: \"string\", default: \"foo\"}],\n}\n\nvar data = [1]\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // [ 1, \"foo\" ]\n```\n\nWith `useDefaults` option `default` keywords throws exception during schema compilation when used in:\n\n- not in `properties` or `items` subschemas\n- in schemas inside `anyOf`, `oneOf` and `not` (see [#42](https://github.com/ajv-validator/ajv/issues/42))\n- in `if` schema\n- in schemas generated by user-defined _macro_ keywords\n\nThe strict mode option can change the behavior for these unsupported defaults (`strict: false` to ignore them, `\"log\"` to log a warning).\n\nSee [Strict mode](#strict-mode).\n\n## Coercing data types\n\nWhen you are validating user inputs all your data properties are usually strings. The option `coerceTypes` allows you to have your data types coerced to the types specified in your schema `type` keywords, both to pass the validation and to use the correctly typed data afterwards.\n\nThis option modifies original data.\n\n**Please note**: if you pass a scalar value to the validating function its type will be coerced and it will pass the validation, but the value of the variable you pass won't be updated because scalars are passed by value.\n\nExample 1:\n\n```javascript\nvar ajv = new Ajv({coerceTypes: true})\nvar schema = {\n type: \"object\",\n properties: {\n foo: {type: \"number\"},\n bar: {type: \"boolean\"},\n },\n required: [\"foo\", \"bar\"],\n}\n\nvar data = {foo: \"1\", bar: \"false\"}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 1, \"bar\": false }\n```\n\nExample 2 (array coercions):\n\n```javascript\nvar ajv = new Ajv({coerceTypes: \"array\"})\nvar schema = {\n properties: {\n foo: {type: \"array\", items: {type: \"number\"}},\n bar: {type: \"boolean\"},\n },\n}\n\nvar data = {foo: \"1\", bar: [\"false\"]}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": [1], \"bar\": false }\n```\n\nThe coercion rules, as you can see from the example, are different from JavaScript both to validate user input as expected and to have the coercion reversible (to correctly validate cases where different types are defined in subschemas of \"anyOf\" and other compound keywords).\n\nSee [Coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md) for details.\n\n## API\n\n##### new Ajv(Object options) -> Object\n\nCreate Ajv instance.\n\n##### .compile(Object schema) -> Function<Object data>\n\nGenerate validating function and cache the compiled schema for future use.\n\nValidating function returns a boolean value. This function has properties `errors` and `schema`. Errors encountered during the last validation are assigned to `errors` property (it is assigned `null` if there was no errors). `schema` property contains the reference to the original schema.\n\nThe schema passed to this method will be validated against meta-schema unless `validateSchema` option is false. If schema is invalid, an error will be thrown. See [options](#options).\n\n##### .compileAsync(Object schema [, Boolean meta][, function callback]) -> Promise\n\nAsynchronous version of `compile` method that loads missing remote schemas using asynchronous function in `options.loadSchema`. This function returns a Promise that resolves to a validation function. An optional callback passed to `compileAsync` will be called with 2 parameters: error (or null) and validating function. The returned promise will reject (and the callback will be called with an error) when:\n\n- missing schema can't be loaded (`loadSchema` returns a Promise that rejects).\n- a schema containing a missing reference is loaded, but the reference cannot be resolved.\n- schema (or some loaded/referenced schema) is invalid.\n\nThe function compiles schema and loads the first missing schema (or meta-schema) until all missing schemas are loaded.\n\nYou can asynchronously compile meta-schema by passing `true` as the second parameter.\n\nSee example in [Asynchronous compilation](#asynchronous-schema-compilation).\n\n##### .validate(Object schema|String key|String ref, data) -> Boolean\n\nValidate data using passed schema (it will be compiled and cached).\n\nInstead of the schema you can use the key that was previously passed to `addSchema`, the schema id if it was present in the schema or any previously resolved reference.\n\nValidation errors will be available in the `errors` property of Ajv instance (`null` if there were no errors).\n\n**Please note**: every time this method is called the errors are overwritten so you need to copy them to another variable if you want to use them later.\n\nIf the schema is asynchronous (has `$async` keyword on the top level) this method returns a Promise. See [Asynchronous validation](#asynchronous-validation).\n\n##### .addSchema(Array<Object>|Object schema [, String key]) -> Ajv\n\nAdd schema(s) to validator instance. This method does not compile schemas (but it still validates them). Because of that dependencies can be added in any order and circular dependencies are supported. It also prevents unnecessary compilation of schemas that are containers for other schemas but not used as a whole.\n\nArray of schemas can be passed (schemas should have ids), the second parameter will be ignored.\n\nKey can be passed that can be used to reference the schema and will be used as the schema id if there is no id inside the schema. If the key is not passed, the schema id will be used as the key.\n\nOnce the schema is added, it (and all the references inside it) can be referenced in other schemas and used to validate data.\n\nAlthough `addSchema` does not compile schemas, explicit compilation is not required - the schema will be compiled when it is used first time.\n\nBy default the schema is validated against meta-schema before it is added, and if the schema does not pass validation the exception is thrown. This behaviour is controlled by `validateSchema` option.\n\n**Please note**: Ajv uses the [method chaining syntax](https://en.wikipedia.org/wiki/Method_chaining) for all methods with the prefix `add*` and `remove*`.\nThis allows you to do nice things like the following.\n\n```javascript\nvar validate = new Ajv().addSchema(schema).addFormat(name, regex).getSchema(uri)\n```\n\n##### .addMetaSchema(Array<Object>|Object schema [, String key]) -> Ajv\n\nAdds meta schema(s) that can be used to validate other schemas. That function should be used instead of `addSchema` because there may be instance options that would compile a meta schema incorrectly (at the moment it is `removeAdditional` option).\n\nThere is no need to explicitly add draft-07 meta schema (http://json-schema.org/draft-07/schema) - it is added by default, unless option `meta` is set to `false`. You only need to use it if you have a changed meta-schema that you want to use to validate your schemas. See `validateSchema`.\n\n##### .validateSchema(Object schema) -> Boolean\n\nValidates schema. This method should be used to validate schemas rather than `validate` due to the inconsistency of `uri` format in JSON Schema standard.\n\nBy default this method is called automatically when the schema is added, so you rarely need to use it directly.\n\nIf schema doesn't have `$schema` property, it is validated against draft 6 meta-schema (option `meta` should not be false).\n\nIf schema has `$schema` property, then the schema with this id (that should be previously added) is used to validate passed schema.\n\nErrors will be available at `ajv.errors`.\n\n##### .getSchema(String key) -> Function<Object data>\n\nRetrieve compiled schema previously added with `addSchema` by the key passed to `addSchema` or by its full reference (id). The returned validating function has `schema` property with the reference to the original schema.\n\n##### .removeSchema([Object schema|String key|String ref|RegExp pattern]) -> Ajv\n\nRemove added/cached schema. Even if schema is referenced by other schemas it can be safely removed as dependent schemas have local references.\n\nSchema can be removed using:\n\n- key passed to `addSchema`\n- it's full reference (id)\n- RegExp that should match schema id or key (meta-schemas won't be removed)\n- actual schema object that will be stable-stringified to remove schema from cache\n\nIf no parameter is passed all schemas but meta-schemas will be removed and the cache will be cleared.\n\n##### .addFormat(String name, String|RegExp|Function|Object format) -> Ajv\n\nAdd format to validate strings or numbers.\n\nStrings are converted to RegExp.\n\nFunction should return validation result as `true` or `false`.\n\nIf object is passed it should have properties `validate`, `compare` and `async`:\n\n- _validate_: a string, RegExp or a function as described above.\n- _compare_: an optional comparison function that accepts two strings and compares them according to the format meaning. This function is used with keywords `formatMaximum`/`formatMinimum` (defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package). It should return `1` if the first value is bigger than the second value, `-1` if it is smaller and `0` if it is equal.\n- _async_: an optional `true` value if `validate` is an asynchronous function; in this case it should return a promise that resolves with a value `true` or `false`.\n- _type_: an optional type of data that the format applies to. It can be `\"string\"` (default) or `\"number\"` (see https://github.com/ajv-validator/ajv/issues/291#issuecomment-259923858). If the type of data is different, the validation will pass.\n\nFormats can be also added via `formats` option.\n\n##### .addKeyword(Object definition) -> Ajv\n\nAdd validation keyword to Ajv instance.\n\nKeyword should be different from all standard JSON Schema keywords and different from previously defined keywords. There is no way to redefine keywords or to remove keyword definition from the instance.\n\nKeyword must start with a letter, `_` or `$`, and may continue with letters, numbers, `_`, `$`, or `-`.\nIt is recommended to use an application-specific prefix for keywords to avoid current and future name collisions.\n\nExample Keywords:\n\n- `\"xyz-example\"`: valid, and uses prefix for the xyz project to avoid name collisions.\n- `\"example\"`: valid, but not recommended as it could collide with future versions of JSON Schema etc.\n- `\"3-example\"`: invalid as numbers are not allowed to be the first character in a keyword\n\nKeyword definition is an object with the following properties:\n\n- _keyword_: keyword name string\n- _type_: optional string or array of strings with data type(s) that the keyword applies to. If not present, the keyword will apply to all types.\n- _schemaType_: optional string or array of strings with the required schema type\n- _code_: function to generate code, used for all pre-defined keywords\n- _validate_: validating function\n- _compile_: compiling function\n- _macro_: macro function\n- _error_: optional error definition object\n- _schema_: an optional `false` value used with \"validate\" keyword to not pass schema\n- _metaSchema_: an optional meta-schema for keyword schema\n- _dependencies_: an optional list of properties that must be present in the parent schema - it will be checked during schema compilation\n- _implements_: an optional list of keyword names to reserve that this keyword implements\n- _modifying_: `true` MUST be passed if keyword modifies data\n- _valid_: pass `true`/`false` to pre-define validation result, the result returned from validation function will be ignored. This option cannot be used with macro keywords.\n- _\\$data_: an optional `true` value to support [\\$data reference](#data-reference) as the value of keyword. The reference will be resolved at validation time. If the keyword has meta-schema it would be extended to allow $data and it will be used to validate the resolved value. Supporting $data reference requires that keyword has _code_ or _validate_ function (the latter can be used in addition to _compile_ or _macro_).\n- _\\$dataError_: optional error definition for invalid \\$data schema\n- _async_: an optional `true` value if the validation function is asynchronous (whether it is compiled or passed in _validate_ property); in this case it should return a promise that resolves with a value `true` or `false`. This option is ignored in case of \"macro\" and \"inline\" keywords.\n- _errors_: an optional boolean or string `\"full\"` indicating whether keyword returns errors. If this property is not set Ajv will determine if the errors were set in case of failed validation.\n\n_compile_, _macro_ and _code_ are mutually exclusive, only one should be used at a time. _validate_ can be used separately or in addition to _compile_ or _macro_ to support \\$data reference.\n\n**Please note**: If the keyword is validating data type that is different from the type(s) in its definition, the validation function will not be called (and expanded macro will not be used), so there is no need to check for data type inside validation function or inside schema returned by macro function (unless you want to enforce a specific type and for some reason do not want to use a separate `type` keyword for that). In the same way as standard keywords work, if the keyword does not apply to the data type being validated, the validation of this keyword will succeed.\n\nSee [User defined keywords](#user-defined-keywords) for more details.\n\n##### .getKeyword(String keyword) -> Object|Boolean\n\nReturns keyword definition, `false` if the keyword is unknown.\n\n##### .removeKeyword(String keyword) -> Ajv\n\nRemoves added or pre-defined keyword so you can redefine them.\n\nWhile this method can be used to extend pre-defined keywords, it can also be used to completely change their meaning - it may lead to unexpected results.\n\n**Please note**: schemas compiled before the keyword is removed will continue to work without changes. To recompile schemas use `removeSchema` method and compile them again.\n\n##### .errorsText([Array<Object> errors [, Object options]]) -> String\n\nReturns the text with all errors in a String.\n\nOptions can have properties `separator` (string used to separate errors, \", \" by default) and `dataVar` (the variable name that dataPaths are prefixed with, \"data\" by default).\n\n## Options\n\nDefaults:\n\n```javascript\n{\n // strict mode options\n strict: true,\n allowMatchingProperties: false,\n // validation and reporting options:\n $data: false,\n allErrors: false,\n verbose: false,\n $comment: false,\n format: true,\n formats: {},\n unknownFormats: true,\n schemas: {},\n logger: undefined,\n // referenced schema options:\n missingRefs: true,\n extendRefs: \"ignore\", // recommended 'fail'\n loadSchema: undefined, // function(uri: string): Promise {}\n // options to modify validated data:\n removeAdditional: false,\n useDefaults: false,\n coerceTypes: false,\n // advanced options:\n meta: true,\n validateSchema: true,\n addUsedSchema: true,\n inlineRefs: true,\n passContext: false,\n loopRequired: Infinity,\n loopEnum: Infinity,\n ownProperties: false,\n multipleOfPrecision: false,\n messages: true,\n sourceCode: false,\n processCode: undefined, // function (str: string, schema: object): string {}\n cache: new Cache,\n serialize: undefined\n jsPropertySyntax: false, // deprecated\n}\n```\n\n##### Strict mode options\n\n- _strict_: By default Ajv executes in strict mode, that is designed to prevent any unexpected behaviours or silently ignored mistakes in schemas (see [Strict Mode](#strict-mode) for more details). It does not change any validation results, but it makes some schemas invalid that would be otherwise valid according to JSON Schema specification. Option values:\n - `true` (default) - use strict mode and throw an exception when any strict mode restrictions is violated.\n - `\"log\"` - log warning when any strict mode restriction is violated.\n - `false` - ignore any strict mode restriction.\n- _allowMatchingProperties_: pass true to allow overlap between \"properties\" and \"patternProperties\". See [Strict Mode](#strict-mode).\n\n##### Validation and reporting options\n\n- _\\$data_: support [\\$data references](#data-reference). Draft 6 meta-schema that is added by default will be extended to allow them. If you want to use another meta-schema you need to use $dataMetaSchema method to add support for $data reference. See [API](#api).\n- _allErrors_: check all rules collecting all errors. Default is to return after the first error.\n- _verbose_: include the reference to the part of the schema (`schema` and `parentSchema`) and validated data in errors (false by default).\n- _\\$comment_ (NEW in Ajv version 6.0): log or pass the value of `$comment` keyword to a function. Option values:\n - `false` (default): ignore \\$comment keyword.\n - `true`: log the keyword value to console.\n - function: pass the keyword value, its schema path and root schema to the specified function\n- _format_: formats validation mode. Option values:\n - `true` (default) - validate added formats (see [Formats](#formats)).\n - `false` - ignore all format keywords.\n- _formats_: an object with format definitions. Keys and values will be passed to `addFormat` method.\n- _keywords_: an array of keyword definitions or strings. Values will be passed to `addKeyword` method.\n- _unknownFormats_: handling of unknown formats. Option values:\n - `true` (default) - if an unknown format is encountered the exception is thrown during schema compilation. If `format` keyword value is [\\$data reference](#data-reference) and it is unknown the validation will fail.\n - `[String]` - an array of unknown format names that will be ignored. This option can be used to allow usage of third party schemas with format(s) for which you don't have definitions, but still fail if another unknown format is used. If `format` keyword value is [\\$data reference](#data-reference) and it is not in this array the validation will fail.\n - `\"ignore\"` - to log warning during schema compilation and always pass validation (the default behaviour in versions before 5.0.0). This option is not recommended, as it allows to mistype format name and it won't be validated without any error message. This behaviour is required by JSON Schema specification.\n- _schemas_: an array or object of schemas that will be added to the instance. In case you pass the array the schemas must have IDs in them. When the object is passed the method `addSchema(value, key)` will be called for each schema in this object.\n- _logger_: sets the logging method. Default is the global `console` object that should have methods `log`, `warn` and `error`. See [Error logging](#error-logging). Option values:\n - logger instance - it should have methods `log`, `warn` and `error`. If any of these methods is missing an exception will be thrown.\n - `false` - logging is disabled.\n\n##### Referenced schema options\n\n- _missingRefs_: handling of missing referenced schemas. Option values:\n - `true` (default) - if the reference cannot be resolved during compilation the exception is thrown. The thrown error has properties `missingRef` (with hash fragment) and `missingSchema` (without it). Both properties are resolved relative to the current base id (usually schema id, unless it was substituted).\n - `\"ignore\"` - to log error during compilation and always pass validation.\n - `\"fail\"` - to log error and successfully compile schema but fail validation if this rule is checked.\n- _extendRefs_: validation of other keywords when `$ref` is present in the schema. Option values:\n - `\"ignore\"` (default) - when `$ref` is used other keywords are ignored (as per [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03#section-3) standard). A warning will be logged during the schema compilation.\n - `\"fail\"` (recommended) - if other validation keywords are used together with `$ref` the exception will be thrown when the schema is compiled. This option is recommended to make sure schema has no keywords that are ignored, which can be confusing.\n - `true` - validate all keywords in the schemas with `$ref` (the default behaviour in versions before 5.0.0).\n- _loadSchema_: asynchronous function that will be used to load remote schemas when `compileAsync` [method](#api-compileAsync) is used and some reference is missing (option `missingRefs` should NOT be 'fail' or 'ignore'). This function should accept remote schema uri as a parameter and return a Promise that resolves to a schema. See example in [Asynchronous compilation](#asynchronous-schema-compilation).\n\n##### Options to modify validated data\n\n- _removeAdditional_: remove additional properties - see example in [Filtering data](#filtering-data). This option is not used if schema is added with `addMetaSchema` method. Option values:\n - `false` (default) - not to remove additional properties\n - `\"all\"` - all additional properties are removed, regardless of `additionalProperties` keyword in schema (and no validation is made for them).\n - `true` - only additional properties with `additionalProperties` keyword equal to `false` are removed.\n - `\"failing\"` - additional properties that fail schema validation will be removed (where `additionalProperties` keyword is `false` or schema).\n- _useDefaults_: replace missing or undefined properties and items with the values from corresponding `default` keywords. Default behaviour is to ignore `default` keywords. This option is not used if schema is added with `addMetaSchema` method. See examples in [Assigning defaults](#assigning-defaults). Option values:\n - `false` (default) - do not use defaults\n - `true` - insert defaults by value (object literal is used).\n - `\"empty\"` - in addition to missing or undefined, use defaults for properties and items that are equal to `null` or `\"\"` (an empty string).\n- _coerceTypes_: change data type of data to match `type` keyword. See the example in [Coercing data types](#coercing-data-types) and [coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md). Option values:\n - `false` (default) - no type coercion.\n - `true` - coerce scalar data types.\n - `\"array\"` - in addition to coercions between scalar types, coerce scalar data to an array with one element and vice versa (as required by the schema).\n\n##### Advanced options\n\n- _meta_: add [meta-schema](http://json-schema.org/documentation.html) so it can be used by other schemas (true by default). If an object is passed, it will be used as the default meta-schema for schemas that have no `$schema` keyword. This default meta-schema MUST have `$schema` keyword.\n- _validateSchema_: validate added/compiled schemas against meta-schema (true by default). `$schema` property in the schema can be http://json-schema.org/draft-07/schema or absent (draft-07 meta-schema will be used) or can be a reference to the schema previously added with `addMetaSchema` method. Option values:\n - `true` (default) - if the validation fails, throw the exception.\n - `\"log\"` - if the validation fails, log error.\n - `false` - skip schema validation.\n- _addUsedSchema_: by default methods `compile` and `validate` add schemas to the instance if they have `$id` (or `id`) property that doesn't start with \"#\". If `$id` is present and it is not unique the exception will be thrown. Set this option to `false` to skip adding schemas to the instance and the `$id` uniqueness check when these methods are used. This option does not affect `addSchema` method.\n- _inlineRefs_: Affects compilation of referenced schemas. Option values:\n - `true` (default) - the referenced schemas that don't have refs in them are inlined, regardless of their size - that substantially improves performance at the cost of the bigger size of compiled schema functions.\n - `false` - to not inline referenced schemas (they will be compiled as separate functions).\n - integer number - to limit the maximum number of keywords of the schema that will be inlined.\n- _passContext_: pass validation context to _compile_ and _validate_ keyword functions. If this option is `true` and you pass some context to the compiled validation function with `validate.call(context, data)`, the `context` will be available as `this` in your keywords. By default `this` is Ajv instance.\n- _loopRequired_: by default `required` keyword is compiled into a single expression (or a sequence of statements in `allErrors` mode). In case of a very large number of properties in this keyword it may result in a very big validation function. Pass integer to set the number of properties above which `required` keyword will be validated in a loop - smaller validation function size but also worse performance.\n- _loopEnum_: by default `enum` keyword is compiled into a single expression. In case of a very large number of allowed values it may result in a large validation function. Pass integer to set the number of values above which `enum` keyword will be validated in a loop.\n- _ownProperties_: by default Ajv iterates over all enumerable object properties; when this option is `true` only own enumerable object properties (i.e. found directly on the object rather than on its prototype) are iterated. Contributed by @mbroadst.\n- _multipleOfPrecision_: by default `multipleOf` keyword is validated by comparing the result of division with parseInt() of that result. It works for dividers that are bigger than 1. For small dividers such as 0.01 the result of the division is usually not integer (even when it should be integer, see issue [#84](https://github.com/ajv-validator/ajv/issues/84)). If you need to use fractional dividers set this option to some positive integer N to have `multipleOf` validated using this formula: `Math.abs(Math.round(division) - division) < 1e-N` (it is slower but allows for float arithmetics deviations).\n- _messages_: Include human-readable messages in errors. `true` by default. `false` can be passed when messages are generated outside of Ajv code (e.g. with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n)).\n- _sourceCode_: add `sourceCode` property to validating function (for debugging; this code can be different from the result of toString call).\n- _processCode_: an optional function to process generated code before it is passed to Function constructor. It can be used to either beautify (the validating function is generated without line-breaks) or to transpile code.\n- _cache_: an optional instance of cache to store compiled schemas using stable-stringified schema as a key. For example, set-associative cache [sacjs](https://github.com/epoberezkin/sacjs) can be used. If not passed then a simple hash is used which is good enough for the common use case (a limited number of statically defined schemas). Cache should have methods `put(key, value)`, `get(key)`, `del(key)` and `clear()`.\n- _serialize_: an optional function to serialize schema to cache key. Pass `false` to use schema itself as a key (e.g., if WeakMap used as a cache). By default [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used.\n- _jsPropertySyntax_ (deprecated) - set to `true` to report `dataPath` in errors as in v6, using JavaScript property syntax (e.g., `\".prop[1].subProp\"`). By default `dataPath` in errors is reported as JSON pointer. This option is added for backward compatibility and is not recommended - this format is difficult to parse even in JS code.\n\n## Validation errors\n\nIn case of validation failure, Ajv assigns the array of errors to `errors` property of validation function (or to `errors` property of Ajv instance when `validate` or `validateSchema` methods were called). In case of [asynchronous validation](#asynchronous-validation), the returned promise is rejected with exception `Ajv.ValidationError` that has `errors` property.\n\n### Error objects\n\nEach error is an object with the following properties:\n\n- _keyword_: validation keyword.\n- _dataPath_: JSON pointer to the part of the data that was validated (e.g., `\"/prop/1/subProp\"`).\n- _schemaPath_: the path (JSON-pointer as a URI fragment) to the schema of the keyword that failed validation.\n- _params_: the object with the additional information about error that can be used to generate error messages (e.g., using [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package). See below for parameters set by all keywords.\n- _message_: the standard error message (can be excluded with option `messages` set to false).\n- _schema_: the schema of the keyword (added with `verbose` option).\n- _parentSchema_: the schema containing the keyword (added with `verbose` option)\n- _data_: the data validated by the keyword (added with `verbose` option).\n\n**Please note**: `propertyNames` keyword schema validation errors have an additional property `propertyName`, `dataPath` points to the object. After schema validation for each property name, if it is invalid an additional error is added with the property `keyword` equal to `\"propertyNames\"`.\n\n### Error parameters\n\nProperties of `params` object in errors depend on the keyword that failed validation.\n\n- `maxItems`, `minItems`, `maxLength`, `minLength`, `maxProperties`, `minProperties` - property `limit` (number, the schema of the keyword).\n- `additionalItems` - property `limit` (the maximum number of allowed items in case when `items` keyword is an array of schemas and `additionalItems` is false).\n- `additionalProperties` - property `additionalProperty` (the property not used in `properties` and `patternProperties` keywords).\n- `dependencies` - properties:\n - `property` (dependent property),\n - `missingProperty` (required missing dependency - only the first one is reported currently)\n - `deps` (required dependencies, comma separated list as a string),\n - `depsCount` (the number of required dependencies).\n- `format` - property `format` (the schema of the keyword).\n- `maximum`, `minimum` - properties:\n - `limit` (number, the schema of the keyword),\n - `exclusive` (boolean, the schema of `exclusiveMaximum` or `exclusiveMinimum`),\n - `comparison` (string, comparison operation to compare the data to the limit, with the data on the left and the limit on the right; can be \"<\", \"<=\", \">\", \">=\")\n- `multipleOf` - property `multipleOf` (the schema of the keyword)\n- `pattern` - property `pattern` (the schema of the keyword)\n- `required` - property `missingProperty` (required property that is missing).\n- `propertyNames` - property `propertyName` (an invalid property name).\n- `patternRequired` (in ajv-keywords) - property `missingPattern` (required pattern that did not match any property).\n- `type` - property `type` (required type(s), a string, can be a comma-separated list)\n- `uniqueItems` - properties `i` and `j` (indices of duplicate items).\n- `const` - property `allowedValue` pointing to the value (the schema of the keyword).\n- `enum` - property `allowedValues` pointing to the array of values (the schema of the keyword).\n- `$ref` - property `ref` with the referenced schema URI.\n- `oneOf` - property `passingSchemas` (array of indices of passing schemas, null if no schema passes).\n\nUser-defined keywords can define other keyword parameters.\n\n### Error logging\n\nA logger instance can be passed via `logger` option to Ajv constructor. The use of other logging packages is supported as long as the package or its associated wrapper exposes the required methods. If any of the required methods are missing an exception will be thrown.\n\n- **Required Methods**: `log`, `warn`, `error`\n\n```javascript\nconst otherLogger = new OtherLogger()\nconst ajv = new Ajv({\n logger: {\n log: console.log.bind(console),\n warn: function warn() {\n otherLogger.logWarn.apply(otherLogger, arguments)\n },\n error: function error() {\n otherLogger.logError.apply(otherLogger, arguments)\n console.error.apply(console, arguments)\n },\n },\n})\n```\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-async](https://github.com/ajv-validator/ajv-async) - plugin to configure async validation mode (DEPRECATED)\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](https://github.com/ajv-validator/ajv/blob/master/CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n[Version 5.0.0](https://github.com/ajv-validator/ajv/releases/tag/5.0.0).\n\n[Version 4.0.0](https://github.com/ajv-validator/ajv/releases/tag/4.0.0).\n\n[Version 3.0.0](https://github.com/ajv-validator/ajv/releases/tag/3.0.0).\n\n[Version 2.0.0](https://github.com/ajv-validator/ajv/releases/tag/2.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](https://github.com/ajv-validator/ajv/blob/master/CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](https://github.com/ajv-validator/ajv/blob/master/LICENSE)\n","readmeFilename":"README.md","gitHead":"80f6f5dcfd83774e585a7c85f4173e7645d60037","_id":"ajv@7.0.0-alpha.0","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-Zbe5fRhojt5dN8shJ2cPJftrvJBnrRvPZEw+NQT72XX/yZ81kDc52hGqI0Kw7VBaWlyUPAJTdkAG/Hx2hSpXkA==","shasum":"4534c309d621a570dd4644b46129227e533516c8","tarball":"http://localhost:4260/ajv/ajv-7.0.0-alpha.0.tgz","fileCount":250,"unpackedSize":594593,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYNaRCRA9TVsSAnZWagAA+D4P/0R0OufSH5U+ZirtwhTE\nQtULT2vbshO0+bNcg8MZ3dDtctLGSEpagX1QFhmY5PZ79IW7LZgZlj9vgYa2\nJ2jj7kDERruX7L0GsDCkw+coYf7VDZCwKR7y1uzaXnbDnJ0jvaCRg7hKLsHg\nEhH8ywuwM+f/KQHE0+zk7vFjwHz+nfrnnR5kHRknn3dOeiV6p+wbnAkMJdCC\nCpxjAfBXQFTpvTgjGfzY856S0IEW7WOwR9kw6EWuHvM1lVtOgyxJLx2WMMIW\nu88lq3ev7zk3j4osYZrjfoZNCya741SvxP4GsADiVCkHLPxY5uonMhMnTgJ2\nmND/L8+2KYzPN1FRl4Pe57hAFlPy+CcWchX/MaFowdpUX4fvEtyAtB30BsyF\n5a9eoCeNiQB3DosbXB3GIj6sLH+/UMOe13PvEIJUL9GwmO73fn3yHsQgL5q/\nYEosX4qdPtuKvYAmMtrbxw67HUcFH9/UchPgnsA4p4icOAm9v4LpV2/3/Sou\nKJDpU/jhJbvddGKP3sJbuEwhz1YYT5DgWanycz3Dd1aFexkQ1hy0Hcobd8Hu\ntb0yyjEt7lyD+8h9hJszvDrnCKv5ADPkpoWIMh4Zw6Lu2gk3g3OIwU9bYMyG\nxPyLBdP1KzAK/TkQf65TtBvwu1o4xhW8kPHK17T19grA1aCSDgCs9uDePHTo\nGke3\r\n=vtbO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCPFud4TU8UWm1DMbGfRN1EY/MfXbvL0sj2KzZBd7HTxQIhAM7NMl3KVu+HIOEPJ4yApDjZTO1qGyx+9lGV6qnq7e6N"}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-alpha.0_1600181905151_0.45655946955055704"},"_hasShrinkwrap":false},"7.0.0-alpha.1":{"name":"ajv","version":"7.0.0-alpha.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint 'lib/**/*.ts' 'spec/**/*.*s' scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write './**/*.{md,json,yaml,js,ts}'","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","fast-json-stable-stringify":"^2.0.0","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.3.0","browserify":"^16.2.0","chai":"^4.0.1","coveralls":"^3.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Using version 6\n\n[JSON Schema draft-07](http://json-schema.org/latest/json-schema-validation.html) is published.\n\n[Ajv version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0) that supports draft-07 is released. It may require either migrating your schemas or updating your code (to continue using draft-04 and v5 schemas, draft-06 schemas will be supported without changes).\n\n**Please note**: To use Ajv with draft-06 schemas you need to explicitly add the meta-schema to the validator instance:\n\n```javascript\najv.addMetaSchema(require(\"ajv/lib/refs/json-schema-draft-06.json\"))\n```\n\n**Please note**: use Ajv v6 if you need draft-04 support - v7 does NOT support it.\n\n## Contents\n\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#getting-started)\n- [Frequently Asked Questions](https://github.com/ajv-validator/ajv/blob/master/FAQ.md)\n- [Using in browser](#using-in-browser)\n - [Ajv and Content Security Policies (CSP)](#ajv-and-content-security-policies-csp)\n- [Command line interface](#command-line-interface)\n- Validation\n - [Strict mode](#strict-mode)\n - [Keywords](#validation-keywords)\n - [Annotation keywords](#annotation-keywords)\n - [Formats](#formats)\n - [Combining schemas with \\$ref](#ref)\n - [\\$data reference](#data-reference)\n - NEW: [$merge and $patch keywords](#merge-and-patch-keywords)\n - [User-defined keywords](#user-defined-keywords)\n - [Asynchronous schema compilation](#asynchronous-schema-compilation)\n - [Asynchronous validation](#asynchronous-validation)\n- [Security considerations](#security-considerations)\n - [Security contact](#security-contact)\n - [Untrusted schemas](#untrusted-schemas)\n - [Circular references in objects](#circular-references-in-javascript-objects)\n - [Trusted schemas](#security-risks-of-trusted-schemas)\n - [ReDoS attack](#redos-attack)\n- Modifying data during validation\n - [Filtering data](#filtering-data)\n - [Assigning defaults](#assigning-defaults)\n - [Coercing data types](#coercing-data-types)\n- API\n - [Methods](#api)\n - [Options](#options)\n - [Validation errors](#validation-errors)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, License](#open-source-software-support)\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](#options)\n- [error messages with parameters](#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [filtering data](#filtering-data) from additional properties\n- [assigning defaults](#assigning-defaults) to missing properties and items\n- [coercing data](#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- keywords `switch`, `patternRequired`, `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum` from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nThe fastest validation call:\n\n```javascript\n// Node.js require:\nvar Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nvar ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nvar validate = ajv.compile(schema)\nvar valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nor with less code\n\n```javascript\n// ...\nvar valid = ajv.validate(schema, data)\nif (!valid) console.log(ajv.errors)\n// ...\n```\n\nor\n\n```javascript\n// ...\nvar valid = ajv.addSchema(schema, \"mySchema\").validate(\"mySchema\", data)\nif (!valid) console.log(ajv.errorsText())\n// ...\n```\n\nSee [API](#api) and [Options](#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema serialized with [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](#validation-errors)\n\n**Note for TypeScript users**: `ajv` provides its own TypeScript declarations\nout of the box, so you don't need to install the deprecated `@types/ajv`\nmodule.\n\n## Using in browser\n\nYou can require Ajv directly from the code you browserify - in this case Ajv will be a part of your bundle.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\nAjv is tested with these browsers:\n\n[![Sauce Test Status](https://saucelabs.com/browser-matrix/epoberezkin.svg)](https://saucelabs.com/u/epoberezkin)\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n### Ajv and Content Security Policies (CSP)\n\nIf you're using Ajv to compile a schema (the typical use) in a browser document that is loaded with a Content Security Policy (CSP), that policy will require a `script-src` directive that includes the value `'unsafe-eval'`.\n:warning: NOTE, however, that `unsafe-eval` is NOT recommended in a secure CSP[[1]](https://developer.chrome.com/extensions/contentSecurityPolicy#relaxing-eval), as it has the potential to open the document to cross-site scripting (XSS) attacks.\n\nIn order to make use of Ajv without easing your CSP, you can [pre-compile a schema using the CLI](https://github.com/ajv-validator/ajv-cli#compile-schemas). This will transpile the schema JSON into a JavaScript file that exports a `validate` function that works simlarly to a schema compiled at runtime.\n\nNote that pre-compilation of schemas is performed using [ajv-pack](https://github.com/ajv-validator/ajv-pack) and there are [some limitations to the schema features it can compile](https://github.com/ajv-validator/ajv-pack#limitations). A successfully pre-compiled schema is equivalent to the same schema compiled at runtime.\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Strict mode\n\nStrict mode intends to prevent any unexpected behaviours or silently ignored mistakes in user schemas. It does not change any validation results compared with JSON Schema specification, but it makes some schemas invalid and throws exception or logs warning (with `strict: \"log\"` option) in case any restriction is violated.\n\nThe strict mode restrictions are below. To disable these restrictions use option `strict: false`.\n\n##### Prohibit unknown keywords\n\nJSON Schema [section 6.5](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-6.5) requires to ignore unknown keywords. The motivation is to increase cross-platform portability of schemas, so that implementations that do not support certain keywords can still do partial validation.\n\nThe problems with this approach are:\n\n- Different validation results with the same schema and data, leading to bugs and inconsistent behaviours.\n- Typos in keywords resulting in keywords being quietly ignored, requiring extensive test coverage of schemas to avoid these mistakes.\n\nBy default Ajv fails schema compilation when unknown keywords are used. Users can explicitly define the keywords that should be allowed and ignored:\n\n```javascript\najv.addKeyword(\"allowedKeyword\")\n```\n\nor\n\n```javascript\najv.addVocabulary([\"allowed1\", \"allowed2\"])\n```\n\n#### Prohibit ignored \"additionalItems\" keyword\n\nJSON Schema section [9.3.1.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2) requires to ignore \"additionalItems\" keyword if \"items\" keyword is absent. This is inconsistent with the interaction of \"additionalProperties\" and \"properties\", and may cause unexpected results.\n\nBy default Ajv fails schema compilation when \"additionalItems\" is used without \"items.\n\n#### Prohibit ignored \"if\", \"then\", \"else\" keywords\n\nJSON Schema section [9.2.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2) requires to ignore \"if\" (only annotations are collected) if both \"then\" and \"else\" are absent, and ignore \"then\"/\"else\" if \"if\" is absent.\n\nBy default Ajv fails schema compilation in these cases.\n\n#### Prohibit overlap between \"properties\" and \"patternProperties\" keywords\n\nThe expectation of users (see #196, #286) is that \"patternProperties\" only apply to properties not already defined in \"properties\" keyword, but JSON Schema section [9.3.2](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2) defines these two keywords as independent. It means that to some properties two subschemas can be applied - one defined in \"properties\" keyword and another defined in \"patternProperties\" for the pattern matching this property.\n\nBy default Ajv fails schema compilation if a pattern in \"patternProperties\" matches a property in \"properties\" in the same schema.\n\nIn addition to allowing such patterns by using option `strict: false`, there is an option `allowMatchingProperties: true` to only allow this case without disabling other strict mode restrictions - there are some rare cases when this is necessary.\n\nTo reiterate, neither this nor other strict mode restrictions change the validation results - they only restrict which schemas are valid.\n\n#### Prohibit unknown formats\n\nTODO\n\nThis will supercede unknownFormats option.\n\n#### Prohibit ignored defaults\n\nWith `useDefaults` option Ajv modifies validated data by assigning defaults from the schema, but there are different limitations when the defaults can be ignored (see [Assigning defaults](#assigning-defaults)). In strict mode Ajv fails schema compilation if such defaults are used in the schema.\n\n#### Number validation\n\nStrict mode also affects number validation. By default Ajv fails `{\"type\": \"number\"}` (or `\"integer\"`) validation for `Infinity` and `NaN`.\n\n## Validation keywords\n\nAjv supports all validation keywords from draft-07 of JSON Schema standard:\n\n- [type](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#type)\n- [for numbers](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-numbers) - maximum, minimum, exclusiveMaximum, exclusiveMinimum, multipleOf\n- [for strings](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-strings) - maxLength, minLength, pattern, format\n- [for arrays](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-arrays) - maxItems, minItems, uniqueItems, items, additionalItems, [contains](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#contains)\n- [for objects](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-objects) - maxProperties, minProperties, required, properties, patternProperties, additionalProperties, dependencies, [propertyNames](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#propertynames)\n- [for all types](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#keywords-for-all-types) - enum, [const](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#const)\n- [compound keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#compound-keywords) - not, oneOf, anyOf, allOf, [if/then/else](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#ifthenelse)\n\nWith [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package Ajv also supports validation keywords from [JSON Schema extension proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals) for JSON Schema standard:\n\n- [patternRequired](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#patternrequired-proposed) - like `required` but with patterns that some property should match.\n- [formatMaximum, formatMinimum, formatExclusiveMaximum, formatExclusiveMinimum](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md#formatmaximum--formatminimum-and-exclusiveformatmaximum--exclusiveformatminimum-proposed) - setting limits for date, time, etc.\n\nSee [JSON Schema validation keywords](https://github.com/ajv-validator/ajv/blob/master/KEYWORDS.md) for more details.\n\n## Annotation keywords\n\nJSON Schema specification defines several annotation keywords that describe schema itself but do not perform any validation.\n\n- `title` and `description`: information about the data represented by that schema\n- `$comment` (NEW in draft-07): information for developers. With option `$comment` Ajv logs or passes the comment string to the user-supplied function. See [Options](#options).\n- `default`: a default value of the data instance, see [Assigning defaults](#assigning-defaults).\n- `examples` (NEW in draft-06): an array of data instances. Ajv does not check the validity of these instances against the schema.\n- `readOnly` and `writeOnly` (NEW in draft-07): marks data-instance as read-only or write-only in relation to the source of the data (database, api, etc.).\n- `contentEncoding`: [RFC 2045](https://tools.ietf.org/html/rfc2045#section-6.1), e.g., \"base64\".\n- `contentMediaType`: [RFC 2046](https://tools.ietf.org/html/rfc2046), e.g., \"image/png\".\n\n**Please note**: Ajv does not implement validation of the keywords `examples`, `contentEncoding` and `contentMediaType` but it reserves them. If you want to create a plugin that implements some of them, it should remove these keywords from the instance.\n\n## Formats\n\nFrom version 7 Ajv does not include formats defined by JSON Schema specification - these and several others formats are provided by [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin.\n\nTo add all formats from this plugin:\n\n```javascript\nconst ajv = new Ajv()\nrequire(\"ajv-formats\")(ajv)\n```\n\nSee ajv-formats documentation for further details.\n\nIt is recommended NOT to use \"format\" keyword implementations with untrusted data, as they use potentially unsafe regular expressions - see [ReDoS attack](#redos-attack).\n\n**Please note**: if you need to use \"format\" keyword to validate untrusted data, you MUST assess their suitability and safety for your validation scenarios.\n\nThe following formats are defined in [ajv-formats](https://github.com/ajv-validator/ajv-formats) for string validation with \"format\" keyword:\n\n- _date_: full-date according to [RFC3339](http://tools.ietf.org/html/rfc3339#section-5.6).\n- _time_: time with optional time-zone.\n- _date-time_: date-time from the same source (time-zone is mandatory). `date`, `time` and `date-time` validate ranges in `full` mode and only regexp in `fast` mode (see [options](#options)).\n- _uri_: full URI.\n- _uri-reference_: URI reference, including full and relative URIs.\n- _uri-template_: URI template according to [RFC6570](https://tools.ietf.org/html/rfc6570)\n- _url_ (deprecated): [URL record](https://url.spec.whatwg.org/#concept-url).\n- _email_: email address.\n- _hostname_: host name according to [RFC1034](http://tools.ietf.org/html/rfc1034#section-3.5).\n- _ipv4_: IP address v4.\n- _ipv6_: IP address v6.\n- _regex_: tests whether a string is a valid regular expression by passing it to RegExp constructor.\n- _uuid_: Universally Unique IDentifier according to [RFC4122](http://tools.ietf.org/html/rfc4122).\n- _json-pointer_: JSON-pointer according to [RFC6901](https://tools.ietf.org/html/rfc6901).\n- _relative-json-pointer_: relative JSON-pointer according to [this draft](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00).\n\n**Please note**: JSON Schema draft-07 also defines formats `iri`, `iri-reference`, `idn-hostname` and `idn-email` for URLs, hostnames and emails with international characters. These formats are available in [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) plugin.\n\nYou can add (and replace) any formats using [addFormat](#api-addformat) method.\n\nThe option `unknownFormats` allows changing the default behaviour when an unknown format is encountered. In this case Ajv can either fail schema compilation (default) or ignore it (default in versions before 5.0.0). You also can allow specific format(s) that will be ignored. See [Options](#options) for details.\n\nYou can find regular expressions used for format validation and the sources that were used in [formats.js](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js).\n\n## Combining schemas with \\$ref\n\nYou can structure your validation logic across multiple schema files and have schemas reference each other using `$ref` keyword.\n\nExample:\n\n```javascript\nvar schema = {\n $id: \"http://example.com/schemas/schema.json\",\n type: \"object\",\n properties: {\n foo: {$ref: \"defs.json#/definitions/int\"},\n bar: {$ref: \"defs.json#/definitions/str\"},\n },\n}\n\nvar defsSchema = {\n $id: \"http://example.com/schemas/defs.json\",\n definitions: {\n int: {type: \"integer\"},\n str: {type: \"string\"},\n },\n}\n```\n\nNow to compile your schema you can either pass all schemas to Ajv instance:\n\n```javascript\nvar ajv = new Ajv({schemas: [schema, defsSchema]})\nvar validate = ajv.getSchema(\"http://example.com/schemas/schema.json\")\n```\n\nor use `addSchema` method:\n\n```javascript\nvar ajv = new Ajv()\nvar validate = ajv.addSchema(defsSchema).compile(schema)\n```\n\nSee [Options](#options) and [addSchema](#api) method.\n\n**Please note**:\n\n- `$ref` is resolved as the uri-reference using schema \\$id as the base URI (see the example).\n- References can be recursive (and mutually recursive) to implement the schemas for different data structures (such as linked lists, trees, graphs, etc.).\n- You don't have to host your schema files at the URIs that you use as schema \\$id. These URIs are only used to identify the schemas, and according to JSON Schema specification validators should not expect to be able to download the schemas from these URIs.\n- The actual location of the schema file in the file system is not used.\n- You can pass the identifier of the schema as the second parameter of `addSchema` method or as a property name in `schemas` option. This identifier can be used instead of (or in addition to) schema \\$id.\n- You cannot have the same \\$id (or the schema identifier) used for more than one schema - the exception will be thrown.\n- You can implement dynamic resolution of the referenced schemas using `compileAsync` method. In this way you can store schemas in any system (files, web, database, etc.) and reference them without explicitly adding to Ajv instance. See [Asynchronous schema compilation](#asynchronous-schema-compilation).\n\n## \\$data reference\n\nWith `$data` option you can use values from the validated data as the values for the schema keywords. See [proposal](https://github.com/json-schema-org/json-schema-spec/issues/51) for more information about how it works.\n\n`$data` reference is supported in the keywords: const, enum, format, maximum/minimum, exclusiveMaximum / exclusiveMinimum, maxLength / minLength, maxItems / minItems, maxProperties / minProperties, formatMaximum / formatMinimum, formatExclusiveMaximum / formatExclusiveMinimum, multipleOf, pattern, required, uniqueItems.\n\nThe value of \"$data\" should be a [JSON-pointer](https://tools.ietf.org/html/rfc6901) to the data (the root is always the top level data object, even if the $data reference is inside a referenced subschema) or a [relative JSON-pointer](http://tools.ietf.org/html/draft-luff-relative-json-pointer-00) (it is relative to the current point in data; if the \\$data reference is inside a referenced subschema it cannot point to the data outside of the root level for this subschema).\n\nExamples.\n\nThis schema requires that the value in property `smaller` is less or equal than the value in the property larger:\n\n```javascript\nvar ajv = new Ajv({$data: true})\n\nvar schema = {\n properties: {\n smaller: {\n type: \"number\",\n maximum: {$data: \"1/larger\"},\n },\n larger: {type: \"number\"},\n },\n}\n\nvar validData = {\n smaller: 5,\n larger: 7,\n}\n\najv.validate(schema, validData) // true\n```\n\nThis schema requires that the properties have the same format as their field names:\n\n```javascript\nvar schema = {\n additionalProperties: {\n type: \"string\",\n format: {$data: \"0#\"},\n },\n}\n\nvar validData = {\n \"date-time\": \"1963-06-19T08:30:06.283185Z\",\n email: \"joe.bloggs@example.com\",\n}\n```\n\n`$data` reference is resolved safely - it won't throw even if some property is undefined. If `$data` resolves to `undefined` the validation succeeds (with the exclusion of `const` keyword). If `$data` resolves to incorrect type (e.g. not \"number\" for maximum keyword) the validation fails.\n\n## $merge and $patch keywords\n\nWith the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) you can use the keywords `$merge` and `$patch` that allow extending JSON Schemas with patches using formats [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) and [JSON Patch (RFC 6902)](https://tools.ietf.org/html/rfc6902).\n\nTo add keywords `$merge` and `$patch` to Ajv instance use this code:\n\n```javascript\nrequire(\"ajv-merge-patch\")(ajv)\n```\n\nExamples.\n\nUsing `$merge`:\n\n```json\n{\n \"$merge\": {\n \"source\": {\n \"type\": \"object\",\n \"properties\": {\"p\": {\"type\": \"string\"}},\n \"additionalProperties\": false\n },\n \"with\": {\n \"properties\": {\"q\": {\"type\": \"number\"}}\n }\n }\n}\n```\n\nUsing `$patch`:\n\n```json\n{\n \"$patch\": {\n \"source\": {\n \"type\": \"object\",\n \"properties\": {\"p\": {\"type\": \"string\"}},\n \"additionalProperties\": false\n },\n \"with\": [{\"op\": \"add\", \"path\": \"/properties/q\", \"value\": {\"type\": \"number\"}}]\n }\n}\n```\n\nThe schemas above are equivalent to this schema:\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"p\": {\"type\": \"string\"},\n \"q\": {\"type\": \"number\"}\n },\n \"additionalProperties\": false\n}\n```\n\nThe properties `source` and `with` in the keywords `$merge` and `$patch` can use absolute or relative `$ref` to point to other schemas previously added to the Ajv instance or to the fragments of the current schema.\n\nSee the package [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) for more information.\n\n## User-defined keywords\n\nThe advantages of defining keywords are:\n\n- allow creating validation scenarios that cannot be expressed using pre-defined keywords\n- simplify your schemas\n- help bringing a bigger part of the validation logic to your schemas\n- make your schemas more expressive, less verbose and closer to your application domain\n- implement data processors that modify your data (`modifying` option MUST be used in keyword definition) and/or create side effects while the data is being validated\n\nIf a keyword is used only for side-effects and its validation result is pre-defined, use option `valid: true/false` in keyword definition to simplify both generated code (no error handling in case of `valid: true`) and your keyword functions (no need to return any validation result).\n\nThe concerns you have to be aware of when extending JSON Schema standard with additional keywords are the portability and understanding of your schemas. You will have to support these keywords on other platforms and to properly document them so that everybody can understand and use your schemas.\n\nYou can define keywords with [addKeyword](#api-addkeyword) method. Keywords are defined on the `ajv` instance level - new instances will not have previously defined keywords.\n\nAjv allows defining keywords with:\n\n- code generation function (used by all pre-defined keywords)\n- validation function\n- compilation function\n- macro function\n\nExample. `range` and `exclusiveRange` keywords using compiled schema:\n\n```javascript\najv.addKeyword({\n keyword: \"range\",\n type: \"number\",\n schemaType: \"array\",\n implements: \"exclusiveRange\",\n compile: ([min, max], parentSchema) =>\n parentSchema.exclusiveRange === true\n ? (data) => data > min && data < max\n : (data) => data >= min && data <= max,\n})\n\nconst schema = {range: [2, 4], exclusiveRange: true}\nconst validate = ajv.compile(schema)\nconsole.log(validate(2.01)) // true\nconsole.log(validate(3.99)) // true\nconsole.log(validate(2)) // false\nconsole.log(validate(4)) // false\n```\n\nSeveral keywords (typeof, instanceof, range and propertyNames) are defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package - they can be used for your schemas and as a starting point for your own keywords.\n\nSee [User-defined keywords](https://github.com/ajv-validator/ajv/blob/master/CUSTOM.md) for more details.\n\n## Asynchronous schema compilation\n\nDuring asynchronous compilation remote references are loaded using supplied function. See `compileAsync` [method](#api-compileAsync) and `loadSchema` [option](#options).\n\nExample:\n\n```javascript\nvar ajv = new Ajv({loadSchema: loadSchema})\n\najv.compileAsync(schema).then(function (validate) {\n var valid = validate(data)\n // ...\n})\n\nfunction loadSchema(uri) {\n return request.json(uri).then(function (res) {\n if (res.statusCode >= 400) throw new Error(\"Loading error: \" + res.statusCode)\n return res.body\n })\n}\n```\n\n**Please note**: [Option](#options) `missingRefs` should NOT be set to `\"ignore\"` or `\"fail\"` for asynchronous compilation to work.\n\n## Asynchronous validation\n\nExample in Node.js REPL: https://runkit.com/esp/ajv-asynchronous-validation\n\nYou can define formats and keywords that perform validation asynchronously by accessing database or some other service. You should add `async: true` in the keyword or format definition (see [addFormat](#api-addformat), [addKeyword](#api-addkeyword) and [User-defined keywords](user-defined-keywords)).\n\nIf your schema uses asynchronous formats/keywords or refers to some schema that contains them it should have `\"$async\": true` keyword so that Ajv can compile it correctly. If asynchronous format/keyword or reference to asynchronous schema is used in the schema without `$async` keyword Ajv will throw an exception during schema compilation.\n\n**Please note**: all asynchronous subschemas that are referenced from the current or other schemas should have `\"$async\": true` keyword as well, otherwise the schema compilation will fail.\n\nValidation function for an asynchronous format/keyword should return a promise that resolves with `true` or `false` (or rejects with `new Ajv.ValidationError(errors)` if you want to return errors from the keyword function).\n\nAjv compiles asynchronous schemas to [async functions](http://tc39.github.io/ecmascript-asyncawait/). Async functions are supported in Node.js 7+ and all modern browsers. You can supply a transpiler as a function via `processCode` option. See [Options](#options).\n\nThe compiled validation function has `$async: true` property (if the schema is asynchronous), so you can differentiate these functions if you are using both synchronous and asynchronous schemas.\n\nValidation result will be a promise that resolves with validated data or rejects with an exception `Ajv.ValidationError` that contains the array of validation errors in `errors` property.\n\nExample:\n\n```javascript\nconst ajv = new Ajv()\n\najv.addKeyword({\n keyword: \"idExists\"\n async: true,\n type: \"number\",\n validate: checkIdExists,\n})\n\nfunction checkIdExists(schema, data) {\n return knex(schema.table)\n .select(\"id\")\n .where(\"id\", data)\n .then(function (rows) {\n return !!rows.length // true if record is found\n })\n}\n\nvar schema = {\n $async: true,\n properties: {\n userId: {\n type: \"integer\",\n idExists: {table: \"users\"},\n },\n postId: {\n type: \"integer\",\n idExists: {table: \"posts\"},\n },\n },\n}\n\nvar validate = ajv.compile(schema)\n\nvalidate({userId: 1, postId: 19})\n .then(function (data) {\n console.log(\"Data is valid\", data) // { userId: 1, postId: 19 }\n })\n .catch(function (err) {\n if (!(err instanceof Ajv.ValidationError)) throw err\n // data is invalid\n console.log(\"Validation errors:\", err.errors)\n })\n```\n\n#### Using transpilers\n\n```javascript\nvar ajv = new Ajv({processCode: transpileFunc})\nvar validate = ajv.compile(schema) // transpiled es7 async function\nvalidate(data).then(successFunc).catch(errorFunc)\n```\n\nSee [Options](#options).\n\n## Security considerations\n\nJSON Schema, if properly used, can replace data sanitisation. It doesn't replace other API security considerations. It also introduces additional security aspects to consider.\n\n##### Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n##### Untrusted schemas\n\nAjv treats JSON schemas as trusted as your application code. This security model is based on the most common use case, when the schemas are static and bundled together with the application.\n\nIf your schemas are received from untrusted sources (or generated from untrusted data) there are several scenarios you need to prevent:\n\n- compiling schemas can cause stack overflow (if they are too deep)\n- compiling schemas can be slow (e.g. [#557](https://github.com/ajv-validator/ajv/issues/557))\n- validating certain data can be slow\n\nIt is difficult to predict all the scenarios, but at the very least it may help to limit the size of untrusted schemas (e.g. limit JSON string length) and also the maximum schema object depth (that can be high for relatively small JSON strings). You also may want to mitigate slow regular expressions in `pattern` and `patternProperties` keywords.\n\nRegardless the measures you take, using untrusted schemas increases security risks.\n\n##### Circular references in JavaScript objects\n\nAjv does not support schemas and validated data that have circular references in objects. See [issue #802](https://github.com/ajv-validator/ajv/issues/802).\n\nAn attempt to compile such schemas or validate such data would cause stack overflow (or will not complete in case of asynchronous validation). Depending on the parser you use, untrusted data can lead to circular references.\n\n##### Security risks of trusted schemas\n\nSome keywords in JSON Schemas can lead to very slow validation for certain data. These keywords include (but may be not limited to):\n\n- `pattern` and `format` for large strings - in some cases using `maxLength` can help mitigate it, but certain regular expressions can lead to exponential validation time even with relatively short strings (see [ReDoS attack](#redos-attack)).\n- `patternProperties` for large property names - use `propertyNames` to mitigate, but some regular expressions can have exponential evaluation time as well.\n- `uniqueItems` for large non-scalar arrays - use `maxItems` to mitigate\n\n**Please note**: The suggestions above to prevent slow validation would only work if you do NOT use `allErrors: true` in production code (using it would continue validation after validation errors).\n\nYou can validate your JSON schemas against [this meta-schema](https://github.com/ajv-validator/ajv/blob/master/lib/refs/json-schema-secure.json) to check that these recommendations are followed:\n\n```javascript\nconst isSchemaSecure = ajv.compile(require(\"ajv/lib/refs/json-schema-secure.json\"))\n\nconst schema1 = {format: \"email\"}\nisSchemaSecure(schema1) // false\n\nconst schema2 = {format: \"email\", maxLength: MAX_LENGTH}\nisSchemaSecure(schema2) // true\n```\n\n**Please note**: following all these recommendation is not a guarantee that validation of untrusted data is safe - it can still lead to some undesirable results.\n\n##### Content Security Policies (CSP)\n\nSee [Ajv and Content Security Policies (CSP)](#ajv-and-content-security-policies-csp)\n\n## ReDoS attack\n\nCertain regular expressions can lead to the exponential evaluation time even with relatively short strings.\n\nPlease assess the regular expressions you use in the schemas on their vulnerability to this attack - see [safe-regex](https://github.com/substack/safe-regex), for example.\n\n**Please note**: some formats that Ajv implements use [regular expressions](https://github.com/ajv-validator/ajv/blob/master/lib/compile/formats.js) that can be vulnerable to ReDoS attack, so if you use Ajv to validate data from untrusted sources **it is strongly recommended** to consider the following:\n\n- making assessment of \"format\" implementations in Ajv.\n- using `format: 'fast'` option that simplifies some of the regular expressions (although it does not guarantee that they are safe).\n- replacing format implementations provided by Ajv with your own implementations of \"format\" keyword that either uses different regular expressions or another approach to format validation. Please see [addFormat](#api-addformat) method.\n- disabling format validation by ignoring \"format\" keyword with option `format: false`\n\nWhatever mitigation you choose, please assume all formats provided by Ajv as potentially unsafe and make your own assessment of their suitability for your validation scenarios.\n\n## Filtering data\n\nWith [option `removeAdditional`](#options) (added by [andyscott](https://github.com/andyscott)) you can filter data during the validation.\n\nThis option modifies original data.\n\nExample:\n\n```javascript\nvar ajv = new Ajv({removeAdditional: true})\nvar schema = {\n additionalProperties: false,\n properties: {\n foo: {type: \"number\"},\n bar: {\n additionalProperties: {type: \"number\"},\n properties: {\n baz: {type: \"string\"},\n },\n },\n },\n}\n\nvar data = {\n foo: 0,\n additional1: 1, // will be removed; `additionalProperties` == false\n bar: {\n baz: \"abc\",\n additional2: 2, // will NOT be removed; `additionalProperties` != false\n },\n}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 0, \"bar\": { \"baz\": \"abc\", \"additional2\": 2 }\n```\n\nIf `removeAdditional` option in the example above were `\"all\"` then both `additional1` and `additional2` properties would have been removed.\n\nIf the option were `\"failing\"` then property `additional1` would have been removed regardless of its value and property `additional2` would have been removed only if its value were failing the schema in the inner `additionalProperties` (so in the example above it would have stayed because it passes the schema, but any non-number would have been removed).\n\n**Please note**: If you use `removeAdditional` option with `additionalProperties` keyword inside `anyOf`/`oneOf` keywords your validation can fail with this schema, for example:\n\n```json\n{\n \"type\": \"object\",\n \"oneOf\": [\n {\n \"properties\": {\n \"foo\": {\"type\": \"string\"}\n },\n \"required\": [\"foo\"],\n \"additionalProperties\": false\n },\n {\n \"properties\": {\n \"bar\": {\"type\": \"integer\"}\n },\n \"required\": [\"bar\"],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\nThe intention of the schema above is to allow objects with either the string property \"foo\" or the integer property \"bar\", but not with both and not with any other properties.\n\nWith the option `removeAdditional: true` the validation will pass for the object `{ \"foo\": \"abc\"}` but will fail for the object `{\"bar\": 1}`. It happens because while the first subschema in `oneOf` is validated, the property `bar` is removed because it is an additional property according to the standard (because it is not included in `properties` keyword in the same schema).\n\nWhile this behaviour is unexpected (issues [#129](https://github.com/ajv-validator/ajv/issues/129), [#134](https://github.com/ajv-validator/ajv/issues/134)), it is correct. To have the expected behaviour (both objects are allowed and additional properties are removed) the schema has to be refactored in this way:\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"foo\": {\"type\": \"string\"},\n \"bar\": {\"type\": \"integer\"}\n },\n \"additionalProperties\": false,\n \"oneOf\": [{\"required\": [\"foo\"]}, {\"required\": [\"bar\"]}]\n}\n```\n\nThe schema above is also more efficient - it will compile into a faster function.\n\n## Assigning defaults\n\nWith [option `useDefaults`](#options) Ajv will assign values from `default` keyword in the schemas of `properties` and `items` (when it is the array of schemas) to the missing properties and items.\n\nWith the option value `\"empty\"` properties and items equal to `null` or `\"\"` (empty string) will be considered missing and assigned defaults.\n\nThis option modifies original data.\n\n**Please note**: the default value is inserted in the generated validation code as a literal, so the value inserted in the data will be the deep clone of the default in the schema.\n\nExample 1 (`default` in `properties`):\n\n```javascript\nvar ajv = new Ajv({useDefaults: true})\nvar schema = {\n type: \"object\",\n properties: {\n foo: {type: \"number\"},\n bar: {type: \"string\", default: \"baz\"},\n },\n required: [\"foo\", \"bar\"],\n}\n\nvar data = {foo: 1}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 1, \"bar\": \"baz\" }\n```\n\nExample 2 (`default` in `items`):\n\n```javascript\nvar schema = {\n type: \"array\",\n items: [{type: \"number\"}, {type: \"string\", default: \"foo\"}],\n}\n\nvar data = [1]\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // [ 1, \"foo\" ]\n```\n\nWith `useDefaults` option `default` keywords throws exception during schema compilation when used in:\n\n- not in `properties` or `items` subschemas\n- in schemas inside `anyOf`, `oneOf` and `not` (see [#42](https://github.com/ajv-validator/ajv/issues/42))\n- in `if` schema\n- in schemas generated by user-defined _macro_ keywords\n\nThe strict mode option can change the behavior for these unsupported defaults (`strict: false` to ignore them, `\"log\"` to log a warning).\n\nSee [Strict mode](#strict-mode).\n\n## Coercing data types\n\nWhen you are validating user inputs all your data properties are usually strings. The option `coerceTypes` allows you to have your data types coerced to the types specified in your schema `type` keywords, both to pass the validation and to use the correctly typed data afterwards.\n\nThis option modifies original data.\n\n**Please note**: if you pass a scalar value to the validating function its type will be coerced and it will pass the validation, but the value of the variable you pass won't be updated because scalars are passed by value.\n\nExample 1:\n\n```javascript\nvar ajv = new Ajv({coerceTypes: true})\nvar schema = {\n type: \"object\",\n properties: {\n foo: {type: \"number\"},\n bar: {type: \"boolean\"},\n },\n required: [\"foo\", \"bar\"],\n}\n\nvar data = {foo: \"1\", bar: \"false\"}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": 1, \"bar\": false }\n```\n\nExample 2 (array coercions):\n\n```javascript\nvar ajv = new Ajv({coerceTypes: \"array\"})\nvar schema = {\n properties: {\n foo: {type: \"array\", items: {type: \"number\"}},\n bar: {type: \"boolean\"},\n },\n}\n\nvar data = {foo: \"1\", bar: [\"false\"]}\n\nvar validate = ajv.compile(schema)\n\nconsole.log(validate(data)) // true\nconsole.log(data) // { \"foo\": [1], \"bar\": false }\n```\n\nThe coercion rules, as you can see from the example, are different from JavaScript both to validate user input as expected and to have the coercion reversible (to correctly validate cases where different types are defined in subschemas of \"anyOf\" and other compound keywords).\n\nSee [Coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md) for details.\n\n## API\n\n##### new Ajv(Object options) -> Object\n\nCreate Ajv instance.\n\n##### .compile(Object schema) -> Function<Object data>\n\nGenerate validating function and cache the compiled schema for future use.\n\nValidating function returns a boolean value. This function has properties `errors` and `schema`. Errors encountered during the last validation are assigned to `errors` property (it is assigned `null` if there was no errors). `schema` property contains the reference to the original schema.\n\nThe schema passed to this method will be validated against meta-schema unless `validateSchema` option is false. If schema is invalid, an error will be thrown. See [options](#options).\n\n##### .compileAsync(Object schema [, Boolean meta][, function callback]) -> Promise\n\nAsynchronous version of `compile` method that loads missing remote schemas using asynchronous function in `options.loadSchema`. This function returns a Promise that resolves to a validation function. An optional callback passed to `compileAsync` will be called with 2 parameters: error (or null) and validating function. The returned promise will reject (and the callback will be called with an error) when:\n\n- missing schema can't be loaded (`loadSchema` returns a Promise that rejects).\n- a schema containing a missing reference is loaded, but the reference cannot be resolved.\n- schema (or some loaded/referenced schema) is invalid.\n\nThe function compiles schema and loads the first missing schema (or meta-schema) until all missing schemas are loaded.\n\nYou can asynchronously compile meta-schema by passing `true` as the second parameter.\n\nSee example in [Asynchronous compilation](#asynchronous-schema-compilation).\n\n##### .validate(Object schema|String key|String ref, data) -> Boolean\n\nValidate data using passed schema (it will be compiled and cached).\n\nInstead of the schema you can use the key that was previously passed to `addSchema`, the schema id if it was present in the schema or any previously resolved reference.\n\nValidation errors will be available in the `errors` property of Ajv instance (`null` if there were no errors).\n\n**Please note**: every time this method is called the errors are overwritten so you need to copy them to another variable if you want to use them later.\n\nIf the schema is asynchronous (has `$async` keyword on the top level) this method returns a Promise. See [Asynchronous validation](#asynchronous-validation).\n\n##### .addSchema(Array<Object>|Object schema [, String key]) -> Ajv\n\nAdd schema(s) to validator instance. This method does not compile schemas (but it still validates them). Because of that dependencies can be added in any order and circular dependencies are supported. It also prevents unnecessary compilation of schemas that are containers for other schemas but not used as a whole.\n\nArray of schemas can be passed (schemas should have ids), the second parameter will be ignored.\n\nKey can be passed that can be used to reference the schema and will be used as the schema id if there is no id inside the schema. If the key is not passed, the schema id will be used as the key.\n\nOnce the schema is added, it (and all the references inside it) can be referenced in other schemas and used to validate data.\n\nAlthough `addSchema` does not compile schemas, explicit compilation is not required - the schema will be compiled when it is used first time.\n\nBy default the schema is validated against meta-schema before it is added, and if the schema does not pass validation the exception is thrown. This behaviour is controlled by `validateSchema` option.\n\n**Please note**: Ajv uses the [method chaining syntax](https://en.wikipedia.org/wiki/Method_chaining) for all methods with the prefix `add*` and `remove*`.\nThis allows you to do nice things like the following.\n\n```javascript\nvar validate = new Ajv().addSchema(schema).addFormat(name, regex).getSchema(uri)\n```\n\n##### .addMetaSchema(Array<Object>|Object schema [, String key]) -> Ajv\n\nAdds meta schema(s) that can be used to validate other schemas. That function should be used instead of `addSchema` because there may be instance options that would compile a meta schema incorrectly (at the moment it is `removeAdditional` option).\n\nThere is no need to explicitly add draft-07 meta schema (http://json-schema.org/draft-07/schema) - it is added by default, unless option `meta` is set to `false`. You only need to use it if you have a changed meta-schema that you want to use to validate your schemas. See `validateSchema`.\n\n##### .validateSchema(Object schema) -> Boolean\n\nValidates schema. This method should be used to validate schemas rather than `validate` due to the inconsistency of `uri` format in JSON Schema standard.\n\nBy default this method is called automatically when the schema is added, so you rarely need to use it directly.\n\nIf schema doesn't have `$schema` property, it is validated against draft 6 meta-schema (option `meta` should not be false).\n\nIf schema has `$schema` property, then the schema with this id (that should be previously added) is used to validate passed schema.\n\nErrors will be available at `ajv.errors`.\n\n##### .getSchema(String key) -> Function<Object data>\n\nRetrieve compiled schema previously added with `addSchema` by the key passed to `addSchema` or by its full reference (id). The returned validating function has `schema` property with the reference to the original schema.\n\n##### .removeSchema([Object schema|String key|String ref|RegExp pattern]) -> Ajv\n\nRemove added/cached schema. Even if schema is referenced by other schemas it can be safely removed as dependent schemas have local references.\n\nSchema can be removed using:\n\n- key passed to `addSchema`\n- it's full reference (id)\n- RegExp that should match schema id or key (meta-schemas won't be removed)\n- actual schema object that will be stable-stringified to remove schema from cache\n\nIf no parameter is passed all schemas but meta-schemas will be removed and the cache will be cleared.\n\n##### .addFormat(String name, String|RegExp|Function|Object format) -> Ajv\n\nAdd format to validate strings or numbers.\n\nStrings are converted to RegExp.\n\nFunction should return validation result as `true` or `false`.\n\nIf object is passed it should have properties `validate`, `compare` and `async`:\n\n- _validate_: a string, RegExp or a function as described above.\n- _compare_: an optional comparison function that accepts two strings and compares them according to the format meaning. This function is used with keywords `formatMaximum`/`formatMinimum` (defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package). It should return `1` if the first value is bigger than the second value, `-1` if it is smaller and `0` if it is equal.\n- _async_: an optional `true` value if `validate` is an asynchronous function; in this case it should return a promise that resolves with a value `true` or `false`.\n- _type_: an optional type of data that the format applies to. It can be `\"string\"` (default) or `\"number\"` (see https://github.com/ajv-validator/ajv/issues/291#issuecomment-259923858). If the type of data is different, the validation will pass.\n\nFormats can be also added via `formats` option.\n\n##### .addKeyword(Object definition) -> Ajv\n\nAdd validation keyword to Ajv instance.\n\nKeyword should be different from all standard JSON Schema keywords and different from previously defined keywords. There is no way to redefine keywords or to remove keyword definition from the instance.\n\nKeyword must start with a letter, `_` or `$`, and may continue with letters, numbers, `_`, `$`, or `-`.\nIt is recommended to use an application-specific prefix for keywords to avoid current and future name collisions.\n\nExample Keywords:\n\n- `\"xyz-example\"`: valid, and uses prefix for the xyz project to avoid name collisions.\n- `\"example\"`: valid, but not recommended as it could collide with future versions of JSON Schema etc.\n- `\"3-example\"`: invalid as numbers are not allowed to be the first character in a keyword\n\nKeyword definition is an object with the following properties:\n\n- _keyword_: keyword name string\n- _type_: optional string or array of strings with data type(s) that the keyword applies to. If not present, the keyword will apply to all types.\n- _schemaType_: optional string or array of strings with the required schema type\n- _code_: function to generate code, used for all pre-defined keywords\n- _validate_: validating function\n- _compile_: compiling function\n- _macro_: macro function\n- _error_: optional error definition object\n- _schema_: an optional `false` value used with \"validate\" keyword to not pass schema\n- _metaSchema_: an optional meta-schema for keyword schema\n- _dependencies_: an optional list of properties that must be present in the parent schema - it will be checked during schema compilation\n- _implements_: an optional list of keyword names to reserve that this keyword implements\n- _modifying_: `true` MUST be passed if keyword modifies data\n- _valid_: pass `true`/`false` to pre-define validation result, the result returned from validation function will be ignored. This option cannot be used with macro keywords.\n- _\\$data_: an optional `true` value to support [\\$data reference](#data-reference) as the value of keyword. The reference will be resolved at validation time. If the keyword has meta-schema it would be extended to allow $data and it will be used to validate the resolved value. Supporting $data reference requires that keyword has _code_ or _validate_ function (the latter can be used in addition to _compile_ or _macro_).\n- _\\$dataError_: optional error definition for invalid \\$data schema\n- _async_: an optional `true` value if the validation function is asynchronous (whether it is compiled or passed in _validate_ property); in this case it should return a promise that resolves with a value `true` or `false`. This option is ignored in case of \"macro\" and \"inline\" keywords.\n- _errors_: an optional boolean or string `\"full\"` indicating whether keyword returns errors. If this property is not set Ajv will determine if the errors were set in case of failed validation.\n\n_compile_, _macro_ and _code_ are mutually exclusive, only one should be used at a time. _validate_ can be used separately or in addition to _compile_ or _macro_ to support \\$data reference.\n\n**Please note**: If the keyword is validating data type that is different from the type(s) in its definition, the validation function will not be called (and expanded macro will not be used), so there is no need to check for data type inside validation function or inside schema returned by macro function (unless you want to enforce a specific type and for some reason do not want to use a separate `type` keyword for that). In the same way as standard keywords work, if the keyword does not apply to the data type being validated, the validation of this keyword will succeed.\n\nSee [User defined keywords](#user-defined-keywords) for more details.\n\n##### .getKeyword(String keyword) -> Object|Boolean\n\nReturns keyword definition, `false` if the keyword is unknown.\n\n##### .removeKeyword(String keyword) -> Ajv\n\nRemoves added or pre-defined keyword so you can redefine them.\n\nWhile this method can be used to extend pre-defined keywords, it can also be used to completely change their meaning - it may lead to unexpected results.\n\n**Please note**: schemas compiled before the keyword is removed will continue to work without changes. To recompile schemas use `removeSchema` method and compile them again.\n\n##### .errorsText([Array<Object> errors [, Object options]]) -> String\n\nReturns the text with all errors in a String.\n\nOptions can have properties `separator` (string used to separate errors, \", \" by default) and `dataVar` (the variable name that dataPaths are prefixed with, \"data\" by default).\n\n## Options\n\nDefaults:\n\n```javascript\n{\n // strict mode options\n strict: true,\n allowMatchingProperties: false,\n // validation and reporting options:\n $data: false,\n allErrors: false,\n verbose: false,\n $comment: false,\n format: true,\n formats: {},\n unknownFormats: true,\n schemas: {},\n logger: undefined,\n // referenced schema options:\n missingRefs: true,\n extendRefs: \"ignore\", // recommended 'fail'\n loadSchema: undefined, // function(uri: string): Promise {}\n // options to modify validated data:\n removeAdditional: false,\n useDefaults: false,\n coerceTypes: false,\n // advanced options:\n meta: true,\n validateSchema: true,\n addUsedSchema: true,\n inlineRefs: true,\n passContext: false,\n loopRequired: Infinity,\n loopEnum: Infinity,\n ownProperties: false,\n multipleOfPrecision: false,\n messages: true,\n sourceCode: false,\n processCode: undefined, // function (str: string, schema: object): string {}\n cache: new Cache,\n serialize: undefined\n jsPropertySyntax: false, // deprecated\n}\n```\n\n##### Strict mode options\n\n- _strict_: By default Ajv executes in strict mode, that is designed to prevent any unexpected behaviours or silently ignored mistakes in schemas (see [Strict Mode](#strict-mode) for more details). It does not change any validation results, but it makes some schemas invalid that would be otherwise valid according to JSON Schema specification. Option values:\n - `true` (default) - use strict mode and throw an exception when any strict mode restrictions is violated.\n - `\"log\"` - log warning when any strict mode restriction is violated.\n - `false` - ignore any strict mode restriction.\n- _allowMatchingProperties_: pass true to allow overlap between \"properties\" and \"patternProperties\". See [Strict Mode](#strict-mode).\n\n##### Validation and reporting options\n\n- _\\$data_: support [\\$data references](#data-reference). Draft 6 meta-schema that is added by default will be extended to allow them. If you want to use another meta-schema you need to use $dataMetaSchema method to add support for $data reference. See [API](#api).\n- _allErrors_: check all rules collecting all errors. Default is to return after the first error.\n- _verbose_: include the reference to the part of the schema (`schema` and `parentSchema`) and validated data in errors (false by default).\n- _\\$comment_ (NEW in Ajv version 6.0): log or pass the value of `$comment` keyword to a function. Option values:\n - `false` (default): ignore \\$comment keyword.\n - `true`: log the keyword value to console.\n - function: pass the keyword value, its schema path and root schema to the specified function\n- _format_: formats validation mode. Option values:\n - `true` (default) - validate added formats (see [Formats](#formats)).\n - `false` - ignore all format keywords.\n- _formats_: an object with format definitions. Keys and values will be passed to `addFormat` method.\n- _keywords_: an array of keyword definitions or strings. Values will be passed to `addKeyword` method.\n- _unknownFormats_: handling of unknown formats. Option values:\n - `true` (default) - if an unknown format is encountered the exception is thrown during schema compilation. If `format` keyword value is [\\$data reference](#data-reference) and it is unknown the validation will fail.\n - `[String]` - an array of unknown format names that will be ignored. This option can be used to allow usage of third party schemas with format(s) for which you don't have definitions, but still fail if another unknown format is used. If `format` keyword value is [\\$data reference](#data-reference) and it is not in this array the validation will fail.\n - `\"ignore\"` - to log warning during schema compilation and always pass validation (the default behaviour in versions before 5.0.0). This option is not recommended, as it allows to mistype format name and it won't be validated without any error message. This behaviour is required by JSON Schema specification.\n- _schemas_: an array or object of schemas that will be added to the instance. In case you pass the array the schemas must have IDs in them. When the object is passed the method `addSchema(value, key)` will be called for each schema in this object.\n- _logger_: sets the logging method. Default is the global `console` object that should have methods `log`, `warn` and `error`. See [Error logging](#error-logging). Option values:\n - logger instance - it should have methods `log`, `warn` and `error`. If any of these methods is missing an exception will be thrown.\n - `false` - logging is disabled.\n\n##### Referenced schema options\n\n- _missingRefs_: handling of missing referenced schemas. Option values:\n - `true` (default) - if the reference cannot be resolved during compilation the exception is thrown. The thrown error has properties `missingRef` (with hash fragment) and `missingSchema` (without it). Both properties are resolved relative to the current base id (usually schema id, unless it was substituted).\n - `\"ignore\"` - to log error during compilation and always pass validation.\n - `\"fail\"` - to log error and successfully compile schema but fail validation if this rule is checked.\n- _extendRefs_: validation of other keywords when `$ref` is present in the schema. Option values:\n - `\"ignore\"` (default) - when `$ref` is used other keywords are ignored (as per [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03#section-3) standard). A warning will be logged during the schema compilation.\n - `\"fail\"` (recommended) - if other validation keywords are used together with `$ref` the exception will be thrown when the schema is compiled. This option is recommended to make sure schema has no keywords that are ignored, which can be confusing.\n - `true` - validate all keywords in the schemas with `$ref` (the default behaviour in versions before 5.0.0).\n- _loadSchema_: asynchronous function that will be used to load remote schemas when `compileAsync` [method](#api-compileAsync) is used and some reference is missing (option `missingRefs` should NOT be 'fail' or 'ignore'). This function should accept remote schema uri as a parameter and return a Promise that resolves to a schema. See example in [Asynchronous compilation](#asynchronous-schema-compilation).\n\n##### Options to modify validated data\n\n- _removeAdditional_: remove additional properties - see example in [Filtering data](#filtering-data). This option is not used if schema is added with `addMetaSchema` method. Option values:\n - `false` (default) - not to remove additional properties\n - `\"all\"` - all additional properties are removed, regardless of `additionalProperties` keyword in schema (and no validation is made for them).\n - `true` - only additional properties with `additionalProperties` keyword equal to `false` are removed.\n - `\"failing\"` - additional properties that fail schema validation will be removed (where `additionalProperties` keyword is `false` or schema).\n- _useDefaults_: replace missing or undefined properties and items with the values from corresponding `default` keywords. Default behaviour is to ignore `default` keywords. This option is not used if schema is added with `addMetaSchema` method. See examples in [Assigning defaults](#assigning-defaults). Option values:\n - `false` (default) - do not use defaults\n - `true` - insert defaults by value (object literal is used).\n - `\"empty\"` - in addition to missing or undefined, use defaults for properties and items that are equal to `null` or `\"\"` (an empty string).\n- _coerceTypes_: change data type of data to match `type` keyword. See the example in [Coercing data types](#coercing-data-types) and [coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md). Option values:\n - `false` (default) - no type coercion.\n - `true` - coerce scalar data types.\n - `\"array\"` - in addition to coercions between scalar types, coerce scalar data to an array with one element and vice versa (as required by the schema).\n\n##### Advanced options\n\n- _meta_: add [meta-schema](http://json-schema.org/documentation.html) so it can be used by other schemas (true by default). If an object is passed, it will be used as the default meta-schema for schemas that have no `$schema` keyword. This default meta-schema MUST have `$schema` keyword.\n- _validateSchema_: validate added/compiled schemas against meta-schema (true by default). `$schema` property in the schema can be http://json-schema.org/draft-07/schema or absent (draft-07 meta-schema will be used) or can be a reference to the schema previously added with `addMetaSchema` method. Option values:\n - `true` (default) - if the validation fails, throw the exception.\n - `\"log\"` - if the validation fails, log error.\n - `false` - skip schema validation.\n- _addUsedSchema_: by default methods `compile` and `validate` add schemas to the instance if they have `$id` (or `id`) property that doesn't start with \"#\". If `$id` is present and it is not unique the exception will be thrown. Set this option to `false` to skip adding schemas to the instance and the `$id` uniqueness check when these methods are used. This option does not affect `addSchema` method.\n- _inlineRefs_: Affects compilation of referenced schemas. Option values:\n - `true` (default) - the referenced schemas that don't have refs in them are inlined, regardless of their size - that substantially improves performance at the cost of the bigger size of compiled schema functions.\n - `false` - to not inline referenced schemas (they will be compiled as separate functions).\n - integer number - to limit the maximum number of keywords of the schema that will be inlined.\n- _passContext_: pass validation context to _compile_ and _validate_ keyword functions. If this option is `true` and you pass some context to the compiled validation function with `validate.call(context, data)`, the `context` will be available as `this` in your keywords. By default `this` is Ajv instance.\n- _loopRequired_: by default `required` keyword is compiled into a single expression (or a sequence of statements in `allErrors` mode). In case of a very large number of properties in this keyword it may result in a very big validation function. Pass integer to set the number of properties above which `required` keyword will be validated in a loop - smaller validation function size but also worse performance.\n- _loopEnum_: by default `enum` keyword is compiled into a single expression. In case of a very large number of allowed values it may result in a large validation function. Pass integer to set the number of values above which `enum` keyword will be validated in a loop.\n- _ownProperties_: by default Ajv iterates over all enumerable object properties; when this option is `true` only own enumerable object properties (i.e. found directly on the object rather than on its prototype) are iterated. Contributed by @mbroadst.\n- _multipleOfPrecision_: by default `multipleOf` keyword is validated by comparing the result of division with parseInt() of that result. It works for dividers that are bigger than 1. For small dividers such as 0.01 the result of the division is usually not integer (even when it should be integer, see issue [#84](https://github.com/ajv-validator/ajv/issues/84)). If you need to use fractional dividers set this option to some positive integer N to have `multipleOf` validated using this formula: `Math.abs(Math.round(division) - division) < 1e-N` (it is slower but allows for float arithmetics deviations).\n- _messages_: Include human-readable messages in errors. `true` by default. `false` can be passed when messages are generated outside of Ajv code (e.g. with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n)).\n- _sourceCode_: add `sourceCode` property to validating function (for debugging; this code can be different from the result of toString call).\n- _processCode_: an optional function to process generated code before it is passed to Function constructor. It can be used to either beautify (the validating function is generated without line-breaks) or to transpile code.\n- _cache_: an optional instance of cache to store compiled schemas using stable-stringified schema as a key. For example, set-associative cache [sacjs](https://github.com/epoberezkin/sacjs) can be used. If not passed then a simple hash is used which is good enough for the common use case (a limited number of statically defined schemas). Cache should have methods `put(key, value)`, `get(key)`, `del(key)` and `clear()`.\n- _serialize_: an optional function to serialize schema to cache key. Pass `false` to use schema itself as a key (e.g., if WeakMap used as a cache). By default [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used.\n- _jsPropertySyntax_ (deprecated) - set to `true` to report `dataPath` in errors as in v6, using JavaScript property syntax (e.g., `\".prop[1].subProp\"`). By default `dataPath` in errors is reported as JSON pointer. This option is added for backward compatibility and is not recommended - this format is difficult to parse even in JS code.\n\n## Validation errors\n\nIn case of validation failure, Ajv assigns the array of errors to `errors` property of validation function (or to `errors` property of Ajv instance when `validate` or `validateSchema` methods were called). In case of [asynchronous validation](#asynchronous-validation), the returned promise is rejected with exception `Ajv.ValidationError` that has `errors` property.\n\n### Error objects\n\nEach error is an object with the following properties:\n\n- _keyword_: validation keyword.\n- _dataPath_: JSON pointer to the part of the data that was validated (e.g., `\"/prop/1/subProp\"`).\n- _schemaPath_: the path (JSON-pointer as a URI fragment) to the schema of the keyword that failed validation.\n- _params_: the object with the additional information about error that can be used to generate error messages (e.g., using [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package). See below for parameters set by all keywords.\n- _message_: the standard error message (can be excluded with option `messages` set to false).\n- _schema_: the schema of the keyword (added with `verbose` option).\n- _parentSchema_: the schema containing the keyword (added with `verbose` option)\n- _data_: the data validated by the keyword (added with `verbose` option).\n\n**Please note**: `propertyNames` keyword schema validation errors have an additional property `propertyName`, `dataPath` points to the object. After schema validation for each property name, if it is invalid an additional error is added with the property `keyword` equal to `\"propertyNames\"`.\n\n### Error parameters\n\nProperties of `params` object in errors depend on the keyword that failed validation.\n\n- `maxItems`, `minItems`, `maxLength`, `minLength`, `maxProperties`, `minProperties` - property `limit` (number, the schema of the keyword).\n- `additionalItems` - property `limit` (the maximum number of allowed items in case when `items` keyword is an array of schemas and `additionalItems` is false).\n- `additionalProperties` - property `additionalProperty` (the property not used in `properties` and `patternProperties` keywords).\n- `dependencies` - properties:\n - `property` (dependent property),\n - `missingProperty` (required missing dependency - only the first one is reported currently)\n - `deps` (required dependencies, comma separated list as a string),\n - `depsCount` (the number of required dependencies).\n- `format` - property `format` (the schema of the keyword).\n- `maximum`, `minimum` - properties:\n - `limit` (number, the schema of the keyword),\n - `exclusive` (boolean, the schema of `exclusiveMaximum` or `exclusiveMinimum`),\n - `comparison` (string, comparison operation to compare the data to the limit, with the data on the left and the limit on the right; can be \"<\", \"<=\", \">\", \">=\")\n- `multipleOf` - property `multipleOf` (the schema of the keyword)\n- `pattern` - property `pattern` (the schema of the keyword)\n- `required` - property `missingProperty` (required property that is missing).\n- `propertyNames` - property `propertyName` (an invalid property name).\n- `patternRequired` (in ajv-keywords) - property `missingPattern` (required pattern that did not match any property).\n- `type` - property `type` (required type(s), a string, can be a comma-separated list)\n- `uniqueItems` - properties `i` and `j` (indices of duplicate items).\n- `const` - property `allowedValue` pointing to the value (the schema of the keyword).\n- `enum` - property `allowedValues` pointing to the array of values (the schema of the keyword).\n- `$ref` - property `ref` with the referenced schema URI.\n- `oneOf` - property `passingSchemas` (array of indices of passing schemas, null if no schema passes).\n\nUser-defined keywords can define other keyword parameters.\n\n### Error logging\n\nA logger instance can be passed via `logger` option to Ajv constructor. The use of other logging packages is supported as long as the package or its associated wrapper exposes the required methods. If any of the required methods are missing an exception will be thrown.\n\n- **Required Methods**: `log`, `warn`, `error`\n\n```javascript\nconst otherLogger = new OtherLogger()\nconst ajv = new Ajv({\n logger: {\n log: console.log.bind(console),\n warn: function warn() {\n otherLogger.logWarn.apply(otherLogger, arguments)\n },\n error: function error() {\n otherLogger.logError.apply(otherLogger, arguments)\n console.error.apply(console, arguments)\n },\n },\n})\n```\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-async](https://github.com/ajv-validator/ajv-async) - plugin to configure async validation mode (DEPRECATED)\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](https://github.com/ajv-validator/ajv/blob/master/CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n[Version 5.0.0](https://github.com/ajv-validator/ajv/releases/tag/5.0.0).\n\n[Version 4.0.0](https://github.com/ajv-validator/ajv/releases/tag/4.0.0).\n\n[Version 3.0.0](https://github.com/ajv-validator/ajv/releases/tag/3.0.0).\n\n[Version 2.0.0](https://github.com/ajv-validator/ajv/releases/tag/2.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](https://github.com/ajv-validator/ajv/blob/master/CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](https://github.com/ajv-validator/ajv/blob/master/LICENSE)\n","readmeFilename":"README.md","gitHead":"4bb210de5cd6f1ba9190b80a26e52ec9eb56bff8","_id":"ajv@7.0.0-alpha.1","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-vOWutHnEGQJ6AWg7JFil9yhZ0OJQMHkCbUJrrDWcnHYcUMBHkxf+5mCAU16dCz3eZh3Tkaf/JsyFVbTQkqjzNw==","shasum":"19d5bcec514ac4f31125a68e2ecf6f747e9fb0ae","tarball":"http://localhost:4260/ajv/ajv-7.0.0-alpha.1.tgz","fileCount":250,"unpackedSize":595851,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYhXHCRA9TVsSAnZWagAATGIP/2m6xiuTGIwORcnwkbhW\nyDjojpmM0pdjsbIGxtuo3+VwpUtdoRLZqb3HdN4P5/hBW6XDyU22C0KuXQvu\nhApKLUJ12ZH7JaEUeB3uWozP3ppTpS9c0TCoIp4T/PHfFZriiXyuPgavlfG9\n+yZwz/n+I63rqxrKzUNCHzH+9AxjVrt6mbYDAka4AzJqapCvoIqEdRRuB7RB\nGPutS/az2qcu1V4/wg7DePgg8A3gOHpqPGy0mCRu//5qKR6hRiR4+mqu0gpM\n9NaRe7DduFcte4kyQGBzF1FZy5jprXgjkdCVmaijWpJZOz32hwhio65JQT++\ntfLS1tK3w1CeLIN/fnFR8MZO0HjR+5Q5eww5sUK/88SS4SVDQJh18TrQxo8q\n9eiQkMgn8OUV4blLCoKLCxRKlL73ku3d3FR86R/lqBPdBwEMAJyaNC6MLTtR\ndEZOXIrKVoZ9c5zzrz1+IOqupnvU6YYdHBKTNdHHA2IDxtEYbr+6r+HD9GG9\ngc5AoDpZ/mFhMU2kW0RLgSYdBkhvkDFRglbHASWV5oHfUnt3MkFU4piGEEIU\nvD31R1p48qPq1iyDSIF5v25q/iWPJ4yFWxu6wcQP2Z96tRYyrWDEZGTHXaca\nLc5NJZYnnrCtrGV+IOwBFhsU4EM2nAkJ64iM6idiN8medWg4o9SCmpActIPb\nVGec\r\n=kyiv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAaSswMYxyB/2YnUSlu241Ua/FJp8MwDGwF6dW3G8OcIAiEAsYfnnuztl8+wDA9Zg9GRqmP4d8glsr6ax4KVhYXcJx0="}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-alpha.1_1600263622829_0.3319937715228203"},"_hasShrinkwrap":false},"7.0.0-beta.0":{"name":"ajv","version":"7.0.0-beta.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write './**/*.{md,json,yaml,js,ts}'","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.3.2","browserify":"^16.2.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (tag)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.0)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\n[Ajv version 7.0.0-beta.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) is released with these changes:\n\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe.\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas.\n- schemas are compiled to ES6 code (ES5 code generation is supported with an option).\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using version 6 that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitely added if you use them.\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n**Please note**: use [Ajv v6](https://github.com/ajv-validator/ajv) if you need draft-04 support - v7 does NOT support it.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- assitional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\nTo install version 7 beta:\n\n```\nnpm install ajv@beta\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// Node.js require:\nconst Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n[Changes in version 7.0.0-alpha.2](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0).\n\n[Changes in version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"16c905b67fecdeb32d46af9980c13e4b68037504","_id":"ajv@7.0.0-beta.0","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-7hwYZ5gefadrdKkDNYzOSVtHsZR9I1wOn8Urve2xA9aBnT9aijBDoRl2pu51Wpz/iSLP6EULgGxog6yjCki/GA==","shasum":"6bea4bf29c9ca253d7de11d8cfb869026381c645","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.0.tgz","fileCount":255,"unpackedSize":690746,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfa58oCRA9TVsSAnZWagAAm/8P/0XlKYf9Mrl1e6UOwHGV\n0Ru0MdorXd5ScN6AMWfc+hfqatSPeQKi/E1SX00NGXQlFI4IxibMYPTuqTgG\nbYj+IyhPvkd7yFOxdHE4wIhb3GjhZK32Zhjj2b/i5Qk82E6rZBzfG7Vhbg5R\nkYuUjqjDgtI8I2vjV/zhtYq+mCCRPn9vQIlHXLH5DnPz/FOwpRcyGkgG+1az\nfRh7sIaq4I3gn9dKStYqH2i9l7zB/xQyRtYInOc5MEuPe66v+nwypNXbDl6E\nm59r6Ep4cq8gF+gTRvLI6aaCSIpQCEUSdnrFTdn1cnNp4lL6Pu/oXDaUZ7hJ\neflJ+PPT/5pK4MtzIIKFaCLUH0RTp32PaKdgj2L1frr3baX/4/6JMVcsMSsx\nkffgzQP2qhgstBoxqD4uSBHHISI5MsrDrPSq3Fzu+o/v8QBSuwhchbC0A5Gy\niz+v2LX0krVW2qanCaAzUHD4kYeDlxpadLZVSz4Eg7RB1jn3e8rAn1ihqCFD\nNe9MeQIEeXvRp5Ur4dnrTwdiqRboX5d+9RD1vGfMasrWweNq48xA9NjS8g7m\nHy77ed4mTCeKjf5ipSElyGm+5DwAxVuOunZumVVXHWiq4B3Rbc6OBbzXkvrU\nIYQtu8OXwSQ0QXN+TtFL5x4zmLUrXWVRcXqZNk3SeHOg9ql5c53Y7JA0IVLK\n6Dx0\r\n=PCmN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGIpqqB9z09XenvadvRQgBBMJ1oP1iI8lk48eT2/Ihc1AiEA2Cv78i7p8CG6g+tTQle/A8k2TEm6EjrnlVYbNw2kLP0="}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.0_1600888615763_0.49029968574610594"},"_hasShrinkwrap":false},"6.12.6":{"name":"ajv","version":"6.12.6","description":"Another JSON Schema Validator","main":"lib/ajv.js","typings":"lib/ajv.d.ts","scripts":{"eslint":"eslint lib/{compile/,}*.js spec/{**/,}*.js scripts --ignore-pattern spec/JSON-Schema-Test-Suite","jshint":"jshint lib/{compile/,}*.js","lint":"npm run jshint && npm run eslint","test-spec":"mocha spec/{**/,}*.spec.js -R spec","test-fast":"AJV_FAST_TEST=true npm run test-spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","test-ts":"tsc --target ES5 --noImplicitAny --noEmit spec/typescript/index.ts","bundle":"del-cli dist && node ./scripts/bundle.js . Ajv pure_getters","bundle-beautify":"node ./scripts/bundle.js js-beautify","build":"del-cli lib/dotjs/*.js \"!lib/dotjs/index.js\" && node scripts/compile-dots.js","test-karma":"karma start","test-browser":"del-cli .browser && npm run bundle && scripts/prepare-tests && npm run test-karma","test-all":"npm run test-cov && if-node-version 10 npm run test-browser","test":"npm run lint && npm run build && npm run test-all","prepublish":"npm run build && npm run bundle","watch":"watch \"npm run build\" ./lib/dot"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","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"},"devDependencies":{"ajv-async":"^1.0.0","bluebird":"^3.5.3","brfs":"^2.0.0","browserify":"^16.2.0","chai":"^4.0.1","coveralls":"^3.0.1","del-cli":"^3.0.0","dot":"^1.0.3","eslint":"^7.3.1","gh-pages-generator":"^0.2.3","glob":"^7.0.0","if-node-version":"^1.0.0","js-beautify":"^1.7.3","jshint":"^2.10.2","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","karma-sauce-launcher":"^4.1.3","mocha":"^8.0.1","nyc":"^15.0.0","pre-commit":"^1.1.1","require-globify":"^1.3.0","typescript":"^3.9.5","uglify-js":"^3.6.9","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"gitHead":"fe591439f34e24030f69df9eb8d91e6d037a3af7","_id":"ajv@6.12.6","_nodeVersion":"12.12.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==","shasum":"baf5a62e802b07d977034586f8c3baf5adf26df4","tarball":"http://localhost:4260/ajv/ajv-6.12.6.tgz","fileCount":92,"unpackedSize":929154,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgej1CRA9TVsSAnZWagAAR0YP/jHA0M1PzBq8lWSpR5ri\n/7QS2sKRHRXJWldbw9lQNe2bIyCbFdzWfCTiDZjWv8g+8/CsJ/PkwmdAoCS6\nAIKXIMrPMFZ5lG6uNSX+pzPtaS2N/E74iaofRgkN1hTqb/5P1o8Dxsbb7SG1\nuxVUFnW+RzKEzWVji48/bCPmSvGoGl1fWU75aHbSwET5YA5hmNL1A6jbBffa\ns0tNJocggD3tZLKYzw5CbqEwsSLmzOmBg1HIhFUDtTelzDo7CCRAUU6rPdHp\nGbeR9KjsUwQstAiwukLUWBAmkEG55ACaS1FsZ9DDy7sny/g1ohcUXZVaC3tb\nYiNhkh5X2GSqCGaN8qmgmPezFtCfbQe8+oQk4i7jnxUnqujJOOSKAmThhER1\nWII8HaTfUYQj5cUWLc/Te0d8HlJwVyTFmzTPjE58zQS5xyIXhOLn/jGgP2Qp\nP4t1S7s8IrnovefPhCj1RSwzbJRYkU/XRr4mvYpwMTn06TE1GhlN6hkzjfL/\n3noaTGYXgxPzJ5LCjmhINan1BrqIx7oUyeAwPsevz5TnEignDl/NcdjhOnXr\nuyvfU8arfygvmzacp+1XMS2b5w+FLbbqrh+s1SI4iJHBxamhxE5R3jbqovXI\npClzWbOwOrZ2lzNBiojI3vacgk0LHGVy8Zhn+8jbhlkmIrTiiqMTVDBN9UvF\nGSGr\r\n=Vg+s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDkPRWEQ/1xKKRlM+xlc9LGcUY+TnlcRMLKDo9GML2A/AiEA/+QmhzkvJWIPyOj7OL175pm72Hst85SfxBAt+rGSmzI="}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_6.12.6_1602349300413_0.18453932021292485"},"_hasShrinkwrap":false},"7.0.0-beta.1":{"name":"ajv","version":"7.0.0-beta.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write './**/*.{md,json,yaml,js,ts}'","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.3.2","browserify":"^16.2.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.1)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\n[Ajv version 7.0.0-beta.1](https://github.com/ajv-validator/ajv/tree/v7-beta) is released with these changes:\n\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas.\n- schemas are compiled to ES6 code (ES5 code generation is supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitely added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- assitional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\nTo install version 7 beta:\n\n```\nnpm install ajv@beta\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// Node.js require:\nconst Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"a010c1f1388df438e220cce4bc7d99dc6042d8af","_id":"ajv@7.0.0-beta.1","_nodeVersion":"12.12.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-rKX+VjvPBBBTw+fXQ1b37Z9sarOr49/1QP5Clb1PSy/f8pKiU/+cQ2uBIFtX3QanL/3/LW+mKiw/G8gwRdyTEA==","shasum":"7427b34592edaf2eaa97655ec398e5d17991b817","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.1.tgz","fileCount":255,"unpackedSize":738367,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgfoTCRA9TVsSAnZWagAACS0P+QCqwKJSfn22MXvmNM6V\n4srVm7ktrXU1FJGyw96wMusIp0KpYs/Pezy2HDXUV4ArH6fDoHiAaXfBwsYh\njkL+LYs2psWX/57Bd1jpzTAAWEvmh6Hj/Ep7zrbSdmia6uzf53jITdgEKE68\n2xuuE/B23ChYaA/gTyQUDS/h2zdgXGmsuP2j+94TX0Py+FMP2zfKS4IeHFOE\n+rJvmCA3X32SnRTq+lKskRB2JRfxLFzcB9co1IHnRDWLVo8ceb/yLKdsjAEb\nPV9BydxFOPK659ckLjYOFfoM/vQN0MMJJDq8aLOKjzmzgVE5uUJjdpo8IC52\njs4TOcZZ+Tli9qH2D2dFfX6vulXXhnRVHhvh8x7ZXMwnMzzlZPs2Du42Y3Ca\ny5pU2e7NHb0koOQAbpENvw6+n3ZrlyGLzEFEcEkwZkneR3Zj1PExtzvtsS5K\nGcDi+Tx1JB+Lkf32TtMBYqFItq78zyX3KP8qAZWYKI7Yum4cUALJVmT3pYdl\nGFfmTRLWhJ7d2qnZROlTL2dLsLMWqDn96RA/KVHo/AZ8va3xNu92rB6CdG4a\n158PzlxfMYS/CsS/OSXa+Ck1jYpu/8iBInHNqDts5bhfMTrU1sc/WWquhhv9\nX4/Ep7LNgWlMSZcov6WxRRrLWYlLADYlgHd0OBMv8FniXtwE6CJohVckde6/\nDBgm\r\n=VDyd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCysd9B4O0F/87aH1U57e7JfoVBZIiyXqiFDInyz+l45AIgfE4CYZpAJkUgcZwCIhs2rtTLpv/42Y2gFGHCNIyxH4I="}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.1_1602353682748_0.12518119863012855"},"_hasShrinkwrap":false},"7.0.0-beta.2":{"name":"ajv","version":"7.0.0-beta.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.3.2","browserify":"^16.2.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.2)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\n[Ajv version 7 (beta)](https://github.com/ajv-validator/ajv/tree/v7-beta) is released with these changes:\n\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas.\n- schemas are compiled to ES6 code (ES5 code generation is supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitely added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- assitional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\nTo install version 7 beta:\n\n```\nnpm install ajv@beta\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// Node.js require:\nconst Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"47263dd74119acf246a519805ebf7d12cdf6a44e","_id":"ajv@7.0.0-beta.2","_nodeVersion":"14.14.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-QNYgGgTZ370cYyxsIpQWt8HG7fxBlYrb3wW/SVxsAJ9qqVh8bmbszwNWut93EEhK+rTOY2IKj+SOQRo/7mvQiw==","shasum":"709980b7850183a027631160c01954409c05cfac","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.2.tgz","fileCount":255,"unpackedSize":732099,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJflG8DCRA9TVsSAnZWagAAge8P/iVGNEvLlGQ9F17X43Br\nCMV/muJDLIPuwZelOmCuMUTl0Oj2zsaGdhkWHAgIZUQsvrkBqdGPiTFwv53c\nzqt1AkX7ov9a2gHQWtfjaJcMB5rglB1PsH9f2g8WrIZjbz4PLpmfhQviB0fO\nLCLABl8sw0JmfQ/JyhVAdM0aUdPPzdGIMPE0u0hbhwEPBzoy63rlfOTWz7sv\nXh4eg4wSbn9aKsf/VPTc2rOY6sABgK2o/KlyrAjLlXzenF3hhQguWCe5oijz\n1LLw5iyzxar/noWf9WCXE/1V/dStbWQAwJ9uRcEzAKe3Zw5vkX/48pJqpQuJ\n0MR8i6y+P6LDdQJ0ZUMDlHpIiXfAPM7jTTi8Fm88J8oJLnHnnldCtBDuEj98\nhL5w4kqPrePlTyau8MjUu5twncLJWcAnIPEtM+NECsHvFLlMILQBjxNGzUSg\nVFKmtKGX4Th5wxZop4/zssZ5lhazB2mSs2FvXvrcB8bFUdgZbLGbs4hjjl7g\nn3Sh//GmTpSrh/5wGcyzjKkJq9McBO+5ZjEn0T1zDe1fQFZrI1pj+wCNmDWo\nYRc4htL4d9PynPSQZ0K9FkF8pGbBwMbXbisaLxJEyCUwg0vnEcvRr0ildRB0\nk+UEHvKcf263vkDTbaQYXjl0PZTtb/5zRFi5MeiIVXgN92WI25D9L6FpsO8b\nlECF\r\n=gMrc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDj+BDeichbcl7iIjatpAqBz+ncNYf6zs2DXtxgCvWE8AIgAOdXs2DRgrPyKOVHJKyF+KDcVl6yeJN3l9H79zJeLXs="}]},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.2_1603563266781_0.7921179124179916"},"_hasShrinkwrap":false},"7.0.0-beta.3":{"name":"ajv","version":"7.0.0-beta.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.3.2","browserify":"^16.2.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.3)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\n[Ajv version 7 (beta)](https://github.com/ajv-validator/ajv/tree/v7-beta) is released with these changes:\n\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas.\n- schemas are compiled to ES6 code (ES5 code generation is supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitely added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- assitional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\nTo install version 7 beta:\n\n```\nnpm install ajv@beta\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// Node.js require:\nconst Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"8bedd820360e0f6be3e9a2ae04059546e58dc5b2","_id":"ajv@7.0.0-beta.3","_nodeVersion":"14.14.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-gUGVvM4NmyqrFvCNAQnP4P7FC0RjxMQyRnrXpozNglBkDJnTysVbvycyOZUy5n6yLKSqVDUqWZBXj7dXINrSqw==","shasum":"d34861ccfbdebb55bf9f49a08b29f76bf656fc5c","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.3.tgz","fileCount":283,"unpackedSize":795088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfo7VOCRA9TVsSAnZWagAAMkoP/0WFOe2VsVhWGMmVditG\ndIikPWVO60u1rvWjPqH6w3FR/+HRxgAykGaIWdwllZyAgvDCrtik7JnuVw+C\niUhZOyPiihOn2EybrGs61fZpV4Cfjy33XmzIGdk5smkezWYq3sapPhifIrJn\nXm3NjFrudtVe0TnSbnM/yIcArK3CK1ZeaZuleBJhbtNlJ1IjjmlbiTPU49B3\nVseinnkTvPoIBYot+b3WYpjO0ddyuZaJwjLdvAaffmRy2VMBnd+xdecXEDQc\ntRttk/3lnZ+kMu/kOwgDOfqjRMrFpOG43H1YFdbEj5dqXle6REubw/7Vdv10\nHdLSPmv4IOn9s8tRpDJMDJS/3kzY3V8olknTBzTIu0VPcwyw5aYKQwOQpQ+K\neK8jlx4D1KTQFb3LKzMjw9y90n8J98YZr6d5vauJv68UOPd1jlKMzXGKRcYr\njwlRPMaB38sbBZaaLYRIgCKArTcr1XQbpDRP2/cThL+3mxFb50qw+Z9cuqNy\nNJLU68bZdLjdaV7ZXlcf7L3Pp/SDM0EHeiS5HqpFdJseEMKEMVzPH6RPOQoK\n0kLWGOryqXJe1wIzbaX0XULdESj5QtYiIm0r24MdT1rlVkGAaFzqr3wSvTI7\n/T95Gia27tE+1ZFWBY1Yd0E3I2QFsofdof4kX7f5HpuCO/A4uAwWJ70NYF3f\nWFaa\r\n=Swfi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxR32lV1GIO/3sPW1dwEhRn1Ehvr+lrCCp60xrpgJQMgIgS6u2Xz+Q4XFKJkzPHHF1hQG/6vuKn5TeiSq27xh2G+A="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.3_1604564302050_0.9773755126453094"},"_hasShrinkwrap":false},"7.0.0-beta.4":{"name":"ajv","version":"7.0.0-beta.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different './**/*.{md,json,yaml,js,ts}'","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/**/*.spec.ts' -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.5.0","browserify":"^16.2.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07 (draft-04 is supported in v6).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.4)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\n[Ajv version 7 (beta)](https://github.com/ajv-validator/ajv/tree/v7-beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitely added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote refs (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- assitional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\n```\nnpm install ajv\n```\n\nTo install version 7 beta:\n\n```\nnpm install ajv@beta\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// Node.js require:\nconst Ajv = require(\"ajv\")\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"a416acec42beeb8a0e706779b0d40dff77c319e6","_id":"ajv@7.0.0-beta.4","_nodeVersion":"14.14.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-c6ROIXt0YR6uu3/XfwpXhRetEjNrmaa6WkofjGvO45rUXYNi0S5kI2Cwdm6vQBOnvzjCHSzUrRnCx54SaE1dgQ==","shasum":"1885f0fe044922ca468729f6b299328463379d37","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.4.tgz","fileCount":321,"unpackedSize":838351,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqk5rCRA9TVsSAnZWagAACeQP/R5V17qvH3RcBCxsng1f\nGosK+slAqLSddLYX9WmdKbCutRi/f1Zv/GsSF4IhFJc0fvBvo9/qsGdVM6dm\n2KRWWz1QUHJOgcssO576l9Pce/nd81oUwbcAVZdDG3MgcKfrndCmHiDG6yln\nyDcg2POOviQ0WkNq0PgkZj8nmpFDPcg+xfwVRathx0wOygnrvaWYEro39l7V\nR/fsEdH72lrn7y59UWTr96EOHbpOdXBeNha2KvFmY7cxx2BdKFTGnIuAA5Bi\n8HMbEPQ+JnrgiGR6P7fhP7Ar0TfJ+jSO6MQ8/mcE/XIFZWSap2oeLaiyE7kR\n73x9Q0AoJXBW/9mMDUq6h4B6hj6TbmhE1vhD8FG9D9ScpNmVWX4oFcmQvWXI\nIfUDRKp/Ze5AIrY/ipIGs6NuVifAwGuhX0cVrl0iBfWw3stWM0GiJ9U66KRD\nVwr2mSojJaVfA2QBh0VDHUSaxDy6TdzXjA+MKiTI3e+tgM+4iQBAgyZJ7lCd\nWUEdqhVmmDZYWfLB03OykvI4i2Tq+HevCMFYwgmowgjk5K11YgD5c15S8IFa\nigCaXG1LqM5F4erYWqE8c9dUieK3HQDtgHYVXQbIbMx/6U8cpW7SicWxs9MR\nvv4waoSNx6LdnkMBMN6BI8YrGGv9Mbe7z8GnZO03XtZrxfxdQG6Zs6H/NrJV\n+nhp\r\n=97lt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAffpPCYJ21wN2qcfen/XpN/qM6ncwSLd+3wP5f/9iwwIgLoaHCh+odS3l6Ll2OD/Hfa50odKi0djNaSj/pLJN2cQ="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.4_1604996714930_0.847305201110609"},"_hasShrinkwrap":false},"7.0.0-beta.5":{"name":"ajv","version":"7.0.0-beta.5","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.5)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"5ba3462b5c13a90ab2ff157577a53c12bff9fdc6","_id":"ajv@7.0.0-beta.5","_nodeVersion":"14.14.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-Pa/C51m4ICBeeIXopCOzeAtbw44rxA9O3oFCP1N8y3Y6TZU3YMSfobhEipvEma5ln7tYF6vOmEuaDbc7ByX/Bg==","shasum":"9aab801e671726954e2875fa8f87b0fec1a1082e","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.5.tgz","fileCount":333,"unpackedSize":842070,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfsVzACRA9TVsSAnZWagAAS0IP/i4jA0DSOtBmz/4utf//\n/klbz6y0LGAi8qidgICaF0Va17GG/Tlmc3TM5DJlbjH4X7r6KdkHI9r3oQYt\nNxMulnWzvXirNwaKdJO0/jWPjU2A5uCaOAHJhu5ZYOvGh5fxudpfGr7BeV8u\nPfIJFScC6UIeAJE96fBsHEBabQ7hzSEYTFLjSp7EhPhQeL2dbtJwGBR2lBrM\nRpnHhGVfK2S47p9e863eUd+hRFvim3Gsendzq8/h0amfirMPb/WSclPM8ZRh\naWCC4IEv9FdnokdjrrsINzbh/fbNroqgVSRwDimIazf+XGC3OZKLutDYmq2G\nteI09KdLElM/anCulSvAlXpTH674ffOGoboxRhCmrnNSuHBwhmOZXn0B+FWj\ntzM9a8KjE5m8fAvuzY5Eqv2YFpo6xeATdA3eUAnm8oQ5B24fHvgGLCZ6cPAN\n8FZ5bZznmTd39bSPSHJLyn0vAW6GRJQO9dnJMcFcAH9SdfllfY5zm1oTTk2E\nxAHzXy4XayHMH6mAgx/qv3rFNP7X/+c+DSBnvOJ8BiRNM31yTqV4ri1wHGdR\nD/6RHAVkJKMzFwp7iMex+pzfzMUM9aW2AcUvvKTsLEBX0VwEfyEaiAVYZHMe\naaN9cCF7MgbszBRuHef3KyauwL8yP3aHYZ4kIMl2OMEyAYbfTfQjxG5bVu4v\nqOM6\r\n=naQA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpWG4JfBdeJgNypPV1z06x++Ybd5GPa837xIVIUA/JyAiB8eJvye2piN3AqiUKshfow1WDQovAtyxT/OyHcdmvePw=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.5_1605459135510_0.9674409509446347"},"_hasShrinkwrap":false},"7.0.0-beta.6":{"name":"ajv","version":"7.0.0-beta.6","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.5)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition](https://tools.ietf.org/html/draft-ucarion-json-type-definition-04).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"2c4e5bb89c577a6f2d6f10abf8552b92acd00af1","_id":"ajv@7.0.0-beta.6","_nodeVersion":"14.14.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-9aDR4p4ReYBS1XxrYONdWuFVRweLjJTv8RaNkBEpJm09jkVcVYhtaul5IL7Y/x1RJ9UakETm0oBze4VHIjq4nA==","shasum":"506037b27b7bd62e0e23a237319d2d11dcaba939","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.6.tgz","fileCount":333,"unpackedSize":842286,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfsva0CRA9TVsSAnZWagAAkacP+wfksrhIiE8XoF5A2AWm\nGhnxw8zMkOydVgdGr4CUDc/UC/syvvDEWnm7/Y97pWyb8d2NtHVZkW2p8wiO\ngTAqX0/Xnf2J/qTB67M0qt7rYD1SWFO5Zc/w7Erd5iEdYUDw/ZKYNyr1NERR\ngKLZ6j4atelYJmxDrpE43z/43eZ4zjVsdix1TBDHeUJhqUBaIXZBDAid8LOk\nLbN7dTYNkpVfKLIflzScBdE7CeKcovopYTJUNaUkedp6mPVsA4f7aF2TwGsG\n+evcXs9xiZU4UFttvs5RElkVBKtktUrE2ixpnT5Oa8WxZYycVZ2kcE1NVq1Q\na9370wmH1P/QMjfvtNJQcXLjDkwVd4ja7PXhAu8KJtH9gZOGS0dz3wKR+715\nfRteR/9GTgy9orEaRQwwm5qAaJk4zjHGXOtnY8kqwFBH7VLCn6k1U7RSwSPi\ntaBVEsxHg4dX/0xG5/8uSEwIiGMwSD4uFRxM7e+zkxAEle+Et29LiASNewNL\nAosaA+C5g5J8ksDloYQjoILhIcqkbHHcW5h+rkIuSmqfwO8W4yZceJcpk/0D\nIsWMpe+AjdeM0qYIiFTzRqpHOdsCOwOEaAHCvNP8vo4J3y9hor3BHbOTRApu\nW2gwqNwypLYHLnNx9doBXWFIgg9AO3qUU4DflpelDeXnVIIga8xL2GRovwuQ\n3YfO\r\n=4SIg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEaWecikWXxwH69reIZ1irX9vHgko7QONX8RARKRHGICAiBxQ25+uJENzrckSdMw5Harw1zQjqp5pXTY++ftlRduyw=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.6_1605564083731_0.6920167652138527"},"_hasShrinkwrap":false},"7.0.0-beta.7":{"name":"ajv","version":"7.0.0-beta.7","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run build && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![Build Status](https://travis-ci.org/ajv-validator/ajv.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.5)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policies](./docs/security.md#content-security-policies)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policies](./docs/security.md#content-security-policies) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- BETA: generating standalone module exporting a validation function to be used without Ajv (using [ajv-pack](https://github.com/ajv-validator/ajv-pack))\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-pack](https://github.com/ajv-validator/ajv-pack) - produces a compact module exporting validation functions\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"b9f674e3e8156d554595d3d606cfe2ffa4ca56a5","_id":"ajv@7.0.0-beta.7","_nodeVersion":"14.14.0","_npmVersion":"6.14.9","dist":{"integrity":"sha512-1VY5E4aN4P1lNL+Y+qCGlL0IxT4WCt/f2xWnoJ5qsXCc8fxrKHQqoscXIAkjwhXX+iw10cOtPgPNUto/08Mnkg==","shasum":"39f2c8c8da65aa6889bbf9160ab6c050687eb495","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.7.tgz","fileCount":333,"unpackedSize":843794,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfuk2SCRA9TVsSAnZWagAAIt8P/0xnHparSC3yvxj/gftG\n4roRdQZfBfgzcpqMZLivVZhQJ85alB0JcdnWgfIKW5gqdPqhkfcbvDSAR8Am\nwZrnEiChtZOBCmBAI5TO0cWoz3jSsvddZ0YppDbDNMFJnQKT4CaQeK5nTpGi\n/TCPDQ8iWTQk2LQWzARy6vOZeYM76Kh+nCWoqXhycde0n5G28XNB1n82eQe9\nB8rUeIcR4YlnK6jD0kzf+I3GnQCfQiPO/gsEGZwRxg/WeYt74cUpRLpf5CLd\nu0mMis3NkX8Mc+IGBGC+VM4ChPGgTlFQHiV99ukMFbbci6rVTa/FqtCc6swd\nR60iuQEjL4RaW2hd/42u6pgZiyqUEZSGsGArJxyihzTGzUjLFiWm2UL1c7y4\nE0+ZzcRx+woCmDf0X+a7urCloAKorwUVTIfFG2mcoyqRA5cE30Dv9AMppUHL\n/ofhRcxA8jDu9eqNYVOTqQ4kUWxZIAK8hB7g/ZWOhWxoj0SwP6eDXr8JtQ36\n+Vt2/dJiGYNpg+9WQo6nBPZXRGYjE5srLBnxZfyTj2jFuN/3a1I6f+mwpVYW\nIWmm+x2EOjHrt0nVS3FYN1tubAshQGIFpZi3/K/WeXtnXyxU+eMXnxDDPgXN\nLrO1+dP3UyJjBEzxPLUVMG0JrDoclAo3M+d34N93+oZqzftY8DryWHgq056I\nsKyo\r\n=PgEE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCN6gnYTZyTTF5UsEuJh3dxKPJW/fjn5m3nfWurxifH5gIhAJ11gsVhvg0F5epSBPbIm0qMyC6uelo1F+/bzMq5luaI"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.7_1606045073872_0.07561729603504608"},"_hasShrinkwrap":false},"7.0.0-beta.8":{"name":"ajv","version":"7.0.0-beta.8","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.6.1","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.8)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"2c25b22620a1527b1557f2edaee9b7a226a9877a","_id":"ajv@7.0.0-beta.8","_nodeVersion":"14.14.0","_npmVersion":"6.14.9","dist":{"integrity":"sha512-vzGJf12dayS+Z+eX36ONWWZGop6psAtCU7xDoGHtpPbdr6kDr1VOKSyWcTJyFsnm9n9IafUDYCaSC8kF6qGUaA==","shasum":"9eb3b9277f18e0021d41823e8d9a2585da3d397d","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.8.tgz","fileCount":346,"unpackedSize":863223,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfw/b6CRA9TVsSAnZWagAAVQgP/2Boc6ZPFO+EsQf4evce\ntj8UMzZj0KwiJ+IHtrqwooVkEYOqLxeSJ5q1/Pw15VGDruz++9tPJFd7ilZO\nBca3r0VFAkNJKcNvKcHbtMIod5URXRQv9Hewji1ERva0kr1l2v92UdMhhH9/\n0jBb4JKO+5J7LZVaP29ch3Bff0oU60eM41DKe6dig2lMUDhPvWKqaaKrqTGc\n4lnlZCeVuADQhpaMie1uqDkX3w5sEdmW64ll6LUqPrEqGPvbqE60PrMY5ksd\nP4VHF+wEaGBB2RKfkymI4hKp7Kw7QMPRTaVlBSx98bE0an0Lm8OT0Bt+3tav\nJ40760czWVqVdtckCoDW3p6jnzmJWNeoKDGtjYm5yWfDAU8FXZrDV1cR95hL\nqgPRC/8y8z7PK38utUhiwHWvl/R0LcsI4/VZpaZbAidDASnctbwB0wyGCjMC\nmCtFG9Xcd7e+Hi0ssSnP0Cr0egAsEn3tiYBWAglta9FhdL6iYhrSSnr3gQiP\nt+GOQ1tJSGaXYpD+teGAZppDN/KD9ZmC5YxOrydkvHCn36pUFtrS3ccFCJJ6\n6Ohnrw+flKR6tD2f1EkV4Nh/Zoh9hciqDTbjq04w2Gxa3zVAWzMFnprScccg\nZVSxitsdLq5ck61gnIhG+FkHTvEIZGcM06pfpJPUZoHpQzlYnZ3H93iB4/yp\n+rzn\r\n=hMCQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHm9inzLFcLwlhUnnybgqFoUsSx9veEwEifrVeKYWZcrAiEA8W9VdmlDhIT0PLuxTvuDyRjGfw+n2ZRzOIgW6+SM8U4="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.8_1606678265485_0.21792584008426297"},"_hasShrinkwrap":false},"7.0.0-beta.9":{"name":"ajv","version":"7.0.0-beta.9","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.6.1","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"7b4402e285cc572447013942f58f677b8252a0d7","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.9)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// optional schema type annotation for schema to match MyData type\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-beta.9","_nodeVersion":"14.15.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-XTTuOzIBFMakbATMb54pjbqFzMTXqHgWmahPZu7erwOQRXpGGelAyZd3S5g6iBiMg4R60fQUyWm0wc8W3Sh5OQ==","shasum":"f67e6890e15b95b302e93338c573b34762f64332","tarball":"http://localhost:4260/ajv/ajv-7.0.0-beta.9.tgz","fileCount":346,"unpackedSize":864148,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfx03RCRA9TVsSAnZWagAAOn4P/26ANbLohfWbnwpE4CU+\nJagtw1XYRMe79TgERZTbkBhBjivAOoTWoSnYnvpiVtUvpDih6vdq9l67tBZY\nP9jne1VhvLnLpgamJOLrLi422NlANd8/DQ4p8fCyFdPGhGKgibEVBe/4MwDq\nk3MQRIxFCQ2/ZrHZhL1IDHww4a24toe5tnbfAGE12mn1037l5ew6rsOftK1t\nEJRzEG13YTW5WaT8i6jI0oIkWmnChOP5yj/fBGG+ir2F1qo3mRTwk0geE6rn\njRQ0YoPh34hyfS5MyqZNJ5hquWJ8AtzOLlyH9LGaXDOwiqCpYlJuH+rD4NGI\n67JwdK7U2nHHKKST+CHTBKa7m2K9Rd4FKrtJU3b/urEim44KwHoQZJ9fagan\ncbV6woYpwBWpHYCfOamdiOvZWZ6a/UntuQZ1BhnFqrcktDSeHyeVwkazlgMg\nJ9SWGZOdq4jBiPIbcDJzfZar6DQoK0xaaTmRA8GFKsMSomuvCSqAlyMb5tuI\nva1J/PZDekVty/mK9uZ1/Jf920swpXdZvpKjSgMGY5arjfWYui2Fo96VKifo\ndt3O/YfBQEfLTSrNmt+zpuUbTru9EPVgAp7MhcvUcVr6FgP2KzjudGH6jCKx\nNDMw3dKbijcVD2wk1/wr15QgUlRuvR+z+uVLZVQhqKVQW8jeVyvVOr3sqLs8\nw0SQ\r\n=mmJM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGUEGRVSr+MrPNekIh0L6CB8yv2quc4GSchkWFUohs/KAiBws25fwe+k/2VlgjDRBLDhQSGMXUpyYT71ms+y57Awgg=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-beta.9_1606897105206_0.24836913702738705"},"_hasShrinkwrap":false},"7.0.0-rc.0":{"name":"ajv","version":"7.0.0-rc.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.2.3","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.6.1","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"cf39c22267ce6eaea47640efbf4a6a997e0862cf","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.0)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-dG0RJVjrKMXyo69dCGl3qSbMVsEiNSgNaUAzNicH88lAKPeBBtepiR7fPf+JZvlA8mXQAqVxIFTurbatuAxXug==","shasum":"ed024372c6adbc9ff634bb621505c1ce85cedbb2","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.0.tgz","fileCount":346,"unpackedSize":866450,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfzPseCRA9TVsSAnZWagAAyRMQAJQ3MsA3vTkd2nzMgTkN\nxNMYWHFhIv987/tdzQfNw50AkT87O6w+/LO6oZ82lU2SjiX/9QcPNuA/6EEt\n//TfYJ+ppl+m88/VpbHP9mR+fhhLLQraEXj7GVu4+JtLCVn86HpIKohuOXi8\nz05457dGPVXnu3ODdhbxKfpll5/RRTF4IfBOJNdXKEAXlpUbudUSqz6EYiMV\n7iHHggehTwKdyWO4C4Ev2PxyaUTJJAaCij/eLvHqPqqANf1ld1AodgLENLUA\n9e+5Ag4DqH9DmMhWlBlY4JvupKx2BHEfOs+BAKG4E/Rv46uhO57QsGWe4hnD\nd+OFYY1qHkYR/fX3lN/12tTkuNCyAsDbfPFHFnaMmq/rLwbxPy6AOoupSDOj\npkQyhdl37u9jIH6xuwo6cV4F8SoaXur5ojSKZ4Xkq8epG1XY5829rPI7fC6x\nfMYJYCusHu5bwREhWrjDjWbIbertajHHJTf4dV5oT9PWc+Q4Zy0cnDE9VxQX\nKqF6N82F2jXMCtHs43Wu0CHPMMsx+Jli2VcHh1GfaQBx0baL7CLh1DMZwa93\nV0pm2hq+8RU9sqnmcEFzslPNSMgDIv4J7u9RMC9cvMX5I9uImp/Z7neEdfXR\nFedtppP968Nsx3gVHsXNysKpVif7X8AJuULd9jTlvp+ocYOXxELrwTAaOAa3\nHQz/\r\n=RPYG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDRCJ/7sXCciVNJpDKqiuGUbQMl7uoOJFkawmFkQOQRqQIgNjb0Etab7Pc3mTcRf8DIT9aQHj5P56+DHvf/mDSYFdY="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.0_1607269149355_0.03848574561269591"},"_hasShrinkwrap":false},"7.0.0-rc.1":{"name":"ajv","version":"7.0.0-rc.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv Ajv && node ./scripts/bundle.js 2019 ajv2019 Ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","watch":"watch \"npm run build\" ./lib"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^0.5.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^0.6.1","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^6.11.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0","watch":"^1.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"2721434704ca17edcfa801cad43dc2b79d894f13","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.1)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7 (beta)\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contents\n\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [User-defined keywords](./docs/keywords.md)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Plugins](#plugins)\n- [Related packages](#related-packages)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Tests, Contributing, Changes history](#tests)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)).\n\nThen you need to load Ajv in the browser:\n\n```html\n\n```\n\nThis bundle can be used with different module systems; it creates global `Ajv` if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrate schemas to draft-07 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function\n- this function accepts ajv instance as the first parameter and returns the same instance to allow chaining\n- this function can accept an optional configuration as the second parameter\n\nYoucan import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n## Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification.\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`).\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Tests\n\n```\nnpm install\ngit submodule update --init\nnpm test\n```\n\n## Contributing\n\n`npm run build` - compiles typescript to dist folder.\n\n`npm run watch` - automatically compiles typescript when files in lib folder change\n\nPlease see [Contributing guidelines](./CONTRIBUTING.md)\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.1","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-LGri6nQmALezUc2p8J3eHqlRYXK1bVPyHBd4IGBOaCgCCTM0naZssHIy7SpFX2ZqDe7A0DJi5oCljCwT6WXLrg==","shasum":"e69bf2e131a6c4f5c24c7500ec83b62a2812bf29","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.1.tgz","fileCount":346,"unpackedSize":868411,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0TheCRA9TVsSAnZWagAAUbwP/iDtCnjy4dMvQ5Qgdp0c\nnG9taR5R+Mjg9cVI+FzUXrsajtukBSOiHelGRtcdqmgshXBekfMoxuEpVeHW\nEdDDD92slmzpTi+UsYP6E2DZRLKLXxCjf5qjUc2PwzMq/ev9y5I/PcmGYNyI\nNZ333jbX4p0ZxhcXPSVBbOlTOWIA/kMcdJmsuUo8EI2CLR/uPuMwgS+klzj4\ncYo5toTa8Xmn3MqXNrQAhAnwpeZSzxmI5qijwFVaKeTQfg4ebjicvROnSTBb\nQSNV0pQ0tLwieMF+9GwUbI7TOW/Xw3wVpsSg9AyHWgUQidhZ9zDZ7o/F1m88\nGVYvCRhLbeFsE3MoLvrPzWnOVWjOwiNzBUsFsK1hXWWE8YDMKCubxVHsg9WD\nkqGyTN5G2ivROnyAgJ5tQCsMAO7cQZAZZSEKjDly8K9GkB99ZeqYCIGaR3XZ\nxzlNBoWMs5+gmULzqNWY57TYTTTwGdg8cUxTLTQHctvwlALpRpuEdNdkklQe\nk6dU94dubnUnqpAoN/rjkK+oMe1Z4OsaU7z+W0UJkYEgqKA61M9Mmc8TUp5V\n/ezGeufSLRaKjfpz0J3XiUhXB0UvLUHtWdXVQKnHMg4i3jNtKQTZmyQKMDsf\nAtPS/iB/XHEU0S3U6XTL+l5uPi1lGZRQUduTq6Ez//Uk6YKMjNsfAlyPREW3\nJf0G\r\n=NfUC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6O4pyF6QZUlJjSnATN+Ylw+i9JfBXE+EKn0WIfyMAPgIhAJ2speMpry3+GI0dbvSinMCItUtQEEXTOwd71odINiO6"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.1_1607546971649_0.7851852167860442"},"_hasShrinkwrap":false},"7.0.0-rc.2":{"name":"ajv","version":"7.0.0-rc.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"3545374786e1c121b0f4aa65f1c2bedfde9cfa04","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.2)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\n100+ people contributed to Ajv. You are very welcome to join by implementing new features that are valuable to many users and by improving documentation.\n\nPlease do not be disappointed if your suggestion is not accepted - it is important to maintain the balance between the library size, performance and functionality. If it seems that a feature would benefit only a small number of users, its addition may be delayed until there is more support from the users community - so please submit the issue first to explain why this feature is important.\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/validation.md#user-defined-keywords)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundles using `npm run bundle` script.\n\nThen you need to load Ajv with support of JSON Schema draft-07 in the browser:\n\n```html\n\n\n```\n\nor to load the bundle that supports JSONSchema draft-2019-09:\n\n```html\n\n\n```\n\nThis bundle can be used with different module systems; it creates global `ajv` (or `ajv2019`) if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in a way that is not compatible with CommonJS module format. In this case Ajv bundle has to be loaded before the framework and then you can use global `ajv` (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrating schemas to draft-07 and draft-2019-09 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas, validation keywords and formats\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/validation.md#user-defined-keywords) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.2","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-D2iqHvbT3lszv5KSsTvJL9PSPf/2/s45i68vLXJmT124cxK/JOoOFyo/QnrgMKa2FHlVaMIsp1ZN1P4EH3bCKw==","shasum":"9c237b95072c1ee8c38e2df76422f37bacc9ae5e","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.2.tgz","fileCount":347,"unpackedSize":874034,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf1m1kCRA9TVsSAnZWagAATIMP/1+dyjMTADUY+4yFg3El\nBrlL9ueY/bRCsZ6uSufwY+CzoFs7FTn0WghEPgBhgN9tSdTklGBbNoCqdHmf\nuLK0mkGW/tOKPbm4d0myuaTJ4tqeG156Mnol5guvH4his54UolkaTmm7zGjN\nDhD95J3XeBHcTyUigVPcmfNIkeaZCxZX1srtgbIbDgOl1MApxB+KheaXEYEf\nWdO7/LGI3Jg1Te6Mwr9xjvZjWBFnhrHYAUgQ9vFI3J1YV3ZyQGA2+KiiIEdH\nAG1soX7X2s2mkavGgoLKumbQQMxIqjmSoVRt++MyM9CgdZiqP8C/jUHdI7t0\nlPav1xBjgfta8voU1t3PE60sj8VINsMJcUf2TW8XrhSG6fE3s5f2ImtRo5x3\nJ3LWz6zq9VMwolL7uNd0LCUIvZTgN+ZGCJbSlVvqsEjk5/Xm+cx6118iaCy0\nB4jTmH8Jx4gZXKYEAsd+vNJEtWWh+g688G/jgeg8Jbt7+3V9socUw6dkxhyI\nf0uPascnoZ1KXUQ6h20AgsVBbJkvmBs6qlCtwvsaKdiKQtKgvUF7jLwpM+1R\nsiurtzJG9PVwmz7PCK7ieO886bPuLEPgGkoJLK5yx4oWaNcpppsv9PLNDs+i\nHGazdH9OVFFT8+glOM8kFpijyZ1pn4nt1/X4zOKYBiUnMijNu3TImc4EYIuz\nIgB1\r\n=B8wt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBBQAJ8YPqiIfkDxRi2sUho5H6G7DfX67ukBwEymTQ/OAiAgb877IJTjLDDHqDDVgTl9ofRLS68YCvbtuBT6VAivTA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.2_1607888228072_0.3082910675740216"},"_hasShrinkwrap":false},"7.0.0-rc.3":{"name":"ajv","version":"7.0.0-rc.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"680532989543b60b449658aec35b33f7c07ca937","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.3)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\n100+ people contributed to Ajv. You are very welcome to join by implementing new features that are valuable to many users and by improving documentation.\n\nPlease do not be disappointed if your suggestion is not accepted - it is important to maintain the balance between the library size, performance and functionality. If it seems that a feature would benefit only a small number of users, its addition may be delayed until there is more support from the users community - so please submit the issue first to explain why this feature is important.\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/validation.md#user-defined-keywords)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundles using `npm run bundle` script.\n\nThen you need to load Ajv with support of JSON Schema draft-07 in the browser:\n\n```html\n\n\n```\n\nor to load the bundle that supports JSONSchema draft-2019-09:\n\n```html\n\n\n```\n\nThis bundle can be used with different module systems; it creates global `ajv` (or `ajv2019`) if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in a way that is not compatible with CommonJS module format. In this case Ajv bundle has to be loaded before the framework and then you can use global `ajv` (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrating schemas to draft-07 and draft-2019-09 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas, validation keywords and formats\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/validation.md#user-defined-keywords) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.3","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-znrbMViJVAr+wDDup8uVW0QDseb2PfAlfnOb8LrpRBoi03LdXoDLhBH59+kpSV+jH7hJvSz9Wdxe7ZaIo5mMzA==","shasum":"2454f695767ababa8d3a176b04cc0ac96a0e8f6a","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.3.tgz","fileCount":347,"unpackedSize":874385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf17jPCRA9TVsSAnZWagAA0fQP/A0MYjzYtE6Ksxy5cl8G\nfSLtcukH5BO36FT2OfFb9aLhr536r19OvQ6fc6fyzH8ZTSiUufd3+sX82ubp\n4jstmer5PZyK0poJcyypnIyYDoxsFfuMSsjaAJCpkWXaDehoj8iu9zgfGVy6\nIhn9eTPCv+QHTvtzQHXAt8jyIlMBNqOaIWsktGal1f+7Zd7Mz8AA760/wlzR\nIeIYNQYVW8mwH24V076i6CWV7VhD2ihhPpTknEF9Mha0LA1aZqqMyvGdnGHP\nFfYA/9BrNEPhA522O7pUaeUi2tCVigfpU2G6ULxkbqeqHMON5/llpTPqwYVM\nEcr0QQaZbRp54+LVJC68ki6QIAFnNPwAFcrEnhHYhw8ghjSN2SWAP/A0pxri\nzSoXR6vFBM775K84mJAVKnmuFbcUwUKnrBB+Fo4l6qTbXPQzJha1C9A4sdfW\nJ0Jo9uHAeyaNRSPNYvJ0xUbgaNqB0LSrankDJIuw57fx5RE4mOQSBj3iVRnP\nH0BgZL4vPt9ngpBenH3w3FiH6W8VlRD5Z9+lIZ0tBOsWECO4e2huQ9e0aFEB\nTzdVrfU1t4Tmouy6yshyIrLI/fXMgefuAnk6PR3y6KOuRmrsXX+WeyP0fWO1\ncB5h9JW1HVRtBfwQ3F/d1iFnXtHpLasc5CEi5iqQuO+kH2VztxXbhDo7E+AP\n8tz3\r\n=EwF9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC4Hsi4VzL3DnaqOZz1QpUeF6EIATcgx4Dmmi/gZl6DmQIhAIzvPhg6SC/YtplGN2iGDYiuV9bjani3moOCyak0XHOE"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.3_1607973071365_0.8885780698187438"},"_hasShrinkwrap":false},"7.0.0-rc.4":{"name":"ajv","version":"7.0.0-rc.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"82d052175ceef1e4b5c1890f60fc4c4b5f6e5ef2","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.4)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\n100+ people contributed to Ajv. You are very welcome to join by implementing new features that are valuable to many users and by improving documentation.\n\nPlease do not be disappointed if your suggestion is not accepted - it is important to maintain the balance between the library size, performance and functionality. If it seems that a feature would benefit only a small number of users, its addition may be delayed until there is more support from the users community - so please submit the issue first to explain why this feature is important.\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/validation.md#user-defined-keywords)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundles using `npm run bundle` script.\n\nThen you need to load Ajv with support of JSON Schema draft-07 in the browser:\n\n```html\n\n\n```\n\nor to load the bundle that supports JSONSchema draft-2019-09:\n\n```html\n\n\n```\n\nThis bundle can be used with different module systems; it creates global `ajv` (or `ajv2019`) if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in a way that is not compatible with CommonJS module format. In this case Ajv bundle has to be loaded before the framework and then you can use global `ajv` (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrating schemas to draft-07 and draft-2019-09 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas, validation keywords and formats\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/validation.md#user-defined-keywords) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.4","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-maq+H2VHruKQqN6vBRZr/CSnDKHzzxn9wnZhgv11oj7g/ka5h+sk9+DiTjSEoAxuBYEM+vP9xTfZJQMX0+pY9g==","shasum":"a957c2f07dd7b86db2875c7b40f9305ff11f18e8","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.4.tgz","fileCount":347,"unpackedSize":874391,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf175WCRA9TVsSAnZWagAAhSsQAIQoNUbj4c+ONZppl2JI\nQNU1YQHaJ6hXBgLkighCimK4BdawXoCr9mv2u/e4N5jWTf/3Ec9BsHfHgC4Q\nhHyOIFovNsIvJcsY5julrY5VTJJGG18/ZoeL7mRfcceUt3Ej8cK3CnHk3c0V\n4CClLsyj0953VmZs1IR0SIDDAJQQ9L3HW0ylCq/CHnxMZOcNGMyoR5n5BM1+\n+triRBu69r5rTkWnWUlDiqTlgTWMg445lxXAFNvkbTkCMuFadXiiRJL6vGIp\nbEb2G27FwGlfpdJacwqm2l4loWC3ROBqNONwguKuuMlMVpiFvxwYhMbu8KXo\n0sj8LQzIPz8OobzcPYSY34txmksSmoPZuaojDtv+DpbwHvmdq39O4POp/hKD\nJNzv+UN732Ee9Q5z0MUE5y2V8ZevTM+37x3hX09BLliDtP4aNi6aFih4GtCA\ndS3A+j+VBMwLVStgcMlwtzofdw2xvPojTwzozmF4QvaypBwaz5nkmuUosvSb\nfp6uV9p29Dfm7YMshuBDOwNAITwk2LBMs3eg9BW9VFRjzw9fO5FoUwc9NnUv\nP6Wm4eV+ryW1Ex2uMshXxpCfRnO9YVghrPeKjv3Vn6XkSpFAiUz0LIqU+/i0\n7hf+38v+DpQryEXdYKyfvZ1GJKz3QpZQNhDMdTjptHztPU7ThbfxrlLria2h\n+SpO\r\n=PPp2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqmDluPn1byLgPk1X3q1qpsjmOXMN0HV0898zesGR2EgIgEJ7dUsXjFz8T2A7KcbrGedQPw0NTjF49TJIAXsNJZ8g="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.4_1607974486025_0.8984206937968382"},"_hasShrinkwrap":false},"7.0.0-rc.5":{"name":"ajv","version":"7.0.0-rc.5","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","gh-pages-generator":"^0.2.3","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"12690aca66cbca594a16d85f2a0ce961f9b1877c","readme":"\"Ajv\n\n# Ajv: Another JSON Schema Validator\n\nThe fastest JSON Schema validator for Node.js and browser. Supports draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-rc.5)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 (beta) is released with these changes:\n\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems), [dynamic recursive references](./validation.md#extending-recursive-schemas) and other [additional keywords](./json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0-beta.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0-beta.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv@beta\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\n100+ people contributed to Ajv. You are very welcome to join by implementing new features that are valuable to many users and by improving documentation.\n\nPlease do not be disappointed if your suggestion is not accepted - it is important to maintain the balance between the library size, performance and functionality. If it seems that a feature would benefit only a small number of users, its addition may be delayed until there is more support from the users community - so please submit the issue first to explain why this feature is important.\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](#using-in-browser)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Command line interface](#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Data validation](./docs/validation.md)\n - [Validation basics](./docs/validation.md#validation-basics): [JSON Schema keywords](./docs/validation.md#validation-keywords), [annotations](./docs/validation.md#annotation-keywords), [formats](./docs/validation.md#formats)\n - [Modular schemas](./docs/validation.md#modular-schemas): [combining with \\$ref](./docs/validation.md#ref), [\\$data reference](./docs/validation.md#data-reference), [$merge and $patch](./docs/validation.md#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/validation.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/validation.md#asynchronous-validation)\n - [Modifying data](./docs/validation.md#modifying-data-during-validation): [additional properties](./docs/validation.md#removing-additional-properties), [defaults](./docs/validation.md#assigning-defaults), [type coercion](./docs/validation.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/validation.md#user-defined-keywords)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)     [](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements full JSON Schema [draft-06/07](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/validation.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/validation.md#removing-additional-properties)\n- [assigning defaults](./docs/validation.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/validation.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/validation.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv@beta\n```\n\nTo install the previous [version 6](https://github.com/ajv-validator/ajv/tree/v6):\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nIn TypeScript:\n\n```typescript\nimport Ajv, {JSONSchemaType, DefinedError} from \"ajv\"\n\nconst ajv = new Ajv()\n\ntype MyData = {foo: number}\n\n// Optional schema type annotation for schema to match MyData type.\n// To use JSONSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.\nconst schema: JSONSchemaType = {\n type: \"object\",\n properties: {\n foo: {type: \"number\", minimum: 0},\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\n// validate is a type guard for MyData - type is inferred from schema type\nconst validate = ajv.compile(schema)\n\n// or, if you did not use type annotation for the schema,\n// type parameter can be used to make it type guard:\n// const validate = ajv.compile(schema)\n\nconst data: any = {foo: 1}\n\nif (validate(data)) {\n // data is MyData here\n console.log(data.foo)\n} else {\n // The type cast is needed to allow user-defined keywords and errors\n // You can extend this type to include your error types as needed.\n for (const err of validate.errors as DefinedError[]) {\n switch (err.keyword) {\n case \"minimum\":\n // err type is narrowed here to have \"minimum\" error params properties\n console.log(err.params.limit)\n break\n // ...\n }\n }\n}\n```\n\nSee [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.\n\nAjv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.\n\nThe best performance is achieved when using compiled functions returned by `compile` or `getSchema` methods (there is no additional function call).\n\n**Please note**: every time a validation function or `ajv.validate` are called `errors` property is overwritten. You need to copy `errors` array reference to another variable if you want to use it later (e.g., in the callback). See [Validation errors](./docs/api.md#validation-errors)\n\n## Using in browser\n\nSee [Content Security Policy](./docs/security.md#content-security-policy) to decide the best approach how to use Ajv in the browser.\n\nWhether you use Ajv or compiled schemas, it is recommended that you bundle them together with your code.\n\nIf you need to use Ajv in several bundles you can create a separate UMD bundles using `npm run bundle` script.\n\nThen you need to load Ajv with support of JSON Schema draft-07 in the browser:\n\n```html\n\n\n```\n\nor to load the bundle that supports JSONSchema draft-2019-09:\n\n```html\n\n\n```\n\nThis bundle can be used with different module systems; it creates global `ajv` (or `ajv2019`) if no module system is found.\n\nThe browser bundle is available on [cdnjs](https://cdnjs.com/libraries/ajv).\n\n**Please note**: some frameworks, e.g. Dojo, may redefine global require in a way that is not compatible with CommonJS module format. In this case Ajv bundle has to be loaded before the framework and then you can use global `ajv` (see issue [#234](https://github.com/ajv-validator/ajv/issues/234)).\n\n## Command line interface\n\nCLI is available as a separate npm package [ajv-cli](https://github.com/ajv-validator/ajv-cli). It supports:\n\n- compiling JSON Schemas to test their validity\n- generating [standalone validation code](./docs/standalone.md) that exports validation function(s) to be used without Ajv\n- migrating schemas to draft-07 and draft-2019-09 (using [json-schema-migrate](https://github.com/epoberezkin/json-schema-migrate))\n- validating data file(s) against JSON Schema\n- testing expected validity of data against JSON Schema\n- referenced schemas\n- user-defined meta-schemas, validation keywords and formats\n- files in JSON, JSON5, YAML, and JavaScript format\n- all Ajv options\n- reporting changes in data after validation in [JSON-patch](https://tools.ietf.org/html/rfc6902) format\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/validation.md#user-defined-keywords) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee https://github.com/ajv-validator/ajv/releases\n\n**Please note**: [Changes in version 7.0.0-beta](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0-beta.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@7.0.0-rc.5","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-HMSdbwBa1Ep0HJgGSk+CYWCvbMhbu6hrQJsP/KyB0mt6WIN9jct5Xl4Z72Fkj+2JXCd5d0hguT2Vc/CHZtlHuw==","shasum":"3bcffe7d85ca7199d90bdc48825a1f45628533cf","tarball":"http://localhost:4260/ajv/ajv-7.0.0-rc.5.tgz","fileCount":347,"unpackedSize":874408,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf18ZNCRA9TVsSAnZWagAAlFEP/0DMh+ExyEdb0tfxohYO\nWEhNBNFr34veohbvQFY/TEW2vT9V6C184KJC6Yg5QWM4YNjKhWNW9iUZMdsG\nwFPyd1Xjjhoc6oP6mtaajAldP0Toz7Z9o/LLsYtBwcbd2zYPtee7Yf/fVb5G\nqrD8JGQwDfjyHRDSX3/QwLORKJR5TCvCv6GjTIi8tdcgvjYiNGckig7uS6jj\nbZ+Zp/I7N9abf8Vt7+XExgZJRO57dpQiTUj46l6rQmuogSVhfJuYfrrEhgSe\nZ16PAGHXoJmAr1ooscmWjNJnUCNvlEu0IVA9d0PugGTYIB/13yTZlzzNLEfH\nNfA9rANWKUtIsGJI85FjSC29UVj40QNQmJxjupH1sn+GT7fTYFv3Gz5CYwiV\nUn4vY46ElEmbPy24dPXlVMnR8kdg7hExA1duE5vaAnWeYTOOp/hz6cHFmchM\nE51gMyBhp5JpmbNhD6TUl7qmdPHnApN/TJwp+Utcv9u9VhRckOm3HL4RuGdn\nffz7yjq6MDZ1sQkCZkSes6F2LI9VuAqmb4jQ3hnIx8n3y3BkybMI5N8yt7Gt\nPmGZhCPUTfLCL9vskvSSTx8ITVkQhKWQWeSSNVPrMXpK0Sr0rEzHMO6a+XEy\n6NxxHNC3uCUBFZqNvp3xLlZ49f0SvsvN9R2qGA+KLNiNOCY4vtWxnOuTQhTS\nl/jl\r\n=e24Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTkmbkyzD3a72GyXvoi3eQ6Vn6re2mpNw7xGvezLX78AIhAJULKCkARnv/KhnfAq7sEx7rD2RAHn2CnBJlAqMd3TRd"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0-rc.5_1607976525051_0.9083602305178484"},"_hasShrinkwrap":false},"7.0.0":{"name":"ajv","version":"7.0.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"cd7c6a8385464f818814ebb1e84cc703dc7ef02c","_id":"ajv@7.0.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-hT38y4TE4E8WkqIZMFhGnd9F4Afn75YtFPJlMv8/j4RY2Vz48dYxn6AiD6CeE6JMo96F3Ldgb+j8qmgvcYT9Qg==","shasum":"59804586d998d19efe446fbbf821d147d300d8e2","tarball":"http://localhost:4260/ajv/ajv-7.0.0.tgz","fileCount":347,"unpackedSize":874072,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf2QqpCRA9TVsSAnZWagAAgN4QAJcz+GqWp/qj2LHOsCyK\nuyd6tp6hZpEk4dMOV8MR202F3XuejLjpx/vzTiHkt6XfXrUrYmk92SsJMQ0o\np5EZCTn2r4i5MTXhNviR0pUdyKWWsiSzeMJ3ouhnkUy5cPZQiGvh5U2nNCg/\n15Sl36Df/EZYeaOZyEKwlhsHlRM7DCh5511LTR0xCV33C3FzkoCN3qhrSkqE\n2Et1e/lk1QZI6vr8ykxTPyJuD/bF0vTKe7KEc2YqpXbAZYAF0tJfFFb10494\ncT74khut2i4sgsT8YdC79thsMzZOFSHoWgSnM3Vld6C5EWho8d3eeQwHw1Xt\nUOwBUuzAFhbfBXd6VFp3sL7tl9YldrRI5PL8PJAugDL8JCf5z98DaFBoaFhS\nArGG21s5/7HtOjtRGsypUtl+4FGJuMqO1iWS7MofW4WpO8sr8k1zqui2ksYv\n48wJ2nfPGPwwTGqm7wReO2MGP3HV9sqquJ3BP3DW3BfSiVbK214V78fOth3t\nSOjbUA7pnIBC0Bd7OeXGpxHll6bpg27hdel/R+ADcAPae3H0GZkkFLNCqn8Y\nuWdfpIIPO0beNqYe9EJiIpRKVDAe5r7JlPqYAqUFaCDEoPq5zkOnDq72Wu6h\ndCsMK+6x7DVSDLc3WYtxNNp3TjSZghwzPKAKFfA368DLE56n3xyXr4me9hT1\nJN2W\r\n=wcw9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpQAR9ekoEl7d2y1jEspxp6CF7XfQEJP78X3+O17EaFAiAIAeVkkmSSU5NVlUg4pB/z8YuHS4lZFgajtBUzSL/61A=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.0_1608059560652_0.390501110651579"},"_hasShrinkwrap":false},"7.0.1":{"name":"ajv","version":"7.0.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"616a725993d6d271ada3845f8b050ac226f3a217","_id":"ajv@7.0.1","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-D2UYOXvDzGLVwld2/EyRu3xiJG885QUz2xS1phZzebYLPMPBFbPK4naXGDCtPltZoOG+I1+ZkNAJ65SJ3vqbsg==","shasum":"d39ed49159672a91f796e2563e1e96984956e338","tarball":"http://localhost:4260/ajv/ajv-7.0.1.tgz","fileCount":347,"unpackedSize":874082,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf2mMQCRA9TVsSAnZWagAAQnoP/1hvG1UWt8Y2S9hWrHCl\nf73dHRyilVNNtIhYKR5MQ27laVtRR7A6eg1d/7hjxAOklAGzp+5L8nd2sNhw\ncJA8GhdlbjaJmnKewDtPzy9hUXRyjhtOalzHPSoj25U+iJBrOrdbQlZMwj8S\nDHwiUIGJm2r1tien/bAUpUTbgImz1HDZDeK20NoXSPtmRXzcJRMxxiF0L0qQ\nYlG4xlywG3ELx72aeLQ/HuDkN4AwGW+v/IBMHT21STrPLoIiimzobqMByXWA\ncPATHr020Rr9RzqUjUZduW0ZGNeYkDFBb91GgZAs8uK0WPp3luZqNkxR6+zc\nDorMUtjtCfyVScjl/yywcnAYZaxudkx8q98KyvzO0reKrtAKiaUGgtq6qt5s\n9jvLD7kMNICVUOpgLUjyEfAuHc3aFlkSnXsPI3D7vZB0qrc/LQ79lCVA2udx\nCZVXDXK1LfdjpaK4w/UJ+f4auFo168K4HXNs3ba6nyqH9MvxLwmk4GcSpTcY\nhTeX8Tap5j/E4Ft4OeK7Wkcu8eFJXnSr2xexVYAzR3UZVVnOeb1fOmkjnmDk\nmY0p1tQt32XwshQdtxmCSp8Ql5GhT7RfuT1HoNOOdj+jyNo0PvH1KZNk1jxw\nWJ7byYTmI8zfXNuIy2wazT/HBkTG154d3R+hFfuhWaLh3zc0Mlb3vhZcZktN\nmlzc\r\n=up5U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCPl8HdCtmJrAhQRdc0F2Tg+vTErBDqwU7T5fWT2ZlHCAIgMd99r0jybi4MrcIXD1loeSd7JDezEQDsgGiXyx8kgTA="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.1_1608147728179_0.6734007577980927"},"_hasShrinkwrap":false},"7.0.2":{"name":"ajv","version":"7.0.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"5c28d853673948c86ab3d876a31c14dae9d63d32","_id":"ajv@7.0.2","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-qIaxO9RXjaXyO21tJr0EvwPcZa49m64GcXCU8ZrLjCAlFyMuOcPpI560So4A11M1WsKslJYIXn6jSyG5P0xIeg==","shasum":"04ccc89a93449c64382fe0846d45a7135d986dbc","tarball":"http://localhost:4260/ajv/ajv-7.0.2.tgz","fileCount":347,"unpackedSize":874916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf3kmKCRA9TVsSAnZWagAAxwsQAJ1U4YT+s+hoP9/xah38\njyhT5m4jV3Msb8RO8PpiQvQLbSeYk67R495B0riRLeetOFu8gFGI/3iW7p0w\nuL57gDFmewIM7wXEVfFRQ8z3JrhoB51czB7bFAifVyqhX7m9H3fje+wIsOnd\nXkW33zLWsVnWJo5bH8aEen3ewYj3eLukP+1toyQ1vDOAls0Vrci9xkhfLlov\nGkPE8rHL0/U1kW1WW9pDftO3K7aSOlREJtLk30BdH81WQnsuRugAxJ2LzPSI\nzP20151KnVVAb4SjW61LxhplfShTXwr+/n8R/SvdrJQXDxMA8eYzYEPqrsAl\nwtFmiB+dX2Ylka4JSW7qMrPayqD5UcOCcs0bZClLJde6GohnDyAMwDTPMNYK\ndHygqNGp2NmaXBSOcRXRCZz3KgiIesdHIbRBOmv34R+T+idyA0BQkwcvxUuF\n7P82EOxpmr5Ob4CRuSfR9H6y4VMV0EaQWgYtFu1eKJwAfoVG0ZQiKcVSIHSY\nxNBRH4xzumWRk8Z48Jgs4AEonobTGngpQcuCZ4vrIvhQ/2lZkHRC/hkjnT3I\naNl5Q7oKZZzEMlxMFpf8oRbi2VUlUoX+iEFlJ04d1e/zSbcIBixBDUY1XwD2\n9bCRPuC4Makpb5klD1ztHpkx/fsYuNdIScfXFtE/3hKCG2e1F3ClbfocPXhC\nTtkB\r\n=8xVj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBserjB9EKqT+ncYEC8byVqZOd7a8gwqtv/9OZ6BzHX/AiEA0clgGRJ+f7b90oK5sU8fJUuEmwnPswYQHzp/FgIOowM="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.2_1608403337831_0.5627637239627219"},"_hasShrinkwrap":false},"7.0.3":{"name":"ajv","version":"7.0.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"ca2ae61c489f45fa2ec3ff2ee78b10136cb1ed3c","_id":"ajv@7.0.3","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==","shasum":"13ae747eff125cafb230ac504b2406cf371eece2","tarball":"http://localhost:4260/ajv/ajv-7.0.3.tgz","fileCount":347,"unpackedSize":875320,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf8FRZCRA9TVsSAnZWagAA6lAP/RIhBDnqDD401IjIF2U/\nJHXWh4WUocvjCiUANsPeU9T884nKOQg8l8yn2Gb3QfZmd0FTQj2ihGlXsyM+\n5DJ94Ow6/N1xv6+c8C8O7FE1omEiP5GaDUgtwc4FIujwDIRyJ5plaxsmY06+\npSPRdtFyUBRJg7z308n2iBDmfovh7DTgmbYifd8e0KVOsJ4NmTUiU8RF9mhk\nyGn+c5vPvbyoJNpR1UEAyKk927GXhCZXVgJnW1FrFvpfShX8ohIL5v+IItEA\nYXaRUBCLSJNFHLlO8v6EfzMP/eT9zmt1mUnly9qIxhPRWwUs3LH8IWKyh3H6\n2nE5TSxiT/Q1ufXsZu13AqBc7nHQkqXQnvSBz7xyY6yJpzaxwnGIt3pi9vhh\ngobMQ58FxLoUlTyrmXVGILub8v2lnx2F9NfTOwQasQVeNB1EyyTbDdvAbTsC\nJ/HMb2ohQB6ZFwUrrqQPl6gg9qYSkMs/8IMBlV4H0/hNGTxKbV/JBdkTBhlJ\nXu33OOESi05SEmikd697IRxnCJHaQAvQ46gouOfuKR4X0PX8xOtHCJJLX4g1\nhz3HEdwZMhhN4Hx+bERBYjB9U1o0pe1SruJS3S8vdXMwi6/1PDNK/1gTXNV2\nrtkKtls8FcTUgkdkCFIgnqChzW7bqsGLXxbteFcc67RvceHQNc6jwH2sYNPY\nc5B9\r\n=dlPY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9XsHclJZIzxza6le7zmd4nIZdqCKEThGt68xF/yu6JAIgLpobs6W2cXagZ9yynkclSZg5OTKSJ0n6X7LMBDRX7+Q="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.3_1609585753086_0.06854842769080394"},"_hasShrinkwrap":false},"7.0.4":{"name":"ajv","version":"7.0.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^4.2.5","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"63486ce5aa1f9b942775098ae7228cb2408d245f","_id":"ajv@7.0.4","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==","shasum":"827e5f5ae32f5e5c1637db61f253a112229b5e2f","tarball":"http://localhost:4260/ajv/ajv-7.0.4.tgz","fileCount":347,"unpackedSize":878305,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgGGz1CRA9TVsSAnZWagAAZ04P/Ale7eikSPzCLRqavHgb\nxvVYUg6a/I+T6xRS0NF05J4bKcQ9i7m7hvJ/IioIJgyWi8HMSMvBD1w6yqgu\nv5qTJa+Xsw5cBzhU02EmsnWhxq6JHHvOHqdqj7I5JiLDF7OMILX/GdzwkhkA\nKxB6g027W2wov1hnDJRx7eSzoXjg5JMZ+P+Csbu7iPDCQR5cT1SdL6nwlRja\n+WDWZ3QVp5ojJUbS6Poo1ChHkJp0Au2I3YDvKnNNQaKptaoN52Mm+GBzxuhL\nCZkNmTKFEP57DafGOS97qPp/leggYOTIftE5EoQ4eRxOjgR0Dd5SGT5YoT6A\nwDjiLIWQnQe/mC78ms4WIDX6h/yRsPy/WQMWllz3iNnLGcTQFQvBh0nds//v\ng1Uec8qPnrNVSAvzK/+cvRPf0doA8V8KQXhzZ1P7WBHYOXJpHfaq3ka+eHYQ\n+TDikSMyETeh+K8gwpX/HkMKXnQeLHmiBVM6B7s8ApAZfzUzAPE/wQGtoQaT\ngQ6xpkE4J3lq2XZokwFnlLoZy9vWNRFoSHNTgjxZ8h1Uu84pd3KfMzuki3tJ\nbGMLklMWHoeXF0Amhi4Bf0CwA7iw3kJauBg6R7wi5mFiJCcyzyGObU89TiSo\n42yq2jRlrVmVt4HlhnYmQW9yWOzEsLxxR0Zgmhj3/KL6yrWCwiJq/xzmXGIN\nZRmi\r\n=cAqv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBmlVgZlzoaS2DiDDWRYfDolH8xVOpPCHHHM+MfJncWQAiBxxa8C7nLEHWE6X8ZnDCvyWR0LmJr/Txx5SZJCTq70/A=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.0.4_1612213486548_0.4713523608459591"},"_hasShrinkwrap":false},"7.1.0":{"name":"ajv","version":"7.1.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"8ec80c48384abcf8c46617be27201307a2d7c402","_id":"ajv@7.1.0","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-svS9uILze/cXbH0z2myCK2Brqprx/+JJYK5pHicT/GQiBfzzhUVAIT6MwqJg8y4xV/zoGsUeuPuwtoiKSGE15g==","shasum":"f982ea7933dc7f1012eae9eec5a86687d805421b","tarball":"http://localhost:4260/ajv/ajv-7.1.0.tgz","fileCount":408,"unpackedSize":972115,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgJO3hCRA9TVsSAnZWagAAq6UP/3G0XSdUFCCvw8//bGU8\n70GilKD2UmHBrSbW+mHlTiNWBXzsX0KCY/nF1IgPP2UT2pI8HZnOZjahpZol\n4Vo4N8YtK7WlFR4JuUrMaY3kSlWQ7DV0J361MWLYwshrWeQWtYBEYymb6zkc\n4OBkDRqOYQZKqyTu3cA191k501CWzYSDSpWu15AzjCm+yGAKgJRj3HLyqb2e\nniLseKVw+6PMcSnoZJCM7unSIdFP22IXusAif8NSug+B5YEkPnwX19JTeFuZ\nbtyKs3s7cLrEPSpETMS8jXfp7uVClRnDGfvgIRY0f066kb+gnmEFfCB85TI1\nVGDv9V78lb3a7xjO/YL4+kG3JW7gL56EUvFsWSYh1IhKs0FAaVATVZoysHto\ne0SkoS4/RCI6eA0JKlLb4u50bv5XcGvN59IqhO7l8Xe7XljF5pMznzrWf0If\n8ileFgOA/zZxRrjay3KOgqBn+AwuiNvbtD42RYEc7bRpyDD5UujDfkwHv5i3\nVhgg3ySSFDHYfRxekVkpFV7Jy3dXSjmET3CPN4+mxMdaDygClz41kN0DJt1o\nd+KAnAJpTO1zTVz6sI2CPxEslm7KyhXig3NUCGnCzvzMWtEOeYPgCGZj2ZmL\nFV8zy8b1DtrD2gy9Cp+oJG76FebYp5ppClx1L/mleVsjWwrNBZaPAKfMVL+D\ne0xh\r\n=nSFU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2Nidp4M+FkDFxXOSzZivs/cSb6SiEx702hBDGcBmmzgIgG4AZ6hEnzMdOoiLYcG2gmHdMsAuw46N+O/Tn/jJ4Chk="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.1.0_1613032928047_0.3384724874310796"},"_hasShrinkwrap":false},"7.1.1":{"name":"ajv","version":"7.1.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{md,json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.0.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{md,json,yaml,js,ts}":"prettier --write"},"gitHead":"77d788f5827669928e6d3b714585b47e5d70971f","_id":"ajv@7.1.1","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==","shasum":"1e6b37a454021fa9941713f38b952fc1c8d32a84","tarball":"http://localhost:4260/ajv/ajv-7.1.1.tgz","fileCount":408,"unpackedSize":972134,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgLN1mCRA9TVsSAnZWagAA6EMQAKTl+oR/orO40FZrqFuh\nhvyWHSptWknDB61/qX07dlWekfeHlfiFJD2JQJQKO6YsEXnOQ5UDdzrXtAU2\ngXLWoOyKhju8U1l9HHtq87XpQHjlvZ0kfSUFqd3t5fJx0FzddM1VCPMHBb+M\nGbWPCTGoUGkU6hQthywA8cl1kDKAJ0xFutP0xF9eq/TLosbQV1EIptpNef3c\na15P3bbM4ZNmhQjUGdrL8Xqz6LLm+V8bat0bePcz+Ez4Hadtw6meyKjSxUko\nAV1i1N5eFuwfmx7ukeV7zhR6eJHTS58QmiPuzFB8qSTuGtirY7+HIIW8qVWr\nA167VZAqYTWtxaBRujLB2s0BV1FBCyorSBgPDGoDd2xr+xXqohhgEzV1AmfW\nD02yB+TV01XQqch+4gba9OWqIPa5c/QWx3ON9G2r8jYVwuTaPfFqGsD89UF2\n5KNYjB+R31GjZ0in5k9JjboJcaby9d3NG1wesUm2IFP5EnEzujl2U49oAmty\ntNKXfxp4iSsJsnqyHIn0wOn+Lv780ga3cRgd4ctjf+33UQZXdoMWvmdqCNex\nB1Xay8H1GueDtjAizwBrlg6zZsXURUhm4Jlb3BCrosI5C16cc3ks5OUaRnsS\nk/yMLEPJ8qYKjEMah83OSKsou2ukTSqsDtSiC5NUmsfUsEveOXmha3kzCPUG\nmOCS\r\n=Vi5t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEkE7yfzIO8TG/Bk83efSz/A0C1YFBN22gJF3uQjpovdAiBU09lTKUFyaxSwmq7wgvnrz+v8OiG9sN6ckMU+yiACqA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.1.1_1613552997768_0.4328567676481856"},"_hasShrinkwrap":false},"7.2.0":{"name":"ajv","version":"7.2.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"vuepress dev docs","docs:build":"vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"9823d1d588762e10a05d5260c83a057eb11be3d8","_id":"ajv@7.2.0","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-51Na3IUg3uOACsQ7hzTUCjSzGy8xROySgI8tmNJ+y9JF2hfDS6qkTP7+Ep3htUtSQG1t17QMbe+jZFTlaU4dDQ==","shasum":"54948182f79f2e18c70a501700d78f7a44e6e398","tarball":"http://localhost:4260/ajv/ajv-7.2.0.tgz","fileCount":483,"unpackedSize":1241049,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRKRaCRA9TVsSAnZWagAABBYP/0OsoiXZ6unLTw/AF1g9\nNY0nUOoKOdO9sodY9qX/j5jNGLrdi39APSQd/6kSw/L0fm2Ab8C50RNTrgpY\nKgRMpyf1+VkoF14SEzIpojt6dIrEbnIEKc5VFgt8Rrk4NHWweN5yCK1q0o/m\ngRWlM+vT2ET4MufN/5TEbvOyg8yIRX5ODRgYf7Jjg5qYXE93paBikW+Izf43\ngiSOEyhz6KtKBHj0Jl7a/wdIU01TFwYhkeVbZL+vrAEFh12p311ZItGSXgSL\nA6oo/UV9a+GGzgwtfpHv16zoESjO3Xrrxk8Vj9fFMDNYoONbu7CXQcpYOz8H\nKah2bYVii6bhAPP4BPTxULVXxDI1dKMqAIa5DuS7lH8OOwbRs8+Pgk0iZdvs\nToLyx53Dy5KRBJp3SarpClHHJoLwVjw5wLVTlPQjfdBn7sqExckQcngG+bqv\nSWq5Gobmy1RnzvD59PVBB9Gi2W/HZSCHB69E/7n7TpDcPZA5xiyFYZ8axUeu\n2Y0n32gUQWYFxM2pZscAObDF2rvNGPEb2/n85StYz1rL2XuRBRQMQ1wpAyCU\nKrNrzeHW06XI6OZb8wtiUV3fN9Jh8uRezpX7NzjnXn2ZqJhFwi/ossXckg+s\nge4sCSykA/iofPwW2TysVZgsGBJSwbCxqc7m6fA95t6b/iLvm9yWv8u7zD/J\nv8Up\r\n=XBgu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbUCzvpL0ONMaCVoHrt8s0GFhv5338A0xsTRrK2e2dUgIhALvX+L+MA+UFLy+qIln9xYkcpo44y/DAJymXTcFY2/pH"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.2.0_1615111258159_0.8622245469441063"},"_hasShrinkwrap":false},"7.2.1":{"name":"ajv","version":"7.2.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"vuepress dev docs","docs:build":"vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"dd0eab50fd718249e3c7a0f5e7ed3227dff10e33","_id":"ajv@7.2.1","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==","shasum":"a5ac226171912447683524fa2f1248fcf8bac83d","tarball":"http://localhost:4260/ajv/ajv-7.2.1.tgz","fileCount":484,"unpackedSize":1239266,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRSNrCRA9TVsSAnZWagAA3W4P/0YNT/vgZ6xrk+Ok+9sE\n9VYQEjsv/3LuoxKU3WwOoKrhpa1hTS8gO7tWTBKWhFPb2E9mxomSkZbJfiyt\nM7lbkWwtxC4QjbvAlWIcf2d5eGz0XAs0iw6v4kep1FeOmvcFX/kq85yxbVwL\n7CSA57yCPlU8G7RG5GNB8UXQtNNQZFfAMLsL5fiwvAoIz9sCYLCLBHn7Ep+6\n5MP55QTVuli5qjz4RkrLMYs6kGgVFXo2rXvuaJLHuYBlB8MAYyB8PwOeiM9k\nI4J7+dpctrVLszrpQwQksxC1jdDT3pZ6AhGo2fXYP8gGeOcf8s50wh7I2B4q\nBPoLxeM9orc/62D/5bNG26mTP5G1adlp60MWn68RCesVxMG1OHACOWeDTHuU\nveRBuMhti9QHcMEsV1UNkFiVbSDLVnqcZ1iGz3OPef9Knt5sHCMgmfR1Hd8D\nvzYQ/sdhxKvrJg63+aPIXR37cJUQ30ccb9c8HcP1TOPmvpH7mLXb4vEuSxSM\nVePL8HJh2i3xdGpEZafzoH5uHsaWh9MN/7boe0QUbvEUdNpJbNYuUhxDEvOg\n94dhboXKHTE3RHC2jshMM6JFFVaRCSsNBBmS+OWA5G35hjUqpCYhfXWBtYtY\ncx3bN513Yn8EaiQNsjneF/oRD5Dwvl0eA9PuRW4GShEn66lEWd0WGEFjO/74\ntVWE\r\n=DKCA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCs8tcPApx3rDC1YQCow/VSKJ6Y1yldt+had85eYwZXQwIhAOH+kt+dhPD52JOxObm4cbo8F8dB9RWfZHSkDEgYKCeG"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.2.1_1615143786921_0.25395392125776173"},"_hasShrinkwrap":false},"8.0.0-beta.0":{"name":"ajv","version":"8.0.0-beta.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"51cbcc2ba07f2d61c47a7a2191913325c8c4a318","readme":"\"Ajv\n\n \n\n# Ajv: Another JSON schema validator\n\nSuper fast JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 has these new features:\n\n- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)), including generation of [serializers](./docs/api.md#jtd-serialize) and [parsers](./docs/api.md#jtd-parse) from JTD schemas that are more efficient than native JSON serialization/parsing, combining JSON string parsing and validation in one function.\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/guide/combining-schemas.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nAt Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.\n\nWe strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.\n\n### How we make decisions\n\nWe value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:\n\n- Will this benefit many users or a niche use case?\n- How will this impact the performance of Ajv?\n- How will this expand our library size?\n\nTo help us evaluate and understand, when you submit an issue and pull request:\n\n- Explain why this feature is important to the user base\n- Include documentation\n- Include test coverage with any new feature implementations\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease also review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Choosing schema language: JSON Schema vs JSON Type Definition](./docs/guide/schema-language.md#comparison)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](./docs/guide/environments.md#browsers)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Using in ES5 environment](./docs/guide/environments.md#es5-environments)\n- [Command line interface](./docs/guide/environments.md#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Validation guide](./docs/guide/getting-started.md)\n - [Getting started](./docs/guide/getting-started.md)\n - [Validating formats](./docs/guide/formats.md)\n - [Modular schemas](./docs/guide/combining-schemas.md): [combining with \\$ref](./docs/guide/combining-schemas#ref), [\\$data reference](./docs/guide/combining-schemas.md#data-reference), [$merge and $patch](./docs/guide/combining-schemas#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/guide/managing-schemas.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/guide/async-validation.md)\n - [Modifying data](./docs/guide/modifying-data.md): [additional properties](./docs/guide/modifying-data.md#removing-additional-properties), [defaults](./docs/guide/modifying-data.md#assigning-defaults), [type coercion](./docs/guide/modifying-data.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/guide/user-keywords.md)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)[](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/guide/managing-schemas.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/guide/modifying-data.md#removing-additional-properties)\n- [assigning defaults](./docs/guide/modifying-data.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/guide/modifying-data.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/guide/combining-schemas.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\").default\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nSee more examples in [Guide: getting started](./docs/guide/getting-started.md)\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/guide/user-keywords.md) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@8.0.0-beta.0","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-S3sxD8f96ENFLFguo+Ibo0d1bP30WE+Xw7vu7HHdVUfQW/mapSGGj/0m66vgMxLS4lUe1YxNtKxanyHihTzNCw==","shasum":"4d822a9671f73008d418aebdec2f005c58c6111f","tarball":"http://localhost:4260/ajv/ajv-8.0.0-beta.0.tgz","fileCount":490,"unpackedSize":1259826,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgTJ0pCRA9TVsSAnZWagAAZYwQAJyMZXymuV2qkP1WZFX9\n6ztWCQkdrAt0KWWR0+yOvY3/c8Sp+53ZbGKT4nNHxOwzCvng9baaVko3Nti0\nF7zOwbrnSIwokUDEZisMnGnSzfZYk3FU4zTkOaEi8OlbYDPGz5UYc3zWBdLs\n1Cg8f/0Pi42wkoVkszJgQE4dKZ0nEkS4qQrz/yKvVjCNjSUt4MVFO6o8xRpi\nwxtfskuO5upYiB/W2zxEk295258ROd2AyWA1jZv00LErTg7hNhMxjuEOsQ3G\nl0lFTzwWYvuZqYAEZVIK0Jm0r772y6yKBmhedwydcqfbZHknDVRoVb4pl7Ys\nx7v0CHsKF6NoK2Y3CefSccevxVQhBImtE2BXXcWjB/7BYlfCVRRuB/YXJmuT\nsBU6656UqrHBRwQIQciTmRlTc0Yp9hnVXiVA2aLYRrGWmlNachOg1+TilOW2\niIP5CA24bATt6F3e4HUY7fxQaGRj9skgfU9iCatWns+yWNKqEOHVTVJR6M1k\nXoT80jEFXZXacxqwomu43oj2en08pXMxx5eyu+k09L6rXf3orru9NSn6p5th\ne95+OGeDzzzjdw2bLpEjCxAibWTHkYY4eyVIZbjcyjF9GGbv/2XO8oOFO+sF\nR3CHElqE5zNZZ+5MPJxZm1pkAYUorLe/E59WmguQj18h9sZMpfNZlbR0yMMu\nLLjj\r\n=Ac8z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICeZL5kLM/Z1P87KxSwB2KA6uo84Ulji82fxDA5OHotFAiB22efDHfNU6n2ShhK1pNeYctOAD2wWMhC0tRA/d4kZrw=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0-beta.0_1615633705017_0.47563018708357707"},"_hasShrinkwrap":false},"8.0.0-beta.1":{"name":"ajv","version":"8.0.0-beta.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -f \"\\$recursiveRef with no \\$recursiveAnchor in the initial target schema resource\" -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run prettier:check && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0-beta.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"fbbd2c9e9380f12d52723ed009cf5510e41d3578","readme":"\"Ajv\n\n \n\n# Ajv: Another JSON schema validator\n\nSuper fast JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 has these new features:\n\n- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)), including generation of [serializers](./docs/api.md#jtd-serialize) and [parsers](./docs/api.md#jtd-parse) from JTD schemas that are more efficient than native JSON serialization/parsing, combining JSON string parsing and validation in one function.\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/guide/combining-schemas.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nAt Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.\n\nWe strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.\n\n\n\n### How we make decisions\n\nWe value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:\n\n- Will this benefit many users or a niche use case?\n- How will this impact the performance of Ajv?\n- How will this expand our library size?\n\nTo help us evaluate and understand, when you submit an issue and pull request:\n\n- Explain why this feature is important to the user base\n- Include documentation\n- Include test coverage with any new feature implementations\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease also review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Choosing schema language: JSON Schema vs JSON Type Definition](./docs/guide/schema-language.md#comparison)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](./docs/guide/environments.md#browsers)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Using in ES5 environment](./docs/guide/environments.md#es5-environments)\n- [Command line interface](./docs/guide/environments.md#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Validation guide](./docs/guide/getting-started.md)\n - [Getting started](./docs/guide/getting-started.md)\n - [Validating formats](./docs/guide/formats.md)\n - [Modular schemas](./docs/guide/combining-schemas.md): [combining with \\$ref](./docs/guide/combining-schemas#ref), [\\$data reference](./docs/guide/combining-schemas.md#data-reference), [$merge and $patch](./docs/guide/combining-schemas#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/guide/managing-schemas.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/guide/async-validation.md)\n - [Modifying data](./docs/guide/modifying-data.md): [additional properties](./docs/guide/modifying-data.md#removing-additional-properties), [defaults](./docs/guide/modifying-data.md#assigning-defaults), [type coercion](./docs/guide/modifying-data.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/guide/user-keywords.md)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)[](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/guide/managing-schemas.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/guide/modifying-data.md#removing-additional-properties)\n- [assigning defaults](./docs/guide/modifying-data.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/guide/modifying-data.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/guide/combining-schemas.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\")\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nSee more examples in [Guide: getting started](./docs/guide/getting-started.md)\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/guide/user-keywords.md) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@8.0.0-beta.1","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-Gv2uhXJEeah+8m3LtVW3rm8epYdhMw73O+1QjZsjOLUPoeDEtOnhfFKXk566Dk0L4E3SQ2qmw265qjSZSo3gxw==","shasum":"d39cf119edece647ac2beaf39796c5dde645e7da","tarball":"http://localhost:4260/ajv/ajv-8.0.0-beta.1.tgz","fileCount":488,"unpackedSize":1265822,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgTxNDCRA9TVsSAnZWagAAFaIP/3gTJi7EDQ76lDV385Th\nZUP05Sd2ihKbOPPoeCAuCqKnzVO0GGT3IbsrOAnGBKVIHEjvAXdUAkRvTtXW\nSrlE5H5a5wd62ovK6VZ+944sWVPi4ep/k7pb/XtYABSMMkMYK0KJAV1nt17O\nWNfWMnQpw6er8EVuoC9huxGai/QkYHiB7bcMci2U4yN8nfQtEiSZPZV1xoh5\nl9dgYlkdSSgHbEPvioiP7NbdgTdMu3KNm7lFLlFo+z5bJ94uBJYC3OovH+Ql\nanW+y3+V3coYzNPGzFdxtaP96UxGWTbmN5260MJ03MX7OP2xpPXrNXR/Yqh7\nnSK/MnJ0k7a4qOOdoO3nmgYqHeit0no//p893HkolNtRL8niYQop6E9aoYB5\nYrKRSbXvnZ169dBdFWUaKoenR+ueOVpTwHhZj+eoZ6Onx9LBzwjolaSTgcE1\nacFDku+kpUUQOO+s3QpODCA8yHiDmKUbWF8+bTj6AzgVt/1WRaY4XQZqmzIE\ndtGJqaO2B/guMJJo3UUilxsxp/m88lSXJ0KcqlxQdMyOV7Cj3GCU43uVEJJc\nbIbM4Z/zagby2kQjRfKlYN6rTVSkJZBtMhGkwP5ocp2yfCYOTLmJjp1u3DXa\ni0401Y5He8S8hQW2LXpUUaWfJI9uV1MR7kDuXjaejvFithAY0L4DSy+cd83+\nzlyg\r\n=7wHA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHdIdAyxoJqpfwITS1f3YAbKyiXcadr1wjyG0zmIDFcgAiEAlPq72oKdM/6Ul0tziLEwK83WEwdUOsLGI4hPxJH8DM0="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0-beta.1_1615795011203_0.22470218042154277"},"_hasShrinkwrap":false},"8.0.0-beta.2":{"name":"ajv","version":"8.0.0-beta.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -f \"\\$recursiveRef with no \\$recursiveAnchor in the initial target schema resource\" -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run prettier:check && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0-beta.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"261eb3ec7efaca5d817471d64b9931d77f9e23ec","readme":"\"Ajv\n\n \n\n# Ajv: Another JSON schema validator\n\nSuper fast JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-06/07/2019-09 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 has these new features:\n\n- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)), including generation of [serializers](./docs/api.md#jtd-serialize) and [parsers](./docs/api.md#jtd-parse) from JTD schemas that are more efficient than native JSON serialization/parsing, combining JSON string parsing and validation in one function.\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/guide/combining-schemas.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nAt Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.\n\nWe strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.\n\n\n\n### How we make decisions\n\nWe value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:\n\n- Will this benefit many users or a niche use case?\n- How will this impact the performance of Ajv?\n- How will this expand our library size?\n\nTo help us evaluate and understand, when you submit an issue and pull request:\n\n- Explain why this feature is important to the user base\n- Include documentation\n- Include test coverage with any new feature implementations\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease also review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Choosing schema language: JSON Schema vs JSON Type Definition](./docs/guide/schema-language.md#comparison)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](./docs/guide/environments.md#browsers)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Using in ES5 environment](./docs/guide/environments.md#es5-environments)\n- [Command line interface](./docs/guide/environments.md#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Validation guide](./docs/guide/getting-started.md)\n - [Getting started](./docs/guide/getting-started.md)\n - [Validating formats](./docs/guide/formats.md)\n - [Modular schemas](./docs/guide/combining-schemas.md): [combining with \\$ref](./docs/guide/combining-schemas#ref), [\\$data reference](./docs/guide/combining-schemas.md#data-reference), [$merge and $patch](./docs/guide/combining-schemas#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/guide/managing-schemas.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/guide/async-validation.md)\n - [Modifying data](./docs/guide/modifying-data.md): [additional properties](./docs/guide/modifying-data.md#removing-additional-properties), [defaults](./docs/guide/modifying-data.md#assigning-defaults), [type coercion](./docs/guide/modifying-data.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/guide/user-keywords.md)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)[](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - keyword \"nullable\" from [Open API 3 specification](https://swagger.io/docs/specification/data-models/data-types/).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema draft-07 standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/guide/managing-schemas.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/guide/modifying-data.md#removing-additional-properties)\n- [assigning defaults](./docs/guide/modifying-data.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/guide/modifying-data.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/guide/combining-schemas.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\")\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nSee more examples in [Guide: getting started](./docs/guide/getting-started.md)\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/guide/user-keywords.md) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@8.0.0-beta.2","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-M0YXx/qvObxf4bG2lCvU14pVLvm5vAd87u/KylxCXrB/5YmDpGk9gACkPDLCWjiz62Rgzahlx1xvdEPdCdhGnA==","shasum":"3e357bc3944d30a8facc2b89ad2cfb9fccb884fa","tarball":"http://localhost:4260/ajv/ajv-8.0.0-beta.2.tgz","fileCount":496,"unpackedSize":1284713,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgURONCRA9TVsSAnZWagAAGXoP/3sRTKAbfcw3Ghbl0+1j\neEI6AVfvGHqhFSoo+l8S2SEHa1f5dI9+DV2FJo/reP2sb5gzCDKqg8vqAYzc\n9x0SKCuo2ta7LeKXVc6wR/2lHKa1xTr715wmZr1+b5/JWJs+IqRsMAZlmw3o\n9jjg54Ydjo8FS47VdR3UjuDoZVd7h//2w0DJi9IaxByG7Eh5yYX2SYm2YB6N\nOWrXkfhNFI13fTVR7Typh9D+6PuE2hqu7Iew5mAnVBfX6cfjgZDGvc2pedJl\nDarpaVijbxNQjGaLJnCnaIJWm/FHNa647C/8LS8jWaxW+J/c61iNdrVHQTau\nScj2E+RA7/bW5nnZtfEF5FzvFvfjbqA7bxeyoESSB7OE96R5h8PId14HCUcX\neuB+uUPUHQoy5TFB9ID8LNPpZydxY6qsyPtrfZ0OzCnDSsGkbhntzNRrqOUN\nwG8gjZMNLCHjN49EJQIGC4j7vCsDhW4Q9S8rdgaD2RKEgirdhCJ2+mOFhdn4\niYL/KxMDFTLCeWOwmzWtQ7mWvA0IEM0JikNb2GOKT0pybDEj+RPVlPOXYCd9\nUEpAjQqyDVRe9WObjJVQ/keWdeO8Ny4xxYrL0urDZrOjySeaPLwrtjPHnTRQ\nCVooW1IE+eqNgCK/Kwvi0Fd+Z6nXdMgz66PwiwPStFJkKiRvqPwkqNfjHLzo\noNl1\r\n=O0ay\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCDCN5s5zN/7BjPDyc9nACtIzStVAAhIu5yrg2pnbY6/AIhANI2/mGTAzQDEHS5hEPYXJa6ip7dAyK/kBQXqbLWAbon"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0-beta.2_1615926157094_0.21166170291613873"},"_hasShrinkwrap":false},"7.2.2":{"name":"ajv","version":"7.2.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -f \"\\$recursiveRef with no \\$recursiveAnchor in the initial target schema resource\" -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"678f243d7b54e224f4aa9c61305ddc1a59cc64fd","_id":"ajv@7.2.2","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-uEsX8jbbSu5MfRDQfao+AGt2QdThdRysvCFo7arlv5e2qQzRaCUV28TcS7TCzfGWD1ZLZIlFV+AOvoqQRARuOQ==","shasum":"33e4d3fe9e6ba9f4beb116d08c788160979b2a69","tarball":"http://localhost:4260/ajv/ajv-7.2.2.tgz","fileCount":488,"unpackedSize":1244759,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgVZmMCRA9TVsSAnZWagAAg5YQAIOIsjgkFms2iG8JjgRb\nC13bqvrecdrjzBQoe2eFu2tirrJknet7/iBIpyUL0IPfIP9PUDcCnfBXvbrS\nZJ/Kvirg9ebK+GASXCdGIBoWBEnPa51M7XUM1JmBCrtPveL3uRRQ/kiYCFer\n+tDB7LiEhBEZ8zlUQm2Gp3phhknHnf4wDqoClQQU9KewW/U+gmxtEpLBxSVe\nXqieU6mmed2kkHt9+uzGu99eKt1nbN+tjzrppY26/ZWr15zuHSsIPsh3W1/8\nkE1PHZTM/Vz0/Hq2f+9twglv4KLz1k3d+WA2xflPc1n8WEOLQuXMU51xsLLn\ncpY4yUHyWn84hHwyhd/aCIuhF+lDZmg1D73NtdBrXsxTDySulL8eCVf5IGrl\nciDt/Row1I+luL33zf3IpUAJDfZ6lNu6oHsiFHVJw1TVZDhK6XvPm60prgh8\nSD3mV8eIvNmyVXRNWTJsqWDstro/BxPBx5pUO+xPPRoG48zK1NzTjQOB8WbN\nXton72D/Am+N+6BcoRedfDprEYFxTvYvPadYmwAdWqOp0WB5VIbFMEtPVnad\noughf/cgFdcnCH/CB9o011a1/MHGGaPsqeSUcwm4QGol11+Mw3jAE8g7AGDL\nWWUkzBMiB9bSKnXxP2zHvwlgBRg7ht0DNIPhS0qYGubaTg9MV6AIG2AuxDjN\ns+P3\r\n=AV3+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICrUqy2B1v4n118I75y5bUjY5BtW7EqD/7yNC/ON2DLAAiBgXAWt5+/WWL6bSbAh0j6/eVu2esM0HCwbUgr4bSiBnA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.2.2_1616222604141_0.023944197944711476"},"_hasShrinkwrap":false},"7.2.3":{"name":"ajv","version":"7.2.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -f \"\\$recursiveRef with no \\$recursiveAnchor in the initial target schema resource\" -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"1b07663f3954b48892c7210196f7c6ba08000091","_id":"ajv@7.2.3","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-idv5WZvKVXDqKralOImQgPM9v6WOdLNa0IY3B3doOjw/YxRGT8I+allIJ6kd7Uaj+SF1xZUSU+nPM5aDNBVtnw==","shasum":"ca78d1cf458d7d36d1c3fa0794dd143406db5772","tarball":"http://localhost:4260/ajv/ajv-7.2.3.tgz","fileCount":422,"unpackedSize":927078,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgVZ2+CRA9TVsSAnZWagAA+JAP/AvYiapJNCZsuRrT4ZIC\nWsjZuI+bXrxCcdpBs2bUkIHQ0XpWtN2OVWm5ta1MvJUVMbv+SnkhcsIDRtAB\nXqskcDoQ7TCoIDjBPKyGrDeq7SiJ79/uacpJLKfWbIGgbqKku5+2qmcM2TEJ\nLbUL+roivOQccA5ev2NBd96lBh/no/4dVul7pc1u/wyJaf4am7NR4aRttS9I\nA9mawiWlEJtc5kV3wufCX0sgxcsqKNV9x+i3TGx4VxCzXqm5lgGySRel9csy\n9mdglzTJMA3gIibVj+7abLRy/BCXvWj7CRkrz84tx4ykBfaZOdhbHJLngS4t\ndR/hbyt5hGQQbzrcHD5efHughbwez6IqVllGSm/IX9cvCyOm/OXmYBpzpbDb\n8yQN4T9SLBzljR4Qy8ECGBINlBtKicrCA8vw7bxMGQBxCd24GEbSemq19fcz\n8d25Qlxr8PX45k5H3GpkyTy5GFt18U/e6DMWiDh1aPi30TypVc0yfNyUDimO\nvvc7z6IntYoPAFS+51lGXagnZQ04Fdc6uJ0wPPDeFkvQO4UZvGMBDKo5qyCr\neQTkH7p72327K78pGmCYFacaaNg5NW3H22t9T2xaB9PsdkYeM5PK+sLCMyyp\nfAaQ+jGLQhfL5HH8uCb2erCVunjrYd7W7Twkxslki244vVPq5+7v8E2IZFCn\nSsV0\r\n=nDn7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFx+gRhjmJ7iVpuQagsuWk5WxvVqMJrC58nAsBmW82MZAiAk11wwe9zU8u0gdrmdzxelY5tEr/PKKpWsFKiFj8Gj2A=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.2.3_1616223677554_0.31732159673019944"},"_hasShrinkwrap":false},"8.0.0-beta.3":{"name":"ajv","version":"8.0.0-beta.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run prettier:check && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0-beta.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"d80b6cde4a585be54c678421af5303b87c229c39","readme":"\"Ajv\n\n \n\n# Ajv: Another JSON schema validator\n\nSuper fast JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-06/07/2019-09/2020-12 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 has these new features:\n\n- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)), including generation of [serializers](./docs/api.md#jtd-serialize) and [parsers](./docs/api.md#jtd-parse) from JTD schemas that are more efficient than native JSON serialization/parsing, combining JSON string parsing and validation in one function.\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/guide/combining-schemas.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nAt Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.\n\nWe strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.\n\n\n\n### How we make decisions\n\nWe value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:\n\n- Will this benefit many users or a niche use case?\n- How will this impact the performance of Ajv?\n- How will this expand our library size?\n\nTo help us evaluate and understand, when you submit an issue and pull request:\n\n- Explain why this feature is important to the user base\n- Include documentation\n- Include test coverage with any new feature implementations\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease also review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Choosing schema language: JSON Schema vs JSON Type Definition](./docs/guide/schema-language.md#comparison)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](./docs/guide/environments.md#browsers)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Using in ES5 environment](./docs/guide/environments.md#es5-environments)\n- [Command line interface](./docs/guide/environments.md#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Validation guide](./docs/guide/getting-started.md)\n - [Getting started](./docs/guide/getting-started.md)\n - [Validating formats](./docs/guide/formats.md)\n - [Modular schemas](./docs/guide/combining-schemas.md): [combining with \\$ref](./docs/guide/combining-schemas#ref), [\\$data reference](./docs/guide/combining-schemas.md#data-reference), [$merge and $patch](./docs/guide/combining-schemas#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/guide/managing-schemas.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/guide/async-validation.md)\n - [Modifying data](./docs/guide/modifying-data.md): [additional properties](./docs/guide/modifying-data.md#removing-additional-properties), [defaults](./docs/guide/modifying-data.md#assigning-defaults), [type coercion](./docs/guide/modifying-data.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/guide/user-keywords.md)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)[](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09/2020-12](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) extensions:\n - NEW: keyword [discriminator](./docs/json-schema.md#discriminator).\n - keyword [nullable](./docs/json-schema.md#nullable).\n - full support of schema references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/guide/managing-schemas.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/guide/modifying-data.md#removing-additional-properties)\n- [assigning defaults](./docs/guide/modifying-data.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/guide/modifying-data.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/guide/combining-schemas.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\")\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nSee more examples in [Guide: getting started](./docs/guide/getting-started.md)\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/guide/user-keywords.md) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_id":"ajv@8.0.0-beta.3","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-bgtJ6Qi7Cw9SRf5ghhJO8TpQSFR21fI8Y+j2VT7NxPY19klb+aQrHqat/KbAIduEmDV4cZgWFrTbEf4O2oCeww==","shasum":"8f859668516e093ac829616ba80152a1818a15a8","tarball":"http://localhost:4260/ajv/ajv-8.0.0-beta.3.tgz","fileCount":470,"unpackedSize":998452,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgV5QVCRA9TVsSAnZWagAAfX0P+gNZcYup83qkH2zjl5bm\nOeb/N3dSu+JLwi5Nc5docxB1Cwjs60w3vvzCYAqEPEYNzYehUe6TzQQ3EPqc\n81+0TXhnBxs+LALn8L4b6nMQ0UHIh2MMF8334x8tQzWRM7p+bG2z9hTS0ikn\n0e7hvS6auA7Ka+P/MUmHcftYs2faCmAt2u4LKRBKNl90PAtLrO1m7irNLqxP\nna5FLFuoqEUxngWQrZkOrU//08uYlEy1zvd12+Va/oQZ6E6Jm29e3QpSEzzo\nlIsMP8i34WrbgZEz5L+c0Y0jrq6Zmk4oAZyA6P7P/81lYZXp3oocRzZdidpy\neG8ArPtTqq4PW8pw4F0caLaat8PBILY/7cEJtagqBBoGJ1yhMvNyrqhII4/6\n9AfrDIuQTlSDKhKV8od8NFsIxCjGxV5sapHiD1FnuewMH+y/E6e5b/CGl7S6\nGANTZotlplhRZ5bWlUz4PkwlJPCjIIp/9ZPs6Q8vlP+CXA0mD/hYKGfs77el\nm4CBfYB/TDh/7g04HzYjb215WCQ9TdSUCexsOXjLRyhKTs6JJymrGlsHaBGt\nhiz9aToIW7sD6mnm/Rr0i/c1ML8UpXYj/fFfEbzF4E70NjbRSE0ypN3mLXiM\ntpZ5hXuwlqf0lxMaZcG1tweUanDB1nSwljX2vrzAIgAQAAgy+nu0gb4Dl8WV\nuZJW\r\n=TlW9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBqFMzRjO7SFkpBirKRe/qzlAy/+p9Zj0a/D0KCvm4kpAiB88OjmsfTcIEA5RNN/ExQuT91uiz6wk4k7fUDbMgBu3A=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0-beta.3_1616352276309_0.40604715258402346"},"_hasShrinkwrap":false},"8.0.0-beta.4":{"name":"ajv","version":"8.0.0-beta.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run prettier:check && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0-beta.2","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"readme":"\"Ajv\n\n \n\n# Ajv: Another JSON schema validator\n\nSuper fast JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-06/07/2019-09/2020-12 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Platinum sponsors\n\n[](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n## Using version 7\n\nAjv version 7 has these new features:\n\n- NEW: support of JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/) (from [v7.1.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v7.1.0)), including generation of [serializers](./docs/api.md#jtd-serialize) and [parsers](./docs/api.md#jtd-parse) from JTD schemas that are more efficient than native JSON serialization/parsing, combining JSON string parsing and validation in one function.\n- support of JSON Schema draft-2019-09 features: [`unevaluatedProperties`](./docs/json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./docs/json-schema.md#unevaluateditems), [dynamic recursive references](./docs/guide/combining-schemas.md#extending-recursive-schemas) and other [additional keywords](./docs/json-schema.md#json-schema-draft-2019-09).\n- to reduce the mistakes in JSON schemas and unexpected validation results, [strict mode](./docs/strict-mode.md) is added - it prohibits ignored or ambiguous JSON Schema elements.\n- to make code injection from untrusted schemas impossible, [code generation](./docs/codegen.md) is fully re-written to be safe and to allow code optimization (compiled schema code size is reduced by more than 10%).\n- to simplify Ajv extensions, the new keyword API that is used by pre-defined keywords is available to user-defined keywords - it is much easier to define any keywords now, especially with subschemas. [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package was updated to use the new API (in [v4.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v4.0.0))\n- schemas are compiled to ES6 code (ES5 code generation is also supported with an option).\n- to improve reliability and maintainability the code is migrated to TypeScript.\n\n**Please note**:\n\n- the support for JSON-Schema draft-04 is removed - if you have schemas using \"id\" attributes you have to replace them with \"\\$id\" (or continue using [Ajv v6](https://github.com/ajv-validator/ajv/tree/v6) that will be supported until 02/28/2021).\n- all formats are separated to ajv-formats package - they have to be explicitly added if you use them.\n\nSee [release notes](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0) for the details.\n\nTo install the new version:\n\n```bash\nnpm install ajv\n```\n\nSee [Getting started](#usage) for code example.\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nAt Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.\n\nWe strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.\n\n\n\n### How we make decisions\n\nWe value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:\n\n- Will this benefit many users or a niche use case?\n- How will this impact the performance of Ajv?\n- How will this expand our library size?\n\nTo help us evaluate and understand, when you submit an issue and pull request:\n\n- Explain why this feature is important to the user base\n- Include documentation\n- Include test coverage with any new feature implementations\n\nPlease include documentation and test coverage with any new feature implementations.\n\nTo run tests:\n\n```bash\nnpm install\ngit submodule update --init\nnpm test\n```\n\n`npm run build` - compiles typescript to `dist` folder.\n\nPlease also review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](./docs/components.md).\n\n## Contents\n\n- [Platinum sponsors](#platinum-sponsors)\n- [Using version 7](#using-version-7)\n- [Contributing](#contributing)\n- [Mozilla MOSS grant and OpenJS Foundation](#mozilla-moss-grant-and-openjs-foundation)\n- [Sponsors](#sponsors)\n- [Performance](#performance)\n- [Features](#features)\n- [Getting started](#usage)\n- [Choosing schema language: JSON Schema vs JSON Type Definition](./docs/guide/schema-language.md#comparison)\n- [Frequently Asked Questions](./docs/faq.md)\n- [Using in browser](./docs/guide/environments.md#browsers)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Using in ES5 environment](./docs/guide/environments.md#es5-environments)\n- [Command line interface](./docs/guide/environments.md#command-line-interface)\n- [API reference](./docs/api.md)\n - [Methods](./docs/api.md#ajv-constructor-and-methods)\n - [Options](./docs/api.md#options)\n - [Validation errors](./docs/api.md#validation-errors)\n- NEW: [Strict mode](./docs/strict-mode.md#strict-mode)\n - [Prohibit ignored keywords](./docs/strict-mode.md#prohibit-ignored-keywords)\n - [Prevent unexpected validation](./docs/strict-mode.md#prevent-unexpected-validation)\n - [Strict types](./docs/strict-mode.md#strict-types)\n - [Strict number validation](./docs/strict-mode.md#strict-number-validation)\n- [Validation guide](./docs/guide/getting-started.md)\n - [Getting started](./docs/guide/getting-started.md)\n - [Validating formats](./docs/guide/formats.md)\n - [Modular schemas](./docs/guide/combining-schemas.md): [combining with \\$ref](./docs/guide/combining-schemas#ref), [\\$data reference](./docs/guide/combining-schemas.md#data-reference), [$merge and $patch](./docs/guide/combining-schemas#merge-and-patch-keywords)\n - [Asynchronous schema compilation](./docs/guide/managing-schemas.md#asynchronous-schema-compilation)\n - [Standalone validation code](./docs/standalone.md)\n - [Asynchronous validation](./docs/guide/async-validation.md)\n - [Modifying data](./docs/guide/modifying-data.md): [additional properties](./docs/guide/modifying-data.md#removing-additional-properties), [defaults](./docs/guide/modifying-data.md#assigning-defaults), [type coercion](./docs/guide/modifying-data.md#coercing-data-types)\n- [Extending Ajv](#extending-ajv)\n - User-defined keywords:\n - [basics](./docs/guide/user-keywords.md)\n - [guide](./docs/keywords.md)\n - [Plugins](#plugins)\n - [Related packages](#related-packages)\n- [Security considerations](./docs/security.md)\n - [Security contact](./docs/security.md#security-contact)\n - [Untrusted schemas](./docs/security.md#untrusted-schemas)\n - [Circular references in objects](./docs/security.md#circular-references-in-javascript-objects)\n - [Trusted schemas](./docs/security.md#security-risks-of-trusted-schemas)\n - [ReDoS attack](./docs/security.md#redos-attack)\n - [Content Security Policy](./docs/security.md#content-security-policy)\n- [Some packages using Ajv](#some-packages-using-ajv)\n- [Changes history](#changes-history)\n- [Support, Code of conduct, Contacts, License](#open-source-software-support)\n\n## Mozilla MOSS grant and OpenJS Foundation\n\n[](https://www.mozilla.org/en-US/moss/)[](https://openjsf.org/blog/2020/08/14/ajv-joins-openjs-foundation-as-an-incubation-project/)\n\nAjv has been awarded a grant from Mozilla’s [Open Source Support (MOSS) program](https://www.mozilla.org/en-US/moss/) in the “Foundational Technology” track! It will sponsor the development of Ajv support of [JSON Schema version 2019-09](https://tools.ietf.org/html/draft-handrews-json-schema-02) and of [JSON Type Definition (RFC8927)](https://datatracker.ietf.org/doc/rfc8927/).\n\nAjv also joined [OpenJS Foundation](https://openjsf.org/) – having this support will help ensure the longevity and stability of Ajv for all its users.\n\nThis [blog post](https://www.poberezkin.com/posts/2020-08-14-ajv-json-validator-mozilla-open-source-grant-openjs-foundation.html) has more details.\n\nI am looking for the long term maintainers of Ajv – working with [ReadySet](https://www.thereadyset.co/), also sponsored by Mozilla, to establish clear guidelines for the role of a \"maintainer\" and the contribution standards, and to encourage a wider, more inclusive, contribution from the community.\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=32,4,1&chs=600x416&chxl=-1:|djv|ajv|json-schema-validator-generator|jsen|is-my-json-valid|themis|z-schema|jsck|skeemas|json-schema-library|tv4&chd=t:100,98,72.1,66.8,50.1,15.1,6.1,3.8,1.2,0.7,0.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09/2020-12](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](./docs/json-schema.md))\n - [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) extensions:\n - NEW: keyword [discriminator](./docs/json-schema.md#discriminator).\n - keyword [nullable](./docs/json-schema.md#nullable).\n - full support of schema references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of circular references between schemas\n - correct string lengths for strings with unicode pairs\n - [formats](#formats) defined by JSON Schema standard (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin) and additional formats (can be turned off)\n - [validates schemas against meta-schema](./docs/api.md#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all forms (see [JSON Type Definition schema forms](./docs/json-type-definition.md))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](#using-in-browser) and Node.js 0.10-14.x\n- [asynchronous loading](./docs/guide/managing-schemas.md#asynchronous-schema-compilation) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](./docs/api.md#options)\n- [error messages with parameters](./docs/api.md#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](./docs/guide/modifying-data.md#removing-additional-properties)\n- [assigning defaults](./docs/guide/modifying-data.md#assigning-defaults) to missing properties and items\n- [coercing data](./docs/guide/modifying-data.md#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](#user-defined-keywords)\n- draft-06/07 keywords `const`, `contains`, `propertyNames` and `if/then/else`\n- draft-06 boolean schemas (`true`/`false` as a schema to always pass/fail).\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](./docs/guide/combining-schemas.md#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](./docs/api.md#asynchronous-validation) of user-defined formats and keywords\n\n## Install\n\nTo install version 7:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\")\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nSee more examples in [Guide: getting started](./docs/guide/getting-started.md)\n\n## Extending Ajv\n\n### User defined keywords\n\nSee section in [data validation](./docs/guide/user-keywords.md) and the [detailed guide](./docs/keywords.md).\n\n### Plugins\n\nAjv can be extended with plugins that add keywords, formats or functions to process generated code. When such plugin is published as npm package it is recommended that it follows these conventions:\n\n- it exports a function that accepts ajv instance as the first parameter - it allows using plugins with [ajv-cli](#command-line-interface).\n- this function returns the same instance to allow chaining.\n- this function can accept an optional configuration as the second parameter.\n\nYou can import `Plugin` interface from ajv if you use Typescript.\n\nIf you have published a useful plugin please submit a PR to add it to the next section.\n\n### Related packages\n\n- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - plugin to validate mongodb's bsonType formats\n- [ajv-cli](https://github.com/jessedc/ajv-cli) - command line interface\n- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification\n- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - plugin for defining error messages in the schema\n- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages\n- [ajv-istanbul](https://github.com/ajv-validator/ajv-istanbul) - plugin to instrument generated validation code to measure test coverage of your schemas\n- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - plugin with additional validation keywords (select, typeof, etc.)\n- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - plugin with keywords $merge and $patch\n- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't included in [ajv-formats](https://github.com/ajv-validator/ajv-formats) (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`)\n\n## Some packages using Ajv\n\n- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser\n- [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services\n- [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition\n- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator\n- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org\n- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON Schema http://jsonschemalint.com\n- [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for Node.js\n- [table](https://github.com/gajus/table) - formats data into a string table\n- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser\n- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content\n- [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation\n- [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation\n- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages\n- [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema\n- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON Schema with expect in mocha tests\n- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON Schema\n- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file\n- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app\n- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter\n- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages\n- [ESLint](https://github.com/eslint/eslint) - the pluggable linting utility for JavaScript and JSX\n- [Spectral](https://github.com/stoplightio/spectral) - the customizable linting utility for JSON/YAML, OpenAPI, AsyncAPI, and JSON Schema\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","gitHead":"3570c90881ae609da2a4fd130c728b40ef3ef645","_id":"ajv@8.0.0-beta.4","_nodeVersion":"14.14.0","_npmVersion":"7.5.2","dist":{"integrity":"sha512-M4SfW/InvqHRdSKcgVttiVzN824DOhX4fHYvSWjO1wyEz1+9AdZGbV0o4IA47IverLnyrZxAAd1w5B7rjI3Xhw==","shasum":"9f6779a0dac21a2ac0e1ca9604276eb0c9bf63e4","tarball":"http://localhost:4260/ajv/ajv-8.0.0-beta.4.tgz","fileCount":478,"unpackedSize":1036616,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWZqhCRA9TVsSAnZWagAA8g4P/j7y8wcOdFGZe3z6lGrH\nUdfLwRENr+HNrQ7NDGI0uIXp+axLCxv0lNrL4KhRjp+5NmjE7ULoXR7PD3WE\nsrNVDcrnRB0fakkecEA3h72fokO1ni796b4SfKvPzIGmP7RrYCJQPInjo4eL\nbo7RJ8oLg8kXcdk1097BTb3xrkdOkiVSEeKdcYN925Y2kKa9DlSnXZG7EHWE\nc7JbYMayl32GqnGMW9sFUDuQ52j4NFm91xH2lF1SqWuchkPMp+JoxYRgIRiO\n2YIQ3QA3MxzVpt1qjaTCD8b9ef4aknquFlpY1FrLusvzqjUIOrp+Wh+dmaFu\nEA8IDdmhhRgMiPx6UlXGWDkvImMhtGW/sNYHlzVDMkxN3AhuQsLPoYeeVIfp\nXckE6bmSbSI5S5QX6Xk1r7JlFLEnZYT2fXe6JIqgtnKcWJy0fXK7jeVRiaF+\nbuoVn5Nn74jGbPdkvie7AAjXL8EoCxDhm0xcPf4EGtv7eg5/U7Gntr5XZ38y\nS4VCcz8omE2+ZSLh6kBdlyCrg0syGhOD3pAVy9dFMdALuT8UCnXbby9uU6In\ninfFxMtcbn3H6ioNYJ4lPCCG1YAPqUPiKzBlV9FAhEIladZvPooLjcvUYlmU\njWjiz0RVH7XdNNyOeOKbF1BDWcQwtwAg7EgPrnINeTB4kOgww/DOcIsR7lkR\njYSG\r\n=9C6X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA/8KwqswGNsE3fNMq39IGdnP21Lo/O7r84oABP5rwRMAiA4jb71e8ymUrG4HPco5zD4bPnt+hKG9oliIgf3FJ+5lA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0-beta.4_1616485024717_0.7681146387238358"},"_hasShrinkwrap":false},"7.2.4":{"name":"ajv","version":"7.2.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -f \"\\$recursiveRef with no \\$recursiveAnchor in the initial target schema resource\" -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm link && npm link ajv && npm run json-tests && npm run eslint && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^1.5.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"d6585481ab698d914639c8a7c379c164498fcba6","_id":"ajv@7.2.4","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==","shasum":"8e239d4d56cf884bccca8cca362f508446dc160f","tarball":"http://localhost:4260/ajv/ajv-7.2.4.tgz","fileCount":422,"unpackedSize":927198,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgXZkVCRA9TVsSAnZWagAAw1YP/jk7Js2lJcqcE55VRo1K\ngOzMriEjh7AJD8qbTG5X4BERkgv32c8eDxa7zb59xwQ07JPwUQWk+auyHTVR\n0ZC0aXute717jyZahx1q1VyOvoXwuAbJDtbSwxo95JPtbZdr3U3ylsV/mg8R\nciNU8p12Okwvos53bjppIr/QW0CoJK2128yDYGZmQwoP8k/FCvcoyTL3x8Ge\n5YH9ROkk7tua9mj7nlpOY7lr5rO0FlY8yZLQVJBASk3YlQsmE7Ztrwy65g92\nFJ9ru4WmV4dq2H3Q/c0pXr1BG5Wx3WfirYsOi0s9KuuF9NgyHdpyvelHTxb1\nMkueJJjRIxjvuf0TMyg8YAtwwWfPfXOXfd2LKEcHPV7AGSBaHfwbzJX+8cvR\nEkUuEvgUKIovdLZ4LZKeG3XbsDH5hXeYJu8CX8STuySWm10/6fpz+tJLjZXj\n1uOFhMza11ZT7VeSFYFLdIF3OcpSbOIzbFNnhIgKrttsvaTbAicDi6+W/dYn\nXtImw5EGkES0/SMMk1RVBEOYk2/M1LjnmIC/eIDHwtQotZIph/k/R4K4y9MN\nsqd0MaF+8kFWJzqfjXTmbm2sWUIWFVNySrmzS8fyn1g8PX28V0RoQAk/TElw\ntoliF60Aqt/UadoHeG7io0TJ87IAkuwbJ9DX0zAa3HGAOEkYhazrCNi6KqP3\nTAbi\r\n=yhsH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNJKqAdfaVQ30SayRh2YK1iqXKI/35kZhirz0fRDRtTwIhAMX/6pxnoLEtmdCYC/PWgoM4ro2yynd9Vv2LeW2XbRbA"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_7.2.4_1616746773188_0.7629486919187622"},"_hasShrinkwrap":false},"8.0.0":{"name":"ajv","version":"8.0.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"d7428bed95f5f1a5863ab501c8a59bddc06f49ff","_id":"ajv@8.0.0","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-AgKgeO3Y58RMZoi3S+6OYqGjndt8VlrCwGM3bQEMtbGTLOO+VrymV1Fb0TnffzG4gSwa6MEgIreOn9y3Q9rt+A==","shasum":"392f0aee6a4b6ee8367f5b0bf516e43210762ae7","tarball":"http://localhost:4260/ajv/ajv-8.0.0.tgz","fileCount":467,"unpackedSize":985539,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgXyiZCRA9TVsSAnZWagAAFv8P/1GqaRqICQMKkvGiyBj7\nWrnSaIWD3khl07mB+r0mXQvMqCUUxfZ4dG1B1tNoftfxesvPBMYsHEGK0cCI\n2tWON7F+l3VVjtdslbgWiIWAlbg1Xlh+jZA76EIdSei+ONzgkdnVJmIiCydj\nsuqkMP/DgsKoLqSrJc7BReerajNY3uycGP0nYZBp3erKIhS/5P8NfC47YpFo\ncGS4ZY2Vj8cn/LAXx1AWis32Ix24Hj/jjM+n5TnJh1v/+Xs3aQpPp8+Q9HTD\nrR0hINVmLdhIDzydF221gA4xJlewGc5Ps2K9fnkBQqFJqzzTnKZ60VckOlrd\nUGRClo5aNEHL6Z1wUGL2qmci7yU/JmqjL2FeLqwKXI3Gb+o2+zilRzZsfRpP\n/+fS0MTW6FFe8sKHjdlklcG2EPmUuklnsW9OlUJjH1lM4SV4YupRGpIKM9yl\nhuuCxmsAOqICzw57JXM1F3YzYObmUS0o2yZzDBLa7yjHe6JEjIEk1ham4+Ul\ns9FdnnLa8ih8fX0YPIDLx7j+NVlyKt/DBp3PbAET31ryzsI3mbq54lnVWB7T\nNtWC3vgruEdHXk8aeMT17X5eap5bEfFlqNJa9Brt+kXlcVLkuk+p21jF14VN\ndEX7mFzrTjng7JMtZG+2sfrVOyQdBlf5Og79CG2+TbBsOEdHrXGT6LX2LRzx\n9agx\r\n=/ZGD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDcY6pYSb3nS+t/lxi3csI2BoEb0xT8/vMmOnGCFdIcBAiBeRky9OirBB/4lUBWenotLjFlWWfQqy95oAMqcilz7zA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.0_1616849048849_0.5448691335872347"},"_hasShrinkwrap":false},"8.0.1":{"name":"ajv","version":"8.0.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"022874f855feef8ca585407e2bc5190f7bfdc542","_id":"ajv@8.0.1","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==","shasum":"dac101898a87f8ebb57fea69617e8096523c628c","tarball":"http://localhost:4260/ajv/ajv-8.0.1.tgz","fileCount":467,"unpackedSize":985725,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgX7YNCRA9TVsSAnZWagAA1VcP/13GKSKzGg3wLYTYyurJ\nrkCAT+NJ/JrtnIC1f2HSqgxlEcnVuIU8nqafs0eHaRdoiJfLc6Hs3zMqIUAx\nwQ7CVX2vgk6D5ijS2e9nMpcqq1bgoALUIrk7qM56vYN/X53Hj+an2KDcJnyT\nzHPQdM9SDgY2QLRg48f+h7g8/iJVDGxkDoSwnwXBU9imSMNCphbeN1H0d/yR\ny/e66EIH7yQ/AN1Wa916OLbaAAYoE0ypzx+PSP4UJMsgLU6NV2+6DFm5/iOZ\nMTc2BlnbdUdF9l034pkXO/HA8R6n0MCy3glEL8k21cpzB5fDlEKQUXogD6fz\n7okTGeiarYOqsCznv4izmaM3F+KkbzOapPh2neiv//qfjwBIWLlYvBIO/CaA\nuExNtArnyzP7UrjyzWvcZdHyPrpJXbzvxIyuLcY6Dzt81nwG0A/I1TEbfSr1\nQGDr5eTii21vzPulnHS0e0C+EGva2M4PdiMUxi80AK6Ts1KtrXvUlB8xTEoB\nC/DWfPU8OQvWhuuinKNAdrB2zwx0yzkB1te18xwe4W6CB9QZjunWYIdmnjSR\nq04NLIw6M3Iu/aCsWrrnhjI+orDEhfvyRGWoZf1IkC3iChy3wct0zdIdEJaO\nzodIPJs3VCMdIkISMIFDclyKd5R9UaSmjpATzJzxyj64Cmb2VpvqBajdqnBg\nzJWc\r\n=ZuFv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFuDQ1F1NpyL0eYI03ERv/quneJsh5JE6IvaXeuSAFxdAiEA/nd9evG7NzXk+5qCtm88/Eo+h6lgNyuDNWfZCpi1bFk="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.1_1616885260739_0.28858210660416694"},"_hasShrinkwrap":false},"8.0.2":{"name":"ajv","version":"8.0.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"24dba5c0795f9c01c74e60c7407c5aa33a2da2e9","_id":"ajv@8.0.2","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-V0HGxJd0PiDF0ecHYIesTOqfd1gJguwQUOYfMfAWnRsWQEXfc5ifbUFhD3Wjc+O+y7VAqL+g07prq9gHQ/JOZQ==","shasum":"1396e27f208ed56dd5638ab5a251edeb1c91d402","tarball":"http://localhost:4260/ajv/ajv-8.0.2.tgz","fileCount":467,"unpackedSize":986792,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZCwSCRA9TVsSAnZWagAAHTgP/3dfcNOMYHxTn/qBwi/C\ncVINUw0imhxIYtU4jEpXuVg+SRLey4n1HhyJUQU81fE4gIuRDL0X4q4qsbOM\nY72109mtFNjwZNaGm2KWF+d5ZfwDE24K0QwvwaD0LjSVwErKeUW63pgelEDm\n9Tfyt781Vw+t5cqJXWjv4oqH4uqXU4BLnFzzMqLzEjZIjWfkLTpOdMmMuJi9\n+nobdIhCTGHSCNimRaOYxD0syh1vYgRjzPERjLixerFDZvtgcCg5MV6TtIWJ\n/C/vtukvdK21kE8nhBmaU+p2WZxfOIFbCQbkEXJrBU0Ry6UnyqWBDLDoBdZJ\niNmyx4lhN/cyJggje7K0CTAXMHKMd9P8LorWCtOdKOAkAveLxU+sDhaFLFT6\nU3mv3laWrYDdQ7OkEFsUeVNWBF720sSsu3ohvXiNrCZG/mV9H46arYiIqgh8\ncrqHAURTcMGp2SgKAQVVcTI5tjwfzbx8OypGvskdbvExXn9g2XnQCWSguJhS\n+TuEllgxW/9pRICjWpo2t5Y9/yukwQKoM/897XlWnxrPnnFoWtxlIfq95i5M\nmllA67QRWbvFtk3l3ezjmMqjKubKi2K78c7Ph55mtfCC4xlShz52FDgn0NCC\nUUL9TjfL5MPve13StG5oEOWLCuMOcrhPwDZQtdpUaftZj/FThOZebHeSzGPw\n6wTq\r\n=sGU5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEv3RUkOq37H02WkPdaZF2lTCn1zDmJzE48xs+EkthkGAiEAg4vHigPWBV1jrJHSRIqNtbzGYxDKIQoq6+wQAYYVnUw="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.2_1617177617382_0.9710023278386131"},"_hasShrinkwrap":false},"8.0.3":{"name":"ajv","version":"8.0.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://github.com/ajv-validator/ajv","tonicExampleFilename":".tonic_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^5.0.9","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"f16edb153976fcb2541144715d309d4f9e94d8ee","_id":"ajv@8.0.3","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-Df6NAivu9KpZw+q8ySijAgLvr1mUA5ihkRvCLCxpdYR21ann5yIuN+PpFxmweSj7i3yjJ0x5LN5KVs0RRzskAQ==","shasum":"81f1b07003b329f000b7912e59a24f52392867b6","tarball":"http://localhost:4260/ajv/ajv-8.0.3.tgz","fileCount":467,"unpackedSize":986930,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZXCECRA9TVsSAnZWagAAS/sP/3zRVlsGEQqEi3LvDmhJ\nFvwMZIgnALIcHF2GlZ2WidJHAhWGfzxzxduq66Sp91GOhLrzpVmow4Qdne/6\noGFEMZzvKiIDJWQMff/Y6TnIC0hVHpwnhbFom0hwVxCE8i58v1acfxfwUj2N\nVwEQT1gIA6rtEAZb1yiiJbXjtr72jyWz4wpaxRhd1z/S1u1pHMrt8PshSHbr\nw3IgTmvnLPfvhiEwUdqFtgTpKdIVsU3otzEVaXsNnaw7SWE1JSZtOphz9BNk\nsZa4rDCXZK8YSd5hGh5OJvSCaODtRTyhrDml4yDNAR11mfV4i/km6U+znj3Z\nKPwzZFN/llwxHyI/h7Bc4cQysyRiAaKoVCDwg9JFohfeeQebmLXVah13ZmE+\noz+aGfhQtKq0gZOuuRaLq0YEDveKMgABzF/5v25U0sk05yrNKCsdIlspH1xV\naRazKZ3YpnPVLM8IkCEGKJvPqdUyn7qT5BWK5EoGH5FJANJOeZScll4r512i\nHY/oc4NEw6HXCR4GMm7riPXxkbugDfTWWE3740F1xorGRr6GP27cSg5J1Ijv\npm3KsZnls7nzJOb56lDizWOzIBSTmPQyVTxoBSffcQWIA7OG2SOpKlaCPA4U\n1P9F4um2DaCb+8jKKCpUfA14YejIpsHonKu5EXoYZqFdzfx6GJdH2sNJXnOX\nj2KE\r\n=rT//\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEY31Pjia+GLn7Wx1fLqtVozYs2TMpy6Cm+9BxoPXiCdAiEAv93QkN9BmtkbjY78j8XKgAcVQ7s2FCouAeoBV1pUVfo="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.3_1617260676251_0.8763611490255627"},"_hasShrinkwrap":false},"8.0.4":{"name":"ajv","version":"8.0.4","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"facbb231b726ba4cb5b879432f3dc9a9d9750acb","_id":"ajv@8.0.4","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-v1qwknPv7rNGqtiaC4ywb3OZ3LNrEjbJL5igAe8eTbXOj8ye0XVul2pFRulwl/j3QfUKdQ/J9HZaYfQCnR7cvA==","shasum":"7dc77632eb5dcde646b3aa18dd3bfe0d8965f379","tarball":"http://localhost:4260/ajv/ajv-8.0.4.tgz","fileCount":335,"unpackedSize":657421,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZxPfCRA9TVsSAnZWagAAip0P/005O6aUyMLJRCFwOxBI\ni/e7C3Mpgkd+JvaEEVu45SjRZPqdkXwCSMYr/n1avzNSCrzFD3whM9Xk+DU3\nRia10HtrMjgHZnn4x2lTMtf5f6kcAcx3iUqEb2fVFUC6uY2KYBZHabW2HTu8\nQb0eNqRDWLahXGjeDf6xsA5pr7OFcRJr/YJsiCCn4RRe8yxNQBT4+++emz9/\nLkl62CydLzk2J7TMEtlOEKlRBpvjGqYh8jDTAxiRGzby+Rb66HD3ox3IoM6Q\n0mR0PvSAdUCjLZCQw/5gekD71Xp3ecMHXHFpQwPd9I0BgO1vTwRtFuce32tP\nSXk2eYsXQq45bJ67MO4LWf0smsmLyrLI7c11p/H6gU7ItFoBesxd0Q9Z39is\noQtRTX4TEoGFnwXjCRvdQpVMyg+E+VwyR7J3XK7jp1i2ja9UaWLG7L+fIxh9\nEnJ2zF0zQLMAeFve8JpiUXWB6h1dH5w3NxoUZLSvY68UTwJEv+1uB1eQC4th\ngp8WU79fRM4rG1KhGUxTcr1bXa6JIq8NccPebT9FyPE7hhIJEP7zJFMQ7m15\n+CWPcBOO+A82CQPKaKmnA8y18s/vnUyx1RzYnW5/giSjhGjN7Ix7P/X2BAyw\n4fn/+v1KMqOgA0WzBxCqq0q3i4tZRlV27ljzzl2Ph3MBCzK2WtmCMDHaK3tH\nNJjB\r\n=qGVY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICYZ6WWGGqBl1w1EOsjtp8vpHVo0XngwEDWLXx5YhLSVAiEAivGvOurhLYMrCes/2XUxhS6Ut/DY7rXIx0C/3P1waDI="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.4_1617368030587_0.04092862724189339"},"_hasShrinkwrap":false},"8.0.5":{"name":"ajv","version":"8.0.5","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"b5642ea8655c3922de7f2403cc99d668871d35fb","_id":"ajv@8.0.5","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-RkiLa/AeJx7+9OvniQ/qeWu0w74A8DiPPBclQ6ji3ZQkv5KamO+QGpqmi7O4JIw3rHGUXZ6CoP9tsAkn3gyazg==","shasum":"f07d6fdeffcdbb80485570ce3f1bc845fcc812b9","tarball":"http://localhost:4260/ajv/ajv-8.0.5.tgz","fileCount":458,"unpackedSize":979565,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZz4cCRA9TVsSAnZWagAAPzAP/RKxknmY2CmCYsXDDlhr\nLsWdnI6Ek35rfrUQfH6xseTvlvjUhb3hySbiUh4+3MH8VQpnBEGhLC80tJ9S\nvAVwfi9pa+MT/RnfEgZi6vx9GA4lLIA/xNyHCDN2RZUSrl6bM/0Dk7eJi806\nwO+QVCMr+vT7GfzrRMw3mKnOn3XJMoj0cmqcT7UyJFgB4URLtxaZ0frCnCXP\nZ3nfIsvuE3P7O/POBNUhHCXOblJJL7q1CAgHqAPyK2Y4lfb92U5D6u67cBn+\nY0X4a73thrxYsN3Eis0m9ziQ8Vu/WQHGYeE/wnCjdIamn3AWBIlznJ2oU4cP\nZgrzQnkRcl4by9hQ24NGDhE+wWsaxEJgSEPPHcpjODml1FYfrePFsXk3PzrA\nIwUgkQ7wMrORQRA4qZgzkttqgdtQqgrwI5UzZeealOyfznkkPi2nyWB5i2WM\nhkdHrS/J+GjESCQdCwqEw0oD7gbKN00wNax3o3tXh2UW/zgGDjAr5KIBF+6E\nsJg7wcGy9qosmOK62b3wg4FqN0s/aXrg3wNL1w9uTgU5jdj+1rRPSlN06kmF\njD/BivOK+uxrrD+ZGalTBezRc50ITjdFDuyakEPrF6FMs2b0/rGFmrLuebso\npSW6quOCAVdXkt+XCgpFZn7ZC/aCax+2kibBnEGpOqXe+WgY+t+UQJ/69Z0z\nibUx\r\n=iMZC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD++bp9pUeiuAJ9vcAN4dRPQ/zKYuJNqaxQOmxpmpQTMgIgSeWXMgboUQ33t4NwayN8vVfYXKU10qp+nSH1cTPGtMg="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.0.5_1617378843463_0.9631326227977666"},"_hasShrinkwrap":false},"8.1.0":{"name":"ajv","version":"8.1.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","terser":"^5.2.1","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"df07f668131c6670e9ed624f60d6419a4da9a3c8","_id":"ajv@8.1.0","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==","shasum":"45d5d3d36c7cdd808930cc3e603cf6200dbeb736","tarball":"http://localhost:4260/ajv/ajv-8.1.0.tgz","fileCount":458,"unpackedSize":980522,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgcylACRA9TVsSAnZWagAAObEP/jqDELz9d8KSWuuZe7NG\nIhYLxtX6UZw5ETimXgMebaQA0GMaD++s9iVuNOtjfcUtt9Q4jkugpqhDIpFv\n9lF6NI8kciK+pGVlGlng2X45k7hg+zlL8JWIekRWoFZ+80xc1AaPiV69mXWc\noWea9FVxiYs5FpQog2KIxA6EoPf5ne8Yu0lW4SJASt7iCEbQos3APzBmTVrz\nIZVVPnunSqdaXOqr1rOkRJFLjHHT+HHcXjNFw3TpUQKULwBl8zEu6jtSGLkl\n9qNRXhGbPNui0UHGiCsYd6prI0qsLdufTxW0eAfAQiush5QQJEGSk8Y9IGuo\nbai11J12be4g5f8FcCkHS1loM+aI5Pe+c6YB8zaqxCPX4O+vMpi4YyGqRuAO\n3d7ZcrVIIDtFQMzX0vtMR1CgQCm4sU44Zx/oDjBAYD7dZ/1UhRgrER/iL84E\nzhGff21C4b+2YYl8a+Wh/PJfZNe4bbozBE7Qq0swvJRIb9QnnBQOMIllPrQQ\nH/UqnYVKoPzQEi67IdeQni69ojjwV4wIjVhdJ9f/sx0PIrl5ix19TBuBGr1v\n1SsFLjR763FTmR3ZqTuO++FSAYIXKY8pmjdgFReyahv0ujONXcRLm2yFi91C\niloI1yN2HBaYuMxlbwe+PiQ0s+3iHZd5o7zvAeQL5pQHi5chXtik7WyBI25W\nIcr9\r\n=fARX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOWPTXo53rjt+4rzB54ZDoARLxZV4uRs7a5BTorTmnIQIhAJvguHB5e4Jrs74nAvJhYJodt1z22rIUsy6xRa0cSW/Q"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.1.0_1618159936103_0.8768703964028881"},"_hasShrinkwrap":false},"8.2.0":{"name":"ajv","version":"8.2.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^14.0.27","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"2123bf28c9ce9a948c32301ef5b2ed33359e3742","_id":"ajv@8.2.0","_nodeVersion":"14.16.1","_npmVersion":"6.14.12","dist":{"integrity":"sha512-WSNGFuyWd//XO8n/m/EaOlNLtO0yL8EXT/74LqT4khdhpZjP7lkj/kT5uwRmGitKEVp/Oj7ZUHeGfPtgHhQ5CA==","shasum":"c89d3380a784ce81b2085f48811c4c101df4c602","tarball":"http://localhost:4260/ajv/ajv-8.2.0.tgz","fileCount":458,"unpackedSize":985073,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiCkHCRA9TVsSAnZWagAAnZYQAIvRTdYlDVEsdKwKSOa4\nheKz1UH0mQsPDylFUOf1HVqkaKE9MTVoSsj6PFrLBbs7zqLituSIlHk0Uxkc\n/ySzmfLURro2MFhwg4iL6JJRDSdzYy7PJMGxOMFNj4V/wL8BfrXLhBlmljrd\nlgLQG2fI2QEonKbJNN0rU11fPhxLVo0PPl8jrmAlfPKfuwh50yAqBF8/F61M\nvsJajs+l6+szx4kk7/WWtShWo3UNoxkgUb5TOIruTPSj3/VtPCau2I75V49x\nawH04jjjPNtZdavOxoZ8krLhesIvLGbdva3zwrKMausiH8QhKVcBrvrCpgFk\nHsVNX2cG2vRDash9y+M5mot1aVuXOWh86MkzQ4l+g+qfyR4sJiaoOBCXWczI\ntiugAlYNoVR9XH+7h8v8QnUjdLuIj/vq6sg76GAlMoAL3nuO+WjjXKW9p+92\nfU7st0L8LVvfhEMQUltqsgGfvh8NvfKmIUSie4feR4kdoTGVq4JF01nbzhSD\nSq0HApNB2QZpNmfn3VBMTKm8zw1laTJ1OyuBwsLw6twB/XqRN0JDELL9r62B\nPcwzWKD9GH/Yp2vsfSgC/KLAisjUrR68VYwE7ORMYMpEYPiS+GnTFeWlyFTe\nJhJzFPSK3XbW4Dv2xC0z/rr8Fb9luv1EGh2IJp/LoOfOV6MBf1io5FAVVZ05\nXN82\r\n=CrVI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGrGE74bPNrzTBZTl23kHIn7KT/JEWPki5jUSNf9htKEAiEAs3OIfI7974YZDP5ai4FMGWsJtDGNS562csrlt0QCr2U="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.2.0_1619536134601_0.930788876360908"},"_hasShrinkwrap":false},"8.3.0":{"name":"ajv","version":"8.3.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^15.0.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^5.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"dec89097def11e48d2de94e3e214405f18658986","_id":"ajv@8.3.0","_nodeVersion":"14.16.1","_npmVersion":"6.14.12","dist":{"integrity":"sha512-RYE7B5An83d7eWnDR8kbdaIFqmKCNsP16ay1hDbJEU+sa0e3H9SebskCt0Uufem6cfAVu7Col6ubcn/W+Sm8/Q==","shasum":"25ee7348e32cdc4a1dbb38256bf6bdc451dd577c","tarball":"http://localhost:4260/ajv/ajv-8.3.0.tgz","fileCount":458,"unpackedSize":988475,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgl8jDCRA9TVsSAnZWagAA2MsQAKL7BzqpySQtuka+6IGW\nVPeBWRuE1/qqPOj5rY/qBZyNo6VnqMSF9gQBmCv/s3GA/f3yn7SyN1AzhM2O\nOAxrpUlfx6+wClpr+ZB9g13CM+dMtu9GvsHanJBj9iVgrp6FtFDc3eUPbxXS\nUhmYfGLDb3PGBuzHMq7meDQIjxmG+Wi/AiwKjPIWVspBK5FrgvF6zVpqiZVE\n5fdIoMO+GBhYeZI40AMlvKtzhhgRYU6OOvZidX/+84TWXgsmoS0FhhypI2C2\nRwglxpRTNR2mRTlP4mNycIsu3qIzNdqVg42QHW9MNS+8V0zY0nw+ktL0xFxp\n0+wrH0GyYv38lKAmt9h2wY7XFYROlN6SCCoUn4umtOSQnrCLHT76fUotFhJg\nlr6ewCjEE+wUGQ6YzeEeoRhoFvURkwX1yFQc3PldC6zSklB282V6+3fIADCj\no21z3BvHMLUKipe2+xGUsbyDbhq+P7JGVH3eh4KhJQafd1Uf73U+ZEWXPeyG\nBZu4eZl6GstC8VXzDQbfXRbU1XvIHbcTq1qAI1E4apiCzo2h0piEGC9IDknz\n4qj6apHAmWjznQuJ9sxDaMi4Xzfp3BHCEeOrTP37R/Ct9YvUQTVQquJHXi0q\nFM2lye0yLPkmkcjhCeWRwmuLiu1mDUL12Os5WIKkiKwaWQPiVwoN5em9LM/H\nBKGm\r\n=S0Mu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4j1lqnk7YEO4Kw7j4i3DvkKp9s3MZPBbQRfJIQFRsggIgSlB+nLAR9NpWlYy3I3DsfZRRyQe6EP1d5oNttQocfI0="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.3.0_1620560067325_0.05086957557406735"},"_hasShrinkwrap":false},"8.4.0":{"name":"ajv","version":"8.4.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^15.0.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"84abab262528969bc19879f86039be116df10964","_id":"ajv@8.4.0","_nodeVersion":"14.16.1","_npmVersion":"6.14.12","dist":{"integrity":"sha512-7QD2l6+KBSLwf+7MuYocbWvRPdOu63/trReTLu2KFwkgctnub1auoF+Y1WYcm09CTM7quuscrzqmASaLHC/K4Q==","shasum":"48984fdb2ce225cab15795f0772a8d85669075e4","tarball":"http://localhost:4260/ajv/ajv-8.4.0.tgz","fileCount":458,"unpackedSize":990584,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgntmYCRA9TVsSAnZWagAAKCsP/RyDKU6Hrq7mEyyK/Soj\n6VyWke78FdXVo+HJETg2FO3Nn81h/SARxClnu1aAulEpZvCZMg2k64/vk0Vb\nXO2gfgHMH/uObBFBAONpUECpIH96WbmwfwCr550p7VDQf3aC3IUfBNosAZF/\ntJIhHZiB9phi1PlHKZ8sDlI6thc+MKsSmYQ/UdL0uvLN0J0GeujwRcpPZf3y\nW9IzUitZpiyCj3bv2i+jtcD3gdd0Yus2DhF5llWgW9rrZ0bo8oc4RjEwP8/J\nM8o7fMqiAXNCktUhJROofHpobJEuyh4I8J2r/nYBjJBA2HOeQnIGfw9lXFRa\nXloSH3iVZKIiBc0mKsdXmnRJZdULWOYNS7L710tND5Rr4zoGvIXyUfW/GlZN\n3yJYPEu69cHj/tzAms8gpvJyblEsEvLqj1DF9Aa49TLmnoUI+zEqZXrfWxGu\nEnzRsFdrLdAHjfXDdSFk24dbT92JxsWvEAN3s22gnpTgOfBbfxUvNLiHriZP\nhwy4nntzI2uNJXrsERgN7XdHZI+0Q5qoUU6m3ZSPGlbsRDyoni0LvIDX8IsB\n55vnDiqmD/tvDSph+OBYZYhsrJLUY+W7vbfuxVJkEbmAtG5bDj8OsXvt7RWm\nwe8So8Lm8XJAWEn9+RI+ybqEW5nhZMbFIvjuF+tGI2JZ7crJOEZsRspHh+7k\nl3MW\r\n=XWRn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBot+BlwnKf64Iv4BgOxrZPjiiGOsGpKaTz5Mhp/Y5g6AiBQCR3hUDossDcWXSIMgp4xcIh/EJEUdG7VyJk0OBEsOw=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.4.0_1621023128388_0.7353005585410983"},"_hasShrinkwrap":false},"8.5.0":{"name":"ajv","version":"8.5.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^15.0.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^10.2.11","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.0.5","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^9.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"be07d3d8c0aac8fffe68378d25bdd892c61ba2e5","_id":"ajv@8.5.0","_nodeVersion":"14.17.0","_npmVersion":"6.14.13","dist":{"integrity":"sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==","shasum":"695528274bcb5afc865446aa275484049a18ae4b","tarball":"http://localhost:4260/ajv/ajv-8.5.0.tgz","fileCount":458,"unpackedSize":993887,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgpmU4CRA9TVsSAnZWagAAicwQAJidyvbz3bIAeGYHai01\n2HCpG6psPIsYHA27ukfrQPloRKsEYa5Fav7oH3mfy9kSbxQpE+zWmR9RMWlI\ntea/4TvERhYFYPunKLozKxzapKYUNg+c2srXt9Tl4W28YBMav9/sicU9FH0w\n/qBd5t9LxMdz0DbyrbDcgcq81EfOysqgku4WNNvdna6HYyaCcfVhm3T0wTdS\nmI1HTz76b6bhL6I5U2ckSMDuJW4GCR1P7KAIhIdtQ6tNSLcntt96HltCpxbI\npCuK1vWTKyWzCBzInJmkAd1t6J2cS6jusYRYsyqPiE91u4dAeLsZQrsBzfkN\nWc2+3BppvVY1D8xyPVXPZaggOaXrwu8GqRWLIYbrMm09d+H76lgWJNpoMFmZ\niLzKMNDz04n8s0rGS5k20kCDVrLxraSXjXcadjcv2+mVBIErk/Riw1SZhZSS\n+uCcGHw2Bw7mOocu70437fwG4Js5QeUnF8mg+HdxlLvpUNhRsEZm0NFwNmaa\nq/h9Xl8rmeqVySuZgF2tuJBtAB/HaDh0JwmaWhN+22lI2+E2hgd/X/+dfAeH\nruvhdxfdN+BA1/2Z1oDt9j0IbvnI0iqJUduhjo8Kbw/nA8ztaU3OWg4eVp7h\nCkNdB8vXoM6f+jNAV7rtiPWOcgcNiJD//+s+0q42YTqqUdaVL0uuBzN8LQjH\nBiVm\r\n=Rki5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTkvnAMcGGT66hJq1NGiKAITcp3a3n/5j4aE0Ea6oqKwIhAI1MA5ySZF03P9+hFW/Jnd0QRrhaRGfOojA0y+H2nQdZ"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.5.0_1621517623520_0.2034396048160314"},"_hasShrinkwrap":false},"8.6.0":{"name":"ajv","version":"8.6.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^15.0.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"f8708387a5be62fbd0becc0cedfc580021a5c5da","_id":"ajv@8.6.0","_nodeVersion":"14.17.0","_npmVersion":"6.14.13","dist":{"integrity":"sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==","shasum":"60cc45d9c46a477d80d92c48076d972c342e5720","tarball":"http://localhost:4260/ajv/ajv-8.6.0.tgz","fileCount":458,"unpackedSize":997144,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgvOJcCRA9TVsSAnZWagAAvQEP/iz/nIYLWARPdb7aFYVu\nVUJ9QXJx0pf0j+wzhQRznxoMWK5obpJY5cadEFlBmvsz9yu1RKt9N1wf6Wsv\n0GEm76248GuCi4+add6kQwSaODYK2wnQM9G8wpBZny4i/Eci1ylRoaNsCH7w\n4o5stbuPHCc7IP5diH6ZfFixX7LuRGrFEMpHHHfnGXLVNJd/n0RIFaEyNE3u\nxvZMH1fMTdwvC33MOQTcel19fZ1k0MDag45qKYbvpvZZCNtv8VjeMDT4/tL5\n0p0tXkAzTPqP4r0DuwPha8QLhzq4Tp7GwaxhqT0sPV7V0MntLqKj/qxiZTyt\n2rDXAEGg7PbMg59zKsmKsC8X+BVqQqtoA9FRHywKFEAtAe1XnSeFn/WTMb+T\n9q5inxs1MOMRlgnm2JfmT1IleCBWOe2jfyspH9OjHkNkQQpRqxt5h4bHNDrn\nfQJF3cgdyI4VIVUWUHHRd2iT4wgA8g//qT0cePf2VPOaD+CpVYrx1Pa7O9Ju\nOVJ6tfgAKxq4vzI2UZtR2BBQtYO0tIgkv7KXVS5xHAuz8MhJUcfRl3LJTm4W\nceFWq6OioF7HdbRieekLlFpn2r0+Kioo7ecyuVEA6H92cs8ROGfPJwu7DHNM\neseLo1X6bYyq0NY8tvB7TEDW2+iIsjfZlOls6w37JTMbLqS/95/WFBfrHncN\ne7IE\r\n=gfVm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzOCkWwgnrkiVKpWfwnJf96Pr4LfCA2wa8VoBwkwBj2AIgTDrWy4QNFSK9a/8mqVHUCK3opLQNmqum9ZtLu16oRQ0="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.6.0_1622991452432_0.2906901136533957"},"_hasShrinkwrap":false},"8.6.1":{"name":"ajv","version":"8.6.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^15.0.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^6.0.0","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"9166e38f9ee7e125e283890c60a594d18bb63614","_id":"ajv@8.6.1","_nodeVersion":"14.17.1","_npmVersion":"6.14.13","dist":{"integrity":"sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==","shasum":"ae65764bf1edde8cd861281cda5057852364a295","tarball":"http://localhost:4260/ajv/ajv-8.6.1.tgz","fileCount":458,"unpackedSize":997724,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4YUOCRA9TVsSAnZWagAA9/MP/A/JVYP3mXrMtputqlQ7\n+oRL2PiVO5J5n95KG5ueDG2mSi3w9rDMdVc+mG6iUuxWic4fwwptkIXycGQE\nQNkZfKOli2afry4HCEj2ECbaZDuMzxKfs9j5+io72ocDvAxOBfbZylC7UE4b\nNr4ZtRdUGyzIgfM2vzdqfyIgIMFVYHFM7h8jwyZaVPBGOHnIEKz1XWbmSKgf\nsNDx7AFBDqQr4ghW9HQ9zS16xTJ+ezNk3sAoSwUZim6vPvyWMjbGOQ7UDxur\nA0ia6ZSw15S7dxOvKDutn8o46Xpcf+AlyOT/8KlblSfEDmvR08yVs1w3QNrx\nAlQFspdawHhkCmAoaGbRTEGrAIveApZssus/mJ6EvN7KGar+mB3WNIoXX9Qq\n04HB4UwfVA3v96D8GcwCPy1b2Vdavxz1QkG7LMm3F4ekhttHI2Uj8CjABouT\nDMzAvFanvth9C8t6cr4ohrVU6O1V3eJnlvLGkrJAsY+wrXwc5CTKvL8tYosZ\ncC6NQSXHEtgdPxG0wvv3AfsjHrRdJafuzFAR8Iu8YiLWYvFi1enH9f9m83oy\njQQIOE/W8ZnhHWtFasx5DhGmta6C+VeOtJG0NHXo2u21A/jlS1KMfZohflHN\n72Qy2bUsIi7tKu8BZTWHWv5VepFqkPtyUWvRTsu3WbSgwSRJB1YUa+xsGL3n\ntEJI\r\n=qUzO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF8TBhbrFUCmH/r4cXBp/9hvGxTDd+/8d3UFvV7a9AJhAiBUS6cRsHzlzKPSgoiqe7rstwB7UO0y60Pjvwr3/eT8LA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.6.1_1625392397723_0.7562276567285842"},"_hasShrinkwrap":false},"8.6.2":{"name":"ajv","version":"8.6.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^8.0.3","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^8.0.1","node-fetch":"^2.6.1","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"a04657014022c9ecb9ae0738b2ac07cb0d76cf3f","_id":"ajv@8.6.2","_nodeVersion":"14.17.3","_npmVersion":"6.14.13","dist":{"integrity":"sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==","shasum":"2fb45e0e5fcbc0813326c1c3da535d1881bb0571","tarball":"http://localhost:4260/ajv/ajv-8.6.2.tgz","fileCount":458,"unpackedSize":997742,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg8JbbCRA9TVsSAnZWagAAdDAQAIjez5ftPLlfAdXrUOWn\nmSBuMmagbRbIJ9GzQEq8lqnE3B2bT7ChnpAsv+V1fQ5CI4nSG2Ov50hW0Scc\n3E6tTBqW8mq7VyaNX9vdgbV7GQaA53dE1a0L3oA8K6nFjr3+CsjIFj4dgWO2\nzAPr1r64FLAghNEV0hAo5m/8agM29+mSTxkVzGrnX7mP6P3RvHFiEzqsCUu/\n10R5Urko5Mr0BaHC2hbkMoa4SzaqGr6Z+duD5Y+3JEDQjbrtmQZ50SouO4vc\nf9Ste+450bH2fJ+yGVrzJFglaOZ/U25CrmJTP2bKLS7E/aHW5liTioLRIwWo\nq8VdZ2qRomfzDCV/s5xMvZ2wjgQxamfnqRxPt60+QzKWNonUrltdDm7wupeH\nHyoSIx4Z2NU9Ldpz/qWN8rh4Zd1anAFTQBOw9GcRL3nUqYcUZNG9diXNjxVR\nVEvD88doQwdkIFXGHYhPVx97ql+deqOgrL+S5stoWtCNMGS3vA2jh3wKPYRu\nmIHTNd20o1c0n1u9EVMkkr69i6yDtGqgRHZg8IT1pQYcVreYwwSjBRD7nQ6R\n/pyG0fbz8B4SZaTVtBm6XGp6bSO4MmsIH8aWwtb6RD8mXymbYOiw+O13NIag\nFtn32Bjwsa5r2ZtfuqeLgktOHQ+uMIZT+N55OdJ0JGBpQwlx/6tZoyY3EJ97\nAQQD\r\n=zw9V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXcqA9FO+MAGIBg/47nXYXVxCIMZnSwpMUu7mEk2u+ewIgW7/ckkv/SBNOMu2v+D6BT5cC627yIKHYiHYM8fRsKWI="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.6.2_1626379995375_0.996525796725164"},"_hasShrinkwrap":false},"8.6.3":{"name":"ajv","version":"8.6.3","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^20.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","@vuepress/shared-utils":"^1.8.2","ajv-formats":"^2.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0","vuepress":"^1.8.2"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"760fd100cd36df29c7fda41a23aad0ed537dfa58","_id":"ajv@8.6.3","_nodeVersion":"14.17.6","_npmVersion":"6.14.15","dist":{"integrity":"sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==","shasum":"11a66527761dc3e9a3845ea775d2d3c0414e8764","tarball":"http://localhost:4260/ajv/ajv-8.6.3.tgz","fileCount":458,"unpackedSize":1005628,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhPkT8CRA9TVsSAnZWagAAZIAP/1318U1NmCG2kzms99Bv\nCjJhsQ2UIe6KdQJRb9l7PA5xgmDvgex8ET0A8KXCKH3XZDjMm0cuXW8qjjDn\n+D8SJ4UfPR6xNvY7vINnR+dqFUgRJAZ53eafO8sWHfNXq+pBa+yPbt6J7Av8\nE2IagMeqJIqA5UrYrnzyCrEsCd0g1lRf/1ct5FLfKS/U41052hU90Pvg9acp\nH0T8sBnCnOwKZboUUTC+dbz7nDUs9ujnsNGg2b1FJbgtsTV40RgWprEvt561\nCXhsJtFgu+DSWWe4BE45G32HUWlynrq/oCPIE4Rxa/EC/wAILdY9m/Ba4UuP\nEF4sQqwhlPtYv3ghgHI9bqP0xa8B+oNUjdd47NrAoexaSNA2U19I4dxHSBDx\nwPmp+YvYj+wizso5fz5e4dIQ/Jn0h8Wq72OOH+eiE7jM1yF85iZph247/KAv\n08mCriWN3pawdvHPCtwCYVFipKrtcLgu72R0GvLtCGfExzMiYDJe38AnNT9K\ndEDfyECfREaJTpDfj4AchrEmbmMKV64tiC2FRgDXlK8yuSIaC1IE8vGvAd/S\nQSGUD0oOSapnU+52HuaTTKROKz0zp1HgR5V3gkAgV54VlAY6oRRR+lCQ9fsZ\nwxL+WPAVfXi0MJjptPLDgAKjP8y43xiWRMMjN80bC2Xwu72nBfhPzpCn4pDP\nNcg9\r\n=htFk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcELRVVCV9F8AQ3pLL+z5KQdB/OcPtV10DDUsH2FTCBQIgRMVDebyEibshAJ+wsP+6DO0LyVPB2YvVKtLsUNrhMy0="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.6.3_1631470844543_0.706804260232037"},"_hasShrinkwrap":false},"8.7.0":{"name":"ajv","version":"8.7.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"da46e38a0d4bc85e1c891dcc3ab526fc28961d18","_id":"ajv@8.7.0","_nodeVersion":"14.18.1","_npmVersion":"6.14.15","dist":{"integrity":"sha512-fX9/Yiy9YwnP/QB/4zqBpTavtL4YuXpiHlXlkE0y2itGcO++ixFIg+NFk1l0TfHjt11EDDhHAhLVe0rFgTBaGA==","shasum":"643a9dd10bcaf6b084162f9d1f551091dd6650aa","tarball":"http://localhost:4260/ajv/ajv-8.7.0.tgz","fileCount":458,"unpackedSize":1006454,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNHi3jqKAt2+zgV5gPIn6jxGkaYBxsaU6orWK9Hqm4HAIhAKTOOfmooV9slwrIRSwPomOgtEEHRecdPEuazNFhgRjA"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.7.0_1636402533987_0.9727572277831318"},"_hasShrinkwrap":false},"8.7.1":{"name":"ajv","version":"8.7.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","bundle":"rm -rf bundle && rollup -c","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"8fccddb4161cfe4d63f2b8987d58f6c10a6bf005","_id":"ajv@8.7.1","_nodeVersion":"14.18.1","_npmVersion":"6.14.15","dist":{"integrity":"sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw==","shasum":"52be6f1736b076074798124293618f132ad07a7e","tarball":"http://localhost:4260/ajv/ajv-8.7.1.tgz","fileCount":458,"unpackedSize":1006454,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIENJFi1pQWtMvB8AbMubpJNBknIPneCZZwtoS+EIEK1oAiEAxQeXwuKJkd7UNkh0i9ibH90ckLqJ6IyXG/EkutU4dfY="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.7.1_1636405951365_0.754909540995621"},"_hasShrinkwrap":false},"8.8.0":{"name":"ajv","version":"8.8.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"62048a170893d51451d10b05eb13587a5a27a562","_id":"ajv@8.8.0","_nodeVersion":"14.18.1","_npmVersion":"6.14.15","dist":{"integrity":"sha512-L+cJ/+pkdICMueKR6wIx3VP2fjIx3yAhuvadUv/osv9yFD7OVZy442xFF+Oeu3ZvmhBGQzoF6mTSt+LUWBmGQg==","shasum":"c501f10df72914bb77a458919e79fc73e4a2f9ef","tarball":"http://localhost:4260/ajv/ajv-8.8.0.tgz","fileCount":462,"unpackedSize":1009069,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGczusX+XAC1cCnow7urv1N/8Vg4jaHzg8zVKFsaVp3TAiEAgTyTAHMSyga24rnMRF3rPKEODMaYm1dBzwVDrX7ZimA="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.8.0_1636828384709_0.035928155380404725"},"_hasShrinkwrap":false},"8.8.1":{"name":"ajv","version":"8.8.1","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"4cc0cad069a42ef110b8ac01be20c887cc876623","_id":"ajv@8.8.1","_nodeVersion":"14.18.1","_npmVersion":"6.14.15","dist":{"integrity":"sha512-6CiMNDrzv0ZR916u2T+iRunnD60uWmNn8SkdB44/6stVORUg0aAkWO7PkOhpCmjmW8f2I/G/xnowD66fxGyQJg==","shasum":"e73dd88eeb4b10bbcd82bee136e6fbe801664d18","tarball":"http://localhost:4260/ajv/ajv-8.8.1.tgz","fileCount":462,"unpackedSize":1009069,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlBJ1CRA9TVsSAnZWagAAxMgP/AnECjaA9T13kBqBSS0R\nJDN/MVF2SHf76Bzhs2rShJz/HeU6NUB83Me072lE89imrmT+l1uUuDB2GGjf\ngjPp9A0vrR1hf4BByK6/ZrsN4idoxJGfErMMGf+gyLbYcGyo+3arHRZbecmh\nkQN+4E9Ub+soPDlxcpvHkzUJRFLybiIIJawBYFf0GavzCicy42fGXGo/j6RU\ni6LeMMhSnmyCdeSIEwCywlxNXVNx85j6uRNeI1ZZq2X3HR8bG5IgMD44nCaM\n1PWHvDvlbEgL2Z4rWtweWiiXwvtyIc16DRlLjQvexAzaruh4xhB6MUDeTZCa\nGie4Gmw/Es1Ec/2DkPCovBXXz/ncAD7vb+8kdmU4l7vCeMCNhi1XneyCpyUc\nedhBsGjkJp4MNjPqCnBaSewpqhkS7DInPWWM37mKDFYk4jbSfDMJeUTpiVU7\nug1y/VWuHNQUV2mDbsM4GJmgxsy/qWvjGy8EkZ2h6JuXTCSEo9upzfeyeJiK\nJ36lBGr+yluHQAsY2L8J8jGoogufEqGx/qobOJpXrnWyg8yBbGbIj2hEdvCK\nFV0Q6cKZWGT1NIo2toriRTmgeL+/vlE1Rbg6QxmZwCVdLiqCFDs3ys2wppzd\nn6w/BB4sd33QACwt6/hPznk2W1wzdpQRZmD5PPP1dukh2rufyaaLC1zaBO67\nS+fD\r\n=Smc7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDuEboHjiHs8QJJiwgK2BKLZPCZTkYowq2iRbw65BqqPAiAD46ZydAdQIjoOsnyTb+NiIDfnAT3yuYHgXXT6ZBWYgA=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.8.1_1637094005157_0.3347696741575781"},"_hasShrinkwrap":false},"8.8.2":{"name":"ajv","version":"8.8.2","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^16.3.2","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^11.0.0","mocha":"^9.0.2","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"b2bf7504bab515db60ad276dc015b9c14f775607","_id":"ajv@8.8.2","_nodeVersion":"14.18.1","_npmVersion":"6.14.15","dist":{"integrity":"sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==","shasum":"01b4fef2007a28bf75f0b7fc009f62679de4abbb","tarball":"http://localhost:4260/ajv/ajv-8.8.2.tgz","fileCount":462,"unpackedSize":1009162,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhmpjiCRA9TVsSAnZWagAAxJcP/R1lntz7NwGw0cWVRUl7\nMTU1lSwCwW7vQo+lq56HzyyboZWr2eOpZUwQtb72FB0ehE4tPb/NF4IWivBq\nNXJmti6++KMMVkpXUJEy79go96O7CuBz7GEAkpo2k91Ce22qvEHeI4iNRgHw\najqdDW7FXMIFfHebkICOTxVdP0ER3r+gMAhS4qSNbhxWFvOVOzQm3TvIB99q\nQh6VYXA9wcSe6BfsjT4wIUogNrRi5dEkN2HrUmAB8UaZsdpapzVOcPgMgU+Q\n1V+4ZFnya0cfSZ1Bkyrzajmh70Q1yG/fka8tMxSYuauihvmPJWbuAfmO2wxn\nT0AbxFSg5R58vJEk6rR7co3DtPphq9AMcC2NWukZJE0XmbRik4/T2B8rWj8s\nt8ULJYsC/rl1hV+VH7OfheKrAPaRYj1gc4IxQBiP5YGX3//9h2HQAVoZzyt3\nBn/BP6v1Q2+rp4W5JYc6UvEjaMi/ZXdhs0o6285HzZ4VXvK+TdmlEwun/q3a\nTr3G17vt/g/EviQOad++poqe9rgBwlzuDRe4TbcqQQueowSRQrmmSaB1CXyb\n45qBlvcpfMNHNSl6lGH/n0rP4U0yjEv3vbf6oK16cgMWEgWrwQeUvuhqwSb+\nYkpc7qzRIvfzFdqjLGi5OqMJ7gC/Ns/4WMJa1JQWeaiFsSWwpTVzUQ86w1H6\nBwcs\r\n=/ftt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICGbLDLh1Sg6J8k4x7+lAXjngPb307Jb8a3fVmy2RWQFAiAJE/DuZzXPfdogOdB6ca0Q3aZqfXZMHHwQ8vwWUpb+4Q=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.8.2_1637521634718_0.0026152001312946815"},"_hasShrinkwrap":false},"8.9.0":{"name":"ajv","version":"8.9.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^17.0.0","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^12.1.1","mocha":"^9.0.2","module-from-string":"^3.1.3","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"979d46b1585a92e4343bf9e4505f61139c3eecf8","_id":"ajv@8.9.0","_nodeVersion":"14.18.3","_npmVersion":"6.14.15","dist":{"integrity":"sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==","shasum":"738019146638824dea25edcf299dcba1b0e7eb18","tarball":"http://localhost:4260/ajv/ajv-8.9.0.tgz","fileCount":462,"unpackedSize":1012740,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh4sWMCRA9TVsSAnZWagAA/CcP/iHvDdkHXiGZLHzWVinB\nZpPtuEY0mq3TtfsK2npviTzJ7R1KUCbg7NZS4eduqaUxZRmbKMDksbWNhHQ4\nRFmiVYUaRnLPvX3FsFMgQ165xm5fnzenXWzoHZyO9m8snZcA80Aqa+aEryEb\n5C2cWbHE5sCylrptDDu1m4uJoo8xJZnQ05n3UqqnUt9T0YWMrzdREQGOjqhU\nZURHlguTKamVbHd25APWJZNc4J6EL/ejqJc1pbwM7KHxeBYmrn3DPhtXR5x8\n3SWqVx57lCNiMVGJqYfaNryer+5e4cybfxb+EE2Rx0XNuSZ40DarFDXQGsRD\nMTHqLXB6OIeYNtOaaN+B7muccmGsg1fFu9Yb6OPPSIXornh4fSbG0WFjjwmp\n0zIT+dhO+P3mwJ0nn6xHebXVIn4FlZ1gv68fQg7d3cb8XB3spYK0ASLrEEoY\n/8E9XecsCFlLWGjfrEi+0iuM31me2+efSnfizylJkpaHXX4LsLCwfAPWXRnf\n/JZ3h1BuEUmbqP8guHTgyC4hlgpzUSj636Aguvy5e75mY6UyKm674Cu8YQdO\nOCCddmE12ezY41BtAX5vsn4IMvHUvWleUk8EL4wG6ydRwKV9qMQES3nEbLZQ\nmfLelhmj9InZvQi0x4zBUoTrMIgFBFOruWb4g8sYf2y17E/c81Haa37nHfD0\naXs8\r\n=ZiQ8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC2j0sp3f0aJHDXI55OkG41nMQlp6RuD/j0EPsjPfKQWwIhAKMUEyb7iLxqNtwugL+iYhW9zzgohj2s+7sxHKbXdqs4"}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.9.0_1642251660058_0.9221599369011317"},"_hasShrinkwrap":false},"8.10.0":{"name":"ajv","version":"8.10.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^17.0.0","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","fast-uri":"^1.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^12.1.1","mocha":"^9.0.2","module-from-string":"^3.1.3","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"a27f78264ab1c3951d5131f27181d0a50e54aed0","_id":"ajv@8.10.0","_nodeVersion":"14.18.3","_npmVersion":"6.14.15","dist":{"integrity":"sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==","shasum":"e573f719bd3af069017e3b66538ab968d040e54d","tarball":"http://localhost:4260/ajv/ajv-8.10.0.tgz","fileCount":466,"unpackedSize":1016629,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh/W7iCRA9TVsSAnZWagAAaLUP/1hksgauRb5lI5wLT16b\nyaTP4MwaNuUzUyp5IPmMLPD7gecxDy+AMHLSw3Q98qbZqVu72l8voPQxjTn8\nTUpWO/Mj6R2DcwDHPZfKqM1ZZ1Z4dB1HgF3QQfS/0NXMZj7JZLv64hLsO+Aj\nEiR3rHqvWvxmzP2fUDDKQiDLBQ8Jpkt3wuj4sHno9aFMIO61I7FwGMNmzJQN\nNEp4l5lTkDV4roSBDLswpXOM8STdaFSmbKAfKcrz65S8yYWmpjcYjCHPVYa6\nLnRfsQ1N7UZLTZVgvMut16w6fqKp9kA7beHIJ1S863PGSLtVbkmNgCEcUyF5\nBk0urjDkORs1BoS+NgpYcByyhUsfBaJMcVS2viIsKmcaMKRv46rnBJge0QEx\nF8H85JyoeBcj6MC874e19CWAgCBroivQ/LOuLxCkrYl6SLnosDl8WzKq3EQ+\nbsuTSA8rp2W6e/jEpfWZR/CBV3g+GfrdISwqAx9bQwr1U2ZZUwoCyI1KYIuT\nX4t6WaPbwAk+/PRyH6moaupfktpuUZm9ZyHl6ZIkXFmHxgdPAJa4HXW0d6v2\nvY0eI5a9gB3I5/Juz147V8IMMS+ExsMQ8OdBCIiwm34ri5hp7lEArTktisHV\n7QyadS+0VuY7ZJghBXHxTIeQgZ5wwXmLbe6e8NNCRz+4aRbrLo5HsSUISzyM\nKL1z\r\n=HLGP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHHNWCWcdd1ReXhYOCyYylkQD2Bzd0a5N/2mD20RyHnvAiBBvuozay7qa3D7seQyAKyGetQUPqiAfZnx6dmlE4mA4g=="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.10.0_1643998946582_0.10137826404974248"},"_hasShrinkwrap":false},"8.11.0":{"name":"ajv","version":"8.11.0","description":"Another JSON Schema Validator","main":"dist/ajv.js","types":"dist/ajv.d.ts","scripts":{"eslint":"eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite","prettier:write":"prettier --write \"./**/*.{json,yaml,js,ts}\"","prettier:check":"prettier --list-different \"./**/*.{json,yaml,js,ts}\"","test-spec":"cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot","test-codegen":"nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec","test-debug":"npm run test-spec -- --inspect-brk","test-cov":"nyc npm run test-spec","rollup":"rm -rf bundle && rollup -c","bundle":"rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD","build":"rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts","json-tests":"rm -rf spec/_json/*.js && node scripts/jsontests","test-karma":"karma start","test-browser":"rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start","test-all":"npm run test-cov && if-node-version 12 npm run test-browser","test":"npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov","test-ci":"AJV_FULL_TEST=true npm test","prepublish":"npm run build","benchmark":"npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd","docs:dev":"./scripts/prepare-site && vuepress dev docs","docs:build":"./scripts/prepare-site && vuepress build docs"},"nyc":{"exclude":["**/spec/**","node_modules"],"reporter":["lcov","text-summary"]},"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"author":{"name":"Evgeny Poberezkin"},"license":"MIT","bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"homepage":"https://ajv.js.org","runkitExampleFilename":".runkit_example.js","dependencies":{"fast-deep-equal":"^3.1.1","json-schema-traverse":"^1.0.0","require-from-string":"^2.0.2","uri-js":"^4.2.2"},"devDependencies":{"@ajv-validator/config":"^0.3.0","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.0","@rollup/plugin-typescript":"^8.2.1","@types/chai":"^4.2.12","@types/mocha":"^9.0.0","@types/node":"^17.0.0","@types/require-from-string":"^1.2.0","@typescript-eslint/eslint-plugin":"^3.8.0","@typescript-eslint/parser":"^3.8.0","ajv-formats":"^3.0.0-rc.0","browserify":"^17.0.0","chai":"^4.0.1","cross-env":"^7.0.2","dayjs":"^1.10.4","dayjs-plugin-utc":"^0.1.2","eslint":"^7.8.1","eslint-config-prettier":"^7.0.0","fast-uri":"^1.0.0","glob":"^7.0.0","husky":"^7.0.1","if-node-version":"^1.0.0","jimp":"^0.16.1","js-beautify":"^1.7.3","json-schema-test":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-mocha":"^2.0.0","lint-staged":"^12.1.1","mocha":"^9.0.2","module-from-string":"^3.1.3","node-fetch":"^3.0.0","nyc":"^15.0.0","prettier":"^2.3.1","re2":"^1.16.0","rollup":"^2.44.0","rollup-plugin-terser":"^7.0.2","ts-node":"^10.0.0","tsify":"^5.0.2","typescript":"^4.2.0"},"collective":{"type":"opencollective","url":"https://opencollective.com/ajv"},"funding":{"type":"github","url":"https://github.com/sponsors/epoberezkin"},"prettier":"@ajv-validator/config/prettierrc.json","husky":{"hooks":{"pre-commit":"lint-staged && npm test"}},"lint-staged":{"*.{json,yaml,js,ts}":"prettier --write"},"gitHead":"c067d6d9c3285054ea4c0a2d2adbbc8b5d631935","_id":"ajv@8.11.0","_nodeVersion":"14.19.0","_npmVersion":"6.14.16","dist":{"integrity":"sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==","shasum":"977e91dd96ca669f54a11e23e378e33b884a565f","tarball":"http://localhost:4260/ajv/ajv-8.11.0.tgz","fileCount":466,"unpackedSize":1016907,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiOktjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoJaxAAlaVvTQ2Odj3CLA5v+enMW0jEAGeGlyYxD0Ts+DiQAB4WfJNX\r\nVe0RbcTH/zgnFoDlDEOfcx1/1fEDGn92EfMNH4B+ltJE5qyOPaAVYZeE4+A3\r\nl7P3z01LhKtp911KBXT4DaZ1VXAwvr9rc5tubleEy5iv51Pr9Y2ytB8jNXtC\r\nUpTlwJbKlgP8xvyBs/rZLG7igxdWsA1UWSWU3o90eKBB1Bg6fL8is8ZPMabR\r\nPSINIR4L7T2dSSUlsdzs7RijmZQbu9rzc/Wzz+JR9rc7eufoMUkj0nXkMg84\r\nFP7A3zVGuRZyw0/2dOL3yqMn58DHQaVayFiHQhPDWfG2OJwpTIvDKAuMP2kE\r\nIT3215DU3aUdQvPLNCsSz2B1LnjVPJKOIwAOCRCx5AG+S6jQf2cZWs4QHBzH\r\n6LczlMxWyktXuZvW7a5EvuQGPfaWXGC/uhzXoFUQdukvyez6kR8Ud5tm2yDZ\r\n1KVRxuvq9y+7ZrtHgn4EquzXanJRny6glk5qwlNcxVY5mKPWnxoFgX2W5f4+\r\navGLINZXtGr9prKOyobeQ0kmRP6BPs7QG2NR8eCGrZXVNDD5PU0qM8qPpCoq\r\nnns6qwr7wk3reYcMXewd7ZDP1FaXED/VOmZFCLkK5DlWO12BHCcddpOfZiS5\r\n+l0dQlmSC3TBRvuzsAv2BzTSw19SeHFebto=\r\n=GDNg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBvHJRPXJkPRNoscrSJ8kMjkbE/LlkpAlxhMcZma8ljPAiEAoT5UriPgOHdP72VlfTAzIq6qQyMFATTzsNuwOhTbU1U="}]},"_npmUser":{"name":"esp","email":"e.poberezkin@me.com"},"directories":{},"maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ajv_8.11.0_1647987555563_0.09423244421860977"},"_hasShrinkwrap":false}},"readme":"\"Ajv\n\n \n\n# Ajv JSON schema validator\n\nThe fastest JSON validator for Node.js and browser.\n\nSupports JSON Schema draft-04/06/07/2019-09/2020-12 ([draft-04 support](https://ajv.js.org/json-schema.html#draft-04) requires ajv-draft-04 package) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).\n\n[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)\n[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)\n[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)\n[![SimpleX](https://img.shields.io/badge/chat-on%20SimpleX-%2307b4b9)](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2Fap4lMFzfXF8Hzmh-Vz0WNxp_1jKiOa-h%23MCowBQYDK2VuAyEAcdefddRvDfI8iAuBpztm_J3qFucj8MDZoVs_2EcMTzU%3D)\n[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)\n[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)\n\n## Ajv sponsors\n\n[\"Mozilla\"](https://www.mozilla.org)[](https://opencollective.com/ajv)\n\n[\"Microsoft\"](https://opensource.microsoft.com)[](https://opencollective.com/ajv)[](https://opencollective.com/ajv)\n\n[\"Retool\"](https://retool.com/?utm_source=sponsor&utm_campaign=ajv)[\"Tidelift\"](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=enterprise)[\"SimpleX\"](https://github.com/simplex-chat/simplex-chat)[](https://opencollective.com/ajv)\n\n## Contributing\n\nMore than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.\n\nPlease review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](https://ajv.js.org/components.html).\n\n## Documentation\n\nAll documentation is available on the [Ajv website](https://ajv.js.org).\n\nSome useful site links:\n- [Getting started](https://ajv.js.org/guide/getting-started.html)\n- [JSON Schema vs JSON Type Definition](https://ajv.js.org/guide/schema-language.html)\n- [API reference](https://ajv.js.org/api.html)\n- [Strict mode](https://ajv.js.org/strict-mode.html)\n- [Standalone validation code](https://ajv.js.org/standalone.html)\n- [Security considerations](https://ajv.js.org/security.html)\n- [Command line interface](https://ajv.js.org/packages/ajv-cli.html)\n- [Frequently Asked Questions](https://ajv.js.org/faq.html)\n\n## Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)\n\nSince I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!\n\nYour continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.\n\nPlease sponsor Ajv via:\n\n- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)\n- [Ajv Open Collective️](https://opencollective.com/ajv)\n\nThank you.\n\n#### Open Collective sponsors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Performance\n\nAjv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.\n\nCurrently Ajv is the fastest and the most standard compliant validator according to these benchmarks:\n\n- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place\n- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster\n- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n\nPerformance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):\n\n[![performance](https://chart.googleapis.com/chart?chxt=x,y&cht=bhs&chco=76A4FB&chls=2.0&chbh=62,4,1&chs=600x416&chxl=-1:|ajv|@exodus/schemasafe|is-my-json-valid|djv|@cfworker/json-schema|jsonschema&chd=t:100,69.2,51.5,13.1,5.1,1.2)](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)\n\n## Features\n\n- Ajv implements JSON Schema [draft-06/07/2019-09/2020-12](http://json-schema.org/) standards (draft-04 is supported in v6):\n - all validation keywords (see [JSON Schema validation keywords](https://ajv.js.org/json-schema.html))\n - [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) extensions:\n - NEW: keyword [discriminator](https://ajv.js.org/json-schema.html#discriminator).\n - keyword [nullable](https://ajv.js.org/json-schema.html#nullable).\n - full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)\n - support of recursive references between schemas\n - correct string lengths for strings with unicode pairs\n - JSON Schema [formats](https://ajv.js.org/guide/formats.html) (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin).\n - [validates schemas against meta-schema](https://ajv.js.org/api.html#api-validateschema)\n- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):\n - all keywords (see [JSON Type Definition schema forms](https://ajv.js.org/json-type-definition.html))\n - meta-schema for JTD schemas\n - \"union\" keyword and user-defined keywords (can be used inside \"metadata\" member of the schema)\n- supports [browsers](https://ajv.js.org/guide/environments.html#browsers) and Node.js 10.x - current\n- [asynchronous loading](https://ajv.js.org/guide/managing-schemas.html#asynchronous-schema-loading) of referenced schemas during compilation\n- \"All errors\" validation mode with [option allErrors](https://ajv.js.org/options.html#allerrors)\n- [error messages with parameters](https://ajv.js.org/api.html#validation-errors) describing error reasons to allow error message generation\n- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package\n- [removing-additional-properties](https://ajv.js.org/guide/modifying-data.html#removing-additional-properties)\n- [assigning defaults](https://ajv.js.org/guide/modifying-data.html#assigning-defaults) to missing properties and items\n- [coercing data](https://ajv.js.org/guide/modifying-data.html#coercing-data-types) to the types specified in `type` keywords\n- [user-defined keywords](https://ajv.js.org/guide/user-keywords.html)\n- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package\n- [\\$data reference](https://ajv.js.org/guide/combining-schemas.html#data-reference) to use values from the validated data as values for the schema keywords\n- [asynchronous validation](https://ajv.js.org/guide/async-validation.html) of user-defined formats and keywords\n\n## Install\n\nTo install version 8:\n\n```\nnpm install ajv\n```\n\n## Getting started\n\nTry it in the Node.js REPL: https://runkit.com/npm/ajv\n\nIn JavaScript:\n\n```javascript\n// or ESM/TypeScript import\nimport Ajv from \"ajv\"\n// Node.js require:\nconst Ajv = require(\"ajv\")\n\nconst ajv = new Ajv() // options can be passed, e.g. {allErrors: true}\n\nconst schema = {\n type: \"object\",\n properties: {\n foo: {type: \"integer\"},\n bar: {type: \"string\"}\n },\n required: [\"foo\"],\n additionalProperties: false,\n}\n\nconst data = {\n foo: 1,\n bar: \"abc\"\n}\n\nconst validate = ajv.compile(schema)\nconst valid = validate(data)\nif (!valid) console.log(validate.errors)\n```\n\nLearn how to use Ajv and see more examples in the [Guide: getting started](https://ajv.js.org/guide/getting-started.html)\n\n## Changes history\n\nSee [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)\n\n**Please note**: [Changes in version 8.0.0](https://github.com/ajv-validator/ajv/releases/tag/v8.0.0)\n\n[Version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)\n\n[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).\n\n## Code of conduct\n\nPlease review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).\n\nPlease report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.\n\n## Security contact\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.\n\n## Open-source software support\n\nAjv is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.\n\n## License\n\n[MIT](./LICENSE)\n","maintainers":[{"name":"blakeembrey","email":"hello@blakeembrey.com"},{"name":"esp","email":"e.poberezkin@me.com"}],"time":{"modified":"2022-06-13T02:34:02.048Z","created":"2015-05-29T22:33:14.989Z","0.0.4":"2015-05-29T22:33:14.989Z","0.0.5":"2015-05-29T22:54:15.469Z","0.0.6":"2015-05-29T23:29:05.805Z","0.0.7":"2015-05-29T23:30:34.265Z","0.0.8":"2015-05-30T08:54:32.262Z","0.0.9":"2015-05-30T08:59:50.749Z","0.0.10":"2015-05-30T10:50:33.733Z","0.0.11":"2015-05-30T18:11:21.515Z","0.0.12":"2015-05-30T20:10:46.548Z","0.1.0":"2015-05-30T22:05:16.542Z","0.1.1":"2015-05-30T23:42:28.944Z","0.1.2":"2015-05-31T00:11:45.840Z","0.1.3":"2015-05-31T01:01:44.939Z","0.1.4":"2015-05-31T09:47:27.976Z","0.1.5":"2015-05-31T11:21:59.955Z","0.1.6":"2015-05-31T17:40:16.586Z","0.1.7":"2015-05-31T20:46:42.129Z","0.1.8":"2015-06-01T01:00:08.605Z","0.1.9":"2015-06-01T17:51:44.247Z","0.1.10":"2015-06-01T22:44:00.710Z","0.1.11":"2015-06-01T23:14:54.510Z","0.1.12":"2015-06-02T00:59:48.826Z","0.1.13":"2015-06-03T21:30:56.159Z","0.1.14":"2015-06-03T23:17:48.218Z","0.1.15":"2015-06-03T23:31:39.001Z","0.1.16":"2015-06-04T17:04:24.567Z","0.2.0":"2015-06-04T20:43:29.201Z","0.2.1":"2015-06-04T22:09:18.191Z","0.2.2":"2015-06-04T23:44:18.866Z","0.2.3":"2015-06-05T18:08:24.214Z","0.2.4":"2015-06-05T20:38:32.546Z","0.2.5":"2015-06-06T01:08:01.193Z","0.2.6":"2015-06-06T01:40:29.318Z","0.2.7":"2015-06-06T13:13:46.327Z","0.2.8":"2015-06-06T15:19:02.504Z","0.2.9":"2015-06-06T18:44:25.222Z","0.3.0":"2015-06-07T20:55:50.274Z","0.3.1":"2015-06-07T20:59:08.400Z","0.3.2":"2015-06-07T23:20:03.433Z","0.3.3":"2015-06-07T23:32:14.776Z","0.3.4":"2015-06-08T06:45:46.961Z","0.3.5":"2015-06-08T07:02:12.159Z","0.3.6":"2015-06-10T20:51:30.704Z","0.3.7":"2015-06-10T22:59:02.241Z","0.3.8":"2015-06-12T10:43:55.629Z","0.3.10":"2015-06-12T21:12:53.124Z","0.3.11":"2015-06-12T22:31:05.529Z","0.3.12":"2015-06-13T09:27:35.123Z","0.4.0":"2015-06-13T12:01:18.880Z","0.4.1":"2015-06-13T12:55:34.208Z","0.4.2":"2015-06-13T15:35:37.382Z","0.4.3":"2015-06-13T22:42:06.936Z","0.4.4":"2015-06-14T08:04:37.959Z","0.4.5":"2015-06-14T09:06:02.012Z","0.4.6":"2015-06-15T07:03:31.736Z","0.4.7":"2015-06-15T10:14:59.183Z","0.4.8":"2015-06-15T15:31:02.604Z","0.4.9":"2015-06-15T23:21:32.851Z","0.4.10":"2015-06-16T14:10:55.936Z","0.4.12":"2015-06-16T17:16:40.649Z","0.4.14":"2015-06-16T21:20:19.365Z","0.4.15":"2015-06-16T21:54:34.049Z","0.5.0":"2015-06-17T01:06:16.112Z","0.5.2":"2015-06-17T15:01:45.873Z","0.5.3":"2015-06-17T21:06:22.558Z","0.5.4":"2015-06-17T21:24:10.021Z","0.5.5":"2015-06-18T19:50:11.731Z","0.5.6":"2015-06-19T00:00:10.090Z","0.5.7":"2015-06-19T10:40:04.993Z","0.5.8":"2015-06-20T14:37:41.033Z","0.5.9":"2015-06-20T17:42:13.103Z","0.5.10":"2015-06-22T13:40:40.647Z","0.5.11":"2015-06-23T16:27:20.498Z","0.5.12":"2015-06-23T23:44:08.346Z","0.6.0":"2015-06-24T00:28:55.952Z","0.6.1":"2015-06-30T23:31:42.236Z","0.6.2":"2015-07-20T16:41:46.983Z","0.6.3":"2015-07-21T18:18:18.689Z","0.6.4":"2015-07-21T21:36:48.393Z","0.6.5":"2015-07-21T22:09:03.819Z","0.6.6":"2015-07-21T22:20:20.261Z","0.6.7":"2015-07-22T15:33:12.876Z","0.6.8":"2015-07-24T09:48:18.819Z","0.6.9":"2015-07-26T10:01:24.946Z","0.6.10":"2015-07-30T08:22:29.151Z","0.6.11":"2015-07-31T18:52:46.577Z","0.6.12":"2015-08-06T23:14:50.168Z","0.6.13":"2015-08-07T00:55:20.873Z","0.6.14":"2015-08-08T09:58:13.385Z","0.6.15":"2015-08-08T18:26:38.859Z","0.7.0":"2015-08-09T11:51:14.897Z","0.7.1":"2015-08-11T07:28:24.043Z","0.7.2":"2015-08-16T01:13:01.895Z","1.0.0":"2015-08-17T17:23:01.027Z","1.0.1":"2015-08-21T22:43:52.986Z","1.1.0":"2015-08-22T21:25:09.847Z","1.1.1":"2015-08-23T10:45:49.244Z","1.2.0":"2015-08-23T20:37:30.227Z","1.2.1":"2015-08-23T23:54:29.847Z","1.3.0":"2015-09-02T23:10:00.756Z","1.3.1":"2015-09-02T23:31:49.579Z","1.3.2":"2015-09-07T09:13:20.058Z","1.4.0":"2015-09-13T00:06:34.662Z","1.4.1":"2015-09-22T22:24:24.453Z","1.4.2":"2015-09-23T22:48:36.121Z","1.4.3":"2015-10-02T21:23:28.533Z","1.4.4":"2015-10-10T23:17:39.822Z","1.4.5":"2015-10-15T17:58:38.934Z","1.4.6":"2015-10-25T00:23:18.801Z","1.4.7":"2015-10-25T11:45:09.212Z","1.4.8":"2015-10-25T22:12:13.067Z","1.4.9":"2015-11-07T14:09:25.378Z","2.0.0-beta.0":"2015-11-13T14:35:35.798Z","2.0.0-beta.1":"2015-11-14T23:14:14.681Z","1.4.10":"2015-11-17T20:40:23.302Z","2.0.0-beta.2":"2015-11-17T23:10:49.902Z","2.0.0-beta.3":"2015-11-17T23:24:59.628Z","2.0.0":"2015-11-22T01:28:10.264Z","2.0.1":"2015-11-22T02:17:31.906Z","2.0.2":"2015-11-24T06:44:47.137Z","2.0.3":"2015-11-26T22:57:04.293Z","2.0.4":"2015-11-27T09:27:00.421Z","2.1.0":"2015-11-28T15:12:08.655Z","2.1.2":"2015-11-28T22:40:06.539Z","2.1.3":"2015-11-29T01:45:30.526Z","2.1.4":"2015-12-04T22:22:09.562Z","2.2.0":"2015-12-05T21:28:23.007Z","2.2.1":"2015-12-06T22:10:50.214Z","2.2.2":"2015-12-07T22:08:53.825Z","2.3.0":"2015-12-11T21:44:43.025Z","2.4.0":"2015-12-12T21:58:19.063Z","2.5.0":"2015-12-19T19:01:14.847Z","3.0.0":"2015-12-27T21:47:12.752Z","3.0.1":"2015-12-27T22:11:06.728Z","3.0.2":"2015-12-27T22:13:29.171Z","3.0.3":"2015-12-28T12:21:21.359Z","3.0.4":"2015-12-30T23:06:17.096Z","3.1.0":"2016-01-02T17:19:51.060Z","3.1.1":"2016-01-04T22:27:56.450Z","3.2.0":"2016-01-09T14:51:08.862Z","3.2.1":"2016-01-13T22:19:38.405Z","3.2.2":"2016-01-13T22:26:48.139Z","3.2.3":"2016-01-14T21:46:25.144Z","3.3.0":"2016-01-15T07:00:54.899Z","3.3.1":"2016-01-16T16:15:30.383Z","3.4.0":"2016-01-17T15:19:50.504Z","3.5.0":"2016-02-01T18:16:33.904Z","3.5.1":"2016-02-01T23:39:43.968Z","3.5.2":"2016-02-04T20:03:03.564Z","3.5.3":"2016-02-05T09:21:42.084Z","3.6.0":"2016-02-13T21:17:18.753Z","3.6.1":"2016-02-13T22:13:57.672Z","3.6.2":"2016-02-14T20:43:21.889Z","3.7.0":"2016-02-17T23:04:53.239Z","3.7.1":"2016-02-21T13:29:50.917Z","3.7.2":"2016-02-24T09:27:10.734Z","3.8.0":"2016-02-28T23:08:33.753Z","3.8.1":"2016-03-01T00:27:50.883Z","3.8.2":"2016-03-02T15:01:22.570Z","3.8.3":"2016-03-07T06:57:28.152Z","3.8.4":"2016-03-09T23:23:28.025Z","3.8.5":"2016-03-14T21:19:51.543Z","3.8.6":"2016-03-20T19:33:30.110Z","3.8.7":"2016-03-25T20:35:00.360Z","3.8.8":"2016-03-31T17:36:07.915Z","3.8.9":"2016-04-10T10:54:31.603Z","3.8.10":"2016-04-11T19:49:16.279Z","4.0.0":"2016-04-15T23:01:04.906Z","4.0.1":"2016-04-18T20:21:24.078Z","4.0.2":"2016-04-20T20:22:32.876Z","4.0.3":"2016-04-22T09:23:04.646Z","4.0.4":"2016-04-23T18:56:49.440Z","4.0.5":"2016-05-03T09:00:45.531Z","4.0.6":"2016-05-22T01:12:00.499Z","4.1.0":"2016-05-27T20:31:38.085Z","4.1.1":"2016-06-01T06:18:57.294Z","4.1.2":"2016-06-04T20:43:09.189Z","4.1.3":"2016-06-11T11:08:59.437Z","4.1.4":"2016-06-26T20:33:49.387Z","4.1.5":"2016-06-28T20:47:11.092Z","4.1.6":"2016-07-09T23:39:32.781Z","4.1.7":"2016-07-10T17:52:32.033Z","4.1.8":"2016-07-21T23:49:03.464Z","4.2.0":"2016-07-22T14:52:00.767Z","4.3.0":"2016-07-28T22:48:31.588Z","4.3.1":"2016-08-05T19:34:02.584Z","4.4.0":"2016-08-07T12:11:05.957Z","4.4.1":"2016-08-14T23:35:26.915Z","4.5.0":"2016-08-15T21:21:02.481Z","4.6.0":"2016-08-29T22:31:04.206Z","4.6.1":"2016-08-30T20:00:28.158Z","4.7.0":"2016-09-06T21:55:39.383Z","4.7.1":"2016-09-19T16:31:33.378Z","4.7.2":"2016-09-19T19:35:02.212Z","4.7.3":"2016-09-22T16:59:01.285Z","4.7.4":"2016-09-24T18:00:25.813Z","4.7.5":"2016-09-28T14:21:24.557Z","4.7.6":"2016-10-02T17:36:02.092Z","4.7.7":"2016-10-05T18:46:26.819Z","4.8.0":"2016-10-16T16:42:18.731Z","4.8.1":"2016-10-19T08:39:47.744Z","4.8.2":"2016-10-19T23:42:26.698Z","5.0.0-beta.0":"2016-11-08T19:29:00.351Z","4.9.0":"2016-11-14T21:01:11.669Z","5.0.0-beta.1":"2016-11-30T21:21:38.421Z","4.9.1":"2016-12-03T21:51:46.263Z","4.9.2":"2016-12-06T21:47:20.301Z","4.9.3":"2016-12-10T22:33:35.659Z","4.10.0":"2016-12-11T12:52:50.689Z","4.10.1":"2016-12-23T17:45:51.517Z","4.10.2":"2016-12-24T02:33:31.471Z","4.10.3":"2016-12-25T00:17:28.071Z","5.0.1-beta.0":"2016-12-31T00:39:48.657Z","4.10.4":"2017-01-05T20:03:54.651Z","5.0.1-beta.1":"2017-01-20T23:50:49.769Z","4.11.0":"2017-01-21T00:17:03.538Z","4.11.1":"2017-01-21T00:32:49.653Z","4.11.2":"2017-01-21T21:45:30.184Z","5.0.1-beta.2":"2017-01-23T21:04:55.936Z","5.0.1-beta.3":"2017-02-04T23:03:04.383Z","4.11.3":"2017-02-12T19:18:31.652Z","5.0.2-beta.0":"2017-02-12T19:39:58.543Z","5.0.3-beta.0":"2017-03-01T08:16:12.271Z","4.11.4":"2017-03-04T18:34:14.362Z","4.11.5":"2017-03-11T21:44:40.803Z","5.0.4-beta.0":"2017-03-12T18:46:07.515Z","5.0.4-beta.1":"2017-03-19T19:57:27.319Z","5.0.4-beta.2":"2017-03-25T16:33:52.791Z","4.11.6":"2017-04-07T22:56:39.286Z","5.0.4-beta.3":"2017-04-08T20:11:49.373Z","4.11.7":"2017-04-17T13:30:20.293Z","5.0.0":"2017-04-17T14:42:02.925Z","4.11.8":"2017-04-28T19:23:19.500Z","5.0.1":"2017-04-28T20:22:58.769Z","5.1.0":"2017-05-14T11:17:43.732Z","5.1.1":"2017-05-14T22:50:06.073Z","5.1.2":"2017-05-19T19:53:53.922Z","5.1.3":"2017-05-20T21:35:14.447Z","5.1.4":"2017-05-25T21:17:53.558Z","5.1.5":"2017-05-28T19:59:05.385Z","5.1.6":"2017-06-15T22:37:03.209Z","5.2.0":"2017-06-16T23:13:12.823Z","5.2.1":"2017-07-06T23:29:07.429Z","5.2.2":"2017-07-10T22:19:43.806Z","5.2.3":"2017-09-25T20:57:08.615Z","5.2.4":"2017-10-22T15:16:21.145Z","5.2.5":"2017-10-24T10:32:11.174Z","5.3.0":"2017-10-24T19:00:24.392Z","6.0.0-beta.0":"2017-11-06T07:43:01.783Z","6.0.0-beta.1":"2017-11-06T10:18:18.756Z","6.0.0-beta.2":"2017-11-12T10:13:30.663Z","5.4.0":"2017-11-20T21:23:25.571Z","5.5.0":"2017-11-24T20:45:49.264Z","6.0.0-rc.0":"2017-11-26T10:49:05.261Z","5.5.1":"2017-12-02T12:48:13.998Z","6.0.0-rc.1":"2017-12-03T17:59:06.388Z","5.5.2":"2017-12-16T20:35:18.715Z","6.0.0":"2018-01-07T15:32:13.671Z","6.0.1":"2018-01-11T22:04:19.983Z","6.1.0":"2018-01-26T19:08:17.617Z","6.1.1":"2018-01-30T19:43:41.417Z","6.2.0":"2018-02-26T08:23:58.517Z","6.2.1":"2018-03-03T21:22:14.792Z","6.3.0":"2018-03-17T19:53:05.496Z","6.4.0":"2018-03-25T10:37:19.849Z","6.5.0":"2018-05-08T20:49:29.979Z","6.5.1":"2018-06-10T12:07:59.343Z","6.5.2":"2018-06-30T18:57:47.002Z","6.5.3":"2018-08-17T16:28:53.005Z","6.5.4":"2018-09-23T11:04:08.808Z","6.5.5":"2018-11-04T21:47:17.207Z","6.6.0":"2018-11-29T07:22:47.772Z","6.6.1":"2018-11-29T10:59:52.022Z","6.6.2":"2018-12-16T21:10:59.894Z","6.7.0":"2019-01-13T17:59:39.547Z","6.8.0":"2019-02-02T20:04:07.359Z","6.8.1":"2019-02-02T20:07:09.047Z","6.9.0":"2019-02-09T22:22:22.323Z","6.9.1":"2019-02-10T08:42:28.330Z","6.9.2":"2019-02-22T20:16:31.617Z","6.10.0":"2019-03-03T11:27:56.582Z","6.10.1":"2019-07-06T18:15:06.046Z","6.10.2":"2019-07-14T14:16:08.400Z","6.11.0":"2020-01-18T09:11:13.146Z","6.12.0":"2020-02-22T13:51:48.960Z","6.12.1":"2020-04-18T19:38:30.061Z","6.12.2":"2020-04-19T23:18:22.163Z","6.12.3":"2020-07-04T16:02:12.780Z","6.12.4":"2020-08-15T09:07:56.590Z","6.12.5":"2020-09-13T16:23:15.885Z","7.0.0-alpha.0":"2020-09-15T14:58:25.284Z","7.0.0-alpha.1":"2020-09-16T13:40:23.006Z","7.0.0-beta.0":"2020-09-23T19:16:55.961Z","6.12.6":"2020-10-10T17:01:40.565Z","7.0.0-beta.1":"2020-10-10T18:14:42.993Z","7.0.0-beta.2":"2020-10-24T18:14:26.881Z","7.0.0-beta.3":"2020-11-05T08:18:22.163Z","7.0.0-beta.4":"2020-11-10T08:25:15.116Z","7.0.0-beta.5":"2020-11-15T16:52:15.815Z","7.0.0-beta.6":"2020-11-16T22:01:23.953Z","7.0.0-beta.7":"2020-11-22T11:37:54.151Z","7.0.0-beta.8":"2020-11-29T19:31:05.769Z","7.0.0-beta.9":"2020-12-02T08:18:25.409Z","7.0.0-rc.0":"2020-12-06T15:39:09.732Z","7.0.0-rc.1":"2020-12-09T20:49:34.360Z","7.0.0-rc.2":"2020-12-13T19:37:08.296Z","7.0.0-rc.3":"2020-12-14T19:11:11.603Z","7.0.0-rc.4":"2020-12-14T19:34:46.338Z","7.0.0-rc.5":"2020-12-14T20:08:45.313Z","7.0.0":"2020-12-15T19:12:40.866Z","7.0.1":"2020-12-16T19:42:08.498Z","7.0.2":"2020-12-19T18:42:18.067Z","7.0.3":"2021-01-02T11:09:13.331Z","7.0.4":"2021-02-01T21:04:46.913Z","7.1.0":"2021-02-11T08:42:08.664Z","7.1.1":"2021-02-17T09:09:58.171Z","7.2.0":"2021-03-07T10:00:58.343Z","7.2.1":"2021-03-07T19:03:07.134Z","8.0.0-beta.0":"2021-03-13T11:08:25.177Z","8.0.0-beta.1":"2021-03-15T07:56:51.410Z","8.0.0-beta.2":"2021-03-16T20:22:37.476Z","7.2.2":"2021-03-20T06:43:24.383Z","7.2.3":"2021-03-20T07:01:17.846Z","8.0.0-beta.3":"2021-03-21T18:44:36.581Z","8.0.0-beta.4":"2021-03-23T07:37:04.918Z","7.2.4":"2021-03-26T08:19:33.357Z","8.0.0":"2021-03-27T12:44:09.150Z","8.0.1":"2021-03-27T22:47:40.962Z","8.0.2":"2021-03-31T08:00:17.645Z","8.0.3":"2021-04-01T07:04:36.577Z","8.0.4":"2021-04-02T12:53:50.841Z","8.0.5":"2021-04-02T15:54:03.688Z","8.1.0":"2021-04-11T16:52:16.351Z","8.2.0":"2021-04-27T15:08:54.921Z","8.3.0":"2021-05-09T11:34:27.503Z","8.4.0":"2021-05-14T20:12:08.622Z","8.5.0":"2021-05-20T13:33:43.755Z","8.6.0":"2021-06-06T14:57:32.555Z","8.6.1":"2021-07-04T09:53:17.921Z","8.6.2":"2021-07-15T20:13:15.677Z","8.6.3":"2021-09-12T18:20:44.787Z","8.7.0":"2021-11-08T20:15:34.210Z","8.7.1":"2021-11-08T21:12:31.739Z","8.8.0":"2021-11-13T18:33:04.967Z","8.8.1":"2021-11-16T20:20:05.393Z","8.8.2":"2021-11-21T19:07:14.945Z","8.9.0":"2022-01-15T13:01:00.296Z","8.10.0":"2022-02-04T18:22:26.875Z","8.11.0":"2022-03-22T22:19:15.886Z"},"homepage":"https://ajv.js.org","keywords":["JSON","schema","validator","validation","jsonschema","json-schema","json-schema-validator","json-schema-validation"],"repository":{"type":"git","url":"git+https://github.com/ajv-validator/ajv.git"},"author":{"name":"Evgeny Poberezkin"},"bugs":{"url":"https://github.com/ajv-validator/ajv/issues"},"license":"MIT","readmeFilename":"README.md","users":{"esp":true,"dalcib":true,"jason0518":true,"robertpenner":true,"janpotoms":true,"kikar":true,"slurm":true,"xiechao06":true,"cwagner":true,"kevin.leptons":true,"sopepos":true,"antanst":true,"zafaransari":true,"lensi":true,"ayozebarrera":true,"rajiff":true,"lichenhao":true,"arielfr":true,"wukaidong":true,"ierceg":true,"quocnguyen":true,"horacio.casatti":true,"gvn":true,"david-ruzicka":true,"raojs":true,"princetoad":true,"noyobo":true,"sunnylost":true,"lestad":true,"panlw":true,"tcrowe":true,"nilz3ro":true,"xueboren":true,"kankungyip":true,"qddegtya":true,"ivan403704409":true,"santi8ago8":true,"nicknaso":true,"nichoth":true,"kontrax":true,"abhilash503001":true,"heineiuo":true,"andrewhuffman":true,"oleg_tsyba":true,"slowmove":true,"sasquatch":true,"chaoliu":true,"icognivator":true,"yeelan0319":true,"kakaman":true,"wujr5":true,"ndxbn":true,"alopezsanchez":true,"rvyshnevskyi":true,"akshendra":true,"kron4eg":true,"mauriciolauffer":true,"daniel-lewis-bsc-hons":true,"zhenguo.zhao":true,"jazzhuang":true,"shuoshubao":true,"hengkiardo":true,"mysticatea":true,"andygreenegrass":true,"kshateesh":true,"sinfex":true,"astesio":true,"kkicoo7":true,"arefm":true,"po":true,"jakub.knejzlik":true,"thangkt":true,"danday74":true,"vparaskevas":true,"arai":true,"deividasjackus":true,"tsxuehu":true,"ganeshkbhat":true,"thevikingcoder":true,"freightbpi":true,"x-cold":true,"esilva2902":true,"charlie.wilson":true,"daizch":true,"cmbirk":true,"ricardweii":true,"sornaks":true,"rafaesc92":true,"shivayl":true,"tommytroylin":true,"sopov":true,"yangwao":true,"abnerlin":true,"tztz":true,"horrorandtropics":true,"grabantot":true,"cameronnokes":true,"metaa":true,"zuojiang":true,"juanf03":true,"hmacphail":true}} +{ + "name": "ajv", + "description": "Another JSON Schema Validator", + "dist-tags": { + "latest": "8.11.0" + }, + "versions": { + "8.11.0": { + "name": "ajv", + "version": "8.11.0", + "description": "Another JSON Schema Validator", + "main": "dist/ajv.js", + "types": "dist/ajv.d.ts", + "scripts": { + "eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite", + "prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"", + "prettier:check": "prettier --list-different \"./**/*.{json,yaml,js,ts}\"", + "test-spec": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot", + "test-codegen": "nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec", + "test-debug": "npm run test-spec -- --inspect-brk", + "test-cov": "nyc npm run test-spec", + "rollup": "rm -rf bundle && rollup -c", + "bundle": "rm -rf bundle && node ./scripts/bundle.js ajv ajv7 ajv7 && node ./scripts/bundle.js 2019 ajv2019 ajv2019 && node ./scripts/bundle.js 2020 ajv2020 ajv2020 && node ./scripts/bundle.js jtd ajvJTD ajvJTD", + "build": "rm -rf dist && tsc && cp -r lib/refs dist && rm dist/refs/json-schema-2019-09/index.ts && rm dist/refs/json-schema-2020-12/index.ts && rm dist/refs/jtd-schema.ts", + "json-tests": "rm -rf spec/_json/*.js && node scripts/jsontests", + "test-karma": "karma start", + "test-browser": "rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start", + "test-all": "npm run test-cov && if-node-version 12 npm run test-browser", + "test": "npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov", + "test-ci": "AJV_FULL_TEST=true npm test", + "prepublish": "npm run build", + "benchmark": "npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd", + "docs:dev": "./scripts/prepare-site && vuepress dev docs", + "docs:build": "./scripts/prepare-site && vuepress build docs" + }, + "nyc": { + "exclude": [ + "**/spec/**", + "node_modules" + ], + "reporter": [ + "lcov", + "text-summary" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ajv-validator/ajv.git" + }, + "author": { + "name": "Evgeny Poberezkin" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/ajv-validator/ajv/issues" + }, + "runkitExampleFilename": ".runkit_example.js", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "devDependencies": { + "@ajv-validator/config": "^0.3.0", + "@rollup/plugin-commonjs": "^21.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.0.0", + "@rollup/plugin-typescript": "^8.2.1", + "@types/chai": "^4.2.12", + "@types/mocha": "^9.0.0", + "@types/node": "^17.0.0", + "@types/require-from-string": "^1.2.0", + "@typescript-eslint/eslint-plugin": "^3.8.0", + "@typescript-eslint/parser": "^3.8.0", + "ajv-formats": "^3.0.0-rc.0", + "browserify": "^17.0.0", + "chai": "^4.0.1", + "cross-env": "^7.0.2", + "dayjs": "^1.10.4", + "dayjs-plugin-utc": "^0.1.2", + "eslint": "^7.8.1", + "eslint-config-prettier": "^7.0.0", + "fast-uri": "^1.0.0", + "glob": "^7.0.0", + "husky": "^7.0.1", + "if-node-version": "^1.0.0", + "jimp": "^0.16.1", + "js-beautify": "^1.7.3", + "json-schema-test": "^2.0.0", + "karma": "^6.0.0", + "karma-chrome-launcher": "^3.0.0", + "karma-mocha": "^2.0.0", + "lint-staged": "^12.1.1", + "mocha": "^9.0.2", + "module-from-string": "^3.1.3", + "node-fetch": "^3.0.0", + "nyc": "^15.0.0", + "prettier": "^2.3.1", + "re2": "^1.16.0", + "rollup": "^2.44.0", + "rollup-plugin-terser": "^7.0.2", + "ts-node": "^10.0.0", + "tsify": "^5.0.2", + "typescript": "^4.2.0" + }, + "collective": { + "type": "opencollective", + "url": "https://opencollective.com/ajv" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + }, + "prettier": "@ajv-validator/config/prettierrc.json", + "husky": { + "hooks": { + "pre-commit": "lint-staged && npm test" + } + }, + "lint-staged": { + "*.{json,yaml,js,ts}": "prettier --write" + }, + "gitHead": "c067d6d9c3285054ea4c0a2d2adbbc8b5d631935", + "_id": "ajv@8.11.0", + "_nodeVersion": "14.19.0", + "_npmVersion": "6.14.16", + "dist": { + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "shasum": "977e91dd96ca669f54a11e23e378e33b884a565f", + "tarball": "http://localhost:4260/ajv/ajv-8.11.0.tgz", + "fileCount": 466, + "unpackedSize": 1016907 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "homepage": "https://ajv.js.org", + "repository": { + "type": "git", + "url": "git+https://github.com/ajv-validator/ajv.git" + }, + "author": { + "name": "Evgeny Poberezkin" + }, + "bugs": { + "url": "https://github.com/ajv-validator/ajv/issues" + }, + "license": "MIT", + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/ansi-regex/registry.json b/tests/registry/npm/ansi-regex/registry.json index eab885df18..e60f9a7697 100644 --- a/tests/registry/npm/ansi-regex/registry.json +++ b/tests/registry/npm/ansi-regex/registry.json @@ -1 +1,161 @@ -{"_id":"ansi-regex","_rev":"56-0d93cfc815d10b9e54c4d2b298a530c0","name":"ansi-regex","description":"Regular expression for matching ANSI escape codes","dist-tags":{"latest":"6.0.1"},"versions":{"0.1.0":{"name":"ansi-regex","version":"0.1.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re"],"devDependencies":{"mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@0.1.0","_shasum":"55ca60db6900857c423ae9297980026f941ed903","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"55ca60db6900857c423ae9297980026f941ed903","tarball":"http://localhost:4260/ansi-regex/ansi-regex-0.1.0.tgz","integrity":"sha512-sKASJ0JEeHkkUN5A7GBQ1JH5EmBGi8dhl9KChCXV40kGmykzW4uLkVB8XbjV7598iK+I/HQOlqJGLCFA+1ZmzQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICFNrKksSFLI1nUU89uuh0FXYyTjllUj7rEaVgEb+kf4AiEAgpaAhOocM9F+Nwk8ZX9bpQElv1w2cGdA8DQelu8ZJbs="}]},"directories":{}},"0.2.0":{"name":"ansi-regex","version":"0.2.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@0.2.0","_shasum":"3c48015ac52bcae430b08b822b87522644eb0de7","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"3c48015ac52bcae430b08b822b87522644eb0de7","tarball":"http://localhost:4260/ansi-regex/ansi-regex-0.2.0.tgz","integrity":"sha512-Dl8j95am19SdSL9f3jc7rJN9qykOF10PwqRcJX9iXZfxXDHaXHuiYrZDsRWJCEGdsJwyama5HBZONykdFmvf4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGANhX70jFuwQ3p9TQLXhhUTQBkEYkT71exvXCm7kHPLAiBpDIwsCnR3LMhUEu0Cv2ydghhLfD7HtwG3FsNByKDApw=="}]},"directories":{}},"0.2.1":{"name":"ansi-regex","version":"0.2.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@0.2.1","_shasum":"0d8e946967a3d8143f93e24e298525fc1b2235f9","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"0d8e946967a3d8143f93e24e298525fc1b2235f9","tarball":"http://localhost:4260/ansi-regex/ansi-regex-0.2.1.tgz","integrity":"sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICfo8s4bZKG0g9UNFY/QkHrogtKK5S8PTGqDWDzAdraPAiEA4o3UAqG58AwN4vyEoAi1ryDbK8we8xeaFmZsvBsqQn8="}]},"directories":{}},"1.0.0":{"name":"ansi-regex","version":"1.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"gitHead":"4210f11027ddd7937f9e25a9a1570aee6d0594f5","bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@1.0.0","_shasum":"54c7ce13af71e436348666484c44516ab9bc144e","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"dist":{"shasum":"54c7ce13af71e436348666484c44516ab9bc144e","tarball":"http://localhost:4260/ansi-regex/ansi-regex-1.0.0.tgz","integrity":"sha512-wzNmkzoFDDHQR1zwctGAX0KOZjX8rwjXG+5j4EeLqr1dHyGwcvH7/AIXk5yYB2Abuh2Ge3H44Fn83csDLLUqQA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuY826SxKNnmojTxOZlQLMmJX09dRgHGMzES5BC4q/hwIgWv8f0RQDZe5BTPbFF2VpNfZ9AdZ6So2p1OgJEDnofx0="}]},"directories":{}},"1.1.0":{"name":"ansi-regex","version":"1.1.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha test/test.js","view-supported":"node test/viewCodes.js"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@1.1.0","_shasum":"67792c5d6ad05c792d6cd6057ac8f5e69ebf4357","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"dist":{"shasum":"67792c5d6ad05c792d6cd6057ac8f5e69ebf4357","tarball":"http://localhost:4260/ansi-regex/ansi-regex-1.1.0.tgz","integrity":"sha512-+VAkk48zFJGuS3ru8ycFCrX1wif67Tbn+yJHAo5xxFY5pFVp8Fy9WbZqOKYxGCP9dEr4ny8aGbjMMpcTGPQzMA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHfNx4mPZnwGi6aQi5TpXIAqzudRmeeTfVQn2xU+sLm9AiEAzm02QbEZY+N0h4N8tSuFE8xOlmhWv6Clv0Osnyf0814="}]},"directories":{}},"1.1.1":{"name":"ansi-regex","version":"1.1.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha test/test.js","view-supported":"node test/viewCodes.js"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"gitHead":"47fb974630af70998157b30fad6eb5e5bd7c7cd6","bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@1.1.1","_shasum":"41c847194646375e6a1a5d10c3ca054ef9fc980d","_from":".","_npmVersion":"2.1.16","_nodeVersion":"0.10.35","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"41c847194646375e6a1a5d10c3ca054ef9fc980d","tarball":"http://localhost:4260/ansi-regex/ansi-regex-1.1.1.tgz","integrity":"sha512-q5i8bFLg2wDfsuR56c1NzlJFPzVD+9mxhDrhqOGigEFa87OZHlF+9dWeGWzVTP/0ECiA/JUGzfzRr2t3eYORRw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICU6NOln1A9kSVM+kcZ0RQ7Foaj7ZZrTVD3kUtQWXiPgAiEAkK2BBFckDS1wSyOm3gW6oFGWCccNojUqGbs0ehRYcY0="}]},"directories":{}},"2.0.0":{"name":"ansi-regex","version":"2.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/ansi-regex"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha test/test.js","view-supported":"node test/viewCodes.js"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"mocha":"*"},"gitHead":"57c3f2941a73079fa8b081e02a522e3d29913e2f","bugs":{"url":"https://github.com/sindresorhus/ansi-regex/issues"},"homepage":"https://github.com/sindresorhus/ansi-regex","_id":"ansi-regex@2.0.0","_shasum":"c5061b6e0ef8a81775e50f5d66151bf6bf371107","_from":".","_npmVersion":"2.11.2","_nodeVersion":"0.12.5","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"c5061b6e0ef8a81775e50f5d66151bf6bf371107","tarball":"http://localhost:4260/ansi-regex/ansi-regex-2.0.0.tgz","integrity":"sha512-jCcLjwL2jOaTcRIaJkoRteMwNXg8nfJvwT/9K91kwZhH7bf4lsprqZ2+Qa7tSp8BYtejobOCBkDreC07q0KmZw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdHxAVrdkIa+f4ShCg9LmFGGXaydAjrFi2EKdL7dSQsAIhAKHKSEqbLoyws6ix+AeKJHAHTX7IXclIhkYwIH9vP8a1"}]},"directories":{}},"2.1.1":{"name":"ansi-regex","version":"2.1.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava --verbose","view-supported":"node fixtures/view-codes.js"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"0.17.0","xo":"0.16.0"},"xo":{"rules":{"guard-for-in":0,"no-loop-func":0}},"gitHead":"7c908e7b4eb6cd82bfe1295e33fdf6d166c7ed85","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@2.1.1","_shasum":"c3b33ab5ee360d86e0e628f0468ae7ef27d654df","_from":".","_npmVersion":"2.14.2","_nodeVersion":"0.10.32","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"c3b33ab5ee360d86e0e628f0468ae7ef27d654df","tarball":"http://localhost:4260/ansi-regex/ansi-regex-2.1.1.tgz","integrity":"sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAR2sccS4/yhooGKsXIc/4rbjLYgEI/ZRh6zjX4sAOioAiAMaqaR1nse5wZf6Gl1qpfxCxMLaXyb6MKNhG4G5Cjc+w=="}]},"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/ansi-regex-2.1.1.tgz_1484363378013_0.4482989883981645"},"directories":{}},"3.0.0":{"name":"ansi-regex","version":"3.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava","view-supported":"node fixtures/view-codes.js"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"0a8cc19946c03c38520fe8c086b8adb66f9cce0b","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@3.0.0","_shasum":"ed0317c322064f79466c02966bddb605ab37d998","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.3","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"ed0317c322064f79466c02966bddb605ab37d998","tarball":"http://localhost:4260/ansi-regex/ansi-regex-3.0.0.tgz","integrity":"sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZIxnZvDlDd2wlGhadhaYGHYJUyNwYOgCW3R98PdgWbAiEA2wN0X8oDjEhS1vHmuDx3Rmof6hJLkC4TfVvx6jBu6eE="}]},"maintainers":[{"name":"dthree","email":"threedeecee@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex-3.0.0.tgz_1497985412590_0.5700640194118023"},"directories":{}},"4.0.0":{"name":"ansi-regex","version":"4.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^0.25.0","xo":"^0.23.0"},"gitHead":"a1d92466388fc8766b63bfab27ddc1e1df897dda","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@4.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.11.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==","shasum":"70de791edf021404c3fd615aa89118ae0432e5a9","tarball":"http://localhost:4260/ansi-regex/ansi-regex-4.0.0.tgz","fileCount":4,"unpackedSize":4364,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboLTyCRA9TVsSAnZWagAAGnQP/ikFm/pU0nz/k+kwLXQF\nQaOqkrWmoNlb6fiz7NElGRxe+a7K5dkovim/Plf66V+kcT1u47O/IsNn+1AU\nUYztxJ2Syn8QWdLgCKZlVy4jgN8qrq3ACLHYV6XFo+fV7JVoRqZnVLZlJtCg\nxaWT3K+ckyo0SbFrSKHchZWSha20mtgBjUzeVnzsx0zUELhL3I9soTTMaXOp\n8tYKs2rxhYduYewTu5hDfi/aAYlWhUuS0KkxZ+lR8zjrRJV3OMMcexJ+6qzZ\n5YozFB5L72r+aXJ5b9epDbRMTUh9D+J6OIRED4COBTbi5VaxjE5Qef7Y4wuy\nB5t+S8shSu/yPbMGKdHW+lBIv8tskZgCislmedHL7N3dWqKRqaelIKJHp8ea\n5NlvT4Bq6bIgggoPSG4ccVPvnwhPzZso3yBhx1Xzxdysb3nRor0ZrkDr9NSS\nPHhQwxlIZr3Ba4R7BWeyNjvOw4kAB8EicYP9REruWDoMxee/mWYd3xo1rOTD\nGocidueWQwHJPbyxGm4boKcBsToDN7boOoZAJONR0DBFgB5fCFB7FbzLRgil\nh3sOpoe7K+8/tCC/GlbpnhPEtNtFAWmtVEr5fuG6pwCxwO9ZOUNsFKCccs/Q\nSkXo9JmCGUgLzW04Z0Cms6BMXuS/VKERq+QyJKq5EQXJ93KwEBWj7gSmuYar\nmiIW\r\n=6Av/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAso5oveCqpFlBxrb53yO+PrFu0XbxlabKuVmjtXneRlAiEA9s3wMBc2PkUfz2kFfjMfBAsauEdzEr5cV3K1YMPSUO8="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_4.0.0_1537258737952_0.3982474354635459"},"_hasShrinkwrap":false},"4.1.0":{"name":"ansi-regex","version":"4.1.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^0.25.0","xo":"^0.23.0"},"gitHead":"a079ab2d30cfb752a3f247dcf358d0a591c288c5","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@4.1.0","_nodeVersion":"8.15.0","_npmVersion":"6.8.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==","shasum":"8b9f8f08cf1acb843756a839ca8c7e3168c51997","tarball":"http://localhost:4260/ansi-regex/ansi-regex-4.1.0.tgz","fileCount":4,"unpackedSize":5139,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcgghQCRA9TVsSAnZWagAAkicP/A0YuAuK50ptS+EZeV8x\nNdxf9AYCNd3FSMq/0MeHHbSFb/ofI8CKKGuru3zVPFV/KfVhddUsnqv45Z/y\nNRxrXDkUd0LpUtCZW8QcPOQReuUshJ1n4XvSngt6753R95YbGzqVbDkORvvH\nfOjl/eIiTd3J2amW4LcOsiqTRkNCahD1AA+dEHiYVJ3dpymihWH5vTWWPmll\nGVzb6oUpIb2YtusNlma5ALRPFXYv4kxMVuTV5LXrdxeZyOyhytShYDJX6/DK\n7eaHDjB3TJT3lGq8emq4xI5xLn1pXceZOhd4iusPCvToG3uwu5DMKSuoLYF0\nEzKPyi1D78oUPgZ+mzDSgU3KobiEtMckHatyUSMS2LwBW1Xdz+LEX4mrt6Jn\ni6hSmJQjhlEeYgFlWKpxYgx/B95G+ckCEqDcSlhrLqwcw6VQhEWd8X7RWfOv\nyLJ9rwja7ILbMHIgQHl1NYGqW6+n3Qe/5MtZdwC5OmZaVwbiSpesDOcJXsEM\nD1JqCLZxQTrKwVzlUbj2FJbKjGls5V0RupMKqr4hSftxUIa4PZZ5Aaekt7XX\nVt0EkP6NZ4hRkFYzutsvNOK37slo948zb6Xp8e0ymeMjTIhISCz+k0R0KgmM\nP4o4nK1zyz1VPqzVvKOp0n6VjYABlRe1d1A2ui42LWy5E7I7F081QqpCUkCJ\nVJP2\r\n=TkVA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBW8s+I9AGd0oTXWxFXE5bPmDufETac5wywy5sMer6BBAiEAtP72v3hFf5e/0XRtGiTmNsZ2Pg1GRmrWpJA6TJUYr5o="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_4.1.0_1552025680031_0.26097113418100015"},"_hasShrinkwrap":false},"5.0.0":{"name":"ansi-regex","version":"5.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava && tsd","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^2.4.0","tsd":"^0.9.0","xo":"^0.25.3"},"gitHead":"2b56fb0c7a07108e5b54241e8faec160d393aedb","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@5.0.0","_nodeVersion":"10.16.3","_npmVersion":"6.11.3","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==","shasum":"388539f55179bf39339c81af30a654d69f87cb75","tarball":"http://localhost:4260/ansi-regex/ansi-regex-5.0.0.tgz","fileCount":5,"unpackedSize":5692,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdly0KCRA9TVsSAnZWagAAinUP/0Ck5MNcNm9ueLhK5Ga/\nwggCVoaJ77iq1Kgi8QoOPd0E4PKrMXOnXfoHMjJfvGmzh+2GieptLu+2zzUo\nXQjbFLCvUXzMVJEh7sS5q1AI3JM5dQxEi4Ab2IDWPVn41gvqvdfRWOv1KXtC\nmYxnnhoTUpU3rYKHMbKI+eskQDsZjM/ZZj4Vf2Z8OlTzPv583uuBAAiP/SGk\n6mMwPbdEuVq5hN2EEOlAKzxkxTKCAX3+7Re2H9PVAMmtCXWj09qwaxwRxtVc\nCHi7FGRefk3a3FJxdLPKHdmOR7fQJy5TRoOhutjhQPFZKGqFhReCtsZwHGuJ\nKNqagC1KBLFQRLLwtJGhdQGpLUYZgcurWC1OX+wbMBJB8ZrC0HBIuUAlLCOJ\noKhRI81dJ89lT75+xe6B2X8TZsWzQNuohd4V5ymKBlztU3wOPk1r+SEt8tFu\nH+iesokrKb/tSHL0cr5XVKq5yJC3oWFpvdfM7xToVS4ehxfh50Ib8OuhFJXr\nxws6yKp+PA4RTy533CHyfME1K2lM8M8YQPnFs6uHeaWMQhJHxTsYWIccZP+t\n17qqhl64fW6UhO0Nxio2Jpbwrdo1pfmdsN04AVow6nsEfRfGrZ/9Qzq23c0G\nawgI4nagjuIuQeknNymHC8IbhpYEa5eRY7+uvElE1bWZwmJshf9ZItStOjYI\n1B0E\r\n=DWyA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHZmRpyQjhEtkiaP76KYQKYK38C6gxln7LWeBNELA7DAIgOpfLZg09XrrsW5VwbbWEy+7RDNpdR62FEt94u1lJCpc="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_5.0.0_1570188553674_0.9267473348647308"},"_hasShrinkwrap":false},"6.0.0":{"name":"ansi-regex","version":"6.0.0","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"funding":"https://github.com/chalk/ansi-regex?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"type":"module","exports":"./index.js","engines":{"node":">=12"},"scripts":{"test":"xo && ava && tsd","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^3.15.0","tsd":"^0.14.0","xo":"^0.38.2"},"gitHead":"c1b5e45f7c65a332ffb03ac8e5804ad37c579cdc","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@6.0.0","_nodeVersion":"14.16.1","_npmVersion":"6.14.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==","shasum":"ecc7f5933cbe5ac7b33e209a5ff409ab1669c6b2","tarball":"http://localhost:4260/ansi-regex/ansi-regex-6.0.0.tgz","fileCount":5,"unpackedSize":5631,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgeShnCRA9TVsSAnZWagAA5skP/RJzYexBxMl+ln5Waq+j\nJcMY3Gjz1UL+qodDm2QbAMK41c92SEVh5f26fdyRUfhSgLo3Jjn8PBcMlStr\njAH/FBhyrQsFGyxVsgOhOfkSxDjQtWRX9JBCwnYbCp8zfpOcCqIGgwl6Za8X\njQkODSEkwpBdIAI0I8E8bTLcfO/RK7pPfbEWptrdNJgsv80Y3ye8fLBiFERm\nHzgt1FCR5m0LyVlfq941MpmLyzd0f0dewP3WiQ9yDyD60Sune4s6jw4n97pU\nDG3H/MboqIaGkcQPyVWTtM92UTRKt6dBcIfnCAXgf6qD7Iu2/hWUQQg6NpVX\nAD22nWt5e6GCJXOzDDQSY5xO5dnR4DcYpcQBiszYqxRopGTSWy5E6pK6x+5N\na3mbFq4zFi33TtjM8MRdwGRyIqnGwsYuSTCw/ie6EHZNBlBMLhcMfffYYwtD\n8Yc04q1n3jsloKT4Z3TGDkTDPALEQk7LcOklArsOHkqVDjtUyPMdm3y8ew73\n4k9b7G/x4AnP9yQ6zhIASoToZ8YLnQCPZxFZ93HnMAhPAvwe9n6Ni6LqnKzU\n5myBJYckIV6qcOp1nPwxyBTwdv0uXE5h4FLCbE2B3JVe+kV5cbu3OC2rGwN0\nncdZvUwFGo5rNKkHm+jPcI7/BrZGR1+4r/Z8GFrPYGpY20gFJsL8055NsGvu\n+l/+\r\n=ys2B\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLdXfGwD/nurKg7vItN259S8UAUAS62nccUonevxA/mgIhAKy4ITBu326c+CBVMt1HLqssMHFhIj8COqAV7/kigOXR"}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_6.0.0_1618552935087_0.14381997678067826"},"_hasShrinkwrap":false},"6.0.1":{"name":"ansi-regex","version":"6.0.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"funding":"https://github.com/chalk/ansi-regex?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"type":"module","exports":"./index.js","engines":{"node":">=12"},"scripts":{"test":"xo && ava && tsd","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^3.15.0","tsd":"^0.14.0","xo":"^0.38.2"},"types":"./index.d.ts","gitHead":"d908492e0070f26552fad1b25e339aff9011ae8b","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@6.0.1","_nodeVersion":"16.0.0","_npmVersion":"7.23.0","dist":{"integrity":"sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==","shasum":"3183e38fae9a65d7cb5e53945cd5897d0260a06a","tarball":"http://localhost:4260/ansi-regex/ansi-regex-6.0.1.tgz","fileCount":5,"unpackedSize":5667,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhO78hCRA9TVsSAnZWagAA+F4P/0Xt4D0GoXduv+o147iO\nj3b1oPSNypnmThhmCAUInwB1Xd9SXFEjzuNDNGX/8xeWUQrJssJ+SBEzb5te\nr34P6wPHUeuTa2p1j3ABN9ABP/NPCPkaEDgjx86ImkT++3VI8yNEuSSOsghI\n5Ssvhm6bLJBWzCt/cweIG7x4ZJQPeUbyoWIJmBobCDyNuVgabmk9B2B1RyO0\nf2aounmh5w1fBWsx65MjTi7fu4e/GOP+xscf9Rn1AdRP6rcxJakPjaGTF3HE\naz6UNP9UZCuZ4rb6xOFEfLmiqfNbK31NKNLPrABDXF6NkbJepsUhNmju32cg\nUuo4lSkxfFaVyFXFB1h62RmDdemxZWl9j24fVt+99K4BH6xOiwPmOHHHPJnL\nXNuZ6eCwdcLjPe8Af/0GEsFqdDu591Hwi2Nl8UNAD5hCzcDTITOTL95Dopaw\nGzySTClnDsh17Ud73FWM51FQzVDORa2vOmVzQts3aHlF93ufk9RHtlN9YxAV\nUvM3IxMHx2O8Rc2gSc6t/pJAdFACBLkLDGtcQVhxaFcTpGXrKUr+KN2gFC4D\nXZA/MvK0YXBmrwec20k2wTAdmi7XO5k8HciCPT7MZDJONTBlt9cC/LL41JNc\nvxj0A0loP9R44eVoAJOSbxhpnteeIjw4rwkOySZOqqEsUw5MDFp/peiojlcv\nCOQk\r\n=VRgZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWW/ZEXmQGK500jBFw7uRYczrrcLTzOEnm3uDiNPs6rAIgcKX8SLAOUpBu/tWg+7vPsMA4l7siraEVYPpTETOVqX0="}]},"_npmUser":{"name":"qix","email":"josh@junon.me"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_6.0.1_1631305505393_0.35989069175371236"},"_hasShrinkwrap":false},"5.0.1":{"name":"ansi-regex","version":"5.0.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava && tsd","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^2.4.0","tsd":"^0.9.0","xo":"^0.25.3"},"types":"./index.d.ts","readme":"# ansi-regex\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\n\n\n## Install\n\n```\n$ npm install ansi-regex\n```\n\n\n## Usage\n\n```js\nconst ansiRegex = require('ansi-regex');\n\nansiRegex().test('\\u001B[4mcake\\u001B[0m');\n//=> true\n\nansiRegex().test('cake');\n//=> false\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex());\n//=> ['\\u001B[4m', '\\u001B[0m']\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex({onlyFirst: true}));\n//=> ['\\u001B[4m']\n\n'\\u001B]8;;https://github.com\\u0007click\\u001B]8;;\\u0007'.match(ansiRegex());\n//=> ['\\u001B]8;;https://github.com\\u0007', '\\u001B]8;;\\u0007']\n```\n\n\n## API\n\n### ansiRegex(options?)\n\nReturns a regex for matching ANSI escape codes.\n\n#### options\n\nType: `object`\n\n##### onlyFirst\n\nType: `boolean`
\nDefault: `false` *(Matches any ANSI escape codes in a string)*\n\nMatch only the first ANSI escape.\n\n\n## FAQ\n\n### Why do you test for codes not in the ECMA 48 standard?\n\nSome of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.\n\nOn the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of \"interrupts\" that can mean different things on certain brands of processors, most of which have been phased out.\n\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n\n---\n\n

\n\t\n\t\tGet professional support for this package with a Tidelift subscription\n\t\n\t
\n\t\n\t\tTidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies.\n\t
\n
\n","readmeFilename":"readme.md","gitHead":"a9babce885cf19c363cf1d1c645f834592c3f7a4","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@5.0.1","_nodeVersion":"16.0.0","_npmVersion":"7.23.0","dist":{"integrity":"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==","shasum":"082cb2c89c9fe8659a311a53bd6a4dc5301db304","tarball":"http://localhost:4260/ansi-regex/ansi-regex-5.0.1.tgz","fileCount":5,"unpackedSize":5609,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhQMXnCRA9TVsSAnZWagAADYYP/iz1/gbU0N9EjGpKc+Gm\nnX7qe5zf8TvcOpxBMDSFiCD5ntg/EH4YguqeUhRgW7X/nx58basGjNU2Payd\n6gIBVMEriQUWhS6MllSbiIbxY3ALKRcNhIphqER4kneujLwTqgAMOSjjnOk+\nvhPheetSO9ydRVZvb1UHC45D/4Bl0BJjPuAgF6YJlAae+bon50yImBeBUus4\nSmcbaBKSoCKT+ml4pfNidfUIJn+Zo8u0u8WI/6hfJ5oD9/eerQaSK/Fjt1hZ\nj67NmXWMsMugedkgpKbK3lZX+LucgTrb7L9QJC++LQj6FSRDQBguiODgJ912\nVxqjJN0SSqcpNRVk0dTHhI2IoOn4Mu3HVZolsrVFGXsQDMlNHWxehHUtzZ/h\ne592hb0tqcyIeMFLUMcRhcnaQZrNKTYv7XSMpfPWh73slOk5AaZFOyY/yZ2k\nIqfm7sKVsijHzRgyveZ+n1QyV6CWFMzQbxnj34t7NpnX429VY/F/ZL/E1Yfu\noJhSbp/K0+k8Gp9g9YNDANE7s5jM8pJzlSOo3XUWyaFaujRHMsAtxgtYikZB\n3uzZaYQxryjCkvuvZJFwUBMeLWJP2JKt7bpK3mv7DHvEWTxicBHSPaePhA01\nOfiQ7YzPY3pNI/Fki/jloyJgSazLpvlWv7XWAF/OhvB5G3KQbfDe/hbQg0Yq\nsUn3\r\n=I35d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCS7XsMq0d29jMXjedcRcP044S7ZelyMVBxKjkUpCShHAIgGyiTNkLoCCh/rpMnXAisLtOsV3SGe2ftVRwhvZTAPyw="}]},"_npmUser":{"name":"qix","email":"josh@junon.me"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_5.0.1_1631634919356_0.29996150981120184"},"_hasShrinkwrap":false},"4.1.1":{"name":"ansi-regex","version":"4.1.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"^0.25.0","xo":"^0.23.0"},"readme":"# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\n\n---\n\n
\n\t\n\t\tGet professional support for this package with a Tidelift subscription\n\t\n\t
\n\t\n\t\tTidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies.\n\t
\n
\n\n---\n\n\n## Install\n\n```\n$ npm install ansi-regex\n```\n\n\n## Usage\n\n```js\nconst ansiRegex = require('ansi-regex');\n\nansiRegex().test('\\u001B[4mcake\\u001B[0m');\n//=> true\n\nansiRegex().test('cake');\n//=> false\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex());\n//=> ['\\u001B[4m', '\\u001B[0m']\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex({onlyFirst: true}));\n//=> ['\\u001B[4m']\n\n'\\u001B]8;;https://github.com\\u0007click\\u001B]8;;\\u0007'.match(ansiRegex());\n//=> ['\\u001B]8;;https://github.com\\u0007', '\\u001B]8;;\\u0007']\n```\n\n\n## API\n\n### ansiRegex([options])\n\nReturns a regex for matching ANSI escape codes.\n\n#### options\n\n##### onlyFirst\n\nType: `boolean`
\nDefault: `false` *(Matches any ANSI escape codes in a string)*\n\nMatch only the first ANSI escape.\n\n\n## FAQ\n\n### Why do you test for codes not in the ECMA 48 standard?\n\nSome of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.\n\nOn the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of \"interrupts\" that can mean different things on certain brands of processors, most of which have been phased out.\n\n\n## Security\n\nTo report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.\n\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n\n## License\n\nMIT\n","readmeFilename":"readme.md","gitHead":"64735d25eb839b55bc9fae3877edb702b4c92ca2","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@4.1.1","_nodeVersion":"17.3.1","_npmVersion":"8.3.0","dist":{"integrity":"sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==","shasum":"164daac87ab2d6f6db3a29875e2d1766582dabed","tarball":"http://localhost:4260/ansi-regex/ansi-regex-4.1.1.tgz","fileCount":4,"unpackedSize":5172,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiLA7KACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq3gQ//a+k/IMT0gBGfY6uA0Cgu+o/GhIow5TQbqkJER9T27TO8Po7h\r\n/07GR3KJTtxgFn+wkRlNLgXxdCRRjXe5df4eHzbMM52Ag49iqrYecm3xC28i\r\nCJArVdmZ0djATnvThwWImD/dHN5cj76MHQzJjWEdWPXXim/cRHHHcHXkWEsv\r\nN64mWjz06J8NqidAS0ARvYGc6QmUeWENzuhUO7Pa2rymBrkccTQkYNJUoTCf\r\nJ+DAtQZpUm9jFHOKoKsNtyBkb3BlPLZVjnfF6TNv0Ya2KiW5N3FIQEeS8h54\r\nM9l82ED8sopqO7Z6Vsps2W7xdCTRvKPht+cZJhet4hmcxMQE/lNtH6R4C1hR\r\n0MzhnSYwvvsDfqDbjNaerMe3/yq/EkUj8DTDqnNBPeODWlLgG3WF3tTlA7aQ\r\nIqGk8bVfd8Fxr6EJ4JKjn4bUCbmTSzqK7lAiDX/pDXMOONiDvRwQaDJbT5y5\r\nycep5aL9mlYGkSOf2dPRp7B71KHKQAmGTl3OupYMrWxSVNAoIk3T4r5j6IX4\r\n+8LlAtusnCJ4mGWo2M4rXhQ1o+5gWyLgyf470hdCkgH24Yp/8348NEMRZD+z\r\nGv3sPclHhjVZzS0GhEIvHUYYGUuSRxM6Vd6g1lgv8e9LI3/yqvf830l/FHQo\r\nJwEpTS3Q8YrM9t2YpodilybqqpuTbu8uoB4=\r\n=Hgo9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHTU2SCcqrOjx+c6SBKSTrP6U6QykHkMd5WKISOMq7dAAiEAj9BPT1vJW/ZV85WYFAKWbTTGMksmIw4Sv9s9V9U55ko="}]},"_npmUser":{"name":"qix","email":"josh@junon.me"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_4.1.1_1647054537685_0.02257829120511201"},"_hasShrinkwrap":false},"3.0.1":{"name":"ansi-regex","version":"3.0.1","description":"Regular expression for matching ANSI escape codes","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava","view-supported":"node fixtures/view-codes.js"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"devDependencies":{"ava":"*","xo":"*"},"readme":"# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\n\n\n## Install\n\n```\n$ npm install ansi-regex\n```\n\n\n## Usage\n\n```js\nconst ansiRegex = require('ansi-regex');\n\nansiRegex().test('\\u001B[4mcake\\u001B[0m');\n//=> true\n\nansiRegex().test('cake');\n//=> false\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex());\n//=> ['\\u001B[4m', '\\u001B[0m']\n```\n\n\n## FAQ\n\n### Why do you test for codes not in the ECMA 48 standard?\n\nSome of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.\n\nOn the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of \"interrupts\" that can mean different things on certain brands of processors, most of which have been phased out.\n\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n\n## License\n\nMIT\n","readmeFilename":"readme.md","gitHead":"f545bdb80048f527889eddb9ac1a851c6f2a2241","bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"homepage":"https://github.com/chalk/ansi-regex#readme","_id":"ansi-regex@3.0.1","_nodeVersion":"17.3.1","_npmVersion":"8.3.0","dist":{"integrity":"sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==","shasum":"123d6479e92ad45ad897d4054e3c7ca7db4944e1","tarball":"http://localhost:4260/ansi-regex/ansi-regex-3.0.1.tgz","fileCount":4,"unpackedSize":4054,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiQGbIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqy/Q//Vh9oKpgDxgXcW+UYZ9DZKYScVldnKzuT5VNYLrGT8mMMPxAC\r\nws4wVRyeWo8WX4jwQqpZaDxr5WlH+X2tbxM+PmwncwkOYTtbTGutmr+cwc16\r\nXaKNwQZt4F5fA32N39Jxyu05sLqje517n3rRFvN6HqzOw21DYIL6N7UpUXeD\r\nFiwNMFOi2S3RMUJgf6EDVNB59MNX7X6W85cvJrjRK8xfUJB50ODx1WfUNG1X\r\nc96t6swskGBdq0riRxtmUTyJgxkgaL4eHnYMpLSad1Xx5rVyHckL9CFajYPo\r\np64kmi2+UHAswdfzDYuQTuIt2vKzpKCGGP74FSZ5trTsQNuljvjhemFePlAw\r\nXOoq2sf/yTGiNu9W+ved2NPpR/nSQO9UnBp7P/pKcfY92rPOwRc3ypBx4JDC\r\nQHANx8/fM7TtRrVUyVJoyEYzMnDxDQnzeGRrYfSneg1oI7oci62HXmgrfxvh\r\n8TPDgsKALJixmkDc6FQgENjmMrblrmU7ZuK2H1meidi+62MJEoTj5lwXKp9d\r\nhay1RKGB4qKHEO5PVIBrYdvkoZIaUyIrN4KgcqHHjrOKWhcWAZDu3A9wwyLD\r\nAOMLQbPqJccQj2FrSMOGrc1ego70swRFGX21xLW0xqr8p65PTLGBKp0+OgC9\r\nlcz8F/xfg1PkqVRZw4TGuEcBE3EHcDFSrr0=\r\n=xF18\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGxf4gJU3Ry4fyipshNrDGCYFK/glbif7vsA/O9sywmCAiEAgFdMiI1ykrpU2QunGRKSzrIksQtwFrDpgjgh2uUQKh8="}]},"_npmUser":{"name":"qix","email":"josh@junon.me"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-regex_3.0.1_1648387784373_0.8659992768445368"},"_hasShrinkwrap":false}},"readme":"","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"time":{"modified":"2022-06-13T03:05:25.696Z","created":"2014-06-03T16:59:22.332Z","0.1.0":"2014-06-03T16:59:22.332Z","0.2.0":"2014-06-14T01:12:53.550Z","0.2.1":"2014-06-20T16:44:03.241Z","1.0.0":"2014-08-13T13:29:14.050Z","1.1.0":"2014-08-30T12:38:30.166Z","1.1.1":"2015-02-22T09:24:51.185Z","2.0.0":"2015-06-30T16:07:19.279Z","2.1.1":"2017-01-14T03:09:39.887Z","3.0.0":"2017-06-20T19:03:33.464Z","4.0.0":"2018-09-18T08:18:58.129Z","4.1.0":"2019-03-08T06:14:40.169Z","5.0.0":"2019-10-04T11:29:13.830Z","6.0.0":"2021-04-16T06:02:15.282Z","6.0.1":"2021-09-10T20:25:05.514Z","5.0.1":"2021-09-14T15:55:19.540Z","4.1.1":"2022-03-12T03:08:58.035Z","3.0.1":"2022-03-27T13:29:44.595Z"},"homepage":"https://github.com/chalk/ansi-regex#readme","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","command-line","text","regex","regexp","re","match","test","find","pattern"],"repository":{"type":"git","url":"git+https://github.com/chalk/ansi-regex.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"bugs":{"url":"https://github.com/chalk/ansi-regex/issues"},"license":"MIT","readmeFilename":"","users":{"nfd":true,"scottfreecode":true,"kailash.yogeshwar":true,"usex":true,"edwardxyt":true,"qddegtya":true,"justjavac":true,"hualei":true}} +{ + "name": "ansi-regex", + "description": "Regular expression for matching ANSI escape codes", + "dist-tags": { + "latest": "6.0.1" + }, + "versions": { + "6.0.1": { + "name": "ansi-regex", + "version": "6.0.1", + "description": "Regular expression for matching ANSI escape codes", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-regex.git" + }, + "funding": "https://github.com/chalk/ansi-regex?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "type": "module", + "exports": "./index.js", + "engines": { + "node": ">=12" + }, + "scripts": { + "test": "xo && ava && tsd", + "view-supported": "node fixtures/view-codes.js" + }, + "devDependencies": { + "ava": "^3.15.0", + "tsd": "^0.14.0", + "xo": "^0.38.2" + }, + "types": "./index.d.ts", + "gitHead": "d908492e0070f26552fad1b25e339aff9011ae8b", + "bugs": { + "url": "https://github.com/chalk/ansi-regex/issues" + }, + "_id": "ansi-regex@6.0.1", + "_nodeVersion": "16.0.0", + "_npmVersion": "7.23.0", + "dist": { + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "shasum": "3183e38fae9a65d7cb5e53945cd5897d0260a06a", + "tarball": "http://localhost:4260/ansi-regex/ansi-regex-6.0.1.tgz", + "fileCount": 5, + "unpackedSize": 5667 + }, + "directories": {}, + "_hasShrinkwrap": false + }, + "5.0.1": { + "name": "ansi-regex", + "version": "5.0.1", + "description": "Regular expression for matching ANSI escape codes", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-regex.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd", + "view-supported": "node fixtures/view-codes.js" + }, + "devDependencies": { + "ava": "^2.4.0", + "tsd": "^0.9.0", + "xo": "^0.25.3" + }, + "types": "./index.d.ts", + "readme": "# ansi-regex\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\n\n\n## Install\n\n```\n$ npm install ansi-regex\n```\n\n\n## Usage\n\n```js\nconst ansiRegex = require('ansi-regex');\n\nansiRegex().test('\\u001B[4mcake\\u001B[0m');\n//=> true\n\nansiRegex().test('cake');\n//=> false\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex());\n//=> ['\\u001B[4m', '\\u001B[0m']\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex({onlyFirst: true}));\n//=> ['\\u001B[4m']\n\n'\\u001B]8;;https://github.com\\u0007click\\u001B]8;;\\u0007'.match(ansiRegex());\n//=> ['\\u001B]8;;https://github.com\\u0007', '\\u001B]8;;\\u0007']\n```\n\n\n## API\n\n### ansiRegex(options?)\n\nReturns a regex for matching ANSI escape codes.\n\n#### options\n\nType: `object`\n\n##### onlyFirst\n\nType: `boolean`
\nDefault: `false` *(Matches any ANSI escape codes in a string)*\n\nMatch only the first ANSI escape.\n\n\n## FAQ\n\n### Why do you test for codes not in the ECMA 48 standard?\n\nSome of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.\n\nOn the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of \"interrupts\" that can mean different things on certain brands of processors, most of which have been phased out.\n\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n\n---\n\n
\n\t\n\t\tGet professional support for this package with a Tidelift subscription\n\t\n\t
\n\t\n\t\tTidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies.\n\t
\n
\n", + "readmeFilename": "readme.md", + "gitHead": "a9babce885cf19c363cf1d1c645f834592c3f7a4", + "bugs": { + "url": "https://github.com/chalk/ansi-regex/issues" + }, + "_id": "ansi-regex@5.0.1", + "_nodeVersion": "16.0.0", + "_npmVersion": "7.23.0", + "dist": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "shasum": "082cb2c89c9fe8659a311a53bd6a4dc5301db304", + "tarball": "http://localhost:4260/ansi-regex/ansi-regex-5.0.1.tgz", + "fileCount": 5, + "unpackedSize": 5609 + }, + "directories": {}, + "_hasShrinkwrap": false + }, + "3.0.1": { + "name": "ansi-regex", + "version": "3.0.1", + "description": "Regular expression for matching ANSI escape codes", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-regex.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "xo && ava", + "view-supported": "node fixtures/view-codes.js" + }, + "devDependencies": { + "ava": "*", + "xo": "*" + }, + "readme": "# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\n\n\n## Install\n\n```\n$ npm install ansi-regex\n```\n\n\n## Usage\n\n```js\nconst ansiRegex = require('ansi-regex');\n\nansiRegex().test('\\u001B[4mcake\\u001B[0m');\n//=> true\n\nansiRegex().test('cake');\n//=> false\n\n'\\u001B[4mcake\\u001B[0m'.match(ansiRegex());\n//=> ['\\u001B[4m', '\\u001B[0m']\n```\n\n\n## FAQ\n\n### Why do you test for codes not in the ECMA 48 standard?\n\nSome of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.\n\nOn the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of \"interrupts\" that can mean different things on certain brands of processors, most of which have been phased out.\n\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n\n## License\n\nMIT\n", + "readmeFilename": "readme.md", + "gitHead": "f545bdb80048f527889eddb9ac1a851c6f2a2241", + "bugs": { + "url": "https://github.com/chalk/ansi-regex/issues" + }, + "_id": "ansi-regex@3.0.1", + "_nodeVersion": "17.3.1", + "_npmVersion": "8.3.0", + "dist": { + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "shasum": "123d6479e92ad45ad897d4054e3c7ca7db4944e1", + "tarball": "http://localhost:4260/ansi-regex/ansi-regex-3.0.1.tgz", + "fileCount": 4, + "unpackedSize": 4054 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "homepage": "https://github.com/chalk/ansi-regex#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-regex.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/chalk/ansi-regex/issues" + }, + "license": "MIT", + "readmeFilename": "" +} diff --git a/tests/registry/npm/ansi-styles/registry.json b/tests/registry/npm/ansi-styles/registry.json index 371cbc635e..702510b501 100644 --- a/tests/registry/npm/ansi-styles/registry.json +++ b/tests/registry/npm/ansi-styles/registry.json @@ -1 +1,120 @@ -{"_id":"ansi-styles","_rev":"85-df2abb99eac01aea4e413fba47935fd1","name":"ansi-styles","description":"ANSI escape codes for styling strings in the terminal","dist-tags":{"latest":"6.1.0"},"versions":{"0.1.0":{"name":"ansi-styles","version":"0.1.0","description":"ANSI escape codes for colorizing strings in the terminal","keywords":["ansi","styles","color","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256"],"homepage":"https://github.com/sindresorhus/ansi-styles","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"main":"ansi-styles.js","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles.git"},"scripts":{"test":"mocha"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"licenses":[{"type":"MIT"}],"files":["ansi-styles.js"],"_id":"ansi-styles@0.1.0","dist":{"shasum":"af63b736c8b14c5dc94af0f3818da822527c10c8","tarball":"http://localhost:4260/ansi-styles/ansi-styles-0.1.0.tgz","integrity":"sha512-S9N78mUU/qZFid8TNkgVFh796qnswzr+ho+GYuf3/3afqUTKlGKe/qN+2j7udlrbqjsrZGkrj+UCEvrRFeStfg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRYgVTGvHrIq7Og4UBJYQvYKR3eDSnjcRMd19ES3jM5AIhAMb68zN8K9psZcQu+4Of1EI5OuSWkVyg9NjCjob0B2Ev"}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.1.1":{"name":"ansi-styles","version":"0.1.1","description":"ANSI escape codes for colorizing strings in the terminal","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/ansi-styles","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["ansi-styles.js"],"main":"ansi-styles","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles.git"},"scripts":{"test":"mocha"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"ansi-styles@0.1.1","dist":{"shasum":"8f1618d24da7072a436f66b79c65385d7c1fe9cf","tarball":"http://localhost:4260/ansi-styles/ansi-styles-0.1.1.tgz","integrity":"sha512-vMKHQSsNruuO1fgtMI/I9Gc7jP3tXnv2QurI7L6QXZN3BmHsEhtd7TVy7qDzUpuRKaUxtpUlBrek5ZhhkBbLhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC0aJgfyP96hNCjr5FEK4lBaTSkBo0O9QC7WOwAmz9amAiAWWN0XcTm4Wwpf9Pq/d1yOiNOHmpeNCCyodoI+e5HTJQ=="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.1.2":{"name":"ansi-styles","version":"0.1.2","description":"ANSI escape codes for colorizing strings in the terminal","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/ansi-styles","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["ansi-styles.js"],"main":"ansi-styles","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles.git"},"scripts":{"test":"mocha"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"ansi-styles@0.1.2","dist":{"shasum":"5bab27c2e0bbe944ee42057cf23adee970abc7c6","tarball":"http://localhost:4260/ansi-styles/ansi-styles-0.1.2.tgz","integrity":"sha512-67aDATkGbpDcNIRjTtfPOGbQUepitKL7Kesl7SS72wV1FLvYEpLYXYFGcWHlhvB18uIoHZAHxmjfsckNMVckNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAYttKopZ01JcjHhAIuitbV9MIUT+7TadkfGDghx50pyAiEA6Ike4TLijzKRDfP/zk+OZt3LdOHZJ5V8s/nZ9mTdNwU="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.2.0":{"name":"ansi-styles","version":"0.2.0","description":"ANSI escape codes for colorizing strings in the terminal","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/ansi-styles","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["ansi-styles.js"],"main":"ansi-styles","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles.git"},"scripts":{"test":"mocha"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"ansi-styles@0.2.0","dist":{"shasum":"359ab4b15dcd64ba6d74734b72c36360a9af2c19","tarball":"http://localhost:4260/ansi-styles/ansi-styles-0.2.0.tgz","integrity":"sha512-YyQBeLj0juxUC9uUXRpQ1ZAzPT1dnsn5vVeJLHYFq4Ct1p0rymUSyvckKCXCH9I0bh3jWDIETA5nXIaZVKlDyA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDmNRO4MgROcKCKyr+cHP2poBC9LE+EWT2G0ttJPsuINAiEA0ZZl7LBgb+Gl/Swo9oTRJ0bLUVCCbEIc/jt0jTAa84o="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"1.0.0":{"name":"ansi-styles","version":"1.0.0","description":"ANSI escape codes for colorizing strings in the terminal","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/ansi-styles","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["ansi-styles.js"],"main":"ansi-styles","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles.git"},"scripts":{"test":"mocha"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"ansi-styles@1.0.0","dist":{"shasum":"cb102df1c56f5123eab8b67cd7b98027a0279178","tarball":"http://localhost:4260/ansi-styles/ansi-styles-1.0.0.tgz","integrity":"sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCawl5mLAJ0kVnzqZ+AxQtfHi4mOr1xRkHULZxOLezqyAIgVpf3/aQ57vPJGxSxP7Kkc/xgSuKA9y6ZEDR2QaLsVCk="}]},"_from":".","_npmVersion":"1.3.15","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"1.1.0":{"name":"ansi-styles","version":"1.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/ansi-styles"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"homepage":"https://github.com/sindresorhus/ansi-styles","_id":"ansi-styles@1.1.0","_shasum":"eaecbf66cd706882760b2f4691582b8f55d7a7de","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"eaecbf66cd706882760b2f4691582b8f55d7a7de","tarball":"http://localhost:4260/ansi-styles/ansi-styles-1.1.0.tgz","integrity":"sha512-f2PKUkN5QngiSemowa6Mrk9MPCdtFiOSmibjZ+j1qhLGHHYsqZwmBMRF3IRMVXo8sybDqx2fJl2d/8OphBoWkA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEPU864OQp7DgSU9AXNpOHK4yAAWvI99UMCEgxmBElSDAiBvIO9ty4uAsAha+OtYj48TQmtWVMraNRhn1o/CWmCYPA=="}]},"directories":{}},"2.0.0":{"name":"ansi-styles","version":"2.0.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/ansi-styles"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"mocha":"*"},"gitHead":"8c71708c951ab5ba824487c67053fb8f1eb8b6ea","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"homepage":"https://github.com/sindresorhus/ansi-styles","_id":"ansi-styles@2.0.0","_shasum":"432b26162fea1b63c878896abc8cc5548f25063e","_from":".","_npmVersion":"2.1.5","_nodeVersion":"0.10.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"dist":{"shasum":"432b26162fea1b63c878896abc8cc5548f25063e","tarball":"http://localhost:4260/ansi-styles/ansi-styles-2.0.0.tgz","integrity":"sha512-0kjBHdIQSa1iuh2rs8Md1GQNHAKrefcRSp2W5OKQU1oBZgCSqQ5aG4o+r69irBlhIPwA8wUaPdN/FWZVIHW7rA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAQocR+KZqHu8RDVGjRE37tTHS3T72Ek/ZIq0DGr6mHAAiEAiUrPvGxFbeLDC2FzpTnoNLj4TS/j6wVExRbIrvmhnfA="}]},"directories":{}},"2.0.1":{"name":"ansi-styles","version":"2.0.1","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/ansi-styles"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"mocha":"*"},"gitHead":"da6541334e1681cb803f891fab8abf4313cc4bc1","bugs":{"url":"https://github.com/sindresorhus/ansi-styles/issues"},"homepage":"https://github.com/sindresorhus/ansi-styles","_id":"ansi-styles@2.0.1","_shasum":"b033f57f93e2d28adeb8bc11138fa13da0fd20a3","_from":".","_npmVersion":"2.1.16","_nodeVersion":"0.10.35","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"b033f57f93e2d28adeb8bc11138fa13da0fd20a3","tarball":"http://localhost:4260/ansi-styles/ansi-styles-2.0.1.tgz","integrity":"sha512-0zjsXMhnTibRx8YrLgLKb5NvWEcHN/OZEe1NzR8VVrEM6xr7/NyLsoMVelAhaoJhOtpuexaeRGD8MF8Z64+9LQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChftvoE6wbxVGq0kMFSRJ57gEJivQWQot37JjthUMDTwIgQ2dCpoKN2KaHU199TIT0TwKY8iq5E+2DMhc8BCMLETc="}]},"directories":{}},"2.1.0":{"name":"ansi-styles","version":"2.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"https://github.com/chalk/ansi-styles"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"mocha":"*"},"gitHead":"18421cbe4a2d93359ec2599a894f704be126d066","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles","_id":"ansi-styles@2.1.0","_shasum":"990f747146927b559a932bf92959163d60c0d0e2","_from":".","_npmVersion":"2.10.1","_nodeVersion":"0.12.4","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"990f747146927b559a932bf92959163d60c0d0e2","tarball":"http://localhost:4260/ansi-styles/ansi-styles-2.1.0.tgz","integrity":"sha512-qGfeDJjjwuLKKzFsdbYhnbn4Hqxkel6cSzdCP5IYmT38eIzVxGCzcOceJNkMG0sD5QMFz8SauI5Y+5lwcgHIgA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnpdD9hdGQmkMQsctjPHrYOBsZbJlYQEQlBynDrjzttwIhAL9c10O5YhEm+f298qUg4MbjskTJqZZo3V/etfLTmKqe"}]},"directories":{}},"2.2.1":{"name":"ansi-styles","version":"2.2.1","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"mocha":"*"},"gitHead":"95c59b23be760108b6530ca1c89477c21b258032","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@2.2.1","_shasum":"b432dd3358b634cf75e1e4664368240533c1ddbe","_from":".","_npmVersion":"3.8.3","_nodeVersion":"4.3.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"b432dd3358b634cf75e1e4664368240533c1ddbe","tarball":"http://localhost:4260/ansi-styles/ansi-styles-2.2.1.tgz","integrity":"sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHh2prCFZwahuHtzuSo2pE6Elj1AIQNKWAWw/ytmkefPAiB7JVjhCZ4tsZHwfaY1RsB9VMESxoHT5bB3pJnXphgr1w=="}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/ansi-styles-2.2.1.tgz_1459197317833_0.9694824463222176"},"directories":{}},"3.0.0":{"name":"ansi-styles","version":"3.0.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=4"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^1.0.0"},"devDependencies":{"ava":"*","xo":"*"},"xo":{"esnext":true},"gitHead":"a80f4c8d155dc6d2c90c0a790ce2dc2e60e6defb","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@3.0.0","_shasum":"5404e93a544c4fec7f048262977bebfe3155e0c1","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"5404e93a544c4fec7f048262977bebfe3155e0c1","tarball":"http://localhost:4260/ansi-styles/ansi-styles-3.0.0.tgz","integrity":"sha512-caosO5GROQ6HZCO0PCuqFmKb0g2ow+7fvz60N3/A3ggyeDnFvLjW8mLR84eK/6hsh206bSm3s3j34bLKJPcnLw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7venaNuAJCBsAVEI6opbc2mQTvo4N7tj851qo7NSfjQIgPAoAAOgf5TSENXsBNXu/EWbcWH/RTVxSfjjEkU0EdMo="}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/ansi-styles-3.0.0.tgz_1484644594587_0.7388329922687262"},"directories":{}},"3.1.0":{"name":"ansi-styles","version":"3.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"maintainers":[{"name":"dthree","email":"threedeecee@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=4"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^1.0.0"},"devDependencies":{"ava":"*","babel-polyfill":"^6.23.0","xo":"*"},"ava":{"require":"babel-polyfill"},"gitHead":"a8f7d0f353eca6d67bad277b6437860fbc0d007e","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@3.1.0","_shasum":"09c202d5c917ec23188caa5c9cb9179cd9547750","_from":".","_npmVersion":"4.6.1","_nodeVersion":"8.0.0","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"09c202d5c917ec23188caa5c9cb9179cd9547750","tarball":"http://localhost:4260/ansi-styles/ansi-styles-3.1.0.tgz","integrity":"sha512-1jXmDD7l38qjk7yqmpFMLvs94InTmzcupUKdP2N4YjuDy5gNRJc1J5zb3Q/ur6FKxep0GW+2vK2qL82GEAwwCQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC3/FMTqAa8GlPUV9SltNHfSTEI+sFS7rBs7CktE8w4mgIgVq1rpKXapuJpfjcI71B0iVM0UfA9vP8CAx73YK33Cdc="}]},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles-3.1.0.tgz_1497307320106_0.3296520886942744"},"directories":{}},"3.2.0":{"name":"ansi-styles","version":"3.2.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^1.9.0"},"devDependencies":{"ava":"*","babel-polyfill":"^6.23.0","xo":"*"},"ava":{"require":"babel-polyfill"},"gitHead":"3340c4d536078a51fd7b5049e939c43c5ab05db3","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@3.2.0","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==","shasum":"c159b8d5be0f9e5a6f346dab94f16ce022161b88","tarball":"http://localhost:4260/ansi-styles/ansi-styles-3.2.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEuVVC7x7QVA3wcmy6N5R/FvCl85Kz2GXjgJ8iw0P54HAiAK+/bvLwH/Q6HoglnG5DWDc+sFxxWUBVFyGfw5f+jilw=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles-3.2.0.tgz_1500809147099_0.7141686324030161"},"directories":{}},"3.2.1":{"name":"ansi-styles","version":"3.2.1","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"files":["index.js"],"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^1.9.0"},"devDependencies":{"ava":"*","babel-polyfill":"^6.23.0","svg-term-cli":"^2.1.1","xo":"*"},"ava":{"require":"babel-polyfill"},"gitHead":"de7527a86c1cf49906b0eb32a0de1402d849ccc2","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@3.2.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==","shasum":"41fbb20243e50b12be0f04b8dedbf07520ce841d","tarball":"http://localhost:4260/ansi-styles/ansi-styles-3.2.1.tgz","fileCount":4,"unpackedSize":9371,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkgSQy8Rtz7ooK6YW4Ptv5DKKpVxfmHmDkkzGYJL60BgIhAKXrz0azsciFr39Mrox8mFpX1zJdBJqXh/L7EHzl6Hp9"}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_3.2.1_1519983600652_0.7656433427334486"},"_hasShrinkwrap":false},"4.0.0":{"name":"ansi-styles","version":"4.0.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^2.0.0"},"devDependencies":{"ava":"^1.4.1","svg-term-cli":"^2.1.1","xo":"^0.24.0"},"gitHead":"3df6a798ff5a86fed4e93d638a0d8525056e684d","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@4.0.0","_nodeVersion":"8.16.0","_npmVersion":"6.9.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA==","shasum":"f6b84e8fc97ea7add7a53b7530ef28f3fde0e048","tarball":"http://localhost:4260/ansi-styles/ansi-styles-4.0.0.tgz","fileCount":4,"unpackedSize":9741,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc8NNCCRA9TVsSAnZWagAAAiQP/2a4KgMz9t4UZBR03CNL\n635U+8tvDW8ihbpL5EGXWjsK4E9WWqjAkTTcP2J/eekN7qCR3MGek0Y1UFJp\nTD3M2wHb3UQrYwBTxSJ61mLR5QpvdXl3q6z1KZ1cZ364D0jWElWaYYiXhNjI\ntm8r5r6ygEbEqAv0FU6U+Dckw/k0++a6KavCa0NBqNXfqrjVNAndtjIJkARg\nwo8hmb2LiqGGqcgFRiqmESNro5+YLa/ictECH8e8RYWWFRe2UiyH8KQPQXnE\nip4ugr/ZbRxrYnbj962/Ctd1mALqeVW/mCSTP1nx70HIuBwfr9P/SjIdLbIG\nFb59gQRMlTgc4d7wmuUVyanhwuVLpZc/yTNfqbfQgDbJ9bZDoO5uKTVWzM+S\n8REx3CfRfAaJpaKjCJNrxhxZQcWdGzhMxhRhzeF3/lCvWkpv/+KyiSu/N32p\nU15+PuyJomZT8R6Kx/VJ/+dzUXCDiPsMgrTKz9+KpWOc6dRVExRKYnRgVCH2\n5Cmav2IVl4GOgM6nxeA4drZP4vR/jQdbjw4qtVbUuKXON1B1auRORDzLwub9\nZmVLXTtECJedZxWVHo0YMm8s5mnUzl+nGWPl/LMt1/MyRtxtCkh20TvV3jBo\n4s5FeioDeIKjw6nUCIraSCNQ0k73rxy/IsirJES4L3j8I8mcUrhuhn9BQmen\nXLdl\r\n=wntf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHDVmsP+iLomR9PHgNp87F1OgJgTzLkN5I6G0mi+CG+TAiBWwyB6i8uUBqTlO+DcrvRagk5SgylEoiHbWV689eETaA=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_4.0.0_1559286594221_0.9141286342597881"},"_hasShrinkwrap":false},"4.1.0":{"name":"ansi-styles","version":"4.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^2.0.1"},"devDependencies":{"ava":"^2.3.0","svg-term-cli":"^2.1.1","xo":"^0.24.0"},"gitHead":"18d3055ac5dab4c210534ce525d6493430d557d9","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@4.1.0","_nodeVersion":"10.16.0","_npmVersion":"6.10.3","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Qts4KCLKG+waHc9C4m07weIY8qyeixoS0h6RnbsNVD6Fw+pEZGW3vTyObL3WXpE09Mq4Oi7/lBEyLmOiLtlYWQ==","shasum":"d3ba8047b818293eaaa7978321dd61bff9842cfc","tarball":"http://localhost:4260/ansi-styles/ansi-styles-4.1.0.tgz","fileCount":4,"unpackedSize":10214,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXdVUCRA9TVsSAnZWagAAmDcP/A8BEtzFCQLnvUOFV+fH\nZXSwAW536SLJN5oq+1jToSQkG1lJA161YVCaxr0iaDxL8SbXIn9ZQ89+VBcZ\nH6hcIEku94U1++/omuF6Qh16v8DApAJZwhs4HCsrZlBkvVNT8UpPf3Rwc8tz\nwPoXaWFlm4hihJwPT8M2nuVyAnCDUQGaZBotXoYOknvl30RanjO9E9nTMtDF\nyJ/KjbETVK+5u6JESVq0KCIc3f60+lUPRzXCUYsV95+23J80/4z0fIjwgf1O\noZhHrfvp3wrrKqpaOZxXJPiySPsJ8nGQsFmgka/DWOxdKxymL25DrmhNKMNd\nFBYbRJBeDHWmISrFqpcFaBd9yf23EH9lDaU62NoJV1DPQfpZq3u/n5Cdq3Ic\nNY6sgSL2XLf6JwKU7NfZzSnmuHSc4/ln8EcmLAJewBVUPaIqFJrRxqNfoY2K\nDoIQzWOy379/LqIs1AOqw6V/jSCAttI0NZZvwUNdNAQA7qyKCN+DyW2/wC0N\n6VRfkQGAS3RJqIeiSeKd+i2joUFMrRbJz8mXB+grqKY3cqMratg8S+cpcfHv\nPeGITPGIgcmTVcP92MC2ytpVmyL0PNbzT/scBEPUYdvhyuFumuHeUK/ul1ms\naG2NMpXfU8f9w/VHzqk7dCzwHtPrz61sAxpCmS3+DUBpKz9Ip7iZZrXnbb/F\nkgmT\r\n=w4D6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPSCzwwFc12TT7uJHAYs4+MbNcIZjZgHEq2cmXWtiR8gIga1KkiCj+QInHbGViQlOO4TeoI9592Kr8m5TmOtOkxlw="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_4.1.0_1566430547434_0.3073668474671494"},"_hasShrinkwrap":false},"4.2.0":{"name":"ansi-styles","version":"4.2.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"@types/color-name":"^1.1.1","color-convert":"^2.0.1"},"devDependencies":{"@types/color-convert":"^1.9.0","ava":"^2.3.0","svg-term-cli":"^2.1.1","tsd":"^0.10.0","xo":"^0.25.3"},"gitHead":"6d1245dee68379d261d358cb46f8f7669218b04f","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@4.2.0","_nodeVersion":"12.13.0","_npmVersion":"6.12.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==","shasum":"5681f0dcf7ae5880a7841d8831c4724ed9cc0172","tarball":"http://localhost:4260/ansi-styles/ansi-styles-4.2.0.tgz","fileCount":5,"unpackedSize":14675,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdypVlCRA9TVsSAnZWagAAngEP+wZkQrJHApsbLoyRRtDt\nF4MXBartHNDHjhH/k1n/+GhMoPVsRWvgS0BOXmfTCeR7FXDzbdWVpdmdOTJO\n6cJ/XHV95wrVsJYCbXZrSpm4if5J8VH70k14tAvxgYdkCPXySyIqrctzZYcK\nTas/e4IAMGfOVZ+LsmPsriuEJQwuc+cttgNcb7PII5Mb8mMSETRvRlF7RysB\nkXjiCtcGhLCazcSIyUiqtTVFL2C855h4q1vrRFXV86H+tI8DMdiKl92xgWDg\n7MajHwSXQF0mduwrdOpZhQVQXYcFCqvxzFNr9Y7izX6m6LqoiMKrbxZ08hGV\nJvRPJzOaMzTwiuWLA2rdsxePkCpA76qQWtxHwfVabYVdfIoCGAVMVejPt9A2\nsoVV48YcfTu9Q3AQArJ8tcZiGRgybXRS7mTbazGUnjn/VKfiK/npVcN8xzLH\njDjDgmqfokSp5JonfPYGFQQLWe7HyCC5zm/6lv8H1/kyfuBa8g78e6ZW1CBx\nBpQ7WHNxqhhbMdPsuufUp67ojMOz3G4JXpb88ewfxovSJVFf2+JPIkKeeCDJ\n1U7SvvU3hc7dkUWhMWxsjKiDnGyE0rEcfD1gVGlVVSGWhhE3hGI3Sur4VzTp\ni7Tty9qpnEIgROqXhnFT44FFWKQDDaK1t1K3HQFx6QhEfVq484Uhvjk9JNoG\nEreL\r\n=cINu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWPGPfokXrboheH0p6/o4aKx/R7ilwx4emHpfzRX2aegIgBkXGH6Wq2Yvx4nQHi2K6meOO+ZCZvtusQ70mSWTdAUg="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_4.2.0_1573557604896_0.04368984078174476"},"_hasShrinkwrap":false},"4.2.1":{"name":"ansi-styles","version":"4.2.1","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"@types/color-name":"^1.1.1","color-convert":"^2.0.1"},"devDependencies":{"@types/color-convert":"^1.9.0","ava":"^2.3.0","svg-term-cli":"^2.1.1","tsd":"^0.11.0","xo":"^0.25.3"},"gitHead":"74d421cf32342ac6ec7b507bd903a9e1105f74d7","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@4.2.1","_nodeVersion":"10.17.0","_npmVersion":"6.13.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==","shasum":"90ae75c424d008d2624c5bf29ead3177ebfcf359","tarball":"http://localhost:4260/ansi-styles/ansi-styles-4.2.1.tgz","fileCount":5,"unpackedSize":14729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeDOG3CRA9TVsSAnZWagAAszAP/2sW6WnLJ1UrghYkSdNT\nxbvlislTDp3antpvGjow1CkHkptklTWjZBMtp8zfrhAZat52Q3wKRrYUpOyK\nNw1eihJGgsSWwIcEX6jS0WBFMOBIvM9i5VRJ79Iwm5F9oVJ0z4aPQkQ+eUJb\nVYjjPQp/LukjvyzwjsZXxHFVuJ3u9k5EoX2q9QGOII7R7jE+M8pSunbuJcWK\nYDnbavJl7WeVd1+9QT5SuyUt59HO0WEZ9eoCkVO2ooLluyFbXZvi6ZDnURgN\n2Fjipox7lMUitDM0/UngYPmDNeGbtfi8zyYtCFRbyGUKQSgzXtYsD7+58Xtu\nH/3vzKbQvABRaRhX6laYiCSe7pV+pOi2rpnPoUAPjdhSkXZF4yLL0DLprrag\nCVBv02fVCagNGmKN9c1JQif7ACCPUEfz+jAClklsUpTY+OLfuYbaYPsJ0WKB\nuE1qZh8Sr9dgqBuK9ASot6BLJcf31Qv0SPmBszFAmdLmt7ozk4AxBZ4dkxpN\n4b59DDkW/yOyVWPxT7B5ZadYUaItTO+ucPp1WYuN/3j71nHEWf2Pcm0JqJTY\nBQy5KNr10nAeTsmNC7+xBllPeHeXM2mJ3GoT6UBQDfY8g0xvvmjU5jgDoQ4m\nUYVmjE06AsQXxXHxBSJzmSabLjQLxQy7E5GP70L8rfUjRSTq/JjpMMgYDfYe\nWZ1u\r\n=wfZo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGeqlsZwnvqwtiKne8fqCS9cl7q3VmiJBUSXTNf4l1N2AiBpOVQvZCoLNQZIN0dSyLzBvVlPuwoItSiuk5lRbelyTg=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_4.2.1_1577902519016_0.16811694192100912"},"_hasShrinkwrap":false},"4.3.0":{"name":"ansi-styles","version":"4.3.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=8"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"color-convert":"^2.0.1"},"devDependencies":{"@types/color-convert":"^1.9.0","ava":"^2.3.0","svg-term-cli":"^2.1.1","tsd":"^0.11.0","xo":"^0.25.3"},"gitHead":"2d02d5bd070f733179007f0904eb5fb41090395a","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@4.3.0","_nodeVersion":"14.11.0","_npmVersion":"6.14.8","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==","shasum":"edd803628ae71c04c85ae7a0906edad34b648937","tarball":"http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz","fileCount":5,"unpackedSize":16978,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfeiACCRA9TVsSAnZWagAA5ccP/0DWoQsxVaTeYJuAyJlY\nPaf8cCbWwUQ6ZqFPreR4yYM+mpnSLnSlo8zqctIMofG63LIic4Co358CXP8v\nv9kvZYChYKZHcW7mxzIBUklWHRlrfDfVJSHhFiyAFHAu2X0hw70CZaZEXSGK\n0BiutHMjskT2GCSkheHBtj9g1OICvGFAP3wx1RasvYH7qhXBVFFCC/3Ci/c3\ne58izr3ivXcnOwqyC1ZlFNmL0rsgt91JtMY/7dcm/TouDpwrlO2BVGgJbD0L\nAu+jvjQnBjbjQlxskuS8mu69VvovP3lauf6YP0oeRdX2/UqY8J65/eDc1MN3\nBBcD8S98VglpGM/RGJmpUlCaoWfoz7yN9YyJk6mV/+wOSS2KRhmaiPXws9xY\nXAVdgFrK2cp1qR9RhOhmNng02WCZ3i7oh/1Pvp1DWCgDtASz5YOlT6ikvyHG\nCvqs3m7vkkhrnaEK68soPmbG2Q3O92wwINk7tX4WjH8TyqBaDbu8Z6t9NOwU\noW/v+A1gxWlrtl5eqOaMxo7XYxiF9YZzWWfzk1t6bl1rPICtYVRx2fn/3qqR\n0VRmR3DulMxsyx7ZwW1C210MbuuiRrDMIJZsg/kvuaLWOmh1US+rHa1YrD6g\n8pmirVpcxxBp1Pj44ZjM7W4X6MaboTHHNiE6dtJdJdZrO66hQnB4Bu25w9uX\n10be\r\n=uXWi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiWmk7MXmf0ZVnUHbCbR2mb9eLfmcN5XoDJMyjv/VX/QIgKOsdyMm5gXdutN1mR1lRxBc/muUtoCWbdoL3I/e7TB4="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_4.3.0_1601839105748_0.2212872458771633"},"_hasShrinkwrap":false},"5.0.0":{"name":"ansi-styles","version":"5.0.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"@types/color-convert":"^1.9.0","ava":"^2.3.0","svg-term-cli":"^2.1.1","tsd":"^0.11.0","xo":"^0.25.3"},"gitHead":"94ab248a83af375cf2179adce343df89daa25da0","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@5.0.0","_nodeVersion":"10.22.1","_npmVersion":"6.14.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-6564t0m0fuQMnockqBv7wJxo9T5C2V9JpYXyNScfRDPVLusOQQhkpMGrFC17QbiolraQ1sMXX+Y5nJpjqozL4g==","shasum":"675dbbb5ca1908fa90abe4e5b1c2e9b1f4080d99","tarball":"http://localhost:4260/ansi-styles/ansi-styles-5.0.0.tgz","fileCount":5,"unpackedSize":13185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxbuRCRA9TVsSAnZWagAAxW4P/AhubyPwX7EZahWbqG8a\nry4Gr1H6qUSbzzLOxTLDTsxxjeKkodlzCic9zzN9qoy10mNw2bZwoOPDdMdB\n0pbSv2KDqf4BQ0bUFVcEYh9FWvAkdBi6W2rOD5qUmfl1KewnvkFt/nLrRl5K\nzZcQI26UTBEl45TwYnmU1PAMCLElGwzDPwKjT19IA9/8Zh54uipAgiB9ImQS\nUypHk2+lVOYFr4cseI6Qtx4YixKUDre+1BCGXzbBnnjyy37Ht2SUU4S/AdYT\nnuWZKU7HjKi311HuxIReLrqaZTCcPkxWgBUdbiazFGH3HQIJ5LQcMZbVi6N4\nBQU00K37u4/d/+yu0ESiKujDbR/3pgddGls9r1X6azcDuqXFUDQR2DGvc4n6\nx2HO3TIire41wxVrTwL4D7ZpSsw0fhHDqu26ppCbOAcj5NFuRidJx/NaHuKF\nZqX6Kl3VAB5bA51z7WM1FkiSewqhfM2m0MQ5kRAzCw5SSJA8s9qoDLTJ8GMW\nBu/jRoPCz6TzFfOeDx7mPfl7T0HadjfC2KtptMPwxm65sQ9W55n/BhX0w75m\ndsmd53mpT0gf5a8rRDayNsewf69eIlSDvvNt5EqUOw4RPL1xGODxwCJia/2Q\nN8JzLDFiFsvmJEVUszEuIqJCnBl4FlawWFehOvxSU1QWqzASzCNQLIQq6Ogk\naI1G\r\n=sA1I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA5mlOoFGX2ZzUw5XhEDdB+9D6d1BJLuk/E66YhwiT1EAiAgDEaQJ3WglYhB/sU8VyYsKP3wDJZFbWvf7QvdkdRLhQ=="}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_5.0.0_1606794128478_0.35759914215476774"},"_hasShrinkwrap":false},"5.1.0":{"name":"ansi-styles","version":"5.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"ava":"^2.4.0","svg-term-cli":"^2.1.1","tsd":"^0.14.0","xo":"^0.37.1"},"gitHead":"b890cf7edccf56215e5948d1cc385fa4e85a8969","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@5.1.0","_nodeVersion":"12.20.1","_npmVersion":"6.14.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-osxifZo3ar56+e8tdYreU6p8FZGciBHo5O0JoDAxMUqZuyNUb+yHEwYtJZ+Z32R459jEgtwVf1u8D7qYwU0l6w==","shasum":"a436bcc51d81f4fab5080b2ba94242e377c41573","tarball":"http://localhost:4260/ansi-styles/ansi-styles-5.1.0.tgz","fileCount":5,"unpackedSize":13405,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCuEfCRA9TVsSAnZWagAARQYP/j3jbwiknKp90fSTFkFL\nAhkP41N8y9cFUXbF4UTDj8oZ096xclr+Qg56EGV864kcp6x/IR5qTxDyLlUe\nhRzQ3ZtGECTr+XXXpULYg1c3TqJr3e7TaHy6onLsvNkgjLViKNvE2BxOxpnc\nWsQRbWF5ZcV4sURIzF7fQj6GArZsCbW8OaDdVKlBcNwNlysaeDXKEiY3cfLK\nPc3qhnXpjwP+br3OasE/YehDtj4OrXgKs5+0xx9S3nnUXfbsejG12a7oC2yZ\nEJNonvx+cbXYVHcL7WEhKp93PDreZLK3LsyDGVQusQcE78q/45sKxeeBsWtz\n9Th/s7TqRL/U8FubEotZl49zA4KPB6JAReFF9iUWxmx08f+pD1nae24T67dv\nVoGYC3c9UOWlgkccRebgGBzjqAnix3F5kz5zi9lLYrT3X3iSUfrjYN5ut/tc\nworOV2DpzmMFWolRpi2AslId4QxoAPM3VMsPfnINlPFDQkiWDBEkw8Ku/gad\np4j9FlTj/EUACT0SWADejY5ZWOI9t2Oj/8xgR6/bCXuL2G8i+9GAuE/BGFPc\njps+07LWI5tZQHrw2wSC8PzrfXJUx6Dh5U/5yG3xHRt9BecdkvyYy9htFTws\n3gIlp26SNcjb0n67RWmo+VXaQ6lhKfx0Mhowvqhl9sbyq3ocB/dm5divBmyr\nCAp4\r\n=chND\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDidn/Opgn11OR6lqhNpD+/+bEocVmfd2JOmaTrL2MUoAIhAItZXfInKrm9Im8dt+G5r6PeQvu9aa292/TBdtjrPWc9"}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_5.1.0_1611325727047_0.2908627011479632"},"_hasShrinkwrap":false},"5.2.0":{"name":"ansi-styles","version":"5.2.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"ava":"^2.4.0","svg-term-cli":"^2.1.1","tsd":"^0.14.0","xo":"^0.37.1"},"gitHead":"4d30b90085fb5a971d7cb0f4dca0920ff4dbc955","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@5.2.0","_nodeVersion":"12.20.1","_npmVersion":"6.14.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==","shasum":"07449690ad45777d1924ac2abb2fc8895dba836b","tarball":"http://localhost:4260/ansi-styles/ansi-styles-5.2.0.tgz","fileCount":5,"unpackedSize":13596,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZCGXCRA9TVsSAnZWagAAIY4QAJ2NcJU7iCjOGPSivrMO\nHSYzm0/3P/LFJMFFv30TB0yX91UxgfFBRV+01o0ksBdK+wzXxYgNF7dbSqGq\n2ulEdYkdIjzrH+E+yfOZ26iArGFlvYimSBDMNq3HS4V6rKU4ZIVXbCd/J2wc\nFCq4wmsyWSp05Ea74BP/iczmC1v2OGNfGM5qrqkpfbJ6/OtvL9dyfhbtBl90\nnhwmCN0OlCvRxkZllnnDyM1nUAx+1E3U270e0R+qUayC34+DWcjVsg13Bu9M\niHkN8pOrV5TCvBGSGyDFG1IvCzrV36r7eGttAs6lRXgW5dzUclmYjnTFbgm0\n9CdgJ0ovDvrbqfvAWyr4BIGuqzEKRtIwxnZlbpvx/1b6vT7+qKMaZW6R3ETf\nmI7ppshymh8Kefs4g5EPrNTp9S4qHPwigEjD1dEy+Rikl8ptmrhkwnk3KQ8c\nwRycjc+a3a+8fF1OW58yr2BOpZ+gcYyonbi/4OWjO0k0NvrfE0+RRrf2hO+o\n6ubsA5ttHeiDvEVxDNC6DJEVOKxd/QH6afDyT4Fuc9wy61wI2ukm36Vi/RS0\n82xqllSSkMvP9RvIvqLMtcZLV8z4zRauBMEnV69WHRNEpifL4QMqatfWHS6U\n14V3Njnql9MeFcZtUtcVd7OKkxaER54rlDBWMGkQkIBhOTA+IChBooqdl2M2\nMhG8\r\n=OR+b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAND+m0Vl7hjZGBFTXuRx5O/TtwhyoDZvIQUhTS4uy1AAiBLOZwjRapi08CEyjcH210r2J7cetSsgdiuHGG1bY1XYw=="}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_5.2.0_1617174934592_0.8102256934313619"},"_hasShrinkwrap":false},"6.0.0":{"name":"ansi-styles","version":"6.0.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"type":"module","exports":"./index.js","engines":{"node":">=12"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"ava":"^3.15.0","svg-term-cli":"^2.1.1","tsd":"^0.14.0","xo":"^0.38.2"},"gitHead":"b566b5ba72df29dc2896db5b4f9bcd1e40789eb2","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@6.0.0","_nodeVersion":"14.16.1","_npmVersion":"6.14.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-4nUCKPhvbhgqc4a1S0w446veDod0i6krCOMF/bPBbBq9eP11BKztPS4Mp5yxUXhr1PFEe6mYcUSAv1jfoMUuOg==","shasum":"2dc5d239631857256fcc501cf052135f290e25b3","tarball":"http://localhost:4260/ansi-styles/ansi-styles-6.0.0.tgz","fileCount":5,"unpackedSize":13494,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgeSS7CRA9TVsSAnZWagAAuJMP/0tEVLWMX5qZbn8X7a4Q\nvKtHQLB8UzaNAqHF3xbdBOGUIIgQub3g+hInvAEZQVjWKBzYvq1MNiveNKWR\nsHMHAIVFQQznBsEFNKV0EflrYFgSwoXfkTVgJqBfnQKHNvelsRUpHDpPvGCu\nfSC5NN+bJCIOzZZAjqeOBntApG0RmCiinyLyJsa6X99tAaMssvWmYSgfztjQ\njwstpLdWTqu0/5qW5ibcj8Oiy4f6ywRKxLju3WB4QaABb75kstIIpRWCD3vw\naUFD+L6/jJPsJJRajpSYWiF6HYQ4rignq6yVdLeaNm8rOySQRh39Qd/3qCkQ\nvsjwuOZ5zuy5d+Ug71qqjhu8P70mhswf/cbhQigyRtCM0zgkgaCkN9BOC49D\nuT4wuzfCDuejezqg2H/ToGPwbqUtfm5p7Dmnd0CnSp0ypyvy4ph/8WFnZag9\nC+KCJCGgSSX7dvb1P9+9ayd8gY6BTE5Mdrcny9S8nQlM/XKuWJhxRI0lwGRW\nVdZdlIfcF8MyqKjl2V/EcsR1aCASMTFUm2Eaj51VGWSOCPqHwb3/epGcIc4F\ncY5y+/hBAAX80HA8md5pndff9RN2AO2x1U56I3mLx6ouKtTfTvalJYW6pjSY\n4ZcfQGyYFxbe0Ua+fYhuVgnQ2DZy5IlhyBJ8D5T0PlOogB81w1Rp9+hj1V+U\n1LxA\r\n=E3cP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFY7x9WkaANBcYZGRYsDJOqWlY74Sa2YzsmucDlQRgh9AiBOe/B4LIsgUCeWV4FGK7bumheht1Y6J3U9z21PkvTzwQ=="}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_6.0.0_1618551995229_0.7726601134349003"},"_hasShrinkwrap":false},"6.1.0":{"name":"ansi-styles","version":"6.1.0","description":"ANSI escape codes for styling strings in the terminal","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"funding":"https://github.com/chalk/ansi-styles?sponsor=1","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"type":"module","exports":"./index.js","engines":{"node":">=12"},"scripts":{"test":"xo && ava && tsd","screenshot":"svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"},"keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"devDependencies":{"ava":"^3.15.0","svg-term-cli":"^2.1.1","tsd":"^0.14.0","xo":"^0.38.2"},"gitHead":"cd0b0cb59337bfd7d3669b2d0fcde7ff661a83a6","bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"homepage":"https://github.com/chalk/ansi-styles#readme","_id":"ansi-styles@6.1.0","_nodeVersion":"12.22.1","_npmVersion":"6.14.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==","shasum":"87313c102b8118abd57371afab34618bf7350ed3","tarball":"http://localhost:4260/ansi-styles/ansi-styles-6.1.0.tgz","fileCount":5,"unpackedSize":15535,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgf+daCRA9TVsSAnZWagAAQOIP/Anx6U+vOfkg1KDr5iZJ\nmkSxedAzNH3576oI9roh7wbQSQ/fQGN/jaY0npudzvsa/NLfWuCQCt00dtQ/\nAyKY5NLtfb5VejLgIF8AF1CtJOHA88TY+aRoA+hL+eUA1PkOY9Y+1lV9U1QO\nJaUVlLQr/FIzY21pSYo6+V0lLmPGgMIs/ULdjpr2X5dZ+7Ff2DzrsQtQV2k9\nAc0G2XQRyp/NTDHCHnfOSnK9zKuFhjY2sjbNn0Gp9r3T7hTcopKqPz6FhIKY\nAUo9rqswIvAYXDEAXCoGWzJoiRsDldxTkf+mb9RV9e2jAUsGAfvJLXntizp3\n7tvMEYINoHPzs4CvRqcYonYeY7FREhTWaaNTxQzy/Ae1mARAmlIl0vXuZifP\nfglSd6wrqcz4euaOc3YRkW9eT+9q4cK7JCjyssc4vdHBMn2Yd5+A4hTn51AB\n5I9QJ8Xc0nWy712korCpcR9cPXrwve50pD2AxEinp+hyQzpPzzKyfDQHwjpe\nVbTu8/aAhDK1s19qFmUY4VtUqS1Uu8NjXpaWOlpdD4BI+dh43tsmSz61RWfJ\nhDIC39htWlyhlak1mCBQIFlGTZPr7GkEeNbZLW8MCpnfgXp7Lcv3Konzm/C+\nrsQw6XBGf4O9Tp25Q0EFyl8uaNb3wOXgSCpUydBe2DFtJWpTHGIX8L9nuVUQ\n5e9Z\r\n=m2Tr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCA/tHV/Ykpiby73wpS1NtBNs2fJbTeFyJQgDAmuDFbsQIgHtpoqyHPZTFeQ4S3cP52dKS24bMMNntxC5FqTsPsP1c="}]},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ansi-styles_6.1.0_1618995033909_0.3859516923978603"},"_hasShrinkwrap":false}},"readme":"# ansi-styles\n\n> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal\n\nYou probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.\n\n\n\n## Install\n\n```\n$ npm install ansi-styles\n```\n\n## Usage\n\n```js\nimport styles from 'ansi-styles';\n\nconsole.log(`${styles.green.open}Hello world!${styles.green.close}`);\n\n\n// Color conversion between 256/truecolor\n// NOTE: When converting from truecolor to 256 colors, the original color\n// may be degraded to fit the new color palette. This means terminals\n// that do not support 16 million colors will best-match the\n// original color.\nconsole.log(`${styles.color.ansi(styles.rgbToAnsi(199, 20, 250))}Hello World${styles.color.close}`)\nconsole.log(`${styles.color.ansi256(styles.rgbToAnsi256(199, 20, 250))}Hello World${styles.color.close}`)\nconsole.log(`${styles.color.ansi16m(...styles.hexToRgb('#abcdef'))}Hello World${styles.color.close}`)\n```\n\n## API\n\nEach style has an `open` and `close` property.\n\n## Styles\n\n### Modifiers\n\n- `reset`\n- `bold`\n- `dim`\n- `italic` *(Not widely supported)*\n- `underline`\n- `overline` *Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash.*\n- `inverse`\n- `hidden`\n- `strikethrough` *(Not widely supported)*\n\n### Colors\n\n- `black`\n- `red`\n- `green`\n- `yellow`\n- `blue`\n- `magenta`\n- `cyan`\n- `white`\n- `blackBright` (alias: `gray`, `grey`)\n- `redBright`\n- `greenBright`\n- `yellowBright`\n- `blueBright`\n- `magentaBright`\n- `cyanBright`\n- `whiteBright`\n\n### Background colors\n\n- `bgBlack`\n- `bgRed`\n- `bgGreen`\n- `bgYellow`\n- `bgBlue`\n- `bgMagenta`\n- `bgCyan`\n- `bgWhite`\n- `bgBlackBright` (alias: `bgGray`, `bgGrey`)\n- `bgRedBright`\n- `bgGreenBright`\n- `bgYellowBright`\n- `bgBlueBright`\n- `bgMagentaBright`\n- `bgCyanBright`\n- `bgWhiteBright`\n\n## Advanced usage\n\nBy default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.\n\n- `styles.modifier`\n- `styles.color`\n- `styles.bgColor`\n\n###### Example\n\n```js\nimport styles from 'ansi-styles';\n\nconsole.log(styles.color.green.open);\n```\n\nRaw escape codes (i.e. without the CSI escape prefix `\\u001B[` and render mode postfix `m`) are available under `styles.codes`, which returns a `Map` with the open codes as keys and close codes as values.\n\n###### Example\n\n```js\nimport styles from 'ansi-styles';\n\nconsole.log(styles.codes.get(36));\n//=> 39\n```\n\n## 16 / 256 / 16 million (TrueColor) support\n\n`ansi-styles` allows converting between various color formats and ANSI escapes, with support for 16, 256 and [16 million colors](https://gist.github.com/XVilka/8346728).\n\nThe following color spaces are supported:\n\n- `rgb`\n- `hex`\n- `ansi256`\n- `ansi`\n\nTo use these, call the associated conversion function with the intended output, for example:\n\n```js\nimport styles from 'ansi-styles';\n\nstyles.color.ansi(styles.rgbToAnsi(100, 200, 15)); // RGB to 16 color ansi foreground code\nstyles.bgColor.ansi(styles.hexToAnsi('#C0FFEE')); // HEX to 16 color ansi foreground code\n\nstyles.color.ansi256(styles.rgbToAnsi256(100, 200, 15)); // RGB to 256 color ansi foreground code\nstyles.bgColor.ansi256(styles.hexToAnsi256('#C0FFEE')); // HEX to 256 color ansi foreground code\n\nstyles.color.ansi16m(100, 200, 15); // RGB to 16 million color foreground code\nstyles.bgColor.ansi16m(...styles.hexToRgb('#C0FFEE')); // Hex (RGB) to 16 million color foreground code\n```\n\n## Related\n\n- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal\n\n## Maintainers\n\n- [Sindre Sorhus](https://github.com/sindresorhus)\n- [Josh Junon](https://github.com/qix-)\n\n## For enterprise\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"time":{"modified":"2022-06-13T03:05:27.416Z","created":"2013-07-31T23:00:29.145Z","0.1.0":"2013-07-31T23:00:32.552Z","0.1.1":"2013-08-03T00:31:59.821Z","0.1.2":"2013-08-03T01:38:52.766Z","0.2.0":"2013-08-03T16:40:58.340Z","1.0.0":"2013-12-08T00:00:09.315Z","1.1.0":"2014-06-03T23:35:17.884Z","2.0.0":"2014-11-23T11:52:58.607Z","2.0.1":"2015-02-22T09:21:36.085Z","2.1.0":"2015-07-01T13:26:31.005Z","2.2.0":"2016-02-21T12:27:55.984Z","2.2.1":"2016-03-28T20:35:18.267Z","3.0.0":"2017-01-17T09:16:34.807Z","3.1.0":"2017-06-12T22:42:00.220Z","3.2.0":"2017-07-23T11:25:48.038Z","3.2.1":"2018-03-02T09:40:00.702Z","4.0.0":"2019-05-31T07:09:54.329Z","4.1.0":"2019-08-21T23:35:47.551Z","4.2.0":"2019-11-12T11:20:05.018Z","4.2.1":"2020-01-01T18:15:19.134Z","4.3.0":"2020-10-04T19:18:25.986Z","5.0.0":"2020-12-01T03:42:08.629Z","5.1.0":"2021-01-22T14:28:47.169Z","5.2.0":"2021-03-31T07:15:34.766Z","6.0.0":"2021-04-16T05:46:35.357Z","6.1.0":"2021-04-21T08:50:34.094Z"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"repository":{"type":"git","url":"git+https://github.com/chalk/ansi-styles.git"},"users":{"passy":true,"tunnckocore":true,"gliviu":true,"operandom":true,"scottfreecode":true,"michalskuza":true,"usex":true,"houzhanfeng":true,"danielheene":true,"willwolffmyren":true,"denmasgeo":true},"homepage":"https://github.com/chalk/ansi-styles#readme","keywords":["ansi","styles","color","colour","colors","terminal","console","cli","string","tty","escape","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"bugs":{"url":"https://github.com/chalk/ansi-styles/issues"},"license":"MIT","readmeFilename":"readme.md"} +{ + "name": "ansi-styles", + "description": "ANSI escape codes for styling strings in the terminal", + "dist-tags": { + "latest": "6.1.0" + }, + "versions": { + "4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "description": "ANSI escape codes for styling strings in the terminal", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-styles.git" + }, + "funding": "https://github.com/chalk/ansi-styles?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd", + "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor" + }, + "dependencies": { + "color-convert": "^2.0.1" + }, + "devDependencies": { + "@types/color-convert": "^1.9.0", + "ava": "^2.3.0", + "svg-term-cli": "^2.1.1", + "tsd": "^0.11.0", + "xo": "^0.25.3" + }, + "gitHead": "2d02d5bd070f733179007f0904eb5fb41090395a", + "bugs": { + "url": "https://github.com/chalk/ansi-styles/issues" + }, + "_id": "ansi-styles@4.3.0", + "_nodeVersion": "14.11.0", + "_npmVersion": "6.14.8", + "dist": { + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "shasum": "edd803628ae71c04c85ae7a0906edad34b648937", + "tarball": "http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz", + "fileCount": 5, + "unpackedSize": 16978 + }, + "directories": {}, + "_hasShrinkwrap": false + }, + "6.1.0": { + "name": "ansi-styles", + "version": "6.1.0", + "description": "ANSI escape codes for styling strings in the terminal", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-styles.git" + }, + "funding": "https://github.com/chalk/ansi-styles?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "type": "module", + "exports": "./index.js", + "engines": { + "node": ">=12" + }, + "scripts": { + "test": "xo && ava && tsd", + "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor" + }, + "devDependencies": { + "ava": "^3.15.0", + "svg-term-cli": "^2.1.1", + "tsd": "^0.14.0", + "xo": "^0.38.2" + }, + "gitHead": "cd0b0cb59337bfd7d3669b2d0fcde7ff661a83a6", + "bugs": { + "url": "https://github.com/chalk/ansi-styles/issues" + }, + "_id": "ansi-styles@6.1.0", + "_nodeVersion": "12.22.1", + "_npmVersion": "6.14.10", + "dist": { + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "shasum": "87313c102b8118abd57371afab34618bf7350ed3", + "tarball": "http://localhost:4260/ansi-styles/ansi-styles-6.1.0.tgz", + "fileCount": 5, + "unpackedSize": 15535 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-styles.git" + }, + "homepage": "https://github.com/chalk/ansi-styles#readme", + "bugs": { + "url": "https://github.com/chalk/ansi-styles/issues" + }, + "license": "MIT", + "readmeFilename": "readme.md" +} diff --git a/tests/registry/npm/asn1/registry.json b/tests/registry/npm/asn1/registry.json index ee1492f644..3ebe655242 100644 --- a/tests/registry/npm/asn1/registry.json +++ b/tests/registry/npm/asn1/registry.json @@ -1 +1,67 @@ -{"_id":"asn1","_rev":"75-143f90f253e5b728d4ab7277916a22e7","name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","dist-tags":{"latest":"0.2.6"},"versions":{"0.1.0":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.0","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"engines":{"node":"~0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.0/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.0","_engineSupported":true,"_npmVersion":"1.0.15","_nodeVersion":"v0.4.9","_defaultsLoaded":true,"dist":{"shasum":"8618214ff5c0180807a885d9c1f3b67dc73e058f","tarball":"http://localhost:4260/asn1/asn1-0.1.0.tgz","integrity":"sha512-CuqJJHh/U5xQcoBHUK43DP7QpIu9ReEGxOtczPYloauyuCuoHL8zoc8CJiAY3BTpsdI8f1wnf5LIXJNXs6CfvA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+yXk7EQstKJQA6frPp4arFqVoBM+p41lVnCC+3sCbOAIgbFMDauBg831QWDn/9cI8mSKUZqOxyBLjr8wdT2D63Ig="}]},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.1":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.1","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":"~0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.1/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.1","_engineSupported":true,"_npmVersion":"1.0.15","_nodeVersion":"v0.4.9","_defaultsLoaded":true,"dist":{"shasum":"a63c6cc21cafa12ac05f5c3f61e6084566292aa2","tarball":"http://localhost:4260/asn1/asn1-0.1.1.tgz","integrity":"sha512-lyoOpJOrMArDiAHsgrepxQwgKIr69V1rRWf6dIUpW62QiUpYqBVfgmnGqONLNFL338bR2RiWM0dJvriGv0tsuQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEWnfKPDaiGdUkGQA36uUlBmETv3C21JGVRo4xIOymikAiBfzzH2EPRZ+WJ7XNtiA61jMO78iIbTels9CqccUrSVpQ=="}]},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.2":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.2","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":"~0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.2/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.2","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"ac835e89fed60d2909179f192295f36162e8c00a","tarball":"http://localhost:4260/asn1/asn1-0.1.2.tgz","integrity":"sha512-tggAehfGC/qeaUksXIbIVFInOATbzNp3vV7eGQu2XL61mBuu/lqWwGpEaa+Rh7rPZrC7gL8OztFL4AVxxdb/Kw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICOaU3ZJWmnqHC3Gr740FNcIWFErFJUJ/P3JiE433YzhAiEAixqbDDaapiISwGf9YnDOnGX8ZoCJgTCq+4owVMVtnZY="}]},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.3":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.3","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":"~0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.3/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.3","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"4bc56225d38f434d832582980bfc7f5e50bbb1c4","tarball":"http://localhost:4260/asn1/asn1-0.1.3.tgz","integrity":"sha512-GwaelydZhpPfIu5QJTxxvEA9JqqZW+953GFkvhRq1Pi4ilZlFi8xZN2olShGtAf7exJwDdRDVlNxrdEKI1Vsyg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVWNbJHtjJKr7ay+qbG2ncktGzzr8Li2tyKg4OmAC94wIhAPq0FhZ1XX9fJsLCc+gtEIwLu6lzLSe2wfHU2rgU1fmT"}]},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.4":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.4","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":"~0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.4/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.4","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"f1ea11165f132785bc040f8d4ed8333a84bddb14","tarball":"http://localhost:4260/asn1/asn1-0.1.4.tgz","integrity":"sha512-kIVN35vv2q8xxiyDc8jScwDHEyg719GwYE0fYuX6lkrlp+bK7fj1Dx+GZ1LCIExvYbMG3zVkETVNHUzPyyZjyA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC41mitkKWX52BAjKsQsH9nnRh6yyyWRMzcSbeMszECGAiBk1bVC9wjtC8trva25wW82y2EoFAgNI/LKMyV8RElGaA=="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"directories":{}},"0.1.5":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.5","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.5/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.5","_engineSupported":true,"_npmVersion":"1.0.22","_nodeVersion":"v0.5.3","_defaultsLoaded":true,"dist":{"shasum":"eb22776346f5b7583c227a2f74bb984133c83260","tarball":"http://localhost:4260/asn1/asn1-0.1.5.tgz","integrity":"sha512-0ckzK7DquXWnPyyVwOuOAXIJ9x/11BJEvDEG+Fl3I45DdafGyaFwzLh7NewytC70msFpZziQKyWDxl9j6iBjvw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAkaff99tB2i7xslqBJ1VO7DyTlsHJkCCD2vABhCVq8yAiBb5jPiI9CqngZa7mhvsKLVfycPLXAlbF3Kw1Ffu5uHmA=="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"directories":{}},"0.1.6":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.6","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.6/package/package.json","serverjs":false,"contributors":false,"wscript":false},"_id":"asn1@0.1.6","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"39f634ff13d942d9d922939a2742909233b84c78","tarball":"http://localhost:4260/asn1/asn1-0.1.6.tgz","integrity":"sha512-+vGj6Ju4zZXosrHAjxAzCmJFxgWD8ZKbkP+mIdKTAMVsW5q4TFb6Ma1KwdyPGwPTzNU4B5pi544PCpzi3KLLtQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBn/wWc1EwxQNwEpqEeq9cFiGgP42i7IgcgIZJytnECXAiBcZQfNW8mtDPpWta9AIGSwdkQjKAQIRn8HmVIdb69qFg=="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"directories":{}},"0.1.7":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.7","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmJsonOpts":{"file":"/Users/mark/.npm/asn1/0.1.7/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"asn1@0.1.7","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"68f70219ea9f57f035bc40507bfb30d14f0f2f62","tarball":"http://localhost:4260/asn1/asn1-0.1.7.tgz","integrity":"sha512-6gk/foyseu/GezFwctDxG8QCcCrWwnTAZ/eFslw9QqW9WUmv9NqPouhbef1P5fPc64g5uOB7rvP7AAY+PSBCBg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDCkx9MlyrAqM3FIP0uVNkusVOtdU1KmJLPKdJgFLomWAIhAK+NQzeGxmVR5FJ19JlQBsVSQM6cl6MtCkpnb9c920fS"}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"directories":{}},"0.1.8":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.8","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"_id":"asn1@0.1.8","_engineSupported":true,"_npmVersion":"1.0.104","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"9b0012d5469d70cb5516c84d4c5b772c1f1521de","tarball":"http://localhost:4260/asn1/asn1-0.1.8.tgz","integrity":"sha512-qOshoIVzsnZoukewbVy9SpeuipoIWYHsfJHnauk9/BML0co9JUeTldjL7upLt0M6mQiK6VJQfCzmk3A95fG+lQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCCng43kQt9TilEnkC0OZpDXxDsqva9YH61u/KYgYv6gIgK+0V99EaaDmq+vU0uBrxu8QBky6AQ9Fvi/CQpNOWVTA="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.9":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.9","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"~0.0.5"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"_id":"asn1@0.1.9","_engineSupported":true,"_npmVersion":"1.0.104","_nodeVersion":"v0.4.10","_defaultsLoaded":true,"dist":{"shasum":"d90236dce043ffa224b28f1aad4b6dfc78783a9c","tarball":"http://localhost:4260/asn1/asn1-0.1.9.tgz","integrity":"sha512-qxACMK7BkZzGpwHYiG84ToCPrIM086pGU3G2J6yxGQJleDesx5Va3iR2ewt2hhn7kBMeo6JdgYH8TfKO2/GaTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCosI84P79EqpEyQ7/P0j4WCzoU5IY0ZfSqT49aU4nDZQIgewX7gmwJ8f0upAQKf2vzWHchch0n/aEoXDCppPgLxIU="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.10":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.10","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"0.1.2"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"_id":"asn1@0.1.10","_engineSupported":true,"_npmVersion":"1.0.106","_nodeVersion":"v0.4.12","_defaultsLoaded":true,"dist":{"shasum":"27488f32749567e1e117a9764c70c76b053312e5","tarball":"http://localhost:4260/asn1/asn1-0.1.10.tgz","integrity":"sha512-Yl9tEdnmJkMjHHxegKMnsE9NzITZqZ+Au+w5wRc3Kjnpp80A5wA+daMddd/xKBd0i0ts/7do9CGD4OjJI5wCRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD26eZPr5rOdbueCJO6wd9WgydFdjnCdo3iIPKPX7E8hQIgPExp6FFqJNX3KPwzgF+w/RXl17bLsGXgXM+1v4aXEq0="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.1.11":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"contributors":[{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.1.11","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","engines":{"node":">=0.4.9"},"dependencies":{},"devDependencies":{"tap":"0.1.4"},"scripts":{"pretest":"which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi","test":"./node_modules/.bin/tap ./tst"},"_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"_id":"asn1@0.1.11","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"559be18376d08a4ec4dbe80877d27818639b2df7","tarball":"http://localhost:4260/asn1/asn1-0.1.11.tgz","integrity":"sha512-Fh9zh3G2mZ8qM/kwsiKwL2U2FmXxVsboP4x1mXjnhKHv3SmzaBZoYvxEQJz/YS2gnCgd8xlAVWcZnQyC9qZBsA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGUwI9IKQ/XsTnT2MoLpwthpwnk33C2h6Z2O4QEARNW+AiAEgsMjwbLwsSdJReqQyk9Pt5lxkXF7jxREAHR+SG7lHQ=="}]},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.2.0":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"contributors":[{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.0","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","dependencies":{},"devDependencies":{"tap":"0.4.8"},"scripts":{"test":"./node_modules/.bin/tap ./tst"},"bugs":{"url":"https://github.com/mcavage/node-asn1/issues"},"homepage":"https://github.com/mcavage/node-asn1","_id":"asn1@0.2.0","dist":{"shasum":"c38a3ddc5f6340a99ee301ad3e395472d2b0fe4e","tarball":"http://localhost:4260/asn1/asn1-0.2.0.tgz","integrity":"sha512-/8v+p97bilwzoMaFxn1BDB7tkObSZNFsh56rq1WGUYTNLyyhIvaHFrmTD/BtWvAk0AOr1w+Cf9igZiY1L4x91w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDzMXe0rEqC8dUfe/Ppi/XfAGapdcgNaEOIza0sAmAL4wIhAPrfk6LjHdnHq76QrCG2Am26fSsYahUrtpSSUeMTF9eb"}]},"_from":".","_npmVersion":"1.3.21","_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.2.1":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"contributors":[{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.1","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","dependencies":{},"devDependencies":{"tap":"0.4.8"},"scripts":{"test":"./node_modules/.bin/tap ./tst"},"bugs":{"url":"https://github.com/mcavage/node-asn1/issues"},"homepage":"https://github.com/mcavage/node-asn1","_id":"asn1@0.2.1","dist":{"shasum":"ecc73f75d31ea3c6ed9d47428db35fecc7b2c6dc","tarball":"http://localhost:4260/asn1/asn1-0.2.1.tgz","integrity":"sha512-Qlt6MN3lOQjpHxlh49dTHVV3ankYp3udK35Aw0bxHMAAVYaa7m+csXAdzdS/t3HJn0eG+o81PTAifeFoCNJCmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICwvV8TzdaQZScR1m6i9nu6vSgAS/xdaEG8mH+mh/fajAiEAh+gYo4cMQ7vumsAshLSF+a4MZxZ8HXQX/zIaz/QqnOU="}]},"_from":".","_npmVersion":"1.3.21","_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.2.2":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"contributors":[{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.2","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","dependencies":{},"devDependencies":{"tap":"0.4.8"},"scripts":{"test":"tap ./tst"},"bugs":{"url":"https://github.com/mcavage/node-asn1/issues"},"homepage":"https://github.com/mcavage/node-asn1","_id":"asn1@0.2.2","dist":{"shasum":"408fcea7db6a668f119c38a9c244fec90061a7ac","tarball":"http://localhost:4260/asn1/asn1-0.2.2.tgz","integrity":"sha512-jkhsc2d+w9wCrma14ozbu1zAbNWcAjPIPAdP6PCHGu6JxOaUzcJQKDGgDooItj/O2uSwZEzhgOtTSNCk+jNDYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDXC6uBKp9vwX58Eq0v/gTg23v+bPdvrTfdWjLhzejl5AiBUOq/+4rZaeDAEvrkd67R9YV6bZ+qik4f1RFESJ0QkUA=="}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"mcavage","email":"mcavage@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"}],"directories":{}},"0.2.3":{"author":{"name":"Mark Cavage","email":"mcavage@gmail.com"},"contributors":[{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"},{"name":"Alex Wilson","email":"alex.wilson@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.3","repository":{"type":"git","url":"git://github.com/mcavage/node-asn1.git"},"main":"lib/index.js","dependencies":{},"devDependencies":{"tap":"0.4.8"},"scripts":{"test":"tap ./tst"},"license":"MIT","bugs":{"url":"https://github.com/mcavage/node-asn1/issues"},"homepage":"https://github.com/mcavage/node-asn1","_id":"asn1@0.2.3","_shasum":"dac8787713c9966849fc8180777ebe9c1ddf3b86","_resolved":"asn1-0.2.3.tgz","_from":"asn1-0.2.3.tgz","_npmVersion":"1.4.28","_npmUser":{"name":"pfmooney","email":"patrick.f.mooney@gmail.com"},"maintainers":[{"name":"mcavage","email":"mcavage@gmail.com"},{"name":"pfmooney","email":"patrick.f.mooney@gmail.com"}],"dist":{"shasum":"dac8787713c9966849fc8180777ebe9c1ddf3b86","tarball":"http://localhost:4260/asn1/asn1-0.2.3.tgz","integrity":"sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC7miC0gj8mgjMJGkSa9m4vEVxRHM/rB9m3rTpfEuXm/gIgegpbzpk1ufxAHxTyhcAo/qagPjMeIcOu7x5vcliwHys="}]},"directories":{}},"0.2.4":{"author":{"name":"Joyent","url":"joyent.com"},"contributors":[{"name":"Mark Cavage","email":"mcavage@gmail.com"},{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"},{"name":"Alex Wilson","email":"alex.wilson@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.4","repository":{"type":"git","url":"git://github.com/joyent/node-asn1.git"},"main":"lib/index.js","dependencies":{"safer-buffer":"~2.1.0"},"devDependencies":{"istanbul":"^0.3.6","faucet":"0.0.1","tape":"^3.5.0","eslint":"2.13.1","eslint-plugin-joyent":"~1.3.0"},"scripts":{"test":"tape ./test/ber/*.test.js"},"license":"MIT","gitHead":"a80f9f24f17a915a8b8634cb72cd55af3f724f6d","bugs":{"url":"https://github.com/joyent/node-asn1/issues"},"homepage":"https://github.com/joyent/node-asn1#readme","_id":"asn1@0.2.4","_npmVersion":"5.6.0","_nodeVersion":"8.11.3","_npmUser":{"name":"melloc","email":"cody.mello@joyent.com"},"dist":{"integrity":"sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==","shasum":"8d2475dfab553bb33e77b54e59e880bb8ce23136","tarball":"http://localhost:4260/asn1/asn1-0.2.4.tgz","fileCount":9,"unpackedSize":18040,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbY17hCRA9TVsSAnZWagAAIyEQAIzewTkLKyCEwZLZAa+Y\n4gyxLVzRjMv+m6jEs6F5c/WFro6qDfmlGLT4Bjxbbyu65Hbe2x9/6meItAu9\nRfrylo9sziNMM2VotpEXhvxEbB1eLXwJQfQyYespJ66jW4nCYibcuRIyAa9k\nU0sjmdkmc15sct9tVr/6y66s7wk7tPflpbTw5LIiJkPS7l9XUTv4m2pxgKy6\n3iFpWHWCw3qL0lM+fK6akfBRQqUYuRt64b8GOFokOzZ8umyTQNJ0Uf9t6HDG\neN/reQn19ShhMOgHEb+TbzQyZavzLCG6C0cto6axvYDWhFe0HCrEjYlcEAxK\nvJ6k6ZbBegdIGbtufxWx8w/PwSQWDj81zyrdSOGK+Q2exlcBeuKdxzCujr+r\nWVZttUAhd57u71QwsLYdFfiAOGU524NbMNGXYMhYR3cfMSxMj+n4gq9I4duO\nQjMM/Ssngc7j5zL9pBtld9NG5T9R68i+Rx7Bd0FPPA0gs5UyyxIjQBt3vmuC\n7uWEpkOWuN//jrz18oJFS9pzVUxF35eyTLB+leKlLBa+56XSl/B0QrONgaXF\n+V9wRHnMrfTGg98WcehqeoCEkXdrwvMGgssSr0+undAO0Vx3dPufLkwqyPbj\nictqz6YWwonqLcD0jihHcrb0sUz+A1T1aEbdW4iKVrgU1Z+SwjJebdPJtP7r\nnYrv\r\n=Rn3q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDSDAAilfv+myGNuT7iVDxca52OY6GAX6BoJZLCaeTyrAIgO19K9K2kYuHxY9W4IkV0C4LS8wigvNifLl6MjtvPhhc="}]},"maintainers":[{"email":"alex@cooperi.net","name":"arekinath"},{"email":"mcavage@gmail.com","name":"mcavage"},{"email":"cody.mello@joyent.com","name":"melloc"},{"email":"pmooney@pfmooney.com","name":"pfmooney"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/asn1_0.2.4_1533239008530_0.4258479106965425"},"_hasShrinkwrap":false},"0.2.6":{"author":{"name":"Joyent","url":"joyent.com"},"contributors":[{"name":"Mark Cavage","email":"mcavage@gmail.com"},{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"},{"name":"Alex Wilson","email":"alex.wilson@joyent.com"}],"name":"asn1","description":"Contains parsers and serializers for ASN.1 (currently BER only)","version":"0.2.6","repository":{"type":"git","url":"git+https://github.com/joyent/node-asn1.git"},"main":"lib/index.js","dependencies":{"safer-buffer":"~2.1.0"},"devDependencies":{"istanbul":"^0.3.6","faucet":"0.0.1","tape":"^3.5.0","eslint":"2.13.1","eslint-plugin-joyent":"~1.3.0"},"scripts":{"test":"tape ./test/ber/*.test.js"},"license":"MIT","gitHead":"c80ab61a3ba35d77deb0a44b9c2bb7abc246dc09","bugs":{"url":"https://github.com/joyent/node-asn1/issues"},"homepage":"https://github.com/joyent/node-asn1#readme","_id":"asn1@0.2.6","_nodeVersion":"12.22.7","_npmVersion":"6.14.13","dist":{"integrity":"sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==","shasum":"0d3a7bb6e64e02a90c0303b31f292868ea09a08d","tarball":"http://localhost:4260/asn1/asn1-0.2.6.tgz","fileCount":10,"unpackedSize":19757,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2j12CRA9TVsSAnZWagAAAMsP/0OlnHNAA18YRr7ioggR\n0/2/6wNWwbA6EpcIUZiWmdaWoWfQBVWKkXRjNT0zLiW0ck1rYrrg9P+DCgXK\nsxW6zBlYirwR8Og2uuxH+Ja2n3CZdZfLo/qifjfViDH2ibbrdF5j2WwKfkeE\nW6SvhktnocxEV1d+9+0fDn+8uC44H/A547c58Ed4HXYCrLKEXwbCb15oppSt\n7qbqGo/Cpht/pBK3P/8RMTNaGifiNp129YL5CfGo5CDUXRF1z6ofZUpFLKt1\n6X0hd7Iok4o+s8JBHDIUhpeMX7Komdz4jX/i+wwzuHldsmg2BeDo5n7VLkl8\nEsnMCQsnrn6ZTWO+QsCxWO+80Fr7+ADtfTm8XDAUR2I+LMtTjC53CcIDaikx\nicieoULaI/Bnq0Bwndtwi2yyog4pAyCZIISNA//WDbbDgzmFEoCUb6L8WTAH\nDD63RiXCDq1gXa3AVaIgn/1PCVNO3ox69lEx5HKPdPHXzX4hObRPOt2+x9QA\nPR1/r4wYO8+awxWCxvbvto8lpmU+9O/QrECqqzqEs/GDUGfBHYHeC5tHb+is\nI/KiqTsgi274xy7jSIjFzL8o4x0xeE5GuHAi7g4gAw/YzxmA5wgOohQ/aqva\ncrjx0nnNVWsQvgf/5Tmf6FK2J3xxaY2n56Gwb4ClQ4G2PzyUDpLskjQMtZk0\n1zf9\r\n=FhY3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDh8rHXgZYfiyydIhYCAvX5qKC8LudijMiGGIeoviWu6gIgHcEVesBYAyn1gYDWhR8vKfZd4gil1GtyOlz0Bsp4bm4="}]},"_npmUser":{"name":"bahamat","email":"bahamat@digitalelf.net"},"directories":{},"maintainers":[{"name":"todd.whiteman","email":"todd.whiteman@joyent.com"},{"name":"kusor","email":"kusorbox@gmail.com"},{"name":"wyatt","email":"wpreul@gmail.com"},{"name":"michael.hicks","email":"michael.hicks@joyent.com"},{"name":"bahamat","email":"bahamat@digitalelf.net"},{"name":"chudley","email":"aguycalledrichard@gmail.com"},{"name":"tchameroy","email":"tyler.chameroy@joyent.com"},{"name":"dbuell","email":"dayne.buell@joyent.com"},{"name":"pfmooney","email":"pmooney@pfmooney.com"},{"name":"mcavage","email":"mcavage@gmail.com"},{"name":"arekinath","email":"alex@cooperi.net"},{"name":"melloc","email":"cody.mello@joyent.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/asn1_0.2.6_1635986787575_0.15391608273285207"},"_hasShrinkwrap":false}},"maintainers":[{"email":"bahamat@digitalelf.net","name":"bahamat"},{"email":"todd.whiteman@joyent.com","name":"todd.whiteman"},{"email":"kusorbox@gmail.com","name":"kusor"},{"email":"michael.hicks@joyent.com","name":"michael.hicks"},{"email":"pmooney@pfmooney.com","name":"pfmooney"},{"email":"mcavage@gmail.com","name":"mcavage"},{"email":"alex@cooperi.net","name":"arekinath"},{"email":"cody.mello@joyent.com","name":"melloc"}],"time":{"modified":"2022-06-13T03:32:30.845Z","created":"2011-07-19T19:07:06.870Z","0.1.0":"2011-12-08T16:49:17.462Z","0.1.1":"2011-12-08T16:49:17.462Z","0.1.2":"2011-12-08T16:49:17.462Z","0.1.3":"2011-12-08T16:49:17.462Z","0.1.4":"2011-12-08T16:49:17.462Z","0.1.5":"2011-12-08T16:49:17.462Z","0.1.6":"2011-12-08T16:49:17.462Z","0.1.7":"2011-12-08T16:49:17.462Z","0.1.8":"2011-11-07T22:10:26.013Z","0.1.9":"2011-11-11T19:18:29.635Z","0.1.10":"2011-12-08T16:49:17.462Z","0.1.11":"2012-01-06T17:02:19.759Z","0.2.0":"2014-02-24T17:51:55.325Z","0.2.1":"2014-04-04T20:03:39.061Z","0.2.2":"2014-09-03T18:29:15.607Z","0.2.3":"2015-09-30T22:53:30.238Z","0.2.4":"2018-08-02T19:43:28.577Z","0.2.6":"2021-11-04T00:46:28.017Z"},"author":{"name":"Joyent","url":"joyent.com"},"repository":{"type":"git","url":"git+https://github.com/joyent/node-asn1.git"},"readme":"node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.\nCurrently BER encoding is supported; at some point I'll likely have to do DER.\n\n## Usage\n\nMostly, if you're *actually* needing to read and write ASN.1, you probably don't\nneed this readme to explain what and why. If you have no idea what ASN.1 is,\nsee this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc\n\nThe source is pretty much self-explanatory, and has read/write methods for the\ncommon types out there.\n\n### Decoding\n\nThe following reads an ASN.1 sequence with a boolean.\n\n var Ber = require('asn1').Ber;\n\n var reader = new Ber.Reader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff]));\n\n reader.readSequence();\n console.log('Sequence len: ' + reader.length);\n if (reader.peek() === Ber.Boolean)\n console.log(reader.readBoolean());\n\n### Encoding\n\nThe following generates the same payload as above.\n\n var Ber = require('asn1').Ber;\n\n var writer = new Ber.Writer();\n\n writer.startSequence();\n writer.writeBoolean(true);\n writer.endSequence();\n\n console.log(writer.buffer);\n\n## Installation\n\n npm install asn1\n\n## License\n\nMIT.\n\n## Bugs\n\nSee .\n","readmeFilename":"README.md","homepage":"https://github.com/joyent/node-asn1#readme","contributors":[{"name":"Mark Cavage","email":"mcavage@gmail.com"},{"name":"David Gwynne","email":"loki@animata.net"},{"name":"Yunong Xiao","email":"yunong@joyent.com"},{"name":"Alex Wilson","email":"alex.wilson@joyent.com"}],"bugs":{"url":"https://github.com/joyent/node-asn1/issues"},"license":"MIT","users":{"shanewholloway":true,"sopov":true}} \ No newline at end of file +{ + "name": "asn1", + "description": "Contains parsers and serializers for ASN.1 (currently BER only)", + "dist-tags": { + "latest": "0.2.6" + }, + "versions": { + "0.2.6": { + "author": { + "name": "Joyent", + "url": "joyent.com" + }, + "name": "asn1", + "description": "Contains parsers and serializers for ASN.1 (currently BER only)", + "version": "0.2.6", + "repository": { + "type": "git", + "url": "git+https://github.com/joyent/node-asn1.git" + }, + "main": "lib/index.js", + "dependencies": { + "safer-buffer": "~2.1.0" + }, + "devDependencies": { + "istanbul": "^0.3.6", + "faucet": "0.0.1", + "tape": "^3.5.0", + "eslint": "2.13.1", + "eslint-plugin-joyent": "~1.3.0" + }, + "scripts": { + "test": "tape ./test/ber/*.test.js" + }, + "license": "MIT", + "gitHead": "c80ab61a3ba35d77deb0a44b9c2bb7abc246dc09", + "bugs": { + "url": "https://github.com/joyent/node-asn1/issues" + }, + "_id": "asn1@0.2.6", + "_nodeVersion": "12.22.7", + "_npmVersion": "6.14.13", + "dist": { + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "shasum": "0d3a7bb6e64e02a90c0303b31f292868ea09a08d", + "tarball": "http://localhost:4260/asn1/asn1-0.2.6.tgz", + "fileCount": 10, + "unpackedSize": 19757 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "author": { + "name": "Joyent", + "url": "joyent.com" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/joyent/node-asn1.git" + }, + "readmeFilename": "README.md", + "homepage": "https://github.com/joyent/node-asn1#readme", + "bugs": { + "url": "https://github.com/joyent/node-asn1/issues" + }, + "license": "MIT" +} diff --git a/tests/registry/npm/assertion-error/registry.json b/tests/registry/npm/assertion-error/registry.json index 7a5e78400b..438e46c860 100644 --- a/tests/registry/npm/assertion-error/registry.json +++ b/tests/registry/npm/assertion-error/registry.json @@ -1 +1,65 @@ -{"_id":"assertion-error","_rev":"17-95a34e275de6ed2a7809e331289d8a38","name":"assertion-error","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.0":{"name":"assertion-error","version":"0.1.0","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","keywords":[],"repository":{"type":"git","url":"git@github.com:qualiancy/assertion-error.git"},"engines":{"node":"*"},"main":"./index","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"component":"*"},"_id":"assertion-error@0.1.0","dist":{"shasum":"555cb007e89be44ba73e7b9600c3907dc381ce2b","tarball":"http://localhost:4260/assertion-error/assertion-error-0.1.0.tgz","integrity":"sha512-5GDYNFgUTLRv4GignYXrUUHcxAzLafgfWYWzWXTeBiimgLrxSW7HTNNAXnHyypP0mS34OOrQ6xpOwe5iePe48w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDSOgg+BYn+W1TNWZFSVXnGIW5/6LO+LwqfQJ048hUxcgIgfQxa0B3fNmKfc2QeVPGMRm9IldEcwByMoh+GNLsTog0="}]},"_from":".","_npmVersion":"1.2.14","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"}],"directories":{}},"1.0.0":{"name":"assertion-error","version":"1.0.0","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","keywords":["test","assertion","assertion-error"],"repository":{"type":"git","url":"git@github.com:chaijs/assertion-error.git"},"engines":{"node":"*"},"main":"./index","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"component":"*"},"bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"_id":"assertion-error@1.0.0","dist":{"shasum":"c7f85438fdd466bc7ca16ab90c81513797a5d23b","tarball":"http://localhost:4260/assertion-error/assertion-error-1.0.0.tgz","integrity":"sha512-g/gZV+G476cnmtYI+Ko9d5khxSoCSoom/EaNmmCfwpOvBXEJ18qwFrxfP1/CsIqk2no1sAKKwxndV0tP7ROOFQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnmhFogTTZa4E1MfbbZn2eDsEN2qxGw6nImAN7NjImFgIhAMbkTUU91blDDpuAzdP6jBBIGHukoDrHhkjD8RtJHQME"}]},"_from":".","_npmVersion":"1.2.23","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"}],"directories":{}},"1.0.1":{"name":"assertion-error","version":"1.0.1","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","keywords":["test","assertion","assertion-error"],"repository":{"type":"git","url":"git@github.com:chaijs/assertion-error.git"},"engines":{"node":"*"},"main":"./index","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"component":"*"},"gitHead":"db10d2fc753f00b3dad24956921056eaf1e03708","bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"homepage":"https://github.com/chaijs/assertion-error","_id":"assertion-error@1.0.1","_shasum":"35aaeec33097f11f42399ecadf33faccd27f5c4c","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"}],"dist":{"shasum":"35aaeec33097f11f42399ecadf33faccd27f5c4c","tarball":"http://localhost:4260/assertion-error/assertion-error-1.0.1.tgz","integrity":"sha512-vSfN0UZYL0hwYkKhFq48vEI7CUJkgELo+xtcdjM/X9o5NRY4GW8PLQUDxQ1KYaugkPpnws9LCxEGzMfYWzL/Ww==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/H+TZ2RE5BBywaNop0yBuFVklnwE5RXhO0eARDgB4LwIgeTtsnwuVXY+wqeknKvvsN9xBvIzeeAA1gw18VVEvqMw="}]},"directories":{}},"1.0.2":{"name":"assertion-error","version":"1.0.2","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","keywords":["test","assertion","assertion-error"],"repository":{"type":"git","url":"git+ssh://git@github.com/chaijs/assertion-error.git"},"engines":{"node":"*"},"main":"./index","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"component":"*"},"gitHead":"b36f593951c1487fa33747c9911025734923f28c","bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"homepage":"https://github.com/chaijs/assertion-error#readme","_id":"assertion-error@1.0.2","_shasum":"13ca515d86206da0bac66e834dd397d87581094c","_from":".","_npmVersion":"3.8.9","_nodeVersion":"5.7.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"13ca515d86206da0bac66e834dd397d87581094c","tarball":"http://localhost:4260/assertion-error/assertion-error-1.0.2.tgz","integrity":"sha512-wzQs0MF+xNG9ji/rooK2bLg8XVqP+dn/IYX6qgejMtmDNB8JRLL+BoBrd4furQNgPaWhJaQRXyMXGa48lzsGtQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLcWfk28lkeQX/e39Gdc+vmgfvlluLHY0EUV215S9VfwIgWG+WCGpIZrvbJHJjx6GsOxS63ISwDqJjagoxWwPqATc="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/assertion-error-1.0.2.tgz_1465237527264_0.8082898685242981"},"directories":{}},"1.1.0":{"name":"assertion-error","version":"1.1.0","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","types":"./index.d.ts","keywords":["test","assertion","assertion-error"],"repository":{"type":"git","url":"git+ssh://git@github.com/chaijs/assertion-error.git"},"engines":{"node":"*"},"main":"./index","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"component":"*","typescript":"^2.6.1"},"gitHead":"faa3f8cbbdba74d2760f9d2e95c008ba9ce4812e","bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"homepage":"https://github.com/chaijs/assertion-error#readme","_id":"assertion-error@1.1.0","_npmVersion":"5.6.0","_nodeVersion":"8.8.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"integrity":"sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==","shasum":"e60b6b0e8f301bd97e5375215bda406c85118c0b","tarball":"http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBLKjetp37+0lhhi9deyZvXmBZcF/3rW0uJJtY/162bGAiA/3giMIaJv7sRAruur386mr5e9OzyX7FBDJo6ugT1cxQ=="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/assertion-error-1.1.0.tgz_1515337170361_0.5846316555980593"},"directories":{}},"2.0.0":{"name":"assertion-error","version":"2.0.0","description":"Error constructor for test and validation frameworks that implements standardized AssertionError specification.","author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"license":"MIT","types":"./dist/mod.d.ts","keywords":["test","assertion","assertion-error"],"repository":{"type":"git","url":"git+ssh://git@github.com/chaijs/assertion-error.git"},"engines":{"node":">=12"},"type":"module","module":"./dist/mod.js","main":"./dist/mod.js","scripts":{"build":"tsc","pretest":"npm run build","test":"NODE_ENV=test node ./test/index.js"},"devDependencies":{"typescript":"^4.4.3"},"gitHead":"06761d175ab7d188c18c1c7ed1ea5ae4a6a4d52c","bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"homepage":"https://github.com/chaijs/assertion-error#readme","_id":"assertion-error@2.0.0","_nodeVersion":"16.8.0","_npmVersion":"7.21.0","dist":{"integrity":"sha512-Q0en67fcMTcBp1xn4DTYasTSKD4KAo86UhA6lr+c6neaz2gelKi5ILIqLcYl9JGWkGGbooYLs2iGQv7v1e83AA==","shasum":"791a05c4b3c3f70652b51dcda070b9ef89da662c","tarball":"http://localhost:4260/assertion-error/assertion-error-2.0.0.tgz","fileCount":5,"unpackedSize":5776,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2j2mCRA9TVsSAnZWagAAj3MP/jHlgRzlMC4+uXz+3raT\ntp7ow0G53y7WkQXSou8+deifgO/AKPbgX5osfckjobDllMBRd8KqMvMn6I4X\nIdywrmDkXn2nutVGTwFi616leeXUlnyht7Jst6zhIEjDukPQ/RBZ+qT8V8H3\nvbzrmpjXj1EZdEMHnKQMdPriFe8ueZBE/bzpDS5AW/seaI/BkEAfx97HesVd\nicHcoOvlLgt7SWGfBArUlZC6ufB8eOl/LFpBaFh7fXHjh/kBmDGGEz3eGXU9\nOhgMgpg5k9/shMb3kIf8hJ/31eWHf9vcU7QPv5U1+z3FaKt/hdCaWfrjpkAz\ne1UE0j+qwYOKWYYyrjFmIS4ZSUf4tzP+y1Rz91kZHKZqipvVARhELGRclrSh\nxINCWcqGmOiuqnh4y3F4gC/K1IGN7rth4Ha67u+yXTFOLwMY0eTVpvu/1OrN\n+sEbccNw+uWO7T+itkc4/DuwFdpCa+LRcOterYmxgSyVoCrwsD1/oeYh6tUN\nMhZXXEoN1+Gkc3rsDc3q53rz6mNSmW+otUUhOjrfLOE6fzl6m9pBLCFTFT6V\ndT60KPLlN4Kv7tEBol/AS4bDu320NpXo2IB/QtKLFHlmxXrKEYXvhVHOUpzh\nWDa2bNhBFKkFoiBG6Z8GTGRup4rQvVtbOwHOP0ygHvWuKOujFP5sZMqPP3kS\nbxPQ\r\n=vExu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCb5vGpzCFi2x+1kbn4dHWMTFIn60/LpTEVxMDoTLNFOAIgO/CAtZzdsNwg94EdSSQlwPA2nyk+rmmGBz09JVL3dIA="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/assertion-error_2.0.0_1633447251025_0.35381096573804993"},"_hasShrinkwrap":false}},"readme":"

\n AssertionError and AssertionResult classes.\n

\n\n

\n \n \n \n \n \n \n \n

\n\n## What is AssertionError?\n\nAssertion Error is a module that contains two classes: `AssertionError`, which\nis an instance of an `Error`, and `AssertionResult` which is not an instance of\nError.\n\nThese can be useful for returning from a function - if the function \"succeeds\"\nreturn an `AssertionResult` and if the function fails return (or throw) an\n`AssertionError`.\n\nBoth `AssertionError` and `AssertionResult` implement the `Result` interface:\n\n```typescript\ninterface Result {\n name: 'AssertionError' | 'AssertionResult'\n ok: boolean\n toJSON(...args: unknown[]): Record\n}\n```\n\nSo if a function returns `AssertionResult | AssertionError` it is easy to check\n_which_ one is returned by checking either `.name` or `.ok`, or check `instanceof Error`.\n\n## Installation\n\n### Node.js\n\n`assertion-error` is available on [npm](http://npmjs.org).\n\n```\n$ npm install --save assertion-error\n```\n\n### Deno\n\n`assertion_error` is available on [Deno.land](https://deno.land/x/assertion_error)\n\n```typescript\nimport {AssertionError, AssertionResult} from 'https://deno.land/x/assertion_error@2.0.0/mod.ts'\n```\n","maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"time":{"modified":"2022-06-13T03:33:52.316Z","created":"2013-04-07T22:59:41.018Z","0.1.0":"2013-04-07T22:59:42.826Z","1.0.0":"2013-06-08T20:41:17.202Z","1.0.1":"2015-03-05T23:45:54.576Z","1.0.2":"2016-06-06T18:25:29.009Z","1.1.0":"2018-01-07T14:59:31.257Z","2.0.0":"2021-10-05T15:20:51.185Z"},"author":{"name":"Jake Luer","email":"jake@qualiancy.com","url":"http://qualiancy.com"},"repository":{"type":"git","url":"git+ssh://git@github.com/chaijs/assertion-error.git"},"homepage":"https://github.com/chaijs/assertion-error#readme","keywords":["test","assertion","assertion-error"],"bugs":{"url":"https://github.com/chaijs/assertion-error/issues"},"license":"MIT","readmeFilename":"README.md"} +{ + "name": "assertion-error", + "description": "Error constructor for test and validation frameworks that implements standardized AssertionError specification.", + "dist-tags": { + "latest": "1.1.0" + }, + "versions": { + "1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "description": "Error constructor for test and validation frameworks that implements standardized AssertionError specification.", + "author": { + "name": "Jake Luer", + "email": "jake@qualiancy.com", + "url": "http://qualiancy.com" + }, + "license": "MIT", + "types": "./index.d.ts", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/chaijs/assertion-error.git" + }, + "engines": { + "node": "*" + }, + "main": "./index", + "scripts": { + "test": "make test" + }, + "dependencies": {}, + "devDependencies": { + "component": "*", + "typescript": "^2.6.1" + }, + "gitHead": "faa3f8cbbdba74d2760f9d2e95c008ba9ce4812e", + "bugs": { + "url": "https://github.com/chaijs/assertion-error/issues" + }, + "_id": "assertion-error@1.1.0", + "_npmVersion": "5.6.0", + "_nodeVersion": "8.8.0", + "dist": { + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "shasum": "e60b6b0e8f301bd97e5375215bda406c85118c0b", + "tarball": "http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz" + }, + "directories": {} + } + }, + "author": { + "name": "Jake Luer", + "email": "jake@qualiancy.com", + "url": "http://qualiancy.com" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/chaijs/assertion-error.git" + }, + "homepage": "https://github.com/chaijs/assertion-error#readme", + "bugs": { + "url": "https://github.com/chaijs/assertion-error/issues" + }, + "license": "MIT", + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/autoprefixer/registry.json b/tests/registry/npm/autoprefixer/registry.json index b979434424..3cccb21681 100644 --- a/tests/registry/npm/autoprefixer/registry.json +++ b/tests/registry/npm/autoprefixer/registry.json @@ -1 +1,47 @@ -{"name":"autoprefixer","dist-tags":{"latest":"10.4.14"},"versions":{"0.1.20130409":{"name":"autoprefixer","version":"0.1.20130409","dependencies":{"rework":">= 0.13.2"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","chai":"1.5.0","sinon-chai":"2.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"06b04fb73779015e79e71df85e261421d7b80742","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.1.20130409.tgz","integrity":"sha512-g9PVgAfftYSvZXD9PsvbutKnYExxJinBDCv8gHnUjwChnqmcl6nBdDWivJT7P/eIups6BrFKBd0rMKZO+YJTbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGISxPGN2wHvjz6wjlcNKCuQQLZlvOwG7dctyBCRUKhNAiEA+PqAkJX8if7Q/ACKP8neFORuxlf3Ag63gEoBI5ZvaR0="}]}},"0.2.20130413":{"name":"autoprefixer","version":"0.2.20130413","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","chai":"1.5.0","sinon-chai":"2.3.1","component":"0.13.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"63170ea937afa0aa4bfc1401e8a21078b4b1538f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.2.20130413.tgz","integrity":"sha512-xb4lIAZRfp+V7SF+enYVGLA3gG2JxamomzpQfEkiv5go1roNhqVM/Tk/z8igxnfm2nKOAhCE8blSK32xMwqR9g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8L0VNqbEUiNFObyNg4557o3TfXUFnedg/FjUJM6fFtwIgFm+04Ke5vuWrpWld9j4VB6FijVr0J+MEA3N1Pnyk04U="}]}},"0.3.20130423":{"name":"autoprefixer","version":"0.3.20130423","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","should":"1.2.2","component":"0.13.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"75c83ea15305adff15bc5abeba9400a79be454a2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.3.20130423.tgz","integrity":"sha512-7DwPpFNuQ9EyvA1+TgOSgyWDhOaJmbyFfRcI1jdoSTqJy07kSpBky7NE0SN1k7Kb8fjjUVlmSXQRZ41XXjzMsQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICw1rMe5TGhJ5Erq6gmWEBQmqMN7h+xQMC3+W9izgNfTAiAkh6YQ+Nt5YVruBfx3cICERvNssxXxovCgRNM9jcXsQA=="}]}},"0.3.20130424":{"name":"autoprefixer","version":"0.3.20130424","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","should":"1.2.2","component":"0.13.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"30346a8f3a39c5e8c280255c3fe584f13d975432","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.3.20130424.tgz","integrity":"sha512-0T9tZiAqy/U/Ntlgp9Vlrs6BoPJCfgEuYto7iIy5vxXaxAQatw0hHauoOdXQsoNM95O4f89/KM7YQdsTtUaasQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDu2gdziBPhdwcvsouAx2n3O3os9WCVP/3peRXRuiDhoAIgVa+tjuax66gKdYSaDUg9euG7hFru4wf/l434Q9459oI="}]}},"0.3.20130427":{"name":"autoprefixer","version":"0.3.20130427","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","should":"1.2.2","component":"0.15.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"27da062b75a92e46c8d662f485136644ac7b12d6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.3.20130427.tgz","integrity":"sha512-B3PFz7iFKJi6r12YxsedsOVfRW9/IzL1UBoJ6QAzq8AdrIlj0UL95+x1SREGXiCzi+noasOcdLToKg0QcA+l0A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFisLKLIkSDWISlwKntQea7Sgnz+txZtVqoZJkMNuUXgIhALcFj4/h122arR3qRLe3X/lRBBFAHZdjwwGHlBWDW1wl"}]}},"0.3.20130502":{"name":"autoprefixer","version":"0.3.20130502","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.6.0","should":"1.2.2","component":"0.15.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"2f152d1c4a47c75bf74b2fc0cec9d2c2c1e8a2ed","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.3.20130502.tgz","integrity":"sha512-yoZb4DmoL5HkoYFgOl17LFXbWxh31RSW72C/aBD07yHliQ8KR2DBy0s4OTULmOgG8WYI2x4M7TFyG3R3iZIOjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGRWKQW6rsgEIOKoaghySXG/oNYdLf6wjKIKQto3QHW7AiAgGIndmo+tpnmaErFa0Ndc/B35uZggJzf8yuBR3uVhTQ=="}]}},"0.4.20130507":{"name":"autoprefixer","version":"0.4.20130507","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.7.0","should":"1.2.2","component":"0.15.1","js-beautify":"1.3.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"ebf597a6789ceed55edc6774a1ea5f91d8b9d935","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130507.tgz","integrity":"sha512-Y6rAt5XRliP1km3Be6hvKDkCiH3zUVGdZxVWk6BFEULUxMK/eFbtS4CAgJDgdCP+KZ4oxomanCTmAAkEiy4FVA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4E3bdI/GA8qJEW1h31hltmMERGWws3KT9ANuTa9xf4wIgX8bK8MvAi8aZNQFb+p5WsvrkRD62bASmJ2yR/VXkTnI="}]}},"0.4.20130515":{"name":"autoprefixer","version":"0.4.20130515","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.7.0","should":"1.2.2","component":"0.15.1","js-beautify":"1.3.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"b6fe5b2a59ab465fff3016167f3f06866d4f8ea9","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130515.tgz","integrity":"sha512-3ZTOwpsXNqsaDJ6HJIGUz+yy9Jbim9cAE2cm4A6MS03CB5yf1zaRvGVcNVQ5r2aFhLvvGbmKvjWZ5TvvVTIHYw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyZxf9jShS0DiKpwC6w5KiahZ6l2CLA+7gbIdKG/asvwIhAJiSYT/iIa0s+pa3xxQ+Bi4qvnKQpojA9gDK8LNpHrBm"}]}},"0.4.20130521":{"name":"autoprefixer","version":"0.4.20130521","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.9.0","sinon":"1.7.0","should":"1.2.2","component":"0.15.1","js-beautify":"1.3.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"75c4bdc76767d1def708f6b3bb34c019b9206cac","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130521.tgz","integrity":"sha512-e0GOQAWhZ8W5zCnwWYORd3yLRrMfhBP/sienKKOoXr3nTLWi86j4UiMLzU9T8009eaA2OZY1ZM5xR6f/9B7jUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCujvbywaXbkrv7QFRSpAxuRBRkP6ianiQb8uXqapF7zwIhAJLcvlcLzLWrXQWxi3kCq2mhhZ4gddzJp3sz45b0mDWj"}]}},"0.4.20130524":{"name":"autoprefixer","version":"0.4.20130524","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.10.0","sinon":"1.7.2","should":"1.2.2","component":"0.16.0","js-beautify":"1.3.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d127c4584487effd9a673819788837abca67fcb2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130524.tgz","integrity":"sha512-UJh/b0QRDkNFhMGZ2TnR2ChHR4j5eSPbdH3OdCI0+//smU1fKXdBCBCMP8rsvoVESueLTFe39pfSxFh15WTFYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICm0OtvtUnkSTW0Hx5dNAIb9SidAnitT8SL7KpnwvItWAiBGuTYwNb7+nriCiXWLkAIOO0Nm9tZaZ5WwtsBess2sPA=="}]}},"0.4.20130528":{"name":"autoprefixer","version":"0.4.20130528","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.10.0","sinon":"1.7.2","should":"1.2.2","component":"0.16.0","js-beautify":"1.3.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d4d10a626ed7aa484e58229df621a2a62d54cdce","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130528.tgz","integrity":"sha512-t59LSu7w6FfycNaFLd+6n227W7PhoyydaB0Gqt053ldDHFQrQEwWAlobOgcLNd5CRzk6UaSSreGv/AE0aSyQGA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEAiJKfv2m5awGbJg1rOzLl4MTyATQGY22t9WyBU1aWfAiEAl3Q0dYjXSkWPXxPBESETYhHswQ7qAeBdrRvqg0gbh/Y="}]}},"0.4.20130530":{"name":"autoprefixer","version":"0.4.20130530","dependencies":{"rework":">= 0.14"},"devDependencies":{"coffee-script":"1.6.2","mocha":"1.10.0","sinon":"1.7.2","should":"1.2.2","component":"0.16.0","js-beautify":"1.3.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d98fdaf2a899523c8c5b1172eab56880279546b6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130530.tgz","integrity":"sha512-Qsfo/7bladcUqOth2jYmFG/kYkm7zCGyw5mbaWplN8JapHbGUVrF3RnKjxF0bcAg+GsI4fd13uneWHMi+A8pvg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGMcfBJpltN0UmB7vuAGg8dwmPx2Wor8r9CgMWPq2/jaAiAQ7iheCdl4Ya/O530oRRgvoV7aLVx0BdUa378XtBa0eg=="}]}},"0.4.20130603":{"name":"autoprefixer","version":"0.4.20130603","dependencies":{"rework":">= 0.15"},"devDependencies":{"coffee-script":"1.6.3","mocha":"1.10.0","sinon":"1.7.2","should":"1.2.2","component":"0.16.2","js-beautify":"1.3.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"e51dc0c9ad983297bc4a8bd80b5218a012a786eb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.4.20130603.tgz","integrity":"sha512-x+X6l9IUmU9mwWNna9YoJtmwNIOZXYf2o0LnP1Dqgei9/xHbXU0HUWcTSKSUFgtOzFkWd1Tyi5TzX4I6s8E1CQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBuKibwh5Qo+j8pyFD7+l6ZJclOwhA4QzY9AoVasWsmJAiEA04hWw9ykn7dCAFMr+Z0GpbcEOSzu77Npgu5woMq+Nmc="}]}},"0.5.20130615":{"name":"autoprefixer","version":"0.5.20130615","dependencies":{"css-parse":"~> 1.4.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.3","fs-extra":"0.6.1","should":"1.2.2","rework":"0.16.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"b518427db421b106c33b0136459d551315e7e1ef","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130615.tgz","integrity":"sha512-HGivtdv/OCeReK7jqVOqif0HwwctGQoF6QW6veaAr3t5fCgUt+tX+NBF+w4KgV/D2swtVR2dy52crQSwyxjyJg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDN+O1jiO+GLi9d1wDfLAid4EFB1GgOnqx1orXTNZ33kAIhAL2/qy3q3TSBSPUpNGCzHWP0fr0qivy3GnoXs6MoTew6"}]}},"0.5.20130616":{"name":"autoprefixer","version":"0.5.20130616","dependencies":{"css-parse":"~> 1.4.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.3","fs-extra":"0.6.1","should":"1.2.2","rework":"0.16.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"ea7a9cc3614357c78edb64388e32ccd5d0d15614","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130616.tgz","integrity":"sha512-xw1fS3oF/xmO2DnuKB6bkV7PZGUMplcutHxB1roNO/vgsyeo84hGFS40rUsm/YMAPCijnpEy9VrkeDFkzejeCw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCpAIwrvj57cRTbLJq9wJOiR3M5YqouAAVJg1rHv9ZgnwIgZxvrYFCfrSFDBcZ1VC0Mcbyg6dXvbVm3uSHtmHob14M="}]}},"0.5.20130617":{"name":"autoprefixer","version":"0.5.20130617","dependencies":{"css-parse":"~> 1.4.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.3","fs-extra":"0.6.1","should":"1.2.2","rework":"0.16.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"1eecf6fc1c83831b86531f13cf9cc3bb6f7aa581","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130617.tgz","integrity":"sha512-uJ0a4v/O75bHGVMMGYq9RUg/TRW/GEYWk6NJfBPFXKHfYHTcw6S2CtZ8hrjd2cvAbOdKsDLyQF8lm79Kg+vNkA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmvvUzGeLI/XiF/xz2H74ETe7JvPHIAfvT2ZlbZuQbFgIhALd4aM7VGF+cKRM9iVSIfftDX7pAQtCSdia1WD3a90iO"}]}},"0.5.20130625":{"name":"autoprefixer","version":"0.5.20130625","dependencies":{"css-parse":"~> 1.5.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.4","fs-extra":"0.6.1","should":"1.2.2","rework":"0.17.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"7dadbe1a7042ff1cf4c837838ffd4e6ba1e8512f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130625.tgz","integrity":"sha512-3myJzGnLhT9O0Bvk2+6CCBptLOqDl9avJYiZhl+n8LA/BW9YgxdNVzHyJ4RzjVT9H9EepIVuiFUV6SfU7EtMwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEVo1f8CJ74Mmf8UBb60MUQsZPtu18XQprSpqWxpFKEwAiEAy/ocUXWn7xAhqYEoUyWfiey1O/a0Exw47nsyOkh1unY="}]}},"0.5.20130626":{"name":"autoprefixer","version":"0.5.20130626","dependencies":{"css-parse":"~> 1.5.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.4","fs-extra":"0.6.1","should":"1.2.2","rework":"0.17.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"0716c2379f835e1dfbd7296a7a19d0e5cf96c22a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130626.tgz","integrity":"sha512-eKwvopKoV56nnFWkf8fbhc/krD/LbiEjSzohOJ5cY9bOhBJlkXG49lwt+1/ObTo9y6bmq/CMwNkOsjbnV2uKoQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAu7uG0YOrdRkemWCASo6oRzVI2/xs9wTRRiL0Jj8OhjAiA0JZE87WWfL+mkOqPvOm+rPF2Z4/phaKMmSoeBd4QCkw=="}]}},"0.5.20130629":{"name":"autoprefixer","version":"0.5.20130629","dependencies":{"css-parse":"~> 1.5.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.5","fs-extra":"0.6.3","should":"1.2.2","rework":"0.17.0","mocha":"1.11.0","glob":"3.2.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"94dfcdaf7d530df83e1f803e87da0350ed1fde00","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.5.20130629.tgz","integrity":"sha512-/BQSoabupFMPP5a4ez2W53O2fuJJWanMF/YK1WFVikdddRvL8bqcO7Y+0X55Z99yCi/r1afM1W1JfybMKHyZ2w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFUJLze6bERmddJd7OJXVUmKVNsIC+8XTeOcpF6TEiSNAiEA13m1j6+xZnb/1zCDc3Cwq4tERKMW57fbOZt8Kv5tTyc="}]}},"0.6.20130716":{"name":"autoprefixer","version":"0.6.20130716","dependencies":{"css-parse":"~> 1.5.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.16.7","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.34.1","rework":"0.17.2","mocha":"1.12.0","glob":"3.2.3","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"9cb6cdf0ca2d46d47d9fe542d75bfaac305ca91c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130716.tgz","integrity":"sha512-gwQuJjtRQHYo84q3833OJz9PMLvLkptVRQ+rVcqvC30sPzFmqDow/gcxOs04H9bFLdmOZ7B0X0OBGc573Bsh8Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXKiqv5S4A8bOgE1AKzkwFvU6p6QoLXH+ce7DplJCzVgIgXHZAWQnUElZtBiPHCgLsY6y3ekQjDW45fbkV5MjygRU="}]}},"0.6.20130721":{"name":"autoprefixer","version":"0.6.20130721","dependencies":{"css-parse":"~> 1.5.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.34.1","rework":"0.17.2","mocha":"1.12.0","glob":"3.2.3","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"dc408546bf1a8c7bea9dfff1361f68d650a2fbfc","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130721.tgz","integrity":"sha512-6XxkKuotfOK6F0gS6qbYO8Z2Vr5uAl4JXcEj42xVgkJd8LkPto1ACfviAhvDTsnlig6DAbaqrAR2xEjlGov1nQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBxFJl87f0QcMZ5WPmyxnsSWfe2Pv51R6CwPlrf/4rdoAiAN2Zjlcm7JfhavusfF7y+UscPBRGoqMeBLnvfP2k10aQ=="}]}},"0.6.20130728":{"name":"autoprefixer","version":"0.6.20130728","dependencies":{"css-parse":"~> 1.5.1","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.34.1","rework":"0.17.2","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"6190702405dcf020bfa139b9a5a6bbe46613d8b1","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130728.tgz","integrity":"sha512-OHUiGoIzY/kAbsLWRhqy+JrglWcFoDJkradjatE154d6Ov+PReFr3C2TRciKMr8GBu2pyferw16PBjdWyU0wEQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDuht50X7vVyZ/Pq/4Iowrnt3qzsqHy9kIE8Cysoo8uTAiBazxvHQ1/ChmHPtTBxA8+br35tsJzlasbIXoiSJZWy8Q=="}]}},"0.6.20130729":{"name":"autoprefixer","version":"0.6.20130729","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.35.0","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"c07610ee6869827dd1d59974c0ce79250296c626","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130729.tgz","integrity":"sha512-bfai5ah+yfZMFiULDps/AylMnE/v9Fi2/BurbHHZ76hNCy1cBIPXToiZC9ivEeHUq917NkZiQX5BmB7h/Gy/ug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCVgcV9YKwT0GvdUoM+VvlzvnbrmkStrOcOfd6Tc9+/IQIgb9ShcTSihimvRhOTxNWlAaA1fauGSB4TTECS098dBYM="}]}},"0.6.20130730":{"name":"autoprefixer","version":"0.6.20130730","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.35.0","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"57482b1e875fcc623004f29e04676ec71888986e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130730.tgz","integrity":"sha512-TkA/OcuIce8zDThr6hHpRb2b9F2rTTNtOWXN8kfsQop8viIDX6nKk+67Js3MkZiOYmRNCzOa1AsLppgUdvLGbw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHE2+wMffnbIBphUUD0opGyN7IJJFSBHpeEh2av5TRG6AiBujEzyJ4DfoVASF6dOBrrKrRi7bQgUPfTTV8kEfV10mw=="}]}},"0.6.20130731":{"name":"autoprefixer","version":"0.6.20130731","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.35.0","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"43844a3611f26c6342b1abf510e5df57dcb3853b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.6.20130731.tgz","integrity":"sha512-DOoYeugGwc4zFh3mphVzeFTX6UW4QLtMFQEOFyZ5l9ibaIhXqNGFepmaTnYPBZcU9ctT5cGVzarRZ66litTPrw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEv7hdPIHD//sq+0QIiERQKqLFPc/q4aVff5ds+lPMEiAiB7l99XlCOe3yTGRDAe5ONN2c/kHUElmYT62hCeFCCqRw=="}]}},"0.7.20130805":{"name":"autoprefixer","version":"0.7.20130805","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.36.0","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d78eca87819fe52b5b9820a90f45401e6d989b14","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130805.tgz","integrity":"sha512-UNZmrGlTzTvU7aB/jRLYhdX87jHunL3T/TKkS5WEQzqf/7U7JLdgJtErHOzRLIh/ciGfYeWX32+6mudxjBSiJA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQiMjz+AqjWfbQArpJPhnBRFXmJhsJyzhHhVx8Dt40SwIgCToI73/g2aoyZIhW6H8tmRB81y+17KBt9OuA09vXwpQ="}]}},"0.7.20130806":{"name":"autoprefixer","version":"0.7.20130806","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.36.0","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"0c8aa3684169d7c007416dc0f2330db9eb57d269","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130806.tgz","integrity":"sha512-BoMq7CpL5CknWV41xvdcQL05jbOXB8mVoUHM7C7NcH2MB9K9+LHVmSpGhBg3AhiBWLfs8ecDpmcrOLfSOc8oYw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDxobLs+WQoK2AVwbuT5JL+cv/JyLmfqrexKHjf2MHcyAiEAmY3YB1TLhsi9I35sXCMOIpZRQ4+kMrHvqJ24O57tRaY="}]}},"0.7.20130807":{"name":"autoprefixer","version":"0.7.20130807","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.36.1","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"65a42da469db2073b7ef2e47519928140e4ff203","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130807.tgz","integrity":"sha512-rWL9HdG8s6K5KPxxRrtJm8hzMHz4HthzOx+7taHMfzZN6tX16r+4fut1uL2ImPd41LoYJvc5bvm5QOIiZUIXQQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDuEsUZ0y0xjRP8rqwZrijSbHCnxoKFaQKF+xyKQPifjwIhAJqMOza7n1oaIP1ETRnl3yoovluiMayKSUjY9DA5zmnE"}]}},"0.7.20130808":{"name":"autoprefixer","version":"0.7.20130808","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.36.1","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"a3a0dc1870db9f1db6f65fc40768f19227c15707","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130808.tgz","integrity":"sha512-ech4B5S/x0Yczm9vQZlI7fml+E5be1lWH6J+/zCRCUCnYPB2FhBW9yg+cvrO3nWMd09zUE7FI7LDd0Lm8pG1vw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCw/KRrsRH6YWq1GG1hNuz9vTtljjc6Y7pwY8T3c3WAdAIgfN++KlZfR+YUkeH5qM3eKzdVj2D/+DDLBdMxLcCd0c0="}]}},"0.7.20130810":{"name":"autoprefixer","version":"0.7.20130810","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.36.1","rework":"0.17.3","mocha":"1.12.0","glob":"3.2.6","nib":"0.9.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"3b32d09a72f3a548192490ceb2c71d5516076f76","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130810.tgz","integrity":"sha512-CLV6lhaO/W60ZVsyDFnEz4QPDjvBZiTLwzx76z8lGjKgg4RmIs+PjRsAWaih4r4xWErPzMLJV6YM0kUQ2NQfbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWs7yQ6Z0NcWIazssPG4YKC8aAwOI+MdcSMUF9jgmQTAIgNfzLosTjRfEJ/sGeR98/qD7QVf+OuyiFHhDd+2VhFpw="}]}},"0.7.20130824":{"name":"autoprefixer","version":"0.7.20130824","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.37.0","rework":"0.17.4","mocha":"1.12.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"1fefbe10f9615844e4a47dfe51a555e7b4546ca9","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.7.20130824.tgz","integrity":"sha512-FGLnSgeb6jf8e/HQd3/yoQKWqVpJwqYxQRl0cVoKnW3RyQw+ZKtHruTQuwrmfbS21Zy0QBs+jWcCBnRx2x9fKw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL17jLpC/hc7hgVwtlrlBH81fRw1xsalu1FOC9WeadmwIgIB9R+2SmI3ybRVQ0NzwkgVYFDhGLRoQ95RTdBg0I688="}]}},"0.8.20130902":{"name":"autoprefixer","version":"0.8.20130902","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.37.0","rework":"0.17.4","mocha":"1.12.1","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"69cf6addb39eaa119ad41638f2166f5409c6d4c7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130902.tgz","integrity":"sha512-piUx7hYALbZfdfMQPzBCSKLSkYG+iv9ckZp4Sn/U7dULR3oyca04CrRkJcoyfW8Cx4LcOf4umeZYUV1jl9BggQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIP6qe0StbDhIprgvpjHwIgwLDHf5S5lCUfYAeOQbyfQIhAJOP3Tu7WZLyIwgF4Vy/nHFRrgjkqcbizNosfkHG1gzO"}]}},"0.8.20130903":{"name":"autoprefixer","version":"0.8.20130903","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.0","fs-extra":"0.6.3","should":"1.2.2","stylus":"0.37.0","rework":"0.17.4","mocha":"1.12.1","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"83c6e3bdf940a3e341d4db455db0fdde6eae4895","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130903.tgz","integrity":"sha512-vBIvZ9WhpD3yPOKOYl3QtjBpqKzoDa8nToBVGUNKh0I+cd1MHhja6v36fGZG9zLyco82r41TVgXB1YvEtTDT1w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDs+hWzCc6Ma2hyOtmbMohUE/LHKk2htpKn86rsztPJZAIhAOvZKlhcHk7OMYjeP9sVgT3LaAGUqE3gO+u0TLa/kTY1"}]}},"0.8.20130906":{"name":"autoprefixer","version":"0.8.20130906","dependencies":{"css-parse":"~> 1.5.2","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.2","fs-extra":"0.6.4","should":"1.2.2","stylus":"0.37.0","rework":"0.18.1","mocha":"1.12.1","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"eb7ae450ca2e5dd3fab333f4201c3e18a2279a1e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130906.tgz","integrity":"sha512-NWKXsWDqtHDLeXov4QeD8vPyqg8CCJpTLzZ5mTPVEb+fT4A/FkV1ANKILv66EXKzQcCRDiE7flyUQcY3V7/yiw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWb44KcO9DKvdaEvuXC1aebThLFOuSbeWdCOl4gWMNsAIgA/w5YHjCvfZp4bpQM9QJagGVPj3Sgy8rW7yPT8U++8Q="}]}},"0.8.20130911":{"name":"autoprefixer","version":"0.8.20130911","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.3","fs-extra":"0.6.4","should":"1.2.2","stylus":"0.37.0","rework":"0.18.1","mocha":"1.12.1","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"3a2d5c33266c8a22325e3a88f5e0d1f7911224ad","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130911.tgz","integrity":"sha512-6NTfSFySbZt3t1ELQL8RKI60hFvPA8ogi4nn7xPryGOQuqkfjmqHluRJQadXyBqv38t8mSRAJtqNoIAJY+NFAQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDeJ92ytqMLDUGmC/DuHJBVKpb1iTQTAKfCX4qwDxhU/AIgfKnBoTvKrpT4Ypwk8hyQbEJv7g+K9O0NXUG0X29npB4="}]}},"0.8.20130919":{"name":"autoprefixer","version":"0.8.20130919","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.6.4","should":"1.3.0","stylus":"0.37.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"2e5e7938090104f34e46dc753d02d71d6fb3cd0b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130919.tgz","integrity":"sha512-xOhb0Oub7+OhIVV/SDTuPsWzekfOm2Jazhy/u7yH6JSUte/N/+GLNe9OK58gD72QeRRl4mMiyanXOpLIVExxsA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOaC2XHpxxtIUtYf4KRVUCjjmivxjfretyn8xBlQyJXAIhANXtBc6pMOecExYuNPBBnZNJSSoR8kX5/L105cpdhYC7"}]}},"0.8.20130923":{"name":"autoprefixer","version":"0.8.20130923","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.6.4","should":"1.3.0","stylus":"0.37.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"9b2a36b9e26900db85eed4f72ff296351c98842c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20130923.tgz","integrity":"sha512-HIXIUt5M1aMLu9r5ANDVOzEEXdM5rGl+noMpk/Z6cnc4s/bMxIhPAuJF56oVtBqt+5WfyEZIIqYcjSRBtxDwow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBsLTkFgAFWrLCb/apCJm2cvbaBP5FGqfevhpdzyiqu9AiArUoVu5GxgxP5HRtergenW6CGc2Pj2tJ4Ymov2ZsgJ4g=="}]}},"0.8.20131001":{"name":"autoprefixer","version":"0.8.20131001","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.6.4","should":"1.3.0","stylus":"0.38.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"89ceda30818afd81bc4e9e7b66c35dc84ef59dfb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131001.tgz","integrity":"sha512-GJ53p8EklCq5y9BDA7HukExoJ4LG7nXkQyOM/7SHABHUqOK22qi34Z95IZzU7+Fx+DG1CTZNt/A5MXTb+Z8Rwg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfnSZYFtQHE4JFZ+Gta1xmRvj2kiADd5pKkb9qLo5V0wIgPCvqFzUivvapDRNYMKWlHjRkRRi05UWPcxYDZfkVzZA="}]}},"0.8.20131006":{"name":"autoprefixer","version":"0.8.20131006","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.6.4","should":"1.3.0","stylus":"0.38.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"244cb9b37631aa0a8e8a333d3ddbc648312b0d22","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131006.tgz","integrity":"sha512-CEJivBybvC01wWQr7n8IbqPESd9DAzqCmalmx+oBLD+8ptBgi5nkinMTJKyHpKEm3t04B5BCTk/KKkrIYsB9Ew==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDb2v6wngonYQCT8CNrymdsOlJBLykQ98Qk/GsfgTpMawIgMTHfFz1S1wS0sceTT44hcwE34gtXW+N7JxZayMHgak8="}]}},"0.8.20131007":{"name":"autoprefixer","version":"0.8.20131007","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.6.4","should":"1.3.0","stylus":"0.38.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"76e1dfec5068395314a066136747a98f61a03f01","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131007.tgz","integrity":"sha512-Zs2fK6ru7PSoLMNcvfr2q089NIRaxk5iC9076y39Bg31st0GAJzn6Rkg7vkmJURwk5bACs/VL7Djj7TDohe1ag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBTmp0g/sR2nCC3BtUvi1Nb/3oG8jTdbvx5Tti4MdieBAiBruNH8p8Of522qIOWFOFrGUFrUnXXpdC41JznV1fk4hQ=="}]}},"0.8.20131009":{"name":"autoprefixer","version":"0.8.20131009","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.7.0","should":"1.3.0","stylus":"0.38.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"e099983dd1b2a59f89479c2ddc85995feba8113d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131009.tgz","integrity":"sha512-KOQKK90jGlRW4dO6/NtM1wQsLPFtMh9tDIwXNmcAVfGQnFBScX5g+3+LjluYiowe7sS2cHjzvJ0vNIEsSevExw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAe8rpU7qpaK6CPGT9rFJEa2iz9kutkJnmtsO726I+lRAiEA8Ht7aSMTEwCt3xxO6sXjdA/IO8LXwkBbAQB0TzhmKbM="}]}},"0.8.20131015":{"name":"autoprefixer","version":"0.8.20131015","dependencies":{"css-parse":"~> 1.5.3","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.8.0","should":"2.0.1","stylus":"0.38.0","rework":"0.18.1","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"75864225d6970ef844c0cf6db463f77bc067d635","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131015.tgz","integrity":"sha512-SJSHthvifLgckAiFYFmCQ0EvylNtfSfwl/rACrxNK2mGTazhQoFvolRIY76xB5pFLmiHNY0sy37oewIHP1yTnw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEvqc5azeP6F77GuKYMGIIOll2A/ZDOLaFnbjZTqfCMRAiB8Bn2edpKZOO3mB3QLocd9bpLbutfPklvaM5WB43XqIg=="}]}},"0.8.20131017":{"name":"autoprefixer","version":"0.8.20131017","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.3.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.17.6","fs-extra":"0.8.0","should":"2.0.1","stylus":"0.38.0","rework":"0.18.2","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"44be191240baacf1374c212cf7b93357c68ccc1a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131017.tgz","integrity":"sha512-KSOAFhcdAfsY2aTY0oy2DeF28xFH5VPs3PngCp6cnaNZ9jAhG/fh0k6AP8jna1fhTO9QKihHcyZK6iiJ0SsjJg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpw5Isc2/OTCzXax2/xCDmI897siqF5gLIkTrxcCol3QIhAP1ETyjDS+2b2HVcIva7kv2vsKDvHmz8QACWIO1igLIp"}]}},"0.8.20131020":{"name":"autoprefixer","version":"0.8.20131020","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.3.2"},"devDependencies":{"coffee-script":"1.6.3","component":"0.18.0","fs-extra":"0.8.0","should":"2.0.1","stylus":"0.38.0","rework":"0.18.3","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"494ee28c93dd39be75f572f86000fba2f4c27dcf","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131020.tgz","integrity":"sha512-Ov1jQ0b6GonLuSb1cggEehjq53ROUVaCC0bDYtnpnBWHlPOfWMieiL7Jf4ITLHAXhCBu+liPIRM7UqqU01ZVBA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDY+/ivawantWlcPwoXsWeGzj1utBxgidyEeWFgyZxFgQIgCQe9uJJKxkrHkhr2m9Te6kFKJsld32Z84n0/EXyhZi0="}]}},"0.8.20131029":{"name":"autoprefixer","version":"0.8.20131029","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.3.2"},"devDependencies":{"coffee-script":"1.6.3","component":"0.18.0","fs-extra":"0.8.1","should":"2.0.2","stylus":"0.38.0","rework":"0.18.3","mocha":"1.13.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"3a8aee5bae85c8d364f472da3430a530827fdb66","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131029.tgz","integrity":"sha512-o2D++z95fjy0VmWQ131b0JflwIsOJe7xsYi5cWP6yQWO/iBDLRr5TOpsGKP98SApj00sMrkI9HKMs3pDNVVElQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIENoHjNQz/MFvXk0b/oM2+mWiTaje84+lIUSnpIHBT03AiEA0jFN5yyQw0mXJOwEhNR1xOaCeoKlfpwGkiZ1jkUT0R4="}]}},"0.8.20131104":{"name":"autoprefixer","version":"0.8.20131104","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.3.2"},"devDependencies":{"coffee-script":"1.6.3","component":"0.18.0","fs-extra":"0.8.1","should":"2.0.2","stylus":"0.39.4","rework":"0.18.3","mocha":"1.14.0","glob":"3.2.6","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"39bdf9a7e909b2be0cd7931be6f98c2c96cd67c7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131104.tgz","integrity":"sha512-OWFSZpTFBECO3bvUysiOI++xBN+DtCKN+jY8Nd9zyO2WWzjBB6LVy5KD9Tot+/inxGky7JsGDZ9g/mdTQttNrQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD81Nb2JlqkG4jVVmpS5CwmhjB0gLWGpEyFUnDgHQ1lRQIhANtJl2eKxuEfR3rghJ4dMqfjAJp+w8F4zN/z7o2/L47R"}]}},"0.8.20131209":{"name":"autoprefixer","version":"0.8.20131209","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.4.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.18.0","fs-extra":"0.8.1","should":"2.1.1","stylus":"0.41.0","rework":"0.18.3","mocha":"1.15.1","glob":"3.2.7","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"90ace7e8bbb6af085758fa0d3d3d4ddaa425324f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131209.tgz","integrity":"sha512-I8mi1mPfTwcAC7h8t+u7FFpNfrkds033vQfMHg1Cyp2P1Ovk3ELgrYF+CvbVim6hz5tenv+icQnCf/EzthYXag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHErouHyIvjwjhH9gEDjTabLEYeXEMukqXx6qA4KavRAAiEAspcvnNojWkGOm5BXWjRDYRPPqZj4F7vFy+N7UuJ2m18="}]}},"0.8.20131213":{"name":"autoprefixer","version":"0.8.20131213","dependencies":{"css-parse":"~> 1.6.0","css-stringify":"~> 1.4.1"},"devDependencies":{"coffee-script":"1.6.3","component":"0.18.0","fs-extra":"0.8.1","should":"2.1.1","stylus":"0.41.3","rework":"0.18.3","mocha":"1.15.1","glob":"3.2.7","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"fe0a9166576087e2819758bd09ddf62859fda20d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-0.8.20131213.tgz","integrity":"sha512-Aoxj5E4zF41nnERg6ZXnUJOltrGFDyqVd90SJPrkXKDvkmESb5LjDpbSvMfWz0T3vjC7RJVXhAegmdkROM31Aw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqr3YfuwUl9bmNxMT4P3bHZtyMSU+mp8/ltV4SkXz5pQIgRmPAFxyxjG0z23lktEW0ZNwhhfzJ7HrswPfzCjkcuK4="}]}},"1.0.20131222":{"name":"autoprefixer","version":"1.0.20131222","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.6.3","browserify":"3.13.0","should":"2.1.1","stylus":"0.41.3","mocha":"1.16.1","glob":"3.2.7","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"87d2d65e8ba6728fb25498814731cf45b5cfcb16","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20131222.tgz","integrity":"sha512-toDYxm5E4vNxr1LMxmAGiEndUKnkmUxNfu5Goc6Ill5x99y78qSMcvVkkfVFtCnTntCinmL74mmn+P9VC5+OjA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9KMgO72hzJ9tUe4ZZFWjegkT1GGUSe+Ocxl6hkBkNUAIgFpL3foKgRFyOmj3Kl4AeuwPWNoOrZT7xnterpvqnq8g="}]}},"1.0.20140103":{"name":"autoprefixer","version":"1.0.20140103","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.6.3","browserify":"3.18.0","should":"2.1.1","stylus":"0.41.3","mocha":"1.16.2","glob":"3.2.7","nib":"1.0.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"cde864bc248892fc878b1b7fa696d21e869bccf4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140103.tgz","integrity":"sha512-FYTslAOGccNxFsHK99LMECoURUPGhaSutkR+Y/QVGSqy9bmtOFqf5yOOOgS+NDnCW8Jjwwlf3NG32/rkPsvqKQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRirHRKALe3oH79fWkEuHhdyYbZs+L2AjXlt4hWFPSXQIhAOJWY1IXxPBqf0SaJ4b6u3v3402QugjDxDY16eSxKMKE"}]}},"1.0.20140109":{"name":"autoprefixer","version":"1.0.20140109","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.6.3","browserify":"3.19.1","should":"2.1.1","stylus":"0.42.0","mocha":"1.17.0","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"7af0c3c4536617dcf7cef325d76de28033633787","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140109.tgz","integrity":"sha512-Iqo+BBZGUc9g+KHKcnRDio+M3I0zfX71OWLx3ElJn+/xgjW8RNbHn04PWJg6scsPtfwn/iAA/qBMnInEIfBb/w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDthHekpyuRjLLc7XXWtVt6sy5WNUUNwrMRlK1jcXEQDAiBcZfdufkFT2Z4RFm7HMW65MmYA+6kVhHxbaBLi0h7rQQ=="}]}},"1.0.20140110":{"name":"autoprefixer","version":"1.0.20140110","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.6.3","browserify":"3.19.1","should":"2.1.1","stylus":"0.42.0","mocha":"1.17.0","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"2c1cc546fdb6b4aabf3ea3e3b84d0a86594c1648","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140110.tgz","integrity":"sha512-WB5zamYjPva3+Rk+rKDfpczAJKthhb0LjmCWsEAs04UK56uKnIfvv5O6RL8PBI422RicYkdlJenHxE9QcH8aTA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzyYnt0BBBBsWsP3ekY3vv8pbagIuuThw9xm+R6swFKgIgV1TLP69iRd1zNqkqCwYveqdsT+thwgWUKninWT9I9dE="}]}},"1.0.20140117":{"name":"autoprefixer","version":"1.0.20140117","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.6.3","browserify":"3.20.0","should":"2.1.1","stylus":"0.42.0","mocha":"1.17.0","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"1b4706f06f779c86ed316fd7eef1f335939c20f7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140117.tgz","integrity":"sha512-7JYpYZ7v1FSIVIzIkQP040CpEWTZCAEVOTpmoD8018d0sJiBo9gmYjzw4UhXNDX3XNEHrUFXShEziqRbxGuC7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCF5VS5BhK9lIqt7NRs6oBeMezGKUmrr+mwum1M71tVFwIhALKb7MGF0exm4nwW8MyQy6xqrHX7WiU3qkGgAcbGaAps"}]}},"1.0.20140130":{"name":"autoprefixer","version":"1.0.20140130","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.24.6","should":"3.1.2","stylus":"0.42.1","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"75bb4b3993b1179d412b68832908a4ad23fa218c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140130.tgz","integrity":"sha512-Et0WWB/BqKoA8BkzIyfrx+Y0N290GEx8Ms3t8dy22MZc+xfEttytaaBx7XHK9Nf7xot7Bz0QaKPFcq6YKm7qwg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDpvAFz0cJJHadeX2H221uWgT6RqTKMCwDyFB1WkLJ9AwIgL1CT+NciySTFPHCNgsmBzp8TMuqLYltBK1DXtgT0sxY="}]}},"1.0.20140203":{"name":"autoprefixer","version":"1.0.20140203","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.24.10","should":"3.1.2","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"7894f87532e1b9fb907f367f9de3327bc457d1d7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140203.tgz","integrity":"sha512-EIGT0HIn2kkSc6KDLRcbB7XzoWcq/IQex3i/lCJo4snJaw7FtByuZcCjs4BE3bR4Ic+3gsKy49sd7ieC/g0sdw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC9Y9YTqv4TaIX7VCb8/U344Igusi74v2gRCjhscV+vDQIhAMq148PSgNl2GExLKrJe3CasTwLXfXE2JoQShnKEcSDm"}]}},"1.0.20140213":{"name":"autoprefixer","version":"1.0.20140213","dependencies":{"postcss":"~0.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.28.2","should":"3.1.2","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"2557eaddf931421676b65d0445fa0acdc459a054","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.0.20140213.tgz","integrity":"sha512-A90Yjvmf+Ww0NuWfYyqUshQTc+tTIo8p+gGeJbaPTdAQ095+EpTfC4GaxlBZ1fSJbE33Ouz4NipP1/z8XeZL4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8bLknlNo78z/uoHYni1liISew/12C0ktzv2uz1i0WWAIgaWN3P2TWWFJy247qnjrcKoXXhtkwsDfG6MpI2rBSfkg="}]}},"1.1.20140218":{"name":"autoprefixer","version":"1.1.20140218","dependencies":{"postcss":"~0.3.1","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.30.1","should":"3.1.2","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"8c41399875dcc872caa89234c2f46aaa29642aba","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140218.tgz","integrity":"sha512-6hIrp9awuswWyqIcqjvAQJHOXcdLmMFbq2dP4Nhi5DobL8g8fcTsQnUjhlUmwc+gPpC09/3J8OzsUUTaxtXUlw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB35sgcYhA9Vy0YvO2sZulzUnNg4PD0icAUyKKo/vUbKAiBzVclt38mX6QEoDo6xhWvcSGnNqYocJIm/U0jeRPs+nQ=="}]}},"1.1.20140222":{"name":"autoprefixer","version":"1.1.20140222","dependencies":{"postcss":"~0.3.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.30.2","should":"3.1.2","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"0ad5eaf4064bc4ab0204cd85dd1feab4b67656cf","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140222.tgz","integrity":"sha512-f9UQXVsyXixKmx5648mkJwl0XFnmKF1tX9K8rFYmTo6NBGLC2KXhDeqfm6qjzKc+fRr8Kzmxey+GNJlkuUA9jg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHJcDANnOFZfl0WjQSaYxqK0rslmEgyTu0k13/8decPpAiEAsewb7G/8j0SwDPCoPK8jGSFe+Jpz5v6/zDYt04Xyr4g="}]}},"1.1.20140226":{"name":"autoprefixer","version":"1.1.20140226","dependencies":{"postcss":"~0.3.2","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.31.2","should":"3.1.3","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"da294050ea8aa0292bbb31aeb4687152ca5f3b87","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140226.tgz","integrity":"sha512-IHt2DlfhR3EAUGSM5m0WxltWt3FS42KL0NNyFu7fTfPgJYmR3t1sw1OHT8xUrQfipgzCOW4yc1zK4EWmzYderw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICos80PxE6mJbA1N/wyXitEQS44DRkvahjbAwqQ6rx2rAiEAsg1HayeVPnRg1W+heup7QWN7lwLsp/C8GNvH1et2HyQ="}]}},"1.1.20140302":{"name":"autoprefixer","version":"1.1.20140302","dependencies":{"postcss":"~0.3.3","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.31.2","should":"3.1.3","stylus":"0.42.2","mocha":"1.17.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"4de90cf16a77492188f3cb9e91875828ead376eb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140302.tgz","integrity":"sha512-EVvpx/apMkux6FrW1mXAJ3lZViLmJnolKI+qybrK/6Qi57upR/JNau2LIDISQ+3Mvo0cWICEbMBeJti2ALjllw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCF6OzUxAudjs3BI370TRIkfqFAahANTaZS7lJP/gm5cgIhAJBV1a1YbogbTXsXFS+8k9L0mBrFch6tTesxspAmus5n"}]}},"1.1.20140319":{"name":"autoprefixer","version":"1.1.20140319","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.33.0","should":"3.1.4","stylus":"0.42.3","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"dc727872f32076b6a3108773d8bc748e1de97d61","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140319.tgz","integrity":"sha512-i695G7+nz1/dkbldM6cDTv3WTJGI1QljWdeaamNysfNjYJ1j38mbdochE5E3hc3Kfp2xKCwOdvU6A999z4lXBA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4LEjdemP+XhOt5zlMZgsshPPwIxcGSWfAaHMSKoNW0AIgMLohoO/zxDfxcOomJH23gUv94r47yvVTQRE4DGUk2aY="}]}},"1.1.20140327":{"name":"autoprefixer","version":"1.1.20140327","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.33.0","should":"3.1.4","stylus":"0.42.3","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"530d78aa3e2f740ce45ca17ffc92384bb4f3241e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140327.tgz","integrity":"sha512-3gVmLExL7vxO2xniNkHzawXAKe008ZfGxtc1nrxEnTpmOC20gAMW2cOPNN4V6iQLLrAxiZtRlYFL/eIGa8iFmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvTuzH+QvuIxQ82ZkqyAUtu4SwfIUIOQ+VYcPmhHQpAAIgHNlL5KXLneCj6OE4Q9h82W1u8+/f6w9wMQ+ZGgnj4yo="}]}},"1.1.20140403":{"name":"autoprefixer","version":"1.1.20140403","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.38.0","should":"3.2.0","stylus":"0.42.3","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"dadf0ff234c51b4d05f20fee44e0cf0997f6052e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140403.tgz","integrity":"sha512-i6hqSrONKlsN++DKpR+JhvW1hW4xoAdLXxXk+EQfIyo0/+wgSfHzX9UOvUIEiJi6qv5Uk0KNsjb/tFdK60dXHQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHAKXfjt9xBQ8rVAzcgPH4mYXzAW4IEsR0kaJZYNvR/fAiAneqdqA6+e8TFXBsmFJ4iF75QfkjueC5N5GtpDizqodg=="}]}},"1.1.20140410":{"name":"autoprefixer","version":"1.1.20140410","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.39.0","should":"3.3.0","stylus":"0.43.1","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"c57173ea6c13468c4fb4a26dae36144b86b34c29","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140410.tgz","integrity":"sha512-SMDFGirF1wC26S1nwkPfLetnOtbW6ItYFzSKxKggpSNzWGMFuzjgEfUgN4be1xR4WQcOA8cSvbr7zZHGMwK45A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQChJLsrX/HV5EPOxBxY7xln+sdY7AG1HhIU0Tm4kbNNYAIhAMTx09JKiDB/0R1Bc6pwmFCQb9r4eHfPKPjtBM/O1OYL"}]}},"1.1.20140429":{"name":"autoprefixer","version":"1.1.20140429","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.44.2","should":"3.3.1","stylus":"0.43.1","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"197a824eb17df27f2dd5d621987b57da06c4331f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140429.tgz","integrity":"sha512-jOrMvUgMAkcoooVT2BoYvGu/EwEriAvDgBzcdrp31gtp+9IDo8ADCaDbwLsj9b//8QZp38KaKiCVNsxtgELvLw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOzsd5hF/LN6w8KWcgxisbre+OHurXDwOqZ8Yg5PkdmQIgV9j4HD6omrvA4MstF7B9qLKkukzHLg/f0MR4Ntodlr4="}]}},"1.1.20140430":{"name":"autoprefixer","version":"1.1.20140430","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"3.44.2","should":"3.3.1","stylus":"0.44.0","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d7bebc41bd6729b2fb9081325e5d0dbf7fcca5a6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140430.tgz","integrity":"sha512-NufBDO/QqzFbSR4PHArcT/QRAR7jRw12HcO7rvMqrPmyGQhngBAZ4Rb+HJgJSWqzcQHIPA0Z8KKdZSX4Hkfm4g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDQkW+d3ijt+d54A1TCeOmgsoqH4r4AEublERyvl+3x5AiEA0/s6OTuFH3I+1PC512lQWSuClUVn1Lfh+E7jM5tjdRQ="}]}},"1.1.20140510":{"name":"autoprefixer","version":"1.1.20140510","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.1","should":"3.3.1","stylus":"0.44.0","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"d15fa7f205f9656b69035fee78b96f884a148fba","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140510.tgz","integrity":"sha512-csKrjZjJV4SZs/5CpMztlUZ3RcUsZgAf7pHxfit3vrmxuAt0cIzz57G11lnD/Ng8GyFiLXrZBGn8B4oUMM459Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0D1gNFB6AZo4ehtVJMZj+hYeP0B/NBgf3tg2Z6z2VMgIgRR66ozNj5xfugE2g6+PJbRqyPEmCdnym+3LR8Mkybwk="}]}},"1.1.20140512":{"name":"autoprefixer","version":"1.1.20140512","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.2","should":"3.3.1","stylus":"0.45.0","mocha":"1.18.2","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"73891071ab498f7af0a8ada6be5ff8ca47d41844","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140512.tgz","integrity":"sha512-r5Sae07cUZy4H14dYZWCAy15EKamPe+jVe+YTvvi/UEQ8yDcztbDPh+x7Edm5124H+WS3S+wP9SfB3QgRIE9YA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHjIwraEgG22uZ+42b00gl5b6CVNOg1kdW1qNZF3emiEAiEAq+HFYZR42i0uFcpRerHTKOYEjtXeZEhkclnqieDqlnc="}]}},"1.1.20140521":{"name":"autoprefixer","version":"1.1.20140521","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.8.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.5","should":"3.3.1","stylus":"0.45.1","mocha":"1.19.0","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"5453219cb14ffccc92d3362bd7ea7ff0475fede4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140521.tgz","integrity":"sha512-qLBR9Cj/0Qmlvhk17R2oxzZAhmCCiyUbpMKNBdWY4/0zaHejFkx4aSd2u8QrJ3f0KeE2Yoj+8R4Xj5Vqf+bqEQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC46yXkM1K3iGiixmP7oxNKWJIDeykvom7I13/6Ux4J3AiEAi7ZeBK+AoMi5xrvSHuEl2b6ZBKMWpTVlRckKuegT5H4="}]}},"1.1.20140523":{"name":"autoprefixer","version":"1.1.20140523","dependencies":{"postcss":"~0.3.4","fs-extra":"~0.9.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.5","should":"3.3.1","stylus":"0.45.1","mocha":"1.19.0","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"8b90eae7404234f51e28fc97a3526f7355a10937","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140523.tgz","integrity":"sha512-sYvZBqUt7lfDjCRkypVqERBvZD4WaFBOrYWbrOh8bbOjl0SKsBiV8aR4xRBU1SXen1O8+c8S9vx+qmay18Q5lA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVAN2VZtLX5bNx6utqDBWTfOmzGGlpt/XUg01oDtc37gIhAIE2eqti5XUUsHUPP5rvVOycBnjVZezfLxqRz/WriVZV"}]}},"1.1.20140605":{"name":"autoprefixer","version":"1.1.20140605","dependencies":{"postcss":"~0.3.5","fs-extra":"~0.9.1"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.8","should":"4.0.1","stylus":"0.46.2","mocha":"1.20.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"2534cd5d041709ba221187713b81b3862b67db7f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.1.20140605.tgz","integrity":"sha512-jhkFOzdINLOhusBL6ipUcKM9gvHAbsgq98JML68FCqrL7MCvn6t5YsCBLjmiBbFOfJgBZ91gWkQX42mW96Pdug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwtDcgc8uNxceNZDxMT4mngc+AAh/9OjBiPAOEClgvXAIhAI1uL0kwnfUjkiNuMo4nw1hxxoDwGP7epVwqkSWrtn91"}]}},"1.2.0":{"name":"autoprefixer","version":"1.2.0","dependencies":{"postcss":"~0.3.5","fs-extra":"~0.9.1","caniuse-db":"~1.0"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.9","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"ed9c5cb0e48364429fa1a90a9c39d95b156c82f4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.2.0.tgz","integrity":"sha512-PfP+UmmSsnB7wmdLnUnPRGE3lQ/wqWrrhmdgaXLsNxO55uqCcCOhlQ+O0GrpwveELFBAay+4OpeKqwkKlxrtpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAk06fNz8vFRzgwCxH64c1leHm7/Brr+6SV+aINF2IL0AiEA8SLzdhrMhFsQnG0IwIFoIJZMgGLvXOKLtLGv6t3BTMs="}]}},"1.3.0":{"name":"autoprefixer","version":"1.3.0","dependencies":{"postcss":"~0.3.5","fs-extra":"~0.9.1","caniuse-db":"1.0.20140618 - 2"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.11","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"dcd97e0d4e3ade99a0da5ccd76f78bbe48d5ff41","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.3.0.tgz","integrity":"sha512-3qB7f9ubsztNO/1Ct6NJHxcQno3p4E6HoEYCCy4+wbHO5dR88sasjC02DhmMXdWqNI0cLZRR2U6ZrxAozuY88w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4fnVMsjN2q4G3QU5gynuvAsEZJFvoeQKzEF6G36/6WAIge16MJWSLwPeF5OQgPRqLdrXS8AZo18B/UPBI2WuzL7U="}]}},"1.3.1":{"name":"autoprefixer","version":"1.3.1","dependencies":{"postcss":"~0.3.5","fs-extra":"~0.9.1","caniuse-db":"1.0.20140618 - 2"},"devDependencies":{"coffee-script":"1.7.1","browserify":"4.1.11","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"bd731b558daabbf4556a74f75766f9e78102fefb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-1.3.1.tgz","integrity":"sha512-TUMhFBOjSFVRuxLlU3YNr6ZyagzPPpXbveCk2qSxEoE8GCK1D2k8PpNTF8zFc7S3QosTIZcC1PVm3YOJFcV8WQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEq7mU+cm97oFtXcZX9gwcDoO1QXhZmlo60nvKj1nT3VAiEAviQf/WKMquqztl2pyPxQ/eNeqe1/Hn0BR4x5VoZBh9E="}]}},"2.0.0":{"name":"autoprefixer","version":"2.0.0","dependencies":{"caniuse-db":"^1.0.20140622","fs-extra":"~0.9.1","postcss":"~1.0.0"},"devDependencies":{"browserify":"4.1.11","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"f074cb735ceccc4e79f73f1e4be5f9deadb004d5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.0.0.tgz","integrity":"sha512-qHwd3K/eOb5nJDZSUnTTusIl2G2Q82MpLMYv2POcxYqPGhgFAimYTPtGQxQFkR6ZuQ7/dHdT27CX7FeptbJBCg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCG/LkHvLUPSMCHbYxyoZeLis9k81+zeWpKW4FfIZdUJAIge8OeFWkoVkoYisLbehJWyk4zdlnroSiwV0CRkqrR4oQ="}]}},"2.0.1":{"name":"autoprefixer","version":"2.0.1","dependencies":{"caniuse-db":"^1.0.20140626","fs-extra":"~0.9.1","postcss":"~1.0.0"},"devDependencies":{"browserify":"4.2.0","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"eaf043ede53fd20bfca4a37be06e9ae98edf76b2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.0.1.tgz","integrity":"sha512-SKcec6fmRmc8WXUIZFJmjSfI68lNCgHmm+YrxEPkGfMNXLDTR8lurGOpfiyMfqoVlHP7QpUUrCLlD7vW9b4PtQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDxeQ+/Lr2zMbGumc8JlQoHzuP1KseAHzu+MwH8KetvMAiEA4rVkoGAy9xc7jVwO4i8XieQ0b3jThm7qYsLiPGaNIaM="}]}},"2.0.2":{"name":"autoprefixer","version":"2.0.2","dependencies":{"caniuse-db":"^1.0.20140628","fs-extra":"~0.10.0","postcss":"~1.0.0"},"devDependencies":{"browserify":"4.2.0","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"e84c05387c11b45bb24b785bacde9b48b84b6f3e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.0.2.tgz","integrity":"sha512-fmusJrMtopwuC50GStE6d5rzyxkQ4xzGmIl7qGR7c1zxuhw3kg5rOHtfd3uaWr2YGD7S0XARiHL/4QrJmHq7tQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDNotVQ4INbHuYRIM09Kk1nSzW9kVPm0L/Gs72wjpV6mAiBXFbyy/k4VEK4dLHpH0sPcY4GOzCVPbCvzXufSH2B8mg=="}]}},"2.1.0":{"name":"autoprefixer","version":"2.1.0","dependencies":{"caniuse-db":"^1.0.20140628","fs-extra":"~0.10.0","postcss":"~1.0.0"},"devDependencies":{"browserify":"4.2.0","should":"4.0.4","stylus":"0.46.3","mocha":"1.20.1","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"93ec96f3609989bf745b09a0e75df09128ca206b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.1.0.tgz","integrity":"sha512-ixiaXT0WchkKWN+IEeut7x/+xrRuTdJIo3BJdktEhE1wVP6e0FrqbDQr+UqlrfUwTSbkoWtJF0RzEPLPvtvQig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpdVZusZNsrVgHluc67PyT8RNsMUz5po73Q9QhrIod3QIhAJtNM09e+pFSLAq3O6eXAMGOybn7+WMyoZo0xX5AWJZn"}]}},"2.1.1":{"name":"autoprefixer","version":"2.1.1","dependencies":{"caniuse-db":"^1.0.20140710","fs-extra":"~0.10.0","postcss":"~1.0.0"},"devDependencies":{"browserify":"4.2.1","should":"4.0.4","stylus":"0.47.1","mocha":"1.20.1","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"6fa859627961e7bfcba9321d4daaf8141b53be8e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.1.1.tgz","integrity":"sha512-SQJEG6k19BTg6ToOteapic2kaJFW6ObPKq5JTWdA/fbJWMFgS6ZjnEqMkNRbe00Er6Gc7fSmYtU16qqwsH2l7Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNheVpkdxmyYMIikTIoFJX6bOoy/Q7YS39uuYAaOwr6gIhAKX3VYsa/vYQm5gcC4jVPpXA3ab3xW1PCh+QqbZgvQE8"}]}},"2.2.0":{"name":"autoprefixer","version":"2.2.0","dependencies":{"caniuse-db":"^1.0.20140727","fs-extra":"~0.10.0","postcss":"~2.1.0"},"devDependencies":{"browserify":"5.9.1","should":"4.0.4","stylus":"0.47.3","mocha":"1.21.3","nib":"1.0.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"shasum":"c7c7936a280a64f8fa0e5f6108ba22f92c639633","tarball":"http://localhost:4260/autoprefixer/autoprefixer-2.2.0.tgz","integrity":"sha512-yNj1+HVcvTxIaFhP6reZc7uv0UluLUO+bdn/JKABaTqSzTKakFMVDDaY3IT67OvsTjBnw571SE5w5mNYsqgbeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHsMvSsIbKaSpCZ0607Jo8SKl7fe+OhM38x1yRRg4jqgAiEAsc8HnVcU+qq3RdS+E4mLYRzcMMEpx3U1L16h68sFxm0="}]}},"3.0.0":{"name":"autoprefixer","version":"3.0.0","dependencies":{"autoprefixer-core":"~3.0.0","fs-extra":"~0.11.0","postcss":"~2.2.1"},"devDependencies":{"gulp-es6-transpiler":"1.0.0","gulp-json-editor":"2.0.2","jshint-stylish":"0.4.0","gulp-replace":"0.4.0","gulp-jshint":"1.8.4","gulp-mocha":"1.0.0","gulp-util":"3.0.0","fs-extra":"0.11.0","request":"2.40.0","should":"4.0.4","stylus":"0.48.1","mocha":"1.21.4","gulp":"3.8.7","nib":"1.0.3","es6-transpiler":"~0.7.14-2"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"805a1bba79ba83082c575260180dce15bc1fcb99","tarball":"http://localhost:4260/autoprefixer/autoprefixer-3.0.0.tgz","integrity":"sha512-nxjVRGerD74BUMANTu/IkflqZk9dBnn+Dpa6SdKZcPUlYalnd8IEG+I7dHT0LJD+nCFvIiWhDWk+QXA+McP7GQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGGQOEUfESCHrxOXEdeuwkcdNORbD1zGioRFcKR7NbS8AiAEkbwMoOezLtd3w4yNu5wXMdjZyTJKg7VFqP/T+nTQZA=="}]}},"3.1.0":{"name":"autoprefixer","version":"3.1.0","dependencies":{"autoprefixer-core":"~3.1.0","fs-extra":"~0.11.1","postcss":"~2.2.4"},"devDependencies":{"gulp-es6-transpiler":"1.0.0","gulp-json-editor":"2.0.2","jshint-stylish":"0.4.0","gulp-replace":"0.4.0","gulp-jshint":"1.8.4","gulp-mocha":"1.1.0","gulp-util":"3.0.1","fs-extra":"0.11.0","request":"2.42.0","should":"4.0.4","stylus":"0.48.1","mocha":"1.21.4","gulp":"3.8.8","nib":"1.0.3","es6-transpiler":"~0.7.17"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"b50e6cc88a543ff81018dfab0467ea7570a7a172","tarball":"http://localhost:4260/autoprefixer/autoprefixer-3.1.0.tgz","integrity":"sha512-WiGslcCwgVz2ywhyYQDkereK5/kGbCB2HJmfCStVnlyaBEAD8HNo7CdCzwwb8/2MOQH1MScXHfiMgO9LvFafnA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCUo1PhvWfC0Caa5n2f3KEIEahhtxCAF1JctHPAeaTH5QIgRoc0nV6phVl/YZ27VlSThjt8Ffuixji5DGWIN6LtShA="}]}},"4.0.0":{"name":"autoprefixer","version":"4.0.0","dependencies":{"autoprefixer-core":"~4.0.0","fs-extra":"~0.11.1","postcss":"~3.0.1"},"devDependencies":{"gulp-bench-summary":"0.1.0","gulp-json-editor":"2.2.1","jshint-stylish":"1.0.0","gulp-replace":"0.5.0","gulp-jshint":"1.9.0","gulp-bench":"1.1.0","gulp-mocha":"1.1.1","gulp-6to5":"1.0.1","gulp-util":"3.0.1","fs-extra":"0.12.0","request":"2.48.0","stylus":"0.49.3","mocha":"2.0.1","gulp":"3.8.10","chai":"1.10.0","nib":"1.0.4","6to5":"1.12.10"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"bf58b968008aca51b0945b48df0c6f4ca2cba046","tarball":"http://localhost:4260/autoprefixer/autoprefixer-4.0.0.tgz","integrity":"sha512-p02oUuDYYmptj9HFoazilsVpQtdW4JvYlgIXivWiFOwZfwENWj6KJ5XsO1tEJWJVyalC38ru806To3yVJLSTzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICGHKCiQKKSoa6K06KXk7h1NCYTJgaQN7vJHVdiFjOeVAiEA03MOc/TgObZ7Y8LI8Xj5dWhizvs+RfnxWltyJRPESfk="}]}},"5.0.0":{"name":"autoprefixer","version":"5.0.0","dependencies":{"autoprefixer-core":"~5.0.0","fs-extra":"~0.14.0","postcss":"~4.0.1"},"devDependencies":{"gulp-bench-summary":"0.1.0","gulp-json-editor":"2.2.1","jshint-stylish":"1.0.0","gulp-replace":"0.5.0","gulp-jshint":"1.9.0","gulp-bench":"1.1.0","gulp-mocha":"2.0.0","gulp-6to5":"2.0.0","gulp-util":"3.0.2","request":"2.51.0","stylus":"0.49.3","mocha":"2.1.0","gulp":"3.8.10","chai":"1.10.0","nib":"1.0.4","6to5":"2.12.2"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"d7ae05093b187ad2214503a8112fad598f0c3ce1","tarball":"http://localhost:4260/autoprefixer/autoprefixer-5.0.0.tgz","integrity":"sha512-xjMPs+buOPk/xBsLZHVXRcSUVvSjoc76EdgWV1CkKYbBWg9KFRQ2j/ny0Mg7nRdl/41sTyddLuAKSptK3NlOJw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCaluiE3EiR450V9HqqnPwdlPLTKvSg1TmUfobGrcxGCgIgQo0hWC5wo6bfQlLA7oCpIC5hW8m071kEK/q2bPPwuHk="}]}},"5.1.0":{"name":"autoprefixer","version":"5.1.0","dependencies":{"autoprefixer-core":"~5.1.0","fs-extra":"~0.16.3","postcss":"~4.0.2"},"devDependencies":{"gulp-bench-summary":"0.1.0","gulp-json-editor":"2.2.1","jshint-stylish":"1.0.0","gulp-replace":"0.5.2","gulp-jshint":"1.9.0","gulp-bench":"1.1.0","gulp-mocha":"2.0.0","gulp-6to5":"3.0.0","gulp-util":"3.0.2","request":"2.51.0","stylus":"0.49.3","mocha":"2.1.0","gulp":"3.8.10","chai":"1.10.0","nib":"1.1.0","6to5":"3.0.16"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"2db51c2461b294c35b7745e197791735cf54af41","tarball":"http://localhost:4260/autoprefixer/autoprefixer-5.1.0.tgz","integrity":"sha512-sstlPEyEfeZu9T4kX080iO2A2peUL9Rrh8nwAXUULO59r/Rqg3kBqK/kGdZ9qDSrCyeU4BNTPTM+dttLa7HTVw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICX3mDN07mEMBBIN1nktFG+oPlpxIsaIcyH105Y0ZHbpAiEA/96MNeYDLowKORTIXvJGRyNwHpF7GSuL9SzqfdT8Tec="}]}},"5.1.1":{"name":"autoprefixer","version":"5.1.1","dependencies":{"autoprefixer-core":"~5.1.9","fs-extra":"~0.18.0","postcss":"~4.0.6"},"devDependencies":{"gulp-bench-summary":"0.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.3","gulp-eslint":"0.9.0","gulp-bench":"1.1.0","gulp-mocha":"2.0.1","gulp-babel":"5.1.0","gulp-util":"3.0.4","request":"2.55.0","stylus":"0.50.0","mocha":"2.2.4","gulp":"3.8.11","chai":"2.2.0","nib":"1.1.0","babel-core":"5.1.4"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"1c4b4e51be1afa9cd7c05d52a6edf606fcfab4f2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-5.1.1.tgz","integrity":"sha512-wTI8FEXMTkOkwSdRSOfW9KV1K0wH3/K6Cd5vUQxRKdLMhXyaGmRpyrqTBLjStT6B14ZhOBnEGC1NcNgd+4mPkA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICwt2JzEzRu38Pl0JMSIXr8jnSmG+UVKe6LqZL7EJ4FgAiEAntry2k9uZBZB+7VKF1SsoBJ5WBz+tIqe53nNnRyKwcY="}]}},"5.2.0":{"name":"autoprefixer","version":"5.2.0","dependencies":{"autoprefixer-core":"~5.2.0","fs-extra":"~0.18.4","postcss":"~4.1.11"},"devDependencies":{"gulp-json-editor":"2.2.1","gulp-replace":"0.5.3","gulp-eslint":"0.12.0","gulp-mocha":"2.1.0","gulp-babel":"5.1.0","mocha":"2.2.5","gulp":"3.8.11","chai":"2.3.0","babel-core":"5.4.7"},"bin":{"autoprefixer":"autoprefixer"},"dist":{"shasum":"94ad5c1940c0ac2f93f365918ebcc36f8a065491","tarball":"http://localhost:4260/autoprefixer/autoprefixer-5.2.0.tgz","integrity":"sha512-SSm4bPAjdQzWuShw81m3/Bfvf6FBH3Vtu7lEOBvDfpRaQeOXxmPsEXaUtC/7eqgGTYS1iryAQzhrBva0AZp9Gg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHWY9oRYO+jOOZyPi6yI+hnUFYz172Y3UoO41p8J74s1AiEA/y/Taoguuidi7NIwQsDHC1qQDXMlLhoC8vCOid+ZM1s="}]}},"6.0.0":{"name":"autoprefixer","version":"6.0.0","dependencies":{"num2fraction":"^1.1.0","browserslist":"~1.0.0","caniuse-db":"^1.0.30000291","postcss":"^5.0.4"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.1.3","browserify":"11.0.1","fs-extra":"0.24.0","should":"7.1.0","mocha":"2.3.0","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"b0e40d8a344bf652a7be950589c6a4cac6d74a1f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.0.0.tgz","integrity":"sha512-H/DWz9UwR1WlB2TcwFXp7V59nQwAYSCl0w1D5Mbo9/ETv1cX2jEes7u3AmS0kh2NPvHocZJWdYHhqDjx8HpXAw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOhDRTn/CuTKgAcgdmrs0/YcG0//4qE98V9YvIbWkA/AIgfGG4fwf4MQaC8zM1coygZce2sscBSJho7lEUGdDOnVo="}]}},"6.0.1":{"name":"autoprefixer","version":"6.0.1","dependencies":{"num2fraction":"^1.1.0","browserslist":"~1.0.0","caniuse-db":"^1.0.30000296","postcss":"^5.0.4"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.1.3","browserify":"11.0.1","fs-extra":"0.24.0","should":"7.1.0","mocha":"2.3.0","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"01e2c40aa8ffdb1837e0b3519260e731e87e4e0a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.0.1.tgz","integrity":"sha512-r7f7y808M7rmLsYFZX1YOHbGXyKrQegdqYLkb+6ZUM6mluioIFI6VL4IGtEd0/94S3bBM4nIv+cctsO5wbRRsw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICdesjGQ/U5V9H/tPQVqUkmF/GCT+7dvNzDOsSCCIuYQAiEAgOVkD7ZEF1eVhNnEr5f4gML1uSY3mzYnDOAcC93fU0s="}]}},"6.0.2":{"name":"autoprefixer","version":"6.0.2","dependencies":{"num2fraction":"^1.1.0","browserslist":"~1.0.0","caniuse-db":"^1.0.30000296","postcss":"^5.0.4"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.1.3","browserify":"11.0.1","fs-extra":"0.24.0","should":"7.1.0","mocha":"2.3.1","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"ab61d0e58c539599e5b6fe55ab41f7c5d5701015","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.0.2.tgz","integrity":"sha512-SRzbj77D2xdyAgwbrufOZCSahbdyeWZENVvusvWKm4YTvNOTJiRZyLR81YaB69eivzMcV9FYipnRGWY9rXCUxw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE0s+eltAcCgOd1+rP3yrZEotYmHtJa+RPBiUL6aq4KKAiBV+wtn0pzmYSh9tXhx6KpYehh4A1aiJMEoCz2KmQM73w=="}]}},"6.0.3":{"name":"autoprefixer","version":"6.0.3","dependencies":{"num2fraction":"^1.2.2","browserslist":"~1.0.0","caniuse-db":"^1.0.30000313","postcss":"^5.0.5"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.1.3","browserify":"11.1.0","fs-extra":"0.24.0","should":"7.1.0","mocha":"2.3.2","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"06badb15cadb2d1dd92d5b95f8f4522911f9c79f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.0.3.tgz","integrity":"sha512-S1IpR22ZEWuDhjxd4gLPqVGStcsGJzCB8kFVSzuR+CoJ1/o5OKSUnpz93rtz//UHB8BsCuGoBWeJTTVJ7NOVNA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB+VQrw7gbT3gHHGDio/apsis7idL97Lm9Ep7x16EibGAiBwWGJdlZLuT5Qn3+tK9xpazFf/o5LHWj3ic8fCn2ZYBw=="}]}},"6.1.0":{"name":"autoprefixer","version":"6.1.0","dependencies":{"postcss-value-parser":"^3.1.1","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000359","postcss":"^5.0.10"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.1.3","browserify":"12.0.1","fs-extra":"0.26.2","should":"7.1.1","mocha":"2.3.3","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"7578acab4f52fadfaaa6004fd2a096c58480c21c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.1.0.tgz","integrity":"sha512-Wv09TG5RaZB3cANM6ubDitcNRNaeUQfclbG7py2ifvkp/bJzgzAeCOCh9zUUBKb+qL+ztmoAxNGVGg7RPbnVKw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC3xWd4ZfO3OOZeRnVdEtI3/0Ik36X+VolA6gNMzD/GUAiB45aYIvcJg4x1a5MEdMZFyQzqKkBCOInz1EYm/g7VjPA=="}]}},"6.1.1":{"name":"autoprefixer","version":"6.1.1","dependencies":{"postcss-value-parser":"^3.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000367","postcss":"^5.0.12"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.0","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.2","should":"7.1.1","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"318b62195a89496300a7361a95212d4ec7f19678","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.1.1.tgz","integrity":"sha512-7ms18c0rTOq7ANZ15yKVUAEGPol9QD2t4LpaNjXnu3nJYMhYDa79g9VOWUxa69CGif+hnJjRexzn6M4tA+aNsA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCn2WEIfiJ1M5pckZ11iHQ2bewDDzOsnHw2QMjzA4+0OwIgUfHorH5fK7+kckPKzU8llPKiY21WIZ60+bokpwADLQQ="}]}},"6.1.2":{"name":"autoprefixer","version":"6.1.2","dependencies":{"postcss-value-parser":"^3.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000372","postcss":"^5.0.12"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.2","should":"7.1.1","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"11a36b50cc0e4adaab5570aed28cf81876e1ab3d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.1.2.tgz","integrity":"sha512-0DbXdRBs+NORhWmDynshylIYhj9X/PaT5soavwja6lptqKN/pGpO/ghOFt+B5Ak9SticHJ3LuwD3pWVx4VvPyg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH9ar+rApf0unbXYyJEhAi2ut9DrJ86G5Kk+cgKlux/oAiEArg7SS3IXOw8/frJdru6vA3RlJIlA6KstXj3Z5+/T2TQ="}]}},"6.2.0":{"name":"autoprefixer","version":"6.2.0","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000377","postcss":"^5.0.13"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.3","should":"8.0.2","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"d136f855db4bb6901687ac1c0f4559a18442b524","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.2.0.tgz","integrity":"sha512-RMs+vk0SL/JieXPjj6mJh4FOfq5+XFPYvoOyjuxW4TLaPvt8ZwtlyjTRXj1ZscggnZ6wjk/8csfd4RrTII6MrQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGr8YuZZPbCfM6FHbbYxf4oNxVT2Lc4HRoRRZebwzIDSAiAar3/XXhMAE+qnnMSRACv9pUya7Wv8Sx4ktFsWHEqkcQ=="}]}},"6.2.1":{"name":"autoprefixer","version":"6.2.1","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000379","postcss":"^5.0.13"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.3","should":"8.0.2","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"dab8b22b200b190ff78f37dba721af0eb541f4d7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.2.1.tgz","integrity":"sha512-tfhvJ0jkLN32Mq25Yq+6szLkjy+VDVKIDItGXcOVmVO/MvlZHKIfdQZPdLIzWRU7Tl51a4hvedzMFO2rix2sEg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDk8q4vbrrzcqX00FRxgURASME3+GkreAq83BmGHK/4ggIgcJFkFQsErDzMdkqeaLilbeRZ7l4xubGM1uUIJvlRwQ0="}]}},"6.2.2":{"name":"autoprefixer","version":"6.2.2","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000382","postcss":"^5.0.13"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.3","should":"8.0.2","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"2250ec2167f4c9374d8739e477d82ab2d70fe476","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.2.2.tgz","integrity":"sha512-QkucjOXlVNgKgkfSwyVkP1Idn6q27gERF3CtklzMDoOGOybLHn34xC/lykdv6/bqZiZ/c2inWSQmWpvvq3yBPw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFbs1xmUnaWTOff2KSHBvMl/0fSd5L57a9IlBsVa5pHDAiEAnwrEyehNJ6DlFadarnzRgsUnsOj8r+idDSJneXN/zEo="}]}},"6.2.3":{"name":"autoprefixer","version":"6.2.3","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.0.1","caniuse-db":"^1.0.30000382","postcss":"^5.0.13"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"12.0.1","fs-extra":"0.26.3","should":"8.0.2","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"a9ecc9fe1a7b52b0b32d110257375d02fa841f1c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.2.3.tgz","integrity":"sha512-7XC5JUvVrJkn1KObAXEQb0BEFxJvzzcrirB5CRQKPQZLAvjftS/oHtfYVOwfV+Vyp/A6g3TXdhUZQIa1fsBkUw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID/waR2lz4313Nlz07q3G9lREI8HMvarRfNrZ3M7wZi+AiANOr8Hc+SFowe2kYoJoFsSpdpTV7Tf2aK7RRvFLxFqqg=="}]}},"6.3.0":{"name":"autoprefixer","version":"6.3.0","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.1.1","caniuse-db":"^1.0.30000387","postcss":"^5.0.14"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.4","should":"8.1.1","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"729baee3e8962a99b3c7b54001fb3d6ec1a6b427","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.0.tgz","integrity":"sha512-1NwcnH63iyh5Gjw/1u/cROXGXWXjrraceAUxBGvdasZg/dIqeBfJ+6SjQODhpjZKXWa+hCBYEDhxmx3HjffvPA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmT5AvRThTfPcLop+e3lVQjFts1gglF3bkwBypGctQpQIgVh3aH3nlm0qwwY6tSTu6OtxiulFI1NZ01yvQzL4a128="}]}},"6.3.1":{"name":"autoprefixer","version":"6.3.1","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.1.1","caniuse-db":"^1.0.30000387","postcss":"^5.0.14"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.4","should":"8.1.1","mocha":"2.3.4","gulp":"3.9.0","coffee-script":"1.10.0"},"dist":{"shasum":"79757c0caef79f00b93bffdcf1e0da7eeb06cc88","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.1.tgz","integrity":"sha512-D3AmS8z74yXWvmqrXNUrj+KKXvjm8UFXIEkhykZsLyzT9d6+1KF4AVrOALW+CN+z5zLc1SHWdUdJVCY7rRPpWg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPpOS4OPt54XCBPoLoEfaquYa8aedGTIis42LAzuYCAwIgP80bhrlLGXJZ20L/CiH0ERQWPcLRdbdT+1D67P74PWY="}]}},"6.3.2":{"name":"autoprefixer","version":"6.3.2","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.1.2","caniuse-db":"^1.0.30000409","postcss":"^5.0.14"},"devDependencies":{"vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"1.1.1","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.5","should":"8.2.2","mocha":"2.4.5","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"9e37caa8b7ae824a3c041efe6cca3fb5d0d2cadf","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.2.tgz","integrity":"sha512-47RyPhiQkr6DLAWxTt1B5xLxSBKR0ThMkzyW0ACeSkslvtuhoN3HuuZSE1b83xI/ArCYVDdwRa0Vr/o1OAoQ0w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB9IDqLw4uVzzQ7OuZxVuWVYKLdPrVTI54OaO9jGryVqAiEAhoOtkBIgDd0vdZ0va1HuDymPJ2FQzBiNtGy2CkVqwuY="}]}},"6.3.3":{"name":"autoprefixer","version":"6.3.3","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.1.3","caniuse-db":"^1.0.30000409","postcss":"^5.0.15"},"devDependencies":{"eslint-config-postcss":"2.0.0","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"2.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.5","should":"8.2.2","mocha":"2.4.5","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"38bcd301504e7b40a9feeb392709067787c521a5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.3.tgz","integrity":"sha512-bFctPTGa2UW43AGPmKumiNRlnqs+rC368j1Qmwd3oBj41SxuaJXcuDGET+BnT2kgD/0gi/mjYG7cL1hy+QV7aA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWTstHeixsqcjNKeFUH4FE8oOCUM4/Gh+yLPLseDo/LwIhAJUgezvrmpvvYbX3hCaCuWgVgJyzlrXEDo6hOFQeXniX"}]}},"6.3.4":{"name":"autoprefixer","version":"6.3.4","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.0","caniuse-db":"^1.0.30000435","postcss":"^5.0.19"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"2.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.7","should":"8.2.2","mocha":"2.4.5","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"9d28d7355f01a794ef59d0f4b1dd91ad3055766b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.4.tgz","integrity":"sha512-CDng8C7oPV/j6DRWz4pU2FewNTQZgwTmNUmVMrubDoSR5kbnXDuWnYeRVTGwjT5aKrfOeSZGQAdwg8wWX0iB4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID6CfNAXBzSZ8EdDLSjsa+fdhDO4eJq0eMY1zoW+D7Z4AiEApWOVkFmTa/3Np3jNxrTIGlMRsKYQMhwGCCteNPMmE34="}]}},"6.3.5":{"name":"autoprefixer","version":"6.3.5","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.0","caniuse-db":"^1.0.30000436","postcss":"^5.0.19"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"2.0.0","gulp-coffee":"2.3.1","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.7","should":"8.3.0","mocha":"2.4.5","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"6bcbd038a337c70627e7fce4438fa58188f0937b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.5.tgz","integrity":"sha512-qK89CpD6q3wnikO196+PwzADyu+BKMB6UtAiOafizhMr5HaIwvFzgMIh3AZEZQEoQb1dTgqFDDEzW60/DRqKsg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYy0Ld9X73rkaGFN0QYavJXzRnhXSOdPTPUxlnnjqwWwIhAO0tNKBQuUG9JsKL7tJi9sKGw3aZAYA2uvYmNnmIwln3"}]}},"6.3.6":{"name":"autoprefixer","version":"6.3.6","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.1","caniuse-db":"^1.0.30000444","postcss":"^5.0.19"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"2.0.0","gulp-coffee":"2.3.2","gulp-mocha":"2.2.0","browserify":"13.0.0","fs-extra":"0.26.7","should":"8.3.0","mocha":"2.4.5","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"de772e1fcda08dce0e992cecf79252d5f008e367","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.6.tgz","integrity":"sha512-MchiI2D0bzHHbRPcyQgCWsqqK12rox4axvplNzcMFFYhSAWj8bvuUw94Kad0rPPEKF62SpUD80PpoA4k9BXlow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCoIgSwCRFQywKHlTT4GOsH1myLGhyw7NgKR/xVOsPFXwIgKDAU3nobgbCEwoW6KvzbCtiFkkUwPnxkksnigAf7QOA="}]}},"6.3.7":{"name":"autoprefixer","version":"6.3.7","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.4","caniuse-db":"^1.0.30000488","postcss":"^5.0.21"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"2.0.0","gulp-coffee":"2.3.2","gulp-mocha":"2.2.0","browserify":"13.0.1","fs-extra":"0.30.0","should":"9.0.2","mocha":"2.5.3","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"8edf3166dd9fd6116533662c8bb36a03c0efc874","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.3.7.tgz","integrity":"sha512-xnArQBxKETltXW1R/ZrmlaslmU5vF4huqAw0iARn1VXXc8TztdtWQJ9myUe/ywZbG7tvErKQ7hZORBf7G8fArQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA5BdNx0hTUGq5SRdpR22tEhiDs5802/GiB7uhtEqPAFAiEAuCeZaX9tWlJspKkw8yt0X6FkjJkDpgRPdx7s4HgLjaU="}]}},"6.4.0":{"name":"autoprefixer","version":"6.4.0","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.5","caniuse-db":"^1.0.30000515","postcss":"^5.1.1"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.0","browserify":"13.1.0","fs-extra":"0.30.0","should":"10.0.0","mocha":"3.0.0","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"4db60af585a303616bb896b50b30bbdd5858d2e3","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.4.0.tgz","integrity":"sha512-uTNTXJowzi/81E/NQ0GhGVQ+7KZtnpOQnIwVjjrkEPVWExzBjiJ3EWCWH+fFapY39J3bsLySQio8tPTU+PBKkQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJtII3wDhUqvnKz5CqRwv2SUXDRAKuFL+IvFRiVsqmGAiEAlQzuZVUY8qkJu3mUjkQweY8DVZNHPfaVmdpc1TCU7qQ="}]}},"6.4.1":{"name":"autoprefixer","version":"6.4.1","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.3.6","caniuse-db":"^1.0.30000527","postcss":"^5.1.2"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.1","browserify":"13.1.0","fs-extra":"0.30.0","should":"11.1.0","mocha":"3.0.2","gulp":"3.9.1","coffee-script":"1.10.0"},"dist":{"shasum":"c1ba8461759faf5fb7737dbdbe5ea46a78c68a6f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.4.1.tgz","integrity":"sha512-n9Su9p0kPiYE8IujWRXNXQZ2RiE4EDnzkDWd+TwEFSAoauE3NkcyXcPBp//efM/C663QhNzi5kQW1rTcFWNX1g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBrIiVydv0QT9yH0BWp5mnKqSBII2gmX8C2GCrVGeZsKAiEAsCQAUFfQsNY049c8ISmTThFrxzjhf+fPEDO7+Q+NizU="}]}},"6.5.0":{"name":"autoprefixer","version":"6.5.0","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.4.0","caniuse-db":"^1.0.30000540","postcss":"^5.2.2"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.1","browserify":"13.1.0","fs-extra":"0.30.0","should":"11.1.0","mocha":"3.1.0","gulp":"3.9.1","coffee-script":"1.11.0"},"dist":{"shasum":"910de0aa0f22af4c7d50367cbc9d4d412945162f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.5.0.tgz","integrity":"sha512-SsEJpxWjW9RShkKCTQvHoz6hQInr56YWsZcWU7m0fiMknXVLf2lnxC1G+qW7+glBC3AYmXh02xvejNdPS9RPqQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyvZjmR1MtYdwYz74nGM2OWbnRnlh+iEwf6ZV3vz7+MgIgZ7ri22SqUgzOpeZhoNtWwJFVn2PTY/hwOt3lu2kSdyg="}]}},"6.5.1":{"name":"autoprefixer","version":"6.5.1","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.4.0","caniuse-db":"^1.0.30000554","postcss":"^5.2.4"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.1","browserify":"13.1.0","fs-extra":"0.30.0","should":"11.1.1","mocha":"3.1.2","gulp":"3.9.1","coffee-script":"1.11.1"},"dist":{"shasum":"ae759a5221e709f3da17c2d656230e67c43cbb75","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.5.1.tgz","integrity":"sha512-STbn1sXvjG/PiS08X9Ue0iPTPXjp9hlLQq6qAK6twHidRgyMgKyXxi1Z2ZUdK1OD0gznnHx6dhioyFU1EwzV3Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCy1V5XiHdul7C/lagUXsYk6ybx0dtfwJU7IphPctFqGwIgTOLUC8W2eLasZ3OT+1GopaHU1RcZjJqeYwyHsDgmqNk="}]}},"6.5.2":{"name":"autoprefixer","version":"6.5.2","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.4.0","caniuse-db":"^1.0.30000576","postcss":"^5.2.5"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.1","browserify":"13.1.1","fs-extra":"1.0.0","should":"11.1.1","mocha":"3.1.2","gulp":"3.9.1","coffee-script":"1.11.1"},"dist":{"shasum":"37cc910c5e1139ad341a006d5f6d441a380b742b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.5.2.tgz","integrity":"sha512-2/YP+Y+ST/KjFgQxXiWcJZGAsxWl3LkTtVX/fioKzS9mcGnLmjTJwflQMNjzihyl1aSHSMzwmUqyCgxzkNQUUA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuVNb+Vk/0H5Ix+/pgER22GbZit9Wjmb5vNNOajQLCPQIgAOmZppe1Ql39tGpABJGZwFsbq8t5PVpGEQmlaTJsajo="}]}},"6.5.3":{"name":"autoprefixer","version":"6.5.3","dependencies":{"postcss-value-parser":"^3.2.3","normalize-range":"^0.1.2","num2fraction":"^1.2.2","browserslist":"~1.4.0","caniuse-db":"^1.0.30000578","postcss":"^5.2.5"},"devDependencies":{"eslint-config-postcss":"2.0.2","vinyl-source-stream":"1.1.0","gulp-json-editor":"2.2.1","gulp-replace":"0.5.4","gulp-eslint":"3.0.1","gulp-coffee":"2.3.2","gulp-mocha":"3.0.1","browserify":"13.1.1","fs-extra":"1.0.0","should":"11.1.1","mocha":"3.1.2","gulp":"3.9.1","coffee-script":"1.11.1"},"dist":{"shasum":"2d853af66d04449fcf50db3066279ab54c3e4b01","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.5.3.tgz","integrity":"sha512-L/jzO2Vl5mW5JbyvbVcFePY8im/9AA9DM5HaF9Aztlbuj6uajYZJt/R7e2QDJpL6GzpeWDpYkN+AjIC9xwLxlg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGQ2/pVtfAc3jw79Gj/DVENAq4DchxmxyHN0TvrX6sNgAiEA5ZBX4thNB0qtn5DY3/fGzNMm3cXHnW6UtUSHEn+UqZk="}]}},"6.5.4":{"name":"autoprefixer","version":"6.5.4","dependencies":{"browserslist":"~1.4.0","caniuse-db":"^1.0.30000597","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.6","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^13.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^1.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.1.2","vinyl-source-stream":"^1.1.0","coffee-script":"1.12.1"},"dist":{"shasum":"1386eb6708ccff36aefff70adc694ecfd60af1b0","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.5.4.tgz","integrity":"sha512-4z/6SOSGrVVKUI5nw9yDnboUkpCTx5QxItoyvWe3m134wgPguMFRu/gGmgGZ6QAVA4DHyue9/UUmb4hIJT2viA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAZP9LINZ8u3rCuZjsRgBv4lxI1sG7/Toq19lOiq9E9fAiEA5k1Bk4zw5eleX7x/001FWQLsgv6dRoSMeRHuZxVrY5c="}]}},"6.6.0":{"name":"autoprefixer","version":"6.6.0","dependencies":{"browserslist":"~1.5.1","caniuse-db":"^1.0.30000602","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.6","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^13.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^1.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.1.2","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.2"},"dist":{"shasum":"d5b347ebbaf79e79d30b81c0ee3e482b288527bf","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.6.0.tgz","integrity":"sha512-8kSuMQVDq/7X/AGbSbLxXWfpV4fT42OvJg0YKiIRTtoeGJT3zOhUHGc0xiEH7yEMTvdO/+fZfW0clbiMULF8bw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC6RWg0MBJeNFBtOSw1tViWzDBplXzixwa+Ae6NKTh4eAiEA8ebTtxqVCiKc58N35FCRZpkJFVIE7STdQpciUOe4yEc="}]}},"6.6.1":{"name":"autoprefixer","version":"6.6.1","dependencies":{"browserslist":"~1.5.1","caniuse-db":"^1.0.30000604","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.8","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^13.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^1.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.1.2","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.2"},"dist":{"shasum":"11a4077abb4b313253ec2f6e1adb91ad84253519","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.6.1.tgz","integrity":"sha512-fUGC+qvkab/Biu8/dAw2YF9BgYO2+fO2F6Ydqf3VzLermd/oWxovCccRTX04ljud8tYc71TtEjXjTsqHb6Y8Jg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAD1Z6m0uPikHZPU2wtttC729pktItZxQuo477n6360kAiEAgcK1m6MciMTmoJqxnMQaPH3a2ONbETK/Y73GQDqbqyc="}]}},"6.7.0":{"name":"autoprefixer","version":"6.7.0","dependencies":{"browserslist":"~1.6.0","caniuse-db":"^1.0.30000613","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.11","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^13.3.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.1.2","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.2"},"dist":{"shasum":"88992cf04df141e7b8293550f2ee716c565d1cae","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.0.tgz","integrity":"sha512-ghIljHY6FdZv2ky9QC/39AiE0CdamzLwYfMtN/IYyjUpnNIjgc5sAheUjldllhHFrliKFQVpMrqPF7oPTFYS6g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDz+t+fP/lf+7quGR1Uqis6g070USdQPBt2WSygMttuKwIhAMS2NZI7F+u1OxzB3OEU3BJEQgdTs8UllCc8R2dnCvLa"}]}},"6.7.1":{"name":"autoprefixer","version":"6.7.1","dependencies":{"browserslist":"^1.7.1","caniuse-db":"^1.0.30000617","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.11","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.0.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.3"},"dist":{"shasum":"d14d0842f6ef90741cfb2b1e8152a04e83b39ed2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.1.tgz","integrity":"sha512-pREvuWqcr4JzzP3UNyChdaf7V1iPNNOvjKJv9TtZrV/2ZerJU9b6G+uXdhxLQStHSYei3mdg67I3UwfAlNITLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBWQe4Wp5NkByKRb3lythQIsAo3outUSOPNk1s8/14VnAiBnZ/w6XyooHCGUKwSD7pRvGkJduu6lytu1j9OnChx+IA=="}]}},"6.7.2":{"name":"autoprefixer","version":"6.7.2","dependencies":{"browserslist":"^1.7.1","caniuse-db":"^1.0.30000618","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.11","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.0.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.3"},"dist":{"shasum":"172ab07b998ae9b957530928a59a40be54a45023","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.2.tgz","integrity":"sha512-BrtFd8nGiHJrfPfGZ4/iv3yFH15Fvo/+nb/ObqjfEaPM/KTUWprhJTBKdp5V3hATndPNV5v6ZLxHiqiQeZBgqQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgF300Vrd+BD6d/uPFxlbJMS1BI9XiqodX2B3Of2Z53gIhANjgL6pS/ti7a/K+FIi+Pd7mqjHLdhB5kxfkLjNtt45U"}]}},"6.7.3":{"name":"autoprefixer","version":"6.7.3","dependencies":{"browserslist":"^1.7.2","caniuse-db":"^1.0.30000623","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.13","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.1.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.3"},"dist":{"shasum":"bc2c28018e9a226f24f0ded36ce81014dccec817","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.3.tgz","integrity":"sha512-4hGgl5c9HHE4FYS9mRKwSAz6FXIDnJDKfWwKWFAAU8VlfTjvHPgx4iqQqlsLHdvhNbJstOyE+o2VU445VT757Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICZdYz1NcXVevY1a9Dgs6171P010LtUnWlDzpntte5R7AiADVdDv7ao+iN80/T80KJfVpSwlnKi2yC8J2L5IBr5ixw=="}]}},"6.7.4":{"name":"autoprefixer","version":"6.7.4","dependencies":{"browserslist":"^1.7.4","caniuse-db":"^1.0.30000624","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.14","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.1.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.4"},"dist":{"shasum":"b4405a263325c04a7c2b1c86fc603ad7bbfe01c6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.4.tgz","integrity":"sha512-iGQzFuiC11bFtVNSR4TNabKZFCv39pv/nMZy4+2FUSnephasu5yEh6PypYKk95vHVePipxaXt/hg42whrdkVBA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFp0vuUoS618HzebqD5kF7h8Ef6a31pTVgZBl3QGZR92AiAHPnmlunMh+/sYrd9lKRacjbu4JwLgGY6t0vCyF+Vudg=="}]}},"6.7.5":{"name":"autoprefixer","version":"6.7.5","dependencies":{"browserslist":"^1.7.5","caniuse-db":"^1.0.30000624","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.15","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.1.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.4"},"dist":{"shasum":"50848f39dc08730091d9495023487e7cc21f518d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.5.tgz","integrity":"sha512-LCShooTZpattm+uitdbaEnhMyVhfYPA3RrPUbYrXaIPoMaqHjiIxGexYTZIXc2sls3K1jQ/sy1jirShwLfzlKw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF/D1w6uLBQVVMaz4UBL0X8eWeLvTkUKUiVfXoAnV7YNAiBs83Nt9jR9nmmVbVddS8GCNN3nixs3Lj/unrQjAZ8vvg=="}]}},"6.7.6":{"name":"autoprefixer","version":"6.7.6","dependencies":{"browserslist":"^1.7.5","caniuse-db":"^1.0.30000628","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.15","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.1.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.3","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.0","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.4"},"dist":{"shasum":"00f05656c7ef73de9d2fd9b4668f6ef6905a855a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.6.tgz","integrity":"sha512-Tq0youP1YjL3vBbIfA4gnuiIHPsu3m1vhoXW8jWafDq0XtqmnG9WQuwfJcMC8lkKNusuL+zDnftFAm6/2Ze6vg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICFBec0qpvKPDX3SRutxlQJymwMDs9d4pyp53tUJKeBoAiB/k97v3Msz6xH4ijf4/aR5ADfq3TjxPTv3shdoHULzvQ=="}]}},"6.7.7":{"name":"autoprefixer","version":"6.7.7","dependencies":{"browserslist":"^1.7.6","caniuse-db":"^1.0.30000634","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^5.2.16","postcss-value-parser":"^3.2.3"},"devDependencies":{"browserify":"^14.1.0","eslint-config-postcss":"^2.0.2","fs-extra":"^2.0.0","gulp":"^3.9.1","gulp-coffee":"^2.3.4","gulp-eslint":"^3.0.1","gulp-json-editor":"^2.2.1","gulp-mocha":"^3.0.1","gulp-replace":"^0.5.4","mocha":"^3.2.0","should":"^11.2.1","vinyl-source-stream":"^1.1.0","coffee-script":"^1.12.4"},"dist":{"shasum":"1dbd1c835658e35ce3f9984099db00585c782014","tarball":"http://localhost:4260/autoprefixer/autoprefixer-6.7.7.tgz","integrity":"sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICB3HMdp+6NA0cTW3aNisU+qx9qnhuOX8k07YUuXLxEqAiEA6v92hJ3FcTx4/yH9g4Fs2jnPsctrNDKOaAsFfLYiTxY="}]}},"7.0.0":{"name":"autoprefixer","version":"7.0.0","dependencies":{"browserslist":"^2.1.2","caniuse-lite":"^1.0.30000665","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.0","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.4.0","browserify":"^14.3.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","fs-extra":"^3.0.1","gulp":"^3.9.1","gulp-babel":"^6.1.2","gulp-coffee":"^2.3.4","gulp-eslint":"^3.0.1","gulp-jest":"^1.0.0","gulp-json-editor":"^2.2.1","gulp-replace":"^0.5.4","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.2.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.24.0"},"dist":{"shasum":"734cc4f56ec964fcd4b6048e028b60c4226e7fdd","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.0.0.tgz","integrity":"sha512-z8lG9sKI4avvfTuEyx+PP4qvqF+x8do/KkB2HjOS9T50nJozsCyssR5eaoNiDpSxHU4Ov73Gu9oCRxigeIkrQg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDlds37kAKMR9ZpSi0ljnEAcwW9xZgYZ5dQcIwI5uzCkAiEAmd6Fv+8lfnLpJBxRfRgBnHAT76x7kzqwXHv5JF34lfA="}]}},"7.0.1":{"name":"autoprefixer","version":"7.0.1","dependencies":{"browserslist":"^2.1.2","caniuse-lite":"^1.0.30000665","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.1","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.4.0","browserify":"^14.3.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","fs-extra":"^3.0.1","gulp":"^3.9.1","gulp-babel":"^6.1.2","gulp-coffee":"^2.3.4","gulp-eslint":"^3.0.1","gulp-jest":"^1.0.0","gulp-json-editor":"^2.2.1","gulp-replace":"^0.5.4","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.2.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.24.0"},"dist":{"shasum":"472d7620a1b286e55ad1d8345a09d76aaed99d92","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.0.1.tgz","integrity":"sha512-ZRu4DbS/F5o5BWHsZBhANJelpUWcsozOF4LtYM/bNclIZCtHP1rInAdlL8esUseOpZACzksLYvSvJyKJW0n8gg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHkmTJmlJVsqdU42zoRaIT5qiHXGJeXiuxwmfWJVLgZmAiA+nDHVT6ypRvO6/yedWFEB8Jx/uiZ5jWfRH11CtD7Jtg=="}]}},"7.1.0":{"name":"autoprefixer","version":"7.1.0","dependencies":{"browserslist":"^2.1.2","caniuse-lite":"^1.0.30000669","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.1","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.4.0","browserify":"^14.3.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","fs-extra":"^3.0.1","gulp":"^3.9.1","gulp-babel":"^6.1.2","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.5.4","jest":"^20.0.1","lint-staged":"^3.4.1","pre-commit":"^1.2.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.24.0"},"dist":{"shasum":"ae4913adc221fa6ca5ad3a6f8039f6a5c06b3877","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.0.tgz","integrity":"sha512-MRZ2DGCRaHH95fRraOIz2/TL5ggQrOCYn80YMBknfLrq5FCncam/anGA88Af9MpbCTX7bUZk3athjRD8Uxk7pA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHYNii7mjR7nDvzMaUbJeeAh2C1t7Q8eBVeC4T2LvS9SAiEA4jVCFxN3PnWBNtZ39HiN9ZuPx0ZHK0wFYJeWo1rwZxA="}]}},"7.1.1":{"name":"autoprefixer","version":"7.1.1","dependencies":{"browserslist":"^2.1.3","caniuse-lite":"^1.0.30000670","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.1","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.4.0","browserify":"^14.3.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","fs-extra":"^3.0.1","gulp":"^3.9.1","gulp-babel":"^6.1.2","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.5.4","jest":"^20.0.3","lint-staged":"^3.4.2","pre-commit":"^1.2.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.24.0"},"dist":{"shasum":"97bc854c7d0b979f8d6489de547a0d17fb307f6d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.1.tgz","integrity":"sha512-y3U+M3XLC3oKKkShZXcsjdCY6bTWmqOboqx1iDeaMumpqumPbEDUqb9586imSWcy8nboBTjqRu8bNe4KcoYOXA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHwPIdDOxv6YvWtKR+0ghbFVS3WfiaPpOhnFv37fdm/5AiBpzpVWnQlCw2pj7VLOl8bYjjScavQ+FooGl0e3UomXJA=="}]}},"7.1.2":{"name":"autoprefixer","version":"7.1.2","dependencies":{"browserslist":"^2.1.5","caniuse-lite":"^1.0.30000697","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.6","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.0","babelify":"^7.3.0","browserify":"^14.4.0","eslint":"^4.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^3.0.1","gulp":"^3.9.1","gulp-babel":"^6.1.2","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^20.0.4","lint-staged":"^4.0.1","pre-commit":"^1.2.2","size-limit":"^0.5.0","vinyl-source-stream":"^1.1.0","babel-register":"^6.24.0"},"dist":{"shasum":"fbeaf07d48fd878e0682bf7cbeeade728adb2b18","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.2.tgz","integrity":"sha512-PoN1+x0sy4ocZLq29AKZFrnpxNqJNlpYWHP12twS+MxM+BHl5kgE6MgU5qWdJIEKAE1cW8+iSfOSwThiN5P1WA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqrVgQVapUh+RfSiAf7KjlMDShA10H1gKyPhrGDrm9PAiAfwhxu7DQ5L/Ha0+DxHY/BDAkQ9FBpZfxabWDlIjm12w=="}]}},"7.1.3":{"name":"autoprefixer","version":"7.1.3","dependencies":{"browserslist":"^2.4.0","caniuse-lite":"^1.0.30000718","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.10","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.0","babelify":"^7.3.0","browserify":"^14.4.0","eslint":"^4.5.0","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.1","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^20.0.4","lint-staged":"^4.0.4","pre-commit":"^1.2.2","size-limit":"^0.10.0","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"dist":{"integrity":"sha512-zGy6aRrZjWhR+25n89jYkpLXutg6xdDGKKnVNzkfamnnhK3mYchkKj5GJR14aJiU0x4UqZ1+N728tkFNUL5N2g==","shasum":"0e8d337976d6f13644db9f8813b4c42f3d1ccc34","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHu/VHSE8kLf8F9GZnlpywML8YkLvK/+tnQ+n6LgD6kDAiAtPJmE4PMkA9E4+vmKNm8bNB7BZ8mVk+Io0dcTQ7bgMA=="}]}},"7.1.4":{"name":"autoprefixer","version":"7.1.4","dependencies":{"browserslist":"^2.4.0","caniuse-lite":"^1.0.30000726","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.11","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^7.2.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.0","babelify":"^7.3.0","browserify":"^14.4.0","eslint":"^4.6.1","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.1","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.0.1","lint-staged":"^4.1.2","pre-commit":"^1.2.2","size-limit":"^0.11.0","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"dist":{"integrity":"sha512-MB1XybOJqu1uAwpfSilAa1wSURNc4W310CFKvMj1fNaJBFxr1PGgz72vZaPr9ryKGqs2vYZ6jDyJ0aiGELjsoA==","shasum":"960847dbaa4016bc8e8e52ec891cbf8f1257a748","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.4.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC3SYHQQUhb/LQbBMK3va/xtiiHovtmFPbB0qxBZ1c9TQIgVjomTu1J0nsyhQsCKd6BmXlWMhm2X3ZGdHFDmDKPnY8="}]}},"7.1.5":{"name":"autoprefixer","version":"7.1.5","dependencies":{"browserslist":"^2.5.0","caniuse-lite":"^1.0.30000744","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.13","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^8.0.1","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.0","babelify":"^7.3.0","browserify":"^14.4.0","eslint":"^4.8.0","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.2","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^4.2.3","pre-commit":"^1.2.2","size-limit":"^0.11.6","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"dist":{"integrity":"sha512-sMN453qIm8Z+tunzYWW+Y490wWkICHhCYm/VohLjjl+N7ARSFuF5au7E6tr7oEbeeXj8mNjpSw2kxjJaO6YCOw==","shasum":"d65d14b83c7cd1dd7bc801daa00557addf5a06b2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.5.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzf5+h6kILRuXePwyqQm/CHmwLeGvEYQrSYl7i28+bcQIgYHInpdlckiW9p7aXgZlrUiTJcll5j4WbT6ebXuhZlow="}]}},"7.1.6":{"name":"autoprefixer","version":"7.1.6","dependencies":{"browserslist":"^2.5.1","caniuse-lite":"^1.0.30000748","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.13","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-eslint":"^8.0.1","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.1","babelify":"^7.3.0","browserify":"^14.5.0","eslint":"^4.9.0","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.2","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.4","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.2.2","size-limit":"^0.11.6","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"dist":{"integrity":"sha512-C9yv/UF3X+eJTi/zvfxuyfxmLibYrntpF3qoJYrMeQwgUJOZrZvpJiMG2FMQ3qnhWtF/be4pYONBBw95ZGe3vA==","shasum":"fb933039f74af74a83e71225ce78d9fd58ba84d7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.1.6.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwtzNF7wZqjX4h/7qy8DddyEYvcdur3niEJhY7tguFVQIhAOZxRQDw5kuylJ2c+SAV5fYTpUUBWB19H0QGnKJ9EzXv"}]}},"7.2.0":{"name":"autoprefixer","version":"7.2.0","dependencies":{"browserslist":"^2.9.1","caniuse-lite":"^1.0.30000777","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.14","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^8.0.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.1","babelify":"^8.0.0","browserify":"^14.5.0","eslint":"^4.12.1","eslint-ci":"^0.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.2","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.5","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.2.2","size-limit":"^0.13.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-vHzhN1Snqf+vG0FUF2pDVlJn3VNHeQM+r0v3XEdwS6vhGqZX/fcaFM+0uvza0vzMGP1KHwr3r+kFCVf1WN0raQ==","shasum":"6bf29695ad19da447bba2b5737660e1e23eac72d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBZRmKTeqQi/0F5wMhIBae0tgHvwVr+UmfmVJIdDnyP1AiEAg0jvw4/nQRX0W8yYfj+YFNI5gpB7PmnVRTSxL20T7g4="}]}},"7.2.1":{"name":"autoprefixer","version":"7.2.1","dependencies":{"browserslist":"^2.9.1","caniuse-lite":"^1.0.30000777","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.14","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^8.0.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.1","babelify":"^8.0.0","browserify":"^14.5.0","eslint":"^4.12.1","eslint-ci":"^0.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.2","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.5","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.2.2","size-limit":"^0.13.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-lTbsa2X03maxG45xCNh30sJaRKDn8JPnanOeQOW3wvD9yPGmIsf041LHqlrZ1lXPF/1M3yTZKXqqYfmxU69xuQ==","shasum":"906b1447a0e6a9e13b371f7909bc4e36da5a5a79","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCzYFYVv0Dk5nl+hlWwv2DNbv6DukJUAGrtYmlBpFuvcgIhAMtjDgB/++NMdlcV16g/ER1Isa3tHnbNAqt3Gjxg7nWt"}]}},"7.2.2":{"name":"autoprefixer","version":"7.2.2","dependencies":{"browserslist":"^2.10.0","caniuse-lite":"^1.0.30000780","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.14","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^8.0.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.1","babelify":"^8.0.0","browserify":"^14.5.0","eslint":"^4.12.1","eslint-ci":"^0.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^4.0.3","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.5","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.2.2","size-limit":"^0.13.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-eTVoSHiGp2cDytg7RS7gtqAnfH+WFcNQMTjywGNu+hH7ViQZ/ZKsvNz2C1oVhCtd9DjMIC15iatpxmtp5Kxvpg==","shasum":"082293b964be00602efacc59aa4aa7df5158bb6e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMdBZY2Usl0SP9k6tXIdwTVOeOUK2MOoHUhOwaKrmEEwIgPj0z2uLBkWnYPWzBqzs99BPx+AgD6GHQmsql12iPL/o="}]}},"7.2.3":{"name":"autoprefixer","version":"7.2.3","dependencies":{"browserslist":"^2.10.0","caniuse-lite":"^1.0.30000783","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.14","postcss-value-parser":"^3.2.3"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^8.0.3","babel-plugin-transform-class-properties":"^6.24.1","babel-preset-env":"^1.6.1","babelify":"^8.0.0","browserify":"^14.5.0","eslint":"^4.13.1","eslint-ci":"^0.1.1","eslint-config-postcss":"^2.0.2","fs-extra":"^5.0.0","gulp":"^3.9.1","gulp-babel":"^7.0.0","gulp-coffee":"^2.3.5","gulp-json-editor":"^2.2.1","gulp-replace":"^0.6.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.2.2","size-limit":"^0.13.2","vinyl-source-stream":"^1.1.0","babel-register":"^6.26.0"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-dqzVGiz3v934+s3YZA6nk7tAs9xuTz5wMJbX1M+L4cY/MTNkOUqP61c1GWkEVlUL/PEy1pKRSCFuoRZrXYx9qA==","shasum":"c2841e38b7940c2d0a9bbffd72c75f33637854f8","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqoqjk9UNksGvFpFs0DG9b6EuFwFxMH+4q9k6QPd1boQIgfZuzDfRP0HINFW39kmLH/LhUGn2sNXSjVLM6DD2BGyc="}]}},"7.2.4":{"name":"autoprefixer","version":"7.2.4","dependencies":{"browserslist":"^2.10.2","caniuse-lite":"^1.0.30000784","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.15","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-am8jJ7Rbh1sy7FvLvNxxQScWvhv2FwLAS3bIhvrZpx9HbX5PEcc/7v6ecgpWuiu0Dwlj+p/z/1boHd8x60JFwA==","shasum":"29b367c03876a29bfd3721260d945e3545666c8d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.4.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDw00S58btzFagjI7QnM8Xf3SMk1t11T+Z27Hs4lukS8wIhAIcrX8Xm4ZXHm4hP7GfyyHaFDIa4G/Tz+WGOueOBu5mf"}]}},"7.2.5":{"name":"autoprefixer","version":"7.2.5","dependencies":{"browserslist":"^2.11.1","caniuse-lite":"^1.0.30000791","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.16","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-XqHfo8Ht0VU+T5P+eWEVoXza456KJ4l62BPewu3vpNf3LP9s2+zYXkXBznzYby4XeECXgG3N4i+hGvOhXErZmA==","shasum":"04ccbd0c6a61131b6d13f53d371926092952d192","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.5.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEZRIbQ5Dm8yMZtpU+sVuari/hkjTBhXli3+6tnI+xbqAiAVX7f/zJ62pTrCJZR21vp3WB1peuO4zsmDiJe/YRL23g=="}]}},"7.2.6":{"name":"autoprefixer","version":"7.2.6","dependencies":{"browserslist":"^2.11.3","caniuse-lite":"^1.0.30000805","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.17","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer-info":"./bin/autoprefixer-info"},"dist":{"integrity":"sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==","shasum":"256672f86f7c735da849c4f07d008abb056067dc","tarball":"http://localhost:4260/autoprefixer/autoprefixer-7.2.6.tgz","fileCount":72,"unpackedSize":321787,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCHzZy79uCCGCKTUAB7KnVIVvBPsIS8sKw0lkX3fJ+Q+0CIQCgKOoajMjDVo/kGP4AtYRObCPrDCd0WaGJ52+0FBEUFg=="}]}},"8.0.0":{"name":"autoprefixer","version":"8.0.0","dependencies":{"browserslist":"^3.0.0","caniuse-lite":"^1.0.30000808","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.17","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-XBEqAoESCyGu3daYmWcTC37Dwmjvs0y40UtUO3MMX+Pd/w7jwNFfUKNtxoMFu0u0wcotP+arDpU3JVH54UV79Q==","shasum":"c19e480f061013127c373df0b01cf46919943f74","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.0.0.tgz","fileCount":72,"unpackedSize":322197,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB6YxRzOhjsEqXbU/K7vLxpPI2j9Gxmsx8M0QO38YskZAiEA1R7zrtRHe4eH5pAseDOpiROxQ9TQv6jVFWbvVLOn9QA="}]}},"8.1.0":{"name":"autoprefixer","version":"8.1.0","dependencies":{"browserslist":"^3.1.1","caniuse-lite":"^1.0.30000810","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.19","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-b6mjq6VZ0guW6evRkKXL5sSSvIXICAE9dyWReZ3l/riidU7bVaJMe5cQ512SmaLA4Pvgnhi5MFsMs/Mvyh9//Q==","shasum":"374cf35be1c0e8fce97408d876f95f66f5cb4641","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.1.0.tgz","fileCount":73,"unpackedSize":325385,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOhqukaJn3EvuKKjJUwg/cqvuV/hnI6d1w8I2RenbW6AIhAL/twNiRNYcAwfYVzeC2XJKkckNEMdo2zgsQxMGUiMWs"}]}},"8.2.0":{"name":"autoprefixer","version":"8.2.0","dependencies":{"browserslist":"^3.2.0","caniuse-lite":"^1.0.30000817","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.20","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-xBVQpGAcSNNS1PBnEfT+F9VF8ZJeoKZ121I3OVQ0n1F0SqVuj4oLI6yFeEviPV8Z/GjoqBRXcYis0oSS8zjNEg==","shasum":"1e49b611b31a5259b86b7a6b2b1b8faf091abe2a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.2.0.tgz","fileCount":74,"unpackedSize":327222,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLigFsS+7fRcAKK3BjzSYr/aZvQRYbYIAaM16eeA77gAIgQ+UuLziqmHZVi4Bkscq+Gtx3Mh46LSuIADddY+cO8uM="}]}},"8.3.0":{"name":"autoprefixer","version":"8.3.0","dependencies":{"browserslist":"^3.2.4","caniuse-lite":"^1.0.30000830","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.21","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-HY2K4efAvC97v6j83pgV97Lieal51xhIV8EitvS4SrWcI+IGVZgjpihvXImsmIUzA6kb/tglPKzERG1oRFOvRA==","shasum":"22ac5151c3c8946bb8f75f337d5c5042c0ec6404","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.3.0.tgz","fileCount":74,"unpackedSize":328588,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1BJXCRA9TVsSAnZWagAAhXgQAJBNxIMdvIJU1hDTxsE/\nC8VJe10UK3i1zT6oEzXE/OA/txSDwZu7j5Tox5pKi5wp25VQc/QbDH8SEJI7\ntxhKIqFsEAb0Bupx2gDuCOcQFN5b5JROxhi3ZS7w3fHo0owS1Hix1c58+5V1\nCAVI8UKLH6azszeVfQuD3Fcqw8XzLPsO8a4mzR2akczKylR5/mGzQU0TZv0k\np53Zk9CxfLoExLB8eorgF7f69IkAzu2AGD44iI4go+wWC1S936baCwPq0Y8G\npZ+k8y+467+vnY65jWv9ijMTs0IwkclawQJv3pLNtba0+c/Wpy3k2HgtryRj\nuCyUntX9ImkD0cuyQw6nYIMGy7AE6v4XGHHKqroniiVPWGUC1ev3IohDbWj7\nHlZoul89+/BYTAHIwZJJih4Fy4LJMf+pmkLgRPnHWYWxh59CGYWpq3lrNUpq\n2+bV5a3fYMnrRFv7zz9VYvT+zsF0rJvPK65EsItJlbG2Bw7DM3lR9CwwMDXA\nJf+3hM5vvEOLGXhS9wXPnB5XsRD5Mo63L1p6B/BdOpu+dr6yn2WpsOf5Uhpv\nSB+q8h98yKBXJim4GC8J6JY7TLfzicuZ5Z5knJSJ0cmWQgNRuc2JhAgOXjrv\nnwy/v+BjJPcR+XFyhcWYlWMlDbtljsqTEwi2ezfxtEMe2fNCMm35EbVEzbuh\n/Klu\r\n=1nEg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC31HTWkmzxhU3KQQDzz/rEUVUbVEeNlBXq2Phy5U0tggIgNMknTrQqYtBJDdbV7xY4c4NOy/npsfso2trDa/GlhqQ="}]}},"8.4.0":{"name":"autoprefixer","version":"8.4.0","dependencies":{"browserslist":"^3.2.6","caniuse-lite":"^1.0.30000832","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-3IxFQtSH+aAlN9fXcovgRqxAoXeI6g9f8VR7yMxMW0b8vFqsSSJHlWL7W0OS+7V1Imsjnf1zD1X1kdAHC23r4A==","shasum":"c44ddc69cc15ad9500c47967068868dcf7aa82df","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.4.0.tgz","fileCount":74,"unpackedSize":329448,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa5BjpCRA9TVsSAnZWagAAvD0P/RCyzZsk+hz6bQqRNuPy\njQtC4tDDPmZqNkkwiAruYw8Zo5VGQ8ou3fOhhkCSGkCkIMFqXohxc3F6WqvO\nts7KZUaBRUF8nUs00P23tfIDz0ytV57xxNfsnKzgM5E38bE8X7cIAzrbeSI4\nmImxvBuhSquTLuowIvpDqIo408DbhZDjV7iauEmjh8SN6fk0+qO9HGb8hZpp\n6RAnBnL6ydeYsMjlHs/7vgxN0SBoWAC5veVDqRsKwwOqtFznig/T+uJeZg8J\n+1rvWw9qUSX1ecsRrU0t1OsbsUhwBZx6K8mFNwEf3IYVoYUN2FdckPnc/ydD\n5tdih949W4+MnY3Ybt8xd+ksxrggm21mDc0H+UZ1bWPEr4J983ry6BwcoMkl\n4RChzhuRe+6MjsAPgDfiQIv9SEJ2qRtDgax9Dp6ZKdnKtGvx76Sa5expjBXn\nAouKJrh5hLivvHkBfXM5uTDLCZiClK4W8MOCk8NNbTHTiNJz1e0cBQWrlVWn\nnOna6GaWm/9A+RddbLov06cekEvN5vYqaI59OB5UNZ98yzvTas0dgrfJWv24\nJswFJiBphGNYhGAH2SJ50cOcJwICmGGHxR5v11EUWlN4MQRlhY7n/vEttelM\n4KEiukLfNvHgjsOvo+l1u0MbgKBy4Sl8Ml9EArut5WWqAy9T5vD5iThGy458\nBkvi\r\n=JyYA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG+aPF6ny/bt7x/F1ivYcRh6SUOmqI6Cz4xZY9BtsPWEAiAjzC0XqMVk94p4fzp3A3cdobi++glWbgX7CRK/5PMzpQ=="}]}},"8.4.1":{"name":"autoprefixer","version":"8.4.1","dependencies":{"browserslist":"^3.2.6","caniuse-lite":"^1.0.30000832","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-YqUclCBDXUT9Y7aQ8Xv+ja8yhTZYJoMsOD7WS++gZIJLCpCu+gPcKGDlhk6S3WxhLkTcNVdaMZAWys2nzZCH7g==","shasum":"c6b30001ea4b3daa6b611e50071f62dd24beb564","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.4.1.tgz","fileCount":74,"unpackedSize":329560,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa5DTVCRA9TVsSAnZWagAABNkP/AudaDtqJahavA5y8rYG\nNoF/cb9LkfkkCQG5S1qzZ0DuIAk/vMbqTRf+rFxTBPjtd6trhH89ZoI31OdK\nYj7SCcksxLz87P/dDWwnzYBGBol0jyAf2Fz18TytX8PIhyOCw3bKMm1OP2Pv\n8Y3Kk+zayLyu3ugfzWWcm+QGZCwhX2ibN7zZ0UzOV9hpXvQXAXFZpl9lAG0z\nxIPjjHT45l56XpBuXu/YML07nbh+50V/4zjRmfytFGdHKO6pQy1tdOxnWQaI\nhxHjs96aysW6Y9rgN/WDL0bdpFwtJv9dh3MM9BzaDDZmXhIeq/agLODTj0cn\nLBAlJ/NncFz2skk4WmGcHXvSn5vtSogWLyKnXboM5fiA41O79hDn1/CQ//3D\nXKfWuGvkDG7OynuJGcZ3SkUgmXTwWc2ReM7F2UTS7IK4IDPnvy/izJlfR3ET\n2mgX5w4P7lGG90yQ6irmKqEeDP2tPp5Mxd7axO1/6aqyUOrDrk59oVZxdtTs\nw6KYxCI4OIB8rCnJ70sv56YYooCSdg1B6C4+O1XPBcGBX5mDIAeIuShGO5EX\nUSKKh/8aWjYOndO0BlwaVHpwjXQ/JqMK1zuqDmto5foyR2W35SRjMRLhZABg\ns5sGs6ZWsYrZcR8PFTTexA6TR/0KrNcO1a6lXlJYfHjI6RrXVPt8tHpRJlqV\nnisS\r\n=DpTq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8Iie0WsAxmgq4pdbDzKM+xrovfb4xPhtL6fDyMawt6gIgCHDU+/2PFAeZqNETuC4FslobjfSh2FTzZ6hxwxG6bqc="}]}},"8.5.0":{"name":"autoprefixer","version":"8.5.0","dependencies":{"browserslist":"^3.2.7","caniuse-lite":"^1.0.30000839","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-buY1XxFoBrXvLsoFb0jP+niSu1tCj2RwMwHj96+RfQ8DJTgb0vUhh0dg6wjJT3JzsFYBrkSj8/sGtarNdlxTFw==","shasum":"89a39b1316fbe7bc2b4997a0c7dad0149d99511c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.5.0.tgz","fileCount":74,"unpackedSize":336328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa9/LqCRA9TVsSAnZWagAAgawP/2NSpQt+K+a+8TeS1SIj\nqJdwSp7ga9TLBDPuqRVVIFxLSpGuj+NRbm6q/+jlLOGQH5ijwQR1Ar8yHuC5\n9TRqVTFRYxtxGGp7ym4Fw5NCD3HfQZrvBrJ+v8997DSGyamfanoB/kuyMUvP\n44F8+3yIPvGqZcRY6Mh2y6FRBYbvUfM+4YJk/anDFFwUHp7exSmPrvjxXXVU\nBxlmUpPRlyTH/1CeQ0FMtYMMOJMGm6OmwrYHieVlYX6nch7TVCTtkUWlqzg8\nfAs4a0L46zLtf8tAt75S3o1SB4ZJ0kmqxkl9OoIceCCVFpFHG67Jgl8U7zre\neDu9Y1odDq4ImDnV1RpJwOMKLJa4b7qNEJehk1MSgXx1eg8gc2iidVefSlIH\nD+LOCua8lEqdomhHioumUnFbBLlal8dlr14xbdWsioAi338bWERUMPulVfWN\nN+5nBWdSMUCpTBeUzzydEYnx5riKny+mcvOW2yREI6JusmO4mC/B87dHLDZD\nLE1CGaQVrj46ZqamnTij+XueZN1ta8Nf//xRp+MgCfohtMT9/kk8XDUQdVys\n0sNp9vsoiwMmBgcMH+gCl6MIoV1AiA7g0Lwn+4dyS/IK5HT2c2PwK+YbX0N7\nvv08u9+K6MkgzUWo9LaCQGRbG4lX34g+0K3veV0KbeOFCj38tiAnwUxBxKZL\nvo25\r\n=+7Rq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFEfWiNCY+jMrCCYkp4J7wk8Jp3bz6Id8kQY0EhUeUYVAiEA2InCPqU/G5/a++nqNqkEKRM9OGZO/mpVV9e2f/AI0UQ="}]}},"8.5.1":{"name":"autoprefixer","version":"8.5.1","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000846","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-0zXQ6OqbnVaplQKkKTASxHFPMNy6WfrXS5QRDJ4zTDxEBB3r7NPDSK4h9KCyQi1tq0tX5MsN4RdzChVBn2k/aw==","shasum":"45b0271b0e634af66613d5a4f99d96f3dcd94474","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.5.1.tgz","fileCount":74,"unpackedSize":336507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbB/VHCRA9TVsSAnZWagAAWpgP/iqPxsDimZqZSpMelsyl\n6PGdyh2aei3WArzLf0BKvnQgdvF+Th8RdR6XhkyR8TZOBCl1/RqvRcJ4Xe4G\nut419ZwUIMeWQVsYFx2x50Ghx2Gh2dH4wFygF7fU179YRfVWRIqAavnCVxXO\nUEy4emI+9MlZUX3ez2nefbN1AXf9JAOEf2hyJr+WceYLp64I6iExpwCa2ZrE\n4HtfQnsZuFCqs8BV96S/DfRvQUEKbRReKNfaqiI1JdHtRoGWO5r4ZMaO9ktu\nHCzWmCnq3Kv09bEy4DhQkMU0P66WhoYBHVu+v0iloGR2zkuueXeXBOAE/XYJ\nQuTfU/WRyavke0ylWZKk8SDxAnGWZ/jCjUnrxi5cxKWn/gtXnTgL7M0rzgKz\nEEdZ2I9acoI9BBwjAuaMhVP/KHPQunEtOjr3O8ok45A9qx8x9qpwLungmgaT\nA+F8Y3SEIzuoZheL+gV3lhPHZmlo9HMNd2QhTCbCLB8O/qozAg+Ltg4HUFMG\n5L60SXeCQ94If2bcc+A8hjvfDOXOvE929N/fKQXofTGJZjK5FcP2YpHDY2I+\nc5ctjL2RMAy0o67iZykNHuAR8m3khINnpssFZo4S6UETw/oedDUxJrB187+z\nfFTUWABsS26gsVCMqS33ViUGIG+3TT7mHO+t/NsTXj80ndoqaKmmTQmoI3X3\n1VZC\r\n=xwV7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHKRQobBXdYaaCQMgNt4dRNNhjncamGk7B6Cr+O/KnffAiA6h//Yl76VPRB9c7NmPjKt49feE4R/sRtn9SZKUqsluQ=="}]}},"8.5.2":{"name":"autoprefixer","version":"8.5.2","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000846","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-X3BmI+0YBTGaqw0cR9FCPTyTAAPRpijzIUPkysRumGmJC6r8vhix1RjzLNjX01Kbb/iSezjZ9OR3G92pa31+WQ==","shasum":"52d86a5ea51a6191024d843f88f2748ce3ab39e5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.5.2.tgz","fileCount":74,"unpackedSize":336892,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDnzfCRA9TVsSAnZWagAAf4MP/iqrPbByqym4y0F5wk4a\n+chS6oVexL60y3S+hNPqKeFUjVLW6bxAjLbnE1P08GK2VXNsrqWCJovvfDzy\nZPabF4bxmyxnMEeHclw7srxGO2jEasjjjudb+3GCKE86JiUja3F+z4QLojc/\nLIG72WH9UsQ7oQtl49Q7owetRBtI+wz51Fv7GksyDwaUq8BCoegMDc+mG+xi\nU8Ofr5xxpndNhxyj7/iwkyMYcDJa1p5YDhchRDoinQrQrsY5RAzjPNTSDWHG\nYAzNbXMfIn4zHK5/nIN/xrACu9SttRYgeCPZ425Ji92u9YXwjqy9BpkoqEcL\noyRmCJ1vJc6/paQxh+k+UMaujUWb0h8QB0RvKeqPyfj+yPTj3lwhYy+k7U65\n0zzkvsSNoVCVOnbX7JuitJ8JaqhKhIZfZbrdAP4ma4/u/SiVW+n0bz+JSlyO\nzJgUtimKmnZjYXwPm6LNfu3RtncsjmekiXdpgTYOOVHOS02LB6bcg3YV8bpb\n3pTa86TEBS3nOMQXVQYvPNshZ84kzfAB5XgdVFCCD/T7dey8A+e2hp89I/pS\nSyxouYs20mndcf/yayIZob5P4FWgfG9/xJ55OwfYOMg1pwEGTfuBtyIDpivF\n9p3sAiiFR3xJGiSJl+DdSmKqVCK6H82SStyLXQ++4L14FSsQRxDLZ/PGl9PA\ninXH\r\n=q6SW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8klDTKY8SKnHF4vMmn5ESDaXcUQpBzn9moDsKVpvStgIgLKf1md093V/tg3O0O7iXvblZA+Pp2uLaSJnA6PIrJts="}]}},"8.6.0":{"name":"autoprefixer","version":"8.6.0","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000847","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-JaYK4gmyklt+es0VDdWVS9R/X96D8eaT0qDLAO6R4niBsoKv6nI4QtfFs8YQskwatIdJ6XZeTBDRpjf4tH+Dlg==","shasum":"6da6b0791e15cb0ebf33c3f299414afd340672c0","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.0.tgz","fileCount":74,"unpackedSize":337880,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbEm/0CRA9TVsSAnZWagAAsm8QAJi4OD5f/cYCQRwWvnl6\nsve7k98ULRHFR3ABDiaIfkVmhuAqIF7z3sijInZwK6OK2fvQH2eZ7Z3Pdab7\nIZVrOyo1XmMNBEQZwOuQAv2lul2rPORsv2LFO1pwsZwNHs5yCOlU0XvX8lfS\na3EFWsmE3ViQv77s01FWrVyjyDXueYErjhlswcJeWXs/om5OPml5eMa3svop\na97x4NKcyjSX9lUgGv60bIEND+jHkvt37ZDUfSj6sWRaEd6aG/swINPRsKW2\nbyuYPR5FG1+O56b5EhSILHnu+I6ROodsnEMi/2ZBxJ4PgW8Hf1Xa3YNlU85r\nX/L7thCy4VNMaloT3+k15tmrVpkbFBTmJJNrhM2jEXT0FFk5yw8nFjpypbCy\nMKyEosyG7h4ffLHXFaVJOhZ6BWwQ8ZRyHY0JIFiC70ElIH6W5vdguDUcE3WK\ny79CtLrwOwr2Fd1O5LeFg6uv2qAnxqMZ0/Uh6uhVgT0rPW81pR8gShxJBef/\nzeejp4XC+mjFKdrymK9YSFiNDfJ6b89aQV7OZ1RmEYoOVBty8nPh+cvH6Sdl\nmk648s7Mu5fo7xsvCOCWPmNEoSVZpGCOpLEdpEXDoQGumzM6KGmOCeSONqGe\nAU3xwAX0WEwteyCiKKhAVPQnXvvZm3S+aOOFRRI1/NBDz8t0SE7aMIBSf/6v\nN1aU\r\n=I6/4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICTYdazTkGMRnaLcNb3lUAx4LmyYf/nxQHIGnUB/JuJIAiEAlDbnYQDe8P0mSCJiqlkQVfgUBqxRWQuX8m+EMKpCDes="}]}},"8.6.1":{"name":"autoprefixer","version":"8.6.1","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000850","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-DqvyCbff+kvfrZgoDHIRK28svWSSFE/Y86FXUd9zflJ+aU7rr+6JCSuhNf1evSPzh+42GdI39BuIjixN5W/EPQ==","shasum":"cb186e6c904cd54a4af7bda078fd27a1fddc7be5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.1.tgz","fileCount":74,"unpackedSize":338237,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbGT29CRA9TVsSAnZWagAAcmkP/01FPZWqRshl1De7te61\njwodLmZyu9C1suq/dHfLgUTfGSi6lT/N1diK4DNAquVTiOrt0W98GaUoq87q\nFvJyYx0S135k904zDqUL55V1T8+MArRvD1BN/2o8NtspwqNEdlfsl/ZGLpj+\nrT0i9CJZ7eC74zn7a0eYhmvntkYfCZ/bqu4d4Mvs89Ad4gzG63W+lhJgUVBi\newTMv69IECQtAM04+JUkpZlhqZYbeQWv2vX67brzGzxo4Q5O+NrHtR8cEXLg\nBz4I/w8He2qodVAps7Q568Xm9FTGmdH5EJzForB6ShS2fhw7i6kCDMZfVySm\n2FBi+OXnVThjmghHtRyu/rvgtyo3mz1740pd2Tr6OUBFLsLJeJsPEoiZ+tAC\nZk6InR4dK9+dHSewxyhZ1BXcbrB5hG11tjP8BvNmrvRyqsP8EFT2/clQXCOL\nosH2ecKiMQdlIqiX1ACQIqT7gpkeSpL019C9mS2sTywRD1uo9igrU6Zp3wy1\n5brB2FCzNKE9mr7L2yUn+iEiiCJ32flzodfSedyHOm4MJH2Q+GaG4w62bX/z\nj/h1/wnnIfCKVTdx3OdubyfSUVXk2dLZdzDx0Vh0PH9OjwABsNPPi7sUXFrJ\n2SV8WVhG4jtgWnvOirxEfzl/pf4Fp0l5SdBQIUvbatzhALhjS/gkpSM7ZRja\nK8FN\r\n=tpJb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYso6jHfoy8qY5cmxit11KBE4KmRRxjQDVKDK+PvOMkgIhALfc7RJ8EHxkAWMX08Vh2enAhl+HgBl3Re2pLObs+Jhq"}]}},"8.6.2":{"name":"autoprefixer","version":"8.6.2","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000851","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-cv9v1mYYBcAnZq4MHseJ9AIdjQmNahnpCpPO46oTkQJS2GggsBp2azHjNpAuQ95Epvsg+AIsyjYhfI9YwFxGSA==","shasum":"51d42ff13243820a582a53ecca20dedaeb7f2efd","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.2.tgz","fileCount":74,"unpackedSize":338329,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbG7AnCRA9TVsSAnZWagAAu0wP/jhZ6G/CL3+QbbaVY94V\nVmPguCHe6cenDRukUY4d9/kmQHmhvS/nNNP0AmcSROZgfEcoH1TqOTzVKXMG\ndk/73yIJXxjnKE5sNWnNE2Y7ATqHbdV0se8pTJnwzlG3iPjS4BfpkSOkkTtt\nZhBrh6oYnn6vcHgavNiTBL1Y7yl3j30dKZXXghFQG37OMF8Q//a6d9VPGsAB\nm/7Ps+KbkwezDL+SGsXr3d+US8YL8lSyIwsS8lr8wulnCLdQNiG9BXaRcLXk\nAEqruy87LzFfuQa99RgkZW9bOobKjk+hlNMAUNj6r5mSzpv4lYucJ5pZPynJ\n7AwN8CqXNLwoZWzBvKzbWepRvhYwTe6SYQL8Az/dnlOs7p+HgO9wdf+CeAm+\n23b6SnBTI15PDUZXUXe0CFZw6BCBcmNidAtJH6lUlmnDYb9wMMMWPqqpiEOK\nbO/rDCK2pO4kzl5CWwm68y35tI5vmCBRlQOM09CR0txVQ1638iCtEjYWiq3j\nm0tnFYSveTzjlLVcy5zLA1n5Iw0TC64QSlprY9UvkpA8/mkzMmYPoJuX6Pi9\n1M5LRUMjCBFtInq1aPsftQnT/BgZhaubyaS1SrSyvvjoW9UhAdo8T/kxTB5D\nNit2qVxgQKK6NZALQ9TGqWUv3nbx3MpynARzgqUuJUBnVQaoEcwz6Hnv5whb\nJARA\r\n=/B/x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDdnRIZU83kkdsAZV/ERe0mWe2CZZC56Ox1cRWxYxF+KwIhAMck20ya5NoViPrm8H/JRR7iAzaLiXN0vEOUlzmy/uyy"}]}},"8.6.3":{"name":"autoprefixer","version":"8.6.3","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000856","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.22","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-KkQyCHBxma7R2eoEkjja/RHUBw+Fc1nY46LdV62fzJI5D7i8mLLCtAZ/AVR3UbXhDZ8mUz4C/PF4lZrbiHa1ZQ==","shasum":"1d38a129e6a4582a565b6570d16f2d7d3de9cbf9","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.3.tgz","fileCount":74,"unpackedSize":340511,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbJ7I5CRA9TVsSAnZWagAA0bsP/28vkKxLJfA39M/VUiSy\n1O4NTL3PHvtrGrlA0d/snJG3LgXy3w9Xel/WHndFeXiQJPSFt7nyySJC6QC7\nWJwuVpdobRDs60smLl+HGTPcj4UJxNcV8McLTPR/4xkCyUW2X18PGyxYUX6l\nJyFVY+V2BGzWhFoRHzOUIbbphKEyJeqzCsaQiX7I+H+Y3kXGyqQBJRJFmh1v\nxWNZi7jt1XB0Ml1/IbLy0bEfB/KCHP3eL/1QWgaretWCdUF8KK5CwxKTW3zS\nE7zVG3LkQtqRsgXLW6DBWpjyHnNzRY9yy5lkVXn6rSIRjs2EaZLi5Ilw7mKE\nBiLf6TEFydph28UB1Oj3uUqJCJlPCYx9rkwscjln8G2gMXmxMceSP3F1H/7V\n1jIVSRufKzi5dRnD6SGiZpoSpvAGpK39VP0BQhaRwrUBH7KygdPhkWFC9RMO\nqrnV9Jwf//Bmq1nvUQRifamevnJeuUq6wMBWW1k1hmyoGBiPIio68VRJgZoc\nQdOVsb2A58rr4ZpXTeP6Dig7bUK4oUphDlSuZgjkF8gtxK9LFqlyM3+S3tLS\nnKR4g7cNgzJ7ks3fwOnbmosOmSYnK2TbSlxTHPqwnzM3oC7F018qV2rKPf6u\nejGJT3zO8udYdABxfAveQStWb64pvHqRcHiA/Ku2rfCT2ADVVYuFYXTHZ40X\n2r5V\r\n=oACG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAOKQTjlhckFnn/4XK44dRRq23atLMqnyrNSGBXb8qS6AiEAwxfGWgC8rnkNJucxRFfu+BuW67ULFj6PxVXgkwxpZhg="}]}},"8.6.4":{"name":"autoprefixer","version":"8.6.4","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000859","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.23","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-9D0OoxWCqq9Okp9wD+igaCf6ZaNjYNFSCKxgMLAxAGqXwpapaZ+D0PBv265VHQLgam8a7gld4E6KgJJM6SKfQQ==","shasum":"6bf501de426a3b95973f5d237dbcc9181e9904d2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.4.tgz","fileCount":74,"unpackedSize":341047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbMlntCRA9TVsSAnZWagAAoDwP/2eSu8gn+cdiEaQpggIE\nyJNQCbAmf/HggMmVHBp/5TthopIcGfJyJWTV2KoXpfs9aT/8Nqcl2FPpEMIP\nyrIsXqn6r9DW1BvGoP8bsryRvMFfZTq7ii4ytdhvrEIZ42A/UnNCMvnQSYyp\nB2LqrXTl0WLXKRJon1wbHVh+rdfPtH6A1cdYB2ihYAGsuCOeGE6GkWQYwraw\n8KWBNbqxwZF6ENnrzUK9GvuW46B7ZL9nrO9afwcxRe728ALOuZaP/n0a9+Dz\nHp/GiAFH8LQwmm00MToooRx+f6W5rlL9ReBvcz3OB5YIRW6IME0CfdNv2CoJ\nmAXHPQCDUfS7YjexuXu6ZLoZX0AA8D+qovWvu4lzmEtxqzd4gKe1W24UDpa+\nC0aWxmZM1ueKZ4scgs7gtvIv42NpvkgO3q9FVe2J9sSAjhMfuwMz64+55gq/\nNpDq+yf39PdRcasHQklhZS7kjsWfRzmeup2VLPQY3dyRdzQvMlppOyUwkwKY\nkit84Xx6hA94tRhAW6M6TLbwVLFabQFGH/ZUwVt7iDaHGl05m2oleiwzBmF/\n4GtoLshV/krP7XJvXyvUo7emym63oaUUBO9Y63WpBgmpmmS6CFt/Z93AfzH5\n1Q+ys5GcEW0kqr1m5YCgaOvjy+2gC1M7i2SeRlTLZY82H7pvcXWJna3G+DxC\njz9k\r\n=ASjd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCE1mBeCV/T9q9yZnFDPO0GHhFg/m7NS48GezDOP1kDHgIgHITstv3qtzv2vhuocCmFaSSafJfct6Ox/UUFAjfCTgA="}]}},"8.6.5":{"name":"autoprefixer","version":"8.6.5","dependencies":{"browserslist":"^3.2.8","caniuse-lite":"^1.0.30000864","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^6.0.23","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==","shasum":"343f3d193ed568b3208e00117a1b96eb691d4ee9","tarball":"http://localhost:4260/autoprefixer/autoprefixer-8.6.5.tgz","fileCount":74,"unpackedSize":340824,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPv5ZCRA9TVsSAnZWagAAW2sQAJYVt+AZ1+n/LBvbrdwB\nAqLiQa+tsSNKpV+oAIVYEpKEcWqf876xMZ3hkmnpD/hl1tG/LP3S5TbeHnqu\nN2bzPvqMdaKfvDJL3S6YdoalapI0qWU0L6YmtU0KOjCsBxiGfZnVPOwZg5gj\nikyiAT5LdsYii85kX1DSHC39YpYtHq/779B7z8Mf9BUeTV2JCHU2WTfCLrL3\n9CEQxhKJz4YiVoS7YD7Iid/10gqxddt04bxDAhJSUD97mLKmGcbv6To93Vcw\nRuRKXGC8BHbNStR+zSDf1XRR6icQxCml2nxu8RC+hUK+qIfnKJzNrufuwvmq\nXD03hlm1QRxnOStH/cDbsNBqz8Pf3l9zufGSjFqhXsanm/V7X5SaAR95Cu/I\nRaxFl5nxG129aMFHs3Mf5E2MMfcLG2q353A1sjz+WTlJUlR+EqYBUTNQ6KQR\n8froNrY9V6lT1YVMiv0DnnWrQZUDSm9H7SPcfH41JPOPjwMCKBAIjnCSNyjh\n+/Ipj2M9OOyAgRj0gK8AVQjyYblK93KOooAcUuCUcA79rpNUjG28o7GRvirl\nHCg0uOKG/pDmYvI4xpYZcsJBP50X8nILr9wbaQGUhI+WRWeQSX0VhPPfC3Zl\nAuALlIn3mg4DWDFmVaHjuiccS5botLiU504Wh9ZBA1PoUlyX4c5NATvSoPZq\nwPaq\r\n=EyW4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFBwm9I9AKWxSP/Exp6ESVL/d2gzestK3+gKW0Jy8M2mAiAN35zn0UFYUriEHFKmWIC1oBAkAg9ZGREVoE+GqFuuDg=="}]}},"9.0.0":{"name":"autoprefixer","version":"9.0.0","dependencies":{"browserslist":"^4.0.1","caniuse-lite":"^1.0.30000865","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.0","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-bMt9puCb+xk5ds1ghr1zzfJ09+SjOcseHCEawhMjibM5KfxkodW8PQMhhEnllyj4Cz3Yixy9A+/0De2VC9R+dQ==","shasum":"fce072cb3c9c61374bf6fb7d1906f630afdb2889","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.0.0.tgz","fileCount":73,"unpackedSize":311370,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbTRaMCRA9TVsSAnZWagAA3NcQAINZqLip62uQkhg6o4nE\nlplLwsDx6RRIpy2vJ08CuDqmwCr9st9zvMNPKBkJ8tj5r5ow0Fe2FKp/PKCG\n3D1qYPlaF+N5Yc9OBXTHSrDPrJ4rwIlI/P3NlTk/LcO2egSb5g5LVRT8g3Vy\n09YUVLdJk5U/dcECE0afv2rVZhWmnTeSOmLaemd0aAUdNNQ4fOtfAACuhx3A\nD8oNhpwjrsbMr+uzYCrFbch9kCsUe6sDrYrWqikd0Y5yHPf2RdevKj2J53mV\nhXaGy8NwcOJptiTswv8lMhMFGEfJfey8BMk665YDdfPpPHrqF/FqbOSnNnLJ\niaAdBea9ezxoEUUpgop10gTqtA8zxGtxJG79DkH/5e4n6WymiPRG5xsiyao5\nBwURfVb6S+UBwJ2yXNbd/pAiQ3fII6tBNsydiJgmrQCk3JHthC9RTRWABwZb\nWr+AVCp3oR4GAGTMcwVhVX+v072op34VVoPuqs1FLk9wXA3q/VwkJIl7FvIn\np0i9W0M7P0UKrNvlvCR1usp4MoVZG5/qUFn+ZdjWVgyLBfjI0hY1p2eltKrY\nNasJUIv8ueY3/YPT894Tb83YXwi24UaeZZtUDKqCxs9zijWwfGEVJvlvQrP/\nNVlQor4F1Sy8My+slG+tDhEwq1rPoZXo9T2A7pBkf05VnfGog419dmUtXjXJ\nOv05\r\n=6HVG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGo6pMj0h/4q9ZzKzkbjTmctcbF1BgQYGiSasCa5uEShAiBKIxKlVJ4oP9KNGNhpGZGl/pisHoGFLtt2lPCmksTHVA=="}]},"engines":{"node":">=6.0.0"}},"9.0.1":{"name":"autoprefixer","version":"9.0.1","dependencies":{"browserslist":"^4.0.1","caniuse-lite":"^1.0.30000865","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.1","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-ytUcgSKu1mZh8pCJq54BkaK7ijigK+nhqVmu8PYOR00letCkrU71qTfKnzhQgn7by/QJvlJGUAofMt+jyXJTxA==","shasum":"b5b74aba3fa60b4f1403729e46a6a1246f16818f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.0.1.tgz","fileCount":73,"unpackedSize":311604,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbU3tJCRA9TVsSAnZWagAAV2cP/0d557UcMhvCeCGx3AJi\n7IqiiwDaOibCe9diN58Lz0ZTKgjZ2TNblWyVWsaacp/zrCqMM/+/JxscoiTT\nnmJtk6uShs9SBh0/jeg//qR9yefLvDLWmBSfZQZ5r3IN9O7Grve+M6MEDPQf\nCCY5st+Q9MxCxzl/bP72vBzTC2xiyPWXRQjBUaGj5uTiKjJGdAvl3C1/fs0j\nD3qVmjrcYTwwUJA9cKKAlPrhabTBhLULfIKC+wvvQlDaGXC7i0cIMK8MTzJ7\n8Fha/PH5Duer4MN6hXBN3pTQrK6RFkwS5PNlh758z7n6MBPI8nzNnAmG/sNm\nBEONJ14laxIguH8YLpxj3U8SNOLrYWD848jWOOASyIkV/YlIR945Tx/1iuVd\nl72bfAnN15Bu/Hp1ZWzKcWQPJ/KNb95GzejsD16ZEk4IEoHe9lmq6qXoF3bp\n84pcnZEQ/FdI6JhmAp4TDOL8xRqB6OksFPZSFJlBt2olp+GdzwQAfG1ugGf+\n2fcgasUocXbmxBwgIyJ/uRyn5CH8Vc/W2CD+rDSkttVus0GqJoR6QtPWAhDm\nS/z59EVal7e2RiEbrSJEYQOPEWyc4ZS53V/WUFB+KJR7gWoPewQ3DWCwuHLx\njWorn4CHbCxR3bX2N3NJW7OUTM/Aj3epTu5IYjuIaiTW4VUBqbcDwYob8cIA\n4VJ7\r\n=jgJO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDrOVF2QsKHH22enjtoz8MVntUK1DyIlne2hv/TBqk1HAiEA5NdKXzmLzRKKGu0ddgpj0pzE3BsTyiyo5QqsHt6OPHY="}]},"engines":{"node":">=6.0.0"}},"9.0.2":{"name":"autoprefixer","version":"9.0.2","dependencies":{"browserslist":"^4.0.1","caniuse-lite":"^1.0.30000865","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-t5PpCq5nCNzgPEzhty83UHYLmteY9FTL3COBfRjL0y4BTDB0OADbHVzG/S7gzqvITSsAZiaJPduoDEv2n68JNQ==","shasum":"c41947aa155038b3614414dbc58b4e70908af6e0","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.0.2.tgz","fileCount":73,"unpackedSize":314823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbX24cCRA9TVsSAnZWagAAf4AP+gL1C5RWpsoJeMzx1wWS\nMJ9fVQW1eS03iumhTFyWJruNxFqy1q3Sx0IUDJRQEOkP1pXAqk0cUljYIXOO\niFYpTpKsZ0UI1qcqeO8P8d7NzXLIj8sAJFE69esV34aKMnmWcnVhleFW+x9w\noh3A+JJhproRwJmVMLqGltuR44SLc/cMXW8q2GBsG9PjoCOB6aVsm3N8PKpV\ntyNq+CWBKld2ZhHA48+upozEzgzW5b6mH2HS9eeBnIPbe9U5pbtoVwWhw8Pm\n7Klf5SNiEvqkYuvh2UrKGdIcAyHKySfou75l21L7492dOO08F7W/4GwDxplr\nd9pa5LrzrSq++PT+0tuc3J4VCTAkKoqfB8UqEW78C0halA6fe5bDlirZsEzG\nEN90eBEAUYyoVpnHKzwNBbtnNJx2RXoLv0Jk22SS1DWRtcQs24BrUwZfmjF5\noUo1SKU9CXnkF+pM98//Nk8tJSlvPJlGIp8C0k9TJuAniNboAyCBLsXvadBA\nWT7/2qH/EXbBUshJTDPiNYENuduGu/ke2+TQYL/teTlQ14L9lxF2KgJdYI5a\nLiS6O+77iG11xaOFcB1EHxUOY0dWs7x2NMabcyiKDpS5N9CCUJNawj0PMKWx\ndOw0cj1IVdyVnhdHr/pfkxVlrptLVN7bbNV34FXYEbM/mWaadjnyYZXuMkiK\nzUAv\r\n=dEos\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDkITCVCgceNY3aKt5r7cFtwFxfGBKXYBSSy1tbxZPcuAIhAODw2GCB81AA5gcBX3S0n7cMqoYHWBzcOXqFei8AuJRD"}]},"engines":{"node":">=6.0.0"}},"9.1.0":{"name":"autoprefixer","version":"9.1.0","dependencies":{"browserslist":"^4.0.1","caniuse-lite":"^1.0.30000872","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-BbAIdxNdptG/x4DiGGfpkDVYyqu4nUyNdBB0Utr49Gn3+0RERV1MdHik2FSbbWwhMAuk1KrfVJHe7nEMheGdBA==","shasum":"566a70d1148046b96b31efa08090f1999ffb6d8c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.0.tgz","fileCount":74,"unpackedSize":319101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbY7GvCRA9TVsSAnZWagAAs3EP/0Sbwumpkzq3hkAYZNB0\nSkgg0Jm9vy0c6f3WDbkiQIRp5rufQTvD0iJBAD5tSZxtB172sA20HekMfu8z\nFGK1Qrh7kZIlwEqB9Gjy/gcGRGcHRGT+wZQD9jGgi/GJ1hbJyStPwSfjlnK1\nB76kRDSFRR9yLzZi9YayJNhWu44pJEzveQU6+SOppOerd3Y8XPIcBaB7g1CC\noPas2nxEXfB9GC3cvJz7EabdM985hNmRKAxSuggpnRacZVkY7JznlOqeFnTq\n4O/AhK/UPus4AT7485peKvRChTqN5O9j1DGHIcSThS9DK32dJLHvC9PemGMa\n1T/VEhLkV8wEUG24lq7gZ4eer9mXk2FWmw5E2Fj0GlHYo/8JNEks9ruREEso\nkTi/TaRf88JUWEpRNbMrJK5m2XQCVcWQMn0e27n0iyP44RZfpQs/FRZE5dF8\nNkTVDMp20QfVoI/wMtR2+wQvepEeqFfBt7mgX02DcKVviw/WgUYs7jRQcPEj\nLCDnyE7Br85aYzup0OrJlzztK7LVZiElIMYQmGSi5tQAWAiysxdgLXkldBdE\nYChpMlaWVw2umPVGuR3bkmnf07vqIDV8dixoNK2L6kkc5/KbcXRa9rf8utyH\nScWpK6hX76atvEMQPjmmcTCqtwDid/08F0Mh5T5D8UbPY2SYWBTZTYYJnfMJ\nfuE7\r\n=u965\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHs9F0SD0v5C06UMwhxw+mk8uiDBrzoxyuqh1hAd3Z0vAiByoaZ9eaSFMjjUIe2M7H+492sRp5K93YtcY3cI0fJwew=="}]},"engines":{"node":">=6.0.0"}},"9.1.1":{"name":"autoprefixer","version":"9.1.1","dependencies":{"browserslist":"^4.0.2","caniuse-lite":"^1.0.30000876","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-Q/2zhVEglXXCBNCOFfnihQcQystPYJt4GrIopeWhPjFxRPXya8eOstB89AafW0nWhSscByp+rSXp9EE5X4zgXQ==","shasum":"e4ffa96c71270b8a1967d1542abc5f8453920a77","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.1.tgz","fileCount":74,"unpackedSize":324179,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcPOFCRA9TVsSAnZWagAA3u0P/17NTd5kiAtWJCn8vbEK\n5VVb8wPYP6naqLSftfyRG26uNzrYh3a6P3iEixUuXd7Ua7+O1gKg+Bo+xTv2\npZuZMJnQ0yXJNRGwfWi9HmHW7Uu+RoeaHqPxApwsTyaXVZo3OLZorrOMNTPy\nh+z2wQNsz56hMgsUn62JSg9CO32hJGHRCFKmb9nS8k0pIpEKTQH3Tw9P+jgk\niJDYd+8Rmiurvi8VRJKxzT3B5IbCXbROmGFsbRcTc+0PIO93O5v3QtQgEoSX\nA1GWdns7Jh9yZ9bfkkkSaxPPrPUPIt6jXOLA73u1W3J5h/mco6kbcVOJnWT7\nTCF9JVXJL+Kv+9XwI2S23eVEAEdQAZ6UrS5wUmFwwR4hTegRfBrG4KuDtRZb\n+QipGpRn35dQxjGrbKN6ojc64pxJplbBz3kniusy/PntdXa2MtkdcNDg8rrR\nqVqe4zdtpLpYeX4ONhRRXGFGa/4T+MWe4TWeoLjPbr18PDbmK2+2dZ9sNROI\nYJPL2N2tVeVcSkV+Pyk0ILBHMBiSqbmVLbHR2wvJSK0KsikZVC1DFLE+Rbil\n0KVm6gzVAepNOfmFMJdhStAXl82yO8lAEWWuda/kH/mQD3h1F0K7UZkNGMUT\n4SWHNInncxEYWK/MBwnx7HA+EtU/SUtQnhLuDbhg/yZZubjTWKQ3lplQczIA\nipUt\r\n=nQN8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBtUpcAPruV6UOCAcwny964QdX9VoBiQUJbq0IfIQqk6AiAS6LRUru3K/KFHnm6uhdKxswlhpP4zxtxvdlAX9OfiHA=="}]},"engines":{"node":">=6.0.0"}},"9.1.2":{"name":"autoprefixer","version":"9.1.2","dependencies":{"browserslist":"^4.0.2","caniuse-lite":"^1.0.30000877","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-deo8jkqEIQALuN4OMbVPmtH8BUTRUW2PtINom/ZZBX6MvDUPcFaxTVB2USkWyeLlfd9garISbhjGN5WDHgRH2w==","shasum":"73672614e3ee43a433b84c1c2a4b1ca392d2f6a1","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.2.tgz","fileCount":74,"unpackedSize":324248,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbeb2oCRA9TVsSAnZWagAA0DMQAJ2+zBMcPiRLQE6DNMKZ\n/gID1fLyNR34SJCrg/DKvvLlUIcKyqCN+YDRgkVViHWgfffkXkoFiQiZnelE\nQv5MgOJ50YEMpDOMVzvc6gb0Lq8FqtDLY/OjS8PhfRfWKUrqfNmbVA7/apZm\nPWwOKv7ltGIMz+/VsK6v3nzp9+uXlsPxTNxFD3GlFuRcbG0xb3YCrj5yB7MP\n/M4ZP9fj7tHBofb9PhcnaOyFPW0t5Y/fF6/P1kg4Y83SUw2a40bxAYyJcc9R\nnmJDXsdajHmmJ/K+qHzr6kSRmhsyjYh3dN86lmUxnjMygKO475GafGQEXJZc\n1YJuB29cAesfM911fFSlOD+xIGtWuDvtw8qWIY1mJpG1iStCxZkKxAUIdj+x\nxbx6XZrQnQVBGJj5EH8LJ9hPhNiRP9bUHMcr5nyrq6BqJAPMQNV37Ni5xT28\nXX45suxj0PkK9OdaigvgHgYyL7z8Zu6He+fUQ5fXJ/7LnbsiBJk1cnRxbaVi\nM6yZE4K0VphKfT0ObY02NOjYiA9227n5CMM7agVzoKn/PwwQBxYosvRe7vtF\nUBpqWfBTdNN8C3Ieu9MyXnc7qVXRueXhrpEuycAPJj7BPdZJcnPjQHAc7rmL\nfdv93S0UVrQg5CVfh9Y7YmSroLNoK4yz8cEsBZ+bhP4fHXPY/t+A0S+JuWZK\neYbB\r\n=kgui\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnSRv4ayl/cF+e1kYXwGux32UkSq0PupsI7sJ0Z5AbOwIhAMeo6jf9zsOt3gaooVDzI0Ecgg90615mMF3hJO1XJvdt"}]},"engines":{"node":">=6.0.0"}},"9.1.3":{"name":"autoprefixer","version":"9.1.3","dependencies":{"browserslist":"^4.0.2","caniuse-lite":"^1.0.30000878","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-No9xrkPCGIHc9I52e+u1MuvkwfTOIXQt3tu+jGSONAJf4awvQmqOTWmk7JhA9Q3BTvBYIRdpS9PLFtrmpZcImg==","shasum":"bd5940ccb9d1bfa3508308659915f0a14394c8d5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.3.tgz","fileCount":74,"unpackedSize":324505,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbfRYmCRA9TVsSAnZWagAAYvkQAKUwrFJIREZejXpLH5mZ\n0lBuhCTGBvTMSQOP3NysFkigqQoRTmrWHUtMgb8DoQyCYoo6xsjekZb28RS8\nJxYANe989tLyryKTv81Yd05cXuGk3y9xCyQDjkNh+zixJSsPdFvEeR8Kat5P\n4GN+uT4J+vddrBc6ubknoyMssPQ9ZN0l3LsPL88+730SR7Ch79pXUruzmo5N\nvmXflNGSr3Bdu+nC599a2PFfYtM8//6xCoO6kZdu1zlhjje9eacbuMTdxtr0\nYHDAKhslenIPKqB13jTM7ybIT68Oh/tpRbN4hct06ooBLvMdhezMfuOMDEkD\nRONgoMIi9ECntv3rpMVGsaV4PN3SmwouuicmQaypEHyF6kMv0jihTb5skq2M\n9KkeQC9+8sy9ycMkZEOu3/8tTylFMZh6/XF2Ft6lS4eBPkokbc1KA8QEC/Xs\n0Bahfo0a57o+wh9jkvh+y19O7QaJcETE8cAV/HYtNV8fBOf/k+cZw0xYmuQj\n2Y57+rDc0SKdPmrnF95pOMydItEo/o3sd/Xkkb8nAdvOtSGNYFitfnNV/FO6\n19/mzSbssFmK/pzICeFtFs5Kg+wwLcVYWeItXC1Ao701iZmZXPbMbkbfy58s\naQ8E50Z6in68XT8lJVP3xOOTBua4nLjCTgJyAfusfNpxRlhte3YflvIxhPI0\nmm35\r\n=Cwh5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfvR9wy7qh2fkLoyafVbAujvnprlxW8YKhAeBbznk9GgIhAN6jFaYpBMoCD7IVexiWcx0Uq4rDOleCr2yRrDFM6ben"}]},"engines":{"node":">=6.0.0"}},"9.1.4":{"name":"autoprefixer","version":"9.1.4","dependencies":{"@babel/register":"^7.0.0","browserslist":"^4.1.0","caniuse-lite":"^1.0.30000884","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-EZ5oGTl8A7Tpr/iKxaX/j898Y3QvWEAEQ2xIc9ddgZwI4p63a5HLIxpZmfRSOBC4/AEyBdtToTVKwV1rUj6qQA==","shasum":"2e850724836e7d6974def410cb184cebc971c9b4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.4.tgz","fileCount":74,"unpackedSize":287773,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbji5hCRA9TVsSAnZWagAA44cP/i4MdiFWcEnhh6WxX7t9\ndMCOz/xZqDG/+Zn5lHlJyqBlEyobprIo4EecNW4gVixajua3UikhFfpgAbbG\nmyGP+/f92eIxE9kQwCVh2YMVUf+wqmKYFrACkZ3hqGZvzz3BOm3vwDU128CT\n+zeu8JIseaH3uy7/GHEQrBJLpapbu6PVltjK4eN1wiJxUMIXsfDOP2ewpgWC\nq+OB+fHLzyIwLVDt4c+FGzkmoCqEbqQjjxEE3Tykdhc3hHUX18XPJScVJDtq\niaveLEjCyoi0+NbUtJoDl9ShVkzJ3HeyPoD6TJW96wI+5J8NFXF20XF/H9J6\nNgw09JYOPCOZ9Yi07026AYQIehItZW2wtQa0weh+CFJzlICxMfmauLTx2x3C\nh7FubhNbiFfp9QULeE4Jg0YINcXFJ1K3MPxusK337vY65E/ihLAgJxaX725W\nSSeI+INneGN0o7mqB0qEMkTa3c8q7+Vlu+lzDK8qyQuE5/OU/YCdWNgkfVIi\nH5wJbnKVoKhNPmbhlFQ2PsGqHHo++iTZEjoc7T2SgisvnpiyHQCBMpethgj/\n6Muv2hbVQVLbL3/NdvtRkeqEFNQybbpaWgExBRKJ7aiDpMKENwcSfQArLqVK\nUhjbowGCDByagHDQPNlToudnEq7i7+5WDhtHBMAVlSfFJoydw7NK2oX1RbSs\nOF4N\r\n=36fe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHIx54LBt/5i8DTRkect4bhuSk/CTcBkjbzMvMh7ImRTAiBSJBaBsKs6Wa7nNjmt2m6S78U/WJ10tsbXX9MfFGLiAQ=="}]},"engines":{"node":">=6.0.0"}},"9.1.5":{"name":"autoprefixer","version":"9.1.5","dependencies":{"browserslist":"^4.1.0","caniuse-lite":"^1.0.30000884","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.2","postcss-value-parser":"^3.2.3"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==","shasum":"8675fd8d1c0d43069f3b19a2c316f3524e4f6671","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.1.5.tgz","fileCount":74,"unpackedSize":287796,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjmV2CRA9TVsSAnZWagAAv30QAIq1DHHuW9nmfN6ANJ8m\n9iSXY+7ZTvpL66GU/RT1yn5/pdBqd7xAuyknFxonNpR1OFOsptxVh/cKjMXs\n8mMErgwb7OgLUn3rcqLi4uy5sAF7TiUYHSa25iamulwP4pSeUSs/9fvmXE9v\negtWxFETOdMTBVyXg6yHhl3UajzzapX62Z/3YwzUHQZusRGzBI2MrngSIWH0\nZ1ANs/IYinit2+TQkVoK13g3E6Ljlqlj7QosQBDPOMm/P8vHafbXlddPIpqi\naG/8ZFdW+3PyeOH4L37R7G6Sp8FOt7b97wUBzdJwa8iHvwCz58qKtAkSDzQE\nyJ5FL3/VHt3XqYwxx4OIfjWLr+Lv+Zwzp/HBZQ4foxV4Ao6FCMEvYcinmx7K\nD4F0v8ePU22YOa8IzXIaEeDV72KUCiMp/9gB6zaoJPVdydXHUTaZTG+gxwuK\nCvtUtuOApxRZk6cz0n53Jvq0oxQan/fBWqgOTjkOASv7Vn4nXw73wRMBb6Qv\n2zGFsxKXNPwXjfPRAi4utIK68gipeiF227Zk19HVJY3w1btMlqCc+wjT+l9I\nzXelsQuMLpVDEo7CLakTKE/gx7kcSvL49xU7ot3STMVROXeFm3vIwBPGhnaM\ndTnl08KtXh+h9HX6orbAqoHdlGmb1oibcKXygV2yl+p9VijU29U1RX24HxsB\nSVaY\r\n=QwS+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICZZaAuqwlIxBnANONXDQ78jjcoRP73nSB4ZbqT7QyL9AiEAugNHD6HEnQUBjVf6PMjMSmmiKQTPlAdhVADggIreh9I="}]},"engines":{"node":">=6.0.0"}},"9.2.0":{"name":"autoprefixer","version":"9.2.0","dependencies":{"browserslist":"^4.2.1","caniuse-lite":"^1.0.30000890","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.5","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-OuxUyTvzRe9EvKyouPqfr8QUkQ0pH400NOFzI1LFINO8zwgJr7ZTybLql03P//LjR0iWile2lCoy2vRTRSFpMw==","shasum":"e46f893882b19a160370e7bcd3ec6bbeaace4d10","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.2.0.tgz","fileCount":74,"unpackedSize":301432,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbw3vCCRA9TVsSAnZWagAAwqkP/34HpwrpHx3ANKQTFRWO\nO/W3ESTZvH0ptZ5mqtprp1cSxzvIM/2PDb9dsNta3vO061LXFzae858MJTXK\noFu7Vv0Vk/iZ9btzsorLLAu1Hb3qoLOOv7TB1EYFk/2kApTP2XFhi24fpStX\nr5TYsuyqlL1/6qx7KJc73uwd7SHiJQ0Umen1q4Udpove1nXCnAqwJDufB5X3\narwLAMCnSESxiUbo4stoyiixquUmBMZXn4f3uER0HPnn25Ylak4BOW0laHCg\nuEDA0TSHjxG3wjDtXeGaFs+tHlR/aOiaAjMhbtlTLR9ArfQcrHCbA3LtrVq4\nlog1axtf+31aLxN13C5U1eNGD/hAtdss+KVEdGfmij138xzaavl8xEKVITOD\nmIp23LV41rSyiz3W8phTZ5zhU87FuIfqz+VhlYADe07lPiGcsfnncFiO8bFe\nHUjT9zOHuVtiaWc4k7eKNGNCa3jXcMlPvsMioOe9kem6c8z5H0sHoyvPH6K6\ne8tkaMLfzgyXxzsSMJB7PI0LQGkPH5tmyXMX6VbYEP/C2LhmppXFV9ME7rJw\nr8kV2z8avqcpfekk+RAboDX6gUcQngUUkD+PtA15cPnHrFh3Q+n0T/azK/kj\nL6StsBnoke4nNjVnfWyYV0WzoG7P0iR30VMBSC2IYOyNEZKm824QiiKPJvvc\nHB4h\r\n=GB6T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDp8fm0nrWc9taHl/pc7N8c32TFgY2xsqRV1YrdDh02+QIgKTKXPyq/8v+PTAy6DWWb6UQEKN6EN4Yte6GBCGLmQX4="}]},"engines":{"node":">=6.0.0"}},"9.2.1":{"name":"autoprefixer","version":"9.2.1","dependencies":{"browserslist":"^4.2.1","caniuse-lite":"^1.0.30000892","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.5","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-qlK4GnZk8OXLK+8kBn9ttfzu2PkhRe8kVYoWcc9HsrZEMWiBkQuRYdXyJg9cIIKxfMzhh6UbvlJ1CsstMIzxwA==","shasum":"1f2f1179ceed4711b7ab064dbd5c3f9e83d9dc62","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.2.1.tgz","fileCount":74,"unpackedSize":301475,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxnkXCRA9TVsSAnZWagAAJK4P/1dJ8cnKpQmWAdfVupaa\nfKUq2pB8JJA475Q/E0y6NUUFNB5TfzKcS4e+5oZj4xfczGojoEzssVZ2YLna\nQgnwFdzsZhZJNO8B83SP7Qn/7gvKSofOg0dMa0G5slnj5zRpR3K5a/R3HiGm\nWdrI3rvpPh/FGwk5UAPXeF3BWRNTAcs2Q82tewNenfwZOCKDIa/lbUIXzJp/\nUxSuDLAeV9cMdCVXI3libXojUhq0gBFQR7rAS5Zwa3eRRmvvO1VCSYRMKcMb\nyXPg3g8JW0znM3RpZE3bhJFqZSYAwHe4tAqSw2j9D3zdPxigaT84DgC10a6J\nr5LQ6kxdOd7Irll7Ms7wRpViePi492TACsYnfNZj0WJO+MhYfxSoZCm6GVXk\n6rqVv/J1bp2HjAB1DEYHV4Lo5HpI7kHqcsBJTyAGOThIDDlpqXuK43JEtoe4\nJVUmIduWMbHGP4Yv+JQY5cQaTPVLBYtuhsTfYJftuBs6ZGJhWDuWimMBjsVj\nGhEWEkH1WJcW9q5BqybXkGTOdCc76jmsWgZgGuUt0hyi05RAhZdswI/xYASo\nfACVq+GYD8CI2kHSDttVZ29pnu9vDRAfd+pGDq0dusJ2jQOpLGp51t11sscC\nEAJfuh/2LuJJkIDIjjRwHxVRH57aMPZzByywqXSIUbVHGIivFDzD5A0kUsX6\nzY0S\r\n=lp97\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICnTvtIrswGIjL3gjMNHesjTWiCclnCkyanPZ5ySFVtxAiEAvDuyUccPH3+iaGtsgy4WoXr/CpUJgahg/6tb2cokct0="}]},"engines":{"node":">=6.0.0"}},"9.3.0":{"name":"autoprefixer","version":"9.3.0","dependencies":{"browserslist":"^4.3.2","caniuse-lite":"^1.0.30000898","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.5","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-rpp+REfk0Ii3lCoiXhU4+CGYn8FbYckmvj6JJbJGSdzaxYCGJ7EvpHncDqgfAn/P6XhWig4u9BBNnsFAfAd5wg==","shasum":"9189fe646f8b804125f0424329472894278b0068","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.3.0.tgz","fileCount":75,"unpackedSize":303718,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzv6iCRA9TVsSAnZWagAAyckP/18szSG0xSOZg3WpAlC5\nmLkcUmFa/N4MtJWN+j02c6oW3NgHd+0zLk9tEPzjj0ylW9F0Iq1uxVegVCXD\nNWhjedCcLwFwEI8sizWJY0WHw09lw4RX3qtM7E64xie3jl1ygzxk0okQJIJk\nAcYpr2F3XxqHQuJUhp+BWsHWpT+khCOuydeUO8xXGN4YI5zmWm2NNkFArPFb\nn2e3mj0C5A+EmurOfOwOG9E49AjglJfH9qinN8gvFdUpnC77Pd43moJUpHCu\nxS3GBJnWHxZiShLilkk4AH7CH1rYyVLMRG/AgpX+D5/wdkZe9NEQQRitnu1P\noFb5MjWg1bZoH827gM8ItU4/LPBF/Jh3EGZ6krcluvWr888LeI7pUHGhU+nj\n692MHMdbVhpv0edsm2KdXLTJCf42KXsrGjf2OAUx+LJM2RFTJ9DxrHiE8bJA\ntk6EPEQEn/y8zpY4RMx4t49HzuMnliieLxTaF2jP8/SjU35GXNyTlD9214+w\ndW+cPYdp/bJzrOk2PlgdR3EpDTx2/5gCE3fgGEV60ccjmXJPbLJtU7iZtXsX\nWgcMmvzJFGWZvUX7r+3HdxRbVlev3lFW5mKCgDoBm6EIEq7ZPQllr3lrxEl1\nQeEoPrVMCGMrtBNZVCy7O8YcS1UXFTn4kBYnVjPbrhVaZcoWPEV5qQEmzV+i\n5yJX\r\n=J5wk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBihHM5c/0YKQi6SQooQ2Jrozf4a9mGCe/DyVWPgnVawAiBc73T0L3RRKtqEfN16hr0lRYkC4sp+mnuqorTxZkiPRQ=="}]},"engines":{"node":">=6.0.0"}},"9.3.1":{"name":"autoprefixer","version":"9.3.1","dependencies":{"browserslist":"^4.3.3","caniuse-lite":"^1.0.30000898","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.5","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-DY9gOh8z3tnCbJ13JIWaeQsoYncTGdsrgCceBaQSIL4nvdrLxgbRSBPevg2XbX7u4QCSfLheSJEEIUUSlkbx6Q==","shasum":"71b622174de2b783d5fd99f9ad617b7a3c78443e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.3.1.tgz","fileCount":75,"unpackedSize":304142,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0GAwCRA9TVsSAnZWagAALWcP/1IzF76iTQQQamkEIeul\n49Zwy/cDeg5NERwI/i9VY3I7MPB0VVt9ldQzVvsqGpaOGCf+8uRMBWidHrAG\nWRsEsXa46dSgNJETl/+t6yRJvTg7+ePvXHn5SNQ3eyI5UC/UD6QCRCTDaZAE\nwK9AQQsbH7jtWE32iNMM5hLBXJ83x3xrcG7Ov/rvxCHZZDRPa4fsYedDmhk5\nlHmPQqDhAoPuE1qpsdc7vaPQDQutVJeRoUpU0rZ62W7M4OpTarkD0DaA2P0F\nCJdtbMFu7c1vZvpPh9po3LXtnSR0juDc131ko+dWW/I8XJM939yDTQuxHXsf\nDErnUq19hKsB2kea4Mukeb77w7eYslL/PoHVwAu3iTz+W8BNpXaBrFpv4xTR\nvbR+/RivBy6aMTVyl3Y24oqPtORgxy+zcU/ednzIZvJuhimhiRK7MKc7864E\nwh04jU5zQkqX/pPgrwjWMGwEPTfR7lnwFBDal7ujZu0mPRA3JfPN6ozcFDnq\nVSXdkUmB0Ed6lvh+gHD/Ngc7+Dgg4gs+aZPGdb03nGsBtru3aeY1SgG8YCwy\nsziH+gnAXLzle9noG/z5uHGHQ/c7BQTU5veXl2y3hQ4uBKqDuIPB93revlQ7\nrDuW1Gj/fQUC/oWE1VfrHiLYKfbh4XzigpWge6eEOuaaefSZxOk5g+nT6oCa\nPngX\r\n=9QEl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCHxUKVX0se3tLBEZQAksmMoV9sI9PCr3fDrwZGWKStPgCIQDQImG07zg6AhrrhGQCIhbDzSjQSItTYxIBv525CZhhfQ=="}]},"engines":{"node":">=6.0.0"}},"9.4.0":{"name":"autoprefixer","version":"9.4.0","dependencies":{"browserslist":"^4.3.5","caniuse-lite":"^1.0.30000912","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.6","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-gv1a1rzOyxmB2JuyXDLVNWyyUl1uelaKyxO1OP3UNWk7jAP+EhAT9rZdcDBH0C+ZEeTL56qNR4j2TjRZL68bXA==","shasum":"4264ee11fdde83e6a2fb0136e6954af6361bf0b6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.0.tgz","fileCount":75,"unpackedSize":321955,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBN1DCRA9TVsSAnZWagAAQacP/1msZobZ8c3uVeIV2xH+\nC6BlsICak8VOssAwxTYhH63IPBMnznT9ys4RJBYjPfxYbAyGkvG+Fru/oF1Y\n56RjzYpYFZDqdZPY8WqJ0tsbFPqjfegsv3dBpEq3/aT9DydWDMpl0wpPjJWR\nXzu0xRiKihzWwi4XCIaFDXadezPsC68XIqFU5dEk6oNZ9w9RQyHpD04XV48F\nCR9q+PeeFUxL67FX4u9UIQIU7yBSYJArvEsoU7fRbF6vuF1fWqZlo/Qe+r2X\nuyJygegZYQN4rojoXhyOUcwXXASXHKjVa+ydl+wN4uFI3URRnnfVwxVh5ll5\nBo9UcVYbWjb1aLlagJZ9NRZKXx3GfOoqqKekOKM75O3jMepP/FhDhHs+xLVK\n8p2dqmgT97QCPu9oyDSKizjPUAao2tq2pNMhvahLhKt3AuXxjkgDQyTVBve2\nuG60L2GxaFqPegb7C+BfxQCwsgO2UU65QSlXF5iB/AlTKjR0lkcEuzfq12C/\nSX4hLPf686RNsAceYuNTirZTBSvk3d/YKEfP5fKR/3AprT2hA3KJcIzls4Ck\nvKqii3605Kpso4REmK4cPAxCOA9okRcQLxM/2quXDtNuKuZayweqW275OSw1\nEogVYGD+fWg8O7ipaPkXh8Wyizri86v1uOJYHtN5lmpmjCBiqFxGfEbpP5tF\nEH0o\r\n=ViHF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAsAb5yj5fHySMN6dg1Yq+5mrxDJzs0v1lOwfhzcap3TAiEAnLLrnH7EDoFDOH+bfSeGROPgmwgVe6Nj8ef1hG4mLSU="}]},"engines":{"node":">=6.0.0"}},"9.4.1":{"name":"autoprefixer","version":"9.4.1","dependencies":{"browserslist":"^4.3.5","caniuse-lite":"^1.0.30000914","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.6","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-T15Bt8akUOGqhkXPLKipYzzmmOOQ+H4dmZtk3VUNBbFiYuUh5uvXb/THxGGxbRlaNG+i39Qm3UdpLtpdiCMw9w==","shasum":"a3d7e9c5940ba85778ab780536f1cc51bd2dfbd6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.1.tgz","fileCount":75,"unpackedSize":321984,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBkwxCRA9TVsSAnZWagAATIgP/i7Sh8sUDOGaY2BMFA4R\n9boTqXAUpkpn5AyOxBdCtvOuLO2ZMe9OvTPq1aC38cPjfEsrkgBkdPVuq9/m\nGOtYH/MZLiNXkPGnIw+m/gwTbfxY546mIRo8qusyDKvkNrtRUG1vuOkhxPwj\nfV6xn1sr4s/eeWusrDOvGlyn9xmBVNd0zbO49G1pLiFzYqa577qgOJ+cbQR3\ne3vDvz50+y3DuAX1z1EcuEg8nWTyZauGEDCRdZolYmRTGmb6Y4U9BsTPF1tC\nC5bFyZRFZXUcvNEUAx0XWM+AS4hi5ZOm4tYGafwN92Zv6DsjteMf1HLVSNV1\nPUcFx3EHyonRCyDYJqbDeGq4jb2LU2HUMOsJ1HlZ0BVkO03Ie4r5Nt0PbwxZ\n16TkjJ2QiPHOkxdLRhsYQD9o4TPbvAE/DNeW2nlww/fkQYigr1tMQVrMK1Y8\nFa2ze+2CERiyUTrWJ0T37yUvtgxJBrLhiBSbcYPd1zM6zQI6YcEm1iPLw6H/\n9Kvs8qtnUAtbVRjFIR4CEov9H/jm15X4K6LBx4BKi+OpSnRl3riJ7Rbd6d4v\nOKimT8EDQLSRYySE2na41lyTdfv8gx3eOxlEXLkFYgM9voCaLyaMx0H5mXoR\npg036LTPHa+CC2ZOnt/PcJw3ttJs5da5IaSF+6PanMtghOA/Cq8HZrE2Yn0K\nXMQ8\r\n=0UQX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyjl2JdDl/h1IGfGIFFm1G8VhneI1dmM13rghWPEVLswIhAPMheP73nNLzhCf0qPY1CDfTmD/nYsIcJyS8APQSNYTd"}]},"engines":{"node":">=6.0.0"}},"9.4.2":{"name":"autoprefixer","version":"9.4.2","dependencies":{"browserslist":"^4.3.5","caniuse-lite":"^1.0.30000914","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.6","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-tYQYJvZvqlJCzF+BLC//uAcdT/Yy4ik9bwZRXr/EehUJ/bjjpTthsWTy8dpowdoIE1sLCDf1ch4Eb2cOSzZC9w==","shasum":"0234d20900684fc4bfb67926493deb68384067f5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.2.tgz","fileCount":75,"unpackedSize":322050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBpR3CRA9TVsSAnZWagAAyCMP/jH/qTz55sq58QmXp1BX\nDmPk5EIEIaC/aQxCPZY3Gwd6D0dY4oIz3RGaPYE6wUjIzBkkY0bA/CvNfIu0\nv2IBq/lsDpJXOqfsI8EPOYc9aDECQ+fyzv2HqR0RhYVfdLMAhzTT81X/DNgY\nsj86F4FOodz+VI2iMqdANz5CruXfWrI6rI0tR+MNZUnNSZzOrAYKnza7wrEE\nUMKQzFAtxdXE9A8sjNMWMA8STvrV0SarJf2G6iZEhWPeOqf4Vvv55LDmZCBv\ngInz+DHJFwa/cm4sWBCXAwUbSPIkdLFShqIPjVN1JunzJvjm40/8aq0YIZFm\nl6M5sILXstZmf/HKsxGgH143V2n9vyLtHlkWkirDoVjCtGR5UIYcUScZTas4\n3UppaNpGNH5XeZCqQbYyBU88Tby9kO6kKVq84MXyBgN0gOmH3IdQUzSvJaLk\nbIP7+aTFfqPZXFakj+wmN7wkqxisE5RibQ/1gshZpmNgNPFUcSfg2EKa0Q36\nfUY7RYxfLQ9vDqmSuN7lvmsxLNrzuNat6/YQ+lmKq5LUHZTvWq4OfRItazkk\nm1xhd/6jLglYpm3289x5DU6sVQLv4G7PGj1TPLQ4ERHt6ggrrr8Gx9BIGYuC\n21tcA1407k/YqqKwuY1SC7mxPY4GTPZ6XW4IA0NBwFyksltufqd4pdMYE4mU\n1L+K\r\n=OhEX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHGXCh/8RTO/uBncFttfOZKjsn+nWRvpbImWC3l9XUg3AiBt7vfoObzeuhay0pZdRDUk80jsO3XjloaaacluqKG46Q=="}]},"engines":{"node":">=6.0.0"}},"9.4.3":{"name":"autoprefixer","version":"9.4.3","dependencies":{"browserslist":"^4.3.6","caniuse-lite":"^1.0.30000921","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.6","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-/XSnzDepRkAU//xLcXA/lUWxpsBuw0WiriAHOqnxkuCtzLhaz+fL4it4gp20BQ8n5SyLzK/FOc7A0+u/rti2FQ==","shasum":"c97384a8fd80477b78049163a91bbc725d9c41d9","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.3.tgz","fileCount":75,"unpackedSize":322961,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFu4xCRA9TVsSAnZWagAA6o4P/2MFfjPAVVbBBgvDErDu\nN1tmsNxzIt8x+MZtc+02HxYvGxnNBFQ0q5WeXpzMWBHG2ShMryh0MQwYHgo7\nfbi/O1PufUgod2NvakrFx9GcsMosX2vLgyJxSIyVqxVGiGYQb/SaVpglvemL\nAZ7GN9M6tVYxpHUAnyYiq7iEWRjlO0NtRPBXZf/SPw6QD02Za3AnaPfrabuW\njOPpQJ5XZkjE1rKAufmOzFJ6QvT9NAHteJr9uzupL3+UK1LPMikyhJzdMRau\ncgq6Tykp5dRauXRSC5297Ip8i4o9Rup1axufaOPdVcdubEOrCEhbL33wIb9e\nW6rO5rV7WYSf6yKidEj0qBuNsTHtRfmYvUbJ55zZxPaDWNDThHg1cb0sZ1Y+\n5WPBPr6kPJAXMUfQSvNI/NlTHgr13KKLBPH3jp3AnGPT6A3seLULmzYx+47a\ncj//w1ESeblwzLlNjP76+nUrqQgkadBgU1IXqkIqfQJ2WbMMD4ONqUzbwUDb\nbSNO/N/goO8JmOXRLcu9WgszUlFH0C1dQAOKwZtiUibLpUgi8WZ6fadzDtej\naiq4bMayTN6TqqIJAM0bxV7c1xmyeRaXINhojmcxE5foa/zXlPVWfu104T3C\nL9tAEWWwSYEkSP2byfAAMXhMcG/WjW+FjtMbpGDdbpj/6o8JhFbAMg6J7pcB\nxF5g\r\n=ex9S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMeN58ajR/GmNMiODq/hjuLxIlqW/+NB95R2L/HWqb8gIgYHbgxMqFNomrXddU08uBjmquiuhRg53gxZoxnvbcCeQ="}]},"engines":{"node":">=6.0.0"}},"9.4.4":{"name":"autoprefixer","version":"9.4.4","dependencies":{"browserslist":"^4.3.7","caniuse-lite":"^1.0.30000926","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.7","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-7tpjBadJyHKf+gOJEmKhZIksWxdZCSrnKbbTJNsw+/zX9+f//DLELRQPWjjjVoDbbWlCuNRkN7RfmZwDVgWMLw==","shasum":"40c42b335bdb22efe8cd80389ca82ffb5e32d68d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.4.tgz","fileCount":75,"unpackedSize":323602,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLeuhCRA9TVsSAnZWagAAsjMP/iHPyNOVnmBp+jXMHyK8\nzdruqFsMF1baOgtGELqZyVquS/+/paJ5zRIRGhpE+lozcjG2g2nodJ3gtz76\nT3eVwn36Zz84EKXaWFCWT1faEdvx8borRWYk29/gGWl0W5F8Xi4tT+6igA2D\nc7cLNlrFeme4RTafpoegDWtLFDSb7LI43NNaUTktrljHzFdQLqw0UhTMWLst\n2F29Qoz9V2+mUE0FE9O/z75orAIjg8v0xAlH99U5hclF9xAVO7VeBUX/znna\nib/lmyrGTSAFhVk612BwarYdyOY1gk9ZpKjkSzL/HEselycaSVXWqfBWz8vc\noM3l7Urs8v2Bz3wQrWAlDcOWkPtCY9KxTTZADCUhtw4Zy1XvVbUmVFC8+0JL\nWyTaYXp4mM3hHARjdsyOISykhUU0kyb7RfpboNzj7aXAgwsPmywF65ofaCzH\nOqJFijTgPTe6Q9HvKW3zNFPQuzVQVTb3bM7xucdPLcg7uzS0YmCCksJTJXzX\nB+y6F8+ucENBvWYwIf6neHbssvEyBtTiMRkVAkZOza2C0RmSicvXgoOtyh3k\nUbAZh50cuFnjVFFHw8Avdsc4Bskrk2tcqZwD1EJ/lBTYpHodbj0fSJRrFYK3\numbmYp/zffuLSt8OV/hZrL62yXSPHKOobrKxahvQNqQ9mKUjXPJiEAToUu4O\nF65k\r\n=YxRD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDtgFPU2dlQSwQb53uZT/nby8M5Vu58kyO2x9KEJjMHKwIhAMyZENAWY08ru9V4OxClaEskgv2MTtrDxCu3j+QOeHzR"}]},"engines":{"node":">=6.0.0"}},"9.4.5":{"name":"autoprefixer","version":"9.4.5","dependencies":{"browserslist":"^4.4.0","caniuse-lite":"^1.0.30000928","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.11","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-M602C0ZxzFpJKqD4V6eq2j+K5CkzlhekCrcQupJmAOrPEZjWJyj/wSeo6qRSNoN6M3/9mtLPQqTTrABfReytQg==","shasum":"a13ccb001e4bc8837f71c3354005b42f02cc03d7","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.5.tgz","fileCount":76,"unpackedSize":325577,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcOh+oCRA9TVsSAnZWagAAJkgQAJDlFWaPU2ZldfYMZGoV\ncnAfoJSoQJOnuvMpXli9zpiMnvuO5cZ8ngJiRD7trzvOMZorO8NMofdChYmo\nFRZwD0OHyN96CXaI7sszAm/wYV2rir4IDMaP/l8zqr0/VH8inYG43crlqqTN\nPUDXZ6d+CDpTzHLpLiSDZrYi1CBStGIBX65Lmof9m81rROxxyjrKqwzuKqkA\n8Nm2xw8uXMUAS04CtyuRSMICG7bi1gSEpbfHacrvYX/k5l9rAxRR0aRdxl5y\nbg/FeEPJdWFbAzC2eYlEg6wmwqsaWRfbZcBh06QYcHDbXuwRB3ZK+CyGGVYx\nfBijzQmBF/4Of9jp/uWpXse1qkyIRJItVqquPle3QTI8y6lEs7NLjWPveRhi\nlWMv3eW8J+Hi56io9Kzuhbwg7YLN0R39Ja6LYSy6XrGqphiyxzD70qUpm8h+\ncMZiUMGrF5oD3VXIHqHDVlXO9SdAOQ4Z45V5ivPcdx8TxMn4m7QNcxDiObO9\ncNLUqsU/qS2y4P3u9ZWwtiS4RungO/a8NbHqDvfJlb2dGX4JsdmhZxr5PuV9\na13korKlBAz/Ufyyc+qBadtw2DeUbyKKwKf9M6MHTDd7UffoleoUgDNo4PWU\nrv6FVTYW+1WjEtCl52Gj2Eo1qv2+2kUUWCSukayxOIik7PwpbrRBCg5Xw9E1\n+YJQ\r\n=8aH2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkt1Ck28TFzH52etnXU6u4z4VMj9ygjWfqyIiE1pCNgAIgbZJviOBIAhV6Gf4gQQIblXFO5PAG8/D5AOVvCTBv19c="}]},"engines":{"node":">=6.0.0"}},"9.4.6":{"name":"autoprefixer","version":"9.4.6","dependencies":{"browserslist":"^4.4.1","caniuse-lite":"^1.0.30000929","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.13","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-Yp51mevbOEdxDUy5WjiKtpQaecqYq9OqZSL04rSoCiry7Tc5I9FEyo3bfxiTJc1DfHeKwSFCUYbBAiOQ2VGfiw==","shasum":"0ace275e33b37de16b09a5547dbfe73a98c1d446","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.6.tgz","fileCount":76,"unpackedSize":325634,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRb6tCRA9TVsSAnZWagAAZPMP+wQRzwO9bHf3D0xy1Y+Z\nWI9ePayzFctJNoSZCx4wXEAcN4PiSgn4x1Fe2TDZ0Isfh6pM7hSRyuir4lyX\nRo0Z2yn4MsTz4cPABUIgAVf+2X/OX77qKy5h7sr3V5k5Ufl13KqemzQyd9kq\nEu42ZDwG0UBQzCcp1Ud9UkYA0UclS7Xdv8VYfLUZQUuM6c+RUlgfG8c1OYUr\nOtBP9AaYuZYpdmf2O5rvunA0w2ZiCYbsCqP+Dal4KFRM/UcLq0A2VoOk22vk\nSrIL0AdJvKuLH6+Qja/DCKEx1LDC0raHFLYQkSqfkJot4CveDEm1eyCvwhL/\nfVZwxyfrkNeOgcjT8zi4pqDApQvIr1L2lZ2MAovEoLDZ2MVORZ4xzso/X72e\nuhh+H2NWxkB0mfEHUp7FjkLgc85tpHVSgqJwRhxNFReLdgEy5Z6svAu24GG7\nte+JaIUHFRAYfVAlmJNIN8KRrU5SS+ZgUb0akr+QlnCeu/ywfu9OIs7JDmRs\nJTUtEjfk2RXA0CYHRZbcEeDt8mBPSb39R1BJSlay1WSUW8s66rQzXxf7Zly5\nKlY6UFB/60h9GwqaKPJL0zsR+g6GPx1tXl8CDSZdKbJ+J2GdMozX3eGaliwD\nNKIdLTYyYO+HAGGmbY30Jk3Yaq+KmkH9YH3pHZC/lYYNOkg5jiiRHhKrs8Wd\ne/ih\r\n=+x+M\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCX6Ta9auwSYH35S123yAcWg9nqYHZERI9RSGoILjOkoAIgViC5imypqG1VaV49xV7xmqJwBW5PfhAj4WB7DdD+y1Y="}]},"engines":{"node":">=6.0.0"}},"9.4.7":{"name":"autoprefixer","version":"9.4.7","dependencies":{"browserslist":"^4.4.1","caniuse-lite":"^1.0.30000932","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-qS5wW6aXHkm53Y4z73tFGsUhmZu4aMPV9iHXYlF0c/wxjknXNHuj/1cIQb+6YH692DbJGGWcckAXX+VxKvahMA==","shasum":"f997994f9a810eae47b38fa6d8a119772051c4ff","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.7.tgz","fileCount":76,"unpackedSize":326905,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcT2H3CRA9TVsSAnZWagAA0+UQAKMVtfCaAgZh/9+qzFN6\nBtZkmSevvVCmqJNFLGR47fX4/S5NxBQxeClv8u9vaIdPx5/gXaMD11xVKLw/\nuMcym3m0XBFapBwk/PhQu7X5jFO2skeXiWwkCiUMZaijHbv3OnPaprBLYHcD\n6zVS9GwZJVzZ4+A+2Fos843PjbfJ1kYN41Gi2TBUMcK+ePrrJiwB3yaJGQ/2\nj/RB/r8EYRL9oBxXrM8Uz0vDZrHlWfZDVcAljmxx6S88fgrpEg00GvxTkjhp\nvnT9yq5XnQiCqLcb/xT17k61NPehSRPhwebh+n6DCxfDRAelBQW4i9iTaee7\n15oIXtYdo5XeAS5+NPkniIyZcHm+mWdg5h3ivzLCZ+fHBud32KALaqKmQz6q\niIkDrYmUVWGAjyn6I2HGtxjTdvK8BI+wvlEHE7a/QQk0nD+DNlyYzLwPgGzX\ngxElmLMFGbRJ2DQ0HGPFO9a+R6eQ3IU6slNzsAvzR+oKaP1/NOJl/wcGX2U8\nzcmRnbyutUHtIbY6oaol0FPXi3YwlNtjO/Mf2y6RmjfDTkSrKlXl81rjGMHy\nWO+9suMEkCRJ9KRGRP0BcH1oWJIalCY5gOgIUUtAx/bXvK0aZusTCLN+mpDt\nSoCoyseWz1Ai34rgR0kquixRAKRGCvLGiYT/kftJsqp+I2278mBG6KMfBkiu\novEE\r\n=DUjO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCjJINNukmjVVYepC9Dp46X35ikd51OByqtjcteAglQ6QIhAPUPZLVEIzRkOtYNRk2TAyNRZcpyPW9TouCxK/ubHxfB"}]},"engines":{"node":">=6.0.0"}},"9.4.8":{"name":"autoprefixer","version":"9.4.8","dependencies":{"browserslist":"^4.4.1","caniuse-lite":"^1.0.30000938","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-DIhd0KMi9Nql3oJkJ2HCeOVihrXFPtWXc6ckwaUNwliDOt9OGr0fk8vV8jCLWXnZc1EXvQ2uLUzGpcPxFAQHEQ==","shasum":"575dcdfd984228c7bccbc08c5fe53f0ea6915593","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.8.tgz","fileCount":76,"unpackedSize":326785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbKR+CRA9TVsSAnZWagAAaX4P/1EmsNHKOMJjohk6vs1A\n7CSvo726BMBCD203AfU5zjT2ejEzbi/QWJp72tBu90Uf+XDqMeFqJjI9m7gp\nzWxL9Hw6Kw+rII8FN5OAe5ipbZMa8eEoBc+1EaG6rXrTZAwwmAt/fwL1GZC6\nJD/SbGqZOYDqti1ajLAD5/kI2EimAkOCrITofrPGoIFKGTtvrNhMZABTUb5X\n5eSkFW087OBmNeX4iyAE5q73nlhj4Dx9Cg4g1nQRu5nFp8wsEZA9aAVCz2lo\nUzUjkp9ir7EhoeD5iEqQD2CwJMjLyExxtQTST210BEDFUcWdCb8Hd+jvh8Dr\nYFhmcJNElDxurX9ANR3M0WXWtscZmAxG/j2KwVTffMFbbeOugC2AzTeIJuyK\nDLXnbQoMBKoqkMfaekUwsugnND0CFucBmqcNDNc063eW/qC7R+htEeIQMqdE\n9qkqbLM9MJTLXJnl/qwYJwm8xev4rDvG+/mp0LqvpImCUzXuooU6MT3kXay4\nnHeSz42IIejK5OeIjqc6DBtaw7pvJkP2AgzdO0a6TCHwT7byV6grUw8C3QN8\nVgKemA2NB6Jgxzr3dd/26QZdi6s2XA+m0JVlF2y2BoDKx3Abk0VeIk3ouZS2\nGfPexZGurewotUmWJMjwErEnrgBGd3SHw5XF3lvTrtXI95UY5EDMpewtqchW\n+dzv\r\n=+y6E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYkwA8MNdR26ThGeDSV8R1jWtzvrITdWhk7WLF9UKLKAIgNKOvi49jT1NmkIzE3rzttM+WMTm3b+QeJaC/ifq7E7Y="}]},"engines":{"node":">=6.0.0"}},"9.4.9":{"name":"autoprefixer","version":"9.4.9","dependencies":{"browserslist":"^4.4.2","caniuse-lite":"^1.0.30000939","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-OyUl7KvbGBoFQbGQu51hMywz1aaVeud/6uX8r1R1DNcqFvqGUUy6+BDHnAZE8s5t5JyEObaSw+O1DpAdjAmLuw==","shasum":"0d3eb86bc1d1228551abcf55220d6fd246b6cb31","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.9.tgz","fileCount":76,"unpackedSize":327016,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcc2YkCRA9TVsSAnZWagAAsdUQAIMxmdkPk/5gWQxDKOJ/\n47K/g3b3TgwoQzBVdJhMJ8ang8kvx9lFNkyWA1jUJyahyqOxx9SqD5GMKVXU\n4MNGthNPdavV66d5IqFoX78VJ/Yuu38GM5g3PQ77OBplPh6IdJv+H1P/wGIQ\n1ugVv3/pgmPuahCa89ksRjYbdX1kiqTTe0VHFG7E+FmrqOhFaDejBNRtbU2M\nYsLgt8o3VDKYOhcbw1S3AtcAoYrepZp7yPVKLW+SWt3b3GW5Z9xUfTPzcR56\nuEekqPj3ilZF2w37s5lCz1y6jj1bmazT35qzpOZmXWZIDgJUu88IQfwBk/LQ\nCxmCeOLXy43ghFSC6HDHN+BODQG+X88tmhGaG5K7xuv4S4C1dySNgO4iyNj3\nw70Z7GN17SFkXg+9Xw+DBsm3KuVcUR4cN3897aYBMEOGBv3xB96SqsuBGU+Y\nd2+bWsRtKfOdP3dCoup4pTRLVB7TJlpwAqK+Bizkr7GYzvgWIfvZ3fRtgRRp\ngFLO1RXMyAWwmShJkSumOujLE6ucIbOCLvHXcl09ieJDa05OsoXMZFA8KoCH\nkTJcQ/Qs05I4ToGm+eLGIH9nu+8g6xAgjjwB3TVpq6hZCNlf9fhdK7kg69em\nYNJ+DQvpitd6Bab5uZ45qWSbO9wnp41SKAwXWq8YWsugzK3Ld/qBzSgBj2rI\n61eW\r\n=cO1x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCjS31tFfMsZ40DrDq1Gidwaz/5e1r/MJVqZGH+5QcuOAIhAIRyVdctVbsVyMgrC8vDdrF3mI5/NL/SSs8OJInUhUuN"}]},"engines":{"node":">=6.0.0"}},"9.4.10":{"name":"autoprefixer","version":"9.4.10","dependencies":{"browserslist":"^4.4.2","caniuse-lite":"^1.0.30000940","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-XR8XZ09tUrrSzgSlys4+hy5r2/z4Jp7Ag3pHm31U4g/CTccYPOVe19AkaJ4ey/vRd1sfj+5TtuD6I0PXtutjvQ==","shasum":"e1be61fc728bacac8f4252ed242711ec0dcc6a7b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.4.10.tgz","fileCount":76,"unpackedSize":327422,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcfdJ/CRA9TVsSAnZWagAAPfMP+wZ4L3W0alhYGdLGIsj+\nDr2pV4YIqMWaDSMRHOa/4NxZh1WSGwlrCNnAH7RxNeYnrjqS5IY9DcNYD5ZF\n0GN8kTDrH9XUjFWihvUM1XMKwa+N4aBiud5w95RHg82JYLMEd3rrD4x4N5iQ\nsX28RTxuR4Z4CsvD/z4VGKVjem2C1an7ia+uhjWPIfK5LX3yNWLvRaIao+51\ngigTp9HcBJ4+DEIb+p6BQke81MtRB0lxWY4S3Be1gNZ7IkHZXjkAqsdFzHyd\nkcpZzLAvk/2B+FiuaNKMEARRAr/3XNvs8ueLni4Eqdea4rT35ZMtlSQuXSKl\nmk/kvF0A66UojnwXAbJeKOwsHYXgXJcsXVNu/cWKU4F+NnCbefgOO6IbJgjT\nvxcctNd08TtLcgy3owAhb34qul0hFo5TqIWSA9/+zOMhhXf7skgr3qyiVIkU\nf0Kx/n4LVgGevGyS6oxKMwohXWFutVUUn2/bxozUUJ4GYLCs7AUS1YJA4Hdp\n7BFWhjcmh5CngRcDdO6wsKk9Ul3UPIeW/v+xTlTEWtUwsXAoGZGTyINduCqJ\n+7114x5nrrGj9DDyqUZoO6qPD+0TCc/Ep1UOtuFoPk9Bge44Lppbmaq1Vji5\ndjptbyrGHih+efWaC5nmwKm5b990rjOq0Dc1xa27jOHlwnuusoRoYsaMfK/x\ndUJL\r\n=Kg5i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFQfNJg2o41PhYkIqGzmJQpa+IY6/Xdj1GXs1kLyI6bVAiEA+vV7QlSlUoeHcxaOxtHspuEtKkk4fxGVud0xQKkoGUQ="}]},"engines":{"node":">=6.0.0"}},"9.5.0":{"name":"autoprefixer","version":"9.5.0","dependencies":{"browserslist":"^4.4.2","caniuse-lite":"^1.0.30000947","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-hMKcyHsZn5+qL6AUeP3c8OyuteZ4VaUlg+fWbyl8z7PqsKHF/Bf8/px3K6AT8aMzDkBo8Bc11245MM+itDBOxQ==","shasum":"7e51d0355c11596e6cf9a0afc9a44e86d1596c70","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.5.0.tgz","fileCount":77,"unpackedSize":330831,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcipwCCRA9TVsSAnZWagAAKxMP/3NOARZYb2ZHXrMoMJbM\nHZaCIdRok9oYYTnshGE9C77J9KjV+SkOZpW154wthNaDGngOnZIxWuTujSTl\nlHEikDR9VZrO1YE3pxJgfDg67nFBbBVvcVmxC3t9fDVV7hCy3N77qHlsSPuV\nQdppvUKsnajHpE0umDDhxU+khndtrLgl+1H60dVj26b5A5y4J6x+hEHcMiaS\nGqodzAiKevdKPD8VaoXDvQsiK2CVDh/eoQewBOPft/uk5+WrxAqkh4WHYcG2\n72Rnu6UR0YacQHPdmPB0/2EDCaINm3dgLehnuMCXkquyi1wNQn1bbl9YnrDv\nNeMjztCbcXYtOqV6JumOdwEZaiY+p6BugY5jqSq2o6j0+sV2OsH15vATB2eb\nKnFzwgECVOtdpZYp7l5fwLKJmGj5LiyMzdcynDvLOfTN3riJqJ6hqQ5XrWGL\nIf0PXG+rYpUcd4Ia/XVmpv57pS4sf/vs/HKeQ+EWciZ0OURtELjoEazE1oNI\n9ggSn2VPOL0pwFTdDJShsgxG5JDyQykMfMwbqdla99KGm4H3wDrrsQyZRRcB\n3etlHbkoZk1+yE9WwCV4xAnY1vDUNAsx79VNYqhaGtrGIBdmd1ijFyr3av+C\nz0RR1ui5yPCdwITx9BU9v3Lbrdma94yWDzdbM+s2ezSWZCSqw6N4UlKpKWjm\n0R27\r\n=E9u1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID1iHCJof/I6IXDrN6lyA5H+heEKo/4lFySbgAag/67HAiEA3CsbwjE9lhGVpuvg7Di2x3sDzUfSVjyzLDCMMPNUN5o="}]},"engines":{"node":">=6.0.0"}},"9.5.1":{"name":"autoprefixer","version":"9.5.1","dependencies":{"browserslist":"^4.5.4","caniuse-lite":"^1.0.30000957","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.14","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==","shasum":"243b1267b67e7e947f28919d786b50d3bb0fb357","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.5.1.tgz","fileCount":78,"unpackedSize":332685,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcqigFCRA9TVsSAnZWagAACQkP/iLagVt0lazP1bYl6umi\nxmXQt+4O5OZ7+OUC4KatJJ8ryQRBBBar4DtVgVVrEmqki6pyv7WaSSaTM1aC\nSH/FnBJhqQNdT0M4Qi58NaP8C7k9nA3rAA7ZfQ/TXebf8TrFaaee7lGRscCW\ncc0rkHKNN1PLxBLXpnDyTQbwE7MmSz0fLOS+o+2i33jlix9ZH8nR69C6BJOH\nOyGIevsJKIHSaWaddyBSfg0QaK0DDenBD/EeNuv+kYUTTn798CPel6OD7N3e\nxP7NGI5Ofj/9qUgDi1ns7ZKGNF4RJXqJL9f0ndxoMD7lflFT1MLFI3Hc+JFH\nbwCMyAB7U7/6GZc/4Mw/A3e6tbUBzhPedEzHKkHy4ee6bUIcsXaLMZ+eQ1iy\n5JgnrGSh2vUE+hs837Wpjv2bNz5RpAvLcuErJoxsVZLfuDocab0hM4axaaN+\nNJkvXuzQrEe2oPv8XJkc+RLD6xH8Ze9ZjZxmeozMW0HjEHE3/opId8qvHYkD\nBIxngsJZMQVFHrFDXdEWwH52ny4mu9drvdB3GcsTZC9gSV+xqdqQCjku8Zyr\nL5lgucq8nwqJ39rErxMOrPAC5cADFHD3W4JTaPimSwTkXYMzFdAgjhWVuPeL\nUF3W8YO6Bkg3+6pvOjYTCfATrRbk5oLiaGakggGu0EEw0vkQBNctknuGa16m\n66V3\r\n=DMti\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvh7Kn2Z0rqpXJpJg/A8pb08K6yJBXS19vpaq+iAx8xwIgWqbWOa47iwF2x/KqMvaTs0z8R3+1TozMo3+TMV++2I8="}]},"engines":{"node":">=6.0.0"}},"9.6.0":{"name":"autoprefixer","version":"9.6.0","dependencies":{"browserslist":"^4.6.1","caniuse-lite":"^1.0.30000971","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.16","postcss-value-parser":"^3.3.1"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-kuip9YilBqhirhHEGHaBTZKXL//xxGnzvsD0FtBQa6z+A69qZD6s/BAX9VzDF1i9VKDquTJDQaPLSEhOnL6FvQ==","shasum":"0111c6bde2ad20c6f17995a33fad7cf6854b4c87","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.0.tgz","fileCount":78,"unpackedSize":332949,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9WnSCRA9TVsSAnZWagAAsz0P/3lTFXkDRPDd1PqIEnJX\naPEyzCbOZ0MmeGeyLPFn9YgA1rELnxMLIuF+lS3XJTh03fzxt89bzD+3B3dd\nidbV2lGQ+plxbFyQeIjlprv8k3v8sIEpnhpTIYELPGBDwfPgaFr1YBG2XF7c\nslmzSst5BkL0eR0sHXH/kNyH4ejJ/jlPs/43xUy1Rnq9qciEHg3gJ6w1Qxz3\nUJl5RxEqxTOCdO2REG9l8hI5XUnyP1Gf72yYE5qSfZi6EEluuY9YS/ZaVYc6\n/K9XbsdN4JuDH+XG0xmhv8i0aYiuktO7dnCNiKGdpqZSXxZJURPsrnlE2R/Q\nXHh2Nnvm9gqifpFiiqq6SylOS1T1KTNpw4TrVLQLixHv2GnMaeiDbSSKG7up\nwGviKunSrdvh6KBz1Jdi8BKuasvuBtovyLt4BACtqioZx4T9G2kgi/3VjzEM\ns6fUqbdSBMvFJvzN0T8X1dDNxlkU+KVVTc0+RqQZP0e3wVlHvQEzns+m8m4w\nPOOVvW2KdnNis7bmrlaSar3YJk7/rEvsXEHTCJ/ov95AXeoFeR0ZgHnHFzW0\nCCHs13mxk6ZsYh8aFZvTk+EMfBpiB54KttxqBGbujZUKrQZQ0F/oYQYYGJb9\nsTFkB8q0htYpXvEZkoN7qQxUJ3RyW8nymOFFKz4aRcqgtNEUuqrpiu5RucdV\nYYEK\r\n=st6/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFdQ83Mqan2XlZy/hBbsZGp5uCClghrfYXrv3f6VI2jLAiBZceLkQJP1IxUL+j5lEY7+iGfbPnPLOp/Kt89xr5Zz6A=="}]},"engines":{"node":">=6.0.0"}},"9.6.1":{"name":"autoprefixer","version":"9.6.1","dependencies":{"browserslist":"^4.6.3","caniuse-lite":"^1.0.30000980","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.17","postcss-value-parser":"^4.0.0"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==","shasum":"51967a02d2d2300bb01866c1611ec8348d355a47","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.1.tgz","fileCount":78,"unpackedSize":333289,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdH8AXCRA9TVsSAnZWagAAwc8P/joBf+MGGcWsn/pgGquJ\nma/zkPcml9RDVp89K0Pn7tEixsQuwn2shLDTEvOxIjb6SsBhSGzVXxVxfhRl\nd2wnzWIuibMCE95bUkjwxD2YRx1JZtAWUyfBSsaF4KLx561rRVTRSfub3D6p\nK/R3xAZKBLGL+0DOXF5yfijTyu0/fneKRtGCnnEwCs1euOG6+pBWE8WIsuC3\nHHUN+2ftj+rBHwB0DnBJc4UhHf/Ww/ueJ+urXOHUlnxAVmWX6wFyJvGZtrix\nYXg1T0DWWzdjEpBFnajbZSfvlG4MqTj/s4yI8wV3OfWrubIQ71Q0liVmkSu6\nrptU5GnWgf9JWgk/LTy8s/6cwGkGLPzvvnEmF0RKHpeF88GHd5MVy6s75HSu\nMvoOb+vuvSh+hVwuahsitU7xPOx/0AYeoYg9GZkyFFz+u3sHMKZdbJJOB5EE\n2eBHnlncym4lauo9lHqtojMezgtkg/39h0zOSPIusiUNc5hbEvIkooRbznLV\nD8CAP6ZnwRO2EPSMVv5gnxkKbAf7A3T9lqiqZuEUAZXXikMrLIKb3knvZOTW\n1sQ+Osa1Ufl1AospdSUu5y+KPAVbHkFsN1JYyNkwdRlJdsKmB6eoLEEu8V3b\njguKVZ/7sjA7tvXQIgF4couribbCPNjsSIMhvAUnfZFCdYcnwLqYFZ5C8aPM\nhpvs\r\n=4PJ2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHiZ3zCkQlvfycSikq36yUmCPRqpXRCwXN46IKrZeZSMAiEA2Kxta4lT5pn0GO1gwYGVgpTF0RAIa95Q1gVZ0isX09E="}]},"engines":{"node":">=6.0.0"}},"9.6.2":{"name":"autoprefixer","version":"9.6.2","dependencies":{"browserslist":"^4.7.0","caniuse-lite":"^1.0.30000998","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.18","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-0hXVBruiJrTMJprJYwdWuIg87R8MJ/Yfrt85XgOgRwyC0mpBIyDdGZhSf+AEh6lAA+R/70Y+89G6YSXsCnnrEw==","shasum":"30ef0c9f090f2681880f76e335c30bbed29ff22d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.2.tgz","fileCount":78,"unpackedSize":333868,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmCvuCRA9TVsSAnZWagAAY/4P+wSb2JfeRrok2CnhqAUD\nY5nYSUWAxjZzmUh7awFPgEqELMOAPtShnE7gtSR0KzUtjzm4MAkxbsiiWyMY\nFnNCwFsVT8MjtK0DfLnP5kFSFYjuwlFEJTVG7ITWeEqoJLHSVSCEp8XSAfH3\n3fYbeeyD8/zUMsIyZXlKf9RyucUm7dwqNFnjl8Xo2x/449PQAHGV7iHsoZie\nIbS6lR6mWziBmT/GWiz6yuF1WDVxyQDaQnUevfmrhE/4rIfPcS4PVM40+UUU\n/qW9v07H+pWVaVrWVH9YI6XENRbgzF4TRo74iGc4gk3bleJhrQPs+wyDRCf+\npuIy7Bn5yK2FToIeZaWaMYGUYe8GasrMWMQeJGGnTU4sZg0XQlxykg2ZbJdw\noZoYxXYijukb3c4QRqecfbccBaUC0ExUywFlU3DbDMdJsJPMYquivYlhVi6+\ntTmqP3HM6/A6Vlr5gwFwTQ9zK+koju+dZPj1Hdg4D3qOT83JKbsOadHqf+VB\n9KJpxLmulv8lEIE9NFp1KkWxoQTkHsHEXfx/EQesnyjL+HnhQC5uhK35CHoE\nKXDrM5XXh4zAigBBpvDBq1mvrmOlzyIQfM8mmq+XyhFqbexgwJIRac9NbDbk\nF9zj75LQI4h9pmWtvHHcVIQDIB6MJFC+cRIUjInOjYFD6CGGHLLX57/3fWcD\nuMFQ\r\n=zttU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG9yKcajInF3aEFrAgrjObRrQPBrM5gP9sEwXgJnLUSjAiAspinkPxzxP+NcccwZrGHjUEU+jD2xmPPJ6/cLTrEAfA=="}]},"engines":{"node":">=6.0.0"}},"9.6.3":{"name":"autoprefixer","version":"9.6.3","dependencies":{"browserslist":"^4.7.0","caniuse-lite":"^1.0.30000998","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.18","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-Mtaw6y+DKDo1LvtAIoggxV79HR2/do0DEuBzXcpTZ5VzRykgXddsHQ1ZEPP1ydMubKvmmxBO0XiX53S0EJl3ag==","shasum":"1718d89a5644a61735163fe02d0e6a2ae2c91a6e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.3.tgz","fileCount":78,"unpackedSize":333972,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmMW1CRA9TVsSAnZWagAAEJQP/21Rp9Pl3uxhC6Y0Ae//\nMK+hT89k6SDnyHBiB9bqtZFFc9/j+Y0VZAcPhjWJpu3rqoPdnqGtt9UGQAl4\nXLfKnIz03TypedCcTleZEcyhansaCc/dZmK/uDCkhCUPFRQNbzBnUf34Ah4y\nZHe0KI/XWmvmMp6FIhCQ0c30wbba7HjKSRBbgTUvheUrWV4eFTDC1jzyRYqL\nM2Y2m83ZlSaijNUb7QzhXvHBZoOk9kTqnXqP3VZsQkWHtSTJnBVxkZKJlGOu\nXV1GKHIrT1PuMtblv8IcQxQCfrIwJ8KNWlmvsrKKbS2v0ae6R2ncabgs4AT3\n+UWCmRgc+LMFc3Yoi/kbilajCtsoTKW40PNjOpQ8kANkGWjfPmWBy4IV0IUF\nIlM91UYwQYJ1f+/6r2SsKl1sdJbujK+yEyjWF+byzYhV/5jgIvwqIH9SJaTp\nqjNA0R6TThsM8L9P5IHn86hR8K/WYOzX8HLDQp10s+2k5vHv0OerXFQ3AtzC\nO8DoWyvzLgSYNMHySJX9uN4eCY3O1BYFoFriqsVxPsIziHJR/o6tNiDoXORi\n+smhgi8ySACPsXz6pn2e52UWO194kC0fSrOJZqdP76hm0QW8be4aPdDYYaos\nBhQU1Qc3atHqQ/hW8y1ac+1SSwUgejX7RNjD7x8xznLWPrZOKuDfkz34aUWb\nsfRh\r\n=bSny\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBp156QgrrMY3JB65jcvMJ8IElJYWWWRn4bKM09fIgyFAiEA+UCgAUzVoMOsND/HRJDJoRCZrKHI+lz7QwKorsxLip0="}]},"engines":{"node":">=6.0.0"}},"9.6.4":{"name":"autoprefixer","version":"9.6.4","dependencies":{"browserslist":"^4.7.0","caniuse-lite":"^1.0.30000998","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.18","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-Koz2cJU9dKOxG8P1f8uVaBntOv9lP4yz9ffWvWaicv9gHBPhpQB22nGijwd8gqW9CNT+UdkbQOQNLVI8jN1ZfQ==","shasum":"e6453be47af316b2923eaeaed87860f52ad4b7eb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.4.tgz","fileCount":78,"unpackedSize":334038,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmMuBCRA9TVsSAnZWagAAjX4P/2W552UNgMEzZLzVmfPU\nqw//u8VEdAu2E3xRHnSWHdOSrLoSR2bhirmzlUm7mfskhwiB8xsdw1Km/nXs\nN0QrdSLJ877sOD3HEyGNl/tKBDssZSB+GO6zsvvVEuRZwbYVdfDcSHe44lc0\n/E0ipIbNCM/pi2RVMcjzn/Xt80zSScF4rjW80C14X9YQTtF7k2r5sz4L7km2\n1kGlXsZrVu5WuikGsLp8jtojFJkx/lYngYqLsXmehrjGhwDPsWLpr8CPX9jg\n6B1+vcUYsqLw1TV29IviN8G9fuuY3Uee3GDLp+fegYGS132TPN4I0RrwoSV9\nN4ztRxvKvdboXAxMeqWzHk9cUFxpu+/167KQ+4PTFgtp3l+65Rg6agHRtdQu\nmRYUSwHu6flZYx4SsBYY551/p9pBPbDovFV8WcjZabUybKB98be3KgI6zHkA\nTBn1wm+p+mdXrnoAQB0stukrj4gkGXjDhl3qH5soALPrUjn1ZVHak/8atsuB\n1nvXsIflr95eZ5TomJ22WklEAiItGnP7hEMRS3p+1Jcf4halMdl7JyKZYhrV\nTMTsTZTh/ySRHFzdUjt9dCW9HqnvASAh+/qV2BrFcJhFVk6hMntUH9teAgQQ\nr74neIXUIMi/5n+FYnrXSL+XjTqZbNiDzKbpjAct2BqhfsaKBg6OZ1572qR7\nydJd\r\n=ex85\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICdqqvWNbFTt9RqA2TNUPLtfSFnD1Z62pJV/+2HlurDaAiB53AjDcV+RZzWrHqOTn8hypLGkKCkPR3H4mQKAQl3dCg=="}]},"engines":{"node":">=6.0.0"}},"9.6.5":{"name":"autoprefixer","version":"9.6.5","dependencies":{"browserslist":"^4.7.0","caniuse-lite":"^1.0.30000999","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.18","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-rGd50YV8LgwFQ2WQp4XzOTG69u1qQsXn0amww7tjqV5jJuNazgFKYEVItEBngyyvVITKOg20zr2V+9VsrXJQ2g==","shasum":"98f4afe7e93cccf323287515d426019619775e5e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.6.5.tgz","fileCount":78,"unpackedSize":335293,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdpCqMCRA9TVsSAnZWagAAyOMQAI3NQS1TdOkJG+F2DYzK\nWHVDuCu46RzJv9c+gtqR++JNkZziTO2/hZqdq20cR3ZHzHQ21tjxT+yoeG8+\nrpo9aWzryFqeQrNQmHr7QItpwSmpe31xqd/YVE16te+qjv57669vHDrmhL6R\nH0DEKyRVHmLcVuhkoFWYTBiYL6Pmf42phdvFXe4BqmYj5T3VEJ8mcti/sLiH\n6cfNft8Ujul2V1gOYGyFmZUqqam6fxQ2IkjlDEXyc/YCvYTYdHMrDdUMNwCC\nVR6Gl0dX4gzqj7Zn/l+xWnmGdFPgN6a+C3G+50sBEo45mBGQltIAxMVi+hw4\nm7aboFZcka6YoMf+68iuxFlbrJH59bMNybQtayPsl5mGDUZdGdRrOf5ZBe/S\nydnDo29MKjqJ15/NEbnXgPx06BKB2ROo43sMFp7BE8FE//z0d+xw4dSltNd7\n06In1TPoH4c+LWcR3hi3aBsTT8Mx61xVSs+DwSeoQmdMmE4FK/OZbfD1AHII\nB8fT3PRmCnDwCgshWd9blfMhhD1vTW9bG5RnlqFTTtk3Hy/ZgQ9KnYiFqcGv\nKsZrgUL1NBr5gygzBwW4eM+65EQ41dzZ122dzedwlzklNJksUtp889O5M14c\nbJfOS6UK9AhfLF0S1tu1DO+P6RcbgNb5oB04v+G/5j3S37N9KHAP57M8C/J0\nbdIR\r\n=w6+F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTHjARpAZ4h1gDZMjTh0npAQR/cU/YZTimGjvctzTNXgIhAM8u4pz5pxtwCY8iXPhX5nPJYEf+T6MNy9mGHaQTd0iO"}]},"engines":{"node":">=6.0.0"}},"9.7.0":{"name":"autoprefixer","version":"9.7.0","dependencies":{"browserslist":"^4.7.2","caniuse-lite":"^1.0.30001004","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.19","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-j2IRvaCfrUxIiZun9ba4mhJ2omhw4OY88/yVzLO+lHhGBumAAK72PgM6gkbSN8iregPOn1ZlxGkmZh2CQ7X4AQ==","shasum":"905ec19e50f04545fe9ff131182cc9ab25246901","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.0.tgz","fileCount":78,"unpackedSize":336512,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsZ8tCRA9TVsSAnZWagAA39kQAJc8ZXVlkriLATyig07F\nviOFDhEFUNPZ7ZISgbPN8sgMjasUoTi1Yqce4B8sdy3tR51BR8HH5JgLeKbO\n4mdOB7hBPgWxfU4fFxFK1gOTuDme071rBV06USczc1w8jz5k8zRb6nmVHQkH\nbiC0zqb2Ag8wOFECsW3pc+Qi3M39D7YnCsCJlyLMLZFflR9aGYA8Q2RYJM8D\nXrDp8o6HSxlIkDp4Y9+VlNF4pyLpuiHDrXllIXYP4C6X/9WF5Zv+vWe33NM/\nPbuZgNYhkoOo6fBSMMqpyCXLKKny033d8HXuurmoyizpKtONNGT/eETn1QuC\nlviU5Ohfvv5u/DuJOqvUEG0bASRi3oJ9/F88kOWsQ8CuxmNt6LHXzcE5LBAW\nLDzuCaF7iYayMdMj58HP70y88pUF2lM4Dk2wTsdB1RPNwJ8Pjnpx2slRY8+j\nv7lRHG5sYsszSAgyLlB5UdVLw5m3NtHl+lkHC5pe17lMETj8h27qTylVQZbI\n4R5wZpNqWsbR/IbxDIajCdhMwJtDPPqRJncFLQTeHxMY9dNh3okT7LP63BA0\nJp/Y4DVNvflnp7BInq1CGmrzYiLXvEnCciVbKjOez/bFcFLOH32aY/0aM/I3\nCL32u1ONuib9z7E+5nf321LCQqQ1qtxU+BBkO2/09MQa1cd/nx+SSNV0I9tg\n2LEI\r\n=lrvI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEhsdBxGix+iYzH9nmLehnQdI7sOuLY6ip9J6mRhxduFAiBfzEzWHtpu7CYiIuLu3SWd2y2PrPd2LD9CMcElGWsOOQ=="}]},"engines":{"node":">=6.0.0"}},"9.7.1":{"name":"autoprefixer","version":"9.7.1","dependencies":{"browserslist":"^4.7.2","caniuse-lite":"^1.0.30001006","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.21","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-w3b5y1PXWlhYulevrTJ0lizkQ5CyqfeU6BIRDbuhsMupstHQOeb1Ur80tcB1zxSu7AwyY/qCQ7Vvqklh31ZBFw==","shasum":"9ffc44c55f5ca89253d9bb7186cefb01ef57747f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.1.tgz","fileCount":78,"unpackedSize":337286,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdu4SACRA9TVsSAnZWagAAVlcQAIkbNqhKa3Ubf+LfUUN5\nJTCJbtf8gDESwd+g3lFCudJdH+t9Een8iloCxXmLpK1qzhvYfHVghjn9n86P\ns3J9zjlYd89N6z6zXeOzXC0BAsZI7VX3cRz8AVufeY+s9dMzJ0xnQtjaIIjo\n1Z47vPgFYK042/gP8MuTi9pE4QRGBkT/EtHlHzVQx1JiPStQ1qh1U3HGmrSC\nnxOjSN0ksT1mNWfsNRCBE1rUDtnkGDESipSp3fiJRwOmhyDwoJMKOmyJGHP7\nH/T57ctJMhMTue44R3ILo3Qqhmy+GI+KNDq3Vc6lRPOg44Ap5nYgaL2ylM+P\nIbUWV/LSae9haWZnyO1hHeTNOpmYc1mPxI1tqL23f+zDRThEsVcIgenprHqB\nlZi9QM3mIaL3phSISEd3EnnO+r4u9aVuP5lcxhWz7eK2+Jr0wAudyPGfuWaa\nIEuKVgf7veOOaV/e5hWnTC6ZBieMxHpqfGTzdOw0E9ubqPAyx3UdEDiHL0aC\nl7Gm7fOSLw6WAv0K7uJjci9BDybAeFPspCGrKopvaIyCePQcYYpWJU1YHb4y\n29XM6llDPj7QIlS5gxumKiNIRS3zbBK4jBlpDBowCouAz9au7QQTmDwtMu57\nDldW/xVA+lY8E+3d1JfxbC9MysLKrN+ggLmYJ5Z4Sr6bWI2HCg2EnVFoDdaP\nqlS3\r\n=jJM+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICEe1cBp1lSg+zDwB8RVFfcgwTv88cxb8yilsG/HxAKDAiBfRVCVhdCu+RbEP59aonD4Pqm/8i3r6wjYljGM1b88Yw=="}]},"engines":{"node":">=6.0.0"}},"9.7.2":{"name":"autoprefixer","version":"9.7.2","dependencies":{"browserslist":"^4.7.3","caniuse-lite":"^1.0.30001010","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.23","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-LCAfcdej1182uVvPOZnytbq61AhnOZ/4JelDaJGDeNwewyU1AMaNthcHsyz1NRjTmd2FkurMckLWfkHg3Z//KA==","shasum":"26cf729fbb709323b40171a874304884dcceffed","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.2.tgz","fileCount":79,"unpackedSize":340395,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd0ykSCRA9TVsSAnZWagAAlvgP/10+y422snnw1pqd+Wwu\nD2BwSAQ2R0/SmnAh2zaFV+jhwLVmEdUi6wZKHnAJ//ovXfMGAxH33KbXoDg6\nTJxY05PKfL0Z13BwZq1HoLbMfNqVknqWCKaZ46UX2eX/g9Nz0i6OAY/9E20Q\n6XZ4devVZm882HCqhXXNmFCIa/sy0qb8Z6WHdSdZ6HEYCEt25yTvr6s9CAtb\n0Jk03ymjMFLbWaiUuHsUXp5bT3PtOYLDDPveMqTm5VaUNcSn4OMc7zAtF2aD\nL7dV5GP+HGerCd1VenZIVn6R4/gV8Sj6N4BYroJoJFe4bCXy7uV+rRB5JdKD\nG6IU0WalshxozRbNLzqCPnikQynnbI/cb5VgggFY9awxr5L2Xf2bBe2j+rnc\nm5iLXvUKEK1jY+ljlb6qBNyb0nfkqCPqrVuS9wmrZfV4K8d7LM2JAAohxt/a\nCwaXKpc3wyJ/Z/p1Tq+u9eaImfgL/mq2PmVMp7oa4e+dQo2FU5fqjaUwMQ9V\n/B2PSgiTQKRDtit42Eh+3ubJdBYzRb7PF/2NLQOrcIwljHOTYw3XDSzzZsAR\n6atFBYXoFJZBF0n9xYvIxjHHmSqqyMZEPudQ7iPXhkRazlHrmBxA4XW0lqA+\nhJa+hAebV2NmlnN3/eZX2luNhJ2xMmSCoD04VJ+drp8QzcmT0iAlxEcEdBd5\n2nBX\r\n=b/jQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAuuCBP3M1M93QjYdA5/BueOIYDSPazXn2zom3+TtjiyAiB8U6RjcZK+xotT9SkvT44lNW2S20TqDdUvu3YssCZXJw=="}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.7.3":{"name":"autoprefixer","version":"9.7.3","dependencies":{"browserslist":"^4.8.0","caniuse-lite":"^1.0.30001012","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.23","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"./bin/autoprefixer"},"dist":{"integrity":"sha512-8T5Y1C5Iyj6PgkPSFd0ODvK9DIleuPKUPYniNxybS47g2k2wFgLZ46lGQHlBuGKIAEV8fbCDfKCCRS1tvOgc3Q==","shasum":"fd42ed03f53de9beb4ca0d61fb4f7268a9bb50b4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.3.tgz","fileCount":79,"unpackedSize":340531,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd4oadCRA9TVsSAnZWagAA1hoQAI8da6jy04JH/ShNKEio\nL4LaGa66IUBnjws7nL8m0aqUW0eehSzPv8ZCf9muinhK8hZ0ZmvWeR3Ubxs9\ngkbZ2k5GnsjJ+R8WCsI3OSEVsxvu1VzpoHCeGijm1MJ9JiW8BCdXgVSVX2UL\ndLuTOYyAb4PO+DdaXkTjxut82jzvuuQ6otSQTzSvtKEmzstXbBAD7YX/HHQ0\nE4Kp92eL5o1trv1su3OrEPwvIo0HNzWZXX0syTC5QGgkS8X/1nNomZqxRJe2\njvqmtSXSCjfd6+3m6c6oRDuZWCZJQR6c+/hqoGoVcdUDttD5m0YTXmd/0ZsR\npIMU2e5EWbA9Jyxus278y8KErvW4JeTGS90FMrlHzMSNPRG/SvaGVOiUW4Aq\nzgwxtLRnbOTGbxZCV3tVPXjWVaKrJY7xLRbn7FKuW1x70lBqKtnmEEVZCsWW\ns3lzlA59c5BmLkHvxZA5RI3dhwugXfotsZ85MMwo/OcMpaeIyqQrtQ/54I8Y\n758UJomYEjyZiXMvy1xthDJCvbt4QXKJl41BWHAszdNaMDH1Ncr2/IWTvG9S\nnEmR5dJbEx/E9EE2QGSU+OzJhyVBGluuS/lBcU3dz14WyCu3LVnu9zzIZZPG\nNZb/DevFZVE2+vq/3Yn6GOYiFT7ugpu3xQ5JKnSBhb8ozEC+4+SfDTPscT0Z\nyjNA\r\n=dgQv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICiW3uu+ul6JBmXFvSHqwLOZTmMhObTo3Do3g695ORuCAiBwE//CANJKlt6V5zHOMn5GgCScjtkMI5pQ0/GAbZ1Gtg=="}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.7.4":{"name":"autoprefixer","version":"9.7.4","dependencies":{"browserslist":"^4.8.3","caniuse-lite":"^1.0.30001020","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.26","postcss-value-parser":"^4.0.2"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==","shasum":"f8bf3e06707d047f0641d87aee8cfb174b2a5378","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.4.tgz","fileCount":79,"unpackedSize":340554,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeHidYCRA9TVsSAnZWagAAxjcP/2kjt45wRDrttRcSjpcr\n/gFGntTT0hANcma40BojwtpKocXLQCARNFohmTM9CFnUCs3hbkpj0Ak4FkfJ\nSdll0ou4onWesMiP9KY75K0DGVkAlwEizGTaOY5FUCoXfqfFGVGl7GjJ/cH6\nh4cY6lht5EXE0VZvzo8Abburte8qNWf6z5EcDQI771UGP0m5EA2HNp73yqn5\n58I7e9kUd/eTJYvrmycvvKySxOWBG4CuJeFNlX+gg0f8zhMdJmRifl41b1LG\nsBpCCYNd5cnS4AUKCW7JkJoYxo7cLexuJUDRhPVDcxQo8zvs8H/NJtsdNhBp\nz0ZTx74MsBW/LD33OYJ5hnEBYF6CNb1S+feZkM6QUBAxT4K/XJ/PItMBaLW1\nV40lz8bJMV0fyaHREYmT8FtuR1T2pjdHStCCV9gZswVVYO86pARVAZA6Qkay\nioT7xKYVseEozGRmMuObfYVKHYrZsFurL+u2RKSGVCsgHDiIEdiOwAva+LkR\nftpIxQM5rV74IOp4e3ZtssznSdZcEwbhAVVRh/sKB8cFF5JDoCw3+9LGa7go\nNEshgnzVqGoeIAPbzmFr5PpBS5AXvBXT0ev+hDLQzV/OKkc/YaxJV/n+baND\nMZhJwEvMA4LslZU6FQgJOr1Btmv45y4Khw7lQtz2r6mHnj+fGR4UWnhjs9Rf\nTHw1\r\n=Q4yS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+gvTz0T5+sFxV5RleWJ+rOyRhbrQVbOLHaZOU/+B7MQIhAJF5xMMma8RGNkQMPLHPArg1KXhmN5wU75lMZUowoC1N"}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.7.5":{"name":"autoprefixer","version":"9.7.5","dependencies":{"browserslist":"^4.11.0","caniuse-lite":"^1.0.30001036","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.27","postcss-value-parser":"^4.0.3"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-URo6Zvt7VYifomeAfJlMFnYDhow1rk2bufwkbamPEAtQFcL11moLk4PnR7n9vlu7M+BkXAZkHFA0mIcY7tjQFg==","shasum":"8df10b9ff9b5814a8d411a5cfbab9c793c392376","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.5.tgz","fileCount":79,"unpackedSize":418720,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeVTfCRA9TVsSAnZWagAAAQcP/0NsWOGzlS/XPOc55lyJ\nfmiU1rGUp3isaO3ZJI0tUJG+y2u6kKKdH/vhpCMT9w1aTne7UaIf33sqBqAC\ndD/GBdnORh2u5r2mOSTcLy5Q33XHYbmEl8t+w/nYG6ihaijvytb88kPDctMw\nc/zfxWCiA7W7kOowZYziY9RX/fu2VblbadOGsC0RALOXMKNvXM3WiUgPjuFz\nivu3HUiEdDgCv1JoFpgP1PHw9fgqO7606csnnR5E8ZDh6Hy2WeFlFYF4S6Dr\nuUSoEBu18sTodpAT5hBDayIi40AoH+D9ajs0CnGBK5oiSxe4yxLLRpH3xIKg\nHcSRu53J9oZFKj9eR3vEyU5x7fTMjufKd9Rg3UZFfpBZQavtfBPKL1Xp6d+k\nViWW5MuQBb1vpStD4WYQ+j++J6FCAPlIrepi7soEOkxIoW+XQzy/ocZ8HQdZ\n0Z6rPg5XYa+nXS2HVZXxn8qjZEbEyzKKbql22GOhMDo+8ojJfgZxk5OsG58E\nm/zXUetUeDhqx2NSXLH46jn/i9HmNT2klgKnZA9JpJ4FWq5jGEbGqYxP1Y6+\nt5VxnTjQEg93uJPVNLEcjA52fKFfuR2t2YfJuEzY5GAsbu+A8JpTvTNcYB74\nBzCjOahJsCLuPw+kRmenu1fUs35la5PLmU+VCJ4kI2sNxMvXEF/IofBLQ8Ob\nXJuR\r\n=8JrS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDR6/eeOl2z1sWtLE0pfk/kOUwnyaFXBqX8xfi0F6sF3wIhAJ+uh9+RIWStYoCkJlg7OEvq8F4ePXCJwwPOD8vcdXB6"}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.7.6":{"name":"autoprefixer","version":"9.7.6","dependencies":{"browserslist":"^4.11.1","caniuse-lite":"^1.0.30001039","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.27","postcss-value-parser":"^4.0.3"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ==","shasum":"63ac5bbc0ce7934e6997207d5bb00d68fa8293a4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.7.6.tgz","fileCount":79,"unpackedSize":419340,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJei5xFCRA9TVsSAnZWagAAaRUP/jQSvU8NggTiFm8k7+Wi\nKm0PlDKjQL/rUurl3nXD7E8P5Q869BLJVYT4enXtFctByFV0w47UwyPWCTJP\niLIlhYqhLcyOeowQlEvPrqdSoBAdSoHOfJpoMgLIenBdMowyP0M47inOrkSe\nacZiOkeGNEIgbC7yEkS3O/WVAggz0eft0cTyjUJ1BeiAWu180JPf86GOv5VN\nQZ/UzrsCftVVgwJ8XeN0mIylCpDOQHuzVWsMW5WXhyc/6JRIZBkkUVpOhVpO\nfTwUhUfvIf8uinYDIIFHjAo7hJ5hlXkLQmDmTSpFu7pKYJGMnzCIYLbAR1M9\ntm6eMewWBmHF3Pjjef3LsSjy/uKsdDzv99EEu4LSkseTsNwVQjWtt1WZr4Nb\nsGutkiBVNUIz8hYazRCxEUDtngtpGKLQ1WodtbJRg/q+Vc9g0VX3Ae751of8\nLSA2Bea9ojqmwxRh8fwLbPWPlJEscWeELzgYdElVfCqoBninrZxopIZb94gK\n2y8Nnixja9D58yrY9e0wYHYGoLPvOOFYXcEGJkZ/7nc7V3opuAPmcj9wzHU8\nVAr+1WzYLEs711iJ4zauPJ50KFbfTP+HyU6CEBEGfVVUQzDtj4vCqLqHxo/x\nf4oLciuqXIRU2sunTdmYrJusRe0D4n3WJP22NBJv06wEAkj9e6EyMqWMsvyj\nNsqJ\r\n=69bP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2yLbJ6W02JwUHt94kaBYPZw7hY6bY3pgD3q1hV4BQegIgegltrVicj6XLrTaLbZWHaFmZhuohRZkKKNoBaLE3/zg="}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.0":{"name":"autoprefixer","version":"9.8.0","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001061","chalk":"^2.4.2","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.30","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==","shasum":"68e2d2bef7ba4c3a65436f662d0a56a741e56511","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.0.tgz","fileCount":80,"unpackedSize":347004,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewMXMCRA9TVsSAnZWagAAB20QAKKROUES32rvabuIrr/+\nNARQCkqsBloDbdlmY4E+sqPpKwYvXxhIRsyKmcd0f/fZORgPqY/vOzSXglOT\nEtrj+74b/YS1CJdduK/+RfbEUYQ0gE4NAPoV7iB0DIdEzKHxYdFLcxHao1lE\n9OhYeUlXbsfFb/De4998wFTF9n1noQc6hNO2l4Rpq5JFFFI+MLX/Mfb9LEPc\n0/0IiusIOLcIr6UMMy2J8Pm+vc8ui0pxYCS128Ltk9cNv7Hf/OWW5t4LRHzJ\nKQMgag6LnV7ohiAGSXHIts3wn/hynpOta4bnlshJ4UEAM5mug310x/aGMLrO\npA8+aPeheXUWG7fItsMFroWfafgx7X5MKdv/l6LItUza4Oh+qd5/VfJe676s\ndC/hLqzGfZFwKByFD9Ke/0oM4KfV/vTLGE/ofzlwJruB93eABk67AsY4PYF6\nNL5t0vZ9wY013U0RJGvdACoSSnwOjPkyA3fuF/ljjOHZljQn7vFL5IAryK7X\n9M1RMHESxXheJvQuHXSMlUPvrLA43kl6eiOXTXqrFFiExtVbe5gWN1UlAr3+\nwYqb5bZH/r9YX2FMnAnHw+F84CC6Whdk5SJw9Dz0qkt1sJEGxTCAZqpY/779\nCA30bRsiNMiGulit0ezWmxMJWYcxXg2YCZsXZ8kDreQb87kf4OFA938kaRbB\n49bN\r\n=Nwqu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCedHLxgkG3VZroXthHN0bcAdccpirvo+k3o/LwswV6ggIhAMt4HcpsSJ6IsFiff5YzoLkJcbeewqQnlVfQBhoROOMb"}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.1":{"name":"autoprefixer","version":"9.8.1","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001084","kleur":"^4.0.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-zDw9+mkCdWZHloBIGrOgMq1tTUed4qy6ZgNAe2Ze2xERZA7CyTgW5Bw3XZbwSeJe8lfDHZIkw8Hwd/6hI3p0NQ==","shasum":"09ebdf209ddeb6900b310c71219f367138950ddd","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.1.tgz","fileCount":80,"unpackedSize":348754,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe7S3WCRA9TVsSAnZWagAAI00P/RnWxNe/6+4XpiAz/GvN\n+kfbstthTAI1oIuWWB4lMlnIfSHCP9s12Zld2KSE2V8CWyydzi9gcr/Od0en\nwzU61JQklkxekVHJNvlRA5zFatJ4EUbWiHWsxlDxVOj+hgg2Kmfwk3w6Qwxn\nx9LWOiVIHnhAG56scrFJVLC8dX+S0/CKtJvsGnOfQpmpWviCNqEruvgCF08d\n3aS9iNPPWvnxeOSmodMkTX1EiEdbu5jdbKd0veo3eAcPALLa4MMk/C2wQFPR\nz5jUE9cdd2RwYqEDJtEvn4uFdemcjGhOcUzEfLrQfcFIp8mMGYSltSUB1cHR\nLpIOAw2sNL6lXJPoFvIjNK9iWn7A2+ivUUmXG/CRXWnjjjKk49K5R7EaxAvP\nAjrFO1a+VWR6audeFIjqU9Vi5YRSz2Ka344rlaM+gsWZcEAlqBFw8a9ZHDZo\n8X24a9JFNSzF44qQBfEGQTDICskmN/XKziNGcicdiaBKtz5lTVVdWCNZ44BN\n0BSnN7mzOgMDuGT5TGtd4RkrG2Z9uhNV7KjQXGgJ5AZ6dOpHhjmIVt4X6w71\nYkhUFh+ykxcuR5FjVHqCuBIK9Zkz5S7hJbBP/RMnenVwnuxsNHxG/uzqLKmE\nI6ZfsbnmwRIs3dgi5kYTWyCtCJLtcTdV6ubAT/6QOPrOQ6DvNa9N0ib4QAoT\nYVIh\r\n=8hif\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIyeIpKWgsF1HxV5uYrmc0t3AuCfpjaT/PssdIa97JiQIhAKiU+ZWUcg58z0BFsr/ca9amOE8tAlzLB7wzd4zn0FDY"}]},"engines":{"node":">=6.0.0"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.2":{"name":"autoprefixer","version":"9.8.2","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001084","kleur":"^4.0.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-9UwMMU8Rg7Fj0c55mbOpXrr/2WrRqoOwOlLNTyyYt+nhiyQdIBWipp5XWzt+Lge8r3DK5y+EHMc1OBf8VpZA6Q==","shasum":"7347396ee576b18687041bfbacd76d78e27baa56","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.2.tgz","fileCount":80,"unpackedSize":348870,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe7rcMCRA9TVsSAnZWagAArVMQAJxo5fC6mSAyeKiNYoIR\n1YoBZ7DOPuLJOG5AuICaVk+YWzNdyozLnjxzb6XH0D3O3Xydx1ZMpCyU9qQi\nEzaKMFxhulT3nR+G8B1BY+Dyg+qFg8zSuCSzEx9pc0ZAbQ1q+kpxIpNOWrde\nSQjPdjQQq6PrF3+xfmIBWvBcegFs5XqynTJibX0+q7IV1NhFBbS7LFRW2s2e\nW+J8QxArQdUv4x4QJhjJGbShFgLOMaCn/TXg7PFIb6c1bugHiPYOcz4EF6vJ\n9koIc3LggsdoS7aiSf1+kvIcqhE0n2lO4pCHvWjbLzMEuMovMx/oMuyl+tIt\nkW0harYGNlPEkukojLTXh1sQfra1UH6ap5IfEs+J9xAjCs9z9+TSVZMOStD7\n1kcdYeEIgI3PmkgYqog02cULSJM546ZbLCjmdSB3vDrJt/7/CcC+GepnVUxC\nego7ga4o/9inEVWcRGtqXTagKPE5u8A1zvShThKYFEBBCSxmXp+c3ny5Bjt0\nlsNTnpMU00QZRG28LjKxoJbXNivJucY94Drt8W3M38m64XK05Og4w0ycqjmW\nydArzdn847EYzXUCYLcod3O3OF6vHp+Zbu+Dxwt4gTAKF5POIvSlY+ZaYMx9\nnv7KhL/8nJyZwn9smyhp3RsfUQwvdqQAHMgMp1Hu4s8kjYuvWiAqwrdyDU0+\nYB8R\r\n=lSyh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEcON8ke/a/pbe5LD50z2DCa6zR687s6+BuXWT7JGIumAiEAi7kQpVa4+27YJ1Fimr35gFK5kN+hlRxrqUm1hQE39DA="}]},"engines":{"node":"^6 || ^8 || ^10 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.3":{"name":"autoprefixer","version":"9.8.3","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001087","kleur":"^4.0.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-Y3CkEPqPqGw0TNBcMoUAxeZT9WEOAh0BPYENOTrN/bEfNBqjlYWjHbR1PKduBrmAVn8WbEZtMA3gAZO5MgV7Pg==","shasum":"e04c8b7f72c608e4aef1b74a542946e2ed271753","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.3.tgz","fileCount":80,"unpackedSize":348964,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8hMSCRA9TVsSAnZWagAAOewP/Ap76UQUGn6CSHernzRg\nXQFRhXNrLx9Te6pYvJm6GTWj6zSfFNRSAU5baCEF9b4trCm2bPLZtydIkRNx\nl0VcY4auY5Z/vNAGVosiSM1uuHnpCeRC+FBJu9C/qZKK0bLyzlYRIbhX9SeM\nlp3hKo0UNktM7dWhA/rwAmMCO+9Q3Elul3FZjqN6bV/xhyJk/hc/GfNMDrF7\nXtbohgDmtiMmqChiEnFizcrAUDXPin7s9AEB2I4kERO2VzNWDCLxExjcNXl1\nMhLwKDB53p9K3/WCAbFzF8KGIBZvOjhBw1bf2O0XEO1wg4C5fBYVtxOhnT5i\n7Qp5zNS5iHbYWPiykYR9lAebCCEJtqUyKcIp/jrSz/KDKl8+jqDirhnT4LUF\nfW3sNdErm8IAMnp7pNo+xWxlUa7HITVkkhoSPCyytoiwUw5HXBpVHC8TF8gx\noajivWH4bztdfnN1qjtm7L354zGptU9YJS1PoQwDoee9YCgld/CRlGikPrSC\n4EWowR6XEFF3ZZO/SkX3DUgnKeG4Nxa9dpVu4TXZ+PlvLtNFgqRiGro0Mcmh\n1ZTMWMcfsa1nWiwmzARD77g2mG4LCJ+8K2xCQRhC43VbCMsM216j1IAQhaP2\nhli7sXpJV8/olgRRUBUE43H63DijuW6WVioeCThmCjLAQCTdlo5cxzeL/IoE\nnH3T\r\n=L6KU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGiBPcjl+VpQCbfoQf5U+3A8iV+P8xYI+K9lZj2qA1JsAiEAvCP+LHSR4R3bW7+lNWycoHHtRsypUYSBqQFvQeSeCPI="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.4":{"name":"autoprefixer","version":"9.8.4","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001087","colorette":"^1.2.0","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-84aYfXlpUe45lvmS+HoAWKCkirI/sw4JK0/bTeeqgHYco3dcsOn0NqdejISjptsYwNji/21dnkDri9PsYKk89A==","shasum":"736f1012673a70fa3464671d78d41abd54512863","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.4.tgz","fileCount":80,"unpackedSize":348961,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8sj+CRA9TVsSAnZWagAASWkP/3oKbp8Mw4uD63uWBm0P\n5GSebHOdk5p+bg9kf14aIoW1vhNaNBd45Xk2AOeYME4hMtBoQQn6zk4T+2YK\nYSiVx+Pv+0U++54bdsLBLWPNd05MKO1srxlkSArrTrOAru6BNVbEIiGXZHew\nYu99X5L3KxJ9X2Q6f+BJ4l3jIEwNWRfE7PzHSpoIfqyGx0rMU1rfLw69xGsl\nAz4jRrV5LeSHbNRXSZ/SFJfMlfa1AXJBCkCydnVBI9UDbbvoQHd7hJzhC9rn\noTnlkXBiNCDf3MBbKkG8pDEAG1i1gyYWBf+WLJLLaFO451mJMgegVIhVRIk6\nnx4DFRijS+KIIwcrd31zBSn4gGXK1UVmVVGpkTiu+CqgV+C8S44xc/MWnSmE\n8LKmg/aXCa2VJZ4URJY4bcsHCZXzx0bqALkZRy6kI7/xWRDSWSjx+I9Ctofx\nXXuLbKtz2vZ5yxvBhMLaHH6aWodtqSJHMRva7Z1T1/SGQx8icZ1O19/SJrCK\nB67R7gkotvdVETx7Xxw6smSwuklnNM7l3fIUDGQDvA0NMdPos+MnFwh5tBq7\nL82WPfFfh9QPbZ3l13tvfr09uoWF2fRdXIsPT1LDQ1oRmtgWAkGDdX0vTr59\nL1X9QZwtrYSgSjP7v2jhFzZj2haZ9q891Gc2YMQAKY5HeKeP6wV+TciaBsqh\nOz2p\r\n=81S3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+yp7UDMn2RdSWynWujCa/TSkyotMlXb2D/IRUvF01WQIhAIKVX02JGYNx0LHOsN4c82MEANTzx+NBdx/gKQ2/fK2n"}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.5":{"name":"autoprefixer","version":"9.8.5","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001097","colorette":"^1.2.0","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg==","shasum":"2c225de229ddafe1d1424c02791d0c3e10ccccaa","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.5.tgz","fileCount":80,"unpackedSize":349115,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfCVG8CRA9TVsSAnZWagAA++4P/A/AETedHF7GjdbrxNnR\n2waYpUoU3+b3hAsNRT6SZaC+IVUtcm8KZv+C5tavNgiWece2VpBt1fQEW/lD\nnr75CG3MDilGH/Q2qNfbTSFTZdtcrovcLn0fjhsJ2LImcGxKagTwAYgnt1m2\nfSFTB/CDImon/JOwSU8U3NJLiK4OerdhAs+Z4bPmLqQjP9ALypSyr+zeeUqd\nRn8zBzllBY9ZDKF9+/fodvZ0ieoZRgX1jtcz0VDnUyFhKIMNIp0j3w/0Z6AR\n1wH2sdnWjjOGxcD9btULGRgxEoBoEShDQK1aTNMb2YSg7tVPnmChVGO8Jk2a\nVGC01lsb1oACN7Hnm1GykwhNEIlyH6egCZGatZpiH19jG0yHbIw7xGckLLoe\nqFg4wHe22UL962ybDfZ1RXkJ0rBu3IFKMEmzna+BK1EgGamteykJdI+C06+o\nig57icw1V8pXzJNwoKJWkI67PKxlQJgk24k7ceLe5nWjj4ob85qS/vxsfiBS\nOO1I+7kVsgwvNqKlYJaR+LIiLS5DfQRPa2hfdlKNrQmv1xda2Y/NNYux9LEx\nu9yajtTD5Tog/YNEMRMCW03zMw8W51J5pDUknTKVX8H8y55UAMZ3T8iHdhV1\nq2jxB1O2nmVRLhAvkvjTQ40y8G449EujNUeWyV8LoRmhxkSEvttb0W8Sj/dl\nBlxC\r\n=/8e9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE0v8yy9GidytSozp41oTxtje8HLWpQrTIiyxgC4AUOIAiEAxDf66WHXNvMeP+ZmcM13aorza8xP5/vrBNn2Kk3oKYk="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"9.8.6":{"name":"autoprefixer","version":"9.8.6","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001109","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==","shasum":"3b73594ca1bf9266320c5acf1588d74dea74210f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.6.tgz","fileCount":80,"unpackedSize":349216,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIyvuCRA9TVsSAnZWagAAwnoP/ioV7W5g94O/f6zfxkdu\nmKr0pWbq41AEqbWU/wPGoE/6scLnH3kXSmS8fthcFga1iLkM9a90zBLsmQo7\ncv+tDPQbVNNBo0RXYgACa52tLRsP42A4up8WsXQnU4ABoM4uP1zUWeXuWuSX\n+KuoChGFxcx/WxvT30ALzCxXSan2eSYil/01koBgIK62T+SZZbfCase6Gxs0\na+wCya45Bt+dGG5e/5sgoXxv78gJLS7SreUXX/zjg02/28E5aNt3hNGZJo15\nYI9jbWkcSsR19R9/717yu+HVN2Z4D6Fzag5JCNW7Sa64/gpv2qyOCbcJY66X\nG9xEYzxjJt5OOLodr4v0BY7yrUf9pTkaFMXy7vHfZpqP8nraqEDpVqR4m4C3\nVq7qEOH1KxELlWYALwCxigZl84TYMQ8ks6Xol9fMLlQiBP5uozbXJ/Dkl8fk\nutnp1gH3J89Izwgc75ZlyZZamMWtaeWt9gm3LtmlyemoY52leZ+4GWDLJYDS\nXeVIPNlwQuMfRwcmF+6CziSEAXXFJTjatc4eKA20G1A5TeG0NgTmnnZIK1P3\nlJhZSnd58YL3Xh/ivrdsDOX6gaOw+HJcQ+9WCG0qihiHtgL8aKwISBwPtqyT\n+AbGKx8eERrWbjKBMWzB16OEvj2Rgi+l8UPdBLq4XGkoJ3cLzHbesHVr9wAA\n3bcd\r\n=IcNB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDrm9j7NIG/4g55VwzfWIQ5ESc89F7gsROWNYLKf6k3oQIhAIyv48k3C6QAku7inEd3hgYFt/cWP8EfZIm4Yuh4kFNe"}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"10.0.0":{"name":"autoprefixer","version":"10.0.0","dependencies":{"browserslist":"^4.14.2","caniuse-lite":"^1.0.30001131","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.0.2"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-rFlVYthz6Iw0LhEYryiGGyjTGofebWie3ydvtqTCJiwWe+z6y8H35b4cadYbOUcYlP495TNeVktW+ZZqxbPW4Q==","shasum":"4afbe9eb902ffb5d7a9ef6d36013948fdb34601f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.0.0.tgz","fileCount":81,"unpackedSize":245678,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYQ54CRA9TVsSAnZWagAAU9wP+wV9G8TSGguBk32MiLgP\nGtWIi52b+uvwVhPAQHamMvvEG7FAn+WmrfXC5Oqj9AIzv2/ELRNbeb/B5qhC\nuByhaLrcGA3uyVB62Nye0SpNbMAO2MXj5uc3sCU4xIA7nhn71bYzk0LwL0iX\nmhzsSa0WT563vT7Z66oLJwAU5eqFTM9+r2M0rv6QJhj0j9HlWmLb/kMcrRJR\nTS0UBqMOEb8ZuSlr/Ox+SIXo4xMg7JyNtk+VKrJQXfGFuIHCLByMvjRNnPJ0\nXEzupO4whKYjHlGZe14nnkApbobjQ4huv0UuWVzf8E09omrMqDBDU5eXoXs2\n7r4nqECxxf2bBL8Oov6tkgSWT/8u0nBBzk1cGIm+2IdccyfN57QB+f2hVUGH\nfsrYvmXQEcNn9cTGjPB/5Noanlp2phsQwtkzsV/OQSeRAonbsEL3eZfAMtwV\nxyt+cgM3RacLTUKQcpQTaossEKl9Pdjiu95IgUnGziylAuHdUXu2IGvrLfQV\nSsOwxdjWjYadX63Vw/QwV/KWPsCMfRDIgO3U57gtof4O8JQXaOqHGFg/8v/h\n+phzNFkq8jwJIPWlpFYA7mlbxDUNDhHgPdxIJipw9UX0+WlxaAd7cND9f3jI\nyfPwCabQNI4mIoEYeyIxPNtbkYeA2sWK7wMg1A/FWZ9JchEava3huaTa7Urp\n0H4r\r\n=eQM8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDHItJz5y4OJWDLuBoe+mdPV9bvqhZVepbMlZQHV91ZsAiAHtkK7VhhMbpsKQpYVDC8FHscOmiCcScFbfsjUhS/PQw=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"10.0.1":{"name":"autoprefixer","version":"10.0.1","dependencies":{"browserslist":"^4.14.5","caniuse-lite":"^1.0.30001137","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-aQo2BDIsoOdemXUAOBpFv4ZQa2DrOtEufarYhtFsK1088Ca0TUwu/aQWf0M3mrILXZ3mTIVn1lR3hPW8acacsw==","shasum":"e2d9000f84ebd98d77b7bc16f8adb2ff1f7bb946","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.0.1.tgz","fileCount":81,"unpackedSize":245646,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfb+BWCRA9TVsSAnZWagAAbBkP/3eL5zb9DhoKwM9oxfvE\ng+bEeIlILlI5HkTFHq+qSxrKnqtjcGgls6KS8mTiVLZjQmyUBxREzuVWSDJu\n9VYk6zuw4Sy14ouXrg7oGVxoJ0O0OdVp2Hm2/e+5lYHz3VcASsR0b+MFrYfP\nkjXWyBKT9u5QEp1MsOT2DyySJMnSJbRWyxHpNLucO/DWvBRtq51TyNsNshgb\nHj0OF/R3qspLJFMqDYpm3QE4K9OB7Pda6RG2sg4FODjydfMjcXBOS7JowXWF\n0lTEnvVs7/rBC1DKH5VYziGcSgjzsuybPIFMQR3ID632ru4mr9AaNibyKDja\n+Er1mOTqUnn6M/owouILKqiGM9tdBqAxofHYPBMoDrfGmC6PfrDnUsrRBTwq\n9Ak1J6bb1/Mewr7YQLpNUACs7kO0AwM+/9nbCP5h/zJW4kxXPmSaS4rYOG/f\nX5+iFlZqV+Sc+1Z34Oe0TLw76RyKunTXYyJmPqXceBgDBq2IrXSsJ4uef050\nga7rhL7CHb5WigqmXXYfvJu4gPTLFIghjIgRdesuLsdHd2Oz3HBMQVStq0rO\nNOoFkgj+Z9j4QwdNP8CUfK3rv9b/mw7944/ieksqq4u9HPc8eMftUlmLBRfY\nxrlCwgnoMWmpi0LqDmvliAp48cen66QssKk6VPsBwNOGFXqbmkH8ZO/+ps7C\nUM9y\r\n=Ks+Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHKVAzM4tnG2abCibpOcb1BQPVpLnjUGRVUs1FtsyeOQIgHPRgd4gPFiUveUd5nV6eAil+mLipwoCVNxnbfBgvygs="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.0.2":{"name":"autoprefixer","version":"10.0.2","dependencies":{"browserslist":"^4.14.7","caniuse-lite":"^1.0.30001157","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-okBmu9OMdt6DNEcZmnl0IYVv8Xl/xYWRSnc2OJ9UJEOt1u30opG1B8aLsViqKryBaYv1SKB4f85fOGZs5zYxHQ==","shasum":"a79f9a02bfb95c621998776ac0d85f8f855b367e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.0.2.tgz","fileCount":81,"unpackedSize":246044,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqqugCRA9TVsSAnZWagAA08cP/A0EefMc7VLbSYuxfRIk\nqXyIB4s5H/WH6/jtm4KWQeQnvtV4N2pGfBzzYsPgq9v7shc3uDHZyc25rWwh\n6cKsxeXzdUrmFjyZAYbNyw6s89sg/rtsaEj5q58aEH8JF3v/oDhNX6y7xBbk\nCd2SHxpQdn5pmPOKhCvcka/RHsbrtZP62l5ypUyMzlajqzpm5uLaWThiywl9\nVYB7GYNsQUkbqaM2gE1nP9QG+AbX0IF8AZ4Qs+IpcIWn+ZfQQZWWM7NRaHol\ngUKtGEMD/Y8c3AzT9vd7fpU4xmhxXj0Mc9NfneIIXzgO6jfuEmTF/rjil4ep\nQCWhGYDtgHJeFhoaBhS1m0EfanqmSkPLG6hbLbymi1tscV+w+GhTxdKVBGo7\na2onDNFCeYMltTMxpgyEYXm5Rlhw+DbYmSRa3zWFo7xY4K+EZVT1mBqIdIRt\n0fLWCSw3vYm/kfKzfGu+L5sBZz11jGfvKj0kQ+q5Aoog8Z4PS0asYNcYWgtO\nkMdFXwnfYpTPK9VaEzSY+CBuUUQZljTKVCS7UG+IhjTO8gkpcfvYk5ZzCAsW\noFu0tv5I/bfPntS239Tnx6U45hTRDcUh2FYw2gAq+AQNXp5ziWPcIbs9fxYv\n9/1oUqP9A6CBPBaIJiPcLFgHKI6bTq/PFmf6pxH+Nj4WCfLV3DVOWbGjeD2i\n6/CJ\r\n=Zy0i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDD1Rw/9gjFSktEZNjVxFREL2GvZTw4jAvRHxDbs1HzfgIhAKSCap8u+u2GzP6y5ZaUVnRZL18tFs5NaZtBBe+LO/Bb"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.0.3":{"name":"autoprefixer","version":"10.0.3","dependencies":{"browserslist":"^4.14.7","caniuse-lite":"^1.0.30001161","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-SIUDNQlGARsfL69nsmi7OKnDtz1HVwPAiYPGn1Nv9eLMpBywXK5DNwAnvTq6aTjuPx3XKPl2boCQRYcThjJa2A==","shasum":"43c8fb60ab095f4b6ff7bc5d24cd05925112f2ce","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.0.3.tgz","fileCount":81,"unpackedSize":246135,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwCZjCRA9TVsSAnZWagAAD7AP/RTq2RhXFxfdl9QXJit5\n+sUmMyropBzVSe1O4qFRPmVC3zhpNnTKHqOXUZbVX517AfToHTM04wS2zucC\nS1sx5ehSiTV6PtyyxX6v3CJbYuhe7KePeosGYD7lB0f7YweUApqYRE8czvkF\nUwGURpfJ5BYSD7GJANUH7B/Zzz8g0hhi9Ope6AEdEIDRbU6mMvgzgyx7PJZD\nxfnsmb6lJRL73Pn5kS4d6OxB/pGdQwAOJWd1nhLjgvPRRdjB3k2PRb0Hr828\np5adRl2Z+nl5ESNyjrwqnwHStijW5I/lnA3a6BtgEMJif4sMs18590WGTNWM\nm0hiXmwd9nZvwnj5mJDVYexyPUlWZ+VMi8XEm/ZoUXP96KVw2Au6cCRng7KX\nsj6jQndUchMaPe8VEWOF6+K5DieXfy1bDunmP6iXXnOcTDZIHMvexEOfXitr\nhYW0HpYihl1cfQInoyVNsrHZ/SwIiB9AqvLn+J5BwpQ3/s4hnTytvSLim6Hi\nerCfhEt5CjQ4Y6bxKWjs5m1yG9z07j9AGrq8na4G7FQbf7/SiNjDLrRyJBZW\nnbsNmYybvSKnbOXA1tKicEubSqeqMU2NhbMBlZyddob1h+ZaqFOSPJ/h1DoX\nEj+cxoSrF3eLcph1Tow21EcqcYOkYJdgpYIew+HGiVcmNf8lGpkGQlZMf3vp\nfiEH\r\n=idke\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID2RH3BxDQwBLe+MvieU9ZKXlRyRROOXmIGXdfmxHDmQAiEAlzGQ4ehmL9/oYF8sCDcMOo9UgGV5IwEWzcXq/F4yRb8="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.0.4":{"name":"autoprefixer","version":"10.0.4","dependencies":{"browserslist":"^4.14.7","caniuse-lite":"^1.0.30001161","colorette":"^1.2.1","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-hmjYejN/WTyPP9cdNmiwtwqM8/ACVJPD5ExtwoOceQohNbgnFNiwpL2+U4bXS8aXozBL00WvH6WhqbuHf0Fgfg==","shasum":"f87ac6105d7861e31af794b8ebb1c6d4390d3d55","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.0.4.tgz","fileCount":81,"unpackedSize":246400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwXBSCRA9TVsSAnZWagAAq1MP+QA9izf3WUklcTYIknRi\nCcpcuO8Wn16ck9BNT/2p4TZrqnKzr+POWcMRpZ73SHXAGVKGGZXK8IlTnXnt\ntu8/Qy+A9J8sQ8syRRxJ34mnltWwy2fo/+JSfiMbqCbVs3DKxPVhoHapzxbh\nbFJbxz/3ewLGbxLEExL3rGJ9wkz8TeTLvo285NTOyUuPtycgHMI37l2DebEp\naGhFaC3biYSoN2385uqh8txkxOPRTvWR9umPJomceB2N8pVl0zc0ciK2qhO6\nsi7oQfpJ6T/gwCcOUR7ZmNjzSRSvt20+ky5Iq9/59K2Oheo7WTE8cgUvRxtl\n0cU6V7qOdMEMgPWLdKxG6F2ohP/NtT3/6FK1yKKe8E9KKxAghybaRdi+lIsE\nuz0bsmJiKhxj4duU0VYgqDgeIoD+/u8ZRxevMKxbjWW14qMdOvzy4k0mRXuB\nHBK/SsrsR5RbmkdyycfzM6G1xXMGrNPFStoN5P6Oxyraiiza7PVKhMAWGonn\nuLFr3/hM+ae8XySEDMx1BSUyogpgunnf9J4qLj29ZxrT5/uphC4SZXCcbIP9\niM7dK+IFrX1100+SE8afvPpX5de2fd9SflTJA0X996QVk2kToLm1NdGZhcBQ\n86wm0Hy71ocJCCh8taYoDYKAXhLKFjxM/OtTkWz2Aa4EfxVlW3tNuVIVe/Y0\nvps6\r\n=OOeM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLsySDVV8jNSB1MXdyvaVUVrBJ2CxlOt3/Ft42leLU6gIgK/QDfnmtkfulHS3lGxwUGa/rLRqzEmnHRHaOXpV3l4w="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.1.0":{"name":"autoprefixer","version":"10.1.0","dependencies":{"browserslist":"^4.15.0","caniuse-lite":"^1.0.30001165","colorette":"^1.2.1","fraction.js":"^4.0.12","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-0/lBNwN+ZUnb5su18NZo5MBIjDaq6boQKZcxwy86Gip/CmXA2zZqUoFQLCNAGI5P25ZWSP2RWdhDJ8osfKEjoQ==","shasum":"b19fd8524edef8c85c9db3bdb0c998de84e172fb","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.1.0.tgz","fileCount":81,"unpackedSize":246768,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfzy5zCRA9TVsSAnZWagAA/gEP/A+FtxbSJMuorGMDvrjS\nljqcen0c+4CW/gsculhbZpCQHcYNpM2DW8v+XPnMmaV/yjbuE+gqIS8XeTrR\naYaMy2ixiLZqO4XzzZGzjL84B2saULV5/XOYsgsDWp692jInfnLB6ApvKbz3\nkz3TR7rfW7TLUOHUWyWDJ9z9c4DQLgG8s9fVYqCL61SCB6D1kvg7EncF55dk\nd3jx7KBhdbkk/1Eab2/waLlybEIOH3WMk1QVx1pEPbVtuXmPYoH13oYgE+XD\nWiWkOVb2nj3QmFNz1MW+aAGYJ/34Kq1ezCos2H94s8xqXrzS539OYeptOzYu\nvVr5T6uS8+zicsgESTw8EO1vv8SHDOQbz8NwNQIhvSmIX56F2f2JnFtP8jFT\n5GUUUM0s+a5QYPLoRYQDCPSS0cBxYKDP7iu1K/4mtHm6r5IqbhcOLqaS3wPI\nwrkLXPFJVRDssKyyEAun+3KPYwoOqYGPLpKkzA3SWarCvWyRc/Fc1p16wxhf\n+26Md1hfVstfqyF2bxfqlYNh6ODBKLEYrAyLFRRFAOdXrsTaT8ChGaWIL8Xh\nE3oikt8X1pvpm7Q5eDokz/I5egMGXCwLBBe4C3PY2hy0gYmHybDpm3QK7gtR\nd+9TEcjtRf9tE+mxejvttfz9Yne9FG2Umkd8l6s1K0KC+fERJ8OtetNLJpjq\nYini\r\n=C/W4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICWinTuQ+IZTtg856aFfrE9gxeJfzlnuWNu6BxTINUxaAiAHI/+K2+fuTiuyAyZpY9+ipHR6hEnkxrh/9XmRWXtXMQ=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.0":{"name":"autoprefixer","version":"10.2.0","dependencies":{"browserslist":"^4.16.1","caniuse-lite":"^1.0.30001173","colorette":"^1.2.1","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-5SdPoK2Q3rxVh4xC8GKdy772KbEESdl2SyJADCw5FMUrd5eNtpOTLo7oCFMEKvK86zQdvsIVTYk93E8dAfRy6g==","shasum":"73c148882ff771b48df9e76eaad88565516eda0c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.0.tgz","fileCount":83,"unpackedSize":249539,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf9RyqCRA9TVsSAnZWagAAuoMQAJdBQ3czIUELlr/Fm/Ya\n7zPEUJDLuBoojatGMVaOYIeuspt5LYYwIO0jMF8ESeBaDoD35wUbHptjUPQ0\n6yNqVLflct5/PFBLx8q8KLumAZ/vN8Jei9CjDEmbkAQl9XUzwcuJO4yjfN02\nKtfr29saN0RROvAS3HO3DMx8udncTDAj022th6M/3sYIN2xm4lx0aAogdHBw\nV6M3VTQh3TrxopMiPpeA7hMe4RE6GLbziuVk2gElRsz1fc1Y2d+cFmp6MqFM\n30tgivhPgi6Ikcnc1B4MKgjuKfq3jpi8pgML5oLdWailM1DMqyxJmnrDzF/b\nqFOnI/4SZ/pwuJMcY3ocrip1wZPz9NlEaNlbefbc9tzwg8xERRjHC8z93j/l\n0+eIT6J+h5uuOq3qL8R/prMBVXY133hg0NFJo9LgsNbto91NdBwxNjw1dtkt\n6rpsLm0y1j26BtZKJwrhYlUo4eW25LVCRpmKs5kImcpwETumlLD9nC6hP3yF\n28F4v1QNVAcQY2a/nOfAWUPTlTnWd8jHHtE+HVeCViwDEpTkWuugcZeVqygx\nR9Mjl/dwOa8A6fY2czHI4znl0b8yjXdlfFG37RlqovCBdSzBD1+ipFbm3CyU\nb1ImhDT1/lDp+Qe74RQ8QANueX4zZGdT2VWv2D21mlnXKrKl/lj0ghsfp93P\nwgbI\r\n=+eRE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCPjFJa8CWrusBLbrgg7E1H4yvqwwdMw+ZvG+J2jNd8/QIhAOqfsn4QfuSl80bXrbuizHsW9e6uGiREH1I7JhrINlUB"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.1":{"name":"autoprefixer","version":"10.2.1","dependencies":{"browserslist":"^4.16.1","caniuse-lite":"^1.0.30001173","colorette":"^1.2.1","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-dwP0UjyYvROUvtU+boBx8ff5pPWami1NGTrJs9YUsS/oZVbRAcdNHOOuXSA1fc46tgKqe072cVaKD69rvCc3QQ==","shasum":"ce96870df6ddd9ba4c9bbba56c54b9ef4b00a962","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.1.tgz","fileCount":83,"unpackedSize":250147,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf97h+CRA9TVsSAnZWagAAricQAIy3q8QU7vCOlqIq+baw\nsgezIqx/cR0Nfw0K8KG63fG1aIUCrSGPPnkzqfQcoRQ+CVHoUqUka3AVs4fO\nUgRYge4/1M9M0K3afpZEnlA7KSNEs0BeLQvgyDeO6OyM3AqPIa25tS19r39M\nYNtBBXEmLCLB12rra4Y5fe85X3YjubdKQjL91NJkrKfH9/ZZOErZ09NzE5aN\nfvjriv8SP9pqtBfcPUtz0gI8cempDpZ+ujT6OSy0TZFaG43IuwKgAu02oavD\np1BxScWmAlONpjAjOeJwuKURkh9hC96GfaG6nq4IhQaybmEXrqrAZc5AHfvF\nTTtafYHIwMmRXP72nm2KtAMQP1W3V4DgzbJot7nO71s1zV9Kzk7fXjzJmZBs\nkAZe/xJWvZyzous6tkIVMjREc34ycgo0Kf9+ZXMlY3AkteeaAZxzFfRLqfUd\ngXdLRyh6w6sJANDQltNKe1Zfomk6SGYx2BL8FQqmYXLgCm9CSXMYRb61XhHE\nd/QTh7/2lr3is1Jx1bnJwxr85pMBz6FoPkXmpfuj7eKKh2ksoeNBqD8IRW/2\n2UMP+EmpCYAS7y9DafcR+IvGXvba1wKwVrh0t+MgdG48B+6xRV9QniucRWvn\nym5wNP+dKx75KTGCjCZT50inl1KG+DOk062EJuN103diW0xrmI5eJv2w6n4O\ncPMg\r\n=c+LF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwJOBsS2PAxWp8aGFCFOVoEnIWz1dKsvTQU1furqgpSAIhANV3Kn1vQLxXhuZk+n2vY0/JVrO3e9WBDTbd/ogFh+5B"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.2":{"name":"autoprefixer","version":"10.2.2","dependencies":{"browserslist":"^4.16.1","caniuse-lite":"^1.0.30001178","colorette":"^1.2.1","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-jOQss7vuYBoPW5dYt4lvhDImjGE1Fvl9NjUCzKI21TB74Gl7CxIRsWgJpOplV7dbtKNVnY97JuwULpIGa6KZ1Q==","shasum":"a452e4d2aabe54b9f22b2229a99bb1e594f6d90f","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.2.tgz","fileCount":83,"unpackedSize":250203,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgBybxCRA9TVsSAnZWagAAYtsP/AuQhCMGqhd3zcHg6W8Z\nfA3Uo3v2kLWppbipbUpLWgh0DkzhnS/TyZGsXcHPFeoT8IqaesWLq7lXo7bP\nLO8/O/wmSTBHe6B+0kezUjz0ZpaYB6rRHPpkPup1F8udmFgpFljSqaZxHB3y\nd84WDde6nO6et7q756tb27qvxBnT0el06psgDlfADLkDLBKGqJGo7A7tBzH2\nxienmJRISMw/8QdBZzv0uuc9vZ2GUM5qKV1gisEKkdg/s8fRt+R+SieoCFiw\n0b3AhhjlvBDr24cT7CU4qrLy+8awC0MI4kVb5l+PTno3BnHkVYNzAOG3uCh/\nwddP12wq7OIHqhnphMg6lp/nzUnI4r6pcEto6uiu4zuexcRPCAluYnDCklNz\nt6CmF1Nakcd2cdOYyHWU6JQA1Hm88MynFTaKYhkEzAmMhb3v5Z0nLamVMvsV\nqOtUmubj1zi+lFCW8U5pm1W5Edcv6X3+4x6uH0RwYtpOM/84vLN9MpFvuGzP\niDLrXT/rv2FMbIv+ImNqorg+EpE00N9MFzml5DU7+wUOWVyaurZTGc0DekuT\n2emmRLmQRJ3/7XivsWx5bFaxHLwl9H8FDnnxt+cvyjUkBq4PL8cg0WGwp4cK\n8HCjbJ+/bGdSw2FL8/ZjlX7megv6dPRFvBF5rRIqyOyPMKfOwEPr1+0InnO2\ns8Ee\r\n=x9th\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIETnNn1zSbitejzk1IplZ+U3FcyrrrPuvu2Ph3v1mH7xAiEAkzInfDTn+xLVNZOOCrqIQXdSbQzn7awSgVX25tPHS/k="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.3":{"name":"autoprefixer","version":"10.2.3","dependencies":{"browserslist":"^4.16.1","caniuse-lite":"^1.0.30001178","colorette":"^1.2.1","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-vlz+iv+EnLkVaTgX8wApfYzmK3LUfK8Z9XAnmflzxMy/+oFuNK8fVGQV79SOpBv4jxk2YQJimw4hXIKZ29570A==","shasum":"2834b55b75cfc10fa80c66000a66dc94b7136804","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.3.tgz","fileCount":83,"unpackedSize":250293,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgByjsCRA9TVsSAnZWagAAVo0P/3b0XQQJXoBXvCXyYsaI\nY61c1xowdIyqH53o0mXLGzpHrhxfVNA8NgRXSgN1gPhlHIEwr0Z+aZTMxzNo\nGJIFprcFkaC13xbW83ielk/j+g02lJzmhn2OGV945NW8XynN82G7xPBEEvZk\nRJbv++lEqy6fMfai2PF6R3029IOAr1zXGuVALDqt1xBhpZCU2Lb/fYI0WOyQ\n4md/rfExl7XzoMqsU66TDYb6Asi8nDi8p7rlY+rYwKu/V2oYxxw4zD+e8zor\nXal3KDY7xI/mKEQXz48dYGPqlR3XHI4i+ixucr+sz6ALPphCdeU90nSBR3gY\nCwh6O0bI25oXI0+HnEv7D4Yux9X9KQ2Uz7lBVooOCY+k4pYcPk5HoTKkryQc\ng9RwKOkCpM9OSyNAcuTmzXpIaZ/y22/Y1pTFnJTp8l3F/K2dHXkE/v+WMryI\nxkc20q51Wsy2vJSk5edBu9n99Ay0BpRBZ4Im5TX2Fel3xSh60fdph0+OIpbJ\nXZDhEHt1+WhAW3Zzwi0hAL/8OLwf1j2kwH25YG1+FgiU2yI4Od8+hCapsWUz\nurEOYy7QiMYBnskdLSAOowsyofHE1I1uCy0bPrYqkTXv2/VjXyZx3j8PXtrY\naM4zkgaw5wyEVL5nMancv1KOZlVKqhQWR+5oSe17iJnID+swexAMCoJMsr3T\nRWyp\r\n=CxE9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEciKY3OeykMw8UavDr/xtPZiPMiYZ95YSIO8df2rMpXAiB+eDRqRA3Wh/5mq8N9cmkEYB+XMyOBUAzz9ITEXqqf/g=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.4":{"name":"autoprefixer","version":"10.2.4","dependencies":{"browserslist":"^4.16.1","caniuse-lite":"^1.0.30001181","colorette":"^1.2.1","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-DCCdUQiMD+P/as8m3XkeTUkUKuuRqLGcwD0nll7wevhqoJfMRpJlkFd1+MQh1pvupjiQuip42lc/VFvfUTMSKw==","shasum":"c0e7cf24fcc6a1ae5d6250c623f0cb8beef2f7e1","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.4.tgz","fileCount":83,"unpackedSize":250464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgFERwCRA9TVsSAnZWagAAWBYP/iYeeRMwr/CXfeQYbPDI\nhQ4Gde2IFMEBPu/JBEdjXqwn1YGXF4Km4n5sjRlHaIps63DbazMARPtOYs/p\nvJMszouHhjGqZ4ExIbXLz4PdJtVrKmUhHGN1PfyAr+v3YWIH+rXr70XFKvtW\nWD+z8FBOjx4GcWYFFulJy4tVbrXT4PCIAe3MfaJclHMpSiwmsyhg2ndpyE68\n8JwdRMqTwnzanVp34ZMWXC+2Mj68jrUWXTdIVj47Na/6LS7Zv3MBs1blFYVB\nA422uutXo6kUgeMePuUDEvyHqpYJusU9iI5u4S+VfQuKrkWZxPkasIJ6FJaH\nt4NTJCYAhGFs3vTp1hikY9rdq08tYbwXuFkYwfzetVHuP0U3o/Gi9mM1R4Ce\nBIRB0har6/ItIYRw5Akmh1qYo5Pnu5aNAtgR3tC9J/2yxqrtqmUTmjj6eUJc\nOIHdMqNjfFb16DZHNn4QIijU9vfMQAuIrxyJutiT1FZutOpaDwHRNsBIcu+Y\nctUhUPLlUBrZfkBO12KwQFLjSOmLEB3fmSNX8vKQ2QNOXe3T+1N3DhLh2QOc\n3HPFzGt5Jn/Ikg8M2/0BKslgbJewOrcQcfQhDB8YOgLRBgUvE7eeHHVQ2d/n\nACkVtQQXuQbQVNZZ3efs32jpBQIqLSVy+ZptTfX/drdvCQ8g0TxfqHPrPoq3\naWlx\r\n=TTR2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBoAR/EqpzTLGGQHu3IMTpe4QYjFXd3s9RP+4Mige7ovAiBOhp/ymB4kAN7Kay4pteeg+Whi5caVc31O864WQHRtBQ=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.5":{"name":"autoprefixer","version":"10.2.5","dependencies":{"browserslist":"^4.16.3","caniuse-lite":"^1.0.30001196","colorette":"^1.2.2","fraction.js":"^4.0.13","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-7H4AJZXvSsn62SqZyJCP+1AWwOuoYpUfK6ot9vm0e87XD6mT8lDywc9D9OTJPMULyGcvmIxzTAMeG2Cc+YX+fA==","shasum":"096a0337dbc96c0873526d7fef5de4428d05382d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.5.tgz","fileCount":83,"unpackedSize":250719,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgQkN1CRA9TVsSAnZWagAAoxcP/A8TdDg9gDtMvbuvIHL+\nOGxq3nqo0o1Hh3q8/7wHU3NRuwbeWjIN5L7N/Ii2zB02Woyil5Cul9iOCCDX\nBMWk55kQSa1vIT99SAbbjyUmmO/sCV0J59Pdm5GmxUaYYDoT94a1qjccqgR6\nyPC0MkVxa8rLeNtM52kkxinZX0b5U4GbuEFqBkMhf37U4nYMncubwYHbf09E\nXsssz9aVivUNa8VRMiJUiQcPuToZep6ss+jSqZWyiF9b0IgWFsHopKDMWY1A\nODvTF4F7JYYrWiRrbSlf9ZIMYSTwL54J16LQEjfiSrRXI70hfj44181JQdR5\nt6TUa8vi2kqSLU6Fbje7HJTjbMiKEnORCRQGHMPeSDiISB9xQdp2DmBqGuoR\nhXVF6SE2ql7q9h5eCuf1Z2YS6X1UqqK2IzocBR0K/EdU3R3URcd32p6ofaml\nn1K0RhK9/DNGQofFPm1/vo8kdAEVdGdktgg4xgtd2FfdEkQeYYJNsJzAbosl\n+d6/4sT2DQkfzdRZGfIAG1hYSmw6Q41Yv5d0OepqSBwC7ELNCi932jTlepSq\n38t8aMP4AqQxgXqWfissiG/NcqDSAP2e5lmi2s7lP0iwhf4asbTe9wIW0dty\nbXK+SJuRw9hb0pwlqUTdhwxpGcbhdz+kzTu/eqlo7r04UmPuZ6KAu3wox9F4\nTHq0\r\n=CCRD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqerWs2ZtHSCdJ/YHwLNyhY1Sim/bkVydplPebkjdtxQIgZviGu57DXJfXmKfjizheIf0u0f0e3P+3odXPFSMpyvE="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.2.6":{"name":"autoprefixer","version":"10.2.6","dependencies":{"browserslist":"^4.16.6","caniuse-lite":"^1.0.30001230","colorette":"^1.2.2","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-8lChSmdU6dCNMCQopIf4Pe5kipkAGj/fvTMslCsih0uHpOrXOPUEVOmYMMqmw3cekQkSD7EhIeuYl5y0BLdKqg==","shasum":"aadd9ec34e1c98d403e01950038049f0eb252949","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.2.6.tgz","fileCount":82,"unpackedSize":223958,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrlvrCRA9TVsSAnZWagAAmicP/1D4xUur9tuUCZls0MS4\nRkpaBM7rDnONmKoc1MxUgYTdlZiNB7advO9sfNTS9VD+ucjvZPFh6qwqln+m\nduPaWWsgb9DhhB9Z2STXaAlyOb6vU/sDjt6IibRQ9OLUIT5z84iWIEDvf27Y\nYHwmJYmdsNlHRVmO0xoi0vbOKP4x8I4M44H0inj/nVVopKFj+Tyj0S18zxht\nIbteENKyBfXz03NcyzFzv4SC1LLbnKEGbhR52znc7TqKlV0d+XSz7Qo2n7KQ\nK+hq3hvg0OUsNEZn65GGQMMo5H64CLXtc1IZHCjqM//Wcf2pO+nrgPTGlADE\nUQsuOq20k/kaBvTCtf2PCfUbHbCiDCjS7N+1zILxbBgpCg/eYZum6SylOokf\nc3cNLJD1ix6Xq4xflUhdt6sszOlHa+tALH7eDSK0b3oxpJ6KlCVLjl999Cl4\nrgz/P9WMevqUh3ntdC3/FtMCfB5JX6JZAP4teQ80L4kt7eAxAl146UmJMrgW\nsNhob7H/dunZiGc1owfyjY6PuBQpe2yufdymQvdzsVXZma7lcG1qc60VyNrN\nHi+zsrRG4I2+1ZaTeTTB6//L2ulI9om9Kk7tSJ6ew/S9+vaTwI8EwMQZJN71\nh4MtGz28K6770Td7RltAXnAwl5Ym35mTYJJJY1CG47g658XGte7XydrpsFbe\npCiV\r\n=EEHW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTLnayQqOYgU4daNcuPYJEz5fdniqMj5eMgPW2mwccxwIhAN8EbMABrHpvr/BAxMVpYTelVkcphgFCCSMuk4C6JOsX"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.0":{"name":"autoprefixer","version":"10.3.0","dependencies":{"browserslist":"^4.16.6","caniuse-lite":"^1.0.30001243","colorette":"^1.2.2","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-BzVzdjs47nT3MphTddr8eSsPVEIUCF96X6iC8V5iEB8RtxrU+ybtdhHV5rsqRqOsoyh/acQaYs7YupHPUECgmg==","shasum":"c60803dce9268f7fe0a5e5c1fe48a74356d7b864","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.0.tgz","fileCount":83,"unpackedSize":224648,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg6YFQCRA9TVsSAnZWagAA1NoQAJgX7qztD2ADQIagGQY2\ntaBchLttE3zOMRtwcN+6mNGgm3XRjlOOT/ysUmDxVxKz/UbYQ91s0gpIYHZO\noSPDCAdyVmndyErdir/xJGJdNN2eVgQb01lW/WRnMU+uzHl3xwoHXEwY1lhs\nERJDGS/8tCK7QwfHRA1+w4rH3zsOKIx1TVzGsk0ZfbbDi5utOIjKbgfKnI3h\n0v9uNuVfpPR1R+dFFiZld3UMH2SF+IATaGHrU/kCAcf9bPTAg+ki9aWc3Lbh\nnrlGRVRO/EZe3QCrl2VXDD3c1Dyi61GIiTePaGZ41g7kQhrN1/6Q0in0z+Ce\nlW84ogRn02m3GGKJ/vzJAwHVkPIn1yw1goD5J0vDBq55GLi+usU/wHXaA6TQ\neWeXDmsJzBaMm7hXpzW8XU2c57wkX3F8zHFr6DShHeaOGqsDldrBpvgqTGXD\nVWTncmC0ei5PBJp2wrwGX4q0rmfRpeZ/0EAs2Q1XpTb6LOKqUXqZr01fgV5U\n9bbjNEF1haIXq+Q8RHBYgs2Dt/DSYY4HZ5a6boeewjKAywcZnimguMxefoTq\nCr6ZQPaA3c0o3h27ZmROKXz68ndb1k7M30eqnd3PcfD4KZKdPvuPtVcDfH4j\ns1nlYWFA83kTz9ito9b9hoL/XAseHAPjthKH6iO+oD4rapbd7qjiPL7lqu3+\nlvs5\r\n=KDh2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBK61Rsecj/W9O5Fv3jZMmIIBEUQI330lPcJXATR9GecAiAnITarmzH4Tu3NIPIUjvyg32nV30O7x9DxoAstlMy3aw=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.1":{"name":"autoprefixer","version":"10.3.1","dependencies":{"browserslist":"^4.16.6","caniuse-lite":"^1.0.30001243","colorette":"^1.2.2","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-L8AmtKzdiRyYg7BUXJTzigmhbQRCXFKz6SA1Lqo0+AR2FBbQ4aTAPFSDlOutnFkjhiz8my4agGXog1xlMjPJ6A==","shasum":"954214821d3aa06692406c6a0a9e9d401eafbed2","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.1.tgz","fileCount":83,"unpackedSize":224731,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg7HwyCRA9TVsSAnZWagAA9xgP/2EpyILC+DuNlu0FfzlD\njpFgnXJutQBQuAvNmbhqW0FDGP5x+jFtrSEhcjOcT/1qhlxq6GowylhJ/IEZ\nFxRu92aHqRGAaFHsQKs3XVrfm2vBcIcopBqYE6ESDvbrQjuC9fQPzRlMKn5v\n4u0GGA00zQ9yS4AY78v0MdNhYUEmqpLpAU7e52KP90Zsjn9R0GKASEQEkk3p\nnqDqfUpQRJkemE5Qysl6xYB3kqgezaWUt5cLj8D8w/Z+nc8WtpD+ab2krr4a\nrkDxdNhzqPLnC5xZ2HpYyGg8I+ZEA1u0IpRtrGU7saMkOglI+QCsagPoNe3C\n1sJj/jChn0grpWQqtJvYYG/hx0ieMVS2bq2wqt+EIsKgWL1lhzJDOMBwYzBn\nYH89pOuGgGZtOefC/+FqGGsU3x8jpujCMpJZJOfM4oGZx7ZnEMtNBeJj+jT5\ngn4I7LoUh5ipN6Z9ciuYWFnWDG4E+tTjxP80XlNat6qMuTJkHXZItJrtn7hV\n7aMN+5D1USLnu6XE/Pa01CnmD41xh+z/4TtIxCBLlx3Vy8w+HdcBXbvcrCYN\nkeFxMKQ6zhvqeqMVgcZh4xaotCULVDnbAqnu8GKS6WiPWiGnogZbYRpw+2HE\naDioTN6eMMyaSwynw578/zflv7VkDLVPjCrwk4q7bTrrYxEWOrxPBpscW/+F\np0Ve\r\n=XR2/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJBRgLjcvjiIhfw4rvpP+0HV76yAnES7DSvZkKIhsBwQIgclWySDNBH8ZrrNZvB22gRs3QIvD5lYtvjc24m5uWMHg="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.2":{"name":"autoprefixer","version":"10.3.2","dependencies":{"browserslist":"^4.16.8","caniuse-lite":"^1.0.30001251","colorette":"^1.3.0","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-RHKq0YCvhxAn9987n0Gl6lkzLd39UKwCkUPMFE0cHhxU0SvcTjBxWG/CtkZ4/HvbqK9U5V8j03nAcGBlX3er/Q==","shasum":"836e4b4f59eb6876c41012c1c937be74035f3ec8","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.2.tgz","fileCount":83,"unpackedSize":224740,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhIUN9CRA9TVsSAnZWagAACdoP/i96HTqqLi9CKytU8fNe\nwjDDKVWotcNvvL8EsvxvGMmXyeZevW4jS00fsGLWmAxf+UtH7Z0IYmFwb7gJ\n15DaXMWFHa8/3xG02HAz/VRJTpxj/vdzBy+dyvFNyV1Auc5KuhOAhjhZXFYi\nGO72j+0AZpuBBiZbJodXRsU5k/O5Qh9mHGOzN1e7GuEQBoEAxzzg2VVHW0iV\ndJ6lIb/fLU6Ckvl2DwF3I0aBenFDKyuM9wuS5UW75fJdSMRB0A/89IXqRMn0\n9c8r5V4TFj7nPlaYY+l5eJTZIeoeTm+BtF6rtDnj0fB5dsN0a/6ZvPMnnA05\nsRKC/OI7DsLHAkn38V8QU+ztLYodxNKMb5YHNSagR+6WhOQ8twbhyjZx3gkM\nqbX/OxTdqoSzJAKSmSZU1yOb/rfEniX0XiWY7fBqbGcbCvJOZeUKEjE7K+aL\nG6M+KjqXwfkopwGzwFRZTb8KWNVbtJ5AOKQZlZzU74yWNKp0x/kxj/10VwM0\nqDjvOrL+2pDxgNKinMJkvDaG02BbDhL2xGeWDi95iNK1ZtqY4uQD8+7WF6ig\n5POls4TrQD3S7D77WhdldMV0Pa6NnwxOb6jWXeweyfEr3/jwdB75DVdEnNCB\no42+oVJeJg8w423P7QNIfUIMe2OIiZjAvNgH2H7GyvkT7bwCgqJENwRy4ffT\nTvjW\r\n=Tyop\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDK2z+dW2yD2GYIok8FQ5Ge73aXdhIgBPBo7wCSZwB1owIhANa7U33DqI5sYTAbghRSntjOR+bPYZkspOzvHjG8i4KQ"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.3":{"name":"autoprefixer","version":"10.3.3","dependencies":{"browserslist":"^4.16.8","caniuse-lite":"^1.0.30001252","colorette":"^1.3.0","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-yRzjxfnggrP/+qVHlUuZz5FZzEbkT+Yt0/Df6ScEMnbbZBLzYB2W0KLxoQCW+THm1SpOsM1ZPcTHAwuvmibIsQ==","shasum":"4bac89c74ef98e6a40fe1c5b76c0d1c91db153ce","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.3.tgz","fileCount":83,"unpackedSize":224991,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ7FbCRA9TVsSAnZWagAAiSkP/RCBsOyXn9QJNywS7SaE\nuRR7oLrBvNd6jz0JVCie2EuzYuegeHibqRvqu1h4gX4b2lICayv0ajPbdo7z\n5naHtqRTs1KwgdsINYzkRNLRwpcBSUdLMQjrzjZL3ad5oYezJGwA+Gd1YJk3\n/O9VV6Q60YE20FIZY/1KrzkaAZDYSLBPFnOi6x73YjQURpK/UXjZADIb4IB9\nV0WL8HqqTLtni+UMG5QA5SELHHwn4sp9m907meqEzyNGXfPUmGJI7jdLhDNx\npURh3J4/9rye231k6pwT76w2ThaXei+ynbiQGS+vqd0jIhXKJLCKRxUXgcFQ\nsjn01VeHj8CUrS9YXgRcVvyicUN6hxkttXX9Rx1Ka/3e8322ASEKmngsEz+1\nkFKply8yZrgLckZVUrYagOdTr9Ug5WLKty8NrWhPB4O2Yu63f7d3OKWCwaot\nxWSLmNxW79ma8nwfkZH5u5NG+XLdGURmilAsMIaKwPxbC3Z0gZkZbt0RIx2a\nGqwPAA6Pjki1Zx1laYUPfIroFo5utpNHFfgsqb3GtEyGuWYECCgQPjyRt9Oj\ne1cp7GBsVfARAarfjJ3QRAuiIRqqp9fQ38fF+fiQ9bcd4cgSaPQainYpR0JO\nGwiQVS1cJboqfa7cMkf78o96/xrErOlX2COfk9z6U+bw51fnwX05b8IWRDnm\nkeCt\r\n=p7MK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHq6p3unE8ms3fdYqgBYLbaioX15nCJAMfO56ciuNMN1AiBLAwcGxwDPmRRrGghOPsexouB7d8XESskrcN1rEVpXNg=="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.4":{"name":"autoprefixer","version":"10.3.4","dependencies":{"browserslist":"^4.16.8","caniuse-lite":"^1.0.30001252","colorette":"^1.3.0","fraction.js":"^4.1.1","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-EKjKDXOq7ug+jagLzmnoTRpTT0q1KVzEJqrJd0hCBa7FiG0WbFOBCcJCy2QkW1OckpO3qgttA1aWjVbeIPAecw==","shasum":"29efe5d19f51c281953178ddb5b84c5f1ca24c86","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.4.tgz","fileCount":83,"unpackedSize":225131,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhMUR5CRA9TVsSAnZWagAAv2MQAJEkK1y+cw3kbx8OaXi2\nc8mDl+0SZUNfwiMTdHCi+/8UaLKEj+nqaalV5nHzIoyi8RU+K8iUzqCRYTG0\n1AgSB7YrDEyVD+wvXiXCrEU/jC1dk6NRvzkb9PouXvTzro1cVMS72WjF09lc\npE2EwVlbQWiQmIC/IoPVbPBg22l6U/W0waD+DSXGpaWpSXJ6oUn2bqOL+0/W\nbZJ5yvL0/lFJaHkRiTcpk2D3XtDuNQuE3dtb040vG4y07VqUulUy5NCm/nOo\nZ9nAW4Txo/2Xy220s1KFR5pAct4CAB2zNh11I22/rq8Ws6Nrrjm8r1B1UcES\ntGMxdviZBNoq+Dnw2BdJBIobGnE5+4aNAyeVv+V9upyuHxK9vEBzZ1SQbTiR\ndWiGUStWeYo9AIRkd/eYpNaX8uypyX9SvqWwqr2FHFWFNCXZFwPIbIlP+0wn\nu4KWERsY7gp5PZpz08B7B3i2FihVlXwWu+hziKtR2WRGjXZT+ug+D6HS6P9A\nfSKrzQTEZajaQH5BWFXKEhZnPNFG2Q+yLZ+TEhcqO4nUf5uPVG7ZqZ8qugdr\nm0+EhjUsJg1iYzHCq0zu54nIhJbVjciXSNQgM8vz+ddoPb/4Sdo/kbACTZ3C\nuInN+HyH5elu8gaWixircA6/j/vYdSikbj1jpm+Hn/PH2iLasoQuETcOVijS\n8lne\r\n=a8ml\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIASjxeesC2LFKPjO74HEaxM1+XnT2UZFt2FR6030c4DUAiEAqP0tK3uPf2uAQYdIKoU01YYsYYT48NzZcZ0wf8h2eTM="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.3.5":{"name":"autoprefixer","version":"10.3.5","dependencies":{"browserslist":"^4.17.1","caniuse-lite":"^1.0.30001259","fraction.js":"^4.1.1","nanocolors":"^0.1.5","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-2H5kQSsyoOMdIehTzIt/sC9ZDIgWqlkG/dbevm9B9xQZ1TDPBHpNUDW5ENqqQQzuaBWEo75JkV0LJe+o5Lnr5g==","shasum":"762e6c13e30c5a0e650bf81d9ffd5713f1c8f344","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.5.tgz","fileCount":83,"unpackedSize":224946,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAu9rUrYIWFpZNetCW2QRYd47nGmlLsLKOykJprwRJu6AiEAxT8lxrLOfTv9lIGko+CVSQEqa2kxn/KVQ/9tU7stX98="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"9.8.7":{"name":"autoprefixer","version":"9.8.7","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001109","nanocolors":"^0.2.8","normalize-range":"^0.1.2","num2fraction":"^1.2.2","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ==","shasum":"e3c12de18a800af1a1a8155fbc01dc7de29ea184","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.7.tgz","fileCount":79,"unpackedSize":318890,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGp9NYygwvsTfNE65b3QZI4RiDyyOjt4Edkk7G5wX7mrAiEA7XId07ah0MEPCclnuozRTSGNh3J9TYdX4x35xmKrVvE="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"10.3.6":{"name":"autoprefixer","version":"10.3.6","dependencies":{"browserslist":"^4.17.1","caniuse-lite":"^1.0.30001260","fraction.js":"^4.1.1","nanocolors":"^0.2.8","normalize-range":"^0.1.2","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-3bDjTfF0MfZntwVCSd18XAT2Zndufh3Mep+mafbzdIQEeWbncVRUVDjH8/EPANV9Hq40seJ24QcYAyhUsFz7gQ==","shasum":"537c8a046e32ec46bfe528bcc9e2a5f2d87cd4c4","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.6.tgz","fileCount":83,"unpackedSize":195386,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6qY5NPeAb+yqLCbe9m1F2zoFZjaHGJun6uADp2Dud/AIgFTkVwrCFZxVRgTM/YgnhVGhGsy9JCvGHzH3IyYVrgkY="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"9.8.8":{"name":"autoprefixer","version":"9.8.8","dependencies":{"browserslist":"^4.12.0","caniuse-lite":"^1.0.30001109","normalize-range":"^0.1.2","num2fraction":"^1.2.2","picocolors":"^0.2.1","postcss":"^7.0.32","postcss-value-parser":"^4.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==","shasum":"fd4bd4595385fa6f06599de749a4d5f7a474957a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-9.8.8.tgz","fileCount":79,"unpackedSize":289279,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICF3wf18E9bJsvS0wsarN4K15RMcnraK0H29/gJzkwygAiEA42+6a4KS/hNczNcuI6uMDLqMVG4VWGUbW5MGiUrNpBM="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}},"10.3.7":{"name":"autoprefixer","version":"10.3.7","dependencies":{"browserslist":"^4.17.3","caniuse-lite":"^1.0.30001264","fraction.js":"^4.1.1","normalize-range":"^0.1.2","picocolors":"^0.2.1","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-EmGpu0nnQVmMhX8ROoJ7Mx8mKYPlcUHuxkwrRYEYMz85lu7H09v8w6R1P0JPdn/hKU32GjpLBFEOuIlDWCRWvg==","shasum":"cef2562058406bd378c94aacda36bb46a97b3186","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.3.7.tgz","fileCount":82,"unpackedSize":195292,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIBiLdiLjO7qWI6cRwdrLuOylZH4XC2o+gbHJ+gWfsNQIhAI6NxhNmICC3ciWQ9IWjhj7egB+IumGaOsonea21JdmJ"}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.4.0":{"name":"autoprefixer","version":"10.4.0","dependencies":{"browserslist":"^4.17.5","caniuse-lite":"^1.0.30001272","fraction.js":"^4.1.1","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.1.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==","shasum":"c3577eb32a1079a440ec253e404eaf1eb21388c8","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.0.tgz","fileCount":83,"unpackedSize":196164,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEJGc8lmGxjaIbYFAiFJBFqBaIC//hNrkaz9qXjT/XNdAiEAoDhjvokspKoDwqtxjFbQP5WnzabF/l7SA9Uy+DK/Mnc="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.4.1":{"name":"autoprefixer","version":"10.4.1","dependencies":{"browserslist":"^4.19.1","caniuse-lite":"^1.0.30001294","fraction.js":"^4.1.2","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-B3ZEG7wtzXDRCEFsan7HmR2AeNsxdJB0+sEC0Hc5/c2NbhJqPwuZm+tn233GBVw82L+6CtD6IPSfVruwKjfV3A==","shasum":"1735959d6462420569bc42408016acbc56861c12","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.1.tgz","fileCount":83,"unpackedSize":196102,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhzIsRCRA9TVsSAnZWagAA1yQQAJrUZvf8OsaCnQZp6rlx\nWl52wM4O2E483wD5D93/prB0ggMtPniTd2cmJL0ikcZXMslHYjd/83j1Tf/i\nYvfpWX9gHxYhrdq/GjMnqAu3HFeuw3wtXB+Wn7WYMx3lhalAeh31lvmO6UfI\nJRR6QPb5exn7HWQvPRP+XqnH8TkCKeQp4Y8wD32d7EVGqPE2HI6QPCo5242W\nYvNI2pouC2g8h2HatLzEiGuKt+gqlMSPXFygdik581i0y1sXhtuLN4Uj9a3a\nE0Zi4v7HEN3CNeUHZttiRPu4Ex5I+VLJsntUZkMwkNuzJwhgyZPpN9nsgVRU\nLusq/81XMcF9FQlFcs0Y0l1fcIIs28BNHAA8ZIUxjOx5vz0jPzAyWLlSFLYu\nZg8xX0jXbnrk2Ovy9fi0ThoLksT1FiBSQcj1g4230LMHskQDyo/7Pu/WdPB2\n0ZDjGaf3rp3fHzuWC8mmkjUwCKcf5duO9l4qXAooMoiDDUH8F6B0IivpOMOZ\nZ0E5CtRX5tkpWzUi0ZbtZ/NjP83kVehxi/cPDJdhLqxkvDhK+hOXvRZj7tx2\nAxrKeb/7DA7wP6OG1GqoiM/ZFXYcv9WdCyEgg9/r1sAtkRBXyH8JjiD43QO3\nBo2gl8A4a5IyhWT6L5cy7DQ8kFG82u8vRP0Lojgyf2ng8DAvr5yJ/z6/HU7F\n1smV\r\n=syX2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDginG9tT7vrUCt64ukUMK8Lf3vgENeOE5jh6gEHtlHwIgc4azhUj64t1P8qJ1B7c3ul5+RfqMQ+BEEKryxlKG+Yk="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.4.2":{"name":"autoprefixer","version":"10.4.2","dependencies":{"browserslist":"^4.19.1","caniuse-lite":"^1.0.30001297","fraction.js":"^4.1.2","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==","shasum":"25e1df09a31a9fba5c40b578936b90d35c9d4d3b","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.2.tgz","fileCount":83,"unpackedSize":196176,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2ELECRA9TVsSAnZWagAA4G4P/1W+paMBaIJ84M9MmtGJ\n8HeHVacE9pcuwiFcxHzrkFekP84UdRYpxmdWmsBL3nOISz/gLqy2z/S7HUzP\ngbQmI36cQ02xx2GT7mRDsngUIPdsZ00/0ylyzXVqO1vEOmBbT5UyZlBIitgk\nwrBtL0TvAMx3KOHoQNsWVPUEIcLqqX2CFn32N07TGbp5fvvnrjvjzOHy5Ywp\nrOJStmFC0co9WfIqFRRopyh7k0PjUT2UQ4WaSG4erAqc5/6KlpRC41Pm4+CL\nNVHc2h/ENJ1CpfPPG6KbrI91uQSXlRmBifqedE9ERIsJYmKdKH48sGLrqNzB\nCncV3N8UTA1EsSisou8qQs7RiMp1PmkHAXeJpSNS5lCTxfr9Eb5+BcpJ7arm\nE/Nmi5rcfFdQkK4F3JyXS13Ctcwesm7KZ+Ow9l7yM+ESwvp/mdmzBgUy89zU\nSbP/enCNDTdYlv1EoJB44uYC8HvrWUfuHP38d4Qkv5vHbDMiVZA9CPV8Umhx\n2EwftM6KWlAm5VzUXjcPGpchUbp/ICzyafGn058k1IKwbuoV6+CcQXh+7E3d\nazbBOFWo5wkyG2JTb2L4rZ1+n4y7RjinTYugvBM2RA0AUGhIGYF1y9hGzvb9\n7IAcfzex/AXhXz9WMcDsf6aRl+N4rDkiC8PP+T1rJVeG6rmu+KRI7a9s/ovt\nXDiJ\r\n=oXr3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBJhHTwKydmxTKfRXbH40PSaTmh7GVe9GNc14D53jwMoAiEApcbtzmRLaXTkjR7ZIROwMvf4MbNrHNkworVV5OYPUek="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":{"type":"opencollective","url":"https://opencollective.com/postcss/"}},"10.4.3":{"name":"autoprefixer","version":"10.4.3","dependencies":{"browserslist":"^4.20.2","caniuse-lite":"^1.0.30001317","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-3EIK6tHl2SyJWCoPsQzL3NEqKOdjCWbPzoOInjVAQYo/y/OCEFG9KwB5162dehG5GadiGfgxu7nrWCpExCfRFQ==","shasum":"d4b9358be607c30d1900c1412d0d668f98bb5a6a","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.3.tgz","fileCount":83,"unpackedSize":196298,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMNsYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr0QA//ZePI+Qxx3QgGXxstZdioJEOsT3uACtP3RJ9QVvWt+JGCMmAE\r\noXCCQeMk3NNbJJLtzsLvD1jIGVqV6p/I5wM804xpSZHtcqzz9RQLkpylzXnt\r\n5jfqNWcKvKcKs6cRe1NQ3j40oAqiSZ9mbzuVs3aQa/Pdn5hlVhJ5TaPzo8Nb\r\n3lXydbqqSDr1ZbJfGCsstU6/lXqtCJ/Zqi87X/giyHmE0wPCZahIotklSn7I\r\nqRyR+D5ZKtGawOsh1MQIbL404KOZvBAOYiU87Ja+6MtmIi7LyR4RKsMlIL+4\r\nTaWqBoHXTfDjt3dQDHRJRxoyoz/DiGMdJglI03sUSVzJCjDnR3xT3EJg6qYX\r\n8Mv8EAlzRda0kok1kA982mynM2OHisTKneQQKBS2Kzz3KYBSQzdK0+n3saEv\r\nt6R+K2ijdLp/4Zch4KQhHClqA840QeyxcDsa0qwEVTAG1slBG63TdnYucYTj\r\nXzDH4CPsPKeISFwajAR37x0OmC5qA43D51ldAp82C/DmOqPtZ8h8K06OiQRc\r\nUTHUNRatIkZACGZ8rlppgxYmCYNAiufV59Yeexaw8edu7WdU/o4AIvF4+sSs\r\nFHZBrJZpzmNFTyGCZHI61UBWadx/DgMKiZehmxsshLUviXqXhrClRZ/0bwnI\r\ncf/ceDVcb1QMElUlX9Eb45kYXtMwvNjfac8=\r\n=5vkW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDWsURCCdv2tEQFQOPCA4AwRZD/HvnyuHwjbU3iVO7jSAiEA2awFgGXHWJErmHIem/+CoBGV+9a6jL/VfAd0FC6Ngsc="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.4":{"name":"autoprefixer","version":"10.4.4","dependencies":{"browserslist":"^4.20.2","caniuse-lite":"^1.0.30001317","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==","shasum":"3e85a245b32da876a893d3ac2ea19f01e7ea5a1e","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.4.tgz","fileCount":83,"unpackedSize":196299,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMaJoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpstg//TisTH5VsavMoipr36MwKCJSgI2O4kCFzBdka7FScWQ7TuPCs\r\nCP8qdvkCvXzcf52KHAXaPOqv2NzXkj/4UtgP2Xew3K9UuRs2miDvzFQV1wl4\r\nJSfqWBpJrg8PbCeuE/hysFUOrIjn+05yhFojKbv/f6MC1XaAbUDL7uIQTo+Y\r\nfDmXuh2gFHC7IEGGjRCHDEP6yTOfx31QTzYuiVhRYDNrVCH4QvD5GdoOjP8C\r\nvHP2TuFEGl5jEEHrBmBkBsjMvLDoIXJYmCNlzoyPoWPpTeKTzDjiUGnoxAIX\r\n78jgbu6jIunscEDZ6Is8czhz58dt+NmoPcCZUz28xWOKYy9H1jQXRR4McNq5\r\nwQ6vVhyrdZKNpuJ+GyZY7qBsTuUL0FbA3ThuXaWO1czDltraegMdJuFQQwxS\r\nhchahANebyF6qWCf7hCsPh4I+NdYcn53cdoT7btXn9cHTp6eT5x4RJlCnZb3\r\n3xgc9MDFR3msF/M8vI/rWhVN6d6nk4eIbBOFTntwDgs/6dC3ij63JPFcs2Iy\r\n07XYK4mTewgTqBcf//QuAow05h0Dag87ayVTkPKr5HKZOpcEL6WD3+lis2Y1\r\nxSrSMQaOYURiiMvNqBbaQdnBPg1c3TtrU4uCFdvveXpvn2dvni189c3gEAxT\r\nIjlkjc0z5v0Mx0q6PqxcpoNduP4YlrZH4DM=\r\n=zTIT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGfQJY7FLbQ1DIwy/VGFeDuk2i6k9QV8++eOoj33U+C8AiEAsk/7vYplr899xBfpM8KS39djsTZ31rmgSVuV1S5lDTs="}]},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.5":{"name":"autoprefixer","version":"10.4.5","dependencies":{"browserslist":"^4.20.2","caniuse-lite":"^1.0.30001332","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw==","shasum":"662193c744094b53d3637f39be477e07bd904998","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.5.tgz","fileCount":83,"unpackedSize":196746,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEBpzhX7zt/KJ+XEtj1EOFqoTAbrajumym22nxX+mJGHAiATTzhOoXU/15E0Qgy/xhJSINRF23oGxlEgF9Yu1wNC8Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiZHGIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqkug//Va0ZPTUJknIZ7a2wcwS1geZiW6SEC2XjpIaIEV20ADPPVyq0\r\nfoJkFGi5iOjlX1yWBcshAYhEfX+9ikQLhIj78No7fglcHpHs/Z5/7Mx7x7Xt\r\nXYwtrOHsjhNuZlBvsQGVRolZfI80D85of8VnN0nkdjLZ8ijJon38BvkE1L6A\r\n8r4E260uELqKGpUTqi5bHvq0Ff2ky5hJeGgWKte1gJCdzaBpNS4sYNsZVXyo\r\nlHYarEBHs1rDnzaBoEz096jX3U2jWuraku7i1b6RqxDmbryn/cAkJl+MNami\r\n1v0WyKctV5Xtdrp9P1f0uRz5rmpB/RlQodBjyXg+per4Bn44rDEDBqgwVmJf\r\nADViJXhIlo3pvGN1PCashGrzfkE5BDECOBG+GOKqFeTUk0GBJyPzNzpifXQ3\r\nTTsZ5lihYuyfBl7OYYITNu5LqNpu61lryMHZ0tZ5XlhOESQTNjIkj/qy3H6B\r\nniVxnKx5gAgjyja8IIeci1Uarzkq/QxVFplL1NWKGY8ay8sWs6KpwInuiYmx\r\n+/iPKFif4ZEbovv1yL7pvDrDfAaA6t3ENRmch2pgy5NwZWB6ap4e4lEw+dpJ\r\nCbM7clm/xeLUJcYnAhGImUSpqGvLlNWl6DKE4zvoHp6p81gqZZwPrcubO/tV\r\nDNThELGJUGdXhQnMawwEdPY2f6jMrc03dMY=\r\n=pVZ/\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.6":{"name":"autoprefixer","version":"10.4.6","dependencies":{"browserslist":"^4.20.3","caniuse-lite":"^1.0.30001334","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-Rvzel0AZO9tJNm3ydySK80PpkWoEZTGC5bHUh/xbrP8qJCy08NFBwNGPcozy3d3SDIM0b2kNxw2K7jAIYFF01A==","shasum":"ce6eba3aea7c03adf0f6a907bd594fd170b3f0b6","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.6.tgz","fileCount":83,"unpackedSize":196961,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDCS4u5c9xg3ZRatX9CYp5dii568+fxyr0dnQaG7gA2yQIhAOS6sbCuhwr+LfIrn0ynzUx4x3EZ9J5DFKPFMvepujTi"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibxHIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqjCxAAksvP75WnSQMU+eZTzG1EG/W79jc2aZf8lSNd6Ri9qmXTeYiU\r\nTtzgGzG/rSHeA79zB8PnuZ4wJgW1tSivRqhOTWBB97eUtk2OVDtZjDdON9uJ\r\nRU7cpeB9ZHh7HkPB0Qgf45BBIu/wqs7lwKYgUZaNdxgQBaVHYLyuVyU7CAoo\r\ncxbXmoh1cPwYMiiuFx8tr5VN+7K/PuVvcydUGHN71lyTRpHB/+ojWapuk0UL\r\nTqBsWptBFr1bEwRgnS5xHUO8dUn0f14NTFgpuGy1H5TehhhBAuG+dbvkozJL\r\nULPRnlanSrYgtTa7rwTs3T/ZPbEiyFdeqlvkqR7lXatU5t1hjnJak8AWkTQH\r\nwD2RhpVy09dz3++FL0fMAQdeHen2dWsEeeKmCygHyAXOGuNyVwJgP5LP86o3\r\nDOkfWAxqJ+29flvph8B1QW5fq4c3tES2NAgoWYtPkuh+fnezi8MDRThRBq4d\r\nZZ36eseGMSIMgtKAbBKRLMst3jRNjFeNA8dmLLRC//zpJ7bzRcli1YjFKvXx\r\nRI1L5owZbj1zMvTWeUiv4kIpo7BycmZ8GCDDD959BPYqMGjq/fKIwVdz9I4a\r\nLO12Z0KTNWyMXjkr57dGg8EqXpIFv223vsbk+ePDv5e2spUMRB/YpP7Xs2lr\r\njwYMHRfIJTabgYOgY20UlOxwkdHTZAHGSi4=\r\n=dOHI\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.7":{"name":"autoprefixer","version":"10.4.7","dependencies":{"browserslist":"^4.20.3","caniuse-lite":"^1.0.30001335","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==","shasum":"1db8d195f41a52ca5069b7593be167618edbbedf","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.7.tgz","fileCount":83,"unpackedSize":197040,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG5DjPVoIwZIakMSJ/iHGgWHbgLs0ftj9rjhLCCFC88zAiEA36v8fBjUsPJTD/ETwxUAJE85UeuFUZu+VkNI8nGGybQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJib/KQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpj9w//bm7X9189cjPl7tAANki0XMiNQSu3xZ5dm7Al7qjR06EOkK4d\r\nBApMPoOAwg8lJtmSiFAofqCb7xi1VY6Q4zrp9D8/xolB9ROj7M6PHBPnQx10\r\n/ybZc7lteBGcTEpNd7jACSqUAJFKw9q6ppLCkaiWseQmkVa9MV9JTdEXXWU+\r\n62omAsQjnxzy6dur09pr96ZdTCaJrnXxSk9GOGz6uJX319SylyhmmVCGRVu+\r\nL1ScfZOOgrxmcjxR39pN0/0zbHRuR5MjeuxmDldft8CETMzMSexzc2G38tsR\r\nkiEZihnxXNXLFN0JTT1/ptGV+pcktQGJcTrFHFs++BTT8z9kKyZvHfpTrJSv\r\nCGI9R45PbBdWWnMZIonXuIZ68PfAwxT+p8xhDlZtxGCdEOjP648RIDQUBkeC\r\nFXukVHPjx8ULtTFpyByTwPiSrEpOYz2c0I2oP7czI8kVmBBPyZcSpp9VJZsf\r\nn8bxoufK8na3cXIdoS9UkzCcAyXOVly7CYdh1rY8nRGFco8ig8k3eNttUKGX\r\nYkQvL/x6q5K147IM9jmaaGNRZeOhvpz7yBptHOKb/hrOqSdGB3NrvlEvqB9S\r\n95cUG/Xyth4dIdvNoBxnV55XEsxCKCCLTPkvQI/ZPQRZiJgaVOP4feuZyB+P\r\najlPuyQ8q30r/utTvLw8SsdsqXvyhT9cnb8=\r\n=gPQu\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.8":{"name":"autoprefixer","version":"10.4.8","dependencies":{"browserslist":"^4.21.3","caniuse-lite":"^1.0.30001373","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==","shasum":"92c7a0199e1cfb2ad5d9427bd585a3d75895b9e5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.8.tgz","fileCount":83,"unpackedSize":197084,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCf145pAIVrKpyPaNKP3vLGBxZt6l4G+4fqvR+mMSBTiQIhAMSAAsxtlYPjKmUn0RJsd06MpbScN2RT1ZuBlzM2ODRB"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi470ZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqm6w/9HagnFhZmizkAyIzBgy49yliETxuWNj6ddSMQmLJ6nJ7uCNa3\r\nJYzBAIHAivHwhyLR/BcfRo3cN+YLbDV3vwnhvYcPwcZqha5ZiGfO5HCKNO9x\r\nZ4cakkeFS5TT8VSQV9luWUhBHOsgadf6WL9HLy+oVQlhQwxe7I+LyaeNF1Dj\r\ncMvwRQTJ4amBtTWceu683frW1rsJ1Ht8kCba9avnsM+uNnDifLwxgNeUHd4r\r\nSXTgHcXhOYjCXGcYhwPjtbUx4YUA3qh7JbgHilw8Oq/pn3xf7YHWLIqK5kIf\r\nj/0MiVOu5DFbK4R81x+kW9HW/If3caTf/SnF/+YvaCVqmGIcu+Hte7uJRl8W\r\nD6dzJ/CT+lUDsGqwPWuHo8nD+8p1gc8OfRgDd/FihEybGEJtdxZIdMcnM9JD\r\nmwnK3fjmamOZn7yLTfwf5wahZULibxlIDSwYbVSSzfsfy3aWZz/KPDOguR7q\r\nMTaRPdd1ipFtdntFTnhhmSHzS8N01jYp0kddSvqEgVRCbfyuGGUtrC0vAv0F\r\nmRuGIxcRawkow7aMdCfP7JuEvwmJZajlZzDHRgzKSJqdwu7b4bcoH6B4oHdy\r\nfSAk5jFxOKbH9vfb3+fHXMygIo8P8jsGOKuDhywwnnM74tsYzq9wgUKuj+Hh\r\nBEUCtxxZHz/fCUR5v4XKLLaQVskHXVYXVeI=\r\n=RD+I\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.9":{"name":"autoprefixer","version":"10.4.9","dependencies":{"browserslist":"^4.21.3","caniuse-lite":"^1.0.30001394","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-Uu67eduPEmOeA0vyJby5ghu1AAELCCNSsLAjK+lz6kYzNM5sqnBO36MqfsjhPjQF/BaJM5U/UuFYyl7PavY/wQ==","shasum":"40f932f7d0535264823882031f9254ea72c693e5","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.9.tgz","fileCount":83,"unpackedSize":198775,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQUUXhOtCvH671G32Pk14yrsLBH1nS2+sdzT8jgthvewIhAN5Xp2Xq2nN0omuT2/ZewrKShi6WMwsZuAzbpFXaonVP"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjHnGmACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrAcQ/9EwM7DBmOS0oWYyoAdEwF+XYdOXNd0xC8RhlpH/kUcJZ3uXKF\r\nJDGSIesoM4Xj3halRf4AYkMm8v8JG3AmjkmYKGPR1kcfIZgLRWAu7sfy1zmn\r\nXeBsyBsZmlw1D1nBCyalKXnA9Jj/1xkw4TAlr0nKyyqfjDJMfyu33IGTVFMd\r\n3OLRfjWLlEHhYvPbwPRaSKKplHqd88UZybCHsDLelygKPJXI5LasMrGa54xY\r\n3D3zPdW1rNCuEbeHvGCVisHRlACNlzXw4mCVGerY3ug1sxwB6kitqh1laudX\r\nY8ongT9n3WXWFWlzsx7jhgq5ZIK7dtWh4vah0x5U/ciRqInen7Y7UjzSN1Oe\r\nrtrdsfGzZUjK6c1OcQn/8oxjwu6EYOoXyJqYEa+bHmIEGjXfSyqlBROw3A9j\r\na9pVaU7QyduIO9yMHx8EH4N8vpPGn/NpjgnREdaDDmXFYzEEdcM78KCadSX6\r\n4NoTUxscIBayYMhlfMMyXLHMuINWNVtyyUPXNNIVCzkK1yK/biePNOuaClG0\r\n4ekMf+BjW199YK+SoM1lEOkAMGW8v1dGRicDNQk+wLebBi/vwhBTLpsLyh6o\r\nkEei9t9EBanzp6TKlGaYVwwmH5k4L4mkoo0cvLygM0hoIgzOk9uwzOVeNz62\r\nzVhkt4ooIUiocNTbHgL0aRs4jo6idC9aQe4=\r\n=VsF7\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.10":{"name":"autoprefixer","version":"10.4.10","dependencies":{"browserslist":"^4.21.3","caniuse-lite":"^1.0.30001399","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-nMaiDARyp1e74c8IeAXkr+BmFKa8By4Zak7tyaNPF09Iu39WFpNXOWrVirmXjKr+5cOyERwvtbMOLYz6iBJYgQ==","shasum":"a1d8891d1516155eb13a772b1289efdc61de14ef","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.10.tgz","fileCount":83,"unpackedSize":197266,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID3IwgbFM+Onuc/afgOSkZe6Rl2VwxgFMruwHWEKv5LyAiBKgoFdQNWDNAqd/rs7LXwGFKPbizOOIfKW9B/CZCvAgw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjIJlWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmql4g/9FNn4+qiWGhxUUb+Gv87swCI5gjxxfYDLFuicAOqjmaNJ1OVJ\r\njq4q4ToCLnOFvuebcr3CvvjSQZAPadvP2lRL8bChJm2jlb5VbEpzy4166GrV\r\nMqCz+B+kfiHuvzBOK9Nhyv6/0zIww+oQSGXkLANzoPAf2JAEFeqMZojK3git\r\nv3R5arJuPQlC15tUVGfahF5/dM5KYxQsY3PahIWbpquJAcW8sSH/JP0HWCMz\r\nlth50aOh1GW4X8/Ulgpu7uHoi71zXQzvKwnKQIgAPs3UGfK6BXK73CAGbyjH\r\n+BbNvzpE4xtQWGjd7sy9NJEgJQC+e0a+tmOsLfMkaBtPdvc0J3qrEqoElYkn\r\n7/H0QEsMMX3fqdXu3vNlVjM8Dt1IsQMzUcqGWpbjJc+gPhoDhjazu+eY4H/9\r\nz/eSUb0SxVXFIDNcXkeop0jcshakrljOYp3oWfa9em2Pj7rcgYgD/jqo3Y1Z\r\nrxZjMpvXF2FUtSCaFZA9swJw0IByhrdRmlxNZZ23Fdq3pnx6JYEdwpf8ZZsK\r\nsVxFb1t0vlieRjydy9RDHF04THsfhiTQ5n0L6zbSXj2b3tIWP4f4JCGJtGNR\r\n0QMQV9xyjntZPbSqpHcUbbmZuA5F0vAkSUssNfh1NQ5Jb2kbU27L7y9LgUyS\r\ncO93aKXtOPT1YSpzazlg6LGjSrkfkq7SdKU=\r\n=yZcY\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.11":{"name":"autoprefixer","version":"10.4.11","dependencies":{"browserslist":"^4.21.3","caniuse-lite":"^1.0.30001399","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-5lHp6DgRodxlBLSkzHOTcufWFflH1ewfy2hvFQyjrblBFlP/0Yh4O/Wrg4ow8WRlN3AAUFFLAQwX8hTptzqVHg==","shasum":"835136aff1d9cd43640151e0d2dba00f8eac7c1c","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.11.tgz","fileCount":83,"unpackedSize":197913,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCPY8/Gu/cmy3VqUaWbpuwJj3njdtzzF2as8YeCDHDieAIgHkQksoKr3KJc6PQ24OVL+w3Z9F++nHLBYKe/b1RX290="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjIhU2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmosKw/+I3sm6jaAFro59N+WSLpVULjih1snDY2ISiPtZTs8nmvhnvN7\r\nIeNxkwx1NbYDEZa8uwj9DE6yYsQ9Ey5WZ5XaY2eCPrOI0mqClsb4U4V68kdl\r\ne/j5DbTzoGPxjnqY4aJa/DXqudDSnKKeI1lshMmoGQWMfc9ssaNRUYjQhceb\r\npNAe7LYPGXDQ9bgMvLvPTdst3HL12Kbjvi0uQFJHTqC9/zFA+SojwhKuqVLH\r\nIj4TmX9BgmiDtp89R/d+Qo2L4UjiXmFgDZ/qmOCdAwKvSuLVv2v7bfWbJMiq\r\nMbKXlc7yFXFP9cmgEAKzMroq92FKWrpBxCL2LC/Ic5GcqdXmn2+/3u9Ozqqi\r\nE6/BjKopu+gkTS0WO4P9Aub0+R6Cwuer2CPjQDy16asovGizXMxRkzSqacTw\r\nRvpn9kqzbU4p+k++3EMxjlNF7sG1BNnn9OqFNTpWkqEpVJKJ7vMy+oX8dwM7\r\nUsSB7sBylI0Wb2YU/CPrA+dnv7gB0LrafzjDGYZCf/ZKMQ9DnKm3T8YyiQDz\r\nvA95EhYceGYNAb0tkX+Ne2e7Fg4zoqI812WBfU5aQeccSr8XpYw6KxhCfGIS\r\nt7qto86wk0SYORd02ztlIik7eHistmAj9+8r9YUe0vAAHhWxpHrsb/mZ7+3a\r\nTuzqIlwVKoozBLsamoeAiE6Qp9JPGAg8Eg0=\r\n=1rDp\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.12":{"name":"autoprefixer","version":"10.4.12","dependencies":{"browserslist":"^4.21.4","caniuse-lite":"^1.0.30001407","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==","shasum":"183f30bf0b0722af54ee5ef257f7d4320bb33129","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.12.tgz","fileCount":83,"unpackedSize":198645,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqtwnUggjMD8Zwow+hyxD78ZPCcVA0ibQpTM+XVhgZGgIgXikrgwmUOq4hLNLJiSiiJbyKTWLxSVj8R/CQYYFriTM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjKkZiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoSWRAAiIjw4vOy5fJVhlZNCphlofEXexpdEfvvPVJrQF+U3toZfvz5\r\nG4pYlQV8JpMAe8XIjTiO5pTHzpvxAw2uQ9LgsntyIdkFt7Sz8EEpBLMWQRPB\r\nSi7l/DI7NMDXx/KQdcovAuf8GgoqFOYk1zOCLQMV+Erq77v0ZLv42wgfja55\r\nCEDF8cKZsR1Fc4vlWze1NoYnWBs9FXLjpnOfiR1JTlcR3JrTDubWVeuzjKST\r\nou2upnL3WN+MxdAOtefMNruTy1MUmtuTN3v771d0m0PItAb11mXLV72rqLtu\r\nzc88ju3Z/O1CTpv6AROl37METrLrfOUf/bJMnYXUnoGRReqrTecE2FMrnZAu\r\nIwLUC3455J7g9UGOgkhBvTy6y6v/I37LKGf0B39A3S9K6CBXdd+nwesaGI7Q\r\nt8Yq77T8X8bvwCpXhyThR7C8m2Q1p8Mw6djgzbxOYdkjQxZzSqSoRMLPJTMz\r\nr5/GipeMAK1CBabfmoN5dbcMhgHlp2+iiYGQDqejT75zxnlUzclJZKfdzARI\r\nHjl+iGtDjWbNovKcwqwcBx1+zd98CeIaTfNPOmY3N+fAYYdsSw2BxAD82LvU\r\nRXa/Utx5zt3OXefvQM+WQ/wc0ptRgdmMS3zEMmhyRbli+B9ffVs5EJQ0//Z6\r\nFF5YvE7W+cu+baf2crBJ4yPU6jiACAFgN9g=\r\n=21pI\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.13":{"name":"autoprefixer","version":"10.4.13","dependencies":{"browserslist":"^4.21.4","caniuse-lite":"^1.0.30001426","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==","shasum":"b5136b59930209a321e9fa3dca2e7c4d223e83a8","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.13.tgz","fileCount":83,"unpackedSize":198690,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLw5omiihNPtILBDufB85TzIApalt7FS2p8UgVOL2z9QIgIk9C8puNSyZF0tbOOUuAJPvpK1A/EV2/mI+gXfH1wO4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjWupsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrNDw//db7cQ3WUDo9hfMC4IIIHw5mS29JewvO72nxVBQVIgGaf4dOr\r\nt1QLdYaL3XOU0TD9k4ayqxyvXcCdpEWoGPNqmCQ9N56CI86cguXCK9HZ1A7K\r\nFyEj9yflSFsfgdSxrR4AY/j6MTfrVDAyeuYJVp7DHd2Ui+P2s+81SfX8aJ7t\r\nnQOe8de1NhKbflAwRUbbQS33CtcPjwWX7pztZKODwbkqBTM6Mas9Rm40Ohc/\r\n5XGWkJeI07G4AlAT+zCZfU44DCFeyQyqhDuOJlxusN1Jeb5HJZ7xLGcduZOL\r\nG8frhxaCLeh1jV9hGVsoQegbknDjihjvVu3NwTZ5Qei9yrxbQ09UKrVGPlcs\r\nXXgkApPBgFiGRbCUqXdyNbzGlOGlHVbFdGSDsXJIDGIk/jTMcdc2aPVdqV7m\r\n6kGWISr5ykMUJtYUq7+rk+YczLnSzL0ILU3mj3WQp8MNtRdXjz+R8OjeBLIU\r\n2mPvVfIgZZUuVbBIGQfbzaTeGspDXQzyrxNtAFGqStWpbOUT04qfDye1TV8X\r\nrHZTq4LHViQWVAwBtH/VMxKbQdxrLx4h3VSNRTBcTauvo9OPh4kegCeAbwzh\r\nOXGLRrt4uc9+Tvm6/LQj+IQ+reJNjqrOhBN65AU2yRU8+Yd0Gc1TKlTkOFA5\r\nzeKQjFUTP/5k0wTb8C+gBk5ykwShotdB6rY=\r\n=vDT1\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]},"10.4.14":{"name":"autoprefixer","version":"10.4.14","dependencies":{"browserslist":"^4.21.5","caniuse-lite":"^1.0.30001464","fraction.js":"^4.2.0","normalize-range":"^0.1.2","picocolors":"^1.0.0","postcss-value-parser":"^4.2.0"},"peerDependencies":{"postcss":"^8.1.0"},"bin":{"autoprefixer":"bin/autoprefixer"},"dist":{"integrity":"sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==","shasum":"e28d49902f8e759dd25b153264e862df2705f79d","tarball":"http://localhost:4260/autoprefixer/autoprefixer-10.4.14.tgz","fileCount":83,"unpackedSize":198756,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbaPVpk/hRBScv7vP4h58dCbdZctLzVGOSM40BEdLIZgIhANmKh9JUosI3TCNjA0Rgf65I78+qL4Ik60ZfP7Nz4HY8"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkClKvACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrPCQ//UACWicbRKEnz0WMamKne+Py6jGL3SxUzymlmPvlsxKcI/4B6\r\nPvU57CyH4E1jlk/NMXcDKX9TMMkL8wgrTw1kFW8/X/kEV3eb/ioBo9dVDfs1\r\nF9nE3UH6wj9x7XoJ7HiXAb8wgAXlNh/UXIRYz0NOcWbol+MSFTIUvWuEapYa\r\ndFg9T1WKI5/GzMoJUw+3D+f2MHwTQjLqHJSUYsVa82OeHD3ZINSsj4qBhgLD\r\nG3j+TQIU8N3nPO/7sCHErgXY3thR519q+Lfw+/5oW//kf7H9hp4e5PUYICWS\r\nJS0PXSwXmHHgpfK6//naPfqAM05tsXL6ioR3qlTusw7vMXaSC4l1EqzaNj1n\r\nfh5Ku34vwp3/blMGZIIHCkfiCWzrJFqg5NywXagJdvo0A1OzzucW9DI5Jmvy\r\nCPyJ0pOvuILGEOhm2t/yQ6fPGbg7TI4V5C7nefS/401IQPR2ee8SRr4foaV7\r\nxqtAD8Tikq0PTuAK39uEWSpywOVTZ4lvVm7Le/uNiNaP+28FC6vB8IuCQ85q\r\nh3HD5XQDPyf3xz26SbbOfZImysSsSEbxVfnhF6UKsPBkQrWkhx2zQrjB6pz+\r\nln6T6ZQjQcZiF5Vf8cW81hEFB61d2/+mUJHUpkYI0n6wMTr0ih4DgsmCa62G\r\nSSKml+YGOLmnouBtf56v+/+5cw3ljXmJT7I=\r\n=wMzp\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^10 || ^12 || >=14"},"funding":[{"type":"opencollective","url":"https://opencollective.com/postcss/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/autoprefixer"}]}},"modified":"2023-03-09T21:42:07.794Z"} +{ + "name": "autoprefixer", + "dist-tags": { + "latest": "10.4.14" + }, + "versions": { + "10.4.14": { + "name": "autoprefixer", + "version": "10.4.14", + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "dist": { + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "shasum": "e28d49902f8e759dd25b153264e862df2705f79d", + "tarball": "http://localhost:4260/autoprefixer/autoprefixer-10.4.14.tgz", + "fileCount": 83, + "unpackedSize": 198756 + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ] + } + }, + "modified": "2023-03-09T21:42:07.794Z" +} diff --git a/tests/registry/npm/balanced-match/registry.json b/tests/registry/npm/balanced-match/registry.json index 4c935dd596..1dc1cf15cf 100644 --- a/tests/registry/npm/balanced-match/registry.json +++ b/tests/registry/npm/balanced-match/registry.json @@ -1 +1,80 @@ -{"_id":"balanced-match","_rev":"34-4b79c477b535c95b4e41227edc231cc0","name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","dist-tags":{"latest":"3.0.1"},"versions":{"0.0.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"tape test/*.js"},"dependencies":{},"devDependencies":{"tape":"~1.1.1"},"keywords":["match","regexp","test","balanced","parse"],"author":{"name":"Julian Gruber","email":"mail@juliangruber.com","url":"http://juliangruber.com"},"license":"MIT","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.0.0","dist":{"shasum":"86efc32ae583496c1c1fbb51cd648de0363ebb03","tarball":"http://localhost:4260/balanced-match/balanced-match-0.0.0.tgz","integrity":"sha512-daYFGv8RHJKIcx7l5jAzeS86+pMEgTAcbF7Q89qnrgRVI1GEDkuGABNGzkcWYrUwUZJ4+uUf8hF4n3SZMIPVOQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHVHvgnAs1bDFoDI6+/pz7mkkZXVfz8thHg0hQ7Y9K/8AiBABPKzjsOSHdHyBJ6tGAMBNjzJTn1XASzfvfo3CnZfAQ=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"0.0.1":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.0.1","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"tape test/*.js"},"dependencies":{},"devDependencies":{"tape":"~1.1.1"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.0.1","dist":{"shasum":"2c408589c3288fc8a152c535ed853f77763899ae","tarball":"http://localhost:4260/balanced-match/balanced-match-0.0.1.tgz","integrity":"sha512-obnFpTIt83MxrUxnHfs4npfChWAw0YcBQui+hI1awrVPzIqpKKkQ7KTunVRKAfauTptPQXZohaPs1hf38HJ05A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCO2l/CrUtV26QU2sOMNhCk02ZePiXNQy7szGHJTneWmgIgNhB9Yc4EEGiKzMSbdGAEskqxf6DeIZLLX63/pzCdMrE="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"0.1.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.1.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~1.1.1"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.1.0","dist":{"shasum":"b504bd05869b39259dd0c5efc35d843176dccc4a","tarball":"http://localhost:4260/balanced-match/balanced-match-0.1.0.tgz","integrity":"sha512-4xb6XqAEo3Z+5pEDJz33R8BZXI8FRJU+cDNLdKgDpmnz+pKKRVYLpdv+VvUAC7yUhBMj4izmyt19eCGv1QGV7A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIADDYF41QH1NuQ+/2uuuSzZelNXhFB1Tqi2YjQq7OuYaAiEA2BMkJ/3Tbk/knnCvb/33vauA8Rw/9xhG5PA90ipzB/U="}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"0.2.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.2.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~1.1.1"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"ba40ed78e7114a4a67c51da768a100184dead39c","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.2.0","_shasum":"38f6730c03aab6d5edbb52bd934885e756d71674","_from":".","_npmVersion":"2.1.8","_nodeVersion":"0.10.32","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"dist":{"shasum":"38f6730c03aab6d5edbb52bd934885e756d71674","tarball":"http://localhost:4260/balanced-match/balanced-match-0.2.0.tgz","integrity":"sha512-kuRgl0wyQa2pmUzVVyVQp0E04p//9u7J6Hi0Hd7fpF2Le1waUYUPmOcp6ITXNBYtBfzu9zw+aTG5eLLfYWHd1A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDorE0C4ozrLlU3/RXjoBGDnTQ1vGfaj6q66FYyGhfNsAiAWgloiwUeWMBJxB1SfnfDam7lkrmul37OR/Jb9PSXVQQ=="}]},"directories":{}},"0.2.1":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.2.1","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~1.1.1"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"d743dd31d7376e0fcf99392a4be7227f2e99bf5d","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.2.1","_shasum":"7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.1","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7","tarball":"http://localhost:4260/balanced-match/balanced-match-0.2.1.tgz","integrity":"sha512-euSOvfze1jPOf85KQOmZ2UcWDJ/dUJukTJdj4o9ZZLyjl7IjdIyE4fAQRSuGrxAjB9nvvvrl4N3bPtRq+W+SyQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBJ3wjKXLgAZjSqy9mOktUcOqNoQh8JSEPhMyfNsbo5hAiEA8V3Y/Vugo26oLm+5dp6W9C4PB4wKNnoPMiESz7Lj3yg="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"0.3.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.3.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~4.2.2"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"a7114b0986554787e90b7ac595a043ca75ea77e5","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.3.0","_shasum":"a91cdd1ebef1a86659e70ff4def01625fc2d6756","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.1","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"a91cdd1ebef1a86659e70ff4def01625fc2d6756","tarball":"http://localhost:4260/balanced-match/balanced-match-0.3.0.tgz","integrity":"sha512-bgB9RrUMd3G7drkg5+Gv+dMZTUSFbfrrp61qsQGlTdCdIPqdzF9UG2G5Ndlg6zR3ArNeGGXMIYSYFZRRtZaT9Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCFVZKtSpYwgtaTT2Kqf1h7zkwzrSJagLcLLzTDM+RwSQIgPQSY7OnNwUniyQQvJ0f8cHvHD6YlDcpo6cvfszyv234="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"0.4.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.4.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~4.5.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"d23ba945af2e80d035dde2a9d7e4ec62efbd440b","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.4.0","_shasum":"84818b70e91d9ac8b4d77df20e9239e80c025089","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.4.1","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"84818b70e91d9ac8b4d77df20e9239e80c025089","tarball":"http://localhost:4260/balanced-match/balanced-match-0.4.0.tgz","integrity":"sha512-0fxU/CUKHz4ojATahMymHO3MC7xccEcNISC+fNroLYitQjVUP3rEAwV8lsviJMjTlrLza4cH/TCH9kBHvSDf1Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIARCRZyc0v8nLUsZoBLVE8r0ayj+33hDa41xwLM8c7m/AiBnlZGwQD0ZJGpLfKojVsbLVxsG7CKYEgLd/AL1D791KQ=="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/balanced-match-0.4.0.tgz_1460018817576_0.08597791171632707"},"directories":{}},"0.4.1":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.4.1","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"~4.5.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"7004b289baaaab6a832f4901735e29d37cc2a863","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.4.1","_shasum":"19053e2e0748eadb379da6c09d455cf5e1039335","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"19053e2e0748eadb379da6c09d455cf5e1039335","tarball":"http://localhost:4260/balanced-match/balanced-match-0.4.1.tgz","integrity":"sha512-vgW4YcTHFsmsL5q8x0ovPQfwzEdFCoQXv6HBse+E46uZNwA+lE5+V1G9ap3IaUz0oM9JPFiJ8tnDZjqdReFSqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAytkJMWi5v5v1dWj3sCpqNsfuHH8wnB0+ogc3MURhfqAiEAn3aM52dUjjGxYPD6DhQHUkMuJlqw/RQRUZbTpgvycUk="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/balanced-match-0.4.1.tgz_1462129663650_0.39764496590942144"},"directories":{}},"0.4.2":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"0.4.2","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test"},"dependencies":{},"devDependencies":{"tape":"^4.6.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"57c2ea29d89a2844ae3bdcc637c6e2cbb73725e2","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@0.4.2","_shasum":"cb3f3e3c732dc0f01ee70b403f302e61d7709838","_from":".","_npmVersion":"2.15.8","_nodeVersion":"4.4.7","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"cb3f3e3c732dc0f01ee70b403f302e61d7709838","tarball":"http://localhost:4260/balanced-match/balanced-match-0.4.2.tgz","integrity":"sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwR6gkoRTPsOQQNI/+S71bhdZoeEMHWYyKDMsSzVwixAIhAIllfa3v0fyWYS51UxB+4wbQk2LCtxJhWSjseBejXl9z"}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/balanced-match-0.4.2.tgz_1468834991581_0.6590619895141572"},"directories":{}},"1.0.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"1.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"make test","bench":"make bench"},"dependencies":{},"devDependencies":{"matcha":"^0.7.0","tape":"^4.6.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"d701a549a7653a874eebce7eca25d3577dc868ac","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@1.0.0","_shasum":"89b4d199ab2bee49de164ea02b89ce462d71b767","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.8.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"89b4d199ab2bee49de164ea02b89ce462d71b767","tarball":"http://localhost:4260/balanced-match/balanced-match-1.0.0.tgz","integrity":"sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDN5U38zzaYjzNgiGzGDWu9nnWtcbrB6JezTyfWwriLJAiBjOrytimT7VRffO2Y/7LWXIOmsJFjo5toVuTAXyucXZg=="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match-1.0.0.tgz_1497251909645_0.8755026108119637"},"directories":{}},"1.0.1":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"1.0.1","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"prettier-standard && standard && tape test/test.js","bench":"matcha test/bench.js","release":"np"},"devDependencies":{"@c4312/matcha":"^1.3.1","np":"^7.4.0","prettier-standard":"^16.4.1","standard":"^16.0.3","tape":"^4.6.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"91e65ccc2a89ae0d81bb57e287131011f41a20db","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@1.0.1","_nodeVersion":"15.9.0","_npmVersion":"7.7.6","dist":{"integrity":"sha512-qyTw2VPYRg31SlVU5WDdvCSyMTJ3YSP4Kz2CidWZFPFawCiHJdCyKyZeXIGMJ5ebMQYXEI56kDR8tcnDkbZstg==","shasum":"4f46cf3183a02a6a25875cf9a4240c15291cf464","tarball":"http://localhost:4260/balanced-match/balanced-match-1.0.1.tgz","fileCount":5,"unpackedSize":7083,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbBCwCRA9TVsSAnZWagAAyIwP/3NssbM+7PI+JjP3izQc\nc6+ePWLbBz5smmilqFyHnv8z2Ouv5PBBO6EVyyRX80DPy7KPPFUFXNOS00Vw\n8yHZ+EyaWzamt6yVDRNxx2DGf8jDzB1Axh8NwkIQKfnwsBxt/wVJFojLo6Rn\nuGOXhy2n5nbZ1JavWL8aquTx/6maPoyEu3omopwrDEhxcAmz50czBRPb8sPH\n+fQYl9SgkJdMUDAUNr65pj77v+gR4glViT838GWsoa32f/Wt/e8Na034+IeU\nzSwnEmA0cvGj2/ubkiAifPIshIXDXcEm0aSRn5lrCzmInGKtD124F5vinY3d\nXZ7CD1YGv2zQ703HZLVhAugd2/4l1Ac3Uf8bGSOFc4ipzwYXUOH8OUlIWKDU\nQ/ktMaueuBENMU4cs/ys3th5qZQFmv0vT8L8VAC1ybJ+tDF80bvvNnIlhwgb\nj2elsnB4uj5DjvDq/hjRHLODAXSJWnikm9gDtRHMcIOy6tJI39UIRfG6br0K\n6MqtN7TE4UkkkPaUEEKPv53fhABsCkkhWVKd2oW04i+hn53Iu7FZm2Pgx5yu\nC82gcej2byggT97RO9PtiNbCtkvJXm52I5dg6lIJ2/Xsqb16O///kgmD7n8/\n8u/9HNauhKbhg0wGuZJgcy0hBbOYFSJOfM+S26UHADWiPcEkJ4fc7nlqG9vv\nmMTG\r\n=ftTQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDlcpMP2h5zkcX0B8nr6vV/qhflEMPCULRG0/JGC4+B3AiAQ6pXxP1MfFPEU2M5/jichFV38qfuD5MdVDPrp4Wu9eA=="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match_1.0.1_1617694895808_0.352537932704025"},"_hasShrinkwrap":false,"deprecated":"this package has been deprecated"},"1.0.2":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"1.0.2","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"tape test/test.js","bench":"matcha test/bench.js"},"devDependencies":{"matcha":"^0.7.0","tape":"^4.6.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"c7412e09b95d6ad97fd1e2996f6adca7626a9ae8","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@1.0.2","_nodeVersion":"15.9.0","_npmVersion":"7.7.6","dist":{"integrity":"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==","shasum":"e83e3a7e3f300b34cb9d87f615fa0cbf357690ee","tarball":"http://localhost:4260/balanced-match/balanced-match-1.0.2.tgz","fileCount":5,"unpackedSize":6939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbFk9CRA9TVsSAnZWagAAZCkP/2oCPlLyH1O+2fxJepxC\nP64dIPH4FmdtcuRV6m9JSSnNayjLyl7KZSkzngJveJAVMwBH2oSO40HVruAc\njNGdawU0sm41Tvkxm0K9AhiT5pfqBHv6KBj/sR5+2iF56zAM7pxrc8eTsgj9\nHBAYq5ZoePKf+Kki77ilWwK1Z7VXekk3KNgPd4jsbZ58JGL2dLVmqJcOPAfx\nTRECI9NV5oyHl+EsOGnMnAB8Z7GvNH+/sVo5lWZkldStJDjlj3mZq9fxMo5I\nw/2pmVPI8dvYYA6r3mp55YYDyvWA49CoRgTHXqEy4tpHmmdTAdB2Je+3j/n0\nvbJm74Ab6CnZnwa9Oaowz+VcKkcczXICTxPj0D+ddvVksD+6VpnAz79Jyia5\nqApDNXnYv+8bdnMwhnA2tQ0vz10HANuZ1xfpXE9Yy4Py/1LsTvExovYsie1G\n9RQ1GkIpGwwyOuzbDqHtrRjduAy35VNtIw2nQTCRLz87w/7DV+RbTvaT1Fp7\nb4WQN9z6BoX0Bl/Qi8PXTDN5J8M83MsRThoYm20M0nAVeGbxrfHTMJoXvxF9\ntlHuV3E7W7x3lvG0za7wLn9p76uOzxDX8Osr5POJ/GpEVciz0PWcbHQHFHUm\nxB+x3O0C9eAdKW/9/7/YA9zMqdqcMuwg6f26neIYIk10oZQyRriBoV6OZtIy\ntw1n\r\n=eH8s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHRQpAKwqTgs0SDP5KcV7MzsuTPMEkHeNqJFBOy5hYMwAiB/QgzhE/4zo/h6mn5Sl6u4YP0UZKqPYCZe5GhyLntdKA=="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match_1.0.2_1617713469141_0.18827857838975826"},"_hasShrinkwrap":false},"2.0.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"2.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","scripts":{"test":"prettier-standard && standard && tape test/test.js","bench":"matcha test/bench.js","release":"np"},"devDependencies":{"@c4312/matcha":"^1.3.1","np":"^7.4.0","prettier-standard":"^16.4.1","standard":"^16.0.3","tape":"^4.6.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"gitHead":"1c56fa33180a54e0e69a3fae9d60c191e74c4174","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@2.0.0","_nodeVersion":"15.9.0","_npmVersion":"7.7.6","dist":{"integrity":"sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==","shasum":"dc70f920d78db8b858535795867bf48f820633d9","tarball":"http://localhost:4260/balanced-match/balanced-match-2.0.0.tgz","fileCount":5,"unpackedSize":7083,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbFnBCRA9TVsSAnZWagAAnBUQAIwSae9EWp8mawlco66Y\nsYcwEHdv5Cc7shxnCSIeYYGgowelCQgirX5QrJHKmPEj10UfrJJvCnHu4uMC\nvyztZIDLxtg3xWMaTObZfVRCO23S90Po81YDJBvOtrRciRGqQmZ+HWmuRYDu\nI7rtvXMK/yc31dnkOjTPBd6FjufQRfH+OyS1cPJP5/ZyXxZsiNi28jIDe/1R\nKETSdx279AtQo+vUL6uK+OnKF9Rxo8GXeabM+4dRezqWtYW1B2RugEKuhSk5\nlwXOrjJEioG+TaIozgXY8X/0hiyRW6mCisMtFE3aYxhgp/WxPwlyNV6k+dtz\nqsnrwPLlZyVg0IX16MbHXJBbr0yvynSbN2t1eUZ1kX36wquzuIMDk6H/1XNY\nhhAydNkpFGICPedeLkFVvVFjpx+zeVryhMj3sq+P5FYdIDcHkhxFDX8s3cfp\ntIrtY7Y59hMsdDnIUwp4qqOvxG7DuuEFprWG38BIVCa0hE3yA+vQ5+ACUmBo\no6DM/RUgXwuqFghoYRX00fxKSedVIWfX8f6nPyG0WhN5svfdPlC/0qayvE0r\nGllsfW6la8n1yVN8jey9we2x0OdLutG4rYB5gEzl91DoLJjP9TopCdNnZhhC\nuM3d6jLW/BVRgPTU7z6YBCXiESw0lntphDMotVZBPeXz2CTqGTNbE4vKAJq4\nROwK\r\n=8h9J\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwPXtClY2xRtpUhfN8Otf+E02dH+DO55UcSuJ0vi+LrAIhALiaQS2V+1k2zJKf/lBKrxIRH8shIVFuYbpjfo7ABZ38"}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match_2.0.0_1617713601488_0.5951607210108762"},"_hasShrinkwrap":false},"3.0.0":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"3.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","main":"index.js","type":"module","scripts":{"test":"standard --fix && node--test test/test.js","bench":"matcha test/bench.js","release":"np"},"devDependencies":{"@c4312/matcha":"^1.3.1","np":"^8.0.4","standard":"^17.1.0","test":"^3.3.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"engines":{"node":">= 16"},"gitHead":"7faf963591218df292de64f542bccbb5a85de93f","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@3.0.0","_nodeVersion":"20.3.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-roy6f9Ri49dpBe1EUBikUsqhJfEVlW+oLV7JFwGm17PdkZ81xVreEYNEIsytl9NQ6fvvvJRXHyVe60O5ve6i1w==","shasum":"c47006ef8f61f4c7ffbecbd69b2fe9c56fb8773c","tarball":"http://localhost:4260/balanced-match/balanced-match-3.0.0.tgz","fileCount":4,"unpackedSize":7127,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHfh6+e4G478Rijxgz6qRQLhcQiHzmBYVuJ1mzlE6FC7AiB5VfbD/aHfrYbKC3EUC85l/DO4yGx4JK96abS4fwZ5bA=="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match_3.0.0_1696493478956_0.8748467054054856"},"_hasShrinkwrap":false},"3.0.1":{"name":"balanced-match","description":"Match balanced character pairs, like \"{\" and \"}\"","version":"3.0.1","repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","exports":"./index.js","type":"module","scripts":{"test":"standard --fix && node--test test/test.js","bench":"matcha test/bench.js","release":"np"},"devDependencies":{"@c4312/matcha":"^1.3.1","np":"^8.0.4","standard":"^17.1.0","test":"^3.3.0"},"keywords":["match","regexp","test","balanced","parse"],"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"]},"engines":{"node":">= 16"},"gitHead":"bb2612142d2d40f46636319ce50197deb6254425","bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"_id":"balanced-match@3.0.1","_nodeVersion":"20.3.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==","shasum":"e854b098724b15076384266497392a271f4a26a0","tarball":"http://localhost:4260/balanced-match/balanced-match-3.0.1.tgz","fileCount":5,"unpackedSize":12334,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEHsKepAWqy0XBNt9lRc2IKfkNV2LfAzNNev+dVSGip1AiEAvZJxo1yLwJNtvZRe+9qcUinlJ6fC6btDmG+KvqyP4+g="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/balanced-match_3.0.1_1696685643512_0.5915305955862984"},"_hasShrinkwrap":false}},"readme":"# balanced-match\n\nMatch balanced string pairs, like `{` and `}` or `` and ``. Supports regular expressions as well!\n\n[![CI](https://github.com/juliangruber/balanced-match/actions/workflows/ci.yml/badge.svg)](https://github.com/juliangruber/balanced-match/actions/workflows/ci.yml)\n[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match)\n\n## Example\n\nGet the first matching pair of braces:\n\n```js\nimport balanced from 'balanced-match'\n\nconsole.log(balanced('{', '}', 'pre{in{nested}}post'))\nconsole.log(balanced('{', '}', 'pre{first}between{second}post'))\nconsole.log(balanced(/\\s+\\{\\s+/, /\\s+\\}\\s+/, 'pre { in{nest} } post'))\n```\n\nThe matches are:\n\n```bash\n$ node example.js\n{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }\n{ start: 3,\n end: 9,\n pre: 'pre',\n body: 'first',\n post: 'between{second}post' }\n{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }\n```\n\n## API\n\n### const m = balanced(a, b, str)\n\nFor the first non-nested matching pair of `a` and `b` in `str`, return an\nobject with those keys:\n\n- **start** the index of the first match of `a`\n- **end** the index of the matching `b`\n- **pre** the preamble, `a` and `b` not included\n- **body** the match, `a` and `b` not included\n- **post** the postscript, `a` and `b` not included\n\nIf there's no match, `undefined` will be returned.\n\nIf the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.\n\n### const r = balanced.range(a, b, str)\n\nFor the first non-nested matching pair of `a` and `b` in `str`, return an\narray with indexes: `[ , ]`.\n\nIf there's no match, `undefined` will be returned.\n\nIf the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.\n\n## Installation\n\nWith [npm](https://npmjs.org) do:\n\n```bash\nnpm install balanced-match\n```\n\n## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure.\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"time":{"modified":"2023-10-07T13:34:03.844Z","created":"2013-10-13T12:26:00.713Z","0.0.0":"2013-10-13T12:26:03.806Z","0.0.1":"2014-01-08T10:12:05.995Z","0.1.0":"2014-04-24T12:44:58.954Z","0.2.0":"2014-11-30T09:50:01.532Z","0.2.1":"2015-10-22T13:13:58.153Z","0.3.0":"2015-11-28T12:37:27.893Z","0.4.0":"2016-04-07T08:46:59.982Z","0.4.1":"2016-05-01T19:07:46.040Z","0.4.2":"2016-07-18T09:43:12.562Z","1.0.0":"2017-06-12T07:18:30.595Z","1.0.1":"2021-04-06T07:41:35.956Z","1.0.2":"2021-04-06T12:51:09.276Z","2.0.0":"2021-04-06T12:53:21.623Z","3.0.0":"2023-10-05T08:11:19.087Z","3.0.1":"2023-10-07T13:34:03.685Z"},"author":{"name":"Julian Gruber","email":"mail@juliangruber.com","url":"http://juliangruber.com"},"repository":{"type":"git","url":"git://github.com/juliangruber/balanced-match.git"},"homepage":"https://github.com/juliangruber/balanced-match","keywords":["match","regexp","test","balanced","parse"],"bugs":{"url":"https://github.com/juliangruber/balanced-match/issues"},"license":"MIT","readmeFilename":"README.md","users":{"dantman":true,"klap-webdevelopment":true,"scottfreecode":true,"arteffeckt":true,"puranjayjain":true,"flumpus-dev":true}} \ No newline at end of file +{ + "name": "balanced-match", + "description": "Match balanced character pairs, like \"{\" and \"}\"", + "dist-tags": { + "latest": "1.0.2" + }, + "versions": { + "1.0.2": { + "name": "balanced-match", + "description": "Match balanced character pairs, like \"{\" and \"}\"", + "version": "1.0.2", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/balanced-match.git" + }, + "main": "index.js", + "scripts": { + "test": "tape test/test.js", + "bench": "matcha test/bench.js" + }, + "devDependencies": { + "matcha": "^0.7.0", + "tape": "^4.6.0" + }, + "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" + ] + }, + "gitHead": "c7412e09b95d6ad97fd1e2996f6adca7626a9ae8", + "bugs": { + "url": "https://github.com/juliangruber/balanced-match/issues" + }, + "_id": "balanced-match@1.0.2", + "_nodeVersion": "15.9.0", + "_npmVersion": "7.7.6", + "dist": { + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "shasum": "e83e3a7e3f300b34cb9d87f615fa0cbf357690ee", + "tarball": "http://localhost:4260/balanced-match/balanced-match-1.0.2.tgz", + "fileCount": 5, + "unpackedSize": 6939 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/balanced-match.git" + }, + "homepage": "https://github.com/juliangruber/balanced-match", + "bugs": { + "url": "https://github.com/juliangruber/balanced-match/issues" + }, + "license": "MIT", + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/bcrypt-pbkdf/registry.json b/tests/registry/npm/bcrypt-pbkdf/registry.json index 5ca80d673b..1c610cfb54 100644 --- a/tests/registry/npm/bcrypt-pbkdf/registry.json +++ b/tests/registry/npm/bcrypt-pbkdf/registry.json @@ -1 +1,53 @@ -{"_id":"bcrypt-pbkdf","_rev":"36-1813af753f7bd459411f7b54d76c5f74","name":"bcrypt-pbkdf","description":"Port of the OpenBSD bcrypt_pbkdf function to pure JS","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"bcrypt-pbkdf","version":"1.0.0","description":"Port of the OpenBSD bcrypt_pbkdf function to pure JS","main":"index.js","dependencies":{"tweetnacl":"^0.14.3"},"devDependencies":{},"license":"BSD-4-Clause","gitHead":"e88be37d3cd25395b4aa496ac468b33671368be6","_id":"bcrypt-pbkdf@1.0.0","scripts":{},"_shasum":"3ca76b85241c7170bf7d9703e7b9aa74630040d4","_from":".","_npmVersion":"3.10.3","_nodeVersion":"0.12.15","_npmUser":{"name":"arekinath","email":"alex@cooperi.net"},"dist":{"shasum":"3ca76b85241c7170bf7d9703e7b9aa74630040d4","tarball":"http://localhost:4260/bcrypt-pbkdf/bcrypt-pbkdf-1.0.0.tgz","integrity":"sha512-1d7nPZyCV4TvkiRd3dZEqDrcj88tAe3ZxwkKeAJJ9eEoDIHyVPxGbmV1HMFVGa2XH4JHRrwUja36rLzR5BA60g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBsBuTlX3JsQac5rE1mTTrcXA9SjHj3veRkF5h3gQJQDAiEAxtyynYs2Ig6eMQybwfYM8xiaT/T6Qrua7OJBdYaAv/o="}]},"maintainers":[{"name":"arekinath","email":"alex@cooperi.net"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/bcrypt-pbkdf-1.0.0.tgz_1471381825814_0.06877309852279723"},"directories":{}},"1.0.1":{"name":"bcrypt-pbkdf","version":"1.0.1","description":"Port of the OpenBSD bcrypt_pbkdf function to pure JS","main":"index.js","dependencies":{"tweetnacl":"^0.14.3"},"devDependencies":{},"license":"BSD-3-Clause","gitHead":"fa2ab3ae9efa15367264151398635a915c7b411d","_id":"bcrypt-pbkdf@1.0.1","scripts":{},"_shasum":"63bc5dcb61331b92bc05fd528953c33462a06f8d","_from":".","_npmVersion":"2.14.9","_nodeVersion":"0.12.9","_npmUser":{"name":"arekinath","email":"alex@cooperi.net"},"dist":{"shasum":"63bc5dcb61331b92bc05fd528953c33462a06f8d","tarball":"http://localhost:4260/bcrypt-pbkdf/bcrypt-pbkdf-1.0.1.tgz","integrity":"sha512-vY4sOrSlpwNZXsinfJ0HpbSkFft4nhSVLeUrQ4j2ydGmBOiVY83aMJStJATBy0C3+XdaYa990kIA1qkC2mUq6g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBZuaBsom/6JLjGKhclNtePzqZsHzR0C80PlV9mSWGjcAiA3p8h8FYgvOslN30CTH1iAqVrEmDMcDtPORpnPxiAbNA=="}]},"maintainers":[{"name":"arekinath","email":"alex@cooperi.net"},{"name":"dap","email":"dap@cs.brown.edu"},{"name":"jclulow","email":"josh@sysmgr.org"},{"name":"trentm","email":"trentm@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/bcrypt-pbkdf-1.0.1.tgz_1486007687899_0.974529881728813"},"directories":{}},"1.0.2":{"name":"bcrypt-pbkdf","version":"1.0.2","description":"Port of the OpenBSD bcrypt_pbkdf function to pure JS","repository":{"type":"git","url":"git://github.com/joyent/node-bcrypt-pbkdf.git"},"main":"index.js","dependencies":{"tweetnacl":"^0.14.3"},"devDependencies":{},"license":"BSD-3-Clause","gitHead":"15fa7399a1090ba70d855764f7ace23003bf45f3","bugs":{"url":"https://github.com/joyent/node-bcrypt-pbkdf/issues"},"homepage":"https://github.com/joyent/node-bcrypt-pbkdf#readme","_id":"bcrypt-pbkdf@1.0.2","scripts":{},"_shasum":"a4301d389b6a43f9b67ff3ca11a3f6637e360e9e","_from":".","_npmVersion":"2.15.11","_nodeVersion":"0.12.18","_npmUser":{"name":"arekinath","email":"alex@cooperi.net"},"dist":{"shasum":"a4301d389b6a43f9b67ff3ca11a3f6637e360e9e","tarball":"http://localhost:4260/bcrypt-pbkdf/bcrypt-pbkdf-1.0.2.tgz","fileCount":5,"unpackedSize":28994,"integrity":"sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQChYywQjt5fZLC9Rra6lu+zL8cvuTL5dMd2eOEhxappzwIhALDhzEgD/8ch3dt4FJFJIkUGloGoubSOB8uag2TfDxIC"}]},"maintainers":[{"name":"arekinath","email":"alex@cooperi.net"},{"name":"dap","email":"dap@cs.brown.edu"},{"name":"jclulow","email":"josh@sysmgr.org"},{"name":"trentm","email":"trentm@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/bcrypt-pbkdf_1.0.2_1530232438519_0.6464853720318084"},"_hasShrinkwrap":false}},"readme":"Port of the OpenBSD `bcrypt_pbkdf` function to pure Javascript. `npm`-ified\nversion of [Devi Mandiri's port](https://github.com/devi/tmp/blob/master/js/bcrypt_pbkdf.js),\nwith some minor performance improvements. The code is copied verbatim (and\nun-styled) from Devi's work.\n\nThis product includes software developed by Niels Provos.\n\n## API\n\n### `bcrypt_pbkdf.pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds)`\n\nDerive a cryptographic key of arbitrary length from a given password and salt,\nusing the OpenBSD `bcrypt_pbkdf` function. This is a combination of Blowfish and\nSHA-512.\n\nSee [this article](http://www.tedunangst.com/flak/post/bcrypt-pbkdf) for\nfurther information.\n\nParameters:\n\n * `pass`, a Uint8Array of length `passlen`\n * `passlen`, an integer Number\n * `salt`, a Uint8Array of length `saltlen`\n * `saltlen`, an integer Number\n * `key`, a Uint8Array of length `keylen`, will be filled with output\n * `keylen`, an integer Number\n * `rounds`, an integer Number, number of rounds of the PBKDF to run\n\n### `bcrypt_pbkdf.hash(sha2pass, sha2salt, out)`\n\nCalculate a Blowfish hash, given SHA2-512 output of a password and salt. Used as\npart of the inner round function in the PBKDF.\n\nParameters:\n\n * `sha2pass`, a Uint8Array of length 64\n * `sha2salt`, a Uint8Array of length 64\n * `out`, a Uint8Array of length 32, will be filled with output\n\n## License\n\nThis source form is a 1:1 port from the OpenBSD `blowfish.c` and `bcrypt_pbkdf.c`.\nAs a result, it retains the original copyright and license. The two files are\nunder slightly different (but compatible) licenses, and are here combined in\none file. For each of the full license texts see `LICENSE`.\n","maintainers":[{"email":"bahamat@digitalelf.net","name":"bahamat"},{"email":"todd.whiteman@joyent.com","name":"todd.whiteman"},{"email":"kusorbox@gmail.com","name":"kusor"},{"email":"michael.hicks@joyent.com","name":"michael.hicks"},{"email":"trentm@gmail.com","name":"trentm"},{"email":"dap@cs.brown.edu","name":"dap"},{"email":"josh@sysmgr.org","name":"jclulow"},{"email":"alex@cooperi.net","name":"arekinath"}],"time":{"modified":"2022-06-13T04:26:47.421Z","created":"2016-08-16T21:10:29.470Z","1.0.0":"2016-08-16T21:10:29.470Z","1.0.1":"2017-02-02T03:54:49.593Z","1.0.2":"2018-06-29T00:33:59.042Z"},"license":"BSD-3-Clause","readmeFilename":"README.md","homepage":"https://github.com/joyent/node-bcrypt-pbkdf#readme","repository":{"type":"git","url":"git://github.com/joyent/node-bcrypt-pbkdf.git"},"bugs":{"url":"https://github.com/joyent/node-bcrypt-pbkdf/issues"}} \ No newline at end of file +{ + "name": "bcrypt-pbkdf", + "description": "Port of the OpenBSD bcrypt_pbkdf function to pure JS", + "dist-tags": { + "latest": "1.0.2" + }, + "versions": { + "1.0.2": { + "name": "bcrypt-pbkdf", + "version": "1.0.2", + "description": "Port of the OpenBSD bcrypt_pbkdf function to pure JS", + "repository": { + "type": "git", + "url": "git://github.com/joyent/node-bcrypt-pbkdf.git" + }, + "main": "index.js", + "dependencies": { + "tweetnacl": "^0.14.3" + }, + "devDependencies": {}, + "license": "BSD-3-Clause", + "gitHead": "15fa7399a1090ba70d855764f7ace23003bf45f3", + "bugs": { + "url": "https://github.com/joyent/node-bcrypt-pbkdf/issues" + }, + "_id": "bcrypt-pbkdf@1.0.2", + "scripts": {}, + "_shasum": "a4301d389b6a43f9b67ff3ca11a3f6637e360e9e", + "_from": ".", + "_npmVersion": "2.15.11", + "_nodeVersion": "0.12.18", + "dist": { + "shasum": "a4301d389b6a43f9b67ff3ca11a3f6637e360e9e", + "tarball": "http://localhost:4260/bcrypt-pbkdf/bcrypt-pbkdf-1.0.2.tgz", + "fileCount": 5, + "unpackedSize": 28994, + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==" + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "license": "BSD-3-Clause", + "readmeFilename": "README.md", + "homepage": "https://github.com/joyent/node-bcrypt-pbkdf#readme", + "repository": { + "type": "git", + "url": "git://github.com/joyent/node-bcrypt-pbkdf.git" + }, + "bugs": { + "url": "https://github.com/joyent/node-bcrypt-pbkdf/issues" + } +} diff --git a/tests/registry/npm/brace-expansion/registry.json b/tests/registry/npm/brace-expansion/registry.json index 52496cfba6..f4852991f6 100644 --- a/tests/registry/npm/brace-expansion/registry.json +++ b/tests/registry/npm/brace-expansion/registry.json @@ -1 +1,84 @@ -{"_id":"brace-expansion","_rev":"36-7d4ba224c59232d5dcca7a8c7bc01ebd","name":"brace-expansion","description":"Brace expansion as known from sh/bash","dist-tags":{"latest":"4.0.0"},"versions":{"0.0.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"0.0.0","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"},"dependencies":{"concat-map":"0.0.0","balanced-match":"0.0.0"},"devDependencies":{"tape":"~1.1.1"},"keywords":[],"author":{"name":"Julian Gruber","email":"mail@juliangruber.com","url":"http://juliangruber.com"},"license":"MIT","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@0.0.0","dist":{"shasum":"b2142015e8ee12d4cdae2a23908d28d44c2baa9f","tarball":"http://localhost:4260/brace-expansion/brace-expansion-0.0.0.tgz","integrity":"sha512-ZjZtiom0CcPQjWOvuqQsl/jP/GbJYO9oRJwJiZcB0f2e4PM3EAwoxAzTJBOcUJ0SSlKShb0wB5bkpzoH4YgbYg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIz68OppfZj5bE9pvkPOiULQUHgRnY5X0txTOV7vNCFQIhAI4tRdbxB4npUxcuFaodGaFxxqwJMGQt0kUIqjs5WvNq"}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{}},"1.0.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.0.0","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"},"dependencies":{"balanced-match":"^0.2.0","concat-map":"0.0.0"},"devDependencies":{"tape":"~1.1.1"},"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"]},"gitHead":"55329dcf69a61c2ea76320c5e87a56de48682c80","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.0.0","_shasum":"a01656d12ebbbd067c8e935903f194ea5efee4ee","_from":".","_npmVersion":"2.1.8","_nodeVersion":"0.10.32","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"}],"dist":{"shasum":"a01656d12ebbbd067c8e935903f194ea5efee4ee","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.0.0.tgz","integrity":"sha512-lpqC6FxtM5XVWHdevRkMRPWSpsoLOWqurCALDPKm0VnLHf3DQ2rqFO8WBc6ierDnXeiMnCzwtDl6PgZrPY7xxA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHiiZuTN8rlOZuQfGyNVObHLXk06S8FCymzz59nrA6kIAiEAkQNqXm+yIrcqfrgeOfchnIebTgu7lM/7ohwc2jaPqnY="}]},"directories":{}},"1.0.1":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.0.1","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"},"dependencies":{"balanced-match":"^0.2.0","concat-map":"0.0.0"},"devDependencies":{"tape":"~1.1.1"},"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"]},"gitHead":"ceba9627f19c590feb7df404e1d6c41f8c01b93a","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.0.1","_shasum":"817708d72ab27a8c312d25efababaea963439ed5","_from":".","_npmVersion":"2.1.11","_nodeVersion":"0.10.16","_npmUser":{"name":"isaacs","email":"i@izs.me"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"dist":{"shasum":"817708d72ab27a8c312d25efababaea963439ed5","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.0.1.tgz","integrity":"sha512-agencL/m7vghsxEHLqdfg0cz3hHCEo46p+VCthmo2ldRTsmW7DANziRJnYCzGPT2Rc6OaYoNmiC9Fq/6laK8Lg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGL4FbAvj1GETCGq8al+snilcC+LBgaWobxTbx8NWHZAIhANmwsSB+I/6UwWGG0pJTZ61b1BqcCFCycRpzUjMB5IUG"}]},"directories":{}},"1.1.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.0","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"},"dependencies":{"balanced-match":"^0.2.0","concat-map":"0.0.1"},"devDependencies":{"tape":"^3.0.3"},"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"]},"gitHead":"b5fa3b1c74e5e2dba2d0efa19b28335641bc1164","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.0","_shasum":"c9b7d03c03f37bc704be100e522b40db8f6cfcd9","_from":".","_npmVersion":"2.1.10","_nodeVersion":"0.10.32","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"dist":{"shasum":"c9b7d03c03f37bc704be100e522b40db8f6cfcd9","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.0.tgz","integrity":"sha512-jW1t9kL3kiXzovHnEgYNuYMnF+hHB1TlyK2wox32dPrWRvwNEJlXz3NdB5mdjFK1Pom22qVVvpGXN2hICWmvGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDAPkyBXMMTJXxO2G60LgymQM/x1fVRSoTL+X3M2ijMQAIhAIy8QqTEZzxuJKSFpS2zCFxK5+XDyIaYWZeOlil5bFAa"}]},"directories":{}},"1.1.1":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.1","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"},"dependencies":{"balanced-match":"^0.2.0","concat-map":"0.0.1"},"devDependencies":{"tape":"^3.0.3"},"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"]},"gitHead":"f50da498166d76ea570cf3b30179f01f0f119612","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.1","_shasum":"da5fb78aef4c44c9e4acf525064fb3208ebab045","_from":".","_npmVersion":"2.6.1","_nodeVersion":"0.10.36","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"dist":{"shasum":"da5fb78aef4c44c9e4acf525064fb3208ebab045","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.1.tgz","integrity":"sha512-8sehXzl+5+hVq+azy8bdvi/vdY1DA0eKIM+k+wK4XqBAy3e0khAcxN+CMIf6QObpDLR4LXBBH8eRRR500WDidg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAMsztomnUx31iO0XaIv4hcdVeg9nUiL0BNflX2zT1mKAiEAnKJYmKMf1DIPlz3tsslDFKMUMZBV5K6i41Erb0rdfOE="}]},"directories":{}},"1.1.2":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.2","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"},"dependencies":{"balanced-match":"^0.3.0","concat-map":"0.0.1"},"devDependencies":{"tape":"4.2.2"},"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"]},"gitHead":"b03773a30fa516b1374945b68e9acb6253d595fa","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.2","_shasum":"f21445d0488b658e2771efd870eff51df29f04ef","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.1","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"f21445d0488b658e2771efd870eff51df29f04ef","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.2.tgz","integrity":"sha512-QY1LGlHZzEwE7NbolI6UYCtLE2zp0I49Cx7anmMGHjwPcb5E/fN/mk5i6oERkhhx78K/UPNEwLjLhHM3tZwjcw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGzXvMvui4rDxLgCCSSd5sHHHnPnkk+FFuMXmUmTPuasAiAI9w6HqWYhvFwjJ1Lt2kvx9juCc42nu86lNVjZVmiVBw=="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"directories":{}},"1.1.3":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.3","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"},"dependencies":{"balanced-match":"^0.3.0","concat-map":"0.0.1"},"devDependencies":{"tape":"4.4.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"]},"gitHead":"f0da1bb668e655f67b6b2d660c6e1c19e2a6f231","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.3","_shasum":"46bff50115d47fc9ab89854abb87d98078a10991","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.5.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"46bff50115d47fc9ab89854abb87d98078a10991","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.3.tgz","integrity":"sha512-JzSkuJYnfzmR0jZiCE/Nbw1I9/NL2Z2diIfhffu5Aq3nihHtfO8CNYcwxmAyTKYKWyte1b1vYBHMVhMbe+WZdw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTtnEPVW6mkENQFogGyd+jwVVZk4fv5oQrv59tJZl+LQIhAIDBZRtfmnRz3bd3iBTboDlyyKBBzKcmMQRB4i13N8Aa"}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"packages-6-west.internal.npmjs.com","tmp":"tmp/brace-expansion-1.1.3.tgz_1455216688668_0.948847763473168"},"directories":{}},"1.1.4":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.4","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"},"dependencies":{"balanced-match":"^0.4.1","concat-map":"0.0.1"},"devDependencies":{"tape":"4.5.1"},"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"]},"gitHead":"1660b75d0bf03b022e7888b576cd5a4080692c1d","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.4","_shasum":"464a204c77f482c085c2a36c456bbfbafb67a127","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"464a204c77f482c085c2a36c456bbfbafb67a127","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.4.tgz","integrity":"sha512-wpJYpqGrDNnMWoi1GX8s8C4/SkHCuuLV0Sxlkvc4+rEBTNkUI2xLiUU3McR0b5dVw71Yw50l+sBGhusHNnjFnw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDv5gzTuC2pQtSUO2lUpdIu+EEkjv5yy57Xfhq9mKbJZAIgNucwl3w78pmRKhcaEEkqf8ALdEUhrSTClfu6fid9vy8="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/brace-expansion-1.1.4.tgz_1462130058897_0.14984136167913675"},"directories":{}},"1.1.5":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.5","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"},"dependencies":{"balanced-match":"^0.4.1","concat-map":"0.0.1"},"devDependencies":{"tape":"4.5.1"},"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"]},"gitHead":"ff31acab078f1bb696ac4c55ca56ea24e6495fb6","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.5","_shasum":"f5b4ad574e2cb7ccc1eb83e6fe79b8ecadf7a526","_from":".","_npmVersion":"2.15.5","_nodeVersion":"4.4.5","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"f5b4ad574e2cb7ccc1eb83e6fe79b8ecadf7a526","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.5.tgz","integrity":"sha512-FtnR1B5L0wpwEeryoTeqAmxrybW2/7BI8lqG9WSk6FxHoPCg5O474xPgWWQkoS7wAilt97IWvz3hDOWtgqMNzg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDcdxKt/UDpxuuF6QUTSAj+Ndice1oRjJYdg0ZT4vFlxAiEA/qg6+kDz31bAvPhuTGit0IkXoFtpj5xgb9i8K7XPmOM="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/brace-expansion-1.1.5.tgz_1465989660138_0.34528115345165133"},"directories":{}},"1.1.6":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.6","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"},"dependencies":{"balanced-match":"^0.4.1","concat-map":"0.0.1"},"devDependencies":{"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"]},"gitHead":"791262fa06625e9c5594cde529a21d82086af5f2","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.6","_shasum":"7197d7eaa9b87e648390ea61fc66c84427420df9","_from":".","_npmVersion":"2.15.8","_nodeVersion":"4.4.7","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"7197d7eaa9b87e648390ea61fc66c84427420df9","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.6.tgz","integrity":"sha512-do+EUHPJZmz1wYWxOspwBMwgEqs0T5xSClPfYRwug3giEKZoiuMN9Ans1hjT8yZZ1Dkx1oaU4yRe540HKKHA0A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD32m58z3rzGaG1vElCS5FolKUXPn6odedg6Xfq9KZQOAIgWSBG2qBNxWBr+2EzNkySLFXLqC2Gj9ZQkHSOkPDUabM="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/brace-expansion-1.1.6.tgz_1469047715600_0.9362958471756428"},"directories":{}},"1.1.7":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.7","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":"^0.4.1","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"]},"gitHead":"892512024872ca7680554be90f6e8ce065053372","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.7","_shasum":"3effc3c50e000531fb720eaff80f0ae8ef23cf59","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.8.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"3effc3c50e000531fb720eaff80f0ae8ef23cf59","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.7.tgz","integrity":"sha512-ebXXDR1wKKxJNfTM872trAU5hpKduCkTN37ipoxsh5yibWq8FfxiobiHuVlPFkspSSNhrxbPHbM4kGyDGdJ5mg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjfkyICBvvj8rQb/0E8LXObvB5Ip4Son+jWmF+agQUewIgYtJplpbk9QT8k8fK4+mvwW/2SG88zw7RyfanboCbDYs="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/brace-expansion-1.1.7.tgz_1491552830231_0.7213963181711733"},"directories":{}},"1.1.8":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.8","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"]},"gitHead":"8f59e68bd5c915a0d624e8e39354e1ccf672edf6","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.8","_shasum":"c07b211c7c952ec1f8efd51a77ef0d1d3990a292","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.8.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"shasum":"c07b211c7c952ec1f8efd51a77ef0d1d3990a292","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.8.tgz","integrity":"sha512-Dnfc9ROAPrkkeLIUweEbh7LFT9Mc53tO/bbM044rKjhgAEyIGKvKXg97PM/kRizZIfUHaROZIoeEaWao+Unzfw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnJTT7JQLt62sEnsf0tHq2Bjs0s5hzFPLTKZ0ezxe48wIhAMjCqrWYo5zNLTOR2UuSzCxYcXppfgandM0w69ZeHWpY"}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"isaacs@npmjs.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion-1.1.8.tgz_1497251980593_0.6575565172825009"},"directories":{}},"1.1.9":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.9","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"]},"gitHead":"0f82dab6708f7c451e4a865b817057bc5a6b3c8e","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.9","_npmVersion":"5.5.1","_nodeVersion":"9.0.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"integrity":"sha512-/+o3o6OV1cm3WKrO7U4wykU+ZICE6HiMEuravc2d03NIuM/VaRn5iMcoQ7NyxFXjvpmRICP2EER0YOnh4yIapA==","shasum":"acdc7dde0e939fb3b32fe933336573e2a7dc2b7c","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.9.tgz","fileCount":3,"unpackedSize":9867,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAFhLoOH1TGldXfcUQuons91mJSbJrZN7qvWgErbY1lwIhALBOh4f4dcTZ4xMkCIZbI0YlooUneFTZMFuQiPvTFZVW"}]},"maintainers":[{"name":"isaacs","email":"isaacs@npmjs.com"},{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_1.1.9_1518170016033_0.0827503901708313"},"_hasShrinkwrap":false},"1.1.10":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"1.1.10","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"]},"gitHead":"54a6176731eb223cd3dede1473190d885d6b3648","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.10","_npmVersion":"5.5.1","_nodeVersion":"9.0.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"integrity":"sha512-u0KjSZq9NOEh36yRmKT/pIYOu0rpGAyUTeUmJgNd1K2tpAaUomh092TZ0fqbBGQc4hz85BVngAiB2mqekvQvIw==","shasum":"5205cdf64c9798c180dc74b7bfc670c3974e6300","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.10.tgz","fileCount":4,"unpackedSize":10964,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDli7mxJRbuSCfeiMcIL+s+gaQlXvfuResXwhPtt2QeKwIhAOXD8xbx/PBIDoeu5Oy4kLIhozwj20XbJgDGdsYvwrnj"}]},"maintainers":[{"name":"isaacs","email":"isaacs@npmjs.com"},{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_1.1.10_1518210808996_0.14734749523785462"},"_hasShrinkwrap":false},"1.1.11":{"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"]},"gitHead":"01a21de7441549d26ac0c0a9ff91385d16e5c21c","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@1.1.11","_npmVersion":"5.5.1","_nodeVersion":"9.0.0","_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"dist":{"integrity":"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==","shasum":"3c7fcbf529d87226f3d2f52b966ff5271eb441dd","tarball":"http://localhost:4260/brace-expansion/brace-expansion-1.1.11.tgz","fileCount":4,"unpackedSize":11059,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2I9J9tPlxp6j/HHQEZt6m3oGHr2r9mzmIpCuNqtxU8AIgEDoaUyizhrLzwPIwhskq7pIaySeBQHqkhwY/BQL5cCk="}]},"maintainers":[{"name":"isaacs","email":"isaacs@npmjs.com"},{"name":"juliangruber","email":"julian@juliangruber.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_1.1.11_1518248541320_0.33962849281003904"},"_hasShrinkwrap":false},"2.0.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"2.0.0","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"},"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"]},"gitHead":"0b6a022491103b806770bc037654744bef3e63be","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@2.0.0","_nodeVersion":"10.19.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-A4GHY1GpcTnp+Elcwp1CbKHY6ZQwwVR7QdjZk4fPetEh7oNBfICu+eLvvVvTEMHgC+SGn+XiLAgGo0MnPPBGOg==","shasum":"3b53b490c803c23a6a5d6c9c8b309879c37c7f98","tarball":"http://localhost:4260/brace-expansion/brace-expansion-2.0.0.tgz","fileCount":5,"unpackedSize":11241,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfewZYCRA9TVsSAnZWagAAd70P/2QT8aQ9+pjZQwM2pk0Z\nB/jNeaDu5O0/Y06KZF3Pzcxl9SFVCWfEr+7WP5mqb+R+dbthggNppICoM2Tk\nmilkoIgrUecspuKsvnJ0qJRYDSktSwD1IgcY/V3Yr8jCW5J56tU5SiUozvuj\nl3od5svv9vsPilwIHnMoRS4p00La7dlKK6v6R9QgdIF300jd+F++5GmSZOmj\nRxQslhhmFcM0nxIrJ1Ku06Tino2o8E8R0XzBUZS42uexstrDk9DGTtQmjqUn\nvnR/KRlJVppSdOeQ5P0L1UjvDObub5XUdfRo4JnQDrPrDZMdItLZ8CeoEVPh\nIwBCNCBoeWxbbPgAr4QdYMTpyIidFpMDd2lhNB+UTibold67Of4tbOn5KcOG\nac1lCdmturxz0AkyxawmQDkelpLdnatWdBzwGmPDk/Nh6bCSR03iKEgT3oJI\nu+NtciBopPto2emV8eN6E9yvlpGz8b7qDxi7FgOSYvEZ4Vy7spRpj6mS8PYl\nXbkTFUaNDr1KIMHlvXjeYX1I0MfFeE5u1uWovNS+bRmPYqVo78kRxJmlEL/J\nsOGS+PEnPx2thCA9VU4IZ+uGn1dx5mR28xylmatytWU2o3kXF4clXVeosSOl\nZYBAoXlsicuQxhrLzwvkReVpfCYNYVLTRjjn1eLrrba+M+FxT8ULtj6Z5Zh+\nqlBk\r\n=GlK9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCr5ZL6FcHVP65o923WcJjCEbbjT/6loKJU+zYITXIhbQIgGEfe3/Y91JY20BO7ZulW1OEI8SlP/Xvlh6hngSAJcF4="}]},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"i@izs.me"}],"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_2.0.0_1601898071832_0.5293279392460339"},"_hasShrinkwrap":false},"2.0.1":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"2.0.1","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"},"devDependencies":{"@c4312/matcha":"^1.3.1","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"]},"gitHead":"b9c0e57027317a8d0a56a7ccee28fc478d847da2","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@2.0.1","_nodeVersion":"14.15.5","_npmVersion":"6.14.11","dist":{"integrity":"sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==","shasum":"1edc459e0f0c548486ecf9fc99f2221364b9a0ae","tarball":"http://localhost:4260/brace-expansion/brace-expansion-2.0.1.tgz","fileCount":5,"unpackedSize":11486,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgM9lGCRA9TVsSAnZWagAAkYIQAIalRvvQqAOlBPALOfU+\nuIHTUBeNj/D6vRuqzPgWQVtUxRpdvXMI/aLxJx38aeZ6WgCvZWBQn3jItTEs\n3H2zWGue5+DAeWvBCqxSjdVV4ai+4EJuyS4+1D1qTm2syzT0aPdYRlhVMA/s\nOpiuPVHF1vqwSwPMCUXNW1sMi4N0qJzpAInYOCQ2NFUFZb5OssTqYQ1bzdl1\nRq/FtfkqOmz7OC/879lo3SCp+uvdXmkkQnSOGVU65HvzJp/NIvsFk5pHwo68\naRXefo/GRnqGFwFYOSqUUlBVjgEJYFdRVrYN+CNHK8iNJ6cphqz3EE1Edl1d\njT1SsFm9dJCqkfz5M/tW03vbMV88MYKhdDff5/Fugz4vcCAKfp+JcJolxUxz\nYXnB/xH/MsIEFIqwfDHYf+HFDZsZk7kJKm5JUciIV9CORiWtHz4d/y+4FYZM\n48okE1VAa5E7DVlGhTEUJUUt05JHztbm4EPklRd4/il61edoL516wp1XryxB\nSG3Jb+wLHH/ZHUQHpqrnBWvs68fxE8848EwiWIPKUk7pP/MtHdftjw2ouPSa\nD3EeHKJirZ3GAJqmwDy/vrOSB5/bQX82dGviV097AdPpnCAH6HJuaXBww+lN\nXgbxcuBiXlMuQAxpmQ578BOIGHnCo9EeauL2Ik9pHissAPUcpFCSUVZvXC3P\nJbt7\r\n=ayXm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDgNFdV3ddgnkb39ucmGYRgdjxRfJEZcnAt+BXCAQaVPgIhAKW05a01tUGrzy0G/gZFOVqMptjiKbs9uy+dDpF0C75F"}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_2.0.1_1614010693500_0.3082242768639887"},"_hasShrinkwrap":false},"3.0.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"3.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/brace-expansion.git"},"homepage":"https://github.com/juliangruber/brace-expansion","exports":"./index.js","type":"module","scripts":{"test":"standard --fix && node --test","gentest":"bash test/generate.sh","bench":"matcha bench/bench.js"},"dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"@c4312/matcha":"^1.3.1","standard":"^17.1.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"]},"engines":{"node":">= 18"},"gitHead":"b01a637b0578a7c59acc7d8386f11f8d0710b512","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@3.0.0","_nodeVersion":"20.3.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-P+6OwxY7i0tsp0Xdei2CjvVOQke51REB4c2d2wCckcMn6NBElNqLuzr6PsxFCdJ3i/cpGEkZ/Nng5I7ZkLo0CA==","shasum":"2ba8d16a84bb3b440107587dae0fa59cf8672452","tarball":"http://localhost:4260/brace-expansion/brace-expansion-3.0.0.tgz","fileCount":7,"unpackedSize":12214,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEC9uzfKooJ89Q8QLlD+tzLeFwFe/78sLtWLDO3ReypKAiBnVIsCDBixEed2GXe6+kCRV/O2pdWrYiYU+YT9S1FG4A=="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_3.0.0_1696685462916_0.3750340778742729"},"_hasShrinkwrap":false},"4.0.0":{"name":"brace-expansion","description":"Brace expansion as known from sh/bash","version":"4.0.0","repository":{"type":"git","url":"git://github.com/juliangruber/brace-expansion.git"},"homepage":"https://github.com/juliangruber/brace-expansion","exports":"./index.js","type":"module","scripts":{"test":"standard --fix && node --test","gentest":"bash test/generate.sh","bench":"matcha bench/bench.js"},"dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"@c4312/matcha":"^1.3.1","standard":"^17.1.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"]},"engines":{"node":">= 18"},"gitHead":"6a39bdddcf944374b475d99b0e8292d3727c7ebe","bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"_id":"brace-expansion@4.0.0","_nodeVersion":"20.3.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-l/mOwLWs7BQIgOKrL46dIAbyCKvPV7YJPDspkuc88rHsZRlg3hptUGdU7Trv0VFP4d3xnSGBQrKu5ZvGB7UeIw==","shasum":"bb24b89bf4d4b37d742acac89b65d1a32b379a81","tarball":"http://localhost:4260/brace-expansion/brace-expansion-4.0.0.tgz","fileCount":8,"unpackedSize":12770,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrhNEy/hwZjHIlsHCYab0+IHgrz7kDfa1w6u/e+kx1EAIgOp8c3E2/Sn13tVi4fV1P31KM5fQX1SqJtVtpcVNa8gI="}]},"_npmUser":{"name":"juliangruber","email":"julian@juliangruber.com"},"directories":{},"maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/brace-expansion_4.0.0_1709035002841_0.7308632197804894"},"_hasShrinkwrap":false}},"readme":"# brace-expansion\n\n[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),\nas known from sh/bash, in JavaScript.\n\n[![CI](https://github.com/juliangruber/brace-expansion/actions/workflows/ci.yml/badge.svg)](https://github.com/juliangruber/brace-expansion/actions/workflows/ci.yml)\n[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)\n\n## Example\n\n```js\nimport expand from 'brace-expansion'\n\nexpand('file-{a,b,c}.jpg')\n// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']\n\nexpand('-v{,,}')\n// => ['-v', '-v', '-v']\n\nexpand('file{0..2}.jpg')\n// => ['file0.jpg', 'file1.jpg', 'file2.jpg']\n\nexpand('file-{a..c}.jpg')\n// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']\n\nexpand('file{2..0}.jpg')\n// => ['file2.jpg', 'file1.jpg', 'file0.jpg']\n\nexpand('file{0..4..2}.jpg')\n// => ['file0.jpg', 'file2.jpg', 'file4.jpg']\n\nexpand('file-{a..e..2}.jpg')\n// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']\n\nexpand('file{00..10..5}.jpg')\n// => ['file00.jpg', 'file05.jpg', 'file10.jpg']\n\nexpand('{{A..C},{a..c}}')\n// => ['A', 'B', 'C', 'a', 'b', 'c']\n\nexpand('ppp{,config,oe{,conf}}')\n// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']\n```\n\n## API\n\n```js\nimport expand from 'brace-expansion'\n```\n\n### const expanded = expand(str)\n\nReturn an array of all possible and valid expansions of `str`. If none are\nfound, `[str]` is returned.\n\nValid expansions are:\n\n```js\n/^(.*,)+(.+)?$/\n// {a,b,...}\n```\n\nA comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.\n\n```js\n/^-?\\d+\\.\\.-?\\d+(\\.\\.-?\\d+)?$/\n// {x..y[..incr]}\n```\n\nA numeric sequence from `x` to `y` inclusive, with optional increment.\nIf `x` or `y` start with a leading `0`, all the numbers will be padded\nto have equal length. Negative numbers and backwards iteration work too.\n\n```js\n/^-?\\d+\\.\\.-?\\d+(\\.\\.-?\\d+)?$/\n// {x..y[..incr]}\n```\n\nAn alphabetic sequence from `x` to `y` inclusive, with optional increment.\n`x` and `y` must be exactly one character, and if given, `incr` must be a\nnumber.\n\nFor compatibility reasons, the string `${` is not eligible for brace expansion.\n\n## Installation\n\nWith [npm](https://npmjs.org) do:\n\n```bash\nnpm install brace-expansion\n```\n\n## Contributors\n\n- [Julian Gruber](https://github.com/juliangruber)\n- [Isaac Z. Schlueter](https://github.com/isaacs)\n- [Haelwenn Monnier](https://github.com/lanodan)\n\n## Sponsors\n\nThis module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!\n\nDo you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!\n\n## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure.\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","maintainers":[{"name":"juliangruber","email":"julian@juliangruber.com"},{"name":"isaacs","email":"i@izs.me"}],"time":{"modified":"2024-02-27T11:56:43.413Z","created":"2013-10-13T12:58:47.118Z","0.0.0":"2013-10-13T12:58:50.153Z","1.0.0":"2014-11-30T09:58:55.317Z","1.0.1":"2014-12-03T07:58:39.708Z","1.1.0":"2014-12-16T18:58:15.116Z","1.1.1":"2015-09-27T21:58:47.098Z","1.1.2":"2015-11-28T12:58:57.647Z","1.1.3":"2016-02-11T18:51:31.874Z","1.1.4":"2016-05-01T19:14:21.252Z","1.1.5":"2016-06-15T11:21:03.644Z","1.1.6":"2016-07-20T20:48:37.117Z","1.1.7":"2017-04-07T08:13:51.907Z","1.1.8":"2017-06-12T07:19:41.589Z","1.1.9":"2018-02-09T09:53:36.709Z","1.1.10":"2018-02-09T21:13:29.675Z","1.1.11":"2018-02-10T07:42:22.313Z","2.0.0":"2020-10-05T11:41:11.973Z","2.0.1":"2021-02-22T16:18:13.617Z","3.0.0":"2023-10-07T13:31:03.177Z","4.0.0":"2024-02-27T11:56:43.001Z"},"author":{"name":"Julian Gruber","email":"mail@juliangruber.com","url":"http://juliangruber.com"},"repository":{"type":"git","url":"git://github.com/juliangruber/brace-expansion.git"},"homepage":"https://github.com/juliangruber/brace-expansion","keywords":[],"bugs":{"url":"https://github.com/juliangruber/brace-expansion/issues"},"license":"MIT","readmeFilename":"README.md","users":{"fotooo":true,"i-erokhin":true,"scottfreecode":true,"shaomingquan":true,"sbruchmann":true,"flumpus-dev":true}} \ No newline at end of file +{ + "name": "brace-expansion", + "description": "Brace expansion as known from sh/bash", + "dist-tags": { + "latest": "2.0.1" + }, + "versions": { + "2.0.1": { + "name": "brace-expansion", + "description": "Brace expansion as known from sh/bash", + "version": "2.0.1", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/brace-expansion.git" + }, + "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" + }, + "devDependencies": { + "@c4312/matcha": "^1.3.1", + "tape": "^4.6.0" + }, + "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" + ] + }, + "gitHead": "b9c0e57027317a8d0a56a7ccee28fc478d847da2", + "bugs": { + "url": "https://github.com/juliangruber/brace-expansion/issues" + }, + "_id": "brace-expansion@2.0.1", + "_nodeVersion": "14.15.5", + "_npmVersion": "6.14.11", + "dist": { + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "shasum": "1edc459e0f0c548486ecf9fc99f2221364b9a0ae", + "tarball": "http://localhost:4260/brace-expansion/brace-expansion-2.0.1.tgz", + "fileCount": 5, + "unpackedSize": 11486 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/brace-expansion.git" + }, + "homepage": "https://github.com/juliangruber/brace-expansion", + "bugs": { + "url": "https://github.com/juliangruber/brace-expansion/issues" + }, + "license": "MIT", + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/browserslist/registry.json b/tests/registry/npm/browserslist/registry.json index 869da4f908..3ebddeaac6 100644 --- a/tests/registry/npm/browserslist/registry.json +++ b/tests/registry/npm/browserslist/registry.json @@ -1 +1,42 @@ -{"name":"browserslist","dist-tags":{"latest":"4.21.5"},"versions":{"0.1.0":{"name":"browserslist","version":"0.1.0","dependencies":{"caniuse-db":"^1.0.30000032 "},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.0.1","chai":"1.10.0","gulp":"3.8.10"},"dist":{"shasum":"b566254ca06832bd3326f1559a2361fed92bd691","tarball":"http://localhost:4260/browserslist/browserslist-0.1.0.tgz","integrity":"sha512-ltSJvB6Lte6O/WltNlFWH5WG0jG4YDFq555/tp5SqtKpdVYc4osmMDHSNIn/YpISYaBFa8B2kOhUA76dgE4Idg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGmMNwGMDK6+NHvC+DN3iMcCWmY7mBwDprrVcWktyV/hAiAZbW/Hba+zDS3rgl2ZyYDFHwvgVrfjcuRhY7rgHwTdrw=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.1.1":{"name":"browserslist","version":"0.1.1","dependencies":{"caniuse-db":"^1.0.30000043"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"dist":{"shasum":"279e955e6e00afcfc4dcc6160d79aea44db0645c","tarball":"http://localhost:4260/browserslist/browserslist-0.1.1.tgz","integrity":"sha512-xc/vrDm9doyy8wHpBd7TKEm4h3IZdjXxeAH7gZdXBI0/JfcnF5xac/DTuBOChbvFOzJly6A3DvrAj/pJn+O0Rw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGsY4BzwSH7i26h9Aip3QZyVyjYHYNwIykOE01QEES2nAiBgV6h+13F361DPgsOKrPicpnHkfSZ6gLoFd4anUp5ooA=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.1.2":{"name":"browserslist","version":"0.1.2","dependencies":{"caniuse-db":"^1.0.30000048"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"dist":{"shasum":"e27e20730dd426149bab8051073a41fc9d3cf238","tarball":"http://localhost:4260/browserslist/browserslist-0.1.2.tgz","integrity":"sha512-qaMt6MQVpyAk5NyOloY5jeznNjnm1Na3igd1AYb579WFQIbQ4AlD0js/kQdUFYWxxHzdYIlExobZjEqDhzCgGA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZxiDt8LLBksTuiOHjQh7lQMmcZVma3EpB3B/oLEkUDwIhAJeAZCmc2UP3ngIVmz6h/VBj2akHFRbeXsy0kkN82Jsl"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.1.3":{"name":"browserslist","version":"0.1.3","dependencies":{"caniuse-db":"^1.0.30000054"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"dist":{"shasum":"2f67975c24bb357b6b48b4bc46e7c39a1f0b3b5b","tarball":"http://localhost:4260/browserslist/browserslist-0.1.3.tgz","integrity":"sha512-ROuKKid9OQDFJeoIucQni6Fuu7da/QzGnIN3YScfSGtKwwyLTet9L9gUEsjElI2fG8n1oGnIO0R9UonbLwJ6BQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDO0K1ASYBGRwiV1fLiY18fI1NEe9aamx/XLvogdijPOAIgeSE1wDcxGSQvVar1ys76G2OW6PKxR/G1BbrwjqNBG6k="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.2.0":{"name":"browserslist","version":"0.2.0","dependencies":{"caniuse-db":"^1.0.30000054"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"dist":{"shasum":"e5b7cf311cccb70772cd22d4f61c7bb80523ecd2","tarball":"http://localhost:4260/browserslist/browserslist-0.2.0.tgz","integrity":"sha512-i6Sq3Sb/Li23kPHugpBK01cW+NTzifzfc2zjlhZ8NcSBoX64B513eXgcALNgEtDmfLzuVgLosLpaNUdUjkKscg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGcG+YRsS6zeITdff8nQN/eS109RjtQlHNM12gWdmhrJAiAJXrMz48XZanXGa/fzQRLbg5rDA30OoQGJDUGmmo6Scg=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.3.0":{"name":"browserslist","version":"0.3.0","dependencies":{"caniuse-db":"^1.0.30000078"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.2","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"2.0.0","gulp":"3.8.11"},"dist":{"shasum":"f4429e509b25e00c43d77bb60cc0be37292613f6","tarball":"http://localhost:4260/browserslist/browserslist-0.3.0.tgz","integrity":"sha512-ZKtKJIsBo251ENUlt5mdi5B8tgDyr9D+E/cUI0DphODaCsclZnVyvYW9ltylmKsFR97+xQmniE4ENbnbCnWR0A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHZ+ggRgpEOV7Ljel0fsX0a5F2KGoBDoIrujJfR9tS3eAiEAliW12b3XqUtjaWwaUQNYZaSDsuxgdRELvPw9HmW4Idc="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.3.1":{"name":"browserslist","version":"0.3.1","dependencies":{"caniuse-db":"^1.0.30000081"},"devDependencies":{"jshint-stylish":"1.0.1","gulp-jshint":"1.9.2","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"2.1.0","gulp":"3.8.11"},"dist":{"shasum":"d60dd16f4aa10087f18b4b19d6432f9f79bdc833","tarball":"http://localhost:4260/browserslist/browserslist-0.3.1.tgz","integrity":"sha512-PQjLnXNWgwYgc8chpFdqTfZsSpXiJuaMD4DnqxrBm/7b4uRR3dlGlBsF+TJaCjIWJeXxT2dD/XbD9PXA++faWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkztK5EjyJRcn428Z3qEloZej7P2951d/qrsK6B0MZvAIga/aNBvaV0/UJAE0oaht/3miMMMBcbY8E16HeTWtkj48="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.3.2":{"name":"browserslist","version":"0.3.2","dependencies":{"caniuse-db":"^1.0.30000113"},"devDependencies":{"gulp-eslint":"0.6.0","gulp-mocha":"2.0.1","mocha":"2.2.1","chai":"2.2.0","gulp":"3.8.11"},"dist":{"shasum":"4e516ed1882086ff2479bab80cd164b3ae463545","tarball":"http://localhost:4260/browserslist/browserslist-0.3.2.tgz","integrity":"sha512-J2C1s94eRdfmItLoo3rKmdatFwPEh2QV/x6OBWC0TZfdmtDtaSfVfOfb0rOJJGNYMiC7fU28uBD8Im3BsUbMLg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkPmDus6TvqmeeATGiGuNcW1S38sG0R+MvwCJFDKSn2QIhAJHUVImcxyBqkQixUpgV05T9Xq660/b/qaD4O96WU0fc"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.3.3":{"name":"browserslist","version":"0.3.3","dependencies":{"caniuse-db":"^1.0.30000127"},"devDependencies":{"gulp-eslint":"0.9.0","gulp-mocha":"2.0.1","mocha":"2.2.4","chai":"2.2.0","gulp":"3.8.11"},"dist":{"shasum":"c21beb6b3d3c2492404084781113f39fc133f2c0","tarball":"http://localhost:4260/browserslist/browserslist-0.3.3.tgz","integrity":"sha512-/jbys+EcVhS1h4hQmIzWdttTzyqhOnEH3dX1dTJO3iVseBueOQq3VF8HZOlwzSOQKyAA9ryvtPY5PV4Q/sBL1A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrFpdVqeQrTqjS+DvQ7/1j2zGE/ORT4Yq2Yp2UFLiEBQIgIcFhZPgOUStj7YA1S8SQO7LXIICQvrmiVXn9MiXA6is="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.4.0":{"name":"browserslist","version":"0.4.0","dependencies":{"caniuse-db":"^1.0.30000153"},"devDependencies":{"gulp-eslint":"0.11.1","gulp-mocha":"2.0.1","mocha":"2.2.4","chai":"2.3.0","gulp":"3.8.11"},"dist":{"shasum":"3bd4ab9199dc1b9150d4d6dba4d9d3aabbc86dd4","tarball":"http://localhost:4260/browserslist/browserslist-0.4.0.tgz","integrity":"sha512-/JVhaf9S6ru3THyiuwX5j86pT79r5UtgwV3s6w+KpGlmUzPxfMbI5OBxO88iFtqgdqPuNirprachS3m1611qKA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH3K+5T6u38RnCfx0YeHBpIrE/ioFUcZFaTi/RKvkSQuAiBs0efV8Mo7x6RxFMiUxX2VvkDtcpPyH8SyK4nNl4lgLw=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"0.5.0":{"name":"browserslist","version":"0.5.0","dependencies":{"caniuse-db":"^1.0.30000214"},"devDependencies":{"gulp-eslint":"0.14.0","gulp-mocha":"2.1.2","mocha":"2.2.5","chai":"3.0.0","gulp":"3.9.0"},"dist":{"shasum":"b82882493637c342b66ad3182c919e1dac6d1724","tarball":"http://localhost:4260/browserslist/browserslist-0.5.0.tgz","integrity":"sha512-qrE6zBcJjdzvEwbeU2/UM1AKBeW16ngVE/zPnmLR679YAHocET7CkGtSF3oh/4ozhjcDZqSID9lCksxUpPLc7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCgqNhC7Gz9VWItRZ7y6yQxMu3FSCRCzkNiQis5MyBt6gIgO6pbMqr5BGCfSQXov2+L0BNo22/F+950YVfR+RfZdcg="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.0.0":{"name":"browserslist","version":"1.0.0","dependencies":{"caniuse-db":"^1.0.30000281"},"devDependencies":{"gulp-eslint":"1.0.0","gulp-mocha":"2.1.3","mocha":"2.3.0","chai":"3.2.0","gulp":"3.9.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"678336f890f2b5bd3cdf2093150533dcbab3e185","tarball":"http://localhost:4260/browserslist/browserslist-1.0.0.tgz","integrity":"sha512-zAsoD942DaSKutUiJB9cNe8CKY0iq0VccRMC8N8OWGQZxqCvDmpWveMlF+I8xLJwBzBnif6VJtW4jOgj/2PKjg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCEdLCvKETNhHhRdkubvto+jN9M8Q5n9a1cR0oW20+jFwIgHVkasxf02emgCfb64zyKOQacXw9vYvBsOD6WCr5vQOM="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.0.1":{"name":"browserslist","version":"1.0.1","dependencies":{"caniuse-db":"^1.0.30000335"},"devDependencies":{"gulp-eslint":"1.0.0","gulp-mocha":"2.1.3","mocha":"2.3.3","chai":"3.3.0","gulp":"3.9.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"ef0dd708318cdf74325faeea59efec84d9464717","tarball":"http://localhost:4260/browserslist/browserslist-1.0.1.tgz","integrity":"sha512-RFDON6gOEm7hSSaEK5UkAbjAwfC7iVzrR5Gu4eHaaL5QsLoR2if5guuQXSgxezs3K5447DiGviNlZy/Uysu0kA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7lCbReU9OqDHrdojwCfUuQTBjOOIGnCqceJhjxI089QIgVZe3YLiQwIFewGELGMGzpwdOu4h7ANL3RbEfm3rc95s="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.1.0":{"name":"browserslist","version":"1.1.0","dependencies":{"caniuse-db":"^1.0.30000384"},"devDependencies":{"eslint":"1.10.3","ava":"0.9.1"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"a9ef42c2a51b51becefb3ce525ebee908a578bc5","tarball":"http://localhost:4260/browserslist/browserslist-1.1.0.tgz","integrity":"sha512-2PiGLsoJs4ACYHhKS83TvN+58EbX4JKzpUzeh9hSM8MY35DTSj440ZDa90A5YlO1iDJ8Xgfedn06Uar8B1K8/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICZ/8rgZ7ULlr4+und18XFZ/KpLWchnxg2MlahokRv5SAiA75d5lkgnXOAo2133e50iUILOAzMifK4URFM1OT4n38w=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.1.1":{"name":"browserslist","version":"1.1.1","dependencies":{"caniuse-db":"^1.0.30000387"},"devDependencies":{"eslint":"1.10.3","ava":"0.9.1"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"a333af8331160e1db14219ec1cc9b2da20cd4d37","tarball":"http://localhost:4260/browserslist/browserslist-1.1.1.tgz","integrity":"sha512-d1SMvBvU5jIGqZRHSSzZ3b1P2pwchbeHQ+Sq0Nqo+TmBTOOsEQIgsjYmQfWaqf8gP8mfhWTJhKX3lnWhomQn1Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGoQZZZPiiJ6qJFRQHO2mdNHIJcsdy86Z3NDnz3r4IzhAiEA9NbBi36d5vNkD/YouYSh2CsNUeY8KhuxaQAWyeSNa38="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.1.2":{"name":"browserslist","version":"1.1.2","dependencies":{"caniuse-db":"^1.0.30000409"},"devDependencies":{"eslint-config-postcss":"^1.0.0","eslint":"1.10.3","ava":"0.11.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"ee71ae31fc87764da23816fc4f09d2346a31879b","tarball":"http://localhost:4260/browserslist/browserslist-1.1.2.tgz","integrity":"sha512-1niL8xpy/nhu5uChGoUnO1hHZG3QyDxs+ELg/1tDQoNkfwiRawnOilxb9SUsVbkXjWYYqjjLFr2RESiAwV3lbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBru2K0wa7uTXOOdxhg2Vdbb6Va7RRxvAt7iVpTWo7FAAiEA0jLKvTc2Pm0hXZlOd24vp0N6jwT1dhbHUzncdKLR3lY="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.1.3":{"name":"browserslist","version":"1.1.3","dependencies":{"caniuse-db":"^1.0.30000409"},"devDependencies":{"eslint-config-postcss":"1.0.0","eslint":"1.10.3","ava":"0.11.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"63e0f1fd68545a56eccafca55b7b722918ebfff5","tarball":"http://localhost:4260/browserslist/browserslist-1.1.3.tgz","integrity":"sha512-X8UFFBqP+v9Gedwd9tuiGYpHsUT971xHjVhSOBiV+LkOSa6qEhOZt1UVAP6LoARMM7huRZ3i/rvbb6lr2v4mrg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCohhYfHwP0g5oQW80V7rvuGiZpaMzazRx8kbhB3g7XyQIgbBZxM/sC0yHxs7sScNHIfThtML9lc0FgCRpCj3GEvSg="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.2.0":{"name":"browserslist","version":"1.2.0","dependencies":{"caniuse-db":"^1.0.30000430"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.4.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"ef1b039b4cdd75f43382fa13a24f2a8d5da536d0","tarball":"http://localhost:4260/browserslist/browserslist-1.2.0.tgz","integrity":"sha512-4KG+F0xRqCJ4LW/YeeW5rvMrqg+sz0M7i1SmJJiAVdxci0j54DNdcrPlLxm8Rq4ZcHivzEUathUQLH3E4ktd+w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6QKD1ZMxh21ozBt3zF2ZFr/1iAsL6msQ2Y6LYcOKHtgIgCpePnpYMrFRs5ePrL8kuG6iYUmWzB3PJGEc7QoT9cLU="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.0":{"name":"browserslist","version":"1.3.0","dependencies":{"caniuse-db":"^1.0.30000431"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.4.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"517bca7192a3b47fd1d71a92366bb2b30b50eed2","tarball":"http://localhost:4260/browserslist/browserslist-1.3.0.tgz","integrity":"sha512-Ndo+18Qsvaj5M8du2HljDj06js5h3m2gI2GKouYTCDaiw04uBTt5YLk0pMarbmBmn1W6t7hPjhPAr+OqEv5naA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4b5ojhmRT0vrdrrFoZB3EcytMSKTbG0cbGx8OZ5WTWgIgBNGItOVrLLNXbm4RU1SeGxSozNWGKlCF6aYWB3ihJuI="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.1":{"name":"browserslist","version":"1.3.1","dependencies":{"caniuse-db":"^1.0.30000444"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.6.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"6198006485d3a350732408dca74165b69abfa718","tarball":"http://localhost:4260/browserslist/browserslist-1.3.1.tgz","integrity":"sha512-n5TVMrDJodz0M9AoD4KIebWtDrbkwbRVOyIWTBIxTFtZ0SnlirNSzzPAHocqB0J6GIrJxZcX5TdukZ3gM8njLg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHU7bJmVnctwBRzIeSmlcF3KaScOvYFbId7FlH//enaCAiEAsJ7pdXlWj/DPKBkBzApETiEwPoDo20x8Z0Me/B/hpPs="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.2":{"name":"browserslist","version":"1.3.2","dependencies":{"caniuse-db":"^1.0.30000471"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.11.1","ava":"0.15.1"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"afb4309174edae938d3042ab0f55dcc2fd88806a","tarball":"http://localhost:4260/browserslist/browserslist-1.3.2.tgz","integrity":"sha512-jeaIbJtmkqhyi5fycC8JX1lm6+TPRqEXoaMVkoImvFqRjIzR2RiTGUGgVgi1XUM7USmDzjZITr8+NHn0lGGHwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEHil7Ev133HHCZ2eeahLJMPI7eT8rKpxoWucrdrTTSQIhAPDNjoGN1J4CWxKxWjNVlCmcEJIakDNZiE09YSNbilIt"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.3":{"name":"browserslist","version":"1.3.3","dependencies":{"caniuse-db":"^1.0.30000484"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.13.0","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"2fc1e896ed3636e2649651f74907b53254ddad6a","tarball":"http://localhost:4260/browserslist/browserslist-1.3.3.tgz","integrity":"sha512-1gWIzmKFCwixAH2BQpUlbCkAFt7aQwLPmE/55eLbx2QF7GEehqpY/FNcti8sUX79R83lGyh+Yi1XLBgMJfZrSg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD9PafXGwsRcrpOb8MChBfEQgZZxel/YZEf5ZK7SaVP+wIhAO2TaQ0NIVrpg1jx4yUfzmNB6GTF8HfKfiy1q5dw8Li4"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.4":{"name":"browserslist","version":"1.3.4","dependencies":{"caniuse-db":"^1.0.30000488"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.13.1","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"97bba1a98f011f976333a053706d089ffc9b30fa","tarball":"http://localhost:4260/browserslist/browserslist-1.3.4.tgz","integrity":"sha512-r0IPQvs3vi0Juqcg5y2I2SUuidw3RSW1bzgSIY2V/7Sd9xpSFUz457ksdNqCYbZyYU8TAPE8Vkg74Sk3c71giQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCHy5n5s8BCCWsV09oq9y3ZJaxtTmpFP+8WROD3bPBRVAIhAPkkOeuds4/L7hGi+1y4UpPojtApaok37AW7mHcsS0/g"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.5":{"name":"browserslist","version":"1.3.5","dependencies":{"caniuse-db":"^1.0.30000506"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.0.1","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"2a1daf9b82b654186337ec13de4684b8f78450d7","tarball":"http://localhost:4260/browserslist/browserslist-1.3.5.tgz","integrity":"sha512-Xb2ZGTLX6WxTPwQfjmeqmQHq0eZPl7mInrrPP7EK+2H/9fylbnVFKN8hUB+42+zyiyqrJwvxHi7fkD8qkVEsig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCbQxDhIeNhLLp8Z3C0p/dGFl1dimXmr6dsrHi+9f8PggIgDBu48F+pF3GlfVQbt+LMAHkC4yo9KmyLJzyA/+mNXR8="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.3.6":{"name":"browserslist","version":"1.3.6","dependencies":{"caniuse-db":"^1.0.30000525"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.3.1","ava":"0.16.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"952ff48d56463d3b538f85ef2f8eaddfd284b133","tarball":"http://localhost:4260/browserslist/browserslist-1.3.6.tgz","integrity":"sha512-fKSWtyNQTclfi1A+s2KU91/r1mfANG1ZibxTdCwJGfV1J9UwcV22plFOm0wkaq4WzqW87zxiAkyp2Ho1Wn1NnA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEOtL74mlgPW3jy3bKrKpqeF1vjB5kTkNCMPhX58v60wIhANPDlRLNdioYJ1CV5zB3BpTz5l3rKED9p9R8KQr4oXG/"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.4.0":{"name":"browserslist","version":"1.4.0","dependencies":{"caniuse-db":"^1.0.30000539"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.6.0","ava":"0.16.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"9cfdcf5384d9158f5b70da2aa00b30e8ff019049","tarball":"http://localhost:4260/browserslist/browserslist-1.4.0.tgz","integrity":"sha512-tXAQS/6YQiUsYWt9gtUTomlPSjxcUlmMoozZ4nk8YVoq/hk+3eJFRfawwrO/TQBGuTQ+5U98Y1bJ1FGp+Vlkgg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDcQd70zDAZgTHFH803VmOdaKN1BVCEOvufoioGDAxd5AiEAsB4pqU4mh5Z5fZ8gtV0b8Bxoj4Cfgq4Cdtc98kzyeYw="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.5.0":{"name":"browserslist","version":"1.5.0","dependencies":{"caniuse-db":"^1.0.30000601"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.0.0","lint-staged":"^3.2.2","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"b9a1f3880dcc7afdf07baf48c8385200530eb126","tarball":"http://localhost:4260/browserslist/browserslist-1.5.0.tgz","integrity":"sha512-1Vq1BmR6GT4KPh1dXqzGSNCT9L3tce9cqcrLE1MTS6E5RZMXW6M0SvEC6aL/k/rGa0TMILyhxk0Dl7mhkawTbw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHpK96zo9kICt/LHFEQPklweX80yDU28xt5eXSdC8DSBAiEA88rl72UB7YebudDf7Kqb0YLAvSwLdSMiG0ELTP6uk+0="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.5.1":{"name":"browserslist","version":"1.5.1","dependencies":{"caniuse-db":"^1.0.30000601"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.0.0","lint-staged":"^3.2.2","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"67c3f2a1a6ad174cd01d25d2362e6e6083b26986","tarball":"http://localhost:4260/browserslist/browserslist-1.5.1.tgz","integrity":"sha512-5TS4g4W9DRb5/bydnZ6j739uwdC9gozmSngWxhCSV1RZH4UtsFTCf1F7nIe7q34cCfnDscUfQn0jbUgUrudQ0Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFlgUbJYOWBYsYwqazxl0/RVpziOHKzmJS1kjY3NM5/3AiAc2hCI4a+jmp72ZSLmaj+yruVHrkQ1Jc8z6BJ3pde2Tw=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.5.2":{"name":"browserslist","version":"1.5.2","dependencies":{"caniuse-db":"^1.0.30000604"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.5","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"1c82fde0ee8693e6d15c49b7bff209dc06298c56","tarball":"http://localhost:4260/browserslist/browserslist-1.5.2.tgz","integrity":"sha512-vCBhhZxZ5WQ7IASBt89jwUAKiLu+ctcWMIGW4lrrKmmH3SIrvEGzGC8FJH9j5NT1ujvFiLZoGK3lzf0UcYWd9g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCCDI3nOCuF5eiswqJ/398HjRSvnvIfy6lI5frcYMOzJwIgRBCQBYME1+s4smexd+k7Ge50k/mYT2Nhec/GKwyujm4="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.6.0":{"name":"browserslist","version":"1.6.0","dependencies":{"caniuse-db":"^1.0.30000613","electron-to-chromium":"^1.2.0"},"devDependencies":{"eslint":"^3.14.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.7","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"85fb7c993540d3fda31c282baf7f5aee698ac9ee","tarball":"http://localhost:4260/browserslist/browserslist-1.6.0.tgz","integrity":"sha512-FVKH0lKXYhHOcvOKOD4ZjYYPFH/ZsSc/Hhwu0NAvV70ItYjAJx+JjQBRv0Vm+N/zIEjIZFjshGIJ6XVtpW1v4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID4LhQqAB+ot+gnx0IGBvI/iI5DmW0q18EczITD92BiBAiEAqqqLuXbK3hrU6PlnPGTsi+KUg20zkeRL8najaxF91to="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.0":{"name":"browserslist","version":"1.7.0","dependencies":{"caniuse-db":"^1.0.30000617","electron-to-chromium":"^1.2.1"},"devDependencies":{"eslint":"^3.14.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.8","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"738df5b2971354d198b2fbd5a22c560d2d896084","tarball":"http://localhost:4260/browserslist/browserslist-1.7.0.tgz","integrity":"sha512-ryKvtArY9nR03Ooup9D5eHN+RKy3pFzKJJPEJIJHOK2tnfyZFJIJznM3xLdaJ6+RWNPZr2uWCp+vslnXWPS8VA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMls3vaMRd3BWBUoFGUgrksaRJ7PGcgIoYH7Jsbh1cFwIhAIJ5USc2Bvj6/4WKH0LdRWmnxlRaO76vg+p1E5iN8aA/"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.1":{"name":"browserslist","version":"1.7.1","dependencies":{"caniuse-db":"^1.0.30000617","electron-to-chromium":"^1.2.1"},"devDependencies":{"eslint":"^3.14.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.9","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"cc9bd193979a2a4b09fdb3df6003fefe48ccefe1","tarball":"http://localhost:4260/browserslist/browserslist-1.7.1.tgz","integrity":"sha512-ZbC9U61Du1/aJ28A74fxKEicP9CAz6+qqkDlyU5LKKEVrHntvpWhwe33YFZtZ+KuMA+ga+VCIykZceGGbdU40A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYXEbVZFKuQNL97oBt3gWt0JXveLDjsfj7Vt97nfVzMAIhAJ9dnDV6M7rixKTpcn3e2AlhUpQT5FdB+D+GE+gz2ztQ"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.2":{"name":"browserslist","version":"1.7.2","dependencies":{"caniuse-db":"^1.0.30000622","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"cf4977283c3e692d6dcc241192e9de91504ff331","tarball":"http://localhost:4260/browserslist/browserslist-1.7.2.tgz","integrity":"sha512-W7aBHM1v4ixu6HlHZ0HsoTXbLeePosomqs1FUbxOEh2jSrqUnT1Cp85otBTnRgFkgFDP1EgdKSviCH7RZVZDRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG/XzSXPobfNxerL4THFy72TOND5I2/3afSPujoOVhX5AiEA6GprgEdKvN1u+NgMM7YsSooebH+2IGt9s+w4ncslL+E="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.3":{"name":"browserslist","version":"1.7.3","dependencies":{"caniuse-db":"^1.0.30000623","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"25ead9c917b278ad668b83f39c8025697797b2ab","tarball":"http://localhost:4260/browserslist/browserslist-1.7.3.tgz","integrity":"sha512-t9+m/xnzNvDNZ9HainrGTAaNIMGpH+lzNn3UQ90uxLhYymx5lskF/VpeWZpm3gg8UF6suBWAouIvljndgEG9FQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGindNA8DPi4HUS5ijZBQv44MxFjVKZK+n7ZK2XfkZ1UAiEAhEAMd9AQR3X9WL87y2MhMuc/BrAxYLgdIujp4tlaDnk="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.4":{"name":"browserslist","version":"1.7.4","dependencies":{"caniuse-db":"^1.0.30000624","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"56a12da876f787223743a866224ccd8f97014628","tarball":"http://localhost:4260/browserslist/browserslist-1.7.4.tgz","integrity":"sha512-Wje0uO1izibOfvmusRJ+rG7rLHhlR2vEDJZ8VKsOaiHucZmMbWVPWIbgME8Zg8x+16xT53RPQU92zgTG47435A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDiLUvpSfJIdDOZDSzRnW4FDPx5UnmwnZnYJJPKnfLVnAiBGB6oPyEBBIkVqhnkXTQeX2uvD4GrCynGVpv70zFWnXA=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.5":{"name":"browserslist","version":"1.7.5","dependencies":{"caniuse-db":"^1.0.30000624","electron-to-chromium":"^1.2.3"},"devDependencies":{"eslint":"^3.16.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.1","lint-staged":"^3.3.1","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"eca4713897b51e444283241facf3985de49a9e2b","tarball":"http://localhost:4260/browserslist/browserslist-1.7.5.tgz","integrity":"sha512-LvH5lOpHIkHMzNXJ62mjmovjIFOJJ6XbfCnDPqvcU2+Ub3QrWyoisnpxABPYbclW2icj8WIkzdeg6oHTMfxjZw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5kvoeE6KH+yskp1danetpeAsIbm48efOV2lYCpWyCHAIgTSvdNBK/yPk1V4mJeVXoz8DK7CfM6K0vK5tPK0ng0OI="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.6":{"name":"browserslist","version":"1.7.6","dependencies":{"caniuse-db":"^1.0.30000631","electron-to-chromium":"^1.2.5"},"devDependencies":{"eslint":"^3.16.1","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.3.1","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"af98589ce6e7ab09618d29451faacb81220bd3ba","tarball":"http://localhost:4260/browserslist/browserslist-1.7.6.tgz","integrity":"sha512-hgVDSSNeJOYpuuBHPLm6rjgxLT5cNXBXjoNq2Nm5Z42EOyoFmTA1RWROiEtqOT2Wo8jPGjafAZMXTMoqrx2vIw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAHw/vZhooJWG72lHeCjLEPub9VpJQ/5eDo6ovyhJEWGAiEAxzgUvFNlDvyBBeCrb3MHj+ZZzvBmI94MW5XWXoBXauI="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"1.7.7":{"name":"browserslist","version":"1.7.7","dependencies":{"caniuse-db":"^1.0.30000639","electron-to-chromium":"^1.2.7"},"devDependencies":{"eslint":"^3.18.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.3.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"0bd76704258be829b2398bb50e4b62d1a166b0b9","tarball":"http://localhost:4260/browserslist/browserslist-1.7.7.tgz","integrity":"sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNBSYcyge31FXVrUUGcE3Op0Qj8TRB7CC6/ViKqUQcbAIhANtyoHClZIlXiAfRohv2E8hLwNuZ165iN0yTxMEfGiKY"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.0.0":{"name":"browserslist","version":"2.0.0","dependencies":{"caniuse-lite":"^1.0.30000657","electron-to-chromium":"^1.3.6"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"f9251e5c728eb7f18020b6743c2ef03feaff2a27","tarball":"http://localhost:4260/browserslist/browserslist-2.0.0.tgz","integrity":"sha512-8WhS6PqdFH+8hoL/zxt6yGFy1CmxzSC0NqdRaLcE16Z4X6W0WBTYzvfn5+wx+ncAoasZwscKXURB4Bm2W0Iq4Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCS/1rQ+9OMAHAwXIszBJN77TGf0x8UQyWVC4I/7R/iqgIgXXUI9tfsLi6ayw7jqG+Je5rzrmYVBINraiR210BhhBY="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.0":{"name":"browserslist","version":"2.1.0","dependencies":{"caniuse-lite":"^1.0.30000659","electron-to-chromium":"^1.3.8"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"2590d3de07c7129a7bd05ce3c3cb2a3fc56e78fa","tarball":"http://localhost:4260/browserslist/browserslist-2.1.0.tgz","integrity":"sha512-4QfJDAgTJDgwE9NrM4DKdtLGQ8m8LscN4yz94gwOqxu/OM+Nf3kVFmDgwA+6T2I1CLxOQ06qYSqaA7NCXHXn/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICRSZ4aubtNu1qqku8q84zYOOup4nRVLf1/IT0QuNWG9AiEAnRqi7pKuKRAijjjvuBXIIz3jAjDFLAyXdYj8BAiPgC8="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.1":{"name":"browserslist","version":"2.1.1","dependencies":{"caniuse-lite":"^1.0.30000664","electron-to-chromium":"^1.3.8"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"d0da26318d86352be7693d407977b8523cc78b11","tarball":"http://localhost:4260/browserslist/browserslist-2.1.1.tgz","integrity":"sha512-WM+z7aa8d0u4fbNX7/LKwrdsQxLThuaGzS1J+1EgIxWtilB3X/UAOmeixEl6FURbnWZ80AbSha+CCvrXqgdw7g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIANStRG3HlKrc127oaHyPFhsDjxHbjpj4YGiVIfxcmwYAiBKIDm2ysTcUB9ukj12IL1ZtxBPNMpvIrEp3J9X55YgUw=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.2":{"name":"browserslist","version":"2.1.2","dependencies":{"caniuse-lite":"^1.0.30000665","electron-to-chromium":"^1.3.9"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"a9dd0791342dab019861c2dd1cd0fd5d83230d39","tarball":"http://localhost:4260/browserslist/browserslist-2.1.2.tgz","integrity":"sha512-yWRRRIXSHU43c2d/MqKTMXxpUKQ4dkKDFFTAjE+HncLqFusWTeph7y+S1Y+KkgBuFwG6WgPMbvC2KZDUYBtdPg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID5RCHrMiVNB0kzlx8zVuUqvDWoYr6QU3/FKnkJPDAC/AiEA6jcJcB9+3NdIs/JGKMQ0/zzEl5lhWI8YZ0/sEoroRcY="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.3":{"name":"browserslist","version":"2.1.3","dependencies":{"caniuse-lite":"^1.0.30000670","electron-to-chromium":"^1.3.11"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.3","lint-staged":"^3.4.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"302dc8e5e44f3d5937850868aab13e11cac3dbc7","tarball":"http://localhost:4260/browserslist/browserslist-2.1.3.tgz","integrity":"sha512-TJ+IxnYxr3t6j9Ernyhw6pq7z0vuPYNl9SjxdmEHXb28WGWVdGFIjwRZKe2CPdm1u0NUEGowOdBPmm/tQzWajQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMcOmDtRJUTtatGE5JQtENLbSGaBjJ9VSiGtrgmez8jQIhAIhFrLVAfkdffpFCMiEAdAa8ZM8V8OBdGHXD0pwFtBjF"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.4":{"name":"browserslist","version":"2.1.4","dependencies":{"caniuse-lite":"^1.0.30000670","electron-to-chromium":"^1.3.11"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.3","lint-staged":"^3.4.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"cc526af4a1312b7d2e05653e56d0c8ab70c0e053","tarball":"http://localhost:4260/browserslist/browserslist-2.1.4.tgz","integrity":"sha512-W2q3Cey3MaYeWiMXiC/7YK527GQdA8BJBET1EFPzjxy2kLabgAh9+2NJzuFCj3Y2gWMu2O34sKtU2t6FC9OlCQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFSfm/hqQFATYKf7UDb603ezoVtOG7niDxiBPoGf8HRHAiEAjVJPNV8EPshGYpv20IaKKIqHUyBIo2X/uxG8Y3YgroE="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.1.5":{"name":"browserslist","version":"2.1.5","dependencies":{"caniuse-lite":"^1.0.30000684","electron-to-chromium":"^1.3.14"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.0.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.4","lint-staged":"^3.6.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"dist":{"shasum":"e882550df3d1cd6d481c1a3e0038f2baf13a4711","tarball":"http://localhost:4260/browserslist/browserslist-2.1.5.tgz","integrity":"sha512-dlcNyLXf7WsJDTqOmwD2AROEIwtgthhUwnUFt4G/AH1Nu4ukgiieeLCfvYrzs7QdMJ+PJVN0/l+EXM1MW4lQtg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEoGerPs6A4X4E3kWn3gx1wOs8yGDTtEW5CyUR5lxTegIgQ4pog2t5pUNNdQgkGGf7squEUkuEpEzRgglELzLLUCU="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.2.0":{"name":"browserslist","version":"2.2.0","dependencies":{"caniuse-lite":"^1.0.30000701","electron-to-chromium":"^1.3.15"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.2.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-t09UuOv/4/hrL1y4wZ871+kKE6E2bkdMD6duZtV7FZIHFpsmdQfW63BH3bAjkfpkbP/eFKyenUbDUKigV/VmRw==","shasum":"5e35ec993e467c6464b8cb708447386891de9f50","tarball":"http://localhost:4260/browserslist/browserslist-2.2.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtvswkWxRrj2yNQR1+G+JqLj4P7m5ITCLUL7C97/Bq7AIhAPPSbvhl9oYuZOAm+wOJGczDoEvvnO8GFdtRtPWVH55H"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.2.1":{"name":"browserslist","version":"2.2.1","dependencies":{"caniuse-lite":"^1.0.30000704","electron-to-chromium":"^1.3.16"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-q9NH7wY49FzqqsYHBv2kA/A5XUaaEvWShX3OGLugthdeqnCEaSEmU/TffiIDlcrb5XISYGCNyLvxtnHgOu1qVA==","shasum":"709048c57bf3bf9b382105c396a737ad525d948e","tarball":"http://localhost:4260/browserslist/browserslist-2.2.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDnXObQvW5AM2bP20qfOrFn/zOGhsSClOpUb0UBLLGrpAIgUgfUSdfbBMKHtacbLyLVdevfrpf+fgMJ41t9to4Cttw="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.2.2":{"name":"browserslist","version":"2.2.2","dependencies":{"caniuse-lite":"^1.0.30000704","electron-to-chromium":"^1.3.16"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-MejxGMNIeIqzgaMKVYfFTWHinrwZOnWMXteN9VlHinTd13/0aDmXY9uyRqNsCTnVxqRmrjQFcXI7cy0q9K1IYg==","shasum":"e9b4618b8a01c193f9786beea09f6fd10dbe31c3","tarball":"http://localhost:4260/browserslist/browserslist-2.2.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGeqmJxnxulr034+/6bvImeFdBwZ1iZgA/i0Oj3we8kyAiEAhuz7ll0/A7KQnSvw3WVEAwlbPVcsK+5W+nirtDcoBjU="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.3.0":{"name":"browserslist","version":"2.3.0","dependencies":{"caniuse-lite":"^1.0.30000710","electron-to-chromium":"^1.3.17"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-jDr9Mea+n+FwI+kR0ce7rXCFBoM7hbL80G/th7oPxuNSK4V5J3LPMHB5vykjeI2h7fgSihBbSdoJPmzUC0606Q==","shasum":"b2aa76415c71643fe2368f6243b43bbbb4211752","tarball":"http://localhost:4260/browserslist/browserslist-2.3.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEBaYREtXtbIN0sjeaSRlRrl5Bn0HsRXTQZmj2/Z9eyZAiEAr0HiXDp1zfXGDYf4k3jACkrD3Npilwaewo8gn8/TIis="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.3.1":{"name":"browserslist","version":"2.3.1","dependencies":{"caniuse-lite":"^1.0.30000712","electron-to-chromium":"^1.3.17"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.8.1","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-YSRvpyaxDBBAPkwYO0THouUmA+cvYbyBHZrP/byJEUGDT9r/6TQcDASBtrAj4S45Le6JZbV8oeUAPR9wT8tisg==","shasum":"39500a2090330b2a090120ea6c7fc78b6e091c5e","tarball":"http://localhost:4260/browserslist/browserslist-2.3.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQClr1lr7Ar38KuTeHqzqNM8WfWw6z5TZvo7JessjMEVQQIhALx3YyA8ag8xse72K3dqRenpYjTWqiHzgMZuvwGoGCsP"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.3.2":{"name":"browserslist","version":"2.3.2","dependencies":{"caniuse-lite":"^1.0.30000715","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.8.4","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-arvLUwBTsmpfmyMfoBQH8WWICiyaVkMxJsft73/rTRU80rAPSXsi3M0uYBcUH22w7MG475eET31F4M0+31w81g==","shasum":"343ff101cce799d5eaf0b742e17d0d21efc2d379","tarball":"http://localhost:4260/browserslist/browserslist-2.3.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7HUAQCbIwNRDZesb/GHNvOviikAdGSF+YD7fX+Qge0QIgTlGBroxSvIaKBYBg+VU6RidctwNDyv/sydHQJadjI8Q="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.3.3":{"name":"browserslist","version":"2.3.3","dependencies":{"caniuse-lite":"^1.0.30000715","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.9.0","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-p9hz6FA2H1w1ZUAXKfK3MlIA4Z9fEd56hnZSOecBIITb5j0oZk/tZRwhdE0xG56RGx2x8cc1c5AWJKWVjMLOEQ==","shasum":"2b0cabc4d28489f682598605858a0782f14b154c","tarball":"http://localhost:4260/browserslist/browserslist-2.3.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDisHjFvqLNVHx713RrCZkHrMToGr/UneT9Zp6unY8XNAIgBZ/59hFPg7qVoMnsAranuGuVCtTKwOy8mqRIRj+8A9U="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.4.0":{"name":"browserslist","version":"2.4.0","dependencies":{"caniuse-lite":"^1.0.30000718","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.5.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.4","pre-commit":"^1.1.3","size-limit":"^0.10.0","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==","shasum":"693ee93d01e66468a6348da5498e011f578f87f8","tarball":"http://localhost:4260/browserslist/browserslist-2.4.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCv1sIhNsY3XqyolL8Xm+TOwDWFz3nYqOI6kV4PEaUAhwIhAMsLSfrGFeep0iBsw4ys/PojOiQy8VtL8jwWVOXa7DpF"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.5.0":{"name":"browserslist","version":"2.5.0","dependencies":{"caniuse-lite":"^1.0.30000744","electron-to-chromium":"^1.3.24"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.8.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.0","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.2.3","pre-commit":"^1.1.3","size-limit":"^0.11.6","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-6Vw1LIigGw8zCK0gxczksUMZlO+oPUwBazAztMmFL/F8D5wB0qCuxRJGYgYM3JzaO0v2ZMRIg+nnnOgNsPGHeA==","shasum":"0ea00d22813a4dfae5786485225a9c584b3ef37c","tarball":"http://localhost:4260/browserslist/browserslist-2.5.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCFaZ+B9Tq9fSjWAOl3BTdCvAMD4RrYbc4QhcbK4RyEwgIhAO41HUkGxaArSnr6uMrfhqKnvQ8feVYdPq95W+X84puq"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.5.1":{"name":"browserslist","version":"2.5.1","dependencies":{"caniuse-lite":"^1.0.30000744","electron-to-chromium":"^1.3.24"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.8.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.0","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.2.3","pre-commit":"^1.1.3","size-limit":"^0.11.6","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-jAvM2ku7YDJ+leAq3bFH1DE0Ylw+F+EQDq4GkqZfgPEqpWYw9ofQH85uKSB9r3Tv7XDbfqVtE+sdvKJW7IlPJA==","shasum":"68e4bc536bbcc6086d62843a2ffccea8396821c6","tarball":"http://localhost:4260/browserslist/browserslist-2.5.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHGc6RQLWfaG4WAh8JiEeUzcY793tWC9pmkhG+i8bfBiAiEA9rixa1HOicT318sD6UHlcOlydm9tnKBZzBuEoTLGhW4="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.6.0":{"name":"browserslist","version":"2.6.0","dependencies":{"caniuse-lite":"^1.0.30000755","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.0","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-XgAVmla9QAC5VkNmJ+i5zbgh+sPumLEL83MDYR9J8LoCJ1NgkptAqIny0+2VyI83OAnVHLdCsUjM4vs8RLsppQ==","shasum":"15b14ab7b7df4b108979585badff121eca9e1835","tarball":"http://localhost:4260/browserslist/browserslist-2.6.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfsPE3vXYWoKjLsRJZXIvD9/JOSEp2k93mNN8+M+I4/AIgYzzjLkNDl8/aExoqXspRUlAbSGYqo72X5W2uJsfJOm8="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.6.1":{"name":"browserslist","version":"2.6.1","dependencies":{"caniuse-lite":"^1.0.30000755","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.0","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-HBZwVT7ciQB9KlXM3AUMQbnQXtHWPsEUKQTiS0BEFfY5bOrMl94ORaqQD1GyuTGh69ZmYeue9QBqiw219e09eQ==","shasum":"cc65a05ad6131ebda26f076f2822ba1bc826376b","tarball":"http://localhost:4260/browserslist/browserslist-2.6.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBCSPw4BWM5zTv9hXGZVGGO+9UvUVQjM+PT/bOaMPtn7AiEAoNxLzWPoT9RvSe5Sem+AbaklaaY15Jggh596o2R2aUk="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.7.0":{"name":"browserslist","version":"2.7.0","dependencies":{"caniuse-lite":"^1.0.30000757","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-s34mrlczJsfbJu//mz/m9zlOy/S6tiP6El1u8iC1gTfEnzKXvxo8RAoCxS/MmojB7rd7bnfYzvKQNHykWaUWWw==","shasum":"dc375dc70048fec3d989042a35022342902eff00","tarball":"http://localhost:4260/browserslist/browserslist-2.7.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHN0vZxn3AtH7ueTM15DoSJYYy0RCD/ZsDJ9g0ODbq8wIgQXu6oCMsvzYnMgx8G8x/+a1xo8S/5n8WS9VbiGFralA="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.8.0":{"name":"browserslist","version":"2.8.0","dependencies":{"caniuse-lite":"^1.0.30000758","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.13.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-iiWHM1Et6Q4TQpB7Ar6pxuM3TNMXasVJY4Y/oh3q38EwR3Z+IdZ9MyVf7PI4MJFB4xpwMcZgs9bEUnPG2E3TCA==","shasum":"27d64028130a2e8585ca96f7c3b7730eff4de493","tarball":"http://localhost:4260/browserslist/browserslist-2.8.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQKW/SA0fxjTGwSy6+cRBTpTyMROAfPULVEEgAYH3dugIhAIf41iZANfkunS5MCccSxg7T12sd3y4LcU80/vrlc5qw"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.9.0":{"name":"browserslist","version":"2.9.0","dependencies":{"caniuse-lite":"^1.0.30000760","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.11.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.3.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^5.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-vJEBcDTANoDhSHL46NeOEW5hvQw7It9uCqzeFPQhpawXfnOwnpvW5C97vn1eGJ7iCkSg8wWU0nYObE7d/N95Iw==","shasum":"706aca15c53be15610f466e348cbfa0c00a6a379","tarball":"http://localhost:4260/browserslist/browserslist-2.9.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsN3GUXoYJQqfrkvUCKzipeSiMUWKmOneMyjFWPCtQnQIgBgDph9sxJbn5aDn+MJbB0lM1RO31339jZMcWpcHNTeE="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.9.1":{"name":"browserslist","version":"2.9.1","dependencies":{"caniuse-lite":"^1.0.30000770","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.11.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.3.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^5.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-3n3nPdbUqn3nWmsy4PeSQthz2ja1ndpoXta+dwFFNhveGjMg6FXpWYe12vsTpNoXJbzx3j7GZXdtoVIdvh3JbA==","shasum":"b72d3982ab01b5cd24da62ff6d45573886aff275","tarball":"http://localhost:4260/browserslist/browserslist-2.9.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCVljHjr4cT0ITWXsLpCCutBql9J6Ims7gk+UFTfW0CMQIhAOaBaJHuOEiTurr4+GaMX8bA9R75l+oV5TSS2Ll7AO6Q"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.10.0":{"name":"browserslist","version":"2.10.0","dependencies":{"caniuse-lite":"^1.0.30000780","electron-to-chromium":"^1.3.28"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.12.1","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.4.1","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-WyvzSLsuAVPOjbljXnyeWl14Ae+ukAT8MUuagKVzIDvwBxl4UAwD1xqtyQs2eWYPGUKMeC3Ol62goqYuKqTTcw==","shasum":"bac5ee1cc69ca9d96403ffb8a3abdc5b6aed6346","tarball":"http://localhost:4260/browserslist/browserslist-2.10.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCui1GlZtU6+n+JJ7uVGZ4efcZ4t3L221HCeNDj3Nf1xAIgB6xT/m0DiyRyfM10wa6n31ABWu3w1DvU3cUjNZUcDA4="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.10.1":{"name":"browserslist","version":"2.10.1","dependencies":{"caniuse-lite":"^1.0.30000784","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.14.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.5.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.4","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-vUe1YhphiCb5lJ4YQwA5VbmAhZgv9cwgAQm/rZT6GA2X97ewDMOLPyDr08iGsqvPajvC/wEwWBZNtFFa8l4Hlw==","shasum":"f9dc692b79004a78ec9ba0d012c54de44cc6d7e4","tarball":"http://localhost:4260/browserslist/browserslist-2.10.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEGGNHGjHbyEkcRXwL/RugQSJf6AT3Hvpt08kz0PLQ8kAiEAwkSHJAC1a+D12A5qPlm7Zg43evrVDcag/h64/OaX7LA="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.10.2":{"name":"browserslist","version":"2.10.2","dependencies":{"caniuse-lite":"^1.0.30000784","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.14.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.5.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.4","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-laXHudMWp4ZLgmObmAHZEzkP7Te4lzUyueSZabSuWTImaQznFhFm42SDRmwutfpAOHqDB4fJKGWSZdyrf5TsXg==","shasum":"0838eec4b3db2d860cee13bf6c0691e7e8133822","tarball":"http://localhost:4260/browserslist/browserslist-2.10.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNZ2ZLy4wt/XYVy7n5nMDtATVPsI6TeWb5n89+SMl/WwIhAK/neiHdy9zOW0VAgM6f7ET9+cL5XfgtkHQTyOoV4QXn"}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.11.0":{"name":"browserslist","version":"2.11.0","dependencies":{"caniuse-lite":"^1.0.30000784","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.14.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.5.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.4","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-mNYp0RNeu1xueGuJFSXkU+K0nH+dBE/gcjtyhtNKfU8hwdrVIfoA7i5iFSjOmzkGdL2QaO7YX9ExiVPE7AY9JA==","shasum":"50350d6873a82ebe0f3ae5483658c571ae5f9d7d","tarball":"http://localhost:4260/browserslist/browserslist-2.11.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCt2Gw2V4lOTsdWRrl86Og1Ipna1TFbzhBVZIx5RNuT+QIgYptpAQj2xwmtxRbYCEK/RTj1NOvJcVMgen4jO5W475w="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.11.1":{"name":"browserslist","version":"2.11.1","dependencies":{"caniuse-lite":"^1.0.30000789","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.15.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.6.1","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.5","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Gp4oJOQOby5TpOJJuUtCrGE0KSJOUYVa/I+/3eD/TRWEK8jqZuJPAK1t+VuG6jp0keudrqtxlH4MbYbmylun9g==","shasum":"02fda29d9a2164b879100126e7b0d0b57e43a7bb","tarball":"http://localhost:4260/browserslist/browserslist-2.11.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEA73BZUhpQ50TtztQdVm+TCFW257zOOGPbzbElNK6lCAiAQ4nGAsgbYypyzexK0t0QnQ44FzvLbmk7ECegSNr76sg=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.11.2":{"name":"browserslist","version":"2.11.2","dependencies":{"caniuse-lite":"^1.0.30000791","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.15.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.6.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.6","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.14.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-BWT1zhRqq8BG/HrUQWB4pgkU6u27OyC1r5ErMn8zRaYTLtRS4cDtDCdZA3XYLsSmYWP2PPlBR8sggzrofImzgg==","shasum":"76ad768b97a689512fcd9724a8b9d76cdffb18fd","tarball":"http://localhost:4260/browserslist/browserslist-2.11.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAP+PRp2QFzWfwjIJMqBbayzcKfnkOZtw7SvPXy7Y/uZAiEAiVbCbRYj/JONHxaGnyPiMqiUsisnzYlUBaxeKyuHQJM="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"2.11.3":{"name":"browserslist","version":"2.11.3","dependencies":{"caniuse-lite":"^1.0.30000792","electron-to-chromium":"^1.3.30"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.15.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.6.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.0.6","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.14.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==","shasum":"fe36167aed1bbcde4827ebfe71347a2cc70b99b2","tarball":"http://localhost:4260/browserslist/browserslist-2.11.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFFJ/8BiYMneUEvURaQ9CGZFi0p71DUveq4OixLdRHgAAiBl49UTA4wHR64A6SFRzc5LmclW1DCIpubIWHKXGxhGDQ=="}]},"deprecated":"Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools."},"3.0.0":{"name":"browserslist","version":"3.0.0","dependencies":{"caniuse-lite":"^1.0.30000807","electron-to-chromium":"^1.3.33"},"devDependencies":{"cross-spawn":"^6.0.4","eslint":"^4.17.0","eslint-ci":"^0.1.1","eslint-config-logux":"^19.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.8.0","eslint-plugin-node":"^6.0.0","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.2.2","lint-staged":"^6.1.0","pre-commit":"^1.1.3","size-limit":"^0.14.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-5ArwxNIJxmBTUUTe+F7P2AM8wNf6zFa9mb3/o0JCrhGdd042PuVgAZg4M+A29NUpqFEYl+H3kQQYoZUXfuRS9g==","shasum":"5b41520c1a5ce6d0d2fe7c44bdf30e526b650403","tarball":"http://localhost:4260/browserslist/browserslist-3.0.0.tgz","fileCount":9,"unpackedSize":51331,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDZtwKYOgHug4UZ6S2Gwjak04yIszrNxkxaiSy7zx0r9gIgA+nw09aFRa4PnYZ48Hn7dSwWo+xBvBRGXjsPrACkvZM="}]}},"3.1.0":{"name":"browserslist","version":"3.1.0","dependencies":{"caniuse-lite":"^1.0.30000808","electron-to-chromium":"^1.3.33"},"devDependencies":{"cross-spawn":"^6.0.4","eslint":"^4.17.0","eslint-ci":"^0.1.1","eslint-config-logux":"^19.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.12.1","eslint-plugin-node":"^6.0.0","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.3.0","lint-staged":"^6.1.0","pre-commit":"^1.1.3","size-limit":"^0.14.1","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-pyoJs5teqQWTdwOTG7F5IDKi7hMvifd9ri3EYLG2ElXlA2AwvqB1SZ6RIPMRHpmYb0RYN8N7GSERey5WgxSCUQ==","shasum":"6a1ccc302ddf48e70480e2ee1a9acc293eceb306","tarball":"http://localhost:4260/browserslist/browserslist-3.1.0.tgz","fileCount":9,"unpackedSize":52284,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGOQDCpA2JMdmZqg40OtNFYIqeUoMl0R6TNpjah7QuUPAiEAnQlKQ0D/+HU3gykDZnx03xIK46X/RbekVsEmzkn0Ung="}]}},"3.1.1":{"name":"browserslist","version":"3.1.1","dependencies":{"caniuse-lite":"^1.0.30000809","electron-to-chromium":"^1.3.33"},"devDependencies":{"cross-spawn":"^6.0.4","eslint":"^4.18.0","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.12.2","eslint-plugin-node":"^6.0.0","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.3.0","lint-staged":"^6.1.1","pre-commit":"^1.1.3","size-limit":"^0.14.1","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-zHGaPnTt70ywm+glR7uMJFZSl+ADGO67SgD2ae20L+Y3KJUeH4fVa89OkTqKCqAnXFE9mO4LTHBKBqKRlr7VNw==","shasum":"d380fc048bc3a33e60fb87dc135110ebaaa6320a","tarball":"http://localhost:4260/browserslist/browserslist-3.1.1.tgz","fileCount":9,"unpackedSize":52337,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHnLeh4av4AQSv5ELbyP9BI3CvgYdgkqXUUoB3zqaomEAiAdjnkGlO9l/wQKFPsF6DTyReirIlGpSeEFn5eRJqXg9g=="}]}},"3.1.2":{"name":"browserslist","version":"3.1.2","dependencies":{"caniuse-lite":"^1.0.30000813","electron-to-chromium":"^1.3.36"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.18.2","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.9.0","eslint-plugin-jest":"^21.13.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.4.2","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.16.1","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-iO5MiK7MZXejqfnCK8onktxxb+mcW+KMiL/5gGF/UCWvVgPzbgbkA5cyYfqj/IIHHo7X1z0znrSHPw9AIfpvrw==","shasum":"893f29399d640ed35fe06bacd7eb1d78609a47e5","tarball":"http://localhost:4260/browserslist/browserslist-3.1.2.tgz","fileCount":9,"unpackedSize":53728,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzwAxuPIp7VPDNuD3ujTm0BJaw0SGShMUFcQGG8VRS8AIgATfQOBaV+OgYXP8XqYJJxOBQuClTVphXktx+OmtK/GU="}]}},"3.2.0":{"name":"browserslist","version":"3.2.0","dependencies":{"caniuse-lite":"^1.0.30000815","electron-to-chromium":"^1.3.39"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.0","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.9.0","eslint-plugin-jest":"^21.15.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.4.2","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-fXFmXYMUbD9E/I81MEknzD5TJmA1dQFy+2gYHHnO08CEWGTzWNlDyawBo9pfUIncaG840+RIuScjCT4IpQxTWA==","shasum":"3d4a99710c12101e4567c9aeedade49c958cb883","tarball":"http://localhost:4260/browserslist/browserslist-3.2.0.tgz","fileCount":9,"unpackedSize":55119,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHw/+WFLJwtWlbFtQgPNCRYqiwssdm7Kek5e0TzkAk5AAiEAszllJogJL64rwZ0ZH5bo4dhbLNQtEB8zWpRxi1Cgb/s="}]}},"3.2.1":{"name":"browserslist","version":"3.2.1","dependencies":{"caniuse-lite":"^1.0.30000819","electron-to-chromium":"^1.3.40"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.9.0","eslint-plugin-jest":"^21.15.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.4.3","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Smb+H/evmlcOdUFLGBu45q0we1tQGFjNLAC1AsO1ZCQ8fBD6WtXLpPHgm6Hp/sh1lVS++WdY8gJwIxMN1jOgLQ==","shasum":"4960a45fbfe39b2be36fe5ba07cce9ea32c8221c","tarball":"http://localhost:4260/browserslist/browserslist-3.2.1.tgz","fileCount":9,"unpackedSize":55165,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAgyhEORTcRzFLbv/1Ghou+X4kMryu8zFB3NX1zBAzoQAiB1HOmm+UHwwadw/2DcP4cbtrefRCOFCd5my1TclbR2pw=="}]}},"3.2.2":{"name":"browserslist","version":"3.2.2","dependencies":{"caniuse-lite":"^1.0.30000819","electron-to-chromium":"^1.3.40"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.9.0","eslint-plugin-jest":"^21.15.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.4.3","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-DIYZZceUfoOEVjaGBv5BAklxotFwOfBkAAV4E8VOhQpxY19rNlxvnOrd5ZjxSGcx9Zz2Y9GgQpvIlqp958cneA==","shasum":"ad0559e3982786d80bfb24421ee2318daceffd2c","tarball":"http://localhost:4260/browserslist/browserslist-3.2.2.tgz","fileCount":9,"unpackedSize":55669,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH+2D0XgA18LerBhAYanOUTE2omVdPrbuiLmVF5leMo3AiEAjCDvgGq+3c9NFDyliQq0cFYdaTvCZoBZFpMF3smHuq4="}]}},"3.2.3":{"name":"browserslist","version":"3.2.3","dependencies":{"caniuse-lite":"^1.0.30000819","electron-to-chromium":"^1.3.40"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.9.0","eslint-plugin-jest":"^21.15.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^22.4.3","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-cdpm0bFVz1KoRFuDTEk0IgxmZ2k2kTRKVlSQWf1RnxUe65GfjnMO30AxHpMkVv5wlPnpEYom7DhXwdMplKsKCw==","shasum":"ad36e56a43daeacf4d2b7bb16441b7ac30be4510","tarball":"http://localhost:4260/browserslist/browserslist-3.2.3.tgz","fileCount":9,"unpackedSize":55855,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAzrYCuav+HNKY/B+dasHVkOmU+ILl5nsnI+03bA/Y1aAiBgOK6k99zrpEEVlVZNdKoRaktHKCxYXvcsiThSvatjDQ=="}]}},"3.2.4":{"name":"browserslist","version":"3.2.4","dependencies":{"caniuse-lite":"^1.0.30000821","electron-to-chromium":"^1.3.41"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.2.0","eslint-plugin-import":"^2.10.0","eslint-plugin-jest":"^21.15.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","fs-extra":"^5.0.0","jest":"^22.4.3","lint-staged":"^7.0.0","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Dwe62y/fNAcMfknzGJnkh7feISrrN0SmRvMFozb+Y2+qg7rfTIH5MS8yHzaIXcEWl8fPeIcdhZNQi1Lux+7dlg==","shasum":"fb9ad70fd09875137ae943a31ab815ed76896031","tarball":"http://localhost:4260/browserslist/browserslist-3.2.4.tgz","fileCount":9,"unpackedSize":55986,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDyqoDy3kNcY3jUDLnTGqBJukTQ/FUrYEY2D89LoLCaVAiBUftcZfvvwTarPhT378sG75kJ2O+/HYNlhnCs8rVw5bg=="}]}},"3.2.5":{"name":"browserslist","version":"3.2.5","dependencies":{"caniuse-lite":"^1.0.30000830","electron-to-chromium":"^1.3.42"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.3.1","eslint-plugin-import":"^2.11.0","eslint-plugin-jest":"^21.15.1","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","fs-extra":"^5.0.0","jest":"^22.4.3","lint-staged":"^7.0.4","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-svi6zUwlR6uiQRwShFfNMSEWzwttsVqSFEcqlLOWsgJ4tYk0goE2KLNGzctsLUU3E1AGpES0cgiyzkvuFNIRIg==","shasum":"aa46a5ea33b5330178f3c91cfd85e148fcb57080","tarball":"http://localhost:4260/browserslist/browserslist-3.2.5.tgz","fileCount":9,"unpackedSize":56065,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa3U/gCRA9TVsSAnZWagAA4ywP/0SXbYZcbScOr+Pf0OOS\nK7bl1/lfsWX6TCBVGWm47NNuFkJjExp4x0O6Vp/Ti+GpgfgvPoPtW+GUgQf1\nF0/NxFElQCkirnfXWXJSAB4YxtIcePSTPezW2E+MeoEK6M4PWvMoygR3IoOX\nfENgmqWF5TUQQ5QMLv+3UmQgB/SMbEXTGXw+ihwVQhlT/NRD63sHM7929mAU\nolF03bok+GwcQ54EVlh+AzuXN5E0UDhDGe+OR5iEPNzRWO2szq5LyHYcoWCg\ndBl0Zy2e4ywDmZaq00InV+6h3Z+HCRE3r6+1qRt1VKrbXwev6/SdNqYFlqf9\nGGl+gHb4yHLpt2lGnJjoFZDkIZw6ihFqnRE1UCFQVtvv0SosetfkSWHGOyJq\nZFY+EI8Zhk9uICtTLegC2gVexS9maolR8PaVL9tLaHCJedv5Tmva8JPgZhfD\noaO/2hI2DNe0xqCfI5VcrYoOPKK+zSmFX8nIJ2oHoCTNYKJ5njdFUf3jRc6U\nEr2antTXT7fd3NFOZLVWpCpKLM6f16TRmtj+tJHwa2In0p9K0fjGKAVKrHSI\n6hXtui79+yjrz24PE0RbF7yojlt8OMhM001o1pNm5OhOQkoNOAucHzFmVWkO\nqV82w/ntcpHL0pZZUq0rhM2otHpTMUQTtHsopi4ovBBx6rrsHqxUkQkeq58Q\nWakA\r\n=sfqL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFMcrXOIoqbjwT0WeEVX2M9zs6Jigky1/kqHcdQ5eyVDAiAWJEDd6+bowyZQeAfmdZfbu7PzlIUJp10ez645G9HCfQ=="}]}},"3.2.6":{"name":"browserslist","version":"3.2.6","dependencies":{"caniuse-lite":"^1.0.30000830","electron-to-chromium":"^1.3.42"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.3.1","eslint-plugin-import":"^2.11.0","eslint-plugin-jest":"^21.15.1","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.1.0","fs-extra":"^5.0.0","jest":"^22.4.3","lint-staged":"^7.0.4","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-XCsMSg9V4S1VRdcp265dJ+8kBRjfuFXcavbisY7G6T9QI0H1Z24PP53vvs0WDYWqm38Mco1ILDtafcS8ZR4xiw==","shasum":"138a44d04a9af64443679191d041f28ce5b965d5","tarball":"http://localhost:4260/browserslist/browserslist-3.2.6.tgz","fileCount":9,"unpackedSize":57060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4S46CRA9TVsSAnZWagAAytUP/2PfpyYCu2TmZcRVhDX+\nk8uKEvkKcuBQyNXOkzb3UJSGJkpTw6QC6QJsL+xBFTuh7/6UqIHfTGBJuGjV\ndNzdWfozehkk5rr3CR3WcE5UiIBis2wSyZ7+/eVmIUGHzEfUZ+Pvhq5oOPlv\neWlTZgJcyYPS3NAE6V1kt7CKkFaKIUXqBO/67VB63Vo+F3SWSFHjDYR5X3pL\nuwiBAnXtK6bzl7LJk0KacOV10znVK8GWFDdw33BsAwpzJh8BJ/UtSzzV9iIG\nbmOzuztJbHAoPgMbr1fUN4z24w8r7pOVd4NZ9tiXUgpbeU3m5j7CNlWGaZPA\n7rdDBLLWLtJ1Tk7345Y7DeKVr6xuBJ7Vom0r+ADXz7cEh5XFaLmPAPp5LQUZ\ndG+oIp0ql/x5yh/SyOdRJP9KcsdazmYeta6cfHFzJLXngZmAp+Cn8aIbI475\nmKzU3lwVVCSBD61ZM5ruOyIEF++SWLnwhZ7MwOdRZNrk3Retthg0RTDp6fm2\nav8KMITQSz541TymzuguXZjMT+vOeudMDKNj+RNIbTgyYb564dZstFD2SMfi\n4PSxC2/A7UaOvAmUrmCsohWlSTQg9jyy3XlQs1+bSFWoXot1iauw/hturUOR\nQt/O2S2C1ETtiOWhXmyCvFK0nvDGZOFRbeliMp8bwyJZDlQKZb1VGN5Hu7ij\nZThx\r\n=W99m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFS0MLeRPMLGWorLtye1PejCVXLR+Saf44SEKMIy8EB9AiEAmkljx4TCiV0ZuMYcsN72Aad6pk71XhnhIP0DOqrZD5E="}]}},"3.2.7":{"name":"browserslist","version":"3.2.7","dependencies":{"caniuse-lite":"^1.0.30000835","electron-to-chromium":"^1.3.45"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^21.0.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.3.1","eslint-plugin-import":"^2.11.0","eslint-plugin-jest":"^21.15.1","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.1.0","fs-extra":"^5.0.0","jest":"^22.4.3","lint-staged":"^7.0.5","pre-commit":"^1.1.3","size-limit":"^0.17.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-oYVLxFVqpX9uMhOIQBLtZL+CX4uY8ZpWcjNTaxyWl5rO8yA9SSNikFnAfvk8J3P/7z3BZwNmEqFKaJoYltj3MQ==","shasum":"aa488634d320b55e88bab0256184dbbcca1e6de9","tarball":"http://localhost:4260/browserslist/browserslist-3.2.7.tgz","fileCount":9,"unpackedSize":57094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa89mYCRA9TVsSAnZWagAAOEkP+QGHcMyv3EMoBx46CXa5\npgrug/XzCvWogEKsLk0SJ3wppCJ49H49OlimTjMJv3qGVeXUHWoM7VZcoTmA\nu+MZiWEJFtvtIQR8vXgBwDWZLw0lY30Ws5dvwejQofRDPE+/yIDxaw86PHF5\nPrHzxAHVEQAdK0KOopc6VtNUyGVaeIarWdT2Ax32PSJrriWtWUYLAbJ+kKlk\nof3Xrc6F0d5E7WCuRKontX4+blYkXLmXFLHMej/nwbhcEXV59uNX4uh7aNnv\nvahT0qaJXzGoRmTJx6QJI2RCedyybdR6KYMPBxuAzVAK5/lqd/cC5NcheIId\nyeucuvMxMp41nOvFjMh+Bwy/eEkhd7EEK9IhCKGwkYyzBwXgYG+efseXSLcA\nGYRRK94qPP4l8+33Mo52MEqOTCM8Y1Y/K5DUpzOx3E/CoPap3kERxPiKOb8Y\nA2rOBxrN9oAWsKv0C/T+Tp28WIg5ZsN1xzFJ0svJl8YeIayvpxTp5e3yXAL/\n5V8Pehc9UJQtqgoOXgJEhtrEMx0rxfjQsPXoSKKPLnpwVmi6bFNh9ddNoJQ2\n9mUGgFH4AjAL0Ro8XRr1fj77pZoVZdV1KDaXnRuTGd6+bWLTq7uZ9lbJ3ci0\n9s4rzudzBuZqt+lPVbk3hsD4WGtTzJTPbJg/u7FZP1CVegQu8RpIP3Izzh3/\ngfXf\r\n=zzW0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCydpucKLqJbW/aVoWsMStH1vX6kVncJTcyfc6MS0YlxgIhAK9HXhd512WqtNdzeBDCAJQ62N0cq+5nMX1TBIyZZKXj"}]}},"3.2.8":{"name":"browserslist","version":"3.2.8","dependencies":{"caniuse-lite":"^1.0.30000844","electron-to-chromium":"^1.3.47"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^4.19.1","eslint-ci":"^0.1.1","eslint-config-logux":"^22.1.0","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.3.1","eslint-plugin-import":"^2.12.0","eslint-plugin-jest":"^21.15.1","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.7.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.1.0","fs-extra":"^5.0.0","jest":"^22.4.4","lint-staged":"^7.1.2","pre-commit":"^1.1.3","size-limit":"^0.18.0","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==","shasum":"b0005361d6471f0f5952797a76fc985f1f978fc6","tarball":"http://localhost:4260/browserslist/browserslist-3.2.8.tgz","fileCount":9,"unpackedSize":56991,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbAuJuCRA9TVsSAnZWagAA+K0P/1IgLg0D4Er3WTHQzOSF\njuPCMtpAOum8GPzqjf3gc2fZ4d0oACoS+hbbYc6GA7NenICLgwdBLs5ochWs\ntfk7fa2NYLzR0sFVUGvp9l/sLFW4D+WIaB/3+7Okyjy1mIgBIOr0lS0AVJJt\nTVeLVWZMT1aEh0hQsOeN1rCsUx1XakmPtjeBDrYJXIHXFa0nYVFp563DQIAx\nVQ4hnOrsUB3z5OkXr2ivEb7NFdetK8EfvJ7bpAQeuafbOxKaWmnAJKXXLBpM\ngg/+JC5yOuecelTgd1HsiR3THFsJ8lzOyuM8MHyDmf/8jmtv/J2DRasj94p2\npT90NI4QOdbng1ga2BszCxfB0nIBFVLek22GupLyg312jpiOx8dMc83bbGIh\nSd/V61kGg7lL/3xCyYaHrj8awyqUi5Dm08yoDJnOeJ1ANSkWlrCYIEjkDL5J\nrTRJ1zEoXgDdT0h2z0PVb5YFWtC/nF/q3YxY2lz3WhTaHpFRqk0Sc7mWHba4\n+vXvd/5jP/hdQ/mTWTo57thy9rfgqX8XT8EDAgk+66K8oJAQqkDZKNJ8jjI6\ngaXP2bVDYTuuqZLWwfVhPpN1KcqnZOam9ye9CCCiGoNbl4v+59641s0a31bz\n9YiIXGGI/3VoldPBMODSeOKhMYEnfQt/AX7fNbyYIZfe2YIp+9jM5ii2LnMk\nGRlq\r\n=wzf5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEEBlQwzNgzb4ZW6ifqFTu6EZAa33twKoCKF647F2EN+AiEA+oMFkZFIJA6yyJf2TWsV79knu1vXsUbF3XTjBsyAkQ4="}]}},"4.0.0":{"name":"browserslist","version":"4.0.0","dependencies":{"caniuse-lite":"^1.0.30000859","electron-to-chromium":"^1.3.50","node-releases":"^1.0.0-alpha.10"},"devDependencies":{"cross-spawn":"^6.0.5","eslint":"^5.0.1","eslint-ci":"^0.1.1","eslint-config-logux":"^23.0.2","eslint-config-standard":"^11.0.0","eslint-plugin-es5":"^1.3.1","eslint-plugin-import":"^2.13.0","eslint-plugin-jest":"^21.17.0","eslint-plugin-node":"^6.0.1","eslint-plugin-promise":"^3.8.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.1.0","fs-extra":"^6.0.1","jest":"^23.2.0","lint-staged":"^7.2.0","pre-commit":"^1.1.3","size-limit":"^0.18.3","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-fJq4izbUYHHNdQd/5Mco31HeL8U8dg5sSaj5boaDP17+aAe41CrxSZbQifIjaWw27iIilmy48z9PrVtelNJhbw==","shasum":"48703f1ed7ef981c6719e39e9444f20632b06571","tarball":"http://localhost:4260/browserslist/browserslist-4.0.0.tgz","fileCount":9,"unpackedSize":59927,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbMqFJCRA9TVsSAnZWagAAiFYP/AiRZM3BqRwjBBQRmM9Y\nxqICl/f+1PdIQwmh26HxFban2TqBj+3DC2PjoLfWjbn/UePQj/8/bPoWIH9u\nJCVdeHV4N0ZJFTQBMtYUZ4OIFbDahtTSszRpDONWHaOSRn5sRr4MeJ3Rxga4\nSlCh0MFGVl123GyDpzWkZa8MANmBWy34M/Yga33hdMd8NK0wJ1VVWNTdYJOC\nKnjyxWQxYcsnHBj0Tp4ghuRWkTXaaY/T+l52s5ooV+UthevozcFIa7DsRqwv\nw2EVs38U9xbdRgBOT0j3wJKIIi9//rZiSL2iYAKmBcOiqXWnBGkJUnd44UIn\nq1QUjBb3wvBf1+7m99QuEn9tWLrjbYcmRBTQwgPqu9WHCPAJRNRW4MwvOHGQ\nJ68+zs5AsCIKwSKmB12vO/LJhLI1WtqlzHin7mab3rfJCeJRBZrEqSgGvN/+\niQQVC2gXooXkFzvBsCldFoD0X0ODB4aBD7scwJ9FeJ3JlifO8A7BGDc4pwCu\nc4MM+iNvrxFikchuOFYeX47zBvbQVXwTb6q4qZpdfJ+SHpDzluU69U5/MtWB\nqmnEznqhqhEyhcoJTbgZjpJo+aYTXO8UqP93rIQhMWmp5fFAjyl0cRDz6hCU\nhiFA4uxaMvKdBXnL+Jbfmpn9nfMFU5eFjr61ngIX3DNMMIigy5Wcu9rx6tMj\noG7p\r\n=o4QD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEZfLaMstF1lUvgT8SCIE0eu4YIWWpVU4kTGXZyEUkutAiEAhhKctwDNQy7FpmA4/jA4HrsvC6FRhmH05Boi5A0L+ck="}]}},"4.0.1":{"name":"browserslist","version":"4.0.1","dependencies":{"caniuse-lite":"^1.0.30000865","electron-to-chromium":"^1.3.52","node-releases":"^1.0.0-alpha.10"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-QqiiIWchEIkney3wY53/huI7ZErouNAdvOkjorUALAwRcu3tEwOV3Sh6He0DnP38mz1JjBpCBb50jQBmaYuHPw==","shasum":"61c05ce2a5843c7d96166408bc23d58b5416e818","tarball":"http://localhost:4260/browserslist/browserslist-4.0.1.tgz","fileCount":9,"unpackedSize":59133,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbSeJCCRA9TVsSAnZWagAAKfYP/2G6T4Pq7ELTY7PtU8SX\nXr5lXpjVXkQRob8YfNnc+nMjLSNCyih6eqdX/H5v8p8FabBPAERz769vYNqi\n8HRgpVCE+AgFNMhKwo3ZSW5mVz30VuXnFvjkEbnA5OcOEBU1l+Ttx7L0ObWd\nUHaPc8Zcf1yf25isYvHoPKG08Kq4wkc7hQu39HcFCCgqxvdRobmHwA3Z2Nem\n8kPCIedcUJI7t59O4TJmUSkMYjFCVXtwPojxNcFkLRtrJa/aTi0exG/DThy1\nFM4Pmf+IPIouyLl5Ty5TdDBP1uMuNXgnPPmn5d24FAf1DwS0RLxckkkzwwbg\nxMB6OvDgapzjq5RJqKTD//opyA1ZxlxzANWunmxy6psjxXsfJ0rIdYntEd8j\nSlYvZ/DEZiBoDqllgeB+L206ginZdHE/r2KzmwkmhYWKvOgOfVvaL+qf9Kym\neb/qwq7Q1QTVxqhRSdAPx3kpH5o40DC1WvPulFwrp5yVPJjqcUZARB/2cGzI\nnzl5O/mOFychfmpZmhmd7+DSFwtNVFk/IiulmU+nzXcBpNQ+ofTW9Ff/WkjP\nkPaTX3tAS5/fiUlxOB1cgMEyYvBqc8wHS33sTL9+PMasM+lY1sjPu6Hhi9JK\n7Y6SIiIyRnvlcKE9HDkeGP3Dhd0GrJ8vR0IbaSiL9CBuWWVUa+2RwGaAMY9V\n9rkR\r\n=ULpe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKC+H/ULDvrNwdUeE1xBFfweD9HR/pE/MM7gRMrycvAgIgfD1Gg75Dr49PXellONag/Cmy4duMhLMskPoPFuMfa+s="}]}},"4.0.2":{"name":"browserslist","version":"4.0.2","dependencies":{"caniuse-lite":"^1.0.30000876","electron-to-chromium":"^1.3.57","node-releases":"^1.0.0-alpha.11"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-lpujC4zv1trcKUUwfD4pFVNga4YSpB3sLB+/I+A8gvGQxno1c0dMB2aCQy0FE5oUNIDjD9puFiFF0zeS6Ji48w==","shasum":"294388f5844bb3ab15ef7394ca17f49bf7a4e6f1","tarball":"http://localhost:4260/browserslist/browserslist-4.0.2.tgz","fileCount":9,"unpackedSize":59263,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcOSXCRA9TVsSAnZWagAA/r0QAJy8eJTgERTA4CmPX4Vh\nDKxpMY6udeZemkEirKCBCOjyvu9swpW9+POsYBUN821jPWWajjrdM9RkIwD1\nGeeK6Mr2ABA+yo2iBcUG6pIL/4xYQqYqckWdcFkUO0hVzwWcgQMl2PBj5PJw\nO3TNMsUkaym0cDx1Izc2YZRmuiQGQHMho6IhJmpzTGT/OcaLWtf9hiKp4MfG\nzVWmriK/HAGX6rMSnltaPdsYKvwzrWQGNd5DcVniPCv77hKIOkKvSfMx28Mg\nG3h0kZd4JqeJGp+YXMRpGEHNHEug+viJKiHLKm4X4IED0waI95Vnn3Q1Kvny\nlftQvPy2tHse8xfwUbeGEo4j/HvF4YOwERPqc+wT3Ks7yZG2UTSJKbuj/eM1\ne0KYA+rO1UIGJGiEd6ie+5ElHL0kCrjf6LysAenBmy+eAb8kadwagVfSfs19\nd9fJaRg7xmuXPYIVU5fTzgPOKsLlnkp4+2mvu0LXUjJzkfl3favi1lkpaNAM\nLBzDaR3ETcOH8aJ7yo7MfvYIWBZb6ajWpoaZ/nFuOXz0oV8WNjz9lMJI7Q0J\ngSsPcLW/YuAxeqv4l116HufvVPZdDxKrQbXQoZ/I8mbaRxgAbW0RUGKllhT4\nsDculTWfsfY0OSHHYIDBK64TZe7YT996nmZGs2TRMBU0+mBts/7pU+urRX99\nAsyd\r\n=daix\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDw4IgTvkKXx598q0gG6Ma+c3tIaagVcVcigvPgrFs5zgIgXEbC9YUmhsgooSBvjlam7ZldOVKhJzWHlcUexObezD8="}]}},"4.1.0":{"name":"browserslist","version":"4.1.0","dependencies":{"caniuse-lite":"^1.0.30000878","electron-to-chromium":"^1.3.61","node-releases":"^1.0.0-alpha.11"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-kQBKB8hnq1SRfSpwHDpM1JNHAyk9fydW8hIDvndR2ijTFKIlBPEvkJkCt8JznOugdm12/YCaRgyq/sqDGz9PwA==","shasum":"81cbb8e52dfa09918f93c6e051d779cb7360785d","tarball":"http://localhost:4260/browserslist/browserslist-4.1.0.tgz","fileCount":9,"unpackedSize":60734,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbfozFCRA9TVsSAnZWagAA4m8P/jdv4i4akkcTCaU7yant\n20YJivOvztPHbs8Sz1O9N3cbc3mmLm2byWD+4Olh3+a4m2DjLBW+a5ZQDIuq\nOFpR/63UtDAJ3rr3b+UpQHHOvG0NbI8pkjDLLoUFv5/p41rdTeRauf30pWc8\nIVAQGQR4HTG/fHN8vh5o7UcBhRlCPxyjnhNYbRNp/9mTSeX6qhURloZvOx/U\ne7EQcx6XMOORTNAubHZGJkXG7TaKjbxvqe/WctkmFODoyWdF5U3jESbdTbXH\nZnkWQbzdli0R8AtFIiOo355mWinw4zBuR0UNOwgMZZhXWFw5AdkAjkzhrck7\nLYqbxz9X0wtrcqhM0lRC5I2Zp2RYxmPvUQvxB4+VMn3RhVM3lTSpKGiVxfWT\no9iekIkBZ4gKMBlJHmWfJebY63Z5gsb8/BaGty1+BnTSr2/Jb0M0hR7kMryu\nZsn9Rb+SjbC25WBkXzw8rd1C4fAs2JDfHaWaOivuoslm7k8vIO4db7CCEHpR\nskpkPgiSP9dzq5Tm9t0hA7arXMX8eUmLEADS23ASdMe/lMvm2M6874UVlTUB\n5I3pspZsE4DTwn6t+g6VZwnjBXaEUUhVyTpaZInJ8CUujTdbQlMiUz2+MS4Q\nnSeXX/cx5jR0T9lr98HP9mLrGSVWw4QVZOZjc1cBUJYvNd7m8//CYYqvkW/r\nqRKX\r\n=Z0Ao\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQ7Wcrp4K1eYDbF5g1XWif7boJ/IqUlOv2S9YQ1USdDgIhAKQxbuhtvWt+5tnuydBeYvtOdysSxQkHUn1uRVt1za7R"}]}},"4.1.1":{"name":"browserslist","version":"4.1.1","dependencies":{"caniuse-lite":"^1.0.30000884","electron-to-chromium":"^1.3.62","node-releases":"^1.0.0-alpha.11"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==","shasum":"328eb4ff1215b12df6589e9ab82f8adaa4fc8cd6","tarball":"http://localhost:4260/browserslist/browserslist-4.1.1.tgz","fileCount":9,"unpackedSize":60761,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbj4+5CRA9TVsSAnZWagAAEvMP/RMqHQAFmsuUQQ55ZYrU\nrCLtRKazA//LFzNLmunzAyfWWLGAdKg/VbdqRHQmXuRn/FhC8uoGm7u3nexd\n4fTetJ8VdjTHsyadd3P0AvnVHXQxwMfMS/jUJR/6Xr9bk0XD1QfSHKk9dMMV\nkNEfO6cxSretQY+4JZgQpsYms1f4ZPUpAVgC/1TiREnT8SnZI8yjVNCs6xtz\ndZ3YacwKR5vsnC0Qd5hJNgZ51fc/O2xfXvc0qxMEpzzeQD34vpMYEzGPfJJh\nzjeBvkuYYbcWJrAB+qDS3FZYirVkDPQR0HdmrAD9V+WT0d7UaQxCEwlGWW9t\n5f5GAPkgOUnuUgBu0D1Q4bo6WJK8iJWPe5bZH0qWTMBbV2Ju8N+zbEE+Vfmn\nqmsY3byXSJf0gSirPg749wIc/cVbBpI50cNrLh0biap4BodTjrstUAXP0a9V\nE2fhVZJKkewEXCjnqYRYXj+YR++H6bNvfdvjPrxCtdE8v4mEAgFwu9zscVTy\nf3I7hC8TYzT/DVHmcpdupMi/Y+7Ap2/6sclJRdSlzJIz6P2jDrrd7ibS1q0I\nthyEPGcoyLqBu7GXVSQm6Tybsg11p0cJ2N+BEm51ySmoZeVTEi9j+w51Itod\n3dIC+k5NVtyJuKLOHS5TvhKxuh55DgomuRZEf71E0ZiK2f92C2RwbEDrWR3Q\nkcEp\r\n=6Mvi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICPZorp3cOj0Wz4dGUbuLIGLKKwwweU81wSDs+6DrrqiAiEAin5rqlEscHQr4JNhvjpnQN2R84Lcrbfg7dyRP1qrvTs="}]}},"4.1.2":{"name":"browserslist","version":"4.1.2","dependencies":{"caniuse-lite":"^1.0.30000888","electron-to-chromium":"^1.3.73","node-releases":"^1.0.0-alpha.12"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-docXmVcYth9AiW5183dEe2IxnbmpXF4jiM6efGBVRAli/iDSS894Svvjenrv5NPqAJ4dEJULmT4MSvmLG9qoYg==","shasum":"632feb46d1cbdd6bb1a6eb660eff68f2345ae7e7","tarball":"http://localhost:4260/browserslist/browserslist-4.1.2.tgz","fileCount":9,"unpackedSize":60837,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbsyzhCRA9TVsSAnZWagAAXb0QAJAAi52Wx4NFgaFHQCq4\nzPsunLv38G0deRqIca+kg+lD/UCxQpVF/RRlvVWwBWaoFJakqbLatrRiZGpr\nq/+lSMXz6VUcL4SHQWql7OzpfVYmo+qPO1wk27/eMrfbp/0t0ZKMy2u3XIXt\nkGZC7O2n8AKHPMHmO39MsGUh9pCOeEPawSCN+Yc0C6T0xy8LthSo+zHHjeGT\nntzi6lm895CIEGMypAFb8iQ2mMZcnCv5nybPiYgULipmuAAd6BqWZAXwVeb1\nUbUrU/hrZoM6Wb0G2Qbiqp3htM/bhl25L77GX007kh2MkhXSCaOmGbwC71Xy\nwNs3FqtzjFJs92j9btSbtk4RosnYBdCt9TNGim4QULGgW+A0Ch1j+odpprxj\nwZjlwrbGBN76TkWSwRwN1hXDoJlDwTuOwNXYg9Te+kr/pGNySLhLFkpnW8/F\n820D6uY60njQ5SIvzjFplCLlgaehApumrWWmIT1+EiDetHjLOColjvX3xHe4\nPkBzFAYo4/ciUqJ7m4TawoOntiXHWkUAfkNB8YoGALvnMog+vyljGQE8hDGD\nbL045F8MRNpNqQekG7nMFKTeF7/1NpIJB9uL20vfAPtH1NJE9pfnsrpU7vtM\nta9Yw6drnT1M+S4ZXnWOdcBq+aUkoINWfTQgS41rT7+hKnBJayzIqi2ItQMq\n/Gqb\r\n=W+iY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3VXJ+FS2crQ03wXbL8SMjN0fiZhXw2AdTK4c06qGt3AIhAIvc/1LWi7ba+9YQUYoyfa3yjRl8wsA7MKuzGqXg5j3C"}]}},"4.2.0":{"name":"browserslist","version":"4.2.0","dependencies":{"caniuse-lite":"^1.0.30000889","electron-to-chromium":"^1.3.73","node-releases":"^1.0.0-alpha.12"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Berls1CHL7qfQz8Lct6QxYA5d2Tvt4doDWHcjvAISybpd+EKZVppNtXgXhaN6SdrPKo7YLTSZuYBs5cYrSWN8w==","shasum":"3e5e5edf7fa9758ded0885cf88c1e4be753a591c","tarball":"http://localhost:4260/browserslist/browserslist-4.2.0.tgz","fileCount":9,"unpackedSize":61927,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbt+DgCRA9TVsSAnZWagAAU7IP/ji6rWCg5z6Xr4LFF0nM\n6JpHNWXr1dgq/dz5vFNbfOw032p8zEUQYS9IW+OXOXR6EvFga7ClgBhsvURJ\n+e5VkU4PEXofhzUKnLy8osfQCCM2M1QCB6xf8Zf/BYzPQaeZksgfFPg2Xe/Y\nWaS6EglYlDuDI+9sj74DQ5KGOAN4f9Os9RkTp9a/nukh0R3175NBA7rB7a6R\nDsHw6oisVt+sd54xvyozMJUsUx//H2Lc72is41KICr/NBVIz208azaOa0u2C\n/S/e3l05pJPG1/ucmJALZnXVQWXF5tLcVMkO13qKkWEAPDR8J5QlOLxxA02P\n59UU5/sYDPvBDAScEj7jRbZtx8OL/eb3ApiqrpuI0Ij0HyrN42X2Z5fKynly\nIhvwFSL7cEIOGM8IHjCpdXrNrvhVc/bBx+A9GgCwckUAQwBwhH5EjkdcxG0e\n47zuApFLQblHPjXw5fsBi8BrNJTUM7Q/J1jrattTH+AohjYGdEMjpoYtH3zA\nklIfsL/XAwM6sV4gkLuFb2cmYISyL2q8N0+4ja9xGfY1NpV2XGDHrjI5I2MZ\nXr4hifsNxY6SG9Z11ntAN2U251ic4TskOmGvAjY4uQDcRzgBBoVuYnKXvkI9\nyw25sEuzwqy9BHxwq2fFLye+GQ4BhLKW/X/xpExW2rmFC7QYb6LRLS33b3kq\nD97R\r\n=olnM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFE/MnBiNiL1ALbeqIBWh/d+h9BLk0s5fgjPU67h+soBAiAp8GgZzb8+LVJATXVRfclYDTxZpTctKqi+u6z4ixKC3A=="}]}},"4.2.1":{"name":"browserslist","version":"4.2.1","dependencies":{"caniuse-lite":"^1.0.30000890","electron-to-chromium":"^1.3.79","node-releases":"^1.0.0-alpha.14"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-1oO0c7Zhejwd+LXihS89WqtKionSbz298rJZKJgfrHIZhrV8AC15gw553VcB0lcEugja7IhWD7iAlrsamfYVPA==","shasum":"257a24c879d1cd4016348eee5c25de683260b21d","tarball":"http://localhost:4260/browserslist/browserslist-4.2.1.tgz","fileCount":9,"unpackedSize":61994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbwn3YCRA9TVsSAnZWagAAKJAP/jr/qBW8a/hmXEHbvLkS\nRaefjR6Sa6qbfqgK1bhkh1zVePbAq2jrA+dexTqtqNfkfVdeFdqqvkXv4tiB\nNHX2PVNwFSx69FRaaqSx2g2RKt0LQnWPsls4KoMXvRzWW2tKoxigz4194ZeZ\nyY1neh/AwsYM2SNFvWOfMX2iWX4L/uuOYp4ltADn2ZuyWVlPi13qsPRHtbhZ\n/w/Ldn34sIIKYzX4O4mE8p/F2MjgL+gUccXhpUi3LRKLY2ve3GSegbtWezzL\nfcfUTvwpvgAETtsf3DwZ6NLuaTm1cnA2TIao//D7JaVBDEZ1qhfisQ9zOlhO\n6NkGP1hbgK9oJFf6sfKZ+xfLLkNqU3kkqdILV50MdDGzqr1/46do+PKYsS81\nMowH960ogWTYPEtuoOXo2gBVJJUft+wGTJyPfsRANQ9Dyc18d37t6CaHfBHW\nDZraz1tDVZEtcy7pLFRfJu0YwwHVVxtlnN4W8JPQBLUTUki4uqA/Yf/uxph7\n8cQkfuArzLb1KEH+icxiBBkU4q7pkpnTj0j6nZut3j2ZoDQnPYzeAsdk46rY\nunkVEBtDr64G5ycPupxImz5Sos4sCnlV7Wtf2PbaYOsiaZn7UFNM9RSdiSan\nJFsMhuomoK3wWD1SWz8UGCkzPfoRo2Bim7tOZc3Lgsh/qI6cwLCZtCYguB5v\n2Xk2\r\n=Il0B\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDZ9Luxqhkwp5AR0usud1z4QAn8PXi/SfZGYknhaf49zwIgG2+kCECuf4SPq6Mnf3HUUpVxzIE9M+9qM5DyOovd8/w="}]}},"4.3.0":{"name":"browserslist","version":"4.3.0","dependencies":{"caniuse-lite":"^1.0.30000893","electron-to-chromium":"^1.3.80","node-releases":"^1.0.0-alpha.14"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-j0jLqo+6ZhFWvTjEIcDyR8LIiN8pA3cUrT/SGAs0LPp/cKvkRpCnzuxtnAW+sOPLTic5wfb+TQvRX2RTN2wo4w==","shasum":"779a235bd1ace0f3841a9b294df4cd47ac046c9d","tarball":"http://localhost:4260/browserslist/browserslist-4.3.0.tgz","fileCount":9,"unpackedSize":62081,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyrhPCRA9TVsSAnZWagAAkNUP/2GeZGd3Aebybt/JNgib\nP5oxz2aII20PcgnGptTiKQ64ItfQmw2vaaJapprWV7NosxwVZT3uTRbM29AN\nMsQFh7++ybPIt20wfUbZROv9ZIHRowj4bYMO2wdRO4B/XI7Jxtt5f7tqTd8b\nsZj8hvgx1eYfFd0PuYsNP9rXj0D3Xovl20fuWmlMJZFzZoHDwJ4qFy6MGB1m\nchKB76RG6gnMsBdPvmWihYvUm1YA5oiLH0uF5/QsR6ks0pBv0GV72I/ebsHH\nkN8USZpZc4PWQu7LyAAyhZn1G1qjvJLpSl5aeAi3BdIuwrUlyDdSsI+ceJYR\nTZeX9qDuzn/EYnIvLmM7LbFR2Sd0lkfr2Nx1GhL78bRxHFY8f0HojVlvdnrH\ncOR5xeyhQ2FHAOthT4n/+fWGh4zIYILQ86cw5NWUB3QN6ZI0LY62fuBwERWY\nJQuEUx9DUidEe5v5/H229P04uN6rJZe6cGA4r5uXsBa8XvZ178ESogKrLFZD\nj9IC0cgb7sh5kJEuZmXSEr7S5UPrsJVwRxMVnY0f0KD1AAS4cRMVWyvmvD0X\nb6NgN/NG1BcCxhyfYTv1cXZGwt/sQrdTxDxcBz9clpgQsPdHghCmJg8UcY5B\nawBxMzlKycHOmWRFmn4ahXnKesoEMfYYqrC9TBk7j989vpdzlGbMtm8WJw2S\n04aj\r\n=2Ra6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+YX1JExWNIrAaNegqVzt9KrrYzz3ZPbL8tvVruoxv8gIgLlJ94pgD39suZlPBwNdRGEN2ElPLmPHe29ptz0Gbhqo="}]}},"4.3.1":{"name":"browserslist","version":"4.3.1","dependencies":{"caniuse-lite":"^1.0.30000893","electron-to-chromium":"^1.3.80","node-releases":"^1.0.0-alpha.14"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-rlvbN4EERDFJcwI8qzmRz48a1zqvwE4L0G4d05EjH2nlswJqBxCXByafWhhCpVrHOsnOrDMtVjibPHdBElb8sg==","shasum":"453e46e74b0663ec5d764cdac3e5ac52bd776038","tarball":"http://localhost:4260/browserslist/browserslist-4.3.1.tgz","fileCount":9,"unpackedSize":62604,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzUVeCRA9TVsSAnZWagAAAB0P/RKgCSNgZl6KOE2bnM2F\nK5r4T7S29VCR9l5HXXFnNaHAJRFQoDI7Dz3fMrRdtCDxca65HCz7ZjG31wiv\nyR2ZDGYvrbnh0hO1yy2bJ72Rm6+sMY3w003B1Ngql85nFTZKmsLC0k7MjRdq\nn+W+sdunEn9s3Nqd2mnMiWdDil/+KvfvnGBjNkV1uPbCoybAVsbM6TncGzyh\nsEBgfDTojvyHaeTuPvOTvuEXcUjnAJRBO0eyCmZzWkA3Sh5AnOEcvuCURMk+\nK5eAPt6gw9Jz0p7IuUl/U1rmQPM2ILzoOHOFqVrTFObE0qMq5mFu7VCr8mzH\noy5oGFDSKCSywrZrZO5NvZJo7X3mCrhnPfmExJSy+APap+dM3jOEU0UqYhTb\n3Hk6GuUDZO3l/1Epqsspt0OMpbAR4e5tBMz/EidDZDV0HRGRekN2HJvp/6nT\n6gnTEl63QPDIxBZNggtLMO8OUcls2vN/Eqr7U4Ezdj5sJdxRiT6/KJa9MlNf\nTBbSF4/JJLLgDog8bvipdClhWOAi5KI8AtaF/2LaK7O329aEVdLMLY9my0i0\nbdtoFS/1DO7vPZn85272pJ7hQSgaRM+E8XAqltbiFeKbUB6FT1fQZayWpV4v\n/6e+Z7vTrlH+ieiH3tXJjxC8R3WUN13eYcUF1QlBEXPPo9GN5Dywmp59L+hK\nIVCF\r\n=z/CB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDR7Y/2NQngoSYpQyD3CZ99rQrIRUZ7ApYrdG0UQGPG9AiAOzOeNkL0k1Il1MO6LZcqURGdsfnBytZOFlaXH2T7Qtw=="}]}},"4.3.2":{"name":"browserslist","version":"4.3.2","dependencies":{"caniuse-lite":"^1.0.30000898","electron-to-chromium":"^1.3.80","node-releases":"^1.0.0-alpha.14"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-wgZJWlYcDvsjRtf8socmAHf1nXq88KrQLB/gMYHGPUc2bzPWsgltSXwPWYHx4Sw0G9E/XGNW5wJDaWlpHRMpjA==","shasum":"a5479f20fd387357be2d01aefcbbdcaadffb4d75","tarball":"http://localhost:4260/browserslist/browserslist-4.3.2.tgz","fileCount":9,"unpackedSize":62961,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzuzcCRA9TVsSAnZWagAAM6gP/jxubgFc2ZDk1kFBNsMO\nj651ieLVTPxtgAokbfWePSvRbl9nWNqyZmGQPmbmjhz58U0hpdqiftfbXlrh\nF9fwVXPt4yu6Zwl6cEeN6uMFg7Ra8OQECZGW1WPC7VW/fLhUFjbKI65EyXeR\nTGVbiwxFjEbhvT4WPEIH0kHvQRQZZwYC+IJez73Qhg6j6dr2dZY77EyoeOBy\nevD4ZVqfA1cEWFic/GYh9SxT/sJZMyf9DARJtIOM1w+crDgsynDV1b3tc08L\nII5d2njOwzHGmFSEEXrBshvcQeBAt1/7UNSyCZxfYijqaCYhlTHa9lvdqNq3\nnNKMgHYeSVD8QZZxurItGNEz36cfK011oXm3f5Ar13pKTa+ZIoiOe9m9BKY2\nASLe5LrWSt+Aig4vX8Xn/JmTYJ7n4gpIwE2JkmPDymwZawu0un3/+b6uaO+b\nZsNkBOfbm1rl2mMo0FQu+66U9DoKeCiDE+BrZELTi9yTBDQTh8wqHm7BLRQ6\naUKMLXm3CpnFwY5oL36TybFYrL6pgW1ynrzK14roWWjnr09j8ffjW4ltLHzn\nDO/FDySkrsX3VLVUWfI8XHzmybklhGLTf6OqrXa/bzKYnX4DMJZWMTMveIPy\nbkUDAhAQtHDoLFjoPiyEoy4AkiIfphflAlGEWtO2hzLUzNzawuvg5Ls7W4sv\nAn0/\r\n=6eM/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+xUROL3D/maZBl8REuvmDrbxwQxsXxSxq034SklzfYAIhAMM+FrkdImg2SW2WeSyyjIzAs2eq4mnfbf4HariJC7Y8"}]}},"4.3.3":{"name":"browserslist","version":"4.3.3","dependencies":{"caniuse-lite":"^1.0.30000898","electron-to-chromium":"^1.3.81","node-releases":"^1.0.0-alpha.15"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-6h84UD1mmHeuQ9IucX6yzBc+KBYcBBTLYt2CXtY7GYCra6iE5kOm7oM+zuGw/0tjGtbJxjm58OvxSBmogEMCRQ==","shasum":"88a7d9ce2e5db561e160ab660bc59cb406a0c41d","tarball":"http://localhost:4260/browserslist/browserslist-4.3.3.tgz","fileCount":9,"unpackedSize":62997,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0FiHCRA9TVsSAnZWagAAm+AP/RULPWGbGq6jZ4MtMKoB\n9kKd93HApnex2qor+eFo+hIvkG9pUZKCjBlY9xABSk/FBye2uhHEXVNFIIVZ\nJi3NiuPeppnsiMcz5pnqrd1VVwbi68WSJ/dW6um1me8ZXUql0Bvhl5EHFRfW\nTqCbPUY8xhilwksrzwI7yE9cu2DswhAUsZS7n/jMDd3KkbFOtw5o50/iSV+m\nqPErcVA4daNFsMFZ6ThILEODK7367fiUYD7abMeJpuK1b7mAoVdWuq2ifg2E\nLxzWXiWJstFc/UfXTcxl1tiP/5IfRHK9WoIt13eeurD4hVkVg4KV5+oJ4Q1Q\nYG2LZ8rKkkktjDZyFFgQhUr8aBwY0GIyvSCPYjCv/JC65iIHP1JJuUnazAwf\nHXeLIcI6r+7KuDU/ikZvWnLVGmpDDmldFC0jD8eLUmBIx7Ga2OjozKgZJacB\nvPlu1elRrvK0nQknQ6RHdMQgGmp2HEbMy5PliiKrLRUmfosU4KPPVzClretw\nXegE/ZZGDTgsJQpuPMyxubjDvG87dUDgeD+9jmQdKoKX8SfsmFdOY4gpo9JS\nKGMJaOSmZc2y7sos3S+94SMHbAPFAl3f8v2hlYSLElA+OgHh3LmOR9PoXmTn\nU8+Mc49INBZ6fbczvENC7Oc7ukgJn7REX5qdzNmdkLdIVMpuWfAXbirM+Sro\n6xXc\r\n=QiKx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCB1/QElLPJzRPAYbP5jRfqspXWzt9WyIM46njqFhChggIhAKbQ5euClWwOrzrw+ugIiNzL18chTojPBFIHoaC7oNLP"}]}},"4.3.4":{"name":"browserslist","version":"4.3.4","dependencies":{"caniuse-lite":"^1.0.30000899","electron-to-chromium":"^1.3.82","node-releases":"^1.0.1"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA==","shasum":"4477b737db6a1b07077275b24791e680d4300425","tarball":"http://localhost:4260/browserslist/browserslist-4.3.4.tgz","fileCount":9,"unpackedSize":63067,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb1PmBCRA9TVsSAnZWagAA518P/jiakX/hqUSFrdgPkFyY\n7bxMM4jOUetwRi4/NiGK4hzw58hWpjoVI0yz2ZHar1TextufOgXm9IqaV12T\nRayZgBPh4UBjY2ykBvf+z9E/ujj4makWVK/fessBNMbjZrHnlXDpYal2A5yO\nwLvF25egtZbs3NPhsnHTx/TLCKxgq8p1U4ybxdLJJckNLpMw079jKaQrG9xd\n+olImOQVBjA0bJhVLRqwt067gG5CRHWi8rvhB4SC7lQzqRGrNu4repIbHGWg\npXdx/9uRldiNNTayaXo5WAYVXhFOhjF5K2YPS+hLLv0z2Q9uCSToiGwYsG+x\nh/1jGtQPBV+YVj6WZwt36m46d7Mq1vs1qaa/CGiT6HfXYbqJ5JlilzviecNI\nJUk1wNKCLnYU4mGAUqe0lKFwOqb1bTJPCAYT+MA5LiT1jJecU2+2AD6esZrX\nDUclupJiye2GOjOmTketwZQoJ5JF0IN5ZoF6nNRQV7Y52W+ZNltfe8mr+mqF\nYlF+BoMdjC7lyfIQMSk05Y0Mjgzsk8VvMb5529dD97YhqwZ/KvBfHoJ/yRim\n/8gYEk0Yt6d3iA3/MqqlOsOsCC44atdhZZ8c4wplrt6knmrEPIyHCqDSa7RU\nGefcPS5qS8J2UpWN+5zZefXiKhJmzkPmROi1lYLBSPv3w1UWfJIeoffwwI1r\n9EJ7\r\n=RJJY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAVXeGyyh8IvIcTkMMPYxmaG3kynvfqsPA4pAVds/e+KAiEA4wK5XhJMvAgyUfaBXyODPFeTB1oiqfK9NJF0DlMyuF0="}]}},"4.3.5":{"name":"browserslist","version":"4.3.5","dependencies":{"caniuse-lite":"^1.0.30000912","electron-to-chromium":"^1.3.86","node-releases":"^1.0.5"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-z9ZhGc3d9e/sJ9dIx5NFXkKoaiQTnrvrMsN3R1fGb1tkWWNSz12UewJn9TNxGo1l7J23h0MRaPmk7jfeTZYs1w==","shasum":"1a917678acc07b55606748ea1adf9846ea8920f7","tarball":"http://localhost:4260/browserslist/browserslist-4.3.5.tgz","fileCount":9,"unpackedSize":63874,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcAiYSCRA9TVsSAnZWagAAO7IP/2dBjtOAUh3CNmT8aju2\nWuSzQEFBn7DpeYkpsq+tO1pWkIT0V/BLHp46dbVF6IN6x6t6zBqgMkj2x3+U\ntlPgnPpdQa7W84qK4arOQkh8uSo2AuzbEEa+2SOlzT98bMLwKIYmWZgwlc90\nhp4pQr7TFnXzjPxURqlp/31nbqiGou2N7SRR7fjVqKmu5U5uS9fqK2HRaosq\nNk3VJ0UakiOUUTRvw2A3qhAoJrb5SGx2pzytiH9bFF5vHLyyonipYjpOjk+b\nlYNHsnf6x0v396GppP9lqtbS/DXQmkWyXFV9xfs2oDqLxZOr8AIJli6KefsS\ncNRCRi6YC8JdTBcubbVgfJVjRR0WIE+EORk2JC+GFge4pbccYo7t93P1amRF\nXA0a04seH9H+qV7oHMSNp0+/HwcUdRfvfiZcU1ABLW/oiaYPzqpEFtEMn/6l\nzehg6z5TlKX24dFXR6PJQMvXhVT7P5cJZQftVkG84q6liReydGywe6FoQnNZ\nyITv+iBKb31AlZcSoPzMms4563/VzkZWkUwUeX8JQvHSXGywHMOl1WKFi4fD\n4lOt+yZPK36q36Cn4n78bTB4e4S6tNdRhyECptO1N/kW0QDXfL4AVhVmLnSF\nWZB6zkHxEb2Fpo9HFc2oPjOEdh4MCgR1Ef6U2uQJ2950Qy3p3tgB005eGn3o\n1Swc\r\n=ZhD6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0Vi5vjBpBnd6liS5xRJYuUEGHVavCgI+J+BxnQNkQUQIhAMIsIbF962+TwvDsJlIldAccyURzHgRLzRAeD70hns7K"}]}},"4.3.6":{"name":"browserslist","version":"4.3.6","dependencies":{"caniuse-lite":"^1.0.30000921","electron-to-chromium":"^1.3.92","node-releases":"^1.1.1"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==","shasum":"0f9d9081afc66b36f477c6bdf3813f784f42396a","tarball":"http://localhost:4260/browserslist/browserslist-4.3.6.tgz","fileCount":9,"unpackedSize":63953,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFFjlCRA9TVsSAnZWagAAIZkP/AsU7rbeUBCKuvlpefX0\n9FOYJ/woXNNhmCWc8kaG8HTR8YU5DTgH9abLDnWznot8jT7dta3QMyU4MID0\nKP4fPrLxylVGTOcvIgLUK0BxM+KEP1leBAkGEtPm3ILbbmAUsPtLAaIBS/0c\naO4fmXATfKC6tncd9mum4giwfmBdLFHiLhdj9W6EDnOD9RapL02qx/xwhdB0\neQUftUL321WLXr4YXH1As3NSWsVKLV/aC0+zKGGaoKC4dt80zGFkl6WjYA+4\nUyn4Ez5dffTZaDiHbtoLpdx5VB4t4Z4yOAZzAuZp3y7+hbXUBxeGCpTLDQqm\nOCn2hmlQRfNYwQc/aRkrLwsAmcbx14TQeMPQhQ9Lt07/ZgDPespiFc+W8jyv\nFB/zpxigIDtzBAnxvZNBWRKZrxbIwo2DrVWkFZz8Q23UEi82I69bbgvOVKKF\neRBm+pggAREUaZe+7Ev1YkflfRaIwomxKCK/IioYtl4TDh8r7UhQNl3Uj+nk\nc/YSnGpCRUMz0dlcB1JkvsIfosNLJ2Y2nyLtJrdHHxCXIcDuezOZUktJMCgZ\nIyAWBkRdt7/V8HnnTwHC9LFn4DJFJ4/lJy4hpZW/39wZWmcJ4oi+YSoufo0N\nDIXyCnXh5D3CJMadYHZDbcFoL9D6aT3IY0zuEjPAbjXRTDFuNc5hjYU/Svj5\n8r5v\r\n=Xd38\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICMLwXIhQfb+E4t0XF19z/07leKrSw0LoFhNfIQvvmWUAiBRCs2MTPZs7VAX9uc3rmAOOMXdThH9SlfprRp2NeWPcA=="}]}},"4.3.7":{"name":"browserslist","version":"4.3.7","dependencies":{"caniuse-lite":"^1.0.30000925","electron-to-chromium":"^1.3.96","node-releases":"^1.1.3"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-pWQv51Ynb0MNk9JGMCZ8VkM785/4MQNXiFYtPqI7EEP0TJO+/d/NqRVn1uiAN0DNbnlUSpL2sh16Kspasv3pUQ==","shasum":"f1de479a6466ea47a0a26dcc725e7504817e624a","tarball":"http://localhost:4260/browserslist/browserslist-4.3.7.tgz","fileCount":9,"unpackedSize":63578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcK9pnCRA9TVsSAnZWagAAeI8P/R0w7zDybtcwEok+Pkxv\njQE1iCmVY6pzYiMRyc8au8AvKI8yW/6rqyclwur2q0yrP8pSAC8fVjyVAiuT\nZjTZeFRoC+jswvSNL7XVIzuYNHNqHZq4ok3spdG1u1NqcaVCvzBicT/fJCju\nw8Iz3RVEPpFvzv3hCYX52Ybuz5R78RKGBBURX5QXN0+Zs/vYZ/wrIOcAb8AG\nCeV+/jCj3zmVAmcfR01sqbsnJCQmyiRaH+0p5cjssBLr3PJTFssyQrCIQUx5\nyKjeM2R33N+MksxEkWkb/ugIaxwQ3Wo8nZy345la0aulAdzl/yxh9HLRRbx0\nANI5JTsZrzXYR9Ea6WF4Fqv/UrIIfQKlv69vcwfg717ueCJ+VYZrndiBmojw\nV/PxlhLT03vvIjjzuyK2yImUg93W9VorPSRUOda3EBEfR7ZOW8ImGtdzy+Ph\ntFT0pQKtgRLnC1QAHRGvYmTotRaa7EJAFFIyqGDyTKgPBb2ZvITDXuSIigw9\n01jh6A1ak7K36XYUtEGHjGJ5iqDA8InvkhyYtf4/6sNdBbGfsmLFTuMIB7AG\nKLytbl4WYjitQW/zINwDRqxOPxQVpRzY+kBr00pNm96knjnEMHy76Q6PC6cG\n9wREuYIE+VT5FkjgcfzaJYhzYbWuZu3Bc8dLPHKfDIRzXmfHXV5qPm6cmQuY\nAW1o\r\n=PFAg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDaUPWdmKBjinc4ijYrF7l1s2jcTfXT9jwPOcNpUtQBGgIhANa4ztrCI1VeUiDD0le3/hEPGrFaOe257PqmuqKESWWP"}]}},"4.4.0":{"name":"browserslist","version":"4.4.0","dependencies":{"caniuse-lite":"^1.0.30000928","electron-to-chromium":"^1.3.100","node-releases":"^1.1.3"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-tQkHS8VVxWbrjnNDXgt7/+SuPJ7qDvD0Y2e6bLtoQluR2SPvlmPUcfcU75L1KAalhqULlIFJlJ6BDfnYyJxJsw==","shasum":"7050d1412cbfc5274aba609ed5e50359ca1a5fdf","tarball":"http://localhost:4260/browserslist/browserslist-4.4.0.tgz","fileCount":9,"unpackedSize":67641,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcOO9dCRA9TVsSAnZWagAAni8P/i407QVv/E9PDU2GFLwJ\nshbVZ7HawuOyJ5xzijzVQByyImIeL3SjdTy3Y3A9jU1aiDx0KwcmxxTcoj1T\nYRFJpQnQyK/B9ykXuMC19KpdFyj3AwaJyjMpbPmpNlIYuRgvBiNHGfe4qsIj\n6mfGGOrV9Kj1nRoIk8GLnzvNcuwRSy9h+S6XFLxSQHqPFG6biv3mF4NldQP8\nGcxfX+7AzKriAEqCdPkT9WjkGlRUqtYyDJSngtJeEKcDBZRUDke36cQ11fof\nIUINhtiyovlFxtGYig6F1Uw7gxQyy381g0dbBNfBjbncwAlkFp4dRllB2iiA\nMkJz5oSj+IuzYGdKuiXoET3XEct3TMHBtXUAyDqyq2/oVmrjcT3IdkgJ9k/s\na44vdOIqG6IDy5yPMTHG14Cv/kRWM6jJ21QpRJA/pxmZXKJYbKJ/75nwJrFI\nV+LWrbVTck7LC0x30T1/HhObnRJmmimUjYQEZippHyMa34ApAj/VucokMRpM\n7VMMXo0UhyyELGMmRUtKVZ28nNiY27caBlyXZNdMDaDA37swceMQUhz9ckNp\nJYrz3Z10DIxN1gWN8Otp0PIGoHGXtoBWtwxXmQqADeLCs1LtjQVj0P/EebkN\nHaNfvf+tMPLSNsWovnqVU3Yy/wBNBFz/Iqs/WMVOAPDhONSbiIUqElouuAXO\nzLgP\r\n=JH2D\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNVhREa92c7LHJu+tNRfrCWYRXY+dslowsmErPS1DaeAIhANFMWij4565535+gy6kadkYinnqAsTXTkkD4CV4pDZqG"}]}},"4.4.1":{"name":"browserslist","version":"4.4.1","dependencies":{"caniuse-lite":"^1.0.30000929","electron-to-chromium":"^1.3.103","node-releases":"^1.1.3"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==","shasum":"42e828954b6b29a7a53e352277be429478a69062","tarball":"http://localhost:4260/browserslist/browserslist-4.4.1.tgz","fileCount":9,"unpackedSize":67872,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQOABCRA9TVsSAnZWagAA1/oP/RFaIxGLr4QuEcxX6puN\naifvd7yVZ4xju9TShKqSueTooRpXp1l5B0F0yeNLZnr5yUXqU4/Gy/ml6AbO\nl1K/1cqcg+zge+7NMf+Dvyu+JBfrK51aRHUjLa2mZe3pq5nUIhmS0mC1vcIk\nIilQhzNbsj8zMkTWTuyBHCNRKDO2ThZkszzXW2hDWC74JZP6nUBvMwlRWF/Q\ny23puGl1BA2jE44T+fWU6PakwmXUf5DJgoQVlYk89O1K2u7P7iTcISt234u/\nGv1mNYIOl7f6mi2K90kaDYdvKs/WSDsDreTvZwA0Bf3bUNSEsIm1wzjepQ+t\ntnmKc5vn3T0g29ynOe4ZFfNh9yQIpI08YRACUIJr5F/848GXns7qvl3mExmJ\nIerlHC1wy3jrU70kQjzRSsr1Kctljsp78f7q3nktWEEi5xV3U6F8ofaFFHgt\nTnWH06GUIqQmhE6TYgyPgg6WB+LnydDHNFMZvezx8T3LwhIZ0D6x1cRY4Ir7\naETP3b1RqikxQGdR1SP8XrnFnf/vm4slCLf2ULv+kVWKmjYKIKfSie0xFmqp\nTuI+nQODTJBxKt/G4D3ug6eohDuG8i5L1U/s2dteQUq1ye+0aIbqdReyh57L\nXpecKykSAAHPNSqSiDO7mRBEOAHbs60LgpnUfYigJONCz4WvRoWnZbRim64w\nnWvd\r\n=HRSf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDBv3JTzX7b89akIxSazps75YXO1Mj33BWTIkT/43qW8QIgI5BJAoyQONAHSIJHsqucKRhvnpL03WwVsitaPx2wIdg="}]}},"4.4.2":{"name":"browserslist","version":"4.4.2","dependencies":{"caniuse-lite":"^1.0.30000939","electron-to-chromium":"^1.3.113","node-releases":"^1.1.8"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==","shasum":"6ea8a74d6464bb0bd549105f659b41197d8f0ba2","tarball":"http://localhost:4260/browserslist/browserslist-4.4.2.tgz","fileCount":9,"unpackedSize":68062,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJccYuTCRA9TVsSAnZWagAAprsP/A2WHvbvNbXuMkvnQr8N\nmrhewldvQWFcZmlRCBWS2RieWZup+iALlKF7FkAm8GeSrbQyFVaXa4tOeJuW\nCbK3HdQf/ox/Z8eWuoc2/1HfXkjLVibaHyHM6n4WgI4RLqwO353CH6DBOf5S\nDg9qOVKXV+KYB9wonNcqxzRo7b4GZM1Rgz++7OmpYxRGiIX/LnoTSvOa3Clr\nVEVG966TaG1GURZGHSxQcQWEpt2p3TWoC1vE4mB7vNVdyqIXHfVBZHlxzHwN\nBATjQxNPS2ntkTElJvF0Bl6uabIVl7rACGfRtQXVYRLyJjVwUnosiPKivIrW\nc4ScQLQQRTpPvnEMqwq51OVVJSUWrEuvua/EPf1Pf00TnOqoc1Q17AUORSvz\ncZA5zPoHzxDR928VrQOVvUUaA2wWTpgyacotgdc9xzVbnETIqtlfSCW5AT4e\nc9PqIq/yPkP00oWFGg+I/FB3pGPcX3cU6gychZ6JL1qoqy0q66vWXfZ/fNKW\nnb7jF5+tOveo8Shund8a4D0I2hMGCOFjMb8XnqEdImjfaI68eQNwDVrMbHID\n1/osO2LkphOALtLOJrxdVhBjclyWBjb6orKYo+vH/lq0z9PohQQxQy2RFMTD\nx/7QFayEgLbncO3x9VMTkTX5O08ZLYqQnxhjxIGXCruwK7Vkq04cA1E0NVMj\nOMab\r\n=OVSU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkJcB6PP/VuL+bbL51NpdzKdVnLKx6dbOg22DfjgYqmAIhAPztPb49n77dIQV0eu4U5D6w1oSuqiRej79iymBpbTUO"}]}},"4.5.0":{"name":"browserslist","version":"4.5.0","dependencies":{"caniuse-lite":"^1.0.30000948","electron-to-chromium":"^1.3.116","node-releases":"^1.1.10"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-92IS3knByY3wF7DDozdKwLxkvp23Ydn2O5L0qVwR1p/ioN7oIDl7d/eyPMc11rTVofT/6IbcdwP9eTId7orGZQ==","shasum":"b26d80ac95b3b592b05ec9cdd8a142d924189ba7","tarball":"http://localhost:4260/browserslist/browserslist-4.5.0.tgz","fileCount":9,"unpackedSize":69484,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcjA8yCRA9TVsSAnZWagAAlJsP/iO6zy5qfH3B9dxPY0UV\ni3ANc5+vAkOplK1OkXz+6wgygqqwakwh3kCAeSB9ctlJFQMoBqoO/wap74VL\n8kg9j1RqROnvMO2fuzJb67UMxicEUoQXeMG91OJ9qd3VWQg24Dx2moHBogiC\n4ZsFYPWcmWRtoac48NQNefZHX4D+Uv0c5FbgkjEAe9rLIIvaUfw0sfZJcxpO\nml415kl/N+4xFjfvf07q/j2jB7TGWggcll7NolhdM7atBUQhGXYfbspZCZDO\nzUoJacWHApjiOzNk+0u6ZZ38m1yGJQa9NKI179ixy/oL0HCZMczPaqvDM2Q1\n2+SV3n7X9m1jqfEMHqXcdocy1UH6CnBbU9a+O0TWaKmwkQIo03r5h9Qjpz1+\nFIz1Dy0Q5BoEiNXyKz9dAT+wo7c9Z2bI6cUhrEy67S6E0eCi4JIFB2m4dG5h\nDbl4qGO94r3KLv+zG0fHIi/+axdzCvTGMsu+dHFoS86jrijrs5of8PMg4l8U\nXtpooCjMQQ/fXXCUcK447pWIeUF+bZDKw/X0MRDx+F10okwizIZFw5dJyk75\n4yTIC4UINCkFMIUvJquVhY0u8O+8ZzdDGGGCUCwj6GVffG7ftvOxKYnBkxk0\naq0/KKFii6vWbqYbFMOpRn82NF7G/UBHVmuAkosZdNPKkVGsspLGBp9jNg/L\n8apO\r\n=iGsS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICRSfQuk88Y3GfzhfLh+IqPQsSIbB+mTjkFmECr5zJXuAiAT2KR19f6ZEAOXkrIPHOBmEwZBNqJonAmzM8iebTR+0Q=="}]}},"4.5.1":{"name":"browserslist","version":"4.5.1","dependencies":{"caniuse-lite":"^1.0.30000949","electron-to-chromium":"^1.3.116","node-releases":"^1.1.11"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-/pPw5IAUyqaQXGuD5vS8tcbudyPZ241jk1W5pQBsGDfcjNQt7p8qxZhgMNuygDShte1PibLFexecWUPgmVLfrg==","shasum":"2226cada1947b33f4cfcf7b608dcb519b6128106","tarball":"http://localhost:4260/browserslist/browserslist-4.5.1.tgz","fileCount":9,"unpackedSize":69537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcjauHCRA9TVsSAnZWagAAm2AP/25PYBrWAy89iOnyVt1U\nj+BbD+x5Yp81c36NOTdrMwQhscsIrrbImmGMwImmt3FzyXzrK206quD04d87\n/mS7l4qv5pqVEz3BTyDpuFzqsgROhP4uXiAFZ6MplifLpy3CsQlvWvWYwmxH\nUaF0UdiVXGncmnCSz3NaL4LHJQCvczF23t7W7UDdcmVWobYfxXbMYeXQrd+Q\nQJ0mj0AsZmpsYPKNjLaw4PoY0gm3leQGrYW6SetrmQjTw+wHfyX1L+wyt5PO\ng7lKaWUG0PaCTS1psTPyRmcSZVJxoBS1AHtze8Kr0B/CSC5yW2MdplhzNusA\neSS4P0BtpoTmXtqYdzdFos9CeeMwTSq0xnmbhHO7wHVfBDfeBrls4S8d5jr6\nIv2EKbd6l+Z4qSQRYy4xPmgREkHTNv7kB+MEDpEfxuauECv+HeZo8b/llfEx\nh8Du2m5pThxI6IjmMLDj2cWaZaFE7YILwFIq1x/9aqlMtlfn8lmtjMX/J3kv\nY2MQcs3F65uypm27n+AFdKYeIK751ABTDXPtn7L5lfHdUW62RMIwDA1ESsMW\nTRfZ/r0q0e1FulOjGFO7es2tLzPK2lbWDm3JQjyyOiFfjIZGBwwq+DyynQcx\nMaDivPzYDUV1gDpUA0dK44q9Yqp8O5EjpF4Cm1YWqLYH9FAtHDTuMJP6/ylS\nfsOZ\r\n=kQdo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD63s4ITM4/D6yBDApYGGmE4qis0EIh65ivilANVPMZ3QIgKyqAPPE9XuvD+6AlImUVjMt3xc8WPgKNSoNDcm2gNLY="}]}},"4.5.2":{"name":"browserslist","version":"4.5.2","dependencies":{"caniuse-lite":"^1.0.30000951","electron-to-chromium":"^1.3.116","node-releases":"^1.1.11"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-zmJVLiKLrzko0iszd/V4SsjTaomFeoVzQGYYOYgRgsbh7WNh95RgDB0CmBdFWYs/3MyFSt69NypjL/h3iaddKQ==","shasum":"36ad281f040af684555a23c780f5c2081c752df0","tarball":"http://localhost:4260/browserslist/browserslist-4.5.2.tgz","fileCount":9,"unpackedSize":69309,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckmahCRA9TVsSAnZWagAAsh4P/0l5ZMbd8Yy0KF7yWQXQ\nsNIaYwbiNUSmkEog9+15afGehg5Q0MWbRU5VkJOzLp4YfSLiRHOxOzMmzEeg\nLjmsGdvWUkoU/t+M0eqL+GmyD9JO/5DdsgnXXR1UxB/BDvtvO17cyCUguz9P\nHBJBqpi+lpALHuaGqmtWAJygDFdxDFxpyxIYrkhSdNjMgeNry7xHRaJRWbUR\nMifhfVyDMv3szwwrRBk4SPxWgWLSZ02CvpgCZvXqToH6LwYFLY5VEHQIAUko\nm0OPy4HfvOb3y19DI1oqK9jP3EPiesxCq8xxpFLGS5V0YVEuxNcswpLOLCZV\nXucxrSkZ+XxsD4GgQ+3I6H7zpCM8DLObRxsW8UzNT1r1fonkDWV9uc3Qj4IL\nvA8+NFCZZ2Ik1hN4NSuOJpDQFKukpa4qxG6zqQ8dO1oFIZTwv6Nh2tLc1+/F\nfqG7M5XBog1eOh0XOk23dAUpeTGyX5drUKoddtv1u3pRoHCFCVoSNrIeYbEF\nAL1DqeVIOT+msKeJRtZrS/5Ip5BBdsqyCUxQlL6pXdd0jbWL6RC+u1rJiaXz\n1hfbdDi0VOp3mdm3NFplRS5rhk3S6v4zFELHzuOJ9Q+qAyV68uPeXIOm2/Qn\nCI0uO+96FHlL4uTb8Z3aEsFnwaBtgKQja45BswTks51PVSEOXJXOPOO1J05p\nOSf8\r\n=67T0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGcgN8NjjKWlsOE7/H72+jnhvByGAZVqL7faMvnnTyESAiEAwMrHOBdh2XA+Qaz2iCchmd+gFecsYW88/v4CGM7eyWA="}]}},"4.5.3":{"name":"browserslist","version":"4.5.3","dependencies":{"caniuse-lite":"^1.0.30000955","electron-to-chromium":"^1.3.122","node-releases":"^1.1.12"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Tx/Jtrmh6vFg24AelzLwCaCq1IUJiMDM1x/LPzqbmbktF8Zo7F9ONUpOWsFK6TtdON95mSMaQUWqi0ilc8xM6g==","shasum":"969495c410314bc89f14e748505e58be968080f1","tarball":"http://localhost:4260/browserslist/browserslist-4.5.3.tgz","fileCount":9,"unpackedSize":68552,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcnoXYCRA9TVsSAnZWagAAaFoP/3JJHSz/XgVkRm6bniYW\nBL62RGKMGSo8SXCYjAQSkkQhZQKGeJsn6+EYCkpbZx5XL/1x7Jp4NAMfdQcB\n2Fr+6N9T+ninNHugHDTGy7X+LtkdZm+mWdQQhr0HyYwcYVtkIrNJYFis44F9\nQfdirT4Cvz0XcG8bjWXDUaUMLECFGkhmBI9+uf6hxExY/adpysh+1RoM1VaB\nyY0Tc0kF3qFX4ywv9uVTUMynoIn2aHwzt/bAJ7wVX5O0W0q7F70u2phML8Bc\nz2+8SolCLwDC1jj5O9JBTU9Es41xtZMdoJUZxEDHFprx33ZukvGNG1I5YMwa\nv7i4ZCjOpCXgvMZ0k+cAAL2yPc1Oqjs4hgALlAWhPFWvzHIP/d1+zfoYH3ER\ngbBJDGk3QVphjvLeAxlSMIju4vvZLlGK2VVoQpUIghSKIBUN759yeTcodY2Y\n8gqCx5AVccsiBsU+MIoqMR/ckDApD+t691GXXb0PrTiIRzWiwIOSrbdIPkVK\n4/SK7Ur2a9JWtKPJBz/5vz4z2poxEzNejd8TcSsTcnrrv/6jmVBC5VixMB/s\nEtl0uRNNBrNneBu/UzLEHtTO8ZNRg/IoWkUkFhb14QoTRq9ndS7GvdosAUQc\nAP1PLIZT5xfJnaCKFJpz+cRRoslHV26q8sVe7lTlPOlurTtGHYXeB9AcBQEC\nJ92u\r\n=8s+j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3Y9t6jBDPZJhcGk3iro2ysI09/otw1BTmwR6jaNtg2gIgObpHM5Tbx4/AkMqz7Gi8o7jDLoHcu/P+C/t9iCEYkXE="}]}},"4.5.4":{"name":"browserslist","version":"4.5.4","dependencies":{"caniuse-lite":"^1.0.30000955","electron-to-chromium":"^1.3.122","node-releases":"^1.1.13"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==","shasum":"166c4ecef3b51737a42436ea8002aeea466ea2c7","tarball":"http://localhost:4260/browserslist/browserslist-4.5.4.tgz","fileCount":9,"unpackedSize":69001,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJco+H/CRA9TVsSAnZWagAAmWkP/3pqndkilyNxF8+0V8Op\n+AZClXD7omlvyYkBWWV2YVMpLbIpEta2u3uN51oOQBA0ldCa1TS76WCtGzVx\ntiLBiiKPfnDtABe18hQZt+DmGQU0j2NQCDhSsIx29m5KiDYpIe2l3qKQTtga\naEOzGAdejqJuSU6KK0Ck4fcqQa7kuzE8HgoMylUy4eid8Lwba9AuBW1FD9kf\nc5ot8bHv6bQWzrKxODwutxuYTpbRfT+HkcoH3u/om5bM7mxJlu3I1I3gkTaS\n71EXaPSfyncaNaFzYPNlfealj/ILXN2OGOaTzTXx2hmPGx/n7pNi69nbI2Y/\n7pD3RBpDvufTrtzV20jHPbTxG5SS22nzmzF7DOpvn6mW0ymM64Bx9MXFppEM\nY64W10Rt08NV93SXPvnx13iYRxNkfMQrXv10kHLFo17C+Kwx6CT0vCp601Or\n9kEmDw370jOxbgQ95U9OdZ+2DPCqYEDNdcAACN1nrE7/6SiX1COS2/m2q3Ov\nAdRyMEaQpuKMUpgJO9pXr/nyxfqzIUdlcutHZ1DuVg8c6SnmFJdmsYqTF12x\ngNH1EHaZhlY6Ny1hzcsi+pUndlbzib8dRYqC+ZsKaJra3O7uPF8tJsmlMhwC\nRLGuuiGVKjdwvNHdsbwkAgyhnkkwO1S38Jm+P4ODiedVAX+k/BuUdrW30mC/\nmJbY\r\n=Pixi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEfxDNQ3HOSg2qA75RSKb99dTUcdnoJc1GVqqNVGjKOpAiBL4C4QBR8hLZIPcJt7++SAv5ZYYuhF7tLjsG7keOfBXA=="}]}},"4.5.5":{"name":"browserslist","version":"4.5.5","dependencies":{"caniuse-lite":"^1.0.30000960","electron-to-chromium":"^1.3.124","node-releases":"^1.1.14"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==","shasum":"fe1a352330d2490d5735574c149a85bc18ef9b82","tarball":"http://localhost:4260/browserslist/browserslist-4.5.5.tgz","fileCount":9,"unpackedSize":68995,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcthgZCRA9TVsSAnZWagAAPP4P/3BXXE3gkL/hRd5+PJmC\njrFK5qZdSig6fY3zd9fjT5EuAR0TqoGgwUHVnLioUIQLI2MTBh6hKP9QAVm1\nmOQDOELcIT9R4e6fpC+gaOnmgO3YC7/CGHioyBe467gbu1y+uH/t0jtCxpk0\nBhWUgNO3/4HHnBnM/NNHz97ybi/kRSAEA6WUfFz9PurP94IWCY8MQwbhOBo8\ntZMpSlZiMShTmS9SQyphE8TWtnCs4fzgE/OLk/TUDLyCB/F3cAoWNMSrjW3Q\nfGRmxhD7zZOuzAu8fYfYRzetJjPnxBPXYCJOdXzHTa/0JROBxWBRtqbtxIN/\n8XbNlqHUmqAlDIECflONT1u9JTK5w5YNA4sBneSLup8aajFeTtFJBF4NZZOQ\n+U1pEIXIwjuCP4O4Qky2pVDXU9B96yXmHdayT6/iNDm3ipHSZtwsLS/Qt1YV\n5BMCvO+2U/3Nl5me30IVGpgO9KSJKFMDiNGBdE2/Hq43NVCpH3iY4iL7DMkJ\nss8xhDWqvs7FxOen3HyuIRq+WUEGrUeaY37SD/nh2EMfDepkVWL3cedsDr8v\nfi97CbqL3eBFNfIqqLbCVYVBlzKsZ3EHdXVFPvZr9jLW97OSrlp8Z6ZtuczJ\nOJfi2ikQeDTGkC3N2BQcyZ/agAtyMjnHzzswswGBJjFk6UiW4uYBv+rT96JD\nuuHH\r\n=ztKO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOr589ctmtYlkOCZ+ESCRM4SNuGYdhNTeEFVl06j+W8gIgQzp86M96MYB4yCve8f/dx5yMfOuOCShaoU31EQSDm8g="}]}},"4.5.6":{"name":"browserslist","version":"4.5.6","dependencies":{"caniuse-lite":"^1.0.30000963","electron-to-chromium":"^1.3.127","node-releases":"^1.1.17"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg==","shasum":"ea42e8581ca2513fa7f371d4dd66da763938163d","tarball":"http://localhost:4260/browserslist/browserslist-4.5.6.tgz","fileCount":9,"unpackedSize":69215,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcyIoSCRA9TVsSAnZWagAAI4oP/RaoSRKXpcrVoAzxUKNq\nw+aQmZyft1wnT3WHZI8aU9ou3FO13V5TwjJe4JaB+yLnG8alp06h9dwkh1vI\njZeRDRFZl7NSFjJ9EjvcSxg3YBxaaFcUzPIVOXLCMPLEKEE4D4C9oJEqZ+BX\nHkpNU9EG+xqD+v6n0J+UQxwJZEo+tpmTTOrOue4VFRjl0o994MdU3tX29pow\nAg2aoAVjZe1sV785Vx6lXqdgCwTG53nH74R4YPFNgddtB/LpTuTQrnVnClFf\nvvGrbYXA7ngwV0LQV/8SUHU/36tvMBF3RpiCGrwdJnfhx47cHpghf649hTjl\nAypG4AoPIiFu6jGyWCEPPKSoUmQ5PIHJk9rqf+4UvFncnn4lZt05qjfjW9vN\nCg5bu6X81HdR5FjM8dRh6OJUzHO6Cqoneusq5JD6gYX+ADaFYXyqx/y/o0lH\nduOhJZFDImGoJ9g0LrLDTy3V2glkizf/lJpY85FdkbSih/xAaGbpEK+dUuQQ\nRqYjZ5oUf1lIG4fsS5/JKknEHDTDQPtJpao1olgwElgHcaHUUUq36kbXqwOv\n9THNszpAhs8I9YZyOLnm0/j2Bw8ATgMsoeJXMt0e/Ts+EBFAzocneDLHdden\nwrTmSHvU5Y0UoRb+9HasX5UNZRD8V9XZagdUVmT3FICSVrIDB0UQobZWeVey\nkzDL\r\n=BWrO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB3Sx9SCBD8T0DKM5rr4R5PvGZhvk03sK4PIY8lz91URAiEAoGTEs3IPVmjJ7O5nUJ5hzXgVPOQzmIbPGElPLXLvXBI="}]}},"4.6.0":{"name":"browserslist","version":"4.6.0","dependencies":{"caniuse-lite":"^1.0.30000967","electron-to-chromium":"^1.3.133","node-releases":"^1.1.19"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==","shasum":"5274028c26f4d933d5b1323307c1d1da5084c9ff","tarball":"http://localhost:4260/browserslist/browserslist-4.6.0.tgz","fileCount":9,"unpackedSize":70491,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc2ogSCRA9TVsSAnZWagAAw0wP/1MAS2vGiDnNz3rG3wwE\nViDoB5XKFZBxDHx4pVVJrShaAGp1FFcKqyWFOJTBn7wtFEeqFDGH0ix4Fjji\n/VEdcxopjG2EVS1n2f5pqWJKIdHgAkSPGiEgQuTXyC+ZRWkad0R8YF9nvCQs\n/CPfthijhaZVmY5krgfO9Y0V1TUdyp5KK0kf1jujgQHU61uamoa8ac/3bVLG\nc31/THNU0FvqqPrOqEBWeGCWsD1j8pv/AOsj80SKQQoOVEgHnmj7v1cjg4D6\n1MKdoN46q57mF9OZmBZjYILxTP7sJ+S7Rezrj5dzLkhLzSKXAbJedqzcqYxy\nYvi2UU5U78gF4bScIqsLOFZchqXHYXMfwaqChq3iu7TYmMgJod31vUa3n9Vl\nAEZ5owo1rP9FDTagotu6nCdMD1g4r193U7GQ+/bnoEeI5x8R5LSKZJkDyAjx\neFQ86x2yYEvcJHKPjwkYFRoLG0JVZhb4/2Ry/opKv0M23co18kPGmZxH0OeD\ndhElBDoOQWD8uu/sp7NRBARxptgwNDd10ZgHpj9NA6bn/jTK8jM8NaJWYDCv\nov5QuUpzPSWhh9uoyRSPKjFecYv9W4p50Nttr/0fn5iFHPbWSbFnXqWk9G/p\nKfm0fgRWIYKC72gEa4G+f0rrdzYdxDT08FwV8tz1JXVHvH+WnTG+Kf8kJDu7\nIZWs\r\n=DZbg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZk0AUtUVXeN0z1BuCsfogycCHtF2KBJ+TgrLd1K/o0gIgHsTYJ08wR3fWGClKFxjXgRbtyilscmX1c7N0xDegDgE="}]}},"4.6.1":{"name":"browserslist","version":"4.6.1","dependencies":{"caniuse-lite":"^1.0.30000971","electron-to-chromium":"^1.3.137","node-releases":"^1.1.21"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-1MC18ooMPRG2UuVFJTHFIAkk6mpByJfxCrnUyvSlu/hyQSFHMrlhM02SzNuCV+quTP4CKmqtOMAIjrifrpBJXQ==","shasum":"ee5059b1aec18cbec9d055d6cb5e24ae50343a9b","tarball":"http://localhost:4260/browserslist/browserslist-4.6.1.tgz","fileCount":9,"unpackedSize":71007,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7ZaqCRA9TVsSAnZWagAAP08P+gLGwB2TVP4jpFdjSkty\n4KghMw6ozEWy4DyD66f4cWZsjtErNQJC0C/UxFGYPN0ZMnkn1yZ53/D0T0Td\naEUcwZZmSxiZw2K7+MIW57RXqI4gEzE9IQzhkma9CrOiFNpeUs/1seKKEytY\nLPE4uX4QNFAhoNQTUoRb0ev97WwocPIHjqkj20COuE4gX+8DbdITlNxLY7Uh\nL2HI0WEygICjDI5KEuf6D97j8MQvPXVBAquxsEHHLNUtlIUpRTVTLuebMb2O\nLqFVabm30wZTCZ9TWqGDLHTU50BhrnpllNXCN27zS41ZJRatGA9AEJMUshVL\nPz3bh/KCvCv+qGj5KEHMAToNApXsM6c1HpS8nyfVwofgPDSZ+u+rDSAs6QCQ\nqyDDfE0otyQW0bikd57le8pgK+VpIWehTRPXi7tl7HYdtcoPCfDYGXoja6vj\nFY505hl1rO34HprZMnNGb/I4XjDEUww+3+bFlu1jxww8GGaz3XLzpexn0Qwh\nQCHro1R50z89RpwvXlosFnJVF/CbbLrDKggu695fFJ5cNXg9yhiaHztg6uHq\nbZP2hv09Y9OI0UL+Pa1wsNMrnFGKWSsIa3u06F7XA4LprPVPg/MbsZ5bj66E\nQD0pOqW21onc8gVLft8kQ1MoEGo2XcpaSMvCESbPgGDZjxVJDNDw4QrMBOd8\n0Aco\r\n=scJF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICuivT4O4Zq5Ppsl+kVNnp+Xe1uyq2wV8PifiaFiL2AgAiEArBTd46zwoZm9XlUTveOkK+HKZL58XNBLmESrs9Q9fsU="}]}},"4.6.2":{"name":"browserslist","version":"4.6.2","dependencies":{"caniuse-lite":"^1.0.30000974","electron-to-chromium":"^1.3.150","node-releases":"^1.1.23"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-2neU/V0giQy9h3XMPwLhEY3+Ao0uHSwHvU8Q1Ea6AgLVL1sXbX3dzPrJ8NWe5Hi4PoTkCYXOtVR9rfRLI0J/8Q==","shasum":"574c665950915c2ac73a4594b8537a9eba26203f","tarball":"http://localhost:4260/browserslist/browserslist-4.6.2.tgz","fileCount":9,"unpackedSize":71636,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+rLzCRA9TVsSAnZWagAA1ggP/j6gDZtUU4rQcrlAiOI6\niTDIT2EJKJkgl008GdAumr2bWUU7+J7d+t+QIzD5mJ2/YSnKlB4q0QryhdSa\niYZouUCOxmxQdAcnuVKv8DAYNSmQCFNw2TYaOBn+QUhwi3GTQS/DSn9MJ3oS\ndyY6g4jjH6niv40fvlf6Zk/+tdhvzgoug1XOjj9VXg147cP954VFqL2fetpn\n87C5PB0RX9TtG6yurDa4/YsT7nLQk1Lkm8qZsy9G1Y9U7E0VXMJmfo1yc+Cr\nLiTMvatOegEHBKTHfDYZERkl43wif8hnKlYByJCjd1CvGp1Rmd+Mv/HqUBMs\nBIexBXhb2x5ICudapk7MtJglub93lvZDaYp7Ep0dy8rlMiLqhCXwjmAsh1zD\nKXAhI/9ExpDWpO47xl2TlTY+ge71NuFPFhjtclQ26YNKpml1Wbn7ZewwEWUI\nkjvCq39nK5wftAuRH3iWNj2m8VX1MRCDsHlKItFDrBcAsIrG8a8pVSzlN6cF\naXJy8i0wwMaXuk+ah610IOcJBIpauGDN7q36ZM23pDxF2ucS/y3DoEKV653K\nZwDas5eBFe6duGIddWDe2+aoUF081NYxIDNswiyRV2fxAL9uAMA1K4WNGPTb\nkpG/3LvDFEuLrcOeK/1YVxHab5GS0tFA5+y7uaXHMGTSzTTUvk1kdYQUywwa\nQtLw\r\n=l8QC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsUSXV6BjIuexc+vDMmpMN4JX8p/6YayFkVn37cWdreAIgAyttvqLl9CcyLkiLFXMv4wkoRH4+UbSIjk5Fm3gByu8="}]}},"4.6.3":{"name":"browserslist","version":"4.6.3","dependencies":{"caniuse-lite":"^1.0.30000975","electron-to-chromium":"^1.3.164","node-releases":"^1.1.23"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==","shasum":"0530cbc6ab0c1f3fc8c819c72377ba55cf647f05","tarball":"http://localhost:4260/browserslist/browserslist-4.6.3.tgz","fileCount":9,"unpackedSize":71520,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCKrLCRA9TVsSAnZWagAADV8P/R3S9nhCZzwKX83V6d6v\nH5knc8R+C7ElzXZEzVZCSeafOCyAdBbuzM/Rku1avtZL/Dd2FH/Qagq0Jlbp\naqEutSn4LQeAMt3pqoOMgBSc5RXOAtMNsefQnudR6acbYitoQ70tMVHHS3mW\nR52am5XhmJmJiDruMxxIFWZfNb/QzdRPhcrTpDXZnnkfJHXH/i6jfXhQyI2S\nhJn/dgHNEx8m59mzGLvZeNKVhfokChpT5VM/BtmTtwVRCltWuDSBYQIXj1Xh\nGfnib3RhgqzOqTV9raYI/AHP58Q1uD5rAbVTIeNjNILSprZNLxUTNwTqn7PV\nwX6fy5kTOViEV2zRp+SL4Ro488cb5ua/SOP+hy3ZrCewIV0EdeFGurfsyFz8\nciulca5neQjDAGBTPM440Iqs5U8C2ZWsKUF+8KYqy/IMHQb2QtktH1vZ4DGA\nz4H84l6IuvxX1jfqUd5UlNHcYjQcFgNS+/mv3y3EmbvILmED2GRcPHLCSnFa\n0vyV5XHVpYyXvnXfkqAIv3ioQzCd4IBDq2asq495N3lAiqqqHA1vM28mKhHL\nSP3mNY/fpD6nASM9TLpUwJeAIBStnFCx5SSqjySccb4gf3o3VkPeZDfledwr\nIylhS72CcokkUYlc5TZiJaKksawu6pVGIT6Sw2L2RtUAMeWbEGJoHK+VH4nx\nPNAg\r\n=l6RH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDk+SW+Z2BVhXRp3Sd3XcW0yFlKsfdEEEY2q+bKyTSaHQIgIwbP9hfIoGIMH7f9swKzlEJ1u8l0ZeSxq1EMLTeLD2A="}]}},"4.6.4":{"name":"browserslist","version":"4.6.4","dependencies":{"caniuse-lite":"^1.0.30000981","electron-to-chromium":"^1.3.188","node-releases":"^1.1.25"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-ErJT8qGfRt/VWHSr1HeqZzz50DvxHtr1fVL1m5wf20aGrG8e1ce8fpZ2EjZEfs09DDZYSvtRaDlMpWslBf8Low==","shasum":"fd0638b3f8867fec2c604ed0ed9300379f8ec7c2","tarball":"http://localhost:4260/browserslist/browserslist-4.6.4.tgz","fileCount":9,"unpackedSize":72056,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdI2QuCRA9TVsSAnZWagAAVi4P/ArB+8E8K1fQMx1LLm65\ntRSoFhJSEPnVf3Z/43bAD7lFH2EfeLAxi/tYH3HgswelP3gUCv9WSXmDZ6R1\n/8gTVScK1YNohnkJnvGA4p1zkawP0kH1O8YvhJ2rhqmsCHxrkgp2u55DGz9o\nC+dyboYvrWQqexKbQcPQaiM7zODxPvpC/mhDW8fLhIhW4n+AgJ7jOrwtHwNE\nfhTcfcJPQoIsUDxf5Z2DtI6oHRvB7aBGwlr/t7kLbLeBDLC9HM38owJ7luoy\nLHSeaPRRFKo5+/hI81XGaejaE5FWXvuf7Kq6nL22BPk/1okcpSjqsMNEC1oV\nrFgwxvZ8lVEPs7Xe+kS3QoNq2Uq4gVEvxJA6CwhV0xlEtHFsnIwsnFU5fTkM\nFaWtq5AdyvD+hsQQupc2KN6hfYsimrYF3hBCJT9/yBpMy4KHmO8B+sd6Kj+r\nNQz7uGYppgq+remshUYwjEjl1FwrUsw5y6qHDVXxgFy/MmbGehas4X/ffhDi\ndKXlFLA503wYhyq/AkbPt0VRA8j8QzBVq38+BsGQ2QreBlXF2Q9mZzfLCo6R\nsx1xmL4u2uRSQ8cfzCV30f3z2g4MkDvTbROGdTcZ6mYeIAhKqQFfxe+4XTxs\nhnKpvse7ycqXkkCh0d6pXMVoUIW4u0Qnq3PG05aZ2XKQxPBvaDSlRsmCJyPB\nLPkR\r\n=KWNE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBC3+e7b5WvywqJUCNVsOpZvWy34uEmGo2D8KquNzXL9AiB4uJvYUkPcoRPGFC+zAIlLFno/P/7bNgoEqZzAXgwU0w=="}]}},"4.6.5":{"name":"browserslist","version":"4.6.5","dependencies":{"caniuse-lite":"^1.0.30000984","electron-to-chromium":"^1.3.191","node-releases":"^1.1.25"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-6MJa56llNfIcHwNKvtiR0A7aCCIFECbMGq+egK8d4I2J4hX6CArxvx66tH27rlT9vKDpAd8+htI94Y9X9pJfEA==","shasum":"0af4d2142b7789f58c4c1fbcc05c0ee085f9a46d","tarball":"http://localhost:4260/browserslist/browserslist-4.6.5.tgz","fileCount":9,"unpackedSize":71847,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdKnhWCRA9TVsSAnZWagAAc1YP/ikONYP1eSw5rsuv8mcF\nIxW79vtmxdR4dDH62bFBYmbCneHiy9pctd6LdD2qQ5g73iCjfSR8C1C9jBd5\nE3dWW4z5aKXmEaKeUDD46iVADr9pc+VvRMeV5ANZb1qxSGc0k4U2sHM5s/PW\nxc6uRFwQPeGld90gltbl+ho9GXuAUugo4muQz816FhTcD0ME/gCJpcJ5z8Tw\nQ60x5wvMUxdy9SN7H+Ry9wDGBEqsXqnxl8NxTmvUZKRKZ8OdS0jGHAzyZqvA\nNuUFKKhbAXHMJoIPWwHJKtWkxACUS3O8lkju1ZwDxV1Jv3G+uWr+GRZvvzyd\nSZlkyTe3wWDxD90UHBAuzPsGHWxk4I7s+MEV86vGX54f0auVgtJAtL1vz6vw\nIepW1uWQlb8QMwFAmVyh0Wxj/PBShaK1bHyXHYXJ2yJ1bqBN2LOEi/Jf2+MT\nlVdHgbRCL2GiHhuNf0fMfztmJXYHAqPwA8jpd1TmY4WZTwIAIBXjZtYgXcwW\nI4G5n4mRYXDHFJHtAy+zcgJCS9uc8UbS9xO4ue9g0264Pt0KiGVxW8mVD8fH\nBE/iIxeZ+2w6uDG08o6Y/qIWrWTp4U1rGiEOZ3xM7H9pfdeDLQET9jua6L0B\nnbLxPUGe1PYrhwOyUO8CMss2fQ2y2uTyh87Fp63oiCQdRmU2/vsykqzuk9Ko\ncBV0\r\n=GFtC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9vCzgYII8D8DgOMe1+8jUDlYphGIzn3LLzQ7BX2zLKAiAGz7vUg8A9eOJvM6TmCJgjE0CijFEqL+9deF2O+6dtEw=="}]}},"4.6.6":{"name":"browserslist","version":"4.6.6","dependencies":{"caniuse-lite":"^1.0.30000984","electron-to-chromium":"^1.3.191","node-releases":"^1.1.25"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==","shasum":"6e4bf467cde520bc9dbdf3747dafa03531cec453","tarball":"http://localhost:4260/browserslist/browserslist-4.6.6.tgz","fileCount":9,"unpackedSize":71843,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdKnmZCRA9TVsSAnZWagAAXAcP/AtNHgp2x8y4pnUhfiYS\n4/nJ69cRsyjb9F/8tAablwlRmVQnlPVg1t3QU/c33CbRdtOw4ZzQlvo9YL3R\nb/U6kyCxPxXrV7gM47VGH+oqLmPwGBZam7eEpTS+VNnTA9yAcmdqiW8f6tfe\n8qrAHe9lPTvq7qztnQHpIVXpGoAq2rhyboVTUF8RJHxnv2AbSaBI+oajsZ23\nsv6p8b20sy3O59XkzFxUmfNIDITgkfjbACNJDs7DZBj4f//iQ+wHXnnik3ol\nMoKKya5HUDV4is6RQhYfLdxlmV8HED7KzHj3Zy8rJvKd28d4vFS0fOe0yMsq\nbEv0gzfmgxsKXfKmDF/fUsR5aSiH3M0YSkVzjbSsMYuyzYIZszxpNSHrom1f\n5blPn+vvMRWq/R/P3dcvIOS7pK/xc6X3owuY+PEjrtfk+uayd+PpWzrojxKp\nsz+pkMFsBCejtESKLktzPkTvGsOsesPh87AFoJjsaShhwBJeqcMQ5cy5IyhV\nT6Y3DCwh81ECRt0xKZlvr8Qrh70+lt86fA/VBKqqRKUCO705GCESYAYN5C6h\nDPZThGGFtZhojwrnV2cVuYSlp46Ovvcha5Bn8KZXgTaVnc6kZPT3f/DSCh2O\nLsEiLJHWNmFiCZNF7LZV6hpMLtZqaznPot1VE27keSo/qJ6kNDwf2iCOvfiz\n8DFp\r\n=utq5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGolf/7SEGGQq2BLmJ9Oai9ydgmjnBeH6Q4EvZhCZJoiAiBEK5qMsSOKBpA2B0WyW7AeDJDYlfhDjKieMZZrIHW0sQ=="}]}},"4.7.0":{"name":"browserslist","version":"4.7.0","dependencies":{"caniuse-lite":"^1.0.30000989","electron-to-chromium":"^1.3.247","node-releases":"^1.1.29"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==","shasum":"9ee89225ffc07db03409f2fee524dc8227458a17","tarball":"http://localhost:4260/browserslist/browserslist-4.7.0.tgz","fileCount":9,"unpackedSize":71437,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdadfWCRA9TVsSAnZWagAAOXUP/21No7EjXMeziLuWuvSr\nqzqNy2SXqQ8kY/RSRqFRANVhUihzpicXDCCHxsrO8Q4ilGqMlnh1/WUWzP8f\nQWPuo2K2d6WpGZ3lte3c1Y7Tyxho58QZ1f0VbRmlNmxGtLMmwlokHrr9RWtF\n0o+SJqOo+lxNusW1rwfeMnV1FXdtXmYIqS1xyy+7P8XNPQsmrOB0SkGann4L\nbhJmzAIHo4/259mgc4mtTAS3uXHjPy59uOT3cowMRBzmrJJVfYpFBs7RhK1a\n1OUN+lKC+aOQV/gdSu2VYS2gu2vvbs+xZDSVpE3uS27nRgqievlkDCcYRar5\nmTul32QaCTchixLbAxi/W7x+x4gQkz6lAnefXmxgyVVz81mPZZq60NZEURHt\nHdfurIciZgJQSw8LTqNCnAv0kPECPBkSL0Oxzurkr2nNzQcXOITcWWHzS5W8\n4PjFnO2fH9/MdiUPV7Y4WA6P8HbiI6dzNMjU/StIqTk0pzt01JY2OIOMEHRo\nyWi2vcO5S2J+PbwlNl2r6MKUuCgdia+aWi52qrM9ulgazecTxCn/xpiR50Jy\nQS+/RpYQJ0kpg7s0jous47jz4yR76oR22G8BcAHJOC+G7+U23Zpt3qWEAqSw\nlldg2dZpXsjbMv0zbj+qymTqg14RyDqdRPl/zGY/VmCqQ90w6qk3h0GgbJ97\nuPDK\r\n=X9KD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCjiJJ3J89L195hcH3NSvNHZ15VqjdNZDbNnCZTYwdxlgIhALjgGU/1shkoRJm/PGP6TfW2TlQ759oroh2JkaFRtNFZ"}]}},"4.7.1":{"name":"browserslist","version":"4.7.1","dependencies":{"caniuse-lite":"^1.0.30000999","electron-to-chromium":"^1.3.284","node-releases":"^1.1.36"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-QtULFqKIAtiyNx7NhZ/p4rB8m3xDozVo/pi5VgTlADLF2tNigz/QH+v0m5qhn7XfHT7u+607NcCNOnC0HZAlMg==","shasum":"bd400d1aea56538580e8c4d5f1c54ac11b5ab468","tarball":"http://localhost:4260/browserslist/browserslist-4.7.1.tgz","fileCount":9,"unpackedSize":71644,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdqGcUCRA9TVsSAnZWagAALagP/0X2w/Jc52oWhO2wArkL\nZqAlD/IVjLoK0tKsL6gJfCadmHNX887152tk4oR13LbURE57BfeFtVEd7inO\ntpRfFs9AflWPzVt05zNU6PQ60MyUHApJDj7hy7iLBGsClMqNl7FgRhEGwJmp\n2rfVk/mx6/Ls0dzRH12gvRkBpCeSj8cHv1/Z7By3W5Nsko0LxcsqAyiZkQiA\n8nr/657gwluuIrn85D8+mbMwt1SwTLtepNhFhR9c8zuPbl8CyL95C5vtqXUa\nXRK5P0dtI7ljM2rKnk74VZ700wGqWhpRHbbbs9K+5oCXVfK0LfLrhPpPjSxR\n0sGdKonrc85UAMY0o+YWzSjbu02BXAi7LQOZ4zkQclAqIaEY1E5Cf2xIWyq4\nysRqHv6ZuXfcR3zrxxAGCkAXSaSNkHSVH8ON8jzt49ODq2EfWE+8BQWebnEo\nxcfB4Mbre9EN7VWoyTkLH0HCzL75Rl+MN8wRvRVyTcddgBAV6a/nF5w4CZPI\nEZUXMfxcRQgQej1Wx/sb9UtJN8exn8O19laBk7QSmQrFxRyFybnIkLQIgXkX\ntejgygdu6ubz21SZNrGusjtS4bz+LFYlfvtyYSy4qipH79qPOwdPqGpIjF8Z\n6AocqqC/yBzeHD+GuDMb92BV3/bEjgWIudrCkNmSGNQ037bKkUKHFFQRilYg\nJagO\r\n=xduj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHxAgc9agN+MYw2z8rdImCdO6SLGD0DJhZqrOsSgatAwIgA47pQRRfUNE1AoECA5xJjfOKD6cBFGm7o9cc2n1iJIk="}]}},"4.7.2":{"name":"browserslist","version":"4.7.2","dependencies":{"caniuse-lite":"^1.0.30001004","electron-to-chromium":"^1.3.295","node-releases":"^1.1.38"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==","shasum":"1bb984531a476b5d389cedecb195b2cd69fb1348","tarball":"http://localhost:4260/browserslist/browserslist-4.7.2.tgz","fileCount":9,"unpackedSize":71917,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsUtFCRA9TVsSAnZWagAAmnMQAIPReGlVAjyEunJyA+Kh\nJmLVmLThoqH6vrcXhhzhRLLMmQLp70ZTWTC4pU57P0SnIvlQCRhq4pdYso6e\n4qgObGF5nWJoVzuJsp5lPCafMuo4NDv6USwdYa6nsV4jSudxM3FLdYz4WEqu\n2XhhQ2KxIaJUcO5mtY4wht5LlUZwCcjccvZ9eNwQwFDJJmyHa7vEbzwZNwFV\nCC+JM3hegQcRkZ4spVsHHJH5OlNkYOFNepf80PEPYUEYg4GwQQJGVQzsUQYU\nm+aGJgKd4zRuKSaN34V8Qhqzt6crprpAJfXxxk3qLtYKE3nuVZeGFNl2fPMV\n3T04lsWaZmkow6rkVuGokezuh2eGDbsPDJQLimINH5cZKALetl/vaGJKxQY1\niN2kKgZ5e2s5Sco7kDUAiOi6Kq/mKEdwMWu9gmMDpyCpSg3blk4DnJTg5Yp6\nvwA3Dt6wWhfdBdoq+RwlFOuT8aUfmPy+cheEEcNtdZGV+8iuPQg6egGN6ZvO\nCxw8X2U2Xy0pUiFZWb4Fi4GrdBdnObLQbg/mJA1tmpw22nJlNdY3qZMqH7lO\ndL8AeA0B9oKZUo8Z07FjyivRBOwcu8b/SVLD1Gyt6cXTJ4BimvxJzuGDhuks\nrS0DtxTZZJLw1MBnAVgdWJcn0weSjG+DzTwqx1KK9poXcHMiuFcvXGJAPgi9\nx6Yz\r\n=Jy4N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHHEW5D9ufpxKWFEd4LF4ib1K4+kcM54aA/m6WZKoUslAiEAxIHdD+xWz/cP/PbVuCACrreE7kt88ae1Q1uVjkGknYQ="}]}},"4.7.3":{"name":"browserslist","version":"4.7.3","dependencies":{"caniuse-lite":"^1.0.30001010","electron-to-chromium":"^1.3.306","node-releases":"^1.1.40"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==","shasum":"02341f162b6bcc1e1028e30624815d4924442dc3","tarball":"http://localhost:4260/browserslist/browserslist-4.7.3.tgz","fileCount":9,"unpackedSize":72094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd0x0GCRA9TVsSAnZWagAAvdgP/jnswQXEEx/btRaNvQ3I\nzGoOcZbYNy1ta0a5mChJCqudSc8dKHr/LymOF7N/6GzLUNFMRvS9WwH0nt+j\n7U+4WKgJvI3H/4E2xHiSPgVWZ7Z1S5N2njxCeY/wIVsyxdGLrVBQ7/G6KJoJ\nJy5diMMAp4DQ6F5nKbhtC8h3+lH4iW/8YOp8xg14p+vdtMO1wi6Dxhxjk4yv\nihdaQIDDAKKJOpCGVFAKiDzt9Ka/zxRCr0prioktk46bLWRl9OSFeuN/J08E\nya+fAmIrtohiVLRqHA3g21qJRWsabZns5T9ggTA+sY3zi7hwMpeVd3+ZC3+0\nGdqWWaDwg9w8WWvg2AdUT4KC6T4wHRnOZchQRvJVXUbm+OLHHSGkCOmWAxP0\nGEZTKJz/vLHyRcy4s4rqG2ZPN1nP55C1SVj+lSNQf0PASeZfD4eC7ZlQzYsX\nko8O+J4aqKYd5QjDErDFncmcRj6y/0WP+rWfg+h6G3t3SVSopYkynz3jdM8x\n4zDrIImlxeMfGx10f0txHicxrFUwMUOUM4YUaHRQar1DuPvMgEtn2+0xVcA2\nyrsA3Pr3+ufUYZnGhfie9WVk+CIbmCnAbfAYPYF2hlYLWn8xvkiJnQ3bee8/\nT6VVLVi1ltQPFBRJQKMeyRv8OQEHK4wg0ithrP566lhtyRaBogTQV3v7MXom\n5Kn+\r\n=YeaN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFSzuBKp8J3Cur7Fv9vnlqFydDGfHR9UEpnNTUFPz7K0AiAUJJQsxewjjIWo/zjiuCyoYJhPJtq9ZSes3iG6MFF59A=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.0":{"name":"browserslist","version":"4.8.0","dependencies":{"caniuse-lite":"^1.0.30001012","electron-to-chromium":"^1.3.317","node-releases":"^1.1.41"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-HYnxc/oLRWvJ3TsGegR0SRL/UDnknGq2s/a8dYYEO+kOQ9m9apKoS5oiathLKZdh/e9uE+/J3j92qPlGD/vTqA==","shasum":"6f06b0f974a7cc3a84babc2ccc56493668e3c789","tarball":"http://localhost:4260/browserslist/browserslist-4.8.0.tgz","fileCount":9,"unpackedSize":74126,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd4n2PCRA9TVsSAnZWagAAnKYP/A256VGF7snpBuk3k7UY\n8RaLQho3cA1cFP742SxwfyGU4Ad5BHtSiWIL4S2ACUckYP2JcS3iamurMu/Q\n6tweBY2OoP8uoA6I0G0nCh6O3Q7SPM1VZqh+2z1MonfC6Hwiiij/RShNjBKP\nbnwB/bIZyVXCy96cnBBQD4e++27pwlJd0HbocjIA+3mzM7nfi0dUPCpW4dxG\n4g5zVnE75Epr9r6+0m7/fR2dmM7Dx5mYPTDF4CcO4ciDqxIp3Pl2xrM9Xazd\n/lkqo7jrrh2jmA4FTEZkHoCRYF4SU1gHqlrAN6fTWk3jLiSgYUfokNW8tByw\n+SVeHoiXcZFru/EwhzyGvj9Kybec+PUD4E9IOFy9B0lnVMH3NfwpPbqrhSP5\nHZyiqFqPhtsrjdbPWxAHvHms3KofhJ0APUkQdsk3wzE4p8BmCmN/ATv5tKD2\nfQE1IgFwMUkqYBiCK5iHKr4/P2G7Dwj7vFQje1BfTRLXdrqjlw97Ha2kbSHJ\nozUYnMkq1lFkmGCGj27aPHwK35NDW1FL2o7Od5zvxh/RoNZ4yxY20WfXsw57\nvpEISf65qq0O1K5880a5XHjRBs/KJ6QrBFjMFSHQg2fexd+nL4gKDKmlEHtq\nyzaJu052UUAMdLpFcOpSNnSLmspEj6MJmP5ZQflgj/aRdcOC6oAaOxsklofa\n1/pa\r\n=l9I7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHU++OUybSWulv1a90QYIV1r8/a+d3dbNtUP6+hHqRNvAiEA53ajhj9DvS/3YTxNcbFDz7fdBuzcVT4TZqWoIxBi9HA="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.1":{"name":"browserslist","version":"4.8.1","dependencies":{"caniuse-lite":"^1.0.30001015","electron-to-chromium":"^1.3.322","node-releases":"^1.1.42"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-X/lIDboA5bvFg9SOhHN7OBgHHlaZQWcwTXBLBGgrB8+6Iy1dL0wmUfHRe7OdETRTuD2d6f5JPa7iTEcbVyVf6Q==","shasum":"df0f50cc4b3255322fae60ae82a946baae69f8c6","tarball":"http://localhost:4260/browserslist/browserslist-4.8.1.tgz","fileCount":9,"unpackedSize":75675,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd6ONLCRA9TVsSAnZWagAAKVcP/25mD62vNqexNMcuzD+g\nhQ/5SSjTVyYNB7Cm3RcKB/PIsZaZGeGJEHRtkrXp8yKQiYZUlpb3Zmfu4zkh\nENfmkfu4suPSAymg1BOR2qGwfTryOfkNElgyGDv1KKOqfSNV6hW+tGEA5HKa\n6PMPzoWQuBkPeHmYGmpoVS0szVhw46c1EwZYU+KjEcmCjcHWif/ArTKQR1i6\nI8XeJr6Xp+ZuD4nFOKde5punBtGKF2nCfacLtRpUqTI/g42QuTVpM9c3pUT2\nGxVf3Ki+SUkREmtilkGm0coY07YxCpKQIZLN/tOwMjtFuI/H05QiaZMu2o22\nUZMUbQDoxA8rBxPPQC5khJomh5Jh/JV4Hw0AZgmmLCa0uMPYI7GBBgRa3IfG\nwFJcaFuHpmAPC5wjD8LjwpibgQtfdxg8rAFsk6JOnJenBThBmlQi+lS6+o8p\nQOvuI3yDKxnCmNwJUms2UfJzgHe7L/w5Uwjm9XUwxrnoHuYBIQCtm/87RCdI\nNUezaY+sydD8J9efPwj8JhnvscsV+1AW6T4mMQyrx15NzQ4IuUp8jxExHW2T\nksfqLnqEH5QiRGsNaxFFZyrlhSSFxHuRI3JCtpG3SrML6jAXan/wrcowZjWd\n2ZnygYa5lzlg9vCo84AQ0PfxIRwlADSLD4ARZcN+geOG0qWocZn+8KgDAZ7R\n9Gp+\r\n=7puv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC0W54MOxDAnJfXbjXAX/ENOoC2dl5jssh+LMjMoowhmAiEA9ySlWtYgXbXXSBaKsZLkliLTiSIR3YzMedH5pDoIc8w="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.2":{"name":"browserslist","version":"4.8.2","dependencies":{"caniuse-lite":"^1.0.30001015","electron-to-chromium":"^1.3.322","node-releases":"^1.1.42"},"bin":{"browserslist":"./cli.js"},"dist":{"integrity":"sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==","shasum":"b45720ad5fbc8713b7253c20766f701c9a694289","tarball":"http://localhost:4260/browserslist/browserslist-4.8.2.tgz","fileCount":9,"unpackedSize":75831,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd6R97CRA9TVsSAnZWagAAHoEP/1AkYLDaA0i7RqRDr0uj\nz33Y8AyY2BH63duh9ytPtael9ssMokBNKOKAYZWE6fHC5Yv+nWuBIqcMsmQn\n6eQx7zDq4l7tf5EGUAlr19zNv9mwX/rAHMZ+rxCMsqwSbt419ZkTk2kv3oeQ\nDt7reVWIcVGy5By85KnAU9bRTNT/teTmiQT6SWRZr1D2F5TUKaOGt2l5m6Cl\n8ASlMEAdGpkS+udskpBvTptal+Awf+URZnbeiK0DGwba6+b1sRXTdoTCCw5T\nCtVxObjeSQKRjE+Y+C40EgPp2COLS4ch1O7KEKAijAexmsHzc1XSo7NVU9ja\nfFFVPCSPLyvrZsCnMyzQaq6f9wRJqUw3HEieIiwUld2nh53ZtkK0W2Gg1Wij\nsN9IPA6k9egYvErVSiXICQDb4NJSr1cnwhCFfILuE4JvZVPsW/20GEAKZr4L\npDqDk7InTZtBhZUtd/E/fNWuaYnEbf9DUXM+M7WFZRc2VD4yQ2DkW8hZ/CEy\n/39QKwDKmE1GTyfDFHazlNonohYq7F5IbatB5mZx3I5TaM4/cV65tS54Od85\nmaKW/Ez7YFSvHGXZ8m/UGSiQd92T7AgYWPrIjxDxEIj2GCZoy0BPY6B7Bg4S\nlPWh6FoRBVjmO+OsVkCs1gRSzzaWRyHDZGQr29lMGkeHNvoOzHBEYSUfoaW5\nXutr\r\n=HBHX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrPUKGO2P1c+wknFJLIFyqbDHNhRJ9XH27AWZInLiFcgIgFlGioJjKdeO6eYaAQyjTE8NyE5xpmYcGw93pV7n7KbQ="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.3":{"name":"browserslist","version":"4.8.3","dependencies":{"caniuse-lite":"^1.0.30001017","electron-to-chromium":"^1.3.322","node-releases":"^1.1.44"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==","shasum":"65802fcd77177c878e015f0e3189f2c4f627ba44","tarball":"http://localhost:4260/browserslist/browserslist-4.8.3.tgz","fileCount":9,"unpackedSize":76009,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeDr/8CRA9TVsSAnZWagAAXK8P/2aHljgnHCV65nE3j9wV\n5cxuSnmDoaGlBauxUcfyl44fPPoioK522HgVFdPU0jNl9BHHDJ+aD2dyzHUf\nnB056JJDaGLT25YevbLeA8QNov1G9ScqZIF4d9ku9noyyilnUgqaTYc+MaGy\ns9IEXValm0/Y4lTN/D8IrQDRN23/FXQy6x6D/im/+KolRZM7KOa/mCLqTNWd\n6pSgD7PnfIyBtMzdmzrooCdbvPpH6br0OW6ADMikw35uHvtVV3l+0eBP/703\nfDdCkRnD0gb27M0Ef+do7ZjTLEQsx+qSpYOP/Fg40lwj6f0ObVo4HfMxQ7Cf\n9EOE8FFwELHJQ61N/F6fZAcp1vMYWEhqXwp8K4Kkvrt83YGaWaDrgSxm3Ahf\nQvh1+/xcqJULIXI//X0YkI20GIZDOLpjE159FDpHleUJW5+Y65d8C/5Pz5od\nOl/MBqG7nYeLmnIkc6Bd5eQARMsywx3DoLB1wwMcQ7GEvk3LbSPpwJzRmorC\nNDayTL1sZzOfXu4TCceSobeamDKwDW9lCFbZgYNMzrlByJfvmkEWLpiJXVAT\n9QTYiVSYtZ/Uwiu2nPzkqCiUSRnlvYKJFkV3XjZaf4SbnrAQCMzAbV0gKfEf\nndow4Jc8rE/4VhbbdJ0j9xUJ5s3LzmctZ8m0L/bI52VRZl5BDHDb7skSvede\nNFrx\r\n=3Bzq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGJyPMQpWolfYRUtnW+e6j9XqqYNxZ+gsZ+UXzaUHDsEAiAyH0PMzq48x9yOj7Z7BHWYcQkuRk8KpvlbeRUWTdkm6g=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.4":{"name":"browserslist","version":"4.8.4","dependencies":{"caniuse-lite":"^1.0.30001021","electron-to-chromium":"^1.3.338","node-releases":"^1.1.46"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-3qv/Ar3nRnRTpwGD+LZc7F4YHDBb3NAEIn+DesNa8TcBhyxf8eDqYwTOa70kiWXwvFjQQz+abbykJcyOlfBfNg==","shasum":"b0cf2470ce928ce86b546217f70825577bb01c3a","tarball":"http://localhost:4260/browserslist/browserslist-4.8.4.tgz","fileCount":9,"unpackedSize":76136,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJjl6CRA9TVsSAnZWagAAEgoP/39XhDHlKYoK9vH3S3E2\ntX9D9lIwOayDt0PGl74/Xe2W/RR4FjKUvreIjkaS4GoGx9s5xeyjO9REOiht\nsir+lkK9RREU20RCJ1DV4sBAXZdkFuHvv9dqpBV6+tS5/UjUcliljg2LXX3l\nGQrbydleWdMvwA6qMAZRqlXKni2GEuL8zfipOboN7wf32DzzAr2KTznDsLo6\n+ffYG1XMBw1TWIKsR1GyCAQLltORCc9U2VmiNfLhQHAKe3NCHpu/eaSkb9ih\nk/Q16VGnBMiLpUDJPtf1wFtpw+90GSRk788HGcHSecl3JRsI29rzJtAIEfYK\ntipi1ncYWrHKc0wmr9yt9GzanubQMDPlU3BjrqDH9P7kO3xX0lhOVJGxhpTa\n50/m51fShKcymbWCQPQ+Pz/xaurRMGo87VBl2vrlkA5oP0pXSDPya4CfSa2f\nxJ6YlkPCF6ltmTrvPIAyBcN+xQ7CSYHbNHL+X14pD7cBfDkm06tmkLoxMz9n\nCb4tsrAo8KOdJ9VEgjHIByksmXOm3WltiVSTV13Fl4eoaNq6V/rZMwUJigJl\nG8qy4VyEW5/QYF53ZrqhB3wPwXWlXF4wz6zWmmgE1aw7aSZoVIXVeyxDUJQn\n4bnGi7q1xhTibhG68RlYd4CKjpHOBeWHqxAphgAOXDFpIghokIfKCeNZ9f5B\nGiz2\r\n=1mSj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsYoWiuTELHoqJmkgtxRMZyiNA1RJkWgCwCy9GXqyk2wIhAJQuYX4D2OqpdpKc1vm2yKzVsnn+78sb7n5dXo67MQvw"}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.5":{"name":"browserslist","version":"4.8.5","dependencies":{"caniuse-lite":"^1.0.30001022","electron-to-chromium":"^1.3.338","node-releases":"^1.1.46"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==","shasum":"691af4e327ac877b25e7a3f7ee869c4ef36cdea3","tarball":"http://localhost:4260/browserslist/browserslist-4.8.5.tgz","fileCount":9,"unpackedSize":76212,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJ2QgCRA9TVsSAnZWagAASuQQAJlLDpenIiH3K3cXHgFP\nshJ+eHs1neOUxtI88Ro79j+idUcM07Q1rygFtLKII1G486V1N2ivZ5Z8+PKH\nPJaSFPP2pl7rcSFm7cOOG5viOqWKhsTOlDA7dac/pArq7jUCiem4ZmbHgWvL\nMCNuLoSZOfOq7l0Noq37GM2R+DzvVWkpKJquuZrB2uSDuuAtnjCszjEICNxk\ninSLkrytcZtLKPzDO/C9iXZfp93qqRT4W8L2jwVvR4B06E8cmNuoSeRtmKQx\nGlv9GMow46ThmbjukNZa1p5VZ/6NFxaclG+9lruI2ac67+q2JywgfJtNVF++\nqcJYN59iDelRlP3ncBHdsH5axTbW5/FJ+En5JbOOC/JQO38iVchvXhm/k6MV\ntp54PlogrUY5YSrYdaCQU3Ro70w4I4Zuhh7EXyWfl1TjwW/vvntYISlojNF0\nG3bZEPW33Q9Zg034NeX6v+RoRlsLS91rnmAd4oQScyHihEp7dZDHekvmiId+\nOpKZExmm7z9I3j3+nO1Auo4i89AqvhzEi58P5UGx7AQc7ool74WiuZkFf+wA\n1wY329AlRmoIf4xgDmB8BdbxI1pJY02zoE5BOEqZH52SNZAMXTDMb1XVnh3d\nWy/knnb5U55kBHOAAdoHEnojNepthiRhwPMg88vg9k2kzn1DplXewvuZHa7S\nBAxC\r\n=puQa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIASqxmrLG2q78P1aPLugLVyQaWklaynd9he3Xy37O0OzAiBqRdjUf1Ww/hrPum/33CaLiFjoVGA1MxBeNKcAtuFCpA=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.6":{"name":"browserslist","version":"4.8.6","dependencies":{"caniuse-lite":"^1.0.30001023","electron-to-chromium":"^1.3.341","node-releases":"^1.1.47"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==","shasum":"96406f3f5f0755d272e27a66f4163ca821590a7e","tarball":"http://localhost:4260/browserslist/browserslist-4.8.6.tgz","fileCount":9,"unpackedSize":76763,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeMiYtCRA9TVsSAnZWagAAUEMQAIliN0SFZKFpdvtUiMVF\npeG3KYl1FTMtB77TfBHXXbYmxCm9sCbIoyFcI2WqEjCZ94yVYgJi74fwA+8v\nYg9DlFZS80NpO8MHg8YztCpBQ+kCTezSKklaukJVpssZTkQ/MH4qka4G6VoY\nc4kCrLrIlaaPIld/E3cc9pKwbdK1awnrIkGmQhxQqzq9NWcOqqret6+X7wBN\nnigsiMupDBFBrY60ZlohYt4JG2/oPNNKWejUO97j5x7e9ZIxfnVEqcnZ0ACv\nRqsGmX3btqgKsAycIDMnVgcTO/i2/tgr/qjtDeyWax1u0xVAb707mopCFYAk\n9NjaLL+XCouwdMXfbllzJ3md3mS/VoDzPH1YqlwK9gT5qZDsufDQ7R1prdyt\nqBkL5h02cf8BkXTdfgQdyIFfXjkbCFuQ0gEkGgL3JSycM6M1dgSabQCYJ/QC\n5VEAhxtSpl4HhdBJi45ck7GwDFBnhCopjzKTqo/6oxW1KxjL/g43qE+saaEK\nhzId7NaqxwfnCoNcQ8HvQoT+GKVIJrBuHv9X01HheZSd2QqOZGN0fV43j29J\n9dWXksCswOs8vFw96102dJug5/FyN8iQYQ0FvWgn3yssYJJeMOM07ZvnY0k0\nYabZNqljgzRvbuE1PLQPaUp1AZbRy5O6hXZyNL07ze6BgJfrdxHNzBkawhG2\nKaSI\r\n=sN6/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCojQc89YL/kgKGjummrQJTCz6FKi9uQyS4SHQB9zZsFgIhALr9P8hng5zs3se7+pD5+J6lWuK8N0c5tI34dszjYuJ/"}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.8.7":{"name":"browserslist","version":"4.8.7","dependencies":{"caniuse-lite":"^1.0.30001027","electron-to-chromium":"^1.3.349","node-releases":"^1.1.49"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==","shasum":"ec8301ff415e6a42c949d0e66b405eb539c532d0","tarball":"http://localhost:4260/browserslist/browserslist-4.8.7.tgz","fileCount":9,"unpackedSize":76902,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeRXFbCRA9TVsSAnZWagAAWmQP/2c1oG4az/DPv4+psrxi\ntNxZJMKg/76jYcrnHOwmHua/L9g75pASk2MA1b1LM000wSH1wVgQn03TPeKg\nmJaq6KBffTwaXsDysxnhpJxd4bmlGQ0L2bgWLpunxA/t38ji9DoflXPlVd1x\nzDjU12RnTNC7tj59O4IxdOCd1lerqAK1jdTOTeNoE1AjGcHCp9ryi4tabbKF\n2iZTkOvHYnh+hBJ4ypSbcsD64CD7odRChrwdi3x6taeL9AateCWUlI5T7dgC\nZ3BustZDxNPGEm/AEmb0rRMETVpsC46HIg1vZJBk5LIM5KHN3pRIkz9dyVri\nghy8+OHOAoZxK46+GI/Lih1NoIXATW7NrDVt7MNLTRRXX0ur1B7tZ7an3Vrm\nEzVuZ/gA4veBQYQV1J2wxfjlyTIkQ9kZB2AvbX8wKSl93Qr8sRtZGTF1WZGK\nT8Rlkl7f7dan+eT97yxBGDwzxsXM2WS5xOugU1hPDTAPdbtCo8kToj4j51WD\nFhtvHWTmK68UGtYkuwKy6o/8LE2pV7vriDohP6d4Sd6JhPvfPdkGhkcfK4bJ\nwMNaYMU3woDrwD04vSW3qFYpenR7rOZeLpx67dCDeFOhM6vxvyTUqN4uajW4\nEJassZlXIgLBEpybEMSIVvV9DgtiJxC0XgOGUP8bVN9D6zpu0nFYgdvQocmW\naliw\r\n=rD/2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAxiMM0G16Eo5SL8gs5Fgy5PwBvsfKtWeDO5Uj/PDBX0AiBEVJl101lwvuBV+PFORjhxdF0gkVWNVUE+pegHgLVGjQ=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.9.0":{"name":"browserslist","version":"4.9.0","dependencies":{"caniuse-lite":"^1.0.30001030","electron-to-chromium":"^1.3.361","node-releases":"^1.1.50"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-seffIXhwgB84+OCeT/aMjpZnsAsYDiMSC+CEs3UkF8iU64BZGYcu+TZYs/IBpo4nRi0vJywUJWYdbTsOhFTweg==","shasum":"ff85c390889e0f754d7bd8ad13412575cdcf5dc7","tarball":"http://localhost:4260/browserslist/browserslist-4.9.0.tgz","fileCount":9,"unpackedSize":78840,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVvqmCRA9TVsSAnZWagAA2JYP/3LuIqScYdhniW+r/w37\nJrjrwu5K2SVn39HvS+gkNpkpuUROzs9C1SOMNqzPOSGwGasLsHg6FQQH6gfU\n6HOiAb8rWUQD97udPGpBIt4YGgHUX3T92vGXkiPCP1EK7V4BJd6KHYs5bxtP\n4RgLuNH9jrUgG6djqId0ROaPOt8DNxOEFzDMvcNjHXWxxgR4UTx3nM6pIUYZ\nbdhBFRoXQJgxLRnajO4IRI+6SQiipBJTSEQeyy2CMjiZBsEPr3Woh2kwJbnN\n5aep73+loNv2SsZ1sCEHUoRYUqfUNVng7YMkcxs2Ro9cVod61E18wK4bLZ72\nQWsHU7ibR8/bw811VI8qcsv9wX0WM4QdkgyhY4lkRIUmc+8lwKYCugZ5i1Ng\nuOwZrkQrEzJm3r3VPfvOaMsKEAxF8VGjQQaHBOylL/uMcTa9+UxxLiTo9/IV\nKtrEt9E6rbvg4T9QM3/hjsYBD/WkRMXSr/LXbacUHJsVD3ch/mwoOVLc3p6w\nwZAMeTRcpbFD7etWjZUknDwLu3WbnC1Wyt4I3482OHWb/QeYyc7MkNISNu2S\nf6B82Dxgfnd1x9nq4VxfzxpvQ4zt4ZN0Ri//z9oZC919tTVKt0TW97Ms1gkL\ndFn1eiXVjyU0k3fi0hfqGQjcljoqT1eLNzC/P7u15EEM3VwuMSNnpimYiE0Q\n7Jjr\r\n=Rmqk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDkQ4ah2seTlT8cv3ZgpLzcl8qUFQsNJi1BIyrFzKLEXAiEA8+dHjOuYRQ0TlmAMSNfASUSRGg6H3ydjyTqzK/9km7c="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.9.1":{"name":"browserslist","version":"4.9.1","dependencies":{"caniuse-lite":"^1.0.30001030","electron-to-chromium":"^1.3.363","node-releases":"^1.1.50"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw==","shasum":"01ffb9ca31a1aef7678128fc6a2253316aa7287c","tarball":"http://localhost:4260/browserslist/browserslist-4.9.1.tgz","fileCount":9,"unpackedSize":79554,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeWbMwCRA9TVsSAnZWagAATOcP/iTtP+SXhUBnSm1oTSVn\n6pRBSGS+5gDMY/RwaXbQO50wYv73Z613ccCOd+mdOjDviGEd7pXSX/SMjeO4\nFG7mVS45cYWGhxbJ3mfjhTJ84Qc+K9snNjTsoRUbr2qg2PLhDImlUfpyAlO5\n+4tDSovJQH/EY2ZCYJgWNMmZKlF55Ddn1wofvDzCzmrjPDpJ2vSBNtKWAvUv\nDoJWpea5sZ0c6g26ct5zQ7lXu1DxHTQKeZd5fqMo48oPlpu4NclJq9erSdNM\nh7FrGT5sDbvup05mPELpjRxrqsJoO30CK/184G+sDM8UoSlOPZU7attuAuql\nghSrtHbSK2u1QgxJlLOONPU6+k2wn/Je74Q//gF7qm7cJA4bI29ikwplyFgd\nebvg8EMEPXGM1Adt9Q25AGisKwPTOA8QVzfA5Kzw2MZYSJkPvD1um2HheKEH\naNgA4Vpc+9ZzWgFO+YhIQwh5PW9tMXyDf3qJLjmexTaHr8DoaIKWa7iu/Jf/\nboBKsSGU8r5TGyajGNKeMPj2kmJrPzpEZJQMXa9az2X3PNEVt14hUxBJ/o2q\nRCqBXCrxGxhKGHLSkrgSFExyCYTAnzGdIcNLOnIX3sgONnjL228clV5tzXfU\nb3nY5TDXKDFaRIgODkTD4JpUAZkjpCAAs0lEwHUDY6DpG8CS5RlyTHgNlzhs\nAQfq\r\n=3Kxw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDFxi8RJzoIJUT45a8ubLlhO2dRMiv2utTSNKVJC2VPKQIgYxq1Y7DZVbawrKACFTGH7ew6CtPCHyDJAtb8MlYUl64="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.10.0":{"name":"browserslist","version":"4.10.0","dependencies":{"caniuse-lite":"^1.0.30001035","electron-to-chromium":"^1.3.378","node-releases":"^1.1.52","pkg-up":"^3.1.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA==","shasum":"f179737913eaf0d2b98e4926ac1ca6a15cbcc6a9","tarball":"http://localhost:4260/browserslist/browserslist-4.10.0.tgz","fileCount":10,"unpackedSize":83605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecus/CRA9TVsSAnZWagAAlC4P/0IHxKThI+6zDFwsFaJT\nI/mBhKg573Lv1V+ZiKKHyM6ISUoNUUOFTC9OtGS0AupCg0T5KB1AtTdvSJYk\nt2GWzCIHOn6awuZipslRNPfVWauox6i8FIFv7r8S1OEO1vGhUE0IrcfMtPie\nMG/9WJyN+2/qMXDuqoDWHGGEqoN+F9PexrRvpynrC+K1SduiLCyzVL8c3xNX\nqKKUJgbVFbUXetukZilztIaMdxPAnGSZVVHHJsUyDd85NNfIa/z2xE3JLXUW\nYUkXn4HFzrbvRQII4bex+e/0Fv3lup4r1o4hGrvYF/HaFlrPKqvddZ5vljt8\nfQuXkbMEPtKuygOO6curmsUmSnvh0YkN7snQCsTRAEMAsaS4nK5sa0POBv0l\npxXPb5kTYT0eZ06is8Fe++3uIw1MCM4PRMHZkO/PmJT6QvlQSEVMSNmiLHRP\nqxv5CAVnb6j0S0zmX08SIRVHGdkRiN6+3VzDU/BTvfjhV49GMYRLh47IjQN/\nXR4ARg4q15oGjwyK/eH53XetjtlspVbbWzjZziZU5jwINcY3rV3QUICPcs01\ncoxdp3SWe4/Dsv1vyemMCLPvsGOrQDHDXARQcGWBHSl2i9/zLRUa3goZBgwW\nvBAyWiXJ9/Qw4rjCUe3HHH+oMK19KSKG5fiRmnkjO1vVn4iiFz3/timyiM/U\ntOYR\r\n=6dgv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID+8o0ecQ0Kt7kZtwEGzWh81tqLmR8WDGs3V4VKpqDxWAiBQV2XBeJRg9hJ+BAlt6n+wqhL/TMPcWIcV9alOnYFttA=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.11.0":{"name":"browserslist","version":"4.11.0","dependencies":{"caniuse-lite":"^1.0.30001035","electron-to-chromium":"^1.3.380","node-releases":"^1.1.52","pkg-up":"^3.1.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-WqEC7Yr5wUH5sg6ruR++v2SGOQYpyUdYYd4tZoAq1F7y+QXoLoYGXVbxhtaIqWmAJjtNTRjVD3HuJc1OXTel2A==","shasum":"aef4357b10a8abda00f97aac7cd587b2082ba1ad","tarball":"http://localhost:4260/browserslist/browserslist-4.11.0.tgz","fileCount":10,"unpackedSize":83816,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJed/f3CRA9TVsSAnZWagAA8d0P/iXPYA9s0MIH4n12yf9B\nJgOGv/wAxq7SXV5w0CZDbyKwXk+hInKG9igPbR/SkNwVF9P9yJl6v+rDuj8d\ncr7Ut/F4Qc89noLj11QIkx7wWG+8qb/YVD2SE17k6wHcfY2UYZV4xv9L++7W\nz8ktyUb2rmDNIq8UyHnzgLxd2OqDoRfEjIiL/INC5UOXrvFE1OQ8PUaiyH8U\n2XLWaJxtXQ5YP5G0m0CE+bT6KBCTfAVuse3T/PaN8Tgk1YgoceQA9hKMZvdy\nVZ4rkmLMaMLz+ZjC0ZlivpeN/G9TdEPdVDMzaTBlIMTQg4n3EJQwOSj1+uKA\n8HveSJIKEfqbt9pz5joLwQnIGSKtwFSAVseD18dRVQ7QBmFY9KFCASLbbmH7\nt6xAXg1h2o0XSQtp1+PqPvIzoFFnctJXwP9PHy8ma5KWpe1VBlJ4pTrj/K19\n/+llKF3gdRgsNoOZoc7MkdzPQiNe5RsfUoobLWoDdJxMPpcEQJZxtidfgaJw\nhNPo0xa9dCPxPvaqCUDcQWhH09zc9YhHhP3KDqnqAi351JTebLcUezjCYpyn\nXwJNsx6zMRppc6uIS0MDQ5hzUdoRyV8CUGvjb7Eq3DhSokraFCxAgUBofIBe\nvmMBOS9a07Fh/Mit5A5jidNITCHViClsqZg58bMELlmtfIxNkoFvw/26Ufjd\nZgFl\r\n=VKtM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3rCcumNjAiaEkTPdhnafKA3HDKB03Ge89dM7qvx9mYQIgSCUl/voTK6Kj9FYklWBMI/hvWq/uflhTIE7dPh/wzGA="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.11.1":{"name":"browserslist","version":"4.11.1","dependencies":{"caniuse-lite":"^1.0.30001038","electron-to-chromium":"^1.3.390","node-releases":"^1.1.53","pkg-up":"^2.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==","shasum":"92f855ee88d6e050e7e7311d987992014f1a1f1b","tarball":"http://localhost:4260/browserslist/browserslist-4.11.1.tgz","fileCount":10,"unpackedSize":83883,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeglZcCRA9TVsSAnZWagAATYsQAJW6idlTIbxBx/et7Ph/\nCntgJcZuSlC6K80j/foh5j1awoE7JQ5xluNPRRjytsib9aSzFD9Q3VDQVJaL\nvDBo/eUtWBuziw4gcK4XQfTVnY/j/bWCY77aFL8hwxwWsNGwdB81Vql8odcH\n9E8FF/C1gNlvwUem+fxkL+yWymcsfEuJ1Ny/J07Hz5In3ocyRHQbuBu4U+2N\n8paSC6bgiNXu7Tc43jgE2Zz5VBVs3AHmxBQECx1rjjr4KjEi2lkzPODiqnu0\nuCkp7XBcxjcACEg6bDsCuc0MCQBmieACVukye8+fYczl6WVM69UpDuBXW8Be\nh5m7lPdXOQ4toGQUKNKgCMLULVnSdzUO7WeSGWwuYxQYxXYg1Blo2B+oFSUj\n6Uyy63ku8tilo75D8VkpMqmhlGqVwGD3NAUIDXmsq5W0W9Eh1Hk6hdhfZnhU\nGEf0vpKCiWv1Ks0SqWQ7xNkh/aoM1EHuXbSPvLMG3P6qFtFaaX3ob2HDFrh0\neLmNCks3X9dRSWP3tAxUGe0yrELbC3zS4oehHVLULCYhfcCGQf+CbNa05BTK\nw9xj2u3spQp9aanEn/+1Eox18R6Qi5kRoCgEhLcPb4DGdJJyEyfnLJ8TWRw+\nDYpySXpxqOnZrO0y9hr6cXG54FkbiTLPjOynOI69IWRakGMUeno8Zz9B02xe\nQNg+\r\n=XTe3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAxXz2AYrK584wNq9Ug+dunaUYpsJQSYqhsJz9ZAvjEDAiA8EeromL3Wts3G2p/dO7v2ekZXDnXdklyJMvIe2xradw=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.12.0":{"name":"browserslist","version":"4.12.0","dependencies":{"caniuse-lite":"^1.0.30001043","electron-to-chromium":"^1.3.413","node-releases":"^1.1.53","pkg-up":"^2.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==","shasum":"06c6d5715a1ede6c51fc39ff67fd647f740b656d","tarball":"http://localhost:4260/browserslist/browserslist-4.12.0.tgz","fileCount":10,"unpackedSize":85531,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenhfoCRA9TVsSAnZWagAA2bQP/2npnJsAjj9Hn/yR+34L\nAy5AU6PtHcj1M6NpR9W7O8tcUBQKExhMx+TyRxn1Az7WA4XiledovhZVRo6h\n+rRu3fnW+tU98QLQOE6OIvn/E63coIX3pWC/f0E88OnTgDlcR/ggstlv+9A1\nC2PKdhwqdwLPzsuPO7u/dlCtgrF3dgAkoTYnA/Ktw58dvNsujSPB3r6CIriy\n8jzax+om+xyBK+m022ENBObEaDYm6Q0k3TdHJPoYxlsA9knVVd19PuoJNZut\nv//lVucS6MU+qoMpXDgmc+GEV90U6Up9AMYc1ZYSZd5GOI7jMRLfgALQBxAu\nbu5BZ7Q4LVWaXz2Stt+XlE0TlW+TrjrlwOh2ZJsjKrBH9uB+PaQD4Rg3j4NG\nV62pze77j1IfYpoTX4SMBcKYm51yCQtw4NEP7NGwo4sqpTpSROLXaq2h6VWz\nSgS1nLunr/tN7hguu8f0FdmJwRUbRy5Hlw6buaBpmcQYKDh8nROrQS8CqQbw\nHbdt5IyRV458ULUBHBJO7YEpMQkBzxUCzMD/z4FBHpqRHQCmAQ3Us0dTYsa2\nu4FeEq4fCw6qXuKJuyF7rgz5Qr1CWmkqEEmG/fUtcXtsu1V1pvbzosmPJnVQ\n2iHF/NRcbENxxDXcFuo7jXuSTk3wPVJf3lPdJu1JKDbOYCaA8mpU72qugf7S\nkjPw\r\n=EG1+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDFkWegl58bvln5HYO/caf3K20IO8pqPjZ6q+QuPyDsOAiB0XgHAlQgEGA9eDOpumeY6DfpAXUbMntLlvYxfa8ubTw=="}]},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.12.1":{"name":"browserslist","version":"4.12.1","dependencies":{"caniuse-lite":"^1.0.30001088","electron-to-chromium":"^1.3.481","escalade":"^3.0.1","node-releases":"^1.1.58"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-WMjXwFtPskSW1pQUDJRxvRKRkeCr7usN0O/Za76N+F4oadaTdQHotSGcX9jT/Hs7mSKPkyMFNvqawB/1HzYDKQ==","shasum":"6d08bef149b70d153930780ba762644e0f329122","tarball":"http://localhost:4260/browserslist/browserslist-4.12.1.tgz","fileCount":10,"unpackedSize":85799,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe84vQCRA9TVsSAnZWagAAeGEP/1ZznBXkGvBmXLQ2hDek\nbChA0Zd8nP37cg0qgAE1rj+yzEoKKsJ3qfS6PhYV05lN1u3gv/jr8as7MBqz\nBsHdklmApSZBxn5aUJnZxurHAa4sgFV1Ys+9svl4zJof3//7qNCtudcHrSZe\ncA0C63rWSO/PR/9Kst2xDf/+5xeE1CIEdOnT89oGjc2J50BskVxlGSJdF/P5\nCLBZcZRf6f/Nxtm2RO7iLCS9moA7kyQhXNx2WGkF/KyBQvNQkc++ca6aMZ3/\nd8V3vdjJFABHUMovbq5NgYfXfKuElbftsz4LsM+EI3CuLm8r3UqgFXa9sWDe\nlZTcW/c/cZMGLphiYuUH715F1UROn2a1CYsHymZ1u8PcGGpB9ZWOJMN8U4Yh\nC33ISCgUDvGLLOTg1H004bsosxTEAO3ZYn0R+Ex0Ol/TfruNKo+N3laPCLUE\nEOntIDWctvYPGOiTmbiwuY37DdOlyR81og8sULpnFPdeVMYTIA1uvAWFrbg3\nrTh2P7LwxljKpd+h0NiYJlABcoZpzg9aAsYwJWISBzp849Xllt5khV9wXDXm\ny9HZh/qKmAQdDHgMghtnZY9REHqErw/2D3pMkjL7Yea7ZjXo+Lr3NKKfak8f\nNP2JXCQ+F4Ifj+tTpVmuegBcHLOr1VyRMNFudxy0U+erFmDLKr2velPMmZhR\nHDq9\r\n=oG1L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICe5uUA4bpJ17osXlZzx2gWo3HebSScbI/ZfhDeNicliAiAUMlXOPxFcP3g+EVJ4VkrR+t9EyJdlOxNXE1pYoUymXA=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.12.2":{"name":"browserslist","version":"4.12.2","dependencies":{"caniuse-lite":"^1.0.30001088","electron-to-chromium":"^1.3.483","escalade":"^3.0.1","node-releases":"^1.1.58"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-MfZaeYqR8StRZdstAK9hCKDd2StvePCYp5rHzQCPicUjfFliDgmuaBNPHYUTpAywBN8+Wc/d7NYVFkO0aqaBUw==","shasum":"76653d7e4c57caa8a1a28513e2f4e197dc11a711","tarball":"http://localhost:4260/browserslist/browserslist-4.12.2.tgz","fileCount":10,"unpackedSize":85846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9i58CRA9TVsSAnZWagAAifcQAIgrXtDwJoO+6k9GPU2N\nHKuXXrDk/LTPitSQL0eZBomUiYiUrYhCjfUhFECqBN/R6/kAd15sR8ElTZbm\nITLrUgz2sH3tXkv4T0zQ59ISgkuO7O/MpGbZfNaPX2qNYIJaSUUoyl2v6Lpo\nNZRK8Ab9XYavqfWbia5i02YtDqvXoTuWZVbHjWJTKcqnlqYX/Es6phzvDyFx\n8K7RtKipZjSRogKW5OhA/MEI2cEGSj0ZiPGQcNxX+bsMGpkIFxQPcGPs6cu9\nRdnsFBxTJ6Cz+TidYItFkJq/e9sfZPJuPC7nMX47mjIvA6EaQERfW+dNugsN\n8NwCXJiKQaTHRU0IOL5jzgs+t1jjLUNnZsqWXUH3q7x0gZ7Hhutv0Wf4mDZL\nUqFrGQ8kuq0WZWe/HH3fS8EfZAzsT3l1ev5Cp2LSj/5jeA16lwIAjFd34FxL\njBTmnjt2eB91MYlcP5IvwHa2UJzje4BFlkNLKAPkSxqKGKFcTU9W3Cejbt36\n5NfnASjY/q+HNugmFkK/ZiixtRY2Te65iLZmilUNkO5Wx6mYM2xNKMmgKdLL\nmbgNajzNL54Mc62VaBEeMZ1uR+F1pVC02BpPg02BNw9xoU5/yn9MEHMi9FAt\nrzhXk3Es05/9JG8v+G5lsRYsyoJS9lt5PzyJdwV+B1MLtl0GHQ/utt04avdY\nY/qb\r\n=IGZQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCXn0JwlbLjcJWl6w6XiphoQOTiLkS3dzgAjuJ1HJTEagIhAPRiugpAbg9HGN1pFtYHk8nk1ySNWu4KucZTyoBsgHY4"}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.13.0":{"name":"browserslist","version":"4.13.0","dependencies":{"caniuse-lite":"^1.0.30001093","electron-to-chromium":"^1.3.488","escalade":"^3.0.1","node-releases":"^1.1.58"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==","shasum":"42556cba011e1b0a2775b611cba6a8eca18e940d","tarball":"http://localhost:4260/browserslist/browserslist-4.13.0.tgz","fileCount":10,"unpackedSize":87585,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfASX6CRA9TVsSAnZWagAAenUP/2r9EQKsO0BvGhO5DyeE\nAjOVaea4tPOIBzTsfYoauCiC4QKmWScC7Ga0zpYTrlvdn2XDPHHEQlv6oM71\nqdnh1m6Tcchy9Mq/V7VwPupcQHthRd24CKP1ChA0pVDIiNJ2TD67VP+28WNn\nZHIgsR+HuogDVrytuJqh1qQvIM7ApZnnz5E08Ka1Rvwu7dOtQswosBJ0oa6O\n1Yie/aI0JrmBGwSvbLr87rsZKnNvASQOtDpE511J/Jnq0L6nlOlhX9zAq0+P\nLaoJey1QoD0lnSWSo39Rxm4xZL/LzU9D7sxVKJh4kCpMoZ5b2LI8ZsVOy2jc\nEfBFv7mp0rts9+toCEvEgAvtSFZIMleQb0vbNocpuCNR1J2bmAiZ43iOTIIv\nCpF08tfsujGy69R1wQu5VQeGowcyHf7pK2cxpPsIAvbIgQHGcUNgIoWLJ6XJ\ny90y5yTcbYpHlwHEwSo9FPwfNebyEULjtTqHRTRTaTS4la1gMnT5z6Zm73jz\nfG/x+lDfcFwXcdsRvDTsnB7OSTDeDluFlrZOquKV1qNQy48+TmaIWaEfE0/e\nDvL7gzxhfycvXqxmU2umZZFE8WdYiA4cQV3p59yUF8QlfeBkIo0tsnmCNpbk\nUHJeJimFlzP3GF025Ge07C43DZu8VIG26DbPFiT4y14mft2kcYhN5F1gNcns\ngM1v\r\n=9fws\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGAMqdD28I5DkFiao0oPpo88A5dZd6iApGHnxqiXPa0GAiEAy2LO6/jHTu4IbVsAc7BBXJKThpLGR4uvhAqm+dbDGHg="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.0":{"name":"browserslist","version":"4.14.0","dependencies":{"caniuse-lite":"^1.0.30001111","electron-to-chromium":"^1.3.523","escalade":"^3.0.2","node-releases":"^1.1.60"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==","shasum":"2908951abfe4ec98737b72f34c3bcedc8d43b000","tarball":"http://localhost:4260/browserslist/browserslist-4.14.0.tgz","fileCount":10,"unpackedSize":87966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLJBRCRA9TVsSAnZWagAAf1QP/R/73zVZRMdvpm8/FImF\nrGP1HdrWsvKklpZBeZHjFxWwITZxuXYUdQhCpGR4HDAm7ECe/tPpku54kKeD\nNEFpfcSmOiP/lUhtVauXM0ZmTYMtwVyokTbwvCqTf7L25L8X/sQ0WHt4Okc6\nLjP86g72XNEIG6uqsrKNNua/Dl7/D47t36Bi9o3Ja0DyxLMrkBUj7ItgNXxM\nEn8tR/kbHUIGcWHzQunOH8yQWoWPTgfXvhoPNfrcrrQYHfxRUgYkalH1e2xw\n/wUetDEz3aEEmAtTjy5Lu3TtLIKCfopjQA2DOJQPIof2G19pG2VqzbYPtrkn\nx2cLp+Hxtvi7Bb0u/UI2yLpTbkOXJ1AOTBDexEZ3CIszGdq4dGBgb1GKZNBU\nn050dm0O8JIFxruGOvNvlhnmpKvtrurcQ3Yhfe2QB4DFR6rATVunEH7OgfOo\nZs1BFNX9ys8QhO9y2QJ5esfx7NOVdmbrkCDmJjgFN0q8MP88e9DkawodW+pt\nD3bmIra1uSi/gTp/vQuVobre6mKnzZzg5d6ekW6bS+/yo3zJktLZfE5AL1GZ\nlXFc9ShfE/ehXKz6IOZT10wWtyFr873HoZx0XVQkFnHUTrl49iFwL9Xo3J47\noHlYZcBMxdsPf5OMNt6mx6SlqZvOPP2V9Bqa9tGCkO2kkCfCq2i3iWjKqkDQ\nq2++\r\n=A7Xy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOh7x6SpcipHLFwjCBnijrYkVCO9FMV/S/+6/i0DwhDQIhALoD+ebpSS8LB/r9fCX5d6jhl72uVpuqTT+H3pVjATYc"}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.1":{"name":"browserslist","version":"4.14.1","dependencies":{"caniuse-lite":"^1.0.30001124","electron-to-chromium":"^1.3.562","escalade":"^3.0.2","node-releases":"^1.1.60"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-zyBTIHydW37pnb63c7fHFXUG6EcqWOqoMdDx6cdyaDFriZ20EoVxcE95S54N+heRqY8m8IUgB5zYta/gCwSaaA==","shasum":"cb2b490ba881d45dc3039078c7ed04411eaf3fa3","tarball":"http://localhost:4260/browserslist/browserslist-4.14.1.tgz","fileCount":10,"unpackedSize":89626,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfUqHyCRA9TVsSAnZWagAABOkP/0Sta31oPVNJ341fyRmd\npGPhoAD2iHQNH4IPxHWI+2/sk3OAJnYKC2XhHEF2j/xenp6eR66q2x6FpTZK\na8ZeUc3z3IZNEF5mm4EijDlIjUpzzfyhqxkWvcE5NPvXQPFpxbxYa5w8+3W2\nG+m4f1kbVJ4HXH+orEzFs5JBVdA6PtZFf3UtXXG1pkCiYnxgNY+xupx53Q7K\nuGpG4Ac5uTqxhaY5X+CDOGxpehnd9fFtBdD0e//gz5Dy+y9JOCrMd1XofLYR\nVLDqLGbz6rGh2lqhp3EyRUkVU1h4atY7CqnnpxGDyUr21ocUhXXX8hRdVK8o\nn7aHWPnSC7b5XSOXuhmuFpRc1dFclpvqrstyvPc1Pg50QMmeE+5aBzqNaGaO\nTdbwcjNMlveFgKEWDvaEOl0xY7iZxqHMkZvefi0ZpZ/zFhWqp+hhvw1s786J\nnKbLqwHaifdps1tqH1UhicHf/2D8D2qisGpKD0mTEveL97qXc6k7pjplbXJh\nOepJ0BKtyA3MiFjWIa7ZvBCO4fCZFnGuLSWHc+ljxRCDMWQmC1vSMspoVR+E\nPeX3/ZuI4wgcCukfDHqCu6M4iFYu5IIBWF50tc0W6hd4X7TiQwEBQrsQsZPe\njxbYcPCRZIF1XmN1e9BNU7miKcEeHN8Rgbpd8F9J4Y3osVCPI+RNLabvBDUh\nWY9O\r\n=2rEH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID2dhB79WMFnM0XJGXrkjytAm5jNFwAnrPhftRYFB/afAiAwOYRm9PmTNrilbvq6W6DUbmx5Eke8AJIOln/ZJzxCXw=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.2":{"name":"browserslist","version":"4.14.2","dependencies":{"caniuse-lite":"^1.0.30001125","electron-to-chromium":"^1.3.564","escalade":"^3.0.2","node-releases":"^1.1.61"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==","shasum":"1b3cec458a1ba87588cc5e9be62f19b6d48813ce","tarball":"http://localhost:4260/browserslist/browserslist-4.14.2.tgz","fileCount":10,"unpackedSize":90018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWSNsCRA9TVsSAnZWagAAtqcP/i+lCvp3uvmrhV8CeMl9\nRGhPoQWdaOD9hlI1SZEOkaiDNIiGXdtFu+ol3Ex1UPYbu/KGDi/ZJ5a6cRbz\nl+Khp0OZyd8EPrX3jvSWxdS946D50793nIWGTqzeXZdZoHp1JsevAKx0/uPX\nLACjwrwSUB1eeZbdPPTumixka1weN8DLgTo0frzKFHMpV9F+lCl5NjxIFprR\n0S/TbVYfyVA/HkeyQfUX+Lx/iFfT64bPJbg3bzXnYztsYneGwEmcufMVR20z\nfimqYcl3CT6agXZmkf6B0Nc8UwElpDKuuiiWLqnhu5RPW1rTH0ZaorhBVZ+2\n/ZdrJzUmIyIRyproyb/6qxkRNfWJlCa0rzZuSuh34b6jw6X+H6O1JdXU0lJb\nIUQHP5B1urZSkmEk8eRgmvV90GWPej8hCdBcRb2mDd6o9EDdJ13LtM7TBuYd\nlRQQB0FnandcRWmbF8Br4DRurW7g8lJ84dAjVqBlyurkHrE7iFe+bDwlv+sL\nwPgA9QmAOgSHbBU54iV4h1UZ6LlD9fikM+spQ7FeQMvZP+EBPikRFYVOK52M\nV87DvGIpEZB0lQeS4P8DAErhRQTsUfNZAH4wdBPdkMZp5BsTc2zFISANVbLs\n6RV8slytDOCL5Ly4X24RT8YsgE4NjREfhO7gdlYZvNSsxgg8xANzINz1tvmb\nVQBz\r\n=Vni1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHTJJlm0TMtBpayBIsjjoGqJm5Mo2TnJYZxGigZM/BKAIgUpd8LgnMPvliGBGSLAsoqllPdB+gkA63mWJ63lu2aao="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.3":{"name":"browserslist","version":"4.14.3","dependencies":{"caniuse-lite":"^1.0.30001131","electron-to-chromium":"^1.3.570","escalade":"^3.1.0","node-releases":"^1.1.61"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-GcZPC5+YqyPO4SFnz48/B0YaCwS47Q9iPChRGi6t7HhflKBcINzFrJvRfC+jp30sRMKxF+d4EHGs27Z0XP1NaQ==","shasum":"381f9e7f13794b2eb17e1761b4f118e8ae665a53","tarball":"http://localhost:4260/browserslist/browserslist-4.14.3.tgz","fileCount":10,"unpackedSize":90037,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfY4JVCRA9TVsSAnZWagAAnn8P/2eBOtjrsl9nPVlHuSde\nBrLCGKheYJHwxEwCHVIwbN+lYWjwAN9ILCJUQPu3aHmGq+dijAGxi188SF2n\nXbG1Kf62R8YY+9BSMjGGBEyX249d/epeT5DgKpbPeA4hK/3ASe1QqFRFpqdh\n6ZaR4+4QWmhmNFPGce2vN3Dg37cgI9vup1zdUrLtysY/ECWSu7hTQx2lB7xg\nhezeTAde2nhK4+H1goO4D+lXLwH/SBondtNO9Hu5Zergk9L2amTjRR9t0tqO\nIeNj9D3u35go8KEJuD6s6MYORfQcjZtcluf0bpTxfYQwbwTxyl69fk5KwFVM\nxZZmW5AZ3neGpdnv8g5Hi4OAgoxGzFVbykyuYh8t43MVDFPc3DYdEuFN3Trj\nb51/l1aDsYlUQba2J4DcYS8dBNQO1tTmeUYliFiBQIRvYdLOQllnBO8dsXQ2\nd1cVJbqHriKrjc1aHCE65FZV+hS/a0yi5yuYYeUQcLrYs59tar2f9K341zwd\n8AFuHcKA58MiebfWTAvliGYgC0lSa6aTJpdZs+nQRwMLytpuBVlJiajuYcO7\niOSJAZDdqbgtkc3dge2W7k9fWGzz4USO5s5WZvea8i30aJvWHGsQd3JvMG65\n2Kc7DrZMFNCvS+YWg6Wk86JIEDGIBEpvFG2Uld5d9X5Pk+wn/d8KvJHyFBP/\nvc5M\r\n=LLls\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCbw5h0vMpEeh9QL+J90bOxMfYLt3SpjBso7/1HI3m8zAIgWTC9sYUvMaxjajEIf2f2OlRnH8d5ZKOm9Kd9vIS8ptk="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.4":{"name":"browserslist","version":"4.14.4","dependencies":{"caniuse-lite":"^1.0.30001135","electron-to-chromium":"^1.3.570","escalade":"^3.1.0","node-releases":"^1.1.61"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-7FOuawafVdEwa5Jv4nzeik/PepAjVte6HmVGHsjt2bC237jeL9QlcTBDF3PnHEvcC6uHwLGYPwZHNZMB7wWAnw==","shasum":"66a18131439f9e16c3da7f352518dfa12f60b0e3","tarball":"http://localhost:4260/browserslist/browserslist-4.14.4.tgz","fileCount":10,"unpackedSize":90145,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfak0ECRA9TVsSAnZWagAAAMIP/Rg7eKcyvwpnI+JIScjE\ngE7FPEWeBKiGENuOm6zjfiG1+W6qxsXPyu7Kbr5nFCLPjuaDOZPCIATZdlHp\nFacyGvBDbK4KxqibKE239Dh5bDaG97NDK37xGGsp++8ftyWmTgZg0GUjyDCl\nw91YGpRK8bc1tv47QTzNObs1rvuF7KucoNvbvuNBLbxqr1GpTxLeCh+HKrnZ\nEtcrTNmt+m0xodeVOUPXScqedWnoVEPZqxy3x/5SMbY8y91Gow37lW8AccfP\nFqjT7sVCkvNOHrAFJBUJc6KxXd3up10BM6vgJOsAEGTyEqcvpGC5xoSz4Nk5\n5Pkmjuzmf4yRuDcnXNKeil8oFzLcGPwnZQrxDhPcYKDDJ6KikvEEFHdT8ede\niR40mbRFJB+EtDV14l5foKROGi4toIx4UUFwewG41iQSJtQ3mU7I7yp1IkaQ\nA92U7/10bJFDOYEBCf1j1FK5jmMLNgHC2aWCy5izztmFMVEzCscRJV3ioTWb\nhuwCdv1tpOb/jJF1HT448m3vLyxtuiYA+d0KD+kf5VU1mnhGlgFJNLe293A7\n5PRcgBIoRo8xszpi7nCUCBFITXeXAPzFsNQ7DNXAdx8oaOlpeVGnzIj2mnCY\nxZqwJaU0God2YTm88HQJyvaqsGIS8SC8dlNBgMPUXx1VRsYrbr05MwTO40wr\npvXP\r\n=kB/M\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFfWcTI7UhhBQDn1G2SpBSTRiRKvbBSrsyWlErnq2ym/AiB/wzJylJ1RwhMMaU5duZH4Gsa11IhN9NR7+S7Qv+e8ow=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.5":{"name":"browserslist","version":"4.14.5","dependencies":{"caniuse-lite":"^1.0.30001135","electron-to-chromium":"^1.3.571","escalade":"^3.1.0","node-releases":"^1.1.61"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==","shasum":"1c751461a102ddc60e40993639b709be7f2c4015","tarball":"http://localhost:4260/browserslist/browserslist-4.14.5.tgz","fileCount":10,"unpackedSize":90209,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbTc8CRA9TVsSAnZWagAA0KwQAJa3xlIrkh7OMGnLrrIC\nOO8SDbp86+Enh46iZgO/mObu4i//kdt2F9Clln1fpuYk46/lfZsPzKmgH7XI\nPutcTwBtxOLPr3Yld1/B/28Hmv0PdNMfnoptLZ5z73KyfGILuTj7B0o1lnRi\nLUyAysdoq7/gDkxcBCsdb0v2sx0DLDh2aGWmJMLQ9R+Fk98QtYZvIegLr+8o\nH0+1SWsWVRexln6U3ABfTI5+YTum702RotHABZzcB/5WlPU2fWZFsxx4uzTD\n8kwX8OPG/nHEu5hYJMmFEk9SIl5mvwo5yNVw8w1wE/SIy9yGCtCgA0vJV8PO\nMDuzppAjBQRlilDPWDJikHEej/uknjsaOwxfCgkkv+RCIXz+rj2a2z4Ktvbq\n0gC4AkPTy51rSjmZ6U1OjcRWh2K7qcs646BJNWB1RKWdweY1x490at3lhB1u\nVGHMecmr1MpsyRCpnHI9nQ0I8F476BgCnYqabqO3K5enTSMOfVYiaY4Qozgs\nm1kPoY+r4foKIVGhLlcyhYI9jESZdaHYIxKpgLd89onoXMJAKtwP309+5FNW\nfWS47A2RCqy9TIBvWEDAECFOwivwEpxp4E6hzGE6dmD0yM9pTvliPeM7Q2Xa\n+eBrdMTzLlTBN0GRYEMQbYyZKBbkOXt9ZEC7ZGIeEdw34hKdm19t3M1vm3tc\nuqQV\r\n=895k\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDmtCll5ixFnL750Ip1beGmi6vWEQo9A08hqhdzvwSeYAiEA4gXQol0LXHy5Cfqpp+f+xGypXQZqqCZjbsdj+eNa9l8="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.6":{"name":"browserslist","version":"4.14.6","dependencies":{"caniuse-lite":"^1.0.30001154","electron-to-chromium":"^1.3.585","escalade":"^3.1.1","node-releases":"^1.1.65"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A==","shasum":"97702a9c212e0c6b6afefad913d3a1538e348457","tarball":"http://localhost:4260/browserslist/browserslist-4.14.6.tgz","fileCount":10,"unpackedSize":90814,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfntBTCRA9TVsSAnZWagAAlxUP/3Wc4gWqrbN5kTbWW089\nBI8jXiVK/Qj5iSE0Xm5pRaSwM54fubXerEGLbkn8H7MMdcRPOztU1G9+zR8P\nD9uZGl7+6ZuMjeY5iSP7AGFLjmzMPh+gma6Xazj+c80PMjsbNCVm4ToR/LVW\nbYwi9mbWUvc09AoYyPaRAhJBPB5ZZQiyIaQiL0yVOA4XbM3EQvXn2us5eW6D\n/GUZPUa6YCe8YWb+kqIwh406bRKBDROJvTQFkbmHWwCcPVU7Hf0RKpaTticr\nvRWigeI5RtxHwe66NYRg1IBT5agMNzWhPcS5JBYo88Bo5U6iGW3dyslNM9hg\n2ZPz3n+MvEJ0T/NzeRheHk0n6yFsXI2KCwXEgaez/uVh/nq0W0ftOdYcoTmA\n0RpIEa88LpZfN7vtHFjtUhXdid+lXPfZgZcwCT/6/puKMm5l5aOhl+MSSn3R\nX6WK8qXi7VPo+KaAq98Q2/Bc0SHwJoKTTTvAAqYnt82hrypi6tzocZ1aXueY\ncDt45p+4tdBfuNBlcnLvqtYM8zP1WynfN7MFIz3Q0m9cdyYVNK4+mo5mZ5XT\nGuD4OSt9KTaz9m1B1QPMqLxs7J9CJTcxPF2V2hQDrvH/9qGawj+2QCdQ00JZ\nfjN9M4LFJ+1yW591eJinLSAk6pj+U/ZU/i9wZTHIiQCuu8Afd3GMAPvilDfR\nsog9\r\n=0vTW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7MKQqdewEzQevWRVGl6JrmoJcdGkVaXWuGjmQHsN7AAiEA5J2HQLZv3az4gly/mu4fx8HUwpwQGFcSpD779XBShuo="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}},"4.14.7":{"name":"browserslist","version":"4.14.7","dependencies":{"caniuse-lite":"^1.0.30001157","colorette":"^1.2.1","electron-to-chromium":"^1.3.591","escalade":"^3.1.1","node-releases":"^1.1.66"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==","shasum":"c071c1b3622c1c2e790799a37bb09473a4351cb6","tarball":"http://localhost:4260/browserslist/browserslist-4.14.7.tgz","fileCount":10,"unpackedSize":93683,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqYROCRA9TVsSAnZWagAAQm8P/j4iUq89CzcxW5uXN5rk\nknBPvAAGBQa6U96zKyg7zAPsiGxvgERtXDjSSEQl8VW4s49w+H35GqzCBMmT\nULNeqQ87xsvUI0/tupwhnanLED+61liPwI/gkZsR/q0C1HIRnXznJP3QkcXW\naHZNPqtJs+Mbj7sc2yG/miCflQt2oPmmKzPfZfuikOti72XUYuV7e6so+U2f\n24sjAAicixcirGT6gd5NQ14ccay2Olj1rDEWjDLZfRAxF9qz1nDfjoUhqDMR\nX081BDgkTQ8oa0Yvo0F8Af6/o1BD8IJ3x6FZ3VHkZpYbrug7zFljR5EWIWr3\n6/P4phYEIpisTqc45ExiqG21bvRWS2lcW3vn9qzB6lKNYiVOsN6gtCuM96X4\nDO4cA2Q99E5gnG8cCuT2SyGycZscWayWxE6Yu05UouzFLr4TQyJRyO4NXmUJ\nvtAyRsHL5dM/aD/p2GZ1W1NZ4uziAxDimNrK2E87d5KlU29lkovf97qgy7LO\ngFHS997ldqcabbLqZ7vaaDUJwaSqGoeGxgJyJghWREj137gk8G7J2p1To8rU\nynzRD/nCtvIWnSi/0uQJgQVi6Kc78nFo6Df7MPk2ALjr/4RWnuHmyTkuyHJV\nkC82ip7J5SRd15w+IqsEc7mzPoYWQa5SnbJP3GDBJftBT1fVm7A9yL5o7TAc\nrnRB\r\n=xphD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCI5t43H8xTGlfzG8ZEI4ehzhq6qjjOxQ8XuwjXDWEJygIhALYzUQqCse4/gTBP0Vd2c6lIBQlx6bo6TN1MUsN46CVA"}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.15.0":{"name":"browserslist","version":"4.15.0","dependencies":{"caniuse-lite":"^1.0.30001164","colorette":"^1.2.1","electron-to-chromium":"^1.3.612","escalade":"^3.1.1","node-releases":"^1.1.67"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==","shasum":"3d48bbca6a3f378e86102ffd017d9a03f122bdb0","tarball":"http://localhost:4260/browserslist/browserslist-4.15.0.tgz","fileCount":12,"unpackedSize":97897,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxtTkCRA9TVsSAnZWagAAwDcP/As5mzAyImXjGs0WJ/k/\n6UWFNofi4Dzw/YQ2z0+uIEcEuMA3jcgO5cw/hXQDbcnotN2hwD37yg2HfszZ\nCY+o7HtgN2R+z1NOjq0uxGGgVmB4gvb3z5L8j1KmjVvJFgOqbfzo6VMeLhg5\n2l7/2gPwy41mWXqDDfA7+xH1taiWughdA6IF1vjAZ/TjKgaA2sWCVzW9MU4z\nNHNIHfx7GSZCr2N7P2OhtV1vc7QnBhSeExgtmNlH40CP3TarbtPjBfWLDLIM\n8aaGEpX9HscTNWyCZ2hu2C//t1HR9HN5nGBDwGKNo4379EcKZiWpvW7KeOtq\nKaTM9YOhyyu5j0G5zOUkPCoyPgP5bMINtNfQPnAuNixQThzuvhUqdoD6ZZ2E\npj5hF+BtArav/sMjW3yNXeUlH1nzGofwmn0H5/CkBujCTlPs8LqiuTydd/Mj\nnfVDc8K+68Vt30G9vveZ+BQFjs6XsZMAnUHobi970hOniwAjvMiIm/4sKtrR\nGYimmQ1MOC/VmIRXEzCBgBFsa8o6k6cFDibYVA1nbnsn07zdai6FEue9WTTn\nz5/UuiHq28cm1520gaW/5fdWKsd3xGGzqbw1cZOjtC9i4FBaoFRO2hGjW8gJ\ngcMXN2yTfwaYZaMxZ6sYOs+S2dkD67FdSb4cexXYXJjH+or8K9VkAN49MYzc\ngCz4\r\n=DeMc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAT6y3TdzvYtvA4o022KrViVnb6FrEl9JnnNObVUTabwAiEA3sDk09aej8sN4RnUHoFlfMe64rO1uCFctDwVHHNqbb8="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.0":{"name":"browserslist","version":"4.16.0","dependencies":{"caniuse-lite":"^1.0.30001165","colorette":"^1.2.1","electron-to-chromium":"^1.3.621","escalade":"^3.1.1","node-releases":"^1.1.67"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==","shasum":"410277627500be3cb28a1bfe037586fbedf9488b","tarball":"http://localhost:4260/browserslist/browserslist-4.16.0.tgz","fileCount":12,"unpackedSize":98337,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0e5bCRA9TVsSAnZWagAAMokP/jtYLQA7uJai+MGzgMC1\nq/PBet2FOKJ1zEKrxzc3u6UJ9eof9maziIVKBcqUixP38w4nZpQODECz0Zve\n8+lzd5S11n6AmBagCYuS4pN43yC1ehSjzM1oqGLPlWSuXyPo0caes4+WS4SP\nO7Ia1JWm+088KbscBoPbcl68LmxfQ9BHx4Oqp3N4LbslbqkkOtV1JoiSQhny\nwJ1DsfCNVFTWLCfGyoXFKqvwlUHTEUN4uH87ly9ay4a/RPoWSgCAiuaGDLN7\nY9XDNusu9maZAVj9SdsKlN4MBxkMLtK5eENsEC/P7XVzmP16WMTTIYDCAFkr\nUjzTBwab1MvjTNTnpaS58YCFBOlLYERC1aoO0sZeJhk21qAPq8UpFHh8WGeW\n9XCX0I0G5i35mOzqISouthJMrAzEBK2v2sNsQzFjj3tl0VwSwlYCZSLqrpC+\nrXjMTqfKe85NFVcF0i2Cy8fLV0eQ/do316X+3Pj3yowCKZZ8tVFf88Q7mPfq\ncMtMeLRuM19+JjQFPffq0o6zwIRg9Atq/cyibB8i2mov5zV5ynMqovsPN7bQ\nM8xcyhIcSAlH27vPblCnjThjpwfSJBqS3KIrNMzC6KBqbeaVVb+SmcnCWcIL\nvOD378HRuD2FIN5n57Mh722wUj1zLz4+Joch0W+oWIeO7YWVundlGjwJAES6\n3YA1\r\n=xInT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCl+oKFlDAJoxjm5obWx+98X934kNe/EQ7pLV9aIuQHxgIgO3g50aK+UQhaP2id1ofMigYv+nb9u8UPsEJedfav07k="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.1":{"name":"browserslist","version":"4.16.1","dependencies":{"caniuse-lite":"^1.0.30001173","colorette":"^1.2.1","electron-to-chromium":"^1.3.634","escalade":"^3.1.1","node-releases":"^1.1.69"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==","shasum":"bf757a2da376b3447b800a16f0f1c96358138766","tarball":"http://localhost:4260/browserslist/browserslist-4.16.1.tgz","fileCount":12,"unpackedSize":98375,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf9RZSCRA9TVsSAnZWagAA1b8QAIRdpRl5Ag6tYfSYFfMR\nchv1hpBXJQdWgh0YhrByUfLXRJChvxGGXF2wEZZd9+8aCbqpnr3RXX8ZXqn1\n4/lqve9UUGgChA53/DCs2FFbEBf/6pgvpTSPVdVn22KzcwRAYIGuYfmityrf\nWwyDV8NPTzu4cx7H6GvDcrJKv9vQqn4OJ/N1p4Gn1mu+VQpZLUnMVV3/o8Mv\nrSbWVzd3WhwNPV5utTGiWXJLg4BrjBB+c2Jreqg/z/W4iMdmkg4LdkGdK//D\nrh1lCy+TiwOo9VIgujTz0Hks669VtMiy0PMc0JMK8lay2G8YQrD2v/pVn301\nsxAk9Wy/Ci6Uk47tykSKUO1WXrG6n8LhehC8lHT/SKcaVuFGt7YnWCU8CGz0\n9TGZUyE1RQRsNGURGZxc2S+8NAiTCk91kbF7P3O81p0AazKFBOuYe+FGu1l6\ndhMDwRnZq0f03XI/bSedLYHFPchLIwYfT2wTJeyo045Dw3q4BovZr17yMYlM\nhWj3yNYmO8acamXmYMLwD3EqFKxS4y0mCJNhPK7cdtsu/sE6XAYCfIr0TZtR\nILejwvAU0ThS9JnmXa3mLaqLG0Mz8s1F01hw/v7LzSo3P3qy7PU6mc+JWjnZ\n0osYAIqQYMXspkmYyvOlT5j+PZAzEkYfrt4tqvf4WHZjRknOeB04A8PMB5Jk\nap1k\r\n=XdeF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqFjhu1GpZ5t6Fiu0+0+hyy8bKIFTFb+7ITrMzmeMzQQIgFCHw6oxBN16uMJ7eJsemh2M5hjfcglBeiDYq2OUCaSI="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.2":{"name":"browserslist","version":"4.16.2","dependencies":{"caniuse-lite":"^1.0.30001181","colorette":"^1.2.1","electron-to-chromium":"^1.3.649","escalade":"^3.1.1","node-releases":"^1.1.70"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-oi5WJ1XukqFwgGsMxja1dySAzyWaXZqWSEWDedulO5M63JDw1rgGQbegfVZvxQyXLwkHm44xUbLsgP8C1iHeNg==","shasum":"f79d67cd37e8d80ff0835fe7bc456e406fb1582c","tarball":"http://localhost:4260/browserslist/browserslist-4.16.2.tgz","fileCount":12,"unpackedSize":99356,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgFwzRCRA9TVsSAnZWagAA5OMQAJiztov3ZCgZf7sBx2Ex\ncYvJ6dsuCOERTJaFio4y0WPfJkpnfcYP+63U03+6sVb4F6JCYCzUtQ5A4oi9\nSwtySBgssVv/WGVMZkcS/4jCi2nhFrZL3BT/oh0RisJucaUcwP1gttY8qyDL\nBqJsgCTo8ClsMTYHbdFqnQUu3RtdmKc2bGQLxGtHkJOgT1O6I3U21jrsTHJx\n8lckXqLJHn8UM71CsEtWlV3pSSHTlQnv8qKBXDEa1l/P13eDPNNPX2LKDGVI\n11yZS0RGLZRh2M3AK3YwAk6rSbeuNFUYyEXOSW8jKb0n9Uz28JAsHp3teAm3\nsaa2Ewbm2y8wtLTwJdiPt3aMWh/sxTnId2H+BawAmC4mqkvdhJGWBQPjUKxr\ngQ1W3FeMdXqb6qeY2AhFVe+61fx8fvGaTZ4/BwMsFMXWkc3lkyJRBd/OZ48l\nooLgPVNvp+DYPZT82EO9E5x3BerDAjIWs7A7cSwvrkoFHp0erCKkGUF3+Yyi\na0/gdVzhtXvZU/JBlGKfn96pPtJhe5mET2KHTaPXRPFp4TI7Gf6rSFI3rvV7\nzI4T/Ky6FDLtpFrpj0kux5TmEO86QGhgXKX0VH1qmw/jG60BnB21bOT2WQWE\nFKlYMnnR3D0HNQk7lLcbKyoAtMaZi+t+PXQW31/OesiIQsOrCX66uOEKN0XR\nrnep\r\n=fz2A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEwg8aVxGI0XnPj9yQGohOPtWBX65K0FzGZFn/zGj1nuAiBgbikRKNRJNmlgs1wSP0sthqG1YQSLC0KdMeSRLTI/Dg=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.3":{"name":"browserslist","version":"4.16.3","dependencies":{"caniuse-lite":"^1.0.30001181","colorette":"^1.2.1","electron-to-chromium":"^1.3.649","escalade":"^3.1.1","node-releases":"^1.1.70"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==","shasum":"340aa46940d7db878748567c5dea24a48ddf3717","tarball":"http://localhost:4260/browserslist/browserslist-4.16.3.tgz","fileCount":12,"unpackedSize":99386,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgFw7XCRA9TVsSAnZWagAAYpgP/iA5bbU2oRsOJuLTX3f7\nrvMY7oqSvRZtsOYVEPjJ4D9Yko6oAL0wCH3SBCy023+JqeURlTijaQZSsizu\nmFjrboMOlFJrasE+EC14gFMnET79bY9u7Y2otUZ6bQqF78xLQWPyXJfmOpLK\n3gYviKl4LgvhFSdN8IyDnEWVcqmnaWiJ9JI1hID7JmrDd3dz7rhu+Xfc1p5F\nHB6Y4kfa6zik5EL+PRKUPJmrBTbpMs8WShIeCPxg84ti9o7KboDIbF1tBNGv\nfbUXc1Tb5B6v4+UM2icA0OWpYpuwljJ3ZySlH7DU7fP6vpVGFc+FadINfZzm\nZBBzE5f4zIayHy7yUuVTqEbsu61AxxzKlu8GC411LhFeXkZI1atRfRUq2coH\njPk1GcRom1BxaR+iL2dXBW0fEU9ZW/8QKBR9qsUGpna6ZX+NO1AIDn8j0u+W\nZE019VZLIa8QSklBrbh2SPRVotI1n9ZyFarRHHnUXfCzxnL0SJRQwXrBqo7f\nCHeYcxiOEjVOPtAKc2APrK8FpUgTUED1dyPTSGYBn0E0VTod9jfRFEKo60Xa\nFxspHoGDH9b2/WrqEibKUaclfCLoS0fmBi+a0W2XoynLxA4elL7fjdJieHLq\n+lusAwLZZ3QGXD3GBrna0VxU+euRZmkqnG78B9EIty1LktCqJlLPqI2cEGVE\njSQD\r\n=PdCB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFUI/6eGR8TqScIWi5bLdeU3radqbF4OUu36kNTJuyNhAiAYbmOurxk2LqZWNi37HLsX+2Cghsj3Jge/0PWRkyaifg=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.4":{"name":"browserslist","version":"4.16.4","dependencies":{"caniuse-lite":"^1.0.30001208","colorette":"^1.2.2","electron-to-chromium":"^1.3.712","escalade":"^3.1.1","node-releases":"^1.1.71"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-d7rCxYV8I9kj41RH8UKYnvDYCRENUlHRgyXy/Rhr/1BaeLGfiCptEdFE8MIrvGfWbBFNjVYx76SQWvNX1j+/cQ==","shasum":"7ebf913487f40caf4637b892b268069951c35d58","tarball":"http://localhost:4260/browserslist/browserslist-4.16.4.tgz","fileCount":11,"unpackedSize":87246,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgdCbWCRA9TVsSAnZWagAAo6oP/jN8K5WpIulTyr6eFruW\njedjkdxnxCMTlVm0KE/3sgS0U5D92fc/TT/NZXDZz7IHk2/VZkWn7d1ncUMc\n6SRItfNXfcIRb1TtePItS4ZwwsnQxmJ+LqWAt013a8tWonXzmmAcDgEiVyNk\nZlzxt4PrxWcuxXWqTC3m2ed5e/Oc7cYtdM5I1gGWON4XWy/eV6z0Zf1qBHew\nIsRr35r0YCu4YETn7ccNc/oxScfuQQyGCTjW3zjDU7eDmDHGOpQhDisD2WlO\nn5UIn7+X8qBLZpfQGIw44RHWTdAZoa/fMKPd5XcLFbXlVxWIOgyDMgoFi8Ar\nbHLptcGbvHWEZBm+36KpCFfCX4gfejbzWUcYOe29LvPZ4c7A1iMAoil2WGMt\n5YqMZVodvhADMMEWXUbrpYvXhkrALFrmKGL2WBp8awrxaVZCvYtAPr45xkqT\nR/xoHQhkMkEVpagbHOv5lCI7PYTaEafqVWIOjsJR0RiqogiMFmhZTN3g2Z+F\n3MIoWCpTfCWGBA+irIhJCuYOU36MLVwFKYC8sYGXdfirwgK1qzOymYCBgEwd\n6T0TboO/WZ+Ld4MTFdf/SZFa+RRtN4/KYzPPXRP7S7ug9fPl6Lw5BmmQFPsO\nnRi3T0LntzcToM+UhymtgpmdlJ5VXnnZhe4uL9dr0Qj221shMG92sBau7OUh\nAk8m\r\n=d28W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGM4TW7Cw5cgEiQ9wAE215/Uc3TwyIdU/aoDYvTCBdTVAiEA2XSmvKy9yGiJRKql2gYKOwiaJs8AJPB6Ex+nyGS39ww="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.5":{"name":"browserslist","version":"4.16.5","dependencies":{"caniuse-lite":"^1.0.30001214","colorette":"^1.2.2","electron-to-chromium":"^1.3.719","escalade":"^3.1.1","node-releases":"^1.1.71"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-C2HAjrM1AI/djrpAUU/tr4pml1DqLIzJKSLDBXBrNErl9ZCCTXdhwxdJjYc16953+mBWf7Lw+uUJgpgb8cN71A==","shasum":"952825440bca8913c62d0021334cbe928ef062ae","tarball":"http://localhost:4260/browserslist/browserslist-4.16.5.tgz","fileCount":11,"unpackedSize":87299,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJggW9SCRA9TVsSAnZWagAArmwP/1jFeitZQ8/iWd9gB/KH\npuBgujALctXj+PeM2gF+O8PToRxCLu0SmbKBFvKHJtrOYqIo2WzRXZCwVMT7\nF6jCZW3XeglYayZUPvZSD9RuYSMLkeOeavtrnzfUUDWyQHAfqDhsyHnVhNBY\njGrhTHuoyO0JnA/iL/biJdhaFSkY+juvjTh5nQmqJUN2IoAfsW7IzXpx+eoI\nJvRR0aLy3IjIIK2q//Ffg0iV8Q0gOY+7G987AOtFrOujgrynzDyPKKkPuhmL\nhlHZeoWUj+Ydn0b1yfN8Azlh5GN8GynH54fXCeyC4YpacUgKLqZcfsWfnDcr\n38R9g8/KiPuutI2p0UnBaxUEAtZI4HRzPEV1+JQ5/jm4GfshlBU42P1BHdXb\nW5HzcJEdQhr1VHO5Gy8XXAjpJAKKbsyXITpFzySizv4c+AewC+hkvKsHxs1H\nkRZWm8geaCBeHdhGauDxt0v5utilmEeN4HvJlxYe3HhBO40aIem+dYX1mdTh\nt0j+iFlEYbfHuJirqq7VdZIwAutlaJUzuB2DWrQ9zsZcHNecSslfSy6MF+Zj\nTmbaVw9m5BwajEpecnBlVL992jMrA+uRtrs+7XegYAtbfpNMijZMXDNwQrhG\nLUrAM9v7gIWodKIa2hhYigq3yR2i5KUkiBkd32Pr2/iPRGtculc69XQtHSqE\nop5E\r\n=8E6h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDHDgDTOtZ2SObrDT3Ov0qVo3bqD7wMfi+l2TJOuT8tTAiEAuNx/VjIB8Ou3vxI1etaJnvnIA4PUiLVD1dyI0ruOQ+A="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.6":{"name":"browserslist","version":"4.16.6","dependencies":{"caniuse-lite":"^1.0.30001219","colorette":"^1.2.2","electron-to-chromium":"^1.3.723","escalade":"^3.1.1","node-releases":"^1.1.71"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==","shasum":"d7901277a5a88e554ed305b183ec9b0c08f66fa2","tarball":"http://localhost:4260/browserslist/browserslist-4.16.6.tgz","fileCount":11,"unpackedSize":87474,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgjAT8CRA9TVsSAnZWagAAtXgP/0fde3ruFSmgTKwtVFgV\nR3TuACE6u+csZSRkMsX89xjUBnxdSYeO7oJgfXowBc158VKzUBBTMpoGfWQ4\npb0Qq1A43AHJapXqsc+2ecXw+7Rj1Gd/ik09nypiKVs+XHv5bHhMpnwjKcH1\njrUvKw134Mq26GQ39zEg6KQ6ixOBZjexWUkEFPbvc0jU7ncta3OqL9j69qYI\nMgUCtjmi8RgJnkebd/RvLbMwLNYU9SZZNxs+D5kORswx2w/R/XOh8aF6Cr30\nFhc/XJ/rS+O+gQ6/KjUMdxwEoKt8eZgzcXUx/yEFEUlTO1V2MYTSiC6Sxrv9\nPJwVD97bMsDo/f7t7/e5VoufWzmP5ckDbkVxnd9dvXdLm+odECisU677ZpMc\nHvmNy4z3LUYz79z2mM2x1OZ9MP963DS2Hem1oDSOkpz+bJMQpRIdRbzidrb2\nDeFsFWxUAfXDc8E8Fk1VU4A4P/hCDDqGEnYneuVKVOL4pDvuOA0DMzQr709A\nSS+bY0nlokxcn4+w2IGqp3ei5NOPvQHTXm+8g4bEIX77M0giLmrQmpfSE4Kd\nJZio0j0toojwFRO3xFuP+xPbFC1IezIt37JuhHWCpo0tztq3DHyGBh78nXc0\nCdSrttd//stvUTreunQ6MoA1Owc8Ejih1RFutUrgIqodGJGmYnnDkSTMnCYO\nD56V\r\n=Y8LQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBgIZh/eG3Dm5S2M5KmuWGoRVh2C6Nq6Ys9AID4a722UAiBLqzi+MxnQi25L2gMougRRZtN2OvCLu+v2AfpiDi8WNw=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.7":{"name":"browserslist","version":"4.16.7","dependencies":{"caniuse-lite":"^1.0.30001248","colorette":"^1.2.2","electron-to-chromium":"^1.3.793","escalade":"^3.1.1","node-releases":"^1.1.73"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==","shasum":"108b0d1ef33c4af1b587c54f390e7041178e4335","tarball":"http://localhost:4260/browserslist/browserslist-4.16.7.tgz","fileCount":11,"unpackedSize":87585,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhCQoVCRA9TVsSAnZWagAAu8wQAILKEQQwabaAYsBSumLn\nLhLsXResZm+u+ATDF5F9MWrtGOg8CS+W8FP1XdrU6ez9AjCjMTvasVsxZPAo\nPuc0HlpJ72SGIvGeTtnqIAXIqa9g6AzYCMq7UO4TcaCmwBu4iLkd4KOMft16\n9r7Oj/gU0ysx+40UGYW/CLKAuaqDvm9RqFSReZWmNcVsHGhL+QhKm3sR3WyR\naUDV4VtlV6t8yytuwxS11tx1F+wEcCT8eRFjwe4ttAOsCc0QSPKAPp2tgFyS\n5xA+bnfL6fPCtbh8Dr5qZWL/cIbTB6j7sMr/IauhK12zmCiP+EXqfQJBjEj+\n7mkT3RtjvfuTCrVE8BhRZ94ohOyqVoXzuSiVB6IBBWJTUZYJ7a5MVX/MB1pk\nEeNLKuQkn/CpZX113b25EYxD3hxgFdSsyG8rWdXd0Wd3fVtJdR+bjSN2TVZ+\n6r1jRx680PwpdkYIAsOP0LFX39236Gln1ziczIbsU302kt/VC/wqU14YRDRz\nPbL7WLZE7g/Z7TVnFHFKlTnc1b+RwSl6wTjWmZZ0F9KfoFgihuY55h+yArfP\nfEWGZNZHmgKeMCirETRPPCGZFwP7A5K6K0j0Ia3iPkTXElgt7O2NgFtJyakS\nim0KHEPtp686ZkqUdPoG8vl4mofdWaX5KarhrmygMczm6pagqge/7cluN6ID\n98gB\r\n=lg0Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4Z4BIGpUdCf/J5z6OQQszvJT+aijNwV/wXi9Jc/s7PwIhAMexst98cPeSXttRHd8y7juZLzi01oAbZcxv9aJBl21v"}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.16.8":{"name":"browserslist","version":"4.16.8","dependencies":{"caniuse-lite":"^1.0.30001251","colorette":"^1.3.0","electron-to-chromium":"^1.3.811","escalade":"^3.1.1","node-releases":"^1.1.75"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==","shasum":"cb868b0b554f137ba6e33de0ecff2eda403c4fb0","tarball":"http://localhost:4260/browserslist/browserslist-4.16.8.tgz","fileCount":11,"unpackedSize":87599,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHS8MCRA9TVsSAnZWagAA3iQP+wZRi7He+1kb2+OMxTVU\nVijXx/sNBGusWaWh/hQMdHJXOQ2uEghaKXeS2HSD01CPJi/kGT9bhPKmymm9\nS9AcsPYECYH8ne2kWD533FvTRzj2cMFXrmeMJdqg8nTUzN3jB+Yp9drqVGyO\n/trkA7Z8q1uuSBnFs2QzbFX/cEITcG6+AKGUL0EPSJOYMdvMVS8Zt9i738+R\nAg3hkKFv2KZLJOMSc3ZkohSelamSj8vHmNvqtOHcCnCU1ioadvoSEghkg9Yf\nGVELAErbuA/JFvTx/5MBm93Xbv2hoKATu+YMjkJn/lbgpWUW0hl+hpRWXMkW\ndOCltJhQe24DUEux0XJ74deAbtkjKqGivjH+1C/v2CbWoZS23TCFgOiC56DS\n+yNz4MpKHtWVmAU2bYlDBuQhq/piqFCvQ0vmfliNB5kG12ooO7ShmH2PE+wv\niDBlTNOVIEVhK2EaJlOBgPYXGHyM5jfSU0OR+p48JVeHRJgcayliEl5yWzmK\nVJr2/5/r7uTZ2DAwsTVg3/Cdi40MnkDCYwZJW1dUwEMjDaPnqYTT0Xx2z+3u\nnje+WO1daG5M0gNUh5/CmA4XPzcBcLZ+0PsElegJczDaAm1Rqdq/DVFFfqjk\nNFlwlcF7MZmlGtWJUa/L195ah9oR8SqGXDGTJKJ6jBDW8EAamEFtg/SnqHfB\nX80q\r\n=ly24\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwQCrX+/IryKPQC36err8pEd5JHz3Qi3FlhtAmmqZvUgIgPluPugj045PA81iiKWa8SwCtCjLS31g3WVJwbTcinow="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.0":{"name":"browserslist","version":"4.17.0","dependencies":{"caniuse-lite":"^1.0.30001254","colorette":"^1.3.0","electron-to-chromium":"^1.3.830","escalade":"^3.1.1","node-releases":"^1.1.75"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==","shasum":"1fcd81ec75b41d6d4994fb0831b92ac18c01649c","tarball":"http://localhost:4260/browserslist/browserslist-4.17.0.tgz","fileCount":11,"unpackedSize":88773,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhNJbECRA9TVsSAnZWagAAlWwP/1BmSOltDDMW/dwCTxGy\nqJpxIOxKhyjsw5XYbmRiWShv/oI9l4RlRVVX/fR7YuyPXFV2z/V3IL9GhXtZ\nyFRSHhT/WKH0xE4TTRFStV37SkRV1SH45n48uY0SYm08Lkwry5O0ZWyfinjv\nyEb1ao4sSCvgLiBuNTCOI7nBv3FMMM8S08e7u0lzHEA9P9y048IqEjMEHXqg\nrvlKPzLh3rpT9Wjy1ow6B+IxFvbAfyGS/aVuxGLqaiJSzPXoMTahzEzABmOz\nZDQq4XrnO2p6k28lGfVn/HeYaqvnsmbn9mk9Xhs3+kNmA1St2ymX6Uk2xXhs\n2uhQIyIv+LmCjL64WXhd5nbfBylHvN8IFGw3mynSeNzJtfjKb1QITCAc9uIo\nJ2ar9EMpG71kquUz628PGic18NdxcUN2XI6rNYEJ305s9IC5QpUtd8OuwFHI\nAlM+ciBJtt9SohnCAg0iEDkukzBKa0ObG6/wZkYSAC87lXZtGquG/deYAVBF\nY9S1XqLFTeyXYMp+AgRNcYAPZtoqmB4RKPElnBj2/qwc9/FrH16/2bsreMdQ\nOgr+/SNR8FqeMQj4Gl8GuhmaecyDwaXK5hSKPzKRnvt028vZ1dT3yVPan+nE\nYTx7MhmUwWpuzHm75ioE1N8wttLAVlg0spnu1LRL6T8pzS7Si/brJjDyDrKR\n7h1C\r\n=kAq4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG5IWDfpvviIWb2kn/DHuPkNcbSAKxyn5AT32/HeaLzlAiEA2ytBdBxk6177+00CWnbbig7qHIrGLz4yBTI4HipoCS0="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.1":{"name":"browserslist","version":"4.17.1","dependencies":{"caniuse-lite":"^1.0.30001259","electron-to-chromium":"^1.3.846","escalade":"^3.1.1","nanocolors":"^0.1.5","node-releases":"^1.1.76"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ==","shasum":"a98d104f54af441290b7d592626dd541fa642eb9","tarball":"http://localhost:4260/browserslist/browserslist-4.17.1.tgz","fileCount":11,"unpackedSize":88940,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCDY/+O9u0BRX/sV30huk+l4jQyfCGUF4DfIhNe9VWo+gIgEIpAR2X5PjVfasUq5GJO8oQH0xSHAkGwRgP4aqgPQ+8="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.2":{"name":"browserslist","version":"4.17.2","dependencies":{"caniuse-lite":"^1.0.30001261","electron-to-chromium":"^1.3.854","escalade":"^3.1.1","nanocolors":"^0.2.12","node-releases":"^1.1.76"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-jSDZyqJmkKMEMi7SZAgX5UltFdR5NAO43vY0AwTpu4X3sGH7GLLQ83KiUomgrnvZRCeW0yPPnKqnxPqQOER9zQ==","shasum":"aa15dbd2fab399a399fe4df601bb09363c5458a6","tarball":"http://localhost:4260/browserslist/browserslist-4.17.2.tgz","fileCount":11,"unpackedSize":68417,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFx91zIYRkIqLVhH3hcUDz044v79+PNeWGSyLbt66K0qAiAFuoXAc7ZHgVcVshws5lT1268Bmgqckl5WSti5IYCaiw=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.3":{"name":"browserslist","version":"4.17.3","dependencies":{"caniuse-lite":"^1.0.30001264","electron-to-chromium":"^1.3.857","escalade":"^3.1.1","node-releases":"^1.1.77","picocolors":"^0.2.1"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==","shasum":"2844cd6eebe14d12384b0122d217550160d2d624","tarball":"http://localhost:4260/browserslist/browserslist-4.17.3.tgz","fileCount":11,"unpackedSize":68382,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBj2qEsQ0CNPjsq+TVBNfdGYq35bUGtU6G3y/fbKkLcOAiEAs/DINZ2dekGLJwGG15f4aR0SIuP9aBsgmhB/apEGO4o="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.4":{"name":"browserslist","version":"4.17.4","dependencies":{"caniuse-lite":"^1.0.30001265","electron-to-chromium":"^1.3.867","escalade":"^3.1.1","node-releases":"^2.0.0","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==","shasum":"72e2508af2a403aec0a49847ef31bd823c57ead4","tarball":"http://localhost:4260/browserslist/browserslist-4.17.4.tgz","fileCount":11,"unpackedSize":68381,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFZXqwObgOSh04zEqJMRQSW1t7lX7yyhS/T7jO7qST5ZAiAQoByPTTD7efYEpRTUya6wGa6bt9P/abOM3zzuY+FUlQ=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.5":{"name":"browserslist","version":"4.17.5","dependencies":{"caniuse-lite":"^1.0.30001271","electron-to-chromium":"^1.3.878","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==","shasum":"c827bbe172a4c22b123f5e337533ceebadfdd559","tarball":"http://localhost:4260/browserslist/browserslist-4.17.5.tgz","fileCount":11,"unpackedSize":68957,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBVbzZxQgjL177FyTaxgE9/WmVdeV5EQwvl570hq7Go1AiB+pqCtFiZ4qa+GdMLP2+HfqYjTJt0g3XF47XbO5+k0+A=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.17.6":{"name":"browserslist","version":"4.17.6","dependencies":{"caniuse-lite":"^1.0.30001274","electron-to-chromium":"^1.3.886","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw==","shasum":"c76be33e7786b497f66cad25a73756c8b938985d","tarball":"http://localhost:4260/browserslist/browserslist-4.17.6.tgz","fileCount":11,"unpackedSize":68665,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBKX1tMHzvwlsC+J3F8yRRiUBdVMbfmQH7JS7TKMYCtFAiEAxxMDUJFIwbgP/SjKFgJqCVmslLArTATEEDH8kB/Us5k="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.18.0":{"name":"browserslist","version":"4.18.0","dependencies":{"caniuse-lite":"^1.0.30001280","electron-to-chromium":"^1.3.896","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-ER2M0g5iAR84fS/zjBDqEgU6iO5fS9JI2EkHr5zxDxYEFk3LjhU9Vpp/INb6RMQphxko7PDV1FH38H/qVP5yCA==","shasum":"849944d9bbbbe5ff6f418a8b558e3effca433cae","tarball":"http://localhost:4260/browserslist/browserslist-4.18.0.tgz","fileCount":11,"unpackedSize":68811,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH1/6YvAvh27JfBpCH5uyVegaVCj25tg1onazGDApuC4AiBJOPMwI0mXjanrnK/b4uk6VlwOHzbfgAfeZfopMLGsKw=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.18.1":{"name":"browserslist","version":"4.18.1","dependencies":{"caniuse-lite":"^1.0.30001280","electron-to-chromium":"^1.3.896","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==","shasum":"60d3920f25b6860eb917c6c7b185576f4d8b017f","tarball":"http://localhost:4260/browserslist/browserslist-4.18.1.tgz","fileCount":11,"unpackedSize":68853,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhko1ACRA9TVsSAnZWagAAWIIP/1p5N7fuEDKmk4DfoI5f\n4zWNZ/LwpubxhzdGBz20Fw2fIVdxm4BaRwqoEzUf3Df/2797NSbetCYd74gJ\n5xaYJTUfS7LiGI7jFpVBsjMpCyRVMLGKcpNM9zr9cgIFQLUkpbZhmNVf5RyA\nuZV+u/8UyNluX/+D+uhr5oB+p6ZeCW2flHDOBjYX10+qEH8g00QT+yDm1NKW\nF9Fm+EUF1FsVB86Lxko6xWiZe8GshmwGYt3/sX5/zeoMXIbw0NEPLklCGj9J\n8JJu/8JWwZGtWcyvcml3rvkrbJupNFdbJSsunY4ca5mQb21mmWj5Zr98KuLR\nMFNme1G45rm1E3XRZDy9qYO3AN3f6dVJ1h/6TZVBN0n3gNujYzLC0YxhRl3b\ndE3pJvAXB8CnvcN6HAUzKtwih2tmkClzTETt3ie4tRJHfcanJG91VMYqyPuG\n4udObutkbleOayyIPv+XkClvoNbEl3B9oeB/NoJrFQstDTok8G/nw7E1QgFP\nJKkpoeVonPIwDH03gzdIxFLCbZhzp5zrV5MravSwhRz4b931gymxJbVlgL9e\nXbAugHu7lDvVeCChr1z+AymfyCCCzruasMvm7I6PqJCmlo+jE2EL/2qMAeTo\nRuRURbKi4Hr4MBKo0KSO2z87JGaVeCht4cNljMVO0SsohVeET7r/BzX5hfRr\n8zQf\r\n=GAgz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA2/EZPynz0JBju1IWAcBWBwCoqJzn4287nmLWN34l4uAiEAxyg4Nkef6Jnydq6qTIlZoZqs+iH7XiMsR6Y88bblYUg="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.19.0":{"name":"browserslist","version":"4.19.0","dependencies":{"caniuse-lite":"^1.0.30001286","electron-to-chromium":"^1.4.17","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-JGHzm73ei2OnAcobcQ61GXNnN6vDCg5Oz5MayudL+FyzjoLnCzUWnuLtDLMIYw8aXgQzzdCZMVky+fftD5jbtA==","shasum":"5f02742ac2b86dde56ae4cef7be2b003e47b1ee0","tarball":"http://localhost:4260/browserslist/browserslist-4.19.0.tgz","fileCount":11,"unpackedSize":69715,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJht/RKCRA9TVsSAnZWagAAkHkQAJG59mbs1QvCFy90eEGK\nMz6wbOQ5CbfuqvkUwtYxzg0wTUFU9uTxO4qgqd1EUoYSqjuJx0KPnpaZPHfS\n0Nzhgl1txUn6nfSPSuRM7Vu9PcWzQJNS9S+L8YHDKsRV60ti25Lfed9l6roO\nI9Iq6ZpiPEXawBh22wYPdsKTFlVr7+afpUbqjp5H1bANU55AndUdCks9caqH\nLWye7Erd4Z/4otDFMBwV/j0VT+PxwwouMgTk6TjMfU8nRzmsfh9GlFHq2D3L\n5BeGIhG0XHmmli4JLw24TMxRPm20PmnlyozDK0sGVPZ9MynBbgcX29Wyw19r\nuvkc9UYUhs9Cx92ERD1lvU1iTisYgm4e3/lKh3ez0BxqvhYCJCiKnQtK7GTv\n20txWTVTpcjyQ8egtgXEKtihecqLaMWkEAA3tqTsLDgreAg+f7wz0mJsLtO/\niJFA8DwuDKsvhOafYzX731gKwtgow8ngXDIN2O4+s1sNOwODX+QfOxwFu38u\nynFKB9nJxnopCAngwICKVgCaF+iG6PWyWQaOXlpGAcJpQX/OV82+Bff64GT+\nsIm5hW48f1hCRHq2oA+sR05TVVr5ptxdtQn9r0R+/wiqkmhOj/td0GxVK+3y\npWTqpMDAy/b/GiJl1wBtN0gLohNOg7vLyGGY7g4Y1Q/9XduZlhp8vmUvGqq0\n8qwF\r\n=Kxaa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFOOwA3NVPP6sfmqKPjDQ+0G8b97BuPlXF7PjoHK4NMDAiA9PvBgnoW8bbkFf936r1a7VWSAJ4Xxk/8RFJplUelO4g=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.19.1":{"name":"browserslist","version":"4.19.1","dependencies":{"caniuse-lite":"^1.0.30001286","electron-to-chromium":"^1.4.17","escalade":"^3.1.1","node-releases":"^2.0.1","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==","shasum":"4ac0435b35ab655896c31d53018b6dd5e9e4c9a3","tarball":"http://localhost:4260/browserslist/browserslist-4.19.1.tgz","fileCount":11,"unpackedSize":69802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhuK7XCRA9TVsSAnZWagAAEFsQAJxx9PE81WaRmnXLuIgN\nV4cqagVe2ymdh22oPDyaCJqeZUAh1X9GZvrx/LIdG5FJ5zUYMaJf1T6tT0LB\nvHDng2UyJ6aBLbYZBVmc5ckVbtdGm+6NIj/0rR20JTNMf4NrdqhobxspT2kV\nvMEUhFY75yDb+LJS4UQb6Nfc5nC7ZCeqC5ZhetQyetXaqjHG+VKmRJHrlOt4\nsKE0OgVYR7V2+FpqkPodS9XwIrYslG6cFeHSMidFi72gTIEs+NVfikoZqopT\nw4BFOv4/GVvzMvi3IshnfO1KpAO+lfALTtM3NNOg6vCIT3gkbGY1g1FQFN0R\nlxs2/q43i0UnFSRQqgpYA3Cd3RMHqJL2l4rdwdcjkGDuE+riTQn6ToD/Grnw\ni5Saa9VqgG9stVMoTehFO9TAmrO3A42yy6HekXizaxgibtMm4Ftp0Ksxa+BF\nGY/ap/E6t9xMP4oXa8r8J2CacTCJn2xFOW8DD1N1B8Cw4mac7CPmbHMmbzi6\nflEcEfpC3MbA1c/1xaPhzyWe9zem8IuKGfjtc3ajQFsB6E+/G4toRanI+Hau\nNVXUiptkyj8jRshbKBIwjbeq3dEuwu1hlBWC/zw8SqMepAiwZDNLL/gIMcnN\nvmYX6MM2/xneaPXPwDn3ISEAvk8qYiVAlhXBXNmOdrYvXG20MvZNwrQgtqb9\nI6HB\r\n=0mBH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGaJ/dmbZrP66FQSvndJE/2LYlRAUU2TeUdOGQuxbsHmAiBI4zJ8dxdDBgjDZe3dTjz9LRvBg7b9BUNBu0P7iQcaeA=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.19.2":{"name":"browserslist","version":"4.19.2","dependencies":{"caniuse-lite":"^1.0.30001312","electron-to-chromium":"^1.4.71","escalade":"^3.1.1","node-releases":"^2.0.2","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-97XU1CTZ5TwU9Qy/Taj+RtiI6SQM1WIhZ9osT7EY0oO2aWXGABZT2OZeRL+6PfaQsiiMIjjwIoYFPq4APgspgQ==","shasum":"9ba98791192a39e1242f0670bb265ceee1baf0a4","tarball":"http://localhost:4260/browserslist/browserslist-4.19.2.tgz","fileCount":11,"unpackedSize":68180,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiD5LzACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoRWhAAh6ssPOt5PuBaO25mu9YMZV0+HgHH9ihht0NHEOvRLeSey57g\r\no6IXHXtiaiBZ9TRaqzmB+GV913fAZgKmAzfQ5NI25AxXFfdI69EEo8EDrwPQ\r\n1tyu3rwMxBDL9gSWaRHhOQJSuaI/SMRpWYSZUY89SimODV9TFccqyshd1Mij\r\nkSPFVP53mIydfpbK9UEkrLVbgYJbvKqYEIDaWFvaEXStFfzB366nKLZWYUlc\r\njpMjUlEyYCayGSfswh+pwm2Fg5xhpLGigwdSXNir3dg/jWGZ3kWrltYI+Ezn\r\n6nVI7Hx8ljFZBLVUto5c4EEiFOggEjf+ubWln5JxfoDmu37PDsd61g8uxRlV\r\nRP3iAPJntp3+3udm5UwuHObMHZE5VBPCMg/XUAtrOPaxKv7Ds1dAjoxjdFlH\r\ntH+1cQvJQ07XBN3pK42XqQpNkVjqhGbde/iFKwyTh+8RJmkwsFH2P9UKwyFN\r\nOHiBsT9Q6l1ynpjjpSJ7o6ZrXVeOuy96Ytkij8rUx/GvVMC66b4kOP7akK2p\r\ntd0MNmNzmuK5C2ByNQZok4fcqGfWPZsbL3tFNoVwImG10+xFlPkzbfDVQ1XV\r\nAtw98AYO9psjxW2WW8/VAMaOBftdbwpTGnOa6bV+O3Psjyd6PtAe0sVMA7rO\r\nUWBYj4g7ZqOxZSLXCfj3tvxVFqFcmFUKq8o=\r\n=jer7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGwX2AwwyDsvw31wk5SmKgDMCmsDYQCobNxwRxV/gZdNAiBk/AowTWhdCKvjRaeoh8o+vQj+WL7gjc6Xgxnu6pK2IA=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.19.3":{"name":"browserslist","version":"4.19.3","dependencies":{"caniuse-lite":"^1.0.30001312","electron-to-chromium":"^1.4.71","escalade":"^3.1.1","node-releases":"^2.0.2","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==","shasum":"29b7caad327ecf2859485f696f9604214bedd383","tarball":"http://localhost:4260/browserslist/browserslist-4.19.3.tgz","fileCount":11,"unpackedSize":68166,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiEDdQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpnoA//bDZYgKIEkuIbz4byewZeQBvX7cXOHM2geT1ck6Lb5DtA6i2g\r\n1nePJeC3pQB91wU1pBOd9fHL9XuoAlLoV/V88SZgHgrcHCpnyeJlaCexTQKV\r\nWbKbGxVw60wQKPT3xRTdKNH/FlJAJhGFL7HmUQ/+Sl/X4kyJu0YZwsjP83F6\r\nLqyE8S446ZmfwbG1zwasgd7btl6vsn79mDfJhHOFNmGc11uEn6RzvxG/GbY3\r\nBi0K1/2RkS5NA94/w1kyTLh1YrJPTTHK2lrsmX/jj0AttEKpm3qKgMhm3zrn\r\nV3wH9EtjLVmZ6wvBQHRDS8KJl38I8t3Vn65DxkvLm7FfFyi4TvLpT6xA2wr2\r\niWbOXhcygpEt8k+l2fxm3ZguJ9LH+SWC+cjwM1frCNyBHhqaUBkgJeZ6HH0j\r\nbPznWCTERwOjciyZlI0gefUvMfxoDgkcl8Tn69LFGw3GZv9Rs1g7hKBanmzK\r\nfHBQS8QfcUdYtr/4tfYCtvtf1eoax+r8+EgFWbSWeXvwielKKdrBSGexmwEk\r\n+JBWgU8H40wcxMnBrMUcHF/JTAI8AbhLCaRmQHeM2YcYHZs5WxeEOppwKBSQ\r\nO6fY7vZu/MJUbuy3C34beMDb88VhR/fPl0azkPOiUQ19rPxEsaLH9Q3d65u0\r\n9lai+OTzUYV9UHTp3R4Jzioi/Iyi8F6/fqA=\r\n=nykY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCe4/nre65LdGIzRv9S8fdls8i6ebDD9u+SZunGOM+udAIhAJYob6HHJTeaIHI8PLghmt80I6UY6Bsoz3PZ3PRK93D/"}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.20.0":{"name":"browserslist","version":"4.20.0","dependencies":{"caniuse-lite":"^1.0.30001313","electron-to-chromium":"^1.4.76","escalade":"^3.1.1","node-releases":"^2.0.2","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==","shasum":"35951e3541078c125d36df76056e94738a52ebe9","tarball":"http://localhost:4260/browserslist/browserslist-4.20.0.tgz","fileCount":11,"unpackedSize":68374,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJTrGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpSfBAAmYBX7cLmqPL9+Jrp2n4rem5GQSP5oodal+2r0nyaE4fl+7Qo\r\nPwMlRmvi3X9XJZDbAatSommBi02smbtLer7yWSES5j0dJIQ3Ce3Ry7VnywfA\r\noYpAda6URzKk0XCbMaF+mzzvRtzqhEuvyfzZGuk/Y0RIEaXsM9+c90a8zr2Z\r\nMwLy+ZVn1J/+x/eUFcz/SYIwYxXQA+QbFJcTv60QYnyd9RI5wHpVBuu1mYHZ\r\nsY2eMZyZhZgELt5g/dLKVznDLRiLGrjMoRYU8b1YUp9RDd+oOegSXtda8JR4\r\ndKcRtXPQRLRXDyRHskWo1zt0llSaxWn3O+0Z4N4MXvO+ErRQubStMOocG742\r\njgpHVhHxdZKLO0jhEXuYajtJUs087Npy+lTjjq6G8IoFOtYIW4kdxGOLRSe0\r\ntUHQYHewi8z+rjrVK2oo8BAJ17U+/ied5jqlEK2f3+n2KcbZEPLiWInq2mnM\r\nxr/WlljqNrUAL/ZsV8BKffgDh2qpZf65EWkL6XpPxEQcpsSN4ywZJzcyulSC\r\nmmSVL23EBz9TApEu07TpYQS0zUbqQ50omfPWiZaFaFxAcr/uHlVtT3HaR8Is\r\n/0qoD1zCtBWPr+cAywI/8gzdeZhop08GcbVnG24R1W8JRzGSa1BKcQWwdVsP\r\nBjp+XsZFxPrCAVNiOJxES3BWctktpizZjmM=\r\n=Lgqw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBeHoyB94aT80hBh1Ry8UKv0cUhCyE7Ax+T97x1dWCFBAiEAivx+ivrudqWQmmu/XHJabv9I6S6gWe5TOVbbSco+Mcc="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"4.20.1":{"name":"browserslist","version":"4.20.1","dependencies":{"caniuse-lite":"^1.0.30001317","electron-to-chromium":"^1.4.84","escalade":"^3.1.1","node-releases":"^2.0.2","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-NkbK9ojxpVgEB9BaIZhrtuk16OnAcztHn6D64hxkSvIeTuXGSovZMR+gXJlh9mzjuLtif2Nl9TTKuTDWa+ax3g==","shasum":"01ad36fdf01a129dc7fb4528d9cc784bea8cd9d5","tarball":"http://localhost:4260/browserslist/browserslist-4.20.1.tgz","fileCount":11,"unpackedSize":68498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMNe7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr4ow//VbZvQMQMBcXrYV4ICJCpTYjE1EaiOdEmpns9a4Q7+txC7I7i\r\n3SAhVpdNL2Nbnihnz8/PWBB89aZ9adCySjM3nJD3OZY4i6DprP65WQkK1cKM\r\ntDeYLsD+MMzgGCDp0ZBEk2hhBhh80Oay9j6LtP2mloWM1kSp1zjulFJqAdc8\r\nrc+PqtauaGEZXD5d3d+NfLSJMdi3yPEhQtKK+xFwu5XqODyR+mXlp7twXCbR\r\nRqtQvQBSghkXqxkbuLsZnPN3McxMMOT4ztqzhOzVyNHvx8BSUtzoBQDuwFRA\r\nmmdHYHbeYKfhvFojB381g5uft7uW1z9s4gW0Fd6X0ZT4YEqsk7qc5K03QnKS\r\nFSdlBGsXj9YrIZzaEgCMIuaQ6K9H7JRQclRmI7raBcL5SiAgB3TTZ9Z0xX6N\r\nTYzw47NOw1GKdt3UPqaPUz2/HWDVZ86TvJQ/dstyMkwJT5qGk+S9+aesYu5I\r\nl9rw3EFveppGrDhc36C7CEHm5Ev6dkQv0Hz/PyRo5iqpCxZitYx75Iw8SGQU\r\nXzSfSIhsUQrSx2Y1R6ji9HDxpYmkDxhwjH9Qdb7Ap6WEkzGv3MtKPYF0biua\r\ndqj4iRctSUOfAb58aDzxG1JqzNg1XfMBAzWQcKNK0aL149QT8aDVQ5An0z6I\r\nL/mMOBu8M7srgIIvxmlcnazccJ7psq0YE4o=\r\n=AI41\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBUt8UlQDqWgXhR49AulY8ii58NU6O7egcDYbghQ92/kAiA2Pj2Tn3q4tvaexve4Pdwd2uvvZ+kZ5K+CGWycOZnwTA=="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist/"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.20.2":{"name":"browserslist","version":"4.20.2","dependencies":{"caniuse-lite":"^1.0.30001317","electron-to-chromium":"^1.4.84","escalade":"^3.1.1","node-releases":"^2.0.2","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==","shasum":"567b41508757ecd904dab4d1c646c612cd3d4f88","tarball":"http://localhost:4260/browserslist/browserslist-4.20.2.tgz","fileCount":11,"unpackedSize":68497,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMNk7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmokAw/9Hf8FRFDQ37g/58vJI10OHLfWGQ0KrbyScylylPNfqr+dBYKh\r\noHCbW4hBgno+tMq2dYFr75u/7lJrSEg6kz6rY/fIZwjbxfNqRSQKI/Sj7hSL\r\naoBV8V1cNvRKVINr9YzVT/OmzsFMDl9ThY8hubg7/GCHFGo66k8pegboIGTu\r\ne6JdQjQmVfRxC83gH3QirkwEsKP0/yCHrIShGhzerVlxqOtztYjH0SaF8uxc\r\nfTcmCJ4UaekzGqpHhC2pCXs4BM7P7UyaFEGj19QnStaxMSxavkzxEd/AUEiz\r\nAcMUJX4H2CUSmk3dQFmp1FJreHve1gY3g9JOk/HkDFN5cTl7t/2HIQnm/tRV\r\nUeED1KTApi6a1ajTBi3utWTjncTzG9gHmu0wvLRHmhKuWfMWXV6JQ0jbn1Et\r\nkUbAIB7oynqMlnvAotwSs6bC871w8yjlig+xHCDxoqLGNS3Ql0y7pWz2RcxT\r\nVSS5IpluIjof6R+oqLQepmAEZxUiTrBNa/DxvamX50NV+IzyHnsWmzi6mN62\r\nKfgIDYE4vsKkpYtp23xtjCC3dgfjlfTEAakEKiZuHzdocrdXOZ5yulOHTASN\r\n5+mn0mNvu/gNUcJv4Wc6I2UynsPo4lJL0y5e0d/ka2/f2HNh0OCK2tlGKsYd\r\nYShMwdwzXHIIj8NQoLSWc2QUUqQlp3GQirA=\r\n=mBzm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDHv4C6Lgrr2SFoHRxVbKupPCegqezcQZPHrsKu8YYLeAiEA48c1CifHhkDbuHGparCUGiAmB6S4MXKoj2Q5ayYf1sE="}]},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.20.3":{"name":"browserslist","version":"4.20.3","dependencies":{"caniuse-lite":"^1.0.30001332","electron-to-chromium":"^1.4.118","escalade":"^3.1.1","node-releases":"^2.0.3","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==","shasum":"eb7572f49ec430e054f56d52ff0ebe9be915f8bf","tarball":"http://localhost:4260/browserslist/browserslist-4.20.3.tgz","fileCount":11,"unpackedSize":68520,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG985yPk+SvcScZ5bcBrPTEFBQbT8zYvJaNU5gFsOVF4AiEA6BxSG1tKRrNJH7g3xyFGpyUfcDUzVkmNaJVOBms9UUk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiZXWUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmruYxAAm7/MqtQ+hsRl/IArQVTAXOa0jZpCoANtZntBh1rYd8FgS+Zp\r\nSMButPvpV20Z9Wv9HbsabasjnvuORtCcSlK49uzRh8aWpVTqc30xjk+yViHr\r\n1zOGAxsnqmGA1wRtPcDFKHDQbaUGl+lckQ1/1ETXN/iwEWjlkewuIwI5gsxB\r\ndoQbswR83ONBaRUkYTL7RRGzYtog/HiA1xG9I/2HEBA6K5tBhkgLh7i8Qd7b\r\nLbnlxf3pDFv5v2TrHa5SqYHMvM9ZojM/4oie1uTpH9RwGSb/QyoLgTT5sbhX\r\nw30imEimINqMQViyoMGyzbh3EfCVj0KAS5iobbTaEQXUTyhwgJToRBwn0Mo2\r\nchBYxmcrhy1VeSyGwLVNPUEO/vvnKUpQ2c9F8FkbUmInhHLfobtfSCKbRbEW\r\nAaEpkpGeHkDCdrUZKhh1727LoAK4/liTpd/aSeaAU8NSOz7Hj6hBUMYV72fK\r\ncKxIHgWZaJ9MDeV+4B8Hm0t7K6jA5QwR96e4RU5DIAeuIn3HlvLiI5I0Fgqs\r\nZG/vBqt32lt8m/36P8vzpcdagx4rNsKZJd++9FX3rHnHQLAxkaxy4XYisvEl\r\nRzxn0FVzC99BjTaWQ5QdfGtjzriIUXZoVoz6bxujf7jgOkvVIrTfULe2TCln\r\nXtyz6DjVqgqFU4YzrXzJPGsftUEoBQufNzg=\r\n=vP1j\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.20.4":{"name":"browserslist","version":"4.20.4","dependencies":{"caniuse-lite":"^1.0.30001349","electron-to-chromium":"^1.4.147","escalade":"^3.1.1","node-releases":"^2.0.5","picocolors":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==","shasum":"98096c9042af689ee1e0271333dbc564b8ce4477","tarball":"http://localhost:4260/browserslist/browserslist-4.20.4.tgz","fileCount":11,"unpackedSize":68520,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCB2ZTRaFrpyKZo4lInXwAyZBR86mbDdlWMCaOZCE2mzwIgHafX4K0D+NCnR5bPmuheexgYPNcwVdBA2THM1U/RxKQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJinuZ3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoYIw//TUZnv1BRVcE25KETG1OyeIw381Uk+Bs7+ORpterQIU3/tu1E\r\n+s8TityAknrQzLX+FR3LDBOF04PpEypDIOYTGPuZzovl24h+Vpjol+fbbJXe\r\n5YhyO2OB4rB+yEz4qwJwjNDwWQjPztR1qwnzCQ31okARKB00M3LTPKycrg9D\r\nnx4OUJXWkoMiwhK6Mva2V4EMP4ACNrO//70XDCKjxUOBZxWoXFrOTdlRJZ+w\r\n6IBI0h5WG2toEGioeeFUWr3l0ayi6L/7vTHZPMux7Wn+8oXt+le3M0L2xSgh\r\nROtfKYB+CfO6QyCJe4WZdnDjDkQwzELYs+jxC41v4L2oNNuPC25lZRiepDqL\r\nhPUt6f7qobxJkmvswO69whq/VZ9vMyMbkCFMRuOj1O2WnGcrkxS4JP+TlJOd\r\ny/m6P8IDCfa8Gkjv+gg6xUOR6lvs01sOGBfeZMk37HDYTdppMdZ4p39mi8j6\r\n8Xhxs9traIarBXGncCAJ6MIpJoEv2DjjA4Z3T571StM5bABRXWCK3uvrMSZU\r\nvg7s9Wc4U1bxG13QowRdKpgzGiAgKnFjPDYoGTZWyqjrWPY6VCqWYY0L4hFM\r\nAqZ9bFmgAK4791jUcKVFJfdLjw5I7YfFG4GqTYZkZxigYvrR53N6A8HtnX3O\r\n2NRmteQZ2dswrgHtpIQTd9z3eXDrLQaufo4=\r\n=6bAk\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.0":{"name":"browserslist","version":"4.21.0","dependencies":{"caniuse-lite":"^1.0.30001358","electron-to-chromium":"^1.4.164","node-releases":"^2.0.5","update-browserslist-db":"^1.0.0"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==","shasum":"7ab19572361a140ecd1e023e2c1ed95edda0cefe","tarball":"http://localhost:4260/browserslist/browserslist-4.21.0.tgz","fileCount":11,"unpackedSize":60570,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDuhE0A9FLP9otAS5Md8aL8/+fmPSDlThP9owst8LTOPQIhAJubGk+eDq8K/3vioplHJmLq2hKSSVggZl580hnwk4bM"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisfRYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqi2g/+MRAk678SHLIKu+ONjtkBuwMNXpZhxuI7xFGgx5LhkmHSaNU8\r\ngM4NV86etqq67lMYWesFWIoTRqekZwd5OELRvNcuHsKrD67Ow1pBk9puwhlD\r\nRuIEa1TfEVUZpgsqMfHtlC6y86A+mrPZjgnMOU9eWkVfwwxg+8Dq2Gw1wKC+\r\nT2Ce961Q3RBGaiMzkHsnTZMMDvGCKzmCSQKMdlQnO0SgvX5Gt+abQ+UIlths\r\nIJHM5eve5zdOE8vYFl5QITTSw+uxizhKJSekKfJWDZXULiD2dV1wN4/yPYrN\r\nF3NIUWRyvIjtal5LX0Hs5reJ909Wi9pW9xmdg20aqzEwlzmy2E1AGlbiF6bt\r\nnC5MBel96NSJo8i+m+hHBOdsuRnVvBdZyis3v/nUqpJBgCbJWE/HHgOr2gI2\r\nCJITGLRaq9/F0onnTket1uQUxG+a9WjqgAEfm2mhwFEGi/JaS51u2skyZVCZ\r\n0geQsfjhnYq027towozInFO+Hs8f3U3iYaNWhrUkY+KBSktyYws2kZMhnA1r\r\nv1quqoADlENMeYL/uOQLZyUV1uRea62PbFmYKQKDVOIGsZo/IwXUXjrkBF3T\r\ny3mwn5/20H390E0mpefXit4Z5fC9PLAmTiz8BYXmyvnYfBm+vezxq7ARmO9S\r\nPyGljUmy9AQ0Cjveuq+93GPLFdxENQAIDUA=\r\n=vFCv\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.1":{"name":"browserslist","version":"4.21.1","dependencies":{"caniuse-lite":"^1.0.30001359","electron-to-chromium":"^1.4.172","node-releases":"^2.0.5","update-browserslist-db":"^1.0.4"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==","shasum":"c9b9b0a54c7607e8dc3e01a0d311727188011a00","tarball":"http://localhost:4260/browserslist/browserslist-4.21.1.tgz","fileCount":11,"unpackedSize":60567,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGoki2HvRDsu0W38MUBQ/xcHq2DY7OwImcZC4agOqEjfAiBR9tfKnhtAXmqiaefR3MMLEdEdy4htvJRhI/Bo+B7i0w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiuyxXACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmogVA//VjkZ4SE87sDWtVmumfmNwx+wGocljrNF8m0InoVKsG2Ndq9D\r\nRKm6I7p/LL7DovzfN8d80igBjPA3UVaGzabZHqF6IGnF/jOy4FYROll3AXyV\r\nzQm3vTeZghsta9hq0uk3WZ7Ywfw8WQYoktdlA6LYK4XEEyYRlXx82nJtVY00\r\nM+CFR7Yo3qoERRGE1QggqZMO8NKHhBHMvNrzDSJCh5g6rHruJLxZU+jlvG1x\r\n+OlMhe855Gto28aohVJnPJRhnAnujUccMCL1p3dhaGm2Y8D1xwMmVfDcpeCY\r\nMw+wHRVNl82OlClqQ6jwRpYqBA+FJBi3aSS8hBdhUpWwScbDlAzuQv0MqQSq\r\nah3XfF0ZaWhEEGyqQbrsM3IrNT9MI8MW62VEs2zEKSZfawUZIhRr/3brkhyi\r\ng7wab1kufSfttgn6UQAhEun2RjgQOMeNZ+bkColbdMYYZ5wNfx+kuJZzGNw9\r\neChefmTC4ROk01857aTvxTNvpysNBtPXR00/K8z/ILUqVvI4bsqM2LFPtcPl\r\nCrYqkf1AfdmfQma8MQbUdgqdqfNiL6lcE8uh1RevpBgvxG8JNzGepSifcQPf\r\nAUqqHrn/IP1Spnjwa92PTdeUofP4dnkzEbgxAi9rpDcvMsKmWq7WxUoT6vbc\r\nFS4YiLWBhNOyO42d3cRC7/RSHwGFxC48Fdk=\r\n=o0nm\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.2":{"name":"browserslist","version":"4.21.2","dependencies":{"caniuse-lite":"^1.0.30001366","electron-to-chromium":"^1.4.188","node-releases":"^2.0.6","update-browserslist-db":"^1.0.4"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==","shasum":"59a400757465535954946a400b841ed37e2b4ecf","tarball":"http://localhost:4260/browserslist/browserslist-4.21.2.tgz","fileCount":11,"unpackedSize":60582,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCorI2pT+00K2Ej/NJJSO1E6mQQoCUNB6Ufa+5l/jzQwgIhAJCX+WiY1yNbu7LB454hOTLEgV+77p6Vax6DhncpUQMK"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJizvjdACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrPOA/+J2YXmNXxJNR31wwp4c78F4Vhz8RZjQAyhp3sY6bUf4pbCcrT\r\nTgIj3olzAYRYzQ9nG2tS/2Cd7224SpYD8OTm+U8c+qEoXoqWiewKwH4h1Tzq\r\n2GYPmA37BxKg68jR0hptLDmud4S3FPTw1KHSDaK/S/LOji0QiOJzESiRBu/z\r\njUoQbdSVDkXETTShAffD+T8LCfG7hqHOLqEy8F/scSlP6vNqOk9dxZZJoPW3\r\nOrl/2MYwSU371DPFaEn2xlmMFWQz56dwYSZgURoAUHavToF4zUnUMcYb8qdt\r\ny8LPBcGC8pfiqkE/djPMIa2/IjgiCBRGZBCGSukhZjzX2eB9MKcZON/W6rBr\r\n8WN5ZIo7aR+PnjDeDkDXvrqKl0+CEwVSSPaA46/v9d94kuSSCOY53aIwPA5Z\r\nT8WHS9L5zvxYupwaZm9uUdMnU2Y4XnqzGnLhvMVzIKb7XXAfMxQJFRdFM8a2\r\nVikCMeZvv/YTSXm6XTFmS+OPWpg6UDVberJzShO2nkrbZYs36Qxoeg7XnPRU\r\ndCoK9+2irEB8dazcBZWp7BuO294bl5YNv9NhM0QGoMaErFU9tV0jE14aRdlQ\r\nVP9oH1J8d/4ppq6fYQS+5d1A0bp+uB2W75qqw6Gq6TZPJIfkzaOPYXLhV/1H\r\nHC6WDx46rOavXWLgTEkQoghtV3IoSAlvNY8=\r\n=Tm5x\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.3":{"name":"browserslist","version":"4.21.3","dependencies":{"caniuse-lite":"^1.0.30001370","electron-to-chromium":"^1.4.202","node-releases":"^2.0.6","update-browserslist-db":"^1.0.5"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==","shasum":"5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a","tarball":"http://localhost:4260/browserslist/browserslist-4.21.3.tgz","fileCount":11,"unpackedSize":60841,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDDfaAaarz0AmnYzcb2WYgk9h+Tg6ozWli1beUwLoz7PAiEAlft9lsCAjc3Z8WokxkkDMWN5buEYwIyHYNYDAcAcxak="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi4QPjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoOKhAAiTPcEarWfoLwjlCVDdSwvv/CJeohSoOcPTG8onLdrKQuYytC\r\nZr//YCdXz0czooD66MsACGYxSTs+J4vothE0mWMwuNvasLjatG34QpNZSZiu\r\nPrIhlQffXfak4bIjrY0Y8RlW+FSrOllTgFPkl7d5MDptpHIL7wMRWm4+Mb4d\r\nIsZHHpgLkwRqibZNnHqCzizNsmWsS5K1hsFOpgq5vgC0FEQuAuBdQP1n0VrQ\r\nJgz701j2WoEpn264v34Df3xc801d1Ix32diC4Ck/Q1KQn8+sxAsd7vb5mrUQ\r\ngamLAN+IA9jErDAo7Eq/Xf3i/iq2jUmFB5CLN/oVVNmfpCQ5hiLMHPbI2SsP\r\n3LIOznEAG3L2ELGHrIujd+eAeRiHr928l9OuyjOFez/Qy+PgvtXeOlAJI9WN\r\nUNOev3I7hv/idKsPrQF70WYcUDWs0l+vCbZ6ASK6J8mo+yPCtG3/deq4SBJd\r\nqCKlFNvDxb4T3Zv0pkPmN8rtbpyCSR3w5cRJCuUqfiFPv+RjofJTq2YrC2y9\r\nNyh5kksQ/CZu1LthKcA6JlIJmx1AJg/MF6vBg3jbL34Yv2auBDBACKj/eGjT\r\ntH1eTYaZaH7DPsK4P4k9/ZtHDs6M1l9Vvg1PXTfabEmhZt7LW/TXI5RBDHa0\r\n5d6LOfXNmlsTRVLkFiJyi0FHr7xmpIAY5KA=\r\n=HeGm\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.4":{"name":"browserslist","version":"4.21.4","dependencies":{"caniuse-lite":"^1.0.30001400","electron-to-chromium":"^1.4.251","node-releases":"^2.0.6","update-browserslist-db":"^1.0.9"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==","shasum":"e7496bbc67b9e39dd0f98565feccdcb0d4ff6987","tarball":"http://localhost:4260/browserslist/browserslist-4.21.4.tgz","fileCount":11,"unpackedSize":61230,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLlgeqRt90GIl8ntoEd6jEzc3ng/jbX+LbOr1nyqD1UwIhAOPLrVWBRGOkIWsjbH2eJB2xIr/5EeFXCbIBAwJKek9n"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjIwC2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrSjg/7Bn1wNnm1PYQMrjeHHczDb6lgwkxkqwiev7IFOEfASlCLjLgR\r\nvegvBTlOljHguOIbhtCfANu1xVAXARKrAq/bjaHjp9MbR8UMiZe/EfHkixYQ\r\nHLsxcqMs8PvURernPsebHXoL8BoRsb0Pdft9a2hRRc36pgAerGsU59Gfm2Xv\r\nV5iMb+AZ0J74a5T/HI51S+d+aONdcBtZDU27c/ovO+bNVNFJSY+VrcxA2jxS\r\nEReH2fU6zRoTIdvRduR86HQacyEfi6hd7vTN5p5fwo4IjirurWMi8BpzPLzg\r\nxEAuj01o8aUAPgDSpSJ0YAvMS4FEebZrdmNOzNUjIwmCcUhaYE5iXD672D7b\r\nAhgSinXCSzEiOUi9fjNcAtiSgPoPP27HAkYgv4T8XyhvMAJZJ/RhLNg6jh+e\r\nlPDhGtBIVI7zu6HooItiIcu40WN/XudQSRKlO8Q6YuzsGM9+KOYKc4V9he3i\r\nVAQmgfXYdYQo20O7wfyTpW8wgiE8miY97ES1Mwr9D78bnxh+pinBSXDwH/cy\r\ne4lkxvtJ2PJ43GT5hDhl9KeujvZMLSUWFQ4Yl9nMrsveESoC7SW6xoMjz6JK\r\n2pAYu1A8wm/dbkcY/pA0vvKGlb5hCiLtbvvurphmEj5uq1fDTe0/61voryki\r\nnEDRaeA5whqRG/dN7Jyve5dw26517abtrKM=\r\n=+ewH\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]},"4.21.5":{"name":"browserslist","version":"4.21.5","dependencies":{"caniuse-lite":"^1.0.30001449","electron-to-chromium":"^1.4.284","node-releases":"^2.0.8","update-browserslist-db":"^1.0.10"},"bin":{"browserslist":"cli.js"},"dist":{"integrity":"sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==","shasum":"75c5dae60063ee641f977e00edd3cfb2fb7af6a7","tarball":"http://localhost:4260/browserslist/browserslist-4.21.5.tgz","fileCount":11,"unpackedSize":61255,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0XHSVAgL/NPe/i20/v1wK0wtg070T8GIZS18EFOvTLQIgRoQX/or0wH43PUIMYs+x1HJLIjcQQmuA2Zd1JKaZSCI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj17HQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpQlg/+IfJutijt+olNrnUqAH5LOGvmMH/c8uXsdFv62GnDXlTdVT2b\r\nIhTtt61aokbgwFhoOdIVQKXqw3k/uGy4pVzT5O4CigvZivbQYPZpYQXYnlxS\r\n/Yf9yL/kH9ekvVjv4XO9fYPPq5JA5UsTJzx1EuxNM1cnYCBl+Ltmu1+PAYJI\r\nW1JacUm+rx4KENjPuYCPzhpq+MqdXcurG/RxxTcIWwNejZhC3JhqVOpBPgF7\r\nZowQ3ooPIFUFStyOoZKUqnC428pLyr4IkBeME2H6jySew/9PL9ooyTsc7zxP\r\nan+iY1OC/gP4DqTtwK6x51pCHkM++sXYr+F645b1JYcAN6cIqkKQh/JgCUnN\r\nX9AifsOMhTgDnp1Ek7kg8tsZI6PO9ZL9gtEmX7ZQLmj8fD79LMj0klwgYc4g\r\n8xnuSjR4GYtt86vLdQTtvGlaLKg3Nqisorh5HhLO6G1ArwA6bS+mdxo+TRpb\r\nfz8DvKncHXQht4oPZ2l/pGv0go20dJwN3MDH+T0r6VDdYAkUQeB14rZeAy6x\r\njc6xkzFQEJ5IXqx+IduopetEClA9O705zKy7gZmr3xR7sxHJhRzfsLeIxj29\r\ny0uu6pJ7QopCVG5Hg8KpKeP1DE0jhPD7masNhtkdSSvao+ELrXATX4Dk5Wga\r\np98gzaP8iuPyJt1O0rPV/vbhBFmgKE8sY3w=\r\n=fvYE\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/browserslist"}]}},"modified":"2023-03-07T23:22:35.944Z"} +{ + "name": "browserslist", + "dist-tags": { + "latest": "4.21.5" + }, + "versions": { + "4.21.5": { + "name": "browserslist", + "version": "4.21.5", + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "dist": { + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "shasum": "75c5dae60063ee641f977e00edd3cfb2fb7af6a7", + "tarball": "http://localhost:4260/browserslist/browserslist-4.21.5.tgz", + "fileCount": 11, + "unpackedSize": 61255 + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ] + } + }, + "modified": "2023-03-07T23:22:35.944Z" +} diff --git a/tests/registry/npm/buildcheck/registry.json b/tests/registry/npm/buildcheck/registry.json index 2e06e164f0..161928b8cf 100644 --- a/tests/registry/npm/buildcheck/registry.json +++ b/tests/registry/npm/buildcheck/registry.json @@ -1 +1,71 @@ -{"_id":"buildcheck","_rev":"5-7b0ee241b8f09893b108dbdd2f2002e1","name":"buildcheck","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.1":{"name":"buildcheck","version":"0.0.1","author":{"name":"Brian White","email":"mscdex@mscdex.net"},"description":"Build environment checking (a la autoconf) for node.js","main":"./lib/index.js","engines":{"node":">=10.0.0"},"devDependencies":{"@mscdex/eslint-config":"^1.1.0","eslint":"^7.0.0"},"scripts":{"lint":"eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib","lint:fix":"npm run lint -- --fix"},"keywords":["build","autoconf","addons","compiler","environment"],"licenses":[{"type":"MIT","url":"http://github.com/mscdex/buildcheck/raw/master/LICENSE"}],"repository":{"type":"git","url":"git+ssh://git@github.com/mscdex/buildcheck.git"},"_resolved":"","_integrity":"","_from":"https://github.com/mscdex/buildcheck/tarball/v0.0.1","bugs":{"url":"https://github.com/mscdex/buildcheck/issues"},"homepage":"https://github.com/mscdex/buildcheck#readme","_id":"buildcheck@0.0.1","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-c8urpjm+vnjxzqedWfC/bdF0f0B1QMmHujcJVYwlQLYpWZpv058Lm4x3Krwoiyb7zjjzHlUtgoTOwEQum2WdAw==","shasum":"64af6f1a138c9b8532ca6407750c9aae7a09d95a","tarball":"http://localhost:4260/buildcheck/buildcheck-0.0.1.tgz","fileCount":11,"unpackedSize":9839,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhPtIoCRA9TVsSAnZWagAAW8IP/3Dd5gfvFTC2+YdbI9Oc\nGOInVGDgDbuP7Q5RaA/oR19s41t6u3+OOX6F7xDedwT+3K2juVQchKiVlPjs\nSg6UZnACrqcnTAevczJ8S2yrcaZdw4mGqtd4BJNvI4AeG6zycE/Jl9K6PxJG\nnz3V6QG833sqe5o8z9yCvDm9Ai3mD8GpTYOQnBb8IZ+Yb0qG1px7sP9/GPnJ\ny33zFUttGc7UUsI6qXoAA4/KAIw2s07SMM2CHNTdwMme6/n6ZFDYxipsd6fa\nNeT04EkIZXF+OwsZOn++succUCJFlia6GrCNijGn6XHFbEkyBF9DYobnhnfL\n2eUdrPwETJFxxyOHxSbtw69ar1X122T9Pdt0vP82zy+Oik8+L+7Wr119sgK2\nXUyEN5PrqkzhMSZ6RipXuy4gXnAoVS0I3yZR1nRrUqE66wYQmwPOKOI/lbnn\nmhykS2QvPzP9+UF3+QYFT/cyjYxsATx6MlG1qfhPSjwvZsg++t7vY6Yxqeys\nqvWEJ4i+RwqOijQyMpSnOy9S7ttTGJ+wYjAJdsfP4EPt4GYDkodJYfm3lYU5\npNAKX9Hdo/dNla+QllDN64XDcfh1seFt2NXMuTO/qhi5PgKAxzyK8419RneR\ngxNl8KUh2zGnaRemr23t1hxykyavTzjRhmXbkoPCCeWGN0wpVeDEockwUaE0\nS07k\r\n=J2Pf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC0WXpnJUwwRToQZ42g5NsdLb3npiuRtw54PSJtPk9eGAiB9TyufJvlxEIqx10ATr8pafVyAICy7IjUP7tChPW6yxw=="}]},"_npmUser":{"name":"mscdex","email":"mscdex@mscdex.net"},"directories":{},"maintainers":[{"name":"mscdex","email":"mscdex@mscdex.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/buildcheck_0.0.1_1631506984609_0.7975404344347068"},"_hasShrinkwrap":false},"0.0.2":{"name":"buildcheck","version":"0.0.2","author":{"name":"Brian White","email":"mscdex@mscdex.net"},"description":"Build environment checking (a la autoconf) for node.js","main":"./lib/index.js","engines":{"node":">=10.0.0"},"devDependencies":{"@mscdex/eslint-config":"^1.1.0","eslint":"^7.0.0"},"scripts":{"lint":"eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib","lint:fix":"npm run lint -- --fix"},"keywords":["build","autoconf","addons","compiler","environment"],"licenses":[{"type":"MIT","url":"http://github.com/mscdex/buildcheck/raw/master/LICENSE"}],"repository":{"type":"git","url":"git+ssh://git@github.com/mscdex/buildcheck.git"},"_resolved":"","_integrity":"","_from":"https://github.com/mscdex/buildcheck/tarball/v0.0.2","bugs":{"url":"https://github.com/mscdex/buildcheck/issues"},"homepage":"https://github.com/mscdex/buildcheck#readme","_id":"buildcheck@0.0.2","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-V8jsKuMjGyUR6vDqIEKEUwzA44RYLdShqvwQt1bimI3RfLYDfvvbD+kjL+ZlaVH7epmxQHx2HflkfmH+5ipxIA==","shasum":"db0ae2d4067b1c91618fc6b470eae235ff17cc96","tarball":"http://localhost:4260/buildcheck/buildcheck-0.0.2.tgz","fileCount":14,"unpackedSize":42188,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCd77KwnvB1TBuyq8AQ/EBRlJad4N8SoKJasRepm8MOPwIhAJtriPyIZ5h5RAq43d9ArmZOU9Ii7K0a5CL7wJwiCY4B"}]},"_npmUser":{"name":"mscdex","email":"mscdex@mscdex.net"},"directories":{},"maintainers":[{"name":"mscdex","email":"mscdex@mscdex.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/buildcheck_0.0.2_1634871484977_0.3103629551650462"},"_hasShrinkwrap":false},"0.0.3":{"name":"buildcheck","version":"0.0.3","author":{"name":"Brian White","email":"mscdex@mscdex.net"},"description":"Build environment checking (a la autoconf) for node.js","main":"./lib/index.js","engines":{"node":">=10.0.0"},"devDependencies":{"@mscdex/eslint-config":"^1.1.0","eslint":"^7.0.0"},"scripts":{"lint":"eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib","lint:fix":"npm run lint -- --fix"},"keywords":["build","autoconf","addons","compiler","environment"],"licenses":[{"type":"MIT","url":"http://github.com/mscdex/buildcheck/raw/master/LICENSE"}],"repository":{"type":"git","url":"git+ssh://git@github.com/mscdex/buildcheck.git"},"_resolved":"","_integrity":"","_from":"https://github.com/mscdex/buildcheck/tarball/v0.0.3","bugs":{"url":"https://github.com/mscdex/buildcheck/issues"},"homepage":"https://github.com/mscdex/buildcheck#readme","_id":"buildcheck@0.0.3","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==","shasum":"70451897a95d80f7807e68fc412eb2e7e35ff4d5","tarball":"http://localhost:4260/buildcheck/buildcheck-0.0.3.tgz","fileCount":14,"unpackedSize":42580,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2lO2CRA9TVsSAnZWagAAkvwP/3lP+9kQb3DC9grgfRou\nWC8iEZxIbG1ggMTKfiYtOOjQ5tTcBQ5lWX4Wjv4KEHu+8R/AoRC2WJMIqwPj\nX3r8K0i22ptWTZdQPlQKXDPQG/yfRrB1mBz8KEJBW1374RBwe0g4q5MAGJSK\nrUVp9kmAJtugq5hvH0JtCb++9uxnvgZzUaO/geT1oPyb4rF9SEhv7AzSLTTg\nVu3vq49qxghoYCkeiOMsoOOrzu0Eix+nXuWFcuqIuVXaA7IQBTgSqnJwUV6d\nwOgQ8M78sJS2v94X0dTWiYH9Ni/LDgnAK62JvL6GhSaE5r98KgprMmp0ebC2\nfjFRllHBckqV8IJLyQiThKlsBDqomkNI1wRelFQFspGprPLLjbwQxm2s6+6H\n6irH8Z7uup6rivQMzQm3xLt5gokRIhwO6CIXQDEDL1k1WlgGic1rlpscsnat\nd/XkddHZvVu7lAW0uuufy37BhxHFTT3JQDxxHg2gRXzpRlEC3aHl5h7gSNKp\nVyqxgWBxnpwHTNv//WHzEIxGTfDXY03GcjpTx2ofqlvzSp4BcbibSgj/GRf6\nm78a9DAKOqZAqJ2gbRwROuTwmeqq9u3r1+V3PwiSPNWz5U5f6EGxQbtr/OoO\nfNkFz+7UCIKEJmDe3gPI0s/bMcAP/sZpdsfLLtBY6aCuKFzg52t/r8sTzvNN\nzW7f\r\n=jW+A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCPtBDI6CdG76mWIhWcyPBzraHJ76pNO2QZnCGDoV+WUQIgYE6E8+IvlPlYV7dil5eQi6IKFs5+gDY1cyv+Db7MUI8="}]},"_npmUser":{"name":"mscdex","email":"mscdex@mscdex.net"},"directories":{},"maintainers":[{"name":"mscdex","email":"mscdex@mscdex.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/buildcheck_0.0.3_1634956644889_0.278232070219929"},"_hasShrinkwrap":false},"0.0.4":{"name":"buildcheck","version":"0.0.4","author":{"name":"Brian White","email":"mscdex@mscdex.net"},"description":"Build environment checking (a la autoconf) for node.js","main":"./lib/index.js","engines":{"node":">=10.0.0"},"devDependencies":{"@mscdex/eslint-config":"^1.1.0","eslint":"^7.0.0"},"scripts":{"lint":"eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib","lint:fix":"npm run lint -- --fix"},"keywords":["build","autoconf","addons","compiler","environment"],"licenses":[{"type":"MIT","url":"http://github.com/mscdex/buildcheck/raw/master/LICENSE"}],"repository":{"type":"git","url":"git+ssh://git@github.com/mscdex/buildcheck.git"},"_resolved":"","_integrity":"","_from":"https://github.com/mscdex/buildcheck/tarball/v0.0.4","bugs":{"url":"https://github.com/mscdex/buildcheck/issues"},"homepage":"https://github.com/mscdex/buildcheck#readme","_id":"buildcheck@0.0.4","_nodeVersion":"10.22.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-3lROzwIR07xIL4Dan3Bj2uJ0x3XQOwRxQ3kivEyTJRevxJLR9erAWgIgmXnjTpC1eL5jPtAhmWyyPqvZEzchaA==","shasum":"01b78c9e595629a4982956eb6cfd98359afb9d76","tarball":"http://localhost:4260/buildcheck/buildcheck-0.0.4.tgz","fileCount":14,"unpackedSize":42908,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiPoZLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrVzw//W6kOVTaMk1b85jdnF2TaMAh3jlpiq1XasL46GmYNLg9r4+kz\r\ne9yLJsp1tddv833EICpuwMweZBQXYdkHR2ixtsRwzFl1joBS2a5lWZn/9wae\r\nzuaOr7zs1Bsud+G7nSob5cdwRbJErfLMP3UXUi096/6B9n53CqGyjs0kxwvK\r\n3mEHFIfCapT7759CqfQrlFBwkju6L6r/BbCawCh9BEat3p42FwQmepvmn3zZ\r\nSNaeotDXTNrawhZDOqYxGVEpVJltPFUBCUWgszYQBd+U1w8kOTd7wXLNfMbQ\r\n2NuEcwc5ZAxEpOPxxchwrRK/oWfKQTiOnjA3EIe1QRpla4U3fVwJHk3at7eU\r\nhU+uiSx+FoCuzZAQNdPrvjyz8l1lACurM2DwvboYHc1lS0OtK4iSwgsOardl\r\npWyheaRiLWe9KuyOUCR+867ps1MLG9Ot8uLYW+Lo7gwOhvMrhsHXyBzZraLC\r\n2ZLZqaU5ULcHRNzA2W6FKgExspmDwvm56vm5K3zirz1u9PKFsx6MoQ5rBD7r\r\nikrDUg+csdoS5Fo+4NSQkWwNZgYDJS2muCIrtNSYmtSIpOolAAQlsnlI/c6z\r\n1bpPBeYwKmbVqbnV3YPbE0slMJ3f9QJC3/7N+KPLYR1NZkGWPm+KX34Wu8EG\r\nROGCdU1iPDNTjXZstVVpJpsbL3Ai4TfccEs=\r\n=LupJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcutYhEnWt+W5kZZ1zE0ti3e5Diac3/o8eZMZyFsWp0gIhAOnyDV76BFbk2eoU+jkhm/deZSfidvoOcUv4ZnMz3u+t"}]},"_npmUser":{"name":"mscdex","email":"mscdex@mscdex.net"},"directories":{},"maintainers":[{"name":"mscdex","email":"mscdex@mscdex.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/buildcheck_0.0.4_1648264778986_0.7520032376978061"},"_hasShrinkwrap":false}},"time":{"created":"2021-09-13T04:23:04.609Z","0.0.1":"2021-09-13T04:23:04.751Z","modified":"2022-04-12T04:42:15.633Z","0.0.2":"2021-10-22T02:58:05.145Z","0.0.3":"2021-10-23T02:37:25.041Z","0.0.4":"2022-03-26T03:19:39.150Z"},"maintainers":[{"name":"mscdex","email":"mscdex@mscdex.net"}],"description":"Build environment checking (a la autoconf) for node.js","homepage":"https://github.com/mscdex/buildcheck#readme","keywords":["build","autoconf","addons","compiler","environment"],"repository":{"type":"git","url":"git+ssh://git@github.com/mscdex/buildcheck.git"},"author":{"name":"Brian White","email":"mscdex@mscdex.net"},"bugs":{"url":"https://github.com/mscdex/buildcheck/issues"},"readme":"# Description\n\nBuild environment checking for [node.js](http://nodejs.org/).\n\nThis allows for autoconf-like functionality for node addons/build scripts.\n\n**Note:** Obsolete and/or exotic build environments or platforms not supported\nby node.js are not supported.\n\n## Requirements\n\n* [node.js](http://nodejs.org/) -- v10.0.0 or newer\n* Supported compilers:\n * gcc\n * clang\n * MSVC 2013+ and Windows SDK 8.1+\n\n## Installation\n\n npm install buildcheck\n\n## Examples\n\n### Check if a C function exists\n\n```js\n'use strict';\n\nconst { BuildEnvironment } = require('buildcheck');\n\nconst buildEnv = new BuildEnvironment();\n\nconsole.log(buildEnv.checkFunction('c', 'preadv2'));\n```\n\n### Check if a C header is usable\n\n```js\n'use strict';\n\nconst { BuildEnvironment } = require('buildcheck');\n\nconst buildEnv = new BuildEnvironment();\n\nconsole.log(buildEnv.checkHeader('c', 'linux/io_uring.h'));\n```\n\n### Try to compile some C code\n\n```js\n'use strict';\n\nconst { BuildEnvironment } = require('buildcheck');\n\nconst buildEnv = new BuildEnvironment();\n\n// Should be a successful compile\nconsole.log(buildEnv.tryCompile('c', 'int main() { return 0; }'));\n\n// Should be a failed compile\nconsole.log(buildEnv.tryCompile('c', 'int main() { return z; }'));\n```\n\n## API\n\n### Exports\n\n* `BuildEnvironment` - The main class for dealing with a build environment.\n\n### BuildEnvironment\n\n#### Methods\n\n* **(constructor)**([< _object_ >config]) - Creates and returns a new BuildEnvironment instance. `config` may contain:\n\n * **compilerC** - _string_ - C compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CC` or `'cc'`\n\n * **compilerCXX** - _string_ - C++ compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CXX` or `'c++'`\n\n * **msvs_version** - _mixed_ - A string or number containing the year of the Visual Studio compiler to use. *Note: this is for Windows only.* **Default:** newest version installed\n\n* **checkDeclared**(< _string_ >lang, < _string_ >symbolName[, < _object_ >options]) - _boolean_ - Checks if a symbol `symbolName` is declared where `lang` is either `'c'` or `'c++'`. Returns `true` if symbol exists, `false` otherwise. `options` may contain:\n\n * **headers** - _array_ - A list of headers to try when checking if the symbol is declared. `checkFunction()` will always first try without a library. If not supplied, a default list of common (platform-specific) headers will be used.\n\n * **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking if the symbol is declared. `checkDeclared()` will always first try without a library.\n\n* **checkFunction**(< _string_ >lang, < _string_ >functionName[, < _object_ >options]) - _boolean_ - Checks if a function `functionName` exists and is linkable where `lang` is either `'c'` or `'c++'`. Returns `true` if function exists, `false` otherwise. `options` may contain:\n\n * **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking for this function. `checkFunction()` will always first try without a library.\n\n* **checkFeature**(< _string_ >featureName) - _mixed_ - Executes a special test for a \"feature\" and returns the result. Supported values for `featureName`:\n\n * `'strerror_r'` - Returns an object containing:\n\n * `declared` - _boolean_ - Whether `strerror_r()` is declared\n\n * `returnsCharPtr` - _boolean_ - If `strerror_r()` is declared, whether it returns `char*` (a GNU extension) or not.\n\n* **checkHeader**(< _string_ >lang, < _string_ >headerName) - _boolean_ - Checks if the header `headerName` exists and is usable where `lang` is either `'c'` or `'c++'`. Returns `true` if the header exists and is usable, `false` otherwise.\n\n* **defines**([< _string_ >lang[, < _boolean_ >rendered]]) - _array_ - Returns a list of features, functions, headers, and symbols known to be defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned. If `rendered` is `true` (defaults to `false`), autoconf-style defines (e.g. \"HAVE_FOO=1\") will be returned instead. Defines coming from features utilize base strings/names from autoconf for better compatibility.\n\n* **libs**([< _string_ >lang]) - _array_ - Returns a list of (`'-l'`-prefixed) libraries known to be required for features and functions defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned.\n\n* **tryCompile**(< _string_ >lang, < _string_ >code[, < _array_ >compilerParams]) - _mixed_ - Attempts to compile `code` where `lang` is either `'c'` or `'c++'`. `compilerParams` is an optional array of compiler/linker flags to include. Returns `true` on successful compilation, or an _Error_ instance with an `output` property containing the compiler error output.\n","readmeFilename":"README.md"} \ No newline at end of file +{ + "name": "buildcheck", + "dist-tags": { + "latest": "0.0.3" + }, + "versions": { + "0.0.3": { + "name": "buildcheck", + "version": "0.0.3", + "author": { + "name": "Brian White", + "email": "mscdex@mscdex.net" + }, + "description": "Build environment checking (a la autoconf) for node.js", + "main": "./lib/index.js", + "engines": { + "node": ">=10.0.0" + }, + "devDependencies": { + "@mscdex/eslint-config": "^1.1.0", + "eslint": "^7.0.0" + }, + "scripts": { + "lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib", + "lint:fix": "npm run lint -- --fix" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/mscdex/buildcheck/raw/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mscdex/buildcheck.git" + }, + "_resolved": "", + "_integrity": "", + "_from": "https://github.com/mscdex/buildcheck/tarball/v0.0.3", + "bugs": { + "url": "https://github.com/mscdex/buildcheck/issues" + }, + "_id": "buildcheck@0.0.3", + "_nodeVersion": "10.22.1", + "_npmVersion": "6.14.6", + "dist": { + "integrity": "sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==", + "shasum": "70451897a95d80f7807e68fc412eb2e7e35ff4d5", + "tarball": "http://localhost:4260/buildcheck/buildcheck-0.0.3.tgz", + "fileCount": 14, + "unpackedSize": 42580 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "description": "Build environment checking (a la autoconf) for node.js", + "homepage": "https://github.com/mscdex/buildcheck#readme", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mscdex/buildcheck.git" + }, + "author": { + "name": "Brian White", + "email": "mscdex@mscdex.net" + }, + "bugs": { + "url": "https://github.com/mscdex/buildcheck/issues" + }, + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/cacache/registry.json b/tests/registry/npm/cacache/registry.json index 65bdc1a699..6837725524 100644 --- a/tests/registry/npm/cacache/registry.json +++ b/tests/registry/npm/cacache/registry.json @@ -1 +1,109 @@ -{"_id":"cacache","_rev":"153-82d556e7418943f0c921c7b8108840ea","name":"cacache","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","dist-tags":{"legacy":"12.0.4","latest":"18.0.3"},"versions":{"1.0.0":{"name":"cacache","version":"1.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@1.0.0","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"dist":{"shasum":"91c256942eaaf0f013683c1462d30f16a450c408","tarball":"http://localhost:4260/cacache/cacache-1.0.0.tgz","integrity":"sha512-TOTTgXgW1w2ZxVKMYggQWwH2VqROCc0p+HaTFltc4TY9gaSSHYMcupoYikGVBV2AvFhACdZFsfLTqMURScro9w==","signatures":[{"sig":"MEYCIQDLENHba52P2IO7t7xZ0qswvVNerdjA2H9N71RW86zbzgIhALez+LhAlqSmGdXRDGJXzmqJ3pZd2ghEnApFbKYJpuuF","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","_shasum":"91c256942eaaf0f013683c1462d30f16a450c408","gitHead":"2d834abbcc4c60ad3364d9721c9bb2ff793aafe9","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"_npmVersion":"4.0.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"6.0.0","dependencies":{"mv":"^2.1.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","pumpify":"^1.3.5","through2":"^2.0.1","randomstring":"^1.1.5","fs-write-stream-atomic":"^1.0.8"},"devDependencies":{"tap":"^8.0.1","standard":"^8.5.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-1.0.0.tgz_1479463297949_0.2984021082520485","host":"packages-18-east.internal.npmjs.com"}},"2.0.0":{"name":"cacache","version":"2.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@2.0.0","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"dist":{"shasum":"d05c1db1398b1ba77f6ab18c950098995d4bc8a7","tarball":"http://localhost:4260/cacache/cacache-2.0.0.tgz","integrity":"sha512-SoahgLDVkxNN7yaQmEynkHASRY0KGE9AfxqCmSpvDdgxCvGqdv9Ml2BC5PzC+YnET2H0o8Erw/iwaQq/bXkwQA==","signatures":[{"sig":"MEYCIQCED6EA+P6NrHOq6sCqROEwfxex3BZGwI0bwj5lrGhlPQIhAOZlihq423Yb4FZ2kS9FvfHYDRsjS8e/0auqj3TAlhmg","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"d05c1db1398b1ba77f6ab18c950098995d4bc8a7","gitHead":"0fa8f9764a137d50ec7e6574c0bf44219f21b570","scripts":{"test":"nyc -- tap test/*.js","pretest":"standard","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"_npmVersion":"4.0.3","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.0.0","dependencies":{"mv":"^2.1.1","from2":"^2.3.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","tar-fs":"^1.14.0","dezalgo":"^1.0.3","pumpify":"^1.3.5","fs-extra":"^1.0.0","inflight":"^1.0.6","lockfile":"^1.0.2","through2":"^2.0.1","graceful-fs":"^4.1.10","randomstring":"^1.1.5"},"devDependencies":{"nyc":"^9.0.1","tap":"^8.0.1","tacks":"^1.2.2","standard":"^8.5.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-2.0.0.tgz_1479646030946_0.24932323582470417","host":"packages-18-east.internal.npmjs.com"}},"3.0.0":{"name":"cacache","version":"3.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@3.0.0","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"eb3d5aec86b698c336cfc2233a67687241541761","tarball":"http://localhost:4260/cacache/cacache-3.0.0.tgz","integrity":"sha512-SmYhXmSBAYS4csrWWixmbLufePk40kGG4/HRrT+Ef9b7xp1KD8K+2chrQp20KPSYg2SAtWtUiZxwX8P838GX9A==","signatures":[{"sig":"MEUCIQDv8ogCmPLWy/cGf6S8gJ76Pu1tmYuwJ+zVi6goy5i67AIgdpi8ZTpFXQZjOfEY8yAXOTQ20HothqYVr7el4uTy1AQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"eb3d5aec86b698c336cfc2233a67687241541761","gitHead":"d97f56e2e9e4d5e26bb7c30345ddaedee4e92b0b","scripts":{"test":"nyc -- tap test/*.js","pretest":"standard lib test *.js","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.0.3","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.2.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","randomstring":"^1.1.5"},"devDependencies":{"nyc":"^10.0.0","tap":"^8.0.1","tacks":"^1.2.2","standard":"^8.6.0","require-inject":"^1.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-3.0.0.tgz_1480797089574_0.8002452596556395","host":"packages-18-east.internal.npmjs.com"}},"3.0.1":{"name":"cacache","version":"3.0.1","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@3.0.1","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"f2bbc3ea4603da1888c9577a288dbad3aa649cbb","tarball":"http://localhost:4260/cacache/cacache-3.0.1.tgz","integrity":"sha512-Kg7W/5pjbz8xbr8BJOolHvwIFgrG1//3xVDHn/skcWCixljnyoIDWZzqr/3eyIlVAcU35MSP2f3I1MAvK7g9Ww==","signatures":[{"sig":"MEUCIQDEmnyUSAaBUo6Ox/tHTUfjxB9I2UNJDLDhQBav42JY8wIgQFBxdTeQ8IPmGSDcAgjy3lLiinbXqrBj3H75eTM7oeE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"f2bbc3ea4603da1888c9577a288dbad3aa649cbb","gitHead":"ad9d97270fee0dfd9e036f07c190c33eb8c9b110","scripts":{"test":"nyc -- tap test/*.js","pretest":"standard lib test *.js","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.0.5","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.2.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","randomstring":"^1.1.5"},"devDependencies":{"nyc":"^10.0.0","tap":"^8.0.1","tacks":"^1.2.2","standard":"^8.6.0","require-inject":"^1.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-3.0.1.tgz_1480835211471_0.4059302939567715","host":"packages-12-west.internal.npmjs.com"}},"4.0.0":{"name":"cacache","version":"4.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@4.0.0","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"acfe5f4dfb2265900ba51783d67a30868b652029","tarball":"http://localhost:4260/cacache/cacache-4.0.0.tgz","integrity":"sha512-eQwQmmyzmz9Dqjrb+jI8QjPGY8LzZc/PVjpR/r4uApGRNp33Cuz7QJ1jXBkUN5zezXmFUlSAoBXHJevaGs51Bw==","signatures":[{"sig":"MEUCIB1WnlDH2sBC2qtfSQaLad23ev7MIxrFYaNiQf50AhhjAiEAneUBKtZfNwheVtDr+xIQQ56Qi7oeB5OxH55G8JM400U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"acfe5f4dfb2265900ba51783d67a30868b652029","gitHead":"bfcb818546929601c21aacdf53907e8578dea0d6","scripts":{"test":"nyc -- tap test/*.js","pretest":"standard lib test *.js","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.4.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","randomstring":"^1.1.5"},"devDependencies":{"nyc":"^10.0.0","tap":"^9.0.3","tacks":"^1.2.2","standard":"^8.6.0","require-inject":"^1.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-4.0.0.tgz_1485563494205_0.06228936044499278","host":"packages-18-east.internal.npmjs.com"}},"5.0.0":{"name":"cacache","version":"5.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@5.0.0","maintainers":[{"name":"zkat","email":"kat@sykosomatic.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"66eda54c377fe1afc485a6d76226c98e17ab7e73","tarball":"http://localhost:4260/cacache/cacache-5.0.0.tgz","integrity":"sha512-tJxPN4jQY2vCGjnyBRvZ0APFi4Yq0fAzZopDoE4LpKUUwd7alUWWo6Jj5V8XU5JlTG41Dnh8wOqGfukyfxXj5A==","signatures":[{"sig":"MEQCIHIYBN/4KwWmpDzjmE8KpQ4lJlOtSoDb4CW+M2vIcpWMAiB03U1Cm3buvHTgfuTDXsnE277duL9vrRLMf4pi6VGTSw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"66eda54c377fe1afc485a6d76226c98e17ab7e73","gitHead":"9c2e370d1f9ec6bc7918d249f56f96ab493c3b8f","scripts":{"test":"nyc -- tap test/*.js","pretest":"standard lib test *.js","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.4.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","randomstring":"^1.1.5"},"devDependencies":{"nyc":"^10.0.0","tap":"^9.0.3","tacks":"^1.2.2","standard":"^8.6.0","require-inject":"^1.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-5.0.0.tgz_1486087189180_0.456214397912845","host":"packages-12-west.internal.npmjs.com"}},"5.0.1":{"name":"cacache","version":"5.0.1","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@5.0.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"253cb8cb059205110c5efe1b974dce6f31c0ddf1","tarball":"http://localhost:4260/cacache/cacache-5.0.1.tgz","integrity":"sha512-Kn79LaXmGNU6IiAk3jzae6bnR4tLXpKeCMAeuYr4oFlq5NdqPyogyM1oG5Mwq0HW4XGjYW1frE20lpeH9a2AKA==","signatures":[{"sig":"MEYCIQD+mDEZfYJPJfnr5vUCN58iQChpBkmZ4ouR00Z/9kwD0AIhAJAb66JXDBOAiYMyXbGq0NF8K7N9C7Ibz9P9zvD1Pmll","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"253cb8cb059205110c5efe1b974dce6f31c0ddf1","gitHead":"8fefee50d0f97171a3a40f5aaef264d45c4a7d2a","scripts":{"test":"nyc -- tap -j8 test/*.js","pretest":"standard lib test *.js","preversion":"npm t","postversion":"npm publish && git push --follow-tags"},"_npmUser":{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.5.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.0.2","glob":"^7.1.1","tacks":"^1.2.2","standard":"^8.6.0","require-inject":"^1.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-5.0.1.tgz_1487404076153_0.38444646121934056","host":"packages-18-east.internal.npmjs.com"}},"5.0.2":{"name":"cacache","version":"5.0.2","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@5.0.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"5c1659e49fd83a3fd56010e5cdaad23f563302b5","tarball":"http://localhost:4260/cacache/cacache-5.0.2.tgz","integrity":"sha512-MXq5lP7eJc6rL27zG8QtheiU+39ZVuYj91MyJK0Q249z5hpEuG2KI4JlQrt2rSxFT/THALTs/V47lKjm3YazAQ==","signatures":[{"sig":"MEQCIEddyhSBjIr2MA2A17QEyR6RqQ7nn+PNxTBptALaKW5HAiB08KhT4ceoHwVPohAvhnkOOfwbxezYtI9Yh7G1CMnTUg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"5c1659e49fd83a3fd56010e5cdaad23f563302b5","gitHead":"30030ed0eca42668e3e0ac628ec9ca4b752b5093","scripts":{"test":"nyc -- tap -j8 test/*.js","pretest":"standard lib test *.js","preversion":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postversion":"npm publish && git push --follow-tags","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.3.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.4.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.0.2","glob":"^7.1.1","tacks":"^1.2.2","standard":"^8.6.0","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/cacache-5.0.2.tgz_1487563944795_0.8896687692031264","host":"packages-18-east.internal.npmjs.com"}},"5.0.3":{"name":"cacache","version":"5.0.3","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@5.0.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"f8c651e6613865dda88ddfd87bc514d9cd34a65f","tarball":"http://localhost:4260/cacache/cacache-5.0.3.tgz","integrity":"sha512-CcAr/dHgpKeidPvYSHOiM0lxH0jSMMAWtQYaGLwd7/L7ejYhYY1dLcBGpM3Mr82KXfPVqomg4xUezpsuNrni1A==","signatures":[{"sig":"MEUCIQCzqw9RKvcZBdCr844+608knlIyBypWnhostlkFvOFKbwIgLirYazbp9YwB6Uf6mh9pTjLCURW0QSSkhhj3y7Zivo0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"f8c651e6613865dda88ddfd87bc514d9cd34a65f","gitHead":"bd1b71f323658dbed44b1bb8be68cff2a81421ae","scripts":{"test":"nyc -- tap -j8 test/*.js","pretest":"standard lib test *.js","preversion":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postversion":"npm publish && git push --follow-tags","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.3.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.4.0","dependencies":{"once":"^1.4.0","slide":"^1.1.6","split":"^1.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.5.4","dezalgo":"^1.0.3","inflight":"^1.0.6","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.0.2","glob":"^7.1.1","tacks":"^1.2.2","standard":"^8.6.0","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/cacache-5.0.3.tgz_1487580656016_0.7145839324221015","host":"packages-12-west.internal.npmjs.com"}},"6.0.0":{"name":"cacache","version":"6.0.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"994ab2c3ec9c2233c1e55ea69dd54ba34539432d","tarball":"http://localhost:4260/cacache/cacache-6.0.0.tgz","integrity":"sha512-Y9kWJCIW7izSd5C+lTqimyd3wm0s8ru0oZzqafJ0R2LMppBDVU1vc9BHjhQTGnrRyRezcve9qkeeeVX2X/xm0A==","signatures":[{"sig":"MEUCIQDQsqf3s7DofbkMFLcuWplOmqzyWlA5s3Jwtc0pHeWzXwIgKXtr5YRLcwKrPD6UhleL1yLowMrNbgZ/7ftNEPZNX5s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"994ab2c3ec9c2233c1e55ea69dd54ba34539432d","gitHead":"1aef3e527e3a1e73b9e2faee482939e9ce958006","scripts":{"test":"nyc -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.1.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.7.1","dependencies":{"once":"^1.4.0","slide":"^1.1.6","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"1","content":"1"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","glob":"^7.1.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.0","benchmark":"^2.1.3","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.0.0.tgz_1488698454431_0.8984206928871572","host":"packages-18-east.internal.npmjs.com"}},"6.0.1":{"name":"cacache","version":"6.0.1","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.0.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"cae27481c35ae7264d6bbccad7e520876302b77d","tarball":"http://localhost:4260/cacache/cacache-6.0.1.tgz","integrity":"sha512-iPapvnle8cYMVJebsN/dwSH0H1/wqjLHDDwweL1Nbmf6j8kQo8sUTPY4aAD3HOeed1HxrHy19ntIRM+oA/lFcA==","signatures":[{"sig":"MEUCIQDyWBG+bPAZgI72c07v0NMo1mNqetErPn6DQlCWI7wzNgIgO9cb2ZCUcBoZPnJBcQsqdSRRNUzyy2nNs0+5htWZBTA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"cae27481c35ae7264d6bbccad7e520876302b77d","gitHead":"b2014641ecff503b8bf8506de5bcb7a5af49b42b","scripts":{"test":"nyc -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.1.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.7.1","dependencies":{"once":"^1.4.0","slide":"^1.1.6","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"1","content":"1"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","glob":"^7.1.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.0","benchmark":"^2.1.3","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.0.1.tgz_1488703539820_0.8354658233001828","host":"packages-12-west.internal.npmjs.com"}},"6.0.2":{"name":"cacache","version":"6.0.2","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.0.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"abda997519d86232b2bf11a901e01caf03d66a93","tarball":"http://localhost:4260/cacache/cacache-6.0.2.tgz","integrity":"sha512-RytdpNOuBhupGU+TVRIadtcxibrJUA+ZGUQX6fk4xs2eqyOZv+FCsvn6MsyzPbCF1/+03E3mHv4c116iM8V7iQ==","signatures":[{"sig":"MEYCIQDqeU7LtNIKhLXoZF4B2Z6aljlRl80+iyEqjngKZ4SGTQIhAKRjVHS1OcGZpevJPY6N0UH4Y24p91BCXwabDV9VAYDY","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"abda997519d86232b2bf11a901e01caf03d66a93","gitHead":"00a64756a4adf445b5b870a20d417195ba037267","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.4.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.7.1","dependencies":{"once":"^1.4.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","lockfile":"^1.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"2","content":"2"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","glob":"^7.1.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.0","benchmark":"^2.1.3","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.0.2.tgz_1489191123557_0.18352518323808908","host":"packages-12-west.internal.npmjs.com"}},"6.1.0":{"name":"cacache","version":"6.1.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.1.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"7c86652a413e797680f1ef3e759b3c8f4a5fc599","tarball":"http://localhost:4260/cacache/cacache-6.1.0.tgz","integrity":"sha512-j6atzTmvts0lgcwt/uhGkjDJN9CoaJw7ltbRkn7gd74r2oHMp5DFKgxoHIA6D0Qb10AlJuZ3vLq2nQ4ZOji+ZQ==","signatures":[{"sig":"MEUCIQD13QV9OBryMe9uBqQnnW+vOuMqF13zhnJul8z+duFbAwIgYehaBw4NJp18SVjjFFiKyxEVkeDYQIGW2R6Ie1bj4sM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"7c86652a413e797680f1ef3e759b3c8f4a5fc599","gitHead":"cac5f9cb23e08093eccb4573370f6ea87bd54e84","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.4.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.7.1","dependencies":{"once":"^1.4.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"2","content":"2"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","glob":"^7.1.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.1","benchmark":"^2.1.3","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.1.0.tgz_1489297959380_0.3542158380150795","host":"packages-18-east.internal.npmjs.com"}},"6.1.1":{"name":"cacache","version":"6.1.1","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.1.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"ad4405780016a33b608bf55a760aa18af0ada309","tarball":"http://localhost:4260/cacache/cacache-6.1.1.tgz","integrity":"sha512-QXp5IxZFVmItqN+0cjwpzArnd2//TFQIRNx9mClIlukjRK8BH69I1FCZLHAb/aMXO/fBDLP85PS0G+jWd2rAyQ==","signatures":[{"sig":"MEYCIQDddOufYSO8rff2W5EUIy5fbfdGFXenl21lETZZwB5W1QIhAIeheyC4qTJTlOf+v2/AXilJLFkOdw1SN5nOCnyHp8ij","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"ad4405780016a33b608bf55a760aa18af0ada309","gitHead":"2318a8f9b79b6efa15c19285046a2be1469dfa77","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"3.10.3","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"6.3.1","dependencies":{"glob":"^7.1.1","once":"^1.4.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"2","content":"2"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.1","benchmark":"^2.1.3","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.1.1.tgz_1489400152392_0.13603505678474903","host":"packages-18-east.internal.npmjs.com"}},"6.1.2":{"name":"cacache","version":"6.1.2","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.1.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"fba9b76f1e2a0fe6073000d9034108ca28d7b577","tarball":"http://localhost:4260/cacache/cacache-6.1.2.tgz","integrity":"sha512-o+WYtDKOnIkk+WBVOiEhZvl0/D+Z9TmX/+GU10wU5bHnre4x0LkKynhW+I/hqA0L9iXfII8o9hORHjTArFuapA==","signatures":[{"sig":"MEUCIQDRCftsZdDpDXycqW4ak/gBeU3wAVF+o32weHU+naPrUgIgG3G3nBCI5GoxVJlvdhh5wSE/wLU4BfG2PwYnxyFIenU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"fba9b76f1e2a0fe6073000d9034108ca28d7b577","gitHead":"956687682e7690680059daaf455d621ce2ceb126","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"3.10.3","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"6.3.1","dependencies":{"glob":"^7.1.1","once":"^1.4.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","dezalgo":"^1.0.3","bluebird":"^3.4.7","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"2","content":"2"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.1","benchmark":"^2.1.3","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.1.2.tgz_1489400728495_0.06708851829171181","host":"packages-18-east.internal.npmjs.com"}},"6.2.0":{"name":"cacache","version":"6.2.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.2.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"ed3001398eacbb3750241cc57375202bb81ae5d1","tarball":"http://localhost:4260/cacache/cacache-6.2.0.tgz","integrity":"sha512-c8pv07FrC3Lj4AG5GYCOZJPKBwM5nt9LWTXabNhQU75bpAEeAlvGtiWM7GIiutKZzAYKdwCxJpAmvPOs2zOwHg==","signatures":[{"sig":"MEUCIHHlHCCljFN75blNl7FoVEhxxZfpXSkrV/qoi6XJvTiaAiEA6PUJo5KOMhHzVwUuCCGB4qOptY0S79ik7m7gKZ5fNrg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"ed3001398eacbb3750241cc57375202bb81ae5d1","gitHead":"00f773eada2f3af160bf08b3b0df0afa6c0eb20f","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.1.2","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"7.7.1","dependencies":{"glob":"^7.1.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","graceful-fs":"^4.1.10","mississippi":"^1.2.0","@npmcorp/move":"^1.0.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1"},"cache-version":{"index":"3","content":"2"},"devDependencies":{"nyc":"^10.0.0","tap":"^10.3.0","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.1","benchmark":"^2.1.3","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.2.0.tgz_1489542166404_0.23625470255501568","host":"packages-12-west.internal.npmjs.com"}},"6.3.0":{"name":"cacache","version":"6.3.0","keywords":["cache","content-addressable cache","file store"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@6.3.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"ecc428901b79aabbd0b0492bca62b88cda0d4773","tarball":"http://localhost:4260/cacache/cacache-6.3.0.tgz","integrity":"sha512-cVwaVKxhVlpzDTLE5CHfIMf/Wvi+CJ0co1t9ADJpU6NyXhk/KRoZRFHcTyWDF4dC6yUn1SgM1Y+WbrW/n6Z00g==","signatures":[{"sig":"MEUCIQDdrdinGC95KISwJPE726Se6gKQL22nz+ZdRpIqsaR3NAIgacG4igBZHxoHA8GAlkhFacUed68fA6im5q8W804Enqg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"ecc428901b79aabbd0b0492bca62b88cda0d4773","gitHead":"82a977ead70a17f60926d54c38cd140ec79a6f30","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.5.0","description":"General content-addressable cache system that maintains a filesystem registry of file data.","directories":{},"_nodeVersion":"4.8.1","dependencies":{"glob":"^7.1.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","checksum-stream":"^1.0.2","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"3","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-6.3.0.tgz_1491029412988_0.4537326372228563","host":"packages-18-east.internal.npmjs.com"}},"7.0.0":{"name":"cacache","version":"7.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"7e59224ff4f1ebafe5f42ff68f472d179a5c204c","tarball":"http://localhost:4260/cacache/cacache-7.0.0.tgz","integrity":"sha512-KvWY0A2KKX97wwKvEeXwi1FH0O24RExZmtTnCc8LDLiJXC84E5EjkR7uXTVnXLYMWwE1+bMnRVixbILEdwMfLg==","signatures":[{"sig":"MEUCIQDCZR9+jIkLqBrZEuixNtNmFJzG+6JCork8VhTqq+vhmwIgWaqJWmEBXTqAQzhqC30PKuIOlSSGZDpwCSObgwWw5iA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"7e59224ff4f1ebafe5f42ff68f472d179a5c204c","gitHead":"99769f69bf8900c8039815ade6b6c44c792a28c7","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.8.0","dependencies":{"glob":"^7.1.1","ssri":"^3.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.0.tgz_1491207188752_0.21650386229157448","host":"packages-18-east.internal.npmjs.com"}},"7.0.1":{"name":"cacache","version":"7.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"7f66ca4f725b121d8037067e1979b0019727b4f4","tarball":"http://localhost:4260/cacache/cacache-7.0.1.tgz","integrity":"sha512-GiYXKHelbNXdxEgwXR9HLSFSvhwGZgtmynA+onvxFUSDC0dDH7jfoCODKa7DYc0nl225+f5pQlJH24jTgi52UA==","signatures":[{"sig":"MEUCIBnyz0F2aQ9tE7JghMDqOTpqYafeBL9hMIGrbGPSMKhMAiEAmyeMO0/CM+/iUlLO2ubrIWXc3SwuNNBbLy2QUyDDnoQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"7f66ca4f725b121d8037067e1979b0019727b4f4","gitHead":"5e7341ce0e6e718cf3b9dd27cccfa794c4246b18","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.8.0","dependencies":{"glob":"^7.1.1","ssri":"^3.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.1.tgz_1491207359331_0.7451633384916931","host":"packages-12-west.internal.npmjs.com"}},"7.0.2":{"name":"cacache","version":"7.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"5b7f7155675b0559ad98a1961f9d0a4c1260532d","tarball":"http://localhost:4260/cacache/cacache-7.0.2.tgz","integrity":"sha512-Lc9qaBS9PQDEGSQM1f2jExrVG8ALIjXKKNCR8EBVUJ+C9HtG0/T26vktgCrIRqKK11V+77ED2pi/A0WFz/obUQ==","signatures":[{"sig":"MEQCIBrDnjfy453UvdGdeKPgNT5iHaVxjihfG+9zog9UZesGAiAdYee8gey12kEWKiG+bKAQ5V/6VaixXZtq2+qiIoezcg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"5b7f7155675b0559ad98a1961f9d0a4c1260532d","gitHead":"422a86dae8269ab3f56bc7e952280c34b58ddfb6","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.2.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.8.0","dependencies":{"glob":"^7.1.1","ssri":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.2.tgz_1491216099682_0.127382418140769","host":"packages-18-east.internal.npmjs.com"}},"7.0.3":{"name":"cacache","version":"7.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"62e876694cf2c094d319f257b83769ea752278ab","tarball":"http://localhost:4260/cacache/cacache-7.0.3.tgz","integrity":"sha512-LXz2O7ylBLq1yzJpn90qT9hDuq4bBH1rKCo6gGR93hGAcWIZgKiYRivVbNx0RPXu0DJc2YeXt8/6NpAdf5hMYA==","signatures":[{"sig":"MEYCIQD8j4ZmJ0wt9cR7O/KMSWh5+lLuf8rYj89VALmOhNQTeQIhAPwDip2+yjrIIBNO13HB4yi1cAzuLH4s6xxpo1HDa+ST","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"62e876694cf2c094d319f257b83769ea752278ab","gitHead":"b677f6def269b2a6968ca3e7c65261dcf1878e47","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.5.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.8.0","dependencies":{"glob":"^7.1.1","ssri":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.1","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^9.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.3.tgz_1491373492663_0.1923560865689069","host":"packages-18-east.internal.npmjs.com"}},"7.0.4":{"name":"cacache","version":"7.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.4","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"59eb6a4dca1aa3dc2a6450c097679afba37bc990","tarball":"http://localhost:4260/cacache/cacache-7.0.4.tgz","integrity":"sha512-zCT7FK/JgFoMr6sGKCULVbKYU/q1aFJVDvp8oI+t/5QgkUw4Hx8CSVYACM1tNShBkd5Avuv2GfKXq+1DO0+8bQ==","signatures":[{"sig":"MEYCIQCKXgfxDNZdoh/iAhoomqdtzxZqZ7ssUjhQB3oomGs56wIhANQUKjEOve76IlPCQZSSM5tOhzL79POrcmaQymcyd0yB","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"a6b344891adeecca6e2b02d9e5b9f3340e91de68","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.5.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"6.10.2","dependencies":{"glob":"^7.1.1","ssri":"^4.1.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.1","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.4.tgz_1492285095516_0.7461334373801947","host":"packages-18-east.internal.npmjs.com"}},"7.0.5":{"name":"cacache","version":"7.0.5","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.0.5","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"31b23a28b2b1e4083e60a42df9ddd2e5dbd3b4ce","tarball":"http://localhost:4260/cacache/cacache-7.0.5.tgz","integrity":"sha512-g5ObsVGIJiCMMvKgWXCeUuX+aUgT4RkzbelngjUjqtwaJDvM2CvzGcYUOziQ3fdwisGwFzW24+QqkWdzeIUWTg==","signatures":[{"sig":"MEQCIBwdGhNYM/0Ky8wrkyHSCKCbMFVN+RyND7aLqvmSJxinAiB9uSBnEOeOoTkC7IzVsLrV0lJO48ixErar70PuJOfeXg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"0be449e5deb99a54c3efcdd2054c52ecfe4834c6","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.0-beta.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"4","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.1","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.0.5.tgz_1492509873056_0.9271866513881832","host":"packages-12-west.internal.npmjs.com"}},"7.1.0":{"name":"cacache","version":"7.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@7.1.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"f73777163e437e4ec45e21a2be298edeb584e36f","tarball":"http://localhost:4260/cacache/cacache-7.1.0.tgz","integrity":"sha512-HkbOhxXGJ80pAkyJeKJZ0zTqniCUF1zVGHPDBoJhKMSeYk2GAD6ed4Iwf/Ql00+L4COwUfld3NLCkI31u064Iw==","signatures":[{"sig":"MEUCIEzlgUQIMOCqxcmUtt3pskeNYoKn/aw02TxFDaOQUpYCAiEAmQQRjgVgtsMZI6h3yKaFehWdVgg4J1+bvNUribnD+aI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"0a0c54336994409c4e86e56f2cc3f8cd32adc12a","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.0-beta.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-7.1.0.tgz_1492683249221_0.14916861057281494","host":"packages-12-west.internal.npmjs.com"}},"8.0.0":{"name":"cacache","version":"8.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@8.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"2c3899c16941aeb0e7378845df8aff03bb0eb81a","tarball":"http://localhost:4260/cacache/cacache-8.0.0.tgz","integrity":"sha512-EU2cZHCYkIfX05XinjeKTVx/WCnJuM6Tu7I7xDrDrG2+/FY8Y6qAnsbqgE3541OAzILM/kJMuBY1gTMbeX6teQ==","signatures":[{"sig":"MEQCIDE/hr3Az6iyPVM02DBH12yvHSXTf9r3wJRpEPIhRessAiBHf5Q+4prDbJPdl4uky/Qw1pADTf8wCK6mlM9GL7wWLA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"2c3899c16941aeb0e7378845df8aff03bb0eb81a","gitHead":"358443a2f0547664ba04cc533f0b2d8f944c20a2","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-8.0.0.tgz_1492892421119_0.964167490368709","host":"packages-12-west.internal.npmjs.com"}},"9.0.0":{"name":"cacache","version":"9.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"edcf620030b0fbf3708193f0718136eedb2170a4","tarball":"http://localhost:4260/cacache/cacache-9.0.0.tgz","integrity":"sha512-VkeahOGLrti/Dh1y+UEcudtK5WWynbAWOmIuMmJ5RdR9EoPyraSuBj0BzN7nEAgRw19NNy/X1QOvU3jGWvxhJw==","signatures":[{"sig":"MEQCIH2Y3x/DSibqxBwRYzr/ZW06ss+tfyULgqbkXIuxQvkIAiBpRWQalSLbh5cAnqrPwErP49gVKmq9zIiAgaYefhr7Lw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["*.js","lib"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"_shasum":"edcf620030b0fbf3708193f0718136eedb2170a4","gitHead":"c2d6b436c99f4cd4715af59547fd3eb528d537a6","scripts":{"test":"nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.0.0.tgz_1493340297200_0.2679894659668207","host":"packages-18-east.internal.npmjs.com"}},"9.1.0":{"name":"cacache","version":"9.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.1.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"7972de4fa9f2a81a4b737011a2cf1f0e0d7ab213","tarball":"http://localhost:4260/cacache/cacache-9.1.0.tgz","integrity":"sha512-pNQeGpcAptdM0JFJA3kQfKoMrg43vuQBgxdoqbPRNMcAjO1oXONAvN4T3RJsZsmgmvNY/bQmotne4nmsEyFn4g==","signatures":[{"sig":"MEYCIQC4vt2VqNQCqh1E/SbUS/TBffTdKcbN9h4NPVydHdrPeQIhAN0yLoRRXmmsF3H25ijUn02ypaZ7WJ3eAy4+OTJyvhW6","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"28a3efa033824d40d5db54ee4fba7370f1a7b003","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.1.0.tgz_1494746134130_0.6239770308602601","host":"packages-12-west.internal.npmjs.com"}},"9.2.0":{"name":"cacache","version":"9.2.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"5e14e78842ea7c8df0c35fc4b315452724c27b79","tarball":"http://localhost:4260/cacache/cacache-9.2.0.tgz","integrity":"sha512-6p5OrZdfA2f/JX2y2u70FsG40h8bib83wBVaFnKqDLaWeii4yvkR4jCC4P9tADyee3Y9sgYnWPvv0XCZMUfPBA==","signatures":[{"sig":"MEUCIQDKBGjZIzAnVDvXH01Ppv20TvZ5+QkAUEkgCRcjstebLQIgFfSOOtutzH4Cnd9wApcNG19pNOPsMdAZlHzkeXBfxfc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"8f6906ed49d5554a18eb712db15f5dc0ec8e2232","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.0.tgz_1494796168879_0.19379548192955554","host":"packages-12-west.internal.npmjs.com"}},"9.2.1":{"name":"cacache","version":"9.2.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"5baf6875a3ef3dca4fdf33efb9b0e3ac23a983a3","tarball":"http://localhost:4260/cacache/cacache-9.2.1.tgz","integrity":"sha512-wknnaRGoo1yzuXMdXXbT/+i/78PWdjZGyNC2LY9t73zARhV0DRrOrJI+eSebosIvtiDZXHK7DiAgl94gGWdtyA==","signatures":[{"sig":"MEYCIQCdUpFdfbj+LCgGRI7BBjccnCgHwI9qyODlRGa9WKrkUwIhAM3M0DoF5bt6PF6AYDI9aj9HxBtyjde66618acxY+jLo","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"b91d2479e75159983dbcd6101229ecbeb9468d97","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.1.tgz_1494802832163_0.25340488692745566","host":"packages-12-west.internal.npmjs.com"}},"9.2.2":{"name":"cacache","version":"9.2.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"cb67e5c3497d474f6b6d889a90ebfc969f2d83fa","tarball":"http://localhost:4260/cacache/cacache-9.2.2.tgz","integrity":"sha512-KchIh0VVk0zpYKtztqFQDYc2ZnQAqwOO3Z5bsuxYfTJuNGvUgEVEBlEVmb/Rf3t3CKgd/8U7x2RC+lgJe0kz2Q==","signatures":[{"sig":"MEUCID61eTMrCIcg8bcX/wmPZ9wBuPVEkDrb+fInhU3cUijKAiEAknlN7WcdFuo9mVtUVeQfWuilwwnDMV7pTvrfo/CmSiA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"950b19a4fba8c5eb0b117114bf7462a939b12cc6","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.2.tgz_1494805618593_0.29162677587009966","host":"packages-12-west.internal.npmjs.com"}},"9.2.3":{"name":"cacache","version":"9.2.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"22edd762e8f91a2d89dc9a2f6f7f28a6b11bf71e","tarball":"http://localhost:4260/cacache/cacache-9.2.3.tgz","integrity":"sha512-Xvz0paVT+igGRdGPDfMy2UgAFnbc77hp6/XruCiJQzcBtKzb+jkP1NG0kAHS8RKp3h560Fc09WnonXyT/oXMxA==","signatures":[{"sig":"MEUCIDoSlD4qJEqVRm7vqAIcD69x6/6DGyF4l5ENC263ORfuAiEAswScIKhnocfpVQ5W5k+CLXvtnlw4VmEIksgJVC3LviI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"1e469adcc80ba94b6afbb3ae50259a2876cc18f7","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.0-beta.61","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.1","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.2.0","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.0.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.3.tgz_1495618087947_0.260176362702623","host":"s3://npm-registry-packages"}},"9.2.4":{"name":"cacache","version":"9.2.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.4","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"f222f569e6d3e1415ad1ae66969c69ca0fc25955","tarball":"http://localhost:4260/cacache/cacache-9.2.4.tgz","integrity":"sha512-DkEucrb5TwM6yCLgDfyHWMH3QECt9g0pMGNtuGBrALo/B0FcQSnt8B+DyyuPFqOvSOwSPZgqYD4TK9IKJBUoKg==","signatures":[{"sig":"MEUCIQDuF5PtJeqAkDzn6Kq7rG11bmA1tDBPjTfexKASsVA/vAIgMbqQ4jzmvqI7ehZlw2QHo1LYPqOJEqQ1PiGPXwClMbA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"fc46a7b78e424c61f6a5a06e00c49795d14291b7","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.0-beta.61","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.2","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.4.7","lru-cache":"^4.0.2","graceful-fs":"^4.1.10","mississippi":"^1.2.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.0"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.3.2","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.4.tgz_1495618360254_0.6785227581858635","host":"s3://npm-registry-packages"}},"9.2.5":{"name":"cacache","version":"9.2.5","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.5","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"cb401d0e59858532062de1f104097cb40c71c3bf","tarball":"http://localhost:4260/cacache/cacache-9.2.5.tgz","integrity":"sha512-mURsTvkjbCSFRTdkuPhHUp9sbEHn3AVrvM4mveg/bhlKKYolfRm23TsFUVAssC9p622lwmh7pgpb+H5mSVpYcA==","signatures":[{"sig":"MEUCIQChMINu6zfqyYQ0uIAdM/mRTA/7Atl+7haRU+BtVHpKcwIgZY4Dlg5HIYmoiMoZGdX0ugU8tCFO8If7KTCbyPOn/eA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"babf105e227d07ec95c8fd8045ea750a8b1c8c3e","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"4.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.3","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.0.2","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.3.2","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.5.tgz_1495675401383_0.041375950910151005","host":"s3://npm-registry-packages"}},"9.2.6":{"name":"cacache","version":"9.2.6","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.6","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"ea5c7f2b6b514710a22a58a27f857fd972fdfa51","tarball":"http://localhost:4260/cacache/cacache-9.2.6.tgz","integrity":"sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==","signatures":[{"sig":"MEYCIQC4cVGXWnGqAqriagypS7UG3PnOPVOBbN36VmgOBVuMkwIhAKjqeNOwzM32T5888YUQLO2EQAXfrVwkFpKShAIjBrUj","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"5e04eb7ec441ce556d611c4edf141a481e107280","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.4","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.0.2","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^10.3.2","tap":"^10.3.2","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.0.1","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.6.tgz_1496209410635_0.7262062451336533","host":"s3://npm-registry-packages"}},"9.2.7":{"name":"cacache","version":"9.2.7","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.7","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"67d71835fed94f6989bde522cf2956df862e3ca5","tarball":"http://localhost:4260/cacache/cacache-9.2.7.tgz","integrity":"sha512-SWRnkRNV5h61SeTfPvVYotM2yqW5KXtG835CebVV7G5EYHQu+dgQbNkasSIcN7LWeoaViLpgaxVlt01TFpqOKw==","signatures":[{"sig":"MEUCIQC+xzNiiaw9pXFTNOpH2ZRDKwzfZNQgvp/GFLTzbbiGugIgc03cVGZawZFMMvSsEZienOyEiWO7Pk4e2ZistWri2Tg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"c4f2f6c95833024d758de1564655a6be4ea27dc8","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.4","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.0.2","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.0.2","tap":"^10.3.3","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.1.0","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.7.tgz_1496673430525_0.7083461554720998","host":"s3://npm-registry-packages"}},"9.2.8":{"name":"cacache","version":"9.2.8","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.8","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"2e38b51161a3904e3b9fb35c0869b751f7d0bcf4","tarball":"http://localhost:4260/cacache/cacache-9.2.8.tgz","integrity":"sha512-nA3gmaDPEsFWqI5eYAe35IfvW54yGJ3ns2wDopWf4iDA3fkhBNsdvnYp4NrL+L7ysMt0/isM84Mwi+b4l8/pMQ==","signatures":[{"sig":"MEYCIQDpbJOrvPmN9xcNinxdhgggtjnYPZL11bm+ev7L/mRa8wIhALmzcG84yVipNh4vnHP0/kEXo6CAQUD+4/qhWtXwvbu9","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"9fd57d24d89ae780389aa8d22e8d2c98f72897d9","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.2-canary.9","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.5","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.0.2","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.0.2","tap":"^10.3.3","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.0","safe-buffer":"^5.1.0","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.8.tgz_1496697511971_0.9950958741828799","host":"s3://npm-registry-packages"}},"9.2.9":{"name":"cacache","version":"9.2.9","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.2.9","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"f9d7ffe039851ec94c28290662afa4dd4bb9e8dd","tarball":"http://localhost:4260/cacache/cacache-9.2.9.tgz","integrity":"sha512-ghg1j5OyTJ6qsrqU++dN23QiTDxb5AZCFGsF3oB+v9v/gY+F4X8L/0gdQMEjd+8Ot3D29M2etX5PKozHRn2JQw==","signatures":[{"sig":"MEUCIQCw+exZ2c5OJV6fB8n9aAcKckTXf7G0He4NcAK7nXmtRQIgcEihR2a8QeZJz04Z1G3lFcxbqD4gSC3mGHzj7kTYOEw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"296f37667a7b3ab4144b52d08365cd4b76bd73b7","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kat@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.0.3","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"7.9.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.6","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.0.2","tap":"^10.3.4","chalk":"^1.1.3","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.0","weallbehave":"^1.2.0","require-inject":"^1.4.0","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.2.9.tgz_1497732123721_0.6806205452885479","host":"s3://npm-registry-packages"}},"9.3.0":{"name":"cacache","version":"9.3.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"CC0-1.0","_id":"cacache@9.3.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"9cd58f2dd0b8c8cacf685b7067b416d6d3cf9db1","tarball":"http://localhost:4260/cacache/cacache-9.3.0.tgz","integrity":"sha512-Vbi8J1XfC8v+FbQ6QkOtKXsHpPnB0i9uMeYFJoj40EbdOsEqWB3DPpNjfsnYBkqOPYA8UvrqH6FZPpBP0zdN7g==","signatures":[{"sig":"MEUCIQCbDLmMvoy2ecCubOpIf0ngPQ0H/dQOLIbtBNOue9bzhwIgVntgr5CAiXoyvpvxQLjBJ2fr6w2nJeNtZVOdkj8rGLM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"8c9ef3ea922c2590c0ac4abc0be21a6ace50f388","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.5.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"8.5.0","dependencies":{"glob":"^7.1.2","ssri":"^4.1.6","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.1.0","tap":"^10.7.0","chalk":"^2.0.1","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-9.3.0.tgz_1507418688161_0.054106614319607615","host":"s3://npm-registry-packages"}},"10.0.0":{"name":"cacache","version":"10.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@10.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"3bba88bf62b0773fd9a691605f60c9d3c595e853","tarball":"http://localhost:4260/cacache/cacache-10.0.0.tgz","integrity":"sha512-s9h6I9NY3KcBjfuS28K6XNmrv/HNFSzlpVD6eYMXugZg3Y8jjI1lUzTeUMa0oKByCDtHfsIy5Ec7KgWRnC5gtg==","signatures":[{"sig":"MEQCIBI6ZH8L+12aFng4fcUO4Dntso7pvAU8DCr99B7Mc1d/AiBdSy7kp7ZUehYakWVnlUoSH7JPG+Mpg69qr3Dlp6NUbQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"ae31cd670555b39336490eeccb51a8cef2927a8e","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.5.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"8.5.0","dependencies":{"glob":"^7.1.2","ssri":"^5.0.0","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.1.0","tap":"^10.7.0","chalk":"^2.0.1","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-10.0.0.tgz_1508783137726_0.09417407028377056","host":"s3://npm-registry-packages"}},"10.0.1":{"name":"cacache","version":"10.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@10.0.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"3e05f6e616117d9b54665b1b20c8aeb93ea5d36f","tarball":"http://localhost:4260/cacache/cacache-10.0.1.tgz","integrity":"sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==","signatures":[{"sig":"MEUCIFuWSdkd1KvL3q89iKrIVD1AUgZUVCd+LLeCyieuLEnRAiEAxQ3J4wj/cKmbRV3wKJ3FVi10B1jhzYZDRjAUsrmrt/U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"32dc59ad340ede670668485299b2dad8e4db0427","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.5.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"8.9.0","dependencies":{"glob":"^7.1.2","ssri":"^5.0.0","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.1.0","tap":"^10.7.0","chalk":"^2.0.1","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-10.0.1.tgz_1510785251234_0.04544048057869077","host":"s3://npm-registry-packages"}},"10.0.2":{"name":"cacache","version":"10.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@10.0.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"105a93a162bbedf3a25da42e1939ed99ffb145f8","tarball":"http://localhost:4260/cacache/cacache-10.0.2.tgz","integrity":"sha512-dljb7dk1jqO5ogE+dRpoR9tpHYv5xz9vPSNunh1+0wRuNdYxmzp9WmsyokgW/DUF1FDRVA/TMsmxt027R8djbQ==","signatures":[{"sig":"MEUCIEvDtjyuT+r4KyJ2d+ppvxbBpomxBfvFVEcy33fl6O1EAiEAh7fkj12Lsxy8QdpYAHjM7uw7mxe9szeZGGfK7tEmMSo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"81b8d1afdee1c275caa00e4907967b46a0feebe6","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.6.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"9.3.0","dependencies":{"glob":"^7.1.2","ssri":"^5.0.0","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"devDependencies":{"nyc":"^11.1.0","tap":"^10.7.0","chalk":"^2.0.1","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache-10.0.2.tgz_1515296450961_0.34615294821560383","host":"s3://npm-registry-packages"}},"10.0.3":{"name":"cacache","version":"10.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@10.0.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"3d7cac2f179ae5523e777f74c4e956ce6686f31f","tarball":"http://localhost:4260/cacache/cacache-10.0.3.tgz","fileCount":29,"integrity":"sha512-fhy5oPxjgI/pfsSPhlqCFtvuM/lvRnD0T7/fCFoXNmR6/1IKMXsjk2UlNbrOkACbm3e9Xb2TfuDZ4d6lyqHXSQ==","signatures":[{"sig":"MEYCIQCy6/R4y4NitEiKzPjwHMSET0qfhkWMHdEFm5Fzrb3iQQIhAM7S78j3yDTXc9EOGkevYfjSnAWv/4/WvwJivAC0ENcM","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101928},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"c15350e1c0629a054f497679e652edbed4972e28","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard lib test *.js","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.6.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"8.9.4","dependencies":{"glob":"^7.1.2","ssri":"^5.0.0","y18n":"^3.2.1","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.1","bluebird":"^3.5.0","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^1.3.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^11.1.0","tap":"^10.7.0","chalk":"^2.0.1","tacks":"^1.2.2","standard":"^10.0.2","benchmark":"^2.1.4","cross-env":"^5.0.1","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_10.0.3_1518811245878_0.5010480970477138","host":"s3://npm-registry-packages"}},"10.0.4":{"name":"cacache","version":"10.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@10.0.4","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"6452367999eff9d4188aefd9a14e9d7c6a263460","tarball":"http://localhost:4260/cacache/cacache-10.0.4.tgz","fileCount":29,"integrity":"sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==","signatures":[{"sig":"MEQCIA+IIfVl6yb5zzXyNC7KT/aOu3nVf/Nea1VFdJqMKEu+AiAzordymFUt7wgSzM7DgoN3Oo6mC/rPGYTvBImcEkWThw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":102024},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"555114e87a79f5c6115b5fde8e74b3fb62bc4a33","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"kzm@sykosomatic.org"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"5.6.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"8.9.4","dependencies":{"glob":"^7.1.2","ssri":"^5.2.4","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.1","graceful-fs":"^4.1.11","mississippi":"^2.0.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^11.4.1","tap":"^11.1.0","chalk":"^2.3.1","tacks":"^1.2.2","standard":"^10.0.3","benchmark":"^2.1.4","cross-env":"^5.1.3","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.3.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_10.0.4_1518821654618_0.08192369229055396","host":"s3://npm-registry-packages"}},"11.0.0":{"name":"cacache","version":"11.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.0.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"6b7ddb262c764cf482495ab086c69ff084385821","tarball":"http://localhost:4260/cacache/cacache-11.0.0.tgz","fileCount":29,"integrity":"sha512-pWhgsZ8GL5Boz69gJ4RPM1xiyIfB5gbB1V0P1WCYjIUDeww1zSIaM63x8R7YlRV95MxvXfxB+QVeY1YdneVaiQ==","signatures":[{"sig":"MEYCIQDW8qJsV/3Ybo9pHq6WQIqIzDLe1uLdzRr9S3cLM5fKnAIhAOpDgpAHk6jICUyCH7evOMoe3Q9rn8yVi7+TnaML8+af","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103377},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"aa59d8256aa45d3043ad081fe65a8a443df562d5","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.0.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"9.8.0","dependencies":{"glob":"^7.1.2","ssri":"^5.3.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.2","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^11.1.3","chalk":"^2.3.2","tacks":"^1.2.2","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.3.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.0.0_1523234286252_0.6432170196203006","host":"s3://npm-registry-packages"}},"11.0.1":{"name":"cacache","version":"11.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.0.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"63cde88b51aa5f50741e34833c9d0048a138d1dd","tarball":"http://localhost:4260/cacache/cacache-11.0.1.tgz","fileCount":29,"integrity":"sha512-s5YA8Lva1PF76kHDquIPW1N0YJXNFiItwrrDXAn8vvunOv/VNXOR1LtQYgPBRpaweIX2xSaBpqIXCYeOTZfHSQ==","signatures":[{"sig":"MEQCIH7racLpqvM9tiQFEqe8pseD/jfTYQg4nsgtJjVwzvcSAiBazvl/AsP1J4jApdbWMr4n9WF7EZu939cvM6Hc1LTmKg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103486},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"41e12c1bba2fd9e296ad98f1e26567f76d3e9e01","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.0.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"9.8.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.2","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^11.1.3","chalk":"^2.3.2","tacks":"^1.2.2","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.3.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.0.1_1523385908811_0.4553085564595629","host":"s3://npm-registry-packages"}},"11.0.2":{"name":"cacache","version":"11.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.0.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"ff30541a05302200108a759e660e30786f788764","tarball":"http://localhost:4260/cacache/cacache-11.0.2.tgz","fileCount":29,"integrity":"sha512-hMiz7LN4w8sdfmKsvNs80ao/vf2JCGWWdpu95JyY90AJZRbZJmgE71dCefRiNf8OCqiZQDcUBfYiLlUNu4/j5A==","signatures":[{"sig":"MEQCIG4G3pWFdPAXChXJvL+TGkPm7uUb5c++WiN+VPkJNp14AiA5e0IjYZBRbAZT0akoHj+sQungHOqPeUJorPG4ngWyOA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103864,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8KCeCRA9TVsSAnZWagAARwIP/iLX3k/nIgihaXX1urCX\nq+kBkZ5pjhGAAH22PhKfhJcMmLStLEzhxQMnFDf+9HowhMHM8vccMZuZbWVW\n6j6xtdalp2L+n9TjJZIGZk5BRLF3Tc3n93G+f8cpbxVvhHnYvs80dJpUMN32\npPNFFa8C3knDGaE9UtQLhsA651OzgFSHykf9lLVJ8hvgne4VpD6wTbKNLd8D\n7UxDtj3Ue+7OTZZBZMdVTgBDrUKqDJX6zUP2dZe/Gtjnc1CtbEmBxh4wRbSx\nRJSJJxVVpwZjxVvdmHXEnwqnxXJseQQP6klSxtjJglGmc5izGFrQvL4CVQeZ\nxSSWyEn/2zmNAvbTvVhM5xsr81hWLWyEc7MbOxss1HjiDe/FJgsCRTt/FE8R\nO7aaT2r9sABBfT2YLr9b1VAcqoiL8H0ATLwe/1RMFJbLtuWkBLBpOe1Cuz5F\nDBL9JwG8rSmCfUMjlFwFXK9YFwEfV/PHz2dtGc7QN0qwyXfmPbl7jmFMJgzh\npa6Z4i72r/LGh1gI4VPQSjcYjTbRWsH9nPPjt7iY6WOF2ZEEXMQqOHvG79Mt\nFaNzzaUiPlfhTpI1iHqAS8at117kpmadxO3058jln68NnJ9CdDZZ8+V3HX8K\ntyjXxV3DrwLvCcd111kPmbE5+KSe9nfXAEL6OpTStkK6q7W9LsW/94QX9vhq\n82+u\r\n=RUWS\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"dfceb7d59980d48918bbff75f230ef3313cb7630","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.0.0-canary.3","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.0.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.2","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^11.1.3","chalk":"^2.3.2","tacks":"^1.2.2","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","safe-buffer":"^5.1.1","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.3.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.0.2_1525719196036_0.5875191634477166","host":"s3://npm-registry-packages"}},"11.0.3":{"name":"cacache","version":"11.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.0.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"632afc1c48c17cf4f37fb0044f8da184b475426d","tarball":"http://localhost:4260/cacache/cacache-11.0.3.tgz","fileCount":29,"integrity":"sha512-PKg49kjNaPFvzwcIo4mo46av7uKDnECAeyNDp3R+WTohi+BeQjPC7zcKxx7P1lyMySNBY5FeGD8Ys38VtBGcTg==","signatures":[{"sig":"MEUCIFgXeRYJjr+So5VXEbtU7A93iuy+VfguNTvpgJoDU/HCAiEAnF1TyJtb0kZXzKF8D6//9y+BpcE/lXkNWGa3VJxGvXw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":104392,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYhgPCRA9TVsSAnZWagAAdY0P/38vCfVgefLo504o/7Sf\njknTMGrBZcxqaV6+jCdky8jz5Nje9URKhrlUyYme7ZE2rzc14N1kFvul3df1\n8NedG4rNcNiJxMpc4k7PN6Iv0sC8+uoZ38TAQpYH2brSuOEAkILDVFpAKXAA\nmoNuPs/bZSJKzNIe7gzVpIbTZaZLFLjK+QsXIa+g8/YgEDOM4BqI01A70nzG\n39gieFaqYv3EiBcSq8qFdkz547wtheGSY359XI4kYhnByE95EJ5PWOtOqxcY\nXZHycgWJEBWzh+zRXzISq3ED3cONWwmbneB9pMb4qW9kwxzsYuJ8EH7GxLyb\nvRxCKtE4qBY4CTJg/vVsfMzF/nKquRHDJKXMtsISoLi9Nm2QUsnrzJuCOT8f\nqxc0jRTEth/k5hFvbj4KXQNPokVT/IoZvvo+oaTfts+39Eum3pfs45Yfa+IN\nl/w8I3dWYPdDi0r4PIl3nqVKh5Og1lJsbc5NNnmZyBDMM4XguaTGyXpUbGL+\nRE5s0jK5QIbQUk8nSqNLlB4xTu0IUGpLBejy04drmBl6aHfmQNxPPZb3Fquh\nyG4jnx5lGPamsSonjtlH8odWZkhiTto8zlsG6WqvyE7RCMyEOZ6YYbU/eine\n7jlvSMoA/Jk04ycXJ1iOjM4rULA9ed6Ssv0yW+BwqwUg7ikYMFnAxHvjevmB\ntrNZ\r\n=m+e7\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"8a94928a0463f05348e8084fb0a3a037b2c275b8","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.3.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.5.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.3","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.0.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.0.3_1533155343050_0.8426501612589756","host":"s3://npm-registry-packages"}},"11.1.0":{"name":"cacache","version":"11.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.1.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"3d76dbc2e9da413acaad2557051960a4dad3e1a4","tarball":"http://localhost:4260/cacache/cacache-11.1.0.tgz","fileCount":29,"integrity":"sha512-wFLexxfPdlvoUlpHIaU4y4Vm+Im/otOPCg1ov5g9/HRfUhVA8GpDdQL66SWBgRpgNC+5ebMT1Vr1RyPaFrJVqw==","signatures":[{"sig":"MEUCIB1UfkkX8dJt92a2Bf+pW/TZrMEg9TIUfAjH7h3iEmNbAiEA52b3OfnnJzt5s0PdZGUp+Dt/MosyBl08XRnIUAKAqk0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":105687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYi/bCRA9TVsSAnZWagAA3BkP/Rjumg5NF0KdlOtimiEu\nDy5v3o8DZMvpQKi/ULuvK3qY0TCCR9GJc3HKk3FCrGWUp53AwJSeBcEFM3W6\nc15/X+97adBqNv+MgkcmK1bs7V56buBfEAoIYGNfhjJu5WuYt4nHR9USdwrD\nSrBl2nR6S8iRgrlOMtSH29c5bwjxvx43omHloxUG3+WSnQnyDZ45r99izi/a\nkxouEmWMAWYPSIEsEoDtlc/VegbED1OcHyJ6EG8GRBZt0PK4coOJMnpaZiUj\npjbdTM/35jyRoKUNK22LHDe6FPFp8iD8eZTORwnMinOIcjUPcE4qo9hxOLSO\n1ucjaFWyAN4xOXoVGoijq/2heGbDMf9SGGFpeBfltiMLhZmA8NakjtrU0wbc\nlcKkTOcKtowhGlkE2bCzs6kZCbhG5NyLwJZWBd4zFN2kk4ttd6u9tK8W99LC\nCmg26BWsDhic/aleju7UIwNq8+c9uBqBBpVxJTeYU7gGrfOdZAoCsx5RjmzX\nDWXyA2h42NdLSl2t6IeFIQV4Xq1ZMB1b3/vGtA5AquFubIYe9lnxlEUjAqF5\n7L4Y6bqVB05bT7qfpq0//yesXQTeod8Zpmjy/1JYTT1U4Vxqtk6j0fjqKTmK\ngjgpHqMLzXML88eRkeyNw4BNmom97GLhpeeuo3bFJ7QqI/rTWF+85y1Tpqsa\n7dRn\r\n=yCMw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"4b28ae3dfd21477f67cf63ae288f0a471fe78970","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.3.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.5.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.3","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.0.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.1.0_1533161434574_0.4302741097099263","host":"s3://npm-registry-packages"}},"11.2.0":{"name":"cacache","version":"11.2.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.2.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"617bdc0b02844af56310e411c0878941d5739965","tarball":"http://localhost:4260/cacache/cacache-11.2.0.tgz","fileCount":29,"integrity":"sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==","signatures":[{"sig":"MEYCIQCX0l+qlULIvxTgs35oY1EGzu6fYKuBgzjYy4XJrxQFSAIhALVEmgJ/AKqDm28THw6n1z8ZftbFs9H0k8FH6iGVRHNR","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":106685,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbaj3sCRA9TVsSAnZWagAAwHsP/j64ncfiQL/IKCQb45Zx\nYRD43mMsd2BDc0k+qCrOlIw2x3jA+eTh9BHjvMBE0BuMuWAjwV4wXKXjBIpu\nwBhzYxwoCEsQbksV7oTAMS1PnQiOQfuZEs2zLfRIxQ8RbeGuynbE6HIKQSL8\nedyjMvsT3rMdY2rFvClYdLxx7qwZJYdL/6GXi8K0+F4Lxe04sMkKqNvwD2UF\nL2dPeZ3OcflO+piFJTZ4/8Yrb8fwR22D0zSiknQEI9T/ojYc7WJWetIPTija\n1IS4cAww4b29oWDY7SUS3yx1+09vPPydioZSvtboIfHqjo6Ahc0QQg3e97+d\nxcS5YJdpANFA6SQHK8gnlkfWZ+AX7eVowzWG17qYqq9XEgo9RcUoKvXS3AtO\nA7HHAkr6ylzkg8JF3xLT/gtyAltAwpIYis9wRb4Vij/clML5vVHjxNb2Vmab\n3TN7JubsSDxrPsdZ8RwBW5VuwqZS5nNo/WTLrUOYQHjSP0zjek8lmq9xAP07\npHgMEAcGKZnMzGkBwBSzEsrCWKLGo2WkkogubRJClL1VAeofLcTT/VpiNLFR\n6fs8oliVIA3KmOV45PPW0LJHt/Cyj0F9jO1BlMZIAn4XSIWUF7IyDjtRqVYA\nh5Ia8Lksurz9SC2b7c8JfOPCHt7gP+RRJyzVJmpbVNO6LGi6UosvT+6SabZh\nGb91\r\n=GisX\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","files":["*.js","lib","locales"],"config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"93b08939e622275afc3f912e885257a93cb56e53","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.3.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.5.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.3","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.0.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.2.0_1533689324598_0.6219370503557153","host":"s3://npm-registry-packages"}},"11.3.0":{"name":"cacache","version":"11.3.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.3.0","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"c37d4c12e3114064becf8904adba039a5befd4fd","tarball":"http://localhost:4260/cacache/cacache-11.3.0.tgz","fileCount":29,"integrity":"sha512-6Af/h56f+GXGAuxfutTZGxOofff+PfaZ3K0XlXjMAzS8HHijzNYySP8zHrJ0vniSzd4wrMgwOHegWh695pHSRA==","signatures":[{"sig":"MEQCIBhda2iqAGOGj0xxcpC3DpJz95I3nRBM2RLHAeNGrjwyAiA0XbrHcMKKMWBEsaAcB2Yvtck/xVDRuXCRitimJjOxZg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":110919,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb38VpCRA9TVsSAnZWagAAwjgP/1hBBUmdSNN1Z7uLlb2K\nDxWWZvH9oPsaNrU++q7PF52VgvszUNpau6lj8E33Wi4O71skDVakfEBZG5WV\nCo7Hm97nWZubL5VD/3Eb/jMe+T4PAyI7lBSefG4sDkMgvbztk7gS5BvAf6ix\nsBZAQb/PIS2f+2tQHiDrxHf1+/ut19EyYX01hOo0IZ70rhZmtVqXQhjtBpSx\nK5Ir++WREaNTRMiRVoAdqVpMl6783NKBErtFziuUm6GFA+JhOjmPm69Yhj9z\nNI3umXFqiLLfA/GdlIJIYEurcCnDqGAxcUDv5aItgXyWVK/prT4V2gPmJkOM\nuzGpXA5Kfh/KO+fjOKh0vMkNlqZROc1h4K6EYKZKeq0xlSL1JadBfTaZOIMS\n2WRhMzFjlZNy43iAtDljJIU41qtbU/fUgnGRA0f784iXAY4XDsYveKyNqOMn\nBE5fXDSuPTEg1NyvOaOYomnwfjTPa4J1kA2bM1BokrnZ5O6XfVbR6/4DvZ36\nJ5peve0oaJ5lJTC/BK5HM301/AFETOQ3H8zmUFTROModACV6l25elIyODFON\n8zMNocTqh5ClN73L4MwvxOkFFl+zmKKJ5iZFs2Eo3cukgwL3ZTOWglk3WsU9\niVGjDmd9LGjwg+vPaY/D8UxXgb4dVKajpOwepiBPhl129uXtFusaHlsiIcSs\nzYQ3\r\n=E2jl\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"4c38261d756a4133cec220d7ac8be3bd142a9dd5","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.4.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.6.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.3","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.0.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.3.0_1541391717699_0.7941223170061609","host":"s3://npm-registry-packages"}},"11.3.1":{"name":"cacache","version":"11.3.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.3.1","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"d09d25f6c4aca7a6d305d141ae332613aa1d515f","tarball":"http://localhost:4260/cacache/cacache-11.3.1.tgz","fileCount":29,"integrity":"sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==","signatures":[{"sig":"MEUCIEfdldQ1dQClW5wsI8h6c3HwBlln5CH1Wg+x6F0N1B0/AiEA73Ax84RVK3u+lcOK4F+A4+hdROjnUloKHKOXM/gZd3A=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":111301,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4LNYCRA9TVsSAnZWagAAKwQP/1WNsqOngJOmHit1rRAc\ngDtvOXzeEn42MtKAQFoZOJT7zt8xNBIg83PMmRXZRtWGGkQvo07pfB4qanoE\nEvze/fDFHi/jvcToD/brYsBJZ/IMXWZs8ukx7vMj/ZdqIH6TGk0dvbOi2TP4\n1kvK9FLcp4esdRQ1so/SAvuOA//fZWaNv+JX6KvMRlLM1tPjujHV+DIRCihQ\nE1BhSYP7c0vmn2telUTfzAPBGR9CFT0h3vk5KMmZs3KvFsRRFs1+MCA+XHku\nw4KnM5zhAgPS6N83DQm01aNMDYp7f+yVmG6oj75Q7tJ+XHMotAbmz7CwwWAm\nEcUvYcLOo71e6oQESuy+VxHff5X6Rk2K3LrOi551cBqOC1u1VEna4g947imD\nhtcEURJZtkLhRARiUkyMiKaRPPOgYiOfvq289WbjroWMR3XdajOwclyn9Cpc\nLwPPp877gN/s60pkQqar5K0mcFjeUF7aLoiV7NRt2Gc/PepFg0VThQ6eitjG\nAQU+pk+a+/W3DVCqzFu98YMUoQvOMz2vViZ1irDiSC8dooH5GK8hitOQ+nHY\nKz2Xjs5uQOFZbCDHQf5pYTVX9WL4/2T4Am1Knz9uscyZGgQsgVqeX3wECkN9\nqLT5bu1KV+CoDRy6VcRTp/8ar6LE6FCR3uJZ3K2Ix0y5oxoTCPzdrY6jvyhW\nK8e5\r\n=1Wit\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"4c94e2cff7985739adb504745324c5052f7ad95e","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.4.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.6.0","dependencies":{"glob":"^7.1.2","ssri":"^6.0.0","y18n":"^4.0.0","chownr":"^1.0.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.1","lru-cache":"^4.1.3","graceful-fs":"^4.1.11","mississippi":"^3.0.0","figgy-pudding":"^3.1.0","unique-filename":"^1.1.0","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.0.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.3.1_1541452631258_0.9082455476227975","host":"s3://npm-registry-packages"}},"11.3.2":{"name":"cacache","version":"11.3.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.3.2","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"2d81e308e3d258ca38125b676b98b2ac9ce69bfa","tarball":"http://localhost:4260/cacache/cacache-11.3.2.tgz","fileCount":29,"integrity":"sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==","signatures":[{"sig":"MEUCIBlYmidt8JVY+cUfh6y3OUgTaYZSvUStuN9q7PKnQbf8AiEAv0k3mqZUHH/Xcd/G5GvKIJlnxKPYXgs6SKswDtJ5aZ4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":111544,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcHTf1CRA9TVsSAnZWagAAMtEQAJTVEcbY8QkjMVhIBBNe\nV7nbRouS62lNStW78eyOqVaakJRH/1w5oe0jzgTm27ItNM1hQae1MJyihDkg\ngs1SE0A9bsUA5IRUyGSmISa0LA/NSMLIYBO3XvLKpY+gLQ7D5enXLHWKbDJ3\nF6x3wpresZZCdynvYtiDz234ofrotdvU/xaIxrxv0laoaJElzPhuRgUShLNe\nYIQxxzF9cNYIYh3he/tiuj90NKYtbOsnHfStrxFneRqx3ynD77l/vdk9tEeM\n4THtgv538k6yN3Nd7ZqSNNTEPEvmIl/ibp5Hb96kiMKctUAsNs907k8LPW/5\nf4c/Jh+SeiIiYR/AjkatC4zWcfhk8Glxac/lNUr3ehwXi3FMTAIp0J0JHpXz\noGUhC1LNDw25Ojjm1EUthBOxLS3HQXMWG/E2Ec4I4QJXE3tYWZs5cch+SvdJ\nLadUCtsewwzMfJocPfGVyh7ujJbKeJ6MT1Lc11TQ9BBpCtjPF4skMK8btWRY\nYLspAHyDEzi7Awu3symh/t9+/4P4fjFchJ2ahGeT64QtoPomezxh8mFhKhnr\niUufymVJWs4O0STKTSpVhBk5Rb/9RVR+RLlss/xuGnBlRuTb7kVCfWCzSQU8\nZKPMIqeC6ZoPCIZ8y09XUrf/RQmMZSwws/PWBSktnLTnMozKyQv4biIvfBNl\nGPMM\r\n=/TH5\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"e2f7cfa65b00d49ad40e6934378221f79159b34f","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.6.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.14.1","dependencies":{"glob":"^7.1.3","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.2","bluebird":"^3.5.3","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.1.1","chalk":"^2.3.2","tacks":"^1.2.7","standard":"^11.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.2","weallcontribute":"^1.0.8","standard-version":"^4.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.3.2_1545418741005_0.06216671094411241","host":"s3://npm-registry-packages"}},"11.3.3":{"name":"cacache","version":"11.3.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@11.3.3","maintainers":[{"name":"charlotteis","email":"charlottelaspencer@gmail.com"},{"name":"iarna","email":"me@re-becca.org"},{"name":"zkat","email":"kat@sykosomatic.org"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc","tarball":"http://localhost:4260/cacache/cacache-11.3.3.tgz","fileCount":29,"integrity":"sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==","signatures":[{"sig":"MEYCIQDCOHZGE9owl15YmfLcD8kd1IZOJpyApyjo/yNgcecKbwIhAOWAqlAwBf5QzTwf2A6WOm/4ucoIh6eV6/vavELCLwxZ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":112357,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdB7xwCRA9TVsSAnZWagAALpIP/0hXZCajeHjjzLrBUEV7\n7EUQTQEZym84XZx0B9mgjcr+Ga/udYJjFX2s+omXnxn47sEDh3aN0AHW5n17\nBVon5YDJo8DJRR2QGBPUE/Dr/nDCPZT6Crgk3z59W/iH4BgnlIOCM4N1xZrI\neiQmlyoFw/bDCDMPNw2a3nvYHLBpYMGOrJrGz0ZxklB3WWJbh5eFsO7QNdJN\npTECf/2TU7AtwnJuo7bcD2nyKPW9z04ijV5JnCZKW3GU6yM7KnfvSb4rghep\nL2K1hhmkqt1YlztHXC/jXo6fNiZid37vcQDPVa7muKZXWOEDQexl4DO0WP1x\nAzo3VdObNRInfQp2mmDTnEfKScfEI81zcWMtfq4izWLKLOMl3QkUKGDDCpq9\nl0Gip5INniQ0cbf3Mu5XuBfzQ+f8n16vgIhkwEQj1+vUXhM6wus8td2wyCDo\nk0in7zPMhpNZmy5EI14rZtJuFQ3m9nSJN8SVi/XDcKYqXZT4/FmQZ+2m/WQ4\nzjJxN4Fh/rJFK+3Mf+itcQApjwTQlBshTkcltEeeAXsRKIGNlWApxZaGOkqm\nvxUmctFA3R7avdsmXIIj/AtwHRbGQSpJZBDR8HmuiHFkRu/JK5mmI7ohMewZ\nNkszQFCfcwYGou3dEw8tJVv0/PMUBhWCBiUQJYqdK/+t6jFKhP6dJFd5M7jH\nofMB\r\n=MkeU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"886b40f394d5b0879a2aa1bee06326a4265459ee","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"zkat","email":"npm@zkat.tech"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.9.1-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.15.3","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_11.3.3_1560788079893_0.464903352864831","host":"s3://npm-registry-packages"}},"12.0.0":{"name":"cacache","version":"12.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@12.0.0","maintainers":[{"name":"isaacs","email":"i@izs.me"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/zkat/cacache#readme","bugs":{"url":"https://github.com/zkat/cacache/issues"},"dist":{"shasum":"1ed91cc306312a53ad688b1563ce4c416faec564","tarball":"http://localhost:4260/cacache/cacache-12.0.0.tgz","fileCount":31,"integrity":"sha512-0baf1FhCp16LhN+xDJsOrSiaPDCTD3JegZptVmLDoEbFcT5aT+BeFGt3wcDU3olCP5tpTCXU5sv0+TsKWT9WGQ==","signatures":[{"sig":"MEUCIQDel1ioqGUmZhr6d7IP22Zmda/WAXhhqd+4AvgOFUB86gIgC+rYU94wczNha5h2hNXKEcIfptyfm54ekeodCXwR0TQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":133904,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLQxECRA9TVsSAnZWagAAnlAP/3tLeWfkXm2trXO+9nFC\nCKLz1Yum8RFhj9BlBNjC/JOWiwb0+s95R+FENdfg8mbuiyBc5SY/HV78C+Dc\ngYvrkg1piAYOna9TK+DdiQ+WafhWQohyq3X6QxatyUvsMaE3yQzo3vYBQmsA\nuZ6U7A3qPZuRaf8A9ryCaSk//EQx8P6eJqY1RmJoSC3axi3CMo6DlxzWa2mA\nEWQXxdMKD1+elGwtjkuO6XFiV6VYX/q1VneXAe5ONpcEtz1N3k77hs0a+YXi\nFCxJ6putj1Z/cIaaRxkVE7woXhTkeB2DqFCPa3DRuDTBrofHlQuH57cXcdAJ\nTwUPMnxwDjn3F8oiRcJuN/bQrrqK4Uuu0nP7SCpmdDudiUhRbTbMO9rjl5b9\nqH0PlECVEO4b6VR4jKQhqQncBRmru4eMaqpCvN9u+aSBEAEZBvQIHoNcR8GJ\nZ2MD+gocXjYctRkKqMTS8V7CuCy64hifepAO64gn/tEpy6y0YOA0I2md/Ig0\nhCs5LaQKKQ5Yit7gQBk8MUZrbm30Jk8k4PdcAzOq7zBwrK6a/Rr+pbnA8sKJ\nAKq1Q9NVbAW6zVHBOcD/2efSwkVgoFD3R/sg17TLEM+JKw9wCNj7GpxrIVMd\nkMhhPkXxfWrItB232gEzo6m7KJDHiUu9lFfpvqTbXf3sw9mnrPUACMZnqdnC\nl28U\r\n=Z5zo\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"5e961324fa1c6a39c5889c5d31114886a84586f7","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/zkat/cacache.git","type":"git"},"_npmVersion":"6.10.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"12.4.0","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_12.0.0_1563233347682_0.7510440409614905","host":"s3://npm-registry-packages"}},"12.0.1":{"name":"cacache","version":"12.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@12.0.1","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"isaacs","email":"i@izs.me"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"527af5682b34bebdcde549ff267a4a46f2944857","tarball":"http://localhost:4260/cacache/cacache-12.0.1.tgz","fileCount":29,"integrity":"sha512-tJtxCdrtecQEmAkTCt8qKZQWANckuD6T7d0EhVUxh9lbggCedG/UoGCEyo5+/vgbpwhEQJ/FHgREsgoObex8Pg==","signatures":[{"sig":"MEYCIQDPbMxAICI4tSgXAGvfetS+4Te+BQ8hHXvBAI2QiyeSjQIhANUoZeeEHKNSeF5y9+zxV+vppEvK8Ar/KdlwIdvBxnsw","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115180,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdMkWDCRA9TVsSAnZWagAAUNAQAJ24oeKldNsQiWWNhQqq\n3e2TfwG6w3Xd0g3J4RuU68mPTxXONa8wm6bbmtIropKpSqPVYaNSjm31LNsM\nvm4rnHfbN2iLSys8qBgtrSoDg4qWiC9s9oMhm3HHpuH83nE2eYBy4yfOgVO9\nxKwPfSOE6AJvXvDP1CgETSCIw1Yr5lwu0S+KVZ9SAhK1RbExaOaGXgYtruUE\ncigDd/Nz8Yz+NL+T5EXr8bwhMOfAUetvy7y2a+ikeeUDVaXhuznAloukMyM4\nlAS7QtDA0sFME0LVhvdu1nnWB5q3+yzgTlD/2NAdyVbkP0tLt+T2/1XTe6aS\njCn/AdjRXJPXW7PuTPwr+J1xwwM/MbMW3D9TQ+WEZ+zpzbFMKGyvDLqrszVT\n+TUCh66DXZmnIzl+Gwc8i7wFdpP/zZC6ONvarjyjtDGljpOaytGxc8LUppES\n3zSrFdsPxav+HpOVt2RbesAZ2mhFcNffjSznu24D5pGyIvDDRJLOGsd9dJ7b\nZFNPACU0Jg5LXHigMYe62NIiQBBHqAd61FYU3A6GzAFIWHJKU8GLg9t/I1un\nwWgW9++lfev0R/Ed10V1W8MZZTkxtje3EUgQqjU/Iq/pyhjDsDbg/Je1q9ye\neEJAnMogGD3/N/2XLPqv/w6OIgsImQe4xdBzjyaJ9Ynbjxozm482jg7cZIgg\nSf/q\r\n=QeUk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"1d2cd974154fc98d29c427435d56dc09e293501f","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.9.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"12.6.0","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1","@npmcli/infer-owner":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_12.0.1_1563575682876_0.9849059790812396","host":"s3://npm-registry-packages"}},"12.0.2":{"name":"cacache","version":"12.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@12.0.2","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"isaacs","email":"i@izs.me"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"8db03205e36089a3df6954c66ce92541441ac46c","tarball":"http://localhost:4260/cacache/cacache-12.0.2.tgz","fileCount":29,"integrity":"sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==","signatures":[{"sig":"MEUCIQDxDUMpvAA/rp1kSjkjGb+8OMyWZKYGCVyH5WrAa1cW1gIgLXI6A17g4SxuhaCVYQqS393OzC0bIJNZMqa+JrPXiBk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115251,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdMk4MCRA9TVsSAnZWagAARK8QAJADGsGGVtuD7catXO/a\nlqb285/vpwd9ZsHGUepNeMq6p53Hbek47jukUwlMR+e99dbroWfiJ3R/tnLb\nrRcUXzovB7mmmac3Br9JtVBDHKt6G6W/HexkPGdCXDE3lWk+xKax8QUgif4g\nQBc5u6IYnCDEEZRSMMVgLbUr0Cj5bzSvXewk2W9eAoAfjSkQL4HVKwmRUIKd\nKdlt2xQ3QbOYKVsd6jO3tqRzeNyVDwx9W/e6y+SPDYZzeqy2HGsLOguqAr+1\n8BhKDEtqh7hJlMDqY2EMSNokAz0r2Jz7L0N1mf40hfQZibx2dWonmiP8xPFC\nm5j2Zo4tQJlthB+S/UCcLQlgKbIHg7Ww92ZEhZYJFCNo64Pc5vUF0TLJZ6XE\nmtRzT6Ze/vO/08o9RmIyadEUfDOmY/i9larInPNDBkgwdc6UMKlevW975MI1\nLRbogcEWVVJ8NseOLpi0Nzg3IyXva7H+J6v03LvU/u+gcvzjUtSWuEdFxln9\nC2MpQ6BAktlMdz0UA2kljL1E9cvykFBBzEznAChUpmWSqUtBvAtTLWoJpBE/\nERcjOynd7v70SMyUmQ8OsflydFO6dEEHR5U2A4QMlWVaaYGarm5ViABJSo7K\nibCpB7Ef9DhFPGgqzKe/WveSaDxX7WEltT3euzKaVOrjPFrWElRWodSnziuN\nvq/X\r\n=WzUQ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"568d7eb5e7429d540a670daf2a9ccde5e9be793e","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.9.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"10.16.0","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","infer-owner":"^1.0.3","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_12.0.2_1563577867745_0.7249907864571483","host":"s3://npm-registry-packages"}},"12.0.3":{"name":"cacache","version":"12.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@12.0.3","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"annekimsey","email":"anne@npmjs.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"be99abba4e1bf5df461cd5a2c1071fc432573390","tarball":"http://localhost:4260/cacache/cacache-12.0.3.tgz","fileCount":29,"integrity":"sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==","signatures":[{"sig":"MEQCIBkXvqhIA7d1GSzl+2mo8I/lf5JECxDMERx0GPcv5tdoAiBYNKHmf17O8slJCQBm39JO51Szwh7gvVXcUMem5+xR/g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115547,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdWvksCRA9TVsSAnZWagAACsEQAJnoOZHbECu0/AKMvHME\nZspR+OhjsI8UyJa0+4bp4419RLpW/J8S5A5AgdnLXZc5+1TRXdd6oVXgqeAW\n7vswR/5SPUeljQYI8DjJELTO2dqbQRxXbeM7LaaJbQBtLMTNpzdhqNnW88/i\nDJVgUUX7hPKHVS2rRa2WbGmR5Qi92be6Q73pCdD+t1nZBc2baaPMEQzzOylk\niXM4CO96ZHLOggn95U1f2AL1RQy1pzWC/9muMpG8Yu0YIJ5JBlF60vjGTkwO\nhdrWFcy3ARZ3tjWIEIQkh2Tet/3yW1dKzk/8DnKwoJ6C+8RhUj43+fOvrOFD\nHvfk4BFZ0Dz3EW2Je83Bj0kjdvNtxZlvwH+BA6Nkq7/uNwiWP+os0A0knE0Q\njlE+Wp5LgJHAvMW95mEyMR0dtzsZ9RFM2oYDPkpLxl2LUAQ2wFQ+mqS9phIl\n3CBWb62xjgrRbh+CbqnUa44y/sU4kXFEzJs2nFj8EAZo1avF4OAsmue1Zr07\n8QKKX2JIyy9KGEhZ/rnQ5dWMJRpPjD5JzY4ejypxnxZgW9QP7h3BXnpkK/zr\nHStpZ2DH4AB8F7/Gf8cm8EcHi6c0MdlIZazJXEUgIURYkr2T0JFUlCp9b6at\nZBLn17XqPSvdewCedGvqGVOuwttsDIKz2F6iwRPXsJpx+5+zZjOQS2zKPSLu\nT60S\r\n=qek1\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"gitHead":"0cb1aaa333eb4d9e3afca20af143c9f7c9fb3d49","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.10.3","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"12.6.0","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","infer-owner":"^1.0.3","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_12.0.3_1566243114847_0.27856964581226906","host":"s3://npm-registry-packages"}},"13.0.0":{"name":"cacache","version":"13.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@13.0.0","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"annekimsey","email":"anne@npmjs.com"},{"name":"billatnpm","email":"billatnpm@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"mikemimik","email":"mike@mikecorp.ca"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"nyc":{"lines":80,"exclude":["node_modules/**","coverage/**","test/**"],"branches":70,"functions":80,"statements":80},"dist":{"shasum":"1797c957bcddf7bc697520920e3a284e64fc21cc","tarball":"http://localhost:4260/cacache/cacache-13.0.0.tgz","fileCount":22,"integrity":"sha512-hc9ozSyxintw3TulgdYl5q3ZMjugHYI8lE5hd1S6E1/7OwLf0vNlBdCaROlzHxE5x0lUpFx+B3iMjWmcHDRxiQ==","signatures":[{"sig":"MEQCICUwY9WdmpYlpaIc8Ehu3TlSnVkLeqNDV7EMlHjsIW7wAiBvH/CIzKRsb4VfaRPm/HvY0dBVJdde3hqE5IXlPAo2SA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":98894,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdi7oJCRA9TVsSAnZWagAAFOwP/RQ3pTGWJG1yIPEKsQRs\nRkJfdtfM71vfEFkbcVXnPZGUTh73Q2LiQVxnaKjTcdkSIVl/wnhkcMCAuElK\n/yGOey19J+JJXVwU2dmT0wV8ZkV2bh/rqALk05pSVN5M8Vo0+lPheTxZn7an\nJhJhDQaYVzi9K0Jl/cUWd5PgrxVbFHOUCiwPUZrMAvTv4uaMeqDVjiOwbGYn\nozsUslwOHlBTtoB8BWcb7em7S0K35iq/FlD129zgFfsUWOnc7tPP24ShukaO\nTGfl+8ay7dxQ7C0JncowStCrNDivBC+Zzj5tHRg9VPTV5cwSDfJfcm5VFKfo\nVBYr1Wn319tnXuOwsNZdrUH6D7Kg8nlk49lrV5Eq5vleZgzgF+7BPQX8z9Y4\nuz0dayrINZcK3eG3n0PJmlPTthPJU8nlVUMp5fGmuJSV/WhUkx9OTNEl3eMz\nALVLAF0CGdbuXtGrlygLXxX3cpl4eX/l++g8EDMztjrjezHCa7Ot+CFunPpw\nr3c4oFrVlPVpO1eW7KrKEI41rlYJVg3q3UfPI6Or12EbXQZu1lRkv9WamIEV\n2Ggr+jCplkfoBOZ6zduwJ5RqSOmkXrv8MqZREWecPhO2rOgUE7Kf3sufehwJ\niK/F+hrecwbTNSEMSmRI0giM72YQ6ymr7OJjaC+R7iC4AC6j9iVQSYRm+x05\nSs35\r\n=si4Q\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"63ef08d2c6e537b8e71e2b1bfa7ea5fd6837c644","scripts":{"test":"tap test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.11.3","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"12.10.0","dependencies":{"glob":"^7.1.4","ssri":"^7.0.0","p-map":"^3.0.0","chownr":"^1.1.2","mkdirp":"^0.5.1","rimraf":"^2.7.1","minipass":"^2.6.5","lru-cache":"^5.1.1","fs-minipass":"^1.2.7","graceful-fs":"^4.2.2","infer-owner":"^1.0.4","figgy-pudding":"^3.5.1","minipass-flush":"^1.0.3","unique-filename":"^1.1.1","minipass-collect":"^1.0.1","promise-inflight":"^1.0.1","minipass-pipeline":"^1.1.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.6.4","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^14.3.0","benchmark":"^2.1.4","cross-env":"^5.2.1","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_13.0.0_1569438216725_0.6681915916397869","host":"s3://npm-registry-packages"}},"13.0.1":{"name":"cacache","version":"13.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@13.0.1","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"annekimsey","email":"anne@npmjs.com"},{"name":"billatnpm","email":"billatnpm@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"mikemimik","email":"mike@mikecorp.ca"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"a8000c21697089082f85287a1aec6e382024a71c","tarball":"http://localhost:4260/cacache/cacache-13.0.1.tgz","fileCount":22,"integrity":"sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==","signatures":[{"sig":"MEQCIAOPOYSskXQU+4XzdLbFuOXrrd4qpMwC/1w++Sx7xZd6AiAa8osLndhocYYUjXvQDCZV3wb/u0Cw6LzeP8ZkQGyUzQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":99047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdkm1eCRA9TVsSAnZWagAASTUP/jEBg8ZJhAowxxM44jkE\nHyrFqRUlvQaF463jFtK9zqHpCdPXxwmT6lgnPOg1OKwawt9ZYWyF1rVvV4bd\nIzR7GVqI3THIDI1g7JjlRbdItTN0412o8B0Jz+8wjMGwyaVk7uP5Lz9GWOAB\nPnMUhDcUUCK5hsEqh8JHbAJrfs8mZkrQX7HYNTYnWQEWnB7OQ8xZp/CNEioa\n7BJQ+NyEvjxbPL4UGtpROtGJ/WO2pU3hG6gdxKQ2X2DhEv2n5aRr4qMGY7//\nfTgAZfYHyfbHNQCEzMv6+dPAi0SI7e0wYTqY/eZM8Hm5BCOah63muml6+/1o\nySBrJv+j2ZOXBQLCdFGcEgYt7CQWBtwRZ39MFtOB8iK6RXkUTNmlmV3DMgLs\nyHYkxtIjc2WkrnjjcKsGFuzhug3tBpDQ26F8w9K1d0Vba9h0ULGUKDh2Lu6p\nyih3S6Hh4xB+SUgeKyeAJ08kTT6xLwGM2Ufv+Ry9hZgPXqQG3xcWCW6QFmVR\n2LolngiVqK4IeCCXATOjx45qARE4foj+1ZBksX/x6Vk4WiSA1N7dV6TxrmZ+\n3oFJM99uJ1xwfkduuTImvl1NbFAcR+KX5boaLJXgW0MfbMfFGu8A7/sN/QSo\nRb3qq48G7bE+PNNf1yxQCcxSlD9M0tf0JApNItZsjnh2tKJQ/sKWw3/jF1/X\nl3qb\r\n=0KSH\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 8"},"gitHead":"a931c99a1063c93946104e976b37e8faa824d957","scripts":{"test":"tap test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.12.0-next.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"12.8.1","dependencies":{"glob":"^7.1.4","ssri":"^7.0.0","p-map":"^3.0.0","chownr":"^1.1.2","mkdirp":"^0.5.1","rimraf":"^2.7.1","minipass":"^3.0.0","lru-cache":"^5.1.1","fs-minipass":"^2.0.0","graceful-fs":"^4.2.2","infer-owner":"^1.0.4","figgy-pudding":"^3.5.1","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.6.9","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^14.3.0","benchmark":"^2.1.4","cross-env":"^5.2.1","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_13.0.1_1569877341577_0.9708965806445355","host":"s3://npm-registry-packages"}},"14.0.0":{"name":"cacache","version":"14.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@14.0.0","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"mikemimik","email":"mike@mikecorp.ca"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true},"dist":{"shasum":"97c10fc87c4c7ee41d45e32631c26761c2687caa","tarball":"http://localhost:4260/cacache/cacache-14.0.0.tgz","fileCount":22,"integrity":"sha512-+Nr/BnA/tjAUXza9gH8F+FSP+1HvWqCKt4c95dQr4EDVJVafbzmPZpLKCkLYexs6vSd2B/1TOXrAoNnqVPfvRA==","signatures":[{"sig":"MEYCIQD0q7EFKLSh7KamuI61Ig1PlHSfGQrePLio344P/NUiBAIhAKBFJgoC2xCTroWQvARxcL1UwwzyQi5vP0kLAS6jtIh7","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":99805,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeL5PGCRA9TVsSAnZWagAA8nMP/iK0X+XlNwoBSzN/WdZX\nfec0Nm8KGGqVTRU6JCwgLu6KWcxkrEUKhaakRm1EpIH2buhemPAKl+M6/uIP\nLF+YXtKr4LvkNk5PS8jZmBvC6OG151ng73c5I2BqHf9HSmpl5iknADbtoII3\nXQEujXetENEr3UYWdkRrnI+kkI+sIl26sFaICVPWc1GYIIJN3JQRJW/tGLu8\no0d7fvx5WTZZ21NFWmJdqJjhowmONjIJ9rorahB581r1guMTjbt9Mpv+556X\nkMoX+uC37npY4ilz74AAOkzn26X0Wo9TZcXooIc2R28yPHjOLhugGKrrMpfh\nK7pbz8w6EzZ5QtSCuR2goiW1MJ4NGweuiYYPlH5zWUzrfLNgZPcDSL+3C7To\nH7shSK+vXbwoqeC33l5KGCwK0PqgzDBsGCRAcy2li33KTVxnbwGE9Z5i4piB\nJ2jy5hNiD8cYOjsk24cB/7LOQVtszGJOU42T7yhthnjAt8SBYVaVENIXjKEE\nWE5yAcpNTg6phmc1JVl8C6rEW09amaB46KeepUUfu1lRY8ecWdKR7JhjGJV9\n6aSoWvzatfwh0KBGmpUuXgB3JkbZI5dVe4ADwWNrJmRXGuOmgeu6ECmjWgEJ\nLkghjo0s7DLah1XdIAptbXp2vBFNqEsVP/BWihy4MUA6Q99VpCcfmXx/Xr1O\nhbDA\r\n=+lX4\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"9ab38aae2b1bde96c5bccfaf071046fc5f49d393","scripts":{"test":"tap test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","update-coc":"weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","update-contrib":"weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.13.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.4.0","dependencies":{"tar":"^6.0.0","glob":"^7.1.4","ssri":"^7.0.0","p-map":"^3.0.0","chownr":"^1.1.2","mkdirp":"^1.0.3","rimraf":"^2.7.1","minipass":"^3.0.0","lru-cache":"^5.1.1","fs-minipass":"^2.0.0","graceful-fs":"^4.2.2","infer-owner":"^1.0.4","figgy-pudding":"^3.5.1","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.6.9","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^14.3.0","benchmark":"^2.1.4","cross-env":"^5.2.1","weallbehave":"^1.2.0","require-inject":"^1.4.4","weallcontribute":"^1.0.9","standard-version":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_14.0.0_1580176326012_0.7801106723175186","host":"s3://npm-registry-packages"}},"15.0.0":{"name":"cacache","version":"15.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.0","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"ahmadnassri","email":"ahmad@ahmadnassri.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"mikemimik","email":"mike@mikecorp.ca"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"133b59edbd2a37ea8ef2d54964c6f247e47e5059","tarball":"http://localhost:4260/cacache/cacache-15.0.0.tgz","fileCount":23,"integrity":"sha512-L0JpXHhplbJSiDGzyJJnJCTL7er7NzbBgxzVqLswEb4bO91Zbv17OUMuUeu/q0ZwKn3V+1HM4wb9tO4eVE/K8g==","signatures":[{"sig":"MEUCIQDQ8b6pPB95TRz6Khddxn5kW6GCA645sYWFEmWUtKdS6wIgXeUXbKASKFIHnuAVtdEm50v4XerMv1hWkLYkiTohHds=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":120578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeSz78CRA9TVsSAnZWagAArukP/jRhV5YGJdPCbGIvTj1j\nQyYUmmnISqQXuw+0Q9TOWGMOTaV+sQzRq0vZted8xaDiK4micGHFHlW+/ZPY\niFlz/l9vtv09+5TkhakTCR1X+URAcylN+tfTkKDVMptVhTvVuhosKRD80HjM\nHxdr5P2SlaOKaGlfsFeqFzMKIo/8LQTgLyrC/Yd5NiluoOihps0xi5Jy9PX4\nLTIkmWNe7SyT9Ygg8jtgAVtnh3jOupj0yMenuojd+EcwLtjsK1dbJHUHrvy8\nZfYLcGybJnl4eG/52cJoTRQcxZkNquDEghSY6KhFOXdAS+e9LeJiNK8T+8zd\nHQdLmXrDhv1/2yyrH1SsbdL8xBOc2ipOvVmVan9zL8Wh0lMSt3ipMme2hzIJ\nNmjqlIdh1dK/uJF3QcOMsyDlsa3Ra6jCtBTC2fgZWM2VG8AxdgV8CBoNX79S\nNa/wXUfY+AveixvvXHo0nD4XJo/WVIVYFqhM0Q4BSH9DeYHLbrPVBf3AGs10\nSiyzqzZ7YKQ2a7QCfvrLBtUro/YBgu0TWFFsAwqc0UH2GuW06Cu7b5uoKyc9\n4+rlNfXvBD0FJVw0w/3OB4RjT/Y/StY9tldvGuPcEj80WlzbXMO6RQNwpEli\nS/wPceAF/hDAdW3SCdYRhSI08lfToY/C+H4RUVExwsgzxW/shuUvDIrE8uD1\nJZsc\r\n=w3RA\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"f9c677b8b37989a6466372277fb312dc8d48e01f","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.13.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.7.0","dependencies":{"tar":"^6.0.1","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^3.0.0","chownr":"^1.1.2","mkdirp":"^1.0.3","rimraf":"^2.7.1","minipass":"^3.1.1","lru-cache":"^5.1.1","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.0_1581989628316_0.35215341493957464","host":"s3://npm-registry-packages"}},"12.0.4":{"name":"cacache","version":"12.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@12.0.4","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"668bcbd105aeb5f1d92fe25570ec9525c8faa40c","tarball":"http://localhost:4260/cacache/cacache-12.0.4.tgz","fileCount":29,"integrity":"sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==","signatures":[{"sig":"MEQCIDWoCDe0i1xVTIb04jB9XzIsmA84pYO1GlTicCPQ7niIAiA4quu5YiGDUZUoL+lFyvnMVVVqNU72MqLQJoJUu1pf/A==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115357,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeVLTCRA9TVsSAnZWagAAvqkP+QGEXsbyzFeaxv8Qv+TB\n8AAXsonmPOk9S+nphs2l4VZJdtEF/EpFXdiaLghALtZ4aWIYacjGklZj47oi\n+MwQSSpPpst7Wla0nCt2fq7Ejm1lVtaVYedk9WwEZKg4hdOTXoy23aKOtnYg\nlHnm/0p1F4/GNNearPtNI/T7drvNyOLYSkkEaRaH5+EVau5fkGF+o9CKVYJj\nCl9gYu+3/S2drDAf+9gYHEOOirN7Hwbx/S18j3M0E8yByrTbtYzUT3G++4ww\nqnsUwcYseQMTbqpn2ogJjNpBmzePJ17K+3Gd49NWk3nTqA+1sILTRcV4Bmfm\n2OImnazGU8KRUz/o/2yhYn1spdWrqzlD5NSuuYIu4lb/kTGN6ZhUYKsYbnx7\nbPM0J6CaagmL2GR97JLELGeMFl4qYYhWR5dn1S4lXHECnZuzhpndqNdE+BAn\nwsBjUvj7xVrzYFhQC18C/t/2tAqNevOF4yhtNQLNS3WCog0vC15F40h4N3wx\n1l7PsYNhe5zSQjWEF7jypi19HqdVfqD1EWESntGPcAedEUdB7+7YHW0ciCob\nwphqxKj7Yeo0AITk20MF24SNDmeAWf8yyYW0uEH8bYcAnRIBGHuuQWOzP5jj\nbnJvUh9MCSKQyqpwH2KzVAGLLfejoFUuI3s5tk++ZWFb6e4NVjuyq8+jCtVG\nEASj\r\n=PNlN\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","config":{"nyc":{"exclude":["node_modules/**","test/**"]}},"readme":"# cacache [![npm version](https://img.shields.io/npm/v/cacache.svg)](https://npm.im/cacache) [![license](https://img.shields.io/npm/l/cacache.svg)](https://npm.im/cacache) [![Travis](https://img.shields.io/travis/zkat/cacache.svg)](https://travis-ci.org/zkat/cacache) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/cacache?svg=true)](https://ci.appveyor.com/project/zkat/cacache) [![Coverage Status](https://coveralls.io/repos/github/zkat/cacache/badge.svg?branch=latest)](https://coveralls.io/github/zkat/cacache?branch=latest)\n\n[`cacache`](https://github.com/zkat/cacache) es una librería de Node.js para\nmanejar caches locales en disco, con acceso tanto con claves únicas como\ndirecciones de contenido (hashes/hacheos). Es súper rápida, excelente con el\nacceso concurrente, y jamás te dará datos incorrectos, aún si se corrompen o\nmanipulan directamente los ficheros del cache.\n\nEl propósito original era reemplazar el caché local de\n[npm](https://npm.im/npm), pero se puede usar por su propia cuenta.\n\n_Traducciones: [English](README.md)_\n\n## Instalación\n\n`$ npm install --save cacache`\n\n## Índice\n\n* [Ejemplo](#ejemplo)\n* [Características](#características)\n* [Cómo Contribuir](#cómo-contribuir)\n* [API](#api)\n * [Usando el API en español](#localized-api)\n * Leer\n * [`ls`](#ls)\n * [`ls.flujo`](#ls-stream)\n * [`saca`](#get-data)\n * [`saca.flujo`](#get-stream)\n * [`saca.info`](#get-info)\n * [`saca.tieneDatos`](#get-hasContent)\n * Escribir\n * [`mete`](#put-data)\n * [`mete.flujo`](#put-stream)\n * [opciones para `mete*`](#put-options)\n * [`rm.todo`](#rm-all)\n * [`rm.entrada`](#rm-entry)\n * [`rm.datos`](#rm-content)\n * Utilidades\n * [`ponLenguaje`](#set-locale)\n * [`limpiaMemoizado`](#clear-memoized)\n * [`tmp.hazdir`](#tmp-mkdir)\n * [`tmp.conTmp`](#with-tmp)\n * Integridad\n * [Subresource Integrity](#integrity)\n * [`verifica`](#verify)\n * [`verifica.ultimaVez`](#verify-last-run)\n\n### Ejemplo\n\n```javascript\nconst cacache = require('cacache/es')\nconst fs = require('fs')\n\nconst tarbol = '/ruta/a/mi-tar.tgz'\nconst rutaCache = '/tmp/my-toy-cache'\nconst clave = 'mi-clave-única-1234'\n\n// ¡Añádelo al caché! Usa `rutaCache` como raíz del caché.\ncacache.mete(rutaCache, clave, '10293801983029384').then(integrity => {\n console.log(`Saved content to ${rutaCache}.`)\n})\n\nconst destino = '/tmp/mytar.tgz'\n\n// Copia el contenido del caché a otro fichero, pero esta vez con flujos.\ncacache.saca.flujo(\n rutaCache, clave\n).pipe(\n fs.createWriteStream(destino)\n).on('finish', () => {\n console.log('extracción completada')\n})\n\n// La misma cosa, pero accesando el contenido directamente, sin tocar el índice.\ncacache.saca.porHacheo(rutaCache, integridad).then(datos => {\n fs.writeFile(destino, datos, err => {\n console.log('datos del tarbol sacados basado en su sha512, y escrito a otro fichero')\n })\n})\n```\n\n### Características\n\n* Extracción por clave o por dirección de contenido (shasum, etc)\n* Usa el estándard de web, [Subresource Integrity](#integrity)\n* Compatible con multiples algoritmos - usa sha1, sha512, etc, en el mismo caché sin problema\n* Entradas con contenido idéntico comparten ficheros\n* Tolerancia de fallas (inmune a corrupción, ficheros parciales, carreras de proceso, etc)\n* Verificación completa de datos cuando (escribiendo y leyendo)\n* Concurrencia rápida, segura y \"lockless\"\n* Compatible con `stream`s (flujos)\n* Compatible con `Promise`s (promesas)\n* Bastante rápida -- acceso, incluyendo verificación, en microsegundos\n* Almacenaje de metadatos arbitrarios\n* Colección de basura y verificación adicional fuera de banda\n* Cobertura rigurosa de pruebas\n* Probablente hay un \"Bloom filter\" por ahí en algún lado. Eso le mola a la gente, ¿Verdad? 🤔\n\n### Cómo Contribuir\n\nEl equipo de cacache felizmente acepta contribuciones de código y otras maneras de participación. ¡Hay muchas formas diferentes de contribuir! La [Guía de Colaboradores](CONTRIBUTING.md) (en inglés) tiene toda la información que necesitas para cualquier tipo de contribución: todo desde cómo reportar errores hasta cómo someter parches con nuevas características. Con todo y eso, no se preocupe por si lo que haces está exáctamente correcto: no hay ningún problema en hacer preguntas si algo no está claro, o no lo encuentras.\n\nEl equipo de cacache tiene miembros hispanohablantes: es completamente aceptable crear `issues` y `pull requests` en español/castellano.\n\nTodos los participantes en este proyecto deben obedecer el [Código de Conducta](CODE_OF_CONDUCT.md) (en inglés), y en general actuar de forma amable y respetuosa mientras participan en esta comunidad.\n\nPor favor refiérase al [Historial de Cambios](CHANGELOG.md) (en inglés) para detalles sobre cambios importantes incluídos en cada versión.\n\nFinalmente, cacache tiene un sistema de localización de lenguaje. Si te interesa añadir lenguajes o mejorar los que existen, mira en el directorio `./locales` para comenzar.\n\nHappy hacking!\n\n### API\n\n#### Usando el API en español\n\ncacache incluye una traducción completa de su API al castellano, con las mismas\ncaracterísticas. Para usar el API como está documentado en este documento, usa\n`require('cacache/es')`\n\ncacache también tiene otros lenguajes: encuéntralos bajo `./locales`, y podrás\nusar el API en ese lenguaje con `require('cacache/')`\n\n#### `> cacache.ls(cache) -> Promise`\n\nEnumera todas las entradas en el caché, dentro de un solo objeto. Cada entrada\nen el objeto tendrá como clave la clave única usada para el índice, el valor\nsiendo un objeto de [`saca.info`](#get-info).\n\n##### Ejemplo\n\n```javascript\ncacache.ls(rutaCache).then(console.log)\n// Salida\n{\n 'my-thing': {\n key: 'my-thing',\n integrity: 'sha512-BaSe64/EnCoDED+HAsh=='\n path: '.testcache/content/deadbeef', // unido con `rutaCache`\n time: 12345698490,\n size: 4023948,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n },\n 'other-thing': {\n key: 'other-thing',\n integrity: 'sha1-ANothER+hasH=',\n path: '.testcache/content/bada55',\n time: 11992309289,\n size: 111112\n }\n}\n```\n\n#### `> cacache.ls.flujo(cache) -> Readable`\n\nEnumera todas las entradas en el caché, emitiendo un objeto de\n[`saca.info`](#get-info) por cada evento de `data` en el flujo.\n\n##### Ejemplo\n\n```javascript\ncacache.ls.flujo(rutaCache).on('data', console.log)\n// Salida\n{\n key: 'my-thing',\n integrity: 'sha512-BaSe64HaSh',\n path: '.testcache/content/deadbeef', // unido con `rutaCache`\n time: 12345698490,\n size: 13423,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n}\n\n{\n key: 'other-thing',\n integrity: 'whirlpool-WoWSoMuchSupport',\n path: '.testcache/content/bada55',\n time: 11992309289,\n size: 498023984029\n}\n\n{\n ...\n}\n```\n\n#### `> cacache.saca(cache, clave, [ops]) -> Promise({data, metadata, integrity})`\n\nDevuelve un objeto con los datos, hacheo de integridad y metadatos identificados\npor la `clave`. La propiedad `data` de este objeto será una instancia de\n`Buffer` con los datos almacenados en el caché. to do with it! cacache just\nwon't care.\n\n`integrity` es un `string` de [Subresource Integrity](#integrity). Dígase, un\n`string` que puede ser usado para verificar a la `data`, que tiene como formato\n`-`.\n\nSo no existe ninguna entrada identificada por `clave`, o se los datos\nalmacenados localmente fallan verificación, el `Promise` fallará.\n\nUna sub-función, `saca.porHacheo`, tiene casi el mismo comportamiento, excepto\nque busca entradas usando el hacheo de integridad, sin tocar el índice general.\nEsta versión *sólo* devuelve `data`, sin ningún objeto conteniéndola.\n\n##### Nota\n\nEsta función lee la entrada completa a la memoria antes de devolverla. Si estás\nalmacenando datos Muy Grandes, es posible que [`saca.flujo`](#get-stream) sea\nuna mejor solución.\n\n##### Ejemplo\n\n```javascript\n// Busca por clave\ncache.saca(rutaCache, 'my-thing').then(console.log)\n// Salida:\n{\n metadata: {\n thingName: 'my'\n },\n integrity: 'sha512-BaSe64HaSh',\n data: Buffer#,\n size: 9320\n}\n\n// Busca por hacheo\ncache.saca.porHacheo(rutaCache, 'sha512-BaSe64HaSh').then(console.log)\n// Salida:\nBuffer#\n```\n\n#### `> cacache.saca.flujo(cache, clave, [ops]) -> Readable`\n\nDevuelve un [Readable\nStream](https://nodejs.org/api/stream.html#stream_readable_streams) de los datos\nalmacenados bajo `clave`.\n\nSo no existe ninguna entrada identificada por `clave`, o se los datos\nalmacenados localmente fallan verificación, el `Promise` fallará.\n\n`metadata` y `integrity` serán emitidos como eventos antes de que el flujo\ncierre.\n\nUna sub-función, `saca.flujo.porHacheo`, tiene casi el mismo comportamiento,\nexcepto que busca entradas usando el hacheo de integridad, sin tocar el índice\ngeneral. Esta versión no emite eventos de `metadata` o `integrity`.\n\n##### Ejemplo\n\n```javascript\n// Busca por clave\ncache.saca.flujo(\n rutaCache, 'my-thing'\n).on('metadata', metadata => {\n console.log('metadata:', metadata)\n}).on('integrity', integrity => {\n console.log('integrity:', integrity)\n}).pipe(\n fs.createWriteStream('./x.tgz')\n)\n// Salidas:\nmetadata: { ... }\nintegrity: 'sha512-SoMeDIGest+64=='\n\n// Busca por hacheo\ncache.saca.flujo.porHacheo(\n rutaCache, 'sha512-SoMeDIGest+64=='\n).pipe(\n fs.createWriteStream('./x.tgz')\n)\n```\n\n#### `> cacache.saca.info(cache, clave) -> Promise`\n\nBusca la `clave` en el índice del caché, devolviendo información sobre la\nentrada si existe.\n\n##### Campos\n\n* `key` - Clave de la entrada. Igual al argumento `clave`.\n* `integrity` - [hacheo de Subresource Integrity](#integrity) del contenido al que se refiere esta entrada.\n* `path` - Dirección del fichero de datos almacenados, unida al argumento `cache`.\n* `time` - Hora de creación de la entrada\n* `metadata` - Metadatos asignados a esta entrada por el usuario\n\n##### Ejemplo\n\n```javascript\ncacache.saca.info(rutaCache, 'my-thing').then(console.log)\n\n// Salida\n{\n key: 'my-thing',\n integrity: 'sha256-MUSTVERIFY+ALL/THINGS=='\n path: '.testcache/content/deadbeef',\n time: 12345698490,\n size: 849234,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n}\n```\n\n#### `> cacache.saca.tieneDatos(cache, integrity) -> Promise`\n\nBusca un [hacheo Subresource Integrity](#integrity) en el caché. Si existe el\ncontenido asociado con `integrity`, devuelve un objeto con dos campos: el hacheo\n_específico_ que se usó para la búsqueda, `sri`, y el tamaño total del\ncontenido, `size`. Si no existe ningún contenido asociado con `integrity`,\ndevuelve `false`.\n\n##### Ejemplo\n\n```javascript\ncacache.saca.tieneDatos(rutaCache, 'sha256-MUSTVERIFY+ALL/THINGS==').then(console.log)\n\n// Salida\n{\n sri: {\n source: 'sha256-MUSTVERIFY+ALL/THINGS==',\n algorithm: 'sha256',\n digest: 'MUSTVERIFY+ALL/THINGS==',\n options: []\n },\n size: 9001\n}\n\ncacache.saca.tieneDatos(rutaCache, 'sha521-NOT+IN/CACHE==').then(console.log)\n\n// Salida\nfalse\n```\n\n#### `> cacache.mete(cache, clave, datos, [ops]) -> Promise`\n\nInserta `datos` en el caché. El `Promise` devuelto se resuelve con un hacheo\n(generado conforme a [`ops.algorithms`](#optsalgorithms)) después que la entrada\nhaya sido escrita en completo.\n\n##### Ejemplo\n\n```javascript\nfetch(\n 'http://localhost:4260/cacache/cacache-1.0.0.tgz'\n).then(datos => {\n return cacache.mete(rutaCache, 'registry.npmjs.org|cacache@1.0.0', datos)\n}).then(integridad => {\n console.log('el hacheo de integridad es', integridad)\n})\n```\n\n#### `> cacache.mete.flujo(cache, clave, [ops]) -> Writable`\n\nDevuelve un [Writable\nStream](https://nodejs.org/api/stream.html#stream_writable_streams) que inserta\nal caché los datos escritos a él. Emite un evento `integrity` con el hacheo del\ncontenido escrito, cuando completa.\n\n##### Ejemplo\n\n```javascript\nrequest.get(\n 'http://localhost:4260/cacache/cacache-1.0.0.tgz'\n).pipe(\n cacache.mete.flujo(\n rutaCache, 'registry.npmjs.org|cacache@1.0.0'\n ).on('integrity', d => console.log(`integrity digest is ${d}`))\n)\n```\n\n#### `> opciones para cacache.mete`\n\nLa funciones `cacache.mete` tienen un número de opciones en común.\n\n##### `ops.metadata`\n\nMetadatos del usuario que se almacenarán con la entrada.\n\n##### `ops.size`\n\nEl tamaño declarado de los datos que se van a insertar. Si es proveído, cacache\nverificará que los datos escritos sean de ese tamaño, o si no, fallará con un\nerror con código `EBADSIZE`.\n\n##### `ops.integrity`\n\nEl hacheo de integridad de los datos siendo escritos.\n\nSi es proveído, y los datos escritos no le corresponden, la operación fallará\ncon un error con código `EINTEGRITY`.\n\n`ops.algorithms` no tiene ningún efecto si esta opción está presente.\n\n##### `ops.algorithms`\n\nPor Defecto: `['sha512']`\n\nAlgoritmos que se deben usar cuando se calcule el hacheo de [subresource\nintegrity](#integrity) para los datos insertados. Puede usar cualquier algoritmo\nenumerado en `crypto.getHashes()`.\n\nPor el momento, sólo se acepta un algoritmo (dígase, un array con exáctamente un\nvalor). No tiene ningún efecto si `ops.integrity` también ha sido proveido.\n\n##### `ops.uid`/`ops.gid`\n\nSi están presentes, cacache hará todo lo posible para asegurarse que todos los\nficheros creados en el proceso de sus operaciones en el caché usen esta\ncombinación en particular.\n\n##### `ops.memoize`\n\nPor Defecto: `null`\n\nSi es verdad, cacache tratará de memoizar los datos de la entrada en memoria. La\npróxima vez que el proceso corriente trate de accesar los datos o entrada,\ncacache buscará en memoria antes de buscar en disco.\n\nSi `ops.memoize` es un objeto regular o un objeto como `Map` (es decir, un\nobjeto con métodos `get()` y `set()`), este objeto en sí sera usado en vez del\ncaché de memoria global. Esto permite tener lógica específica a tu aplicación\nencuanto al almacenaje en memoria de tus datos.\n\nSi quieres asegurarte que los datos se lean del disco en vez de memoria, usa\n`memoize: false` cuando uses funciones de `cacache.saca`.\n\n#### `> cacache.rm.todo(cache) -> Promise`\n\nBorra el caché completo, incluyendo ficheros temporeros, ficheros de datos, y el\níndice del caché.\n\n##### Ejemplo\n\n```javascript\ncacache.rm.todo(rutaCache).then(() => {\n console.log('THE APOCALYPSE IS UPON US 😱')\n})\n```\n\n#### `> cacache.rm.entrada(cache, clave) -> Promise`\n\nAlias: `cacache.rm`\n\nBorra la entrada `clave` del índuce. El contenido asociado con esta entrada\nseguirá siendo accesible por hacheo usando\n[`saca.flujo.porHacheo`](#get-stream).\n\nPara borrar el contenido en sí, usa [`rm.datos`](#rm-content). Si quieres hacer\nesto de manera más segura (pues ficheros de contenido pueden ser usados por\nmultiples entradas), usa [`verifica`](#verify) para borrar huérfanos.\n\n##### Ejemplo\n\n```javascript\ncacache.rm.entrada(rutaCache, 'my-thing').then(() => {\n console.log('I did not like it anyway')\n})\n```\n\n#### `> cacache.rm.datos(cache, integrity) -> Promise`\n\nBorra el contenido identificado por `integrity`. Cualquier entrada que se\nrefiera a este contenido quedarán huérfanas y se invalidarán si se tratan de\naccesar, al menos que contenido idéntico sea añadido bajo `integrity`.\n\n##### Ejemplo\n\n```javascript\ncacache.rm.datos(rutaCache, 'sha512-SoMeDIGest/IN+BaSE64==').then(() => {\n console.log('los datos para `mi-cosa` se borraron')\n})\n```\n\n#### `> cacache.ponLenguaje(locale)`\n\nConfigura el lenguaje usado para mensajes y errores de cacache. La lista de\nlenguajes disponibles está en el directorio `./locales` del proyecto.\n\n_Te interesa añadir más lenguajes? [Somete un PR](CONTRIBUTING.md)!_\n\n#### `> cacache.limpiaMemoizado()`\n\nCompletamente reinicializa el caché de memoria interno. Si estás usando tu\npropio objecto con `ops.memoize`, debes hacer esto de manera específica a él.\n\n#### `> tmp.hazdir(cache, ops) -> Promise`\n\nAlias: `tmp.mkdir`\n\nDevuelve un directorio único dentro del directorio `tmp` del caché.\n\nUna vez tengas el directorio, es responsabilidad tuya asegurarte que todos los\nficheros escrito a él sean creados usando los permisos y `uid`/`gid` concordante\ncon el caché. Si no, puedes pedirle a cacache que lo haga llamando a\n[`cacache.tmp.fix()`](#tmp-fix). Esta función arreglará todos los permisos en el\ndirectorio tmp.\n\nSi quieres que cacache limpie el directorio automáticamente cuando termines, usa\n[`cacache.tmp.conTmp()`](#with-tpm).\n\n##### Ejemplo\n\n```javascript\ncacache.tmp.mkdir(cache).then(dir => {\n fs.writeFile(path.join(dir, 'blablabla'), Buffer#<1234>, ...)\n})\n```\n\n#### `> tmp.conTmp(cache, ops, cb) -> Promise`\n\nCrea un directorio temporero con [`tmp.mkdir()`](#tmp-mkdir) y ejecuta `cb` con\nél como primer argumento. El directorio creado será removido automáticamente\ncuando el valor devolvido por `cb()` se resuelva.\n\nLas mismas advertencias aplican en cuanto a manejando permisos para los ficheros\ndentro del directorio.\n\n##### Ejemplo\n\n```javascript\ncacache.tmp.conTmp(cache, dir => {\n return fs.writeFileAsync(path.join(dir, 'blablabla'), Buffer#<1234>, ...)\n}).then(() => {\n // `dir` no longer exists\n})\n```\n\n#### Hacheos de Subresource Integrity\n\ncacache usa strings que siguen la especificación de [Subresource Integrity\nspec](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).\n\nEs decir, donde quiera cacache espera un argumento o opción `integrity`, ese\nstring debería usar el formato `-`.\n\nUna variación importante sobre los hacheos que cacache acepta es que acepta el\nnombre de cualquier algoritmo aceptado por el proceso de Node.js donde se usa.\nPuedes usar `crypto.getHashes()` para ver cuales están disponibles.\n\n##### Generando tus propios hacheos\n\nSi tienes un `shasum`, en general va a estar en formato de string hexadecimal\n(es decir, un `sha1` se vería como algo así:\n`5f5513f8822fdbe5145af33b64d8d970dcf95c6e`).\n\nPara ser compatible con cacache, necesitas convertir esto a su equivalente en\nsubresource integrity. Por ejemplo, el hacheo correspondiente al ejemplo\nanterior sería: `sha1-X1UT+IIv2+UUWvM7ZNjZcNz5XG4=`.\n\nPuedes usar código así para generarlo por tu cuenta:\n\n```javascript\nconst crypto = require('crypto')\nconst algoritmo = 'sha512'\nconst datos = 'foobarbaz'\n\nconst integrity = (\n algorithm +\n '-' +\n crypto.createHash(algoritmo).update(datos).digest('base64')\n)\n```\n\nTambién puedes usar [`ssri`](https://npm.im/ssri) para deferir el trabajo a otra\nlibrería que garantiza que todo esté correcto, pues maneja probablemente todas\nlas operaciones que tendrías que hacer con SRIs, incluyendo convirtiendo entre\nhexadecimal y el formato SRI.\n\n#### `> cacache.verifica(cache, ops) -> Promise`\n\nExamina y arregla tu caché:\n\n* Limpia entradas inválidas, huérfanas y corrompidas\n* Te deja filtrar cuales entradas retener, con tu propio filtro\n* Reclama cualquier ficheros de contenido sin referencias en el índice\n* Verifica integridad de todos los ficheros de contenido y remueve los malos\n* Arregla permisos del caché\n* Remieve el directorio `tmp` en el caché, y todo su contenido.\n\nCuando termine, devuelve un objeto con varias estadísticas sobre el proceso de\nverificación, por ejemplo la cantidad de espacio de disco reclamado, el número\nde entradas válidas, número de entradas removidas, etc.\n\n##### Opciones\n\n* `ops.uid` - uid para asignarle al caché y su contenido\n* `ops.gid` - gid para asignarle al caché y su contenido\n* `ops.filter` - recibe una entrada como argumento. Devuelve falso para removerla. Nota: es posible que esta función sea invocada con la misma entrada más de una vez.\n\n##### Example\n\n```sh\necho somegarbage >> $RUTACACHE/content/deadbeef\n```\n\n```javascript\ncacache.verifica(rutaCache).then(stats => {\n // deadbeef collected, because of invalid checksum.\n console.log('cache is much nicer now! stats:', stats)\n})\n```\n\n#### `> cacache.verifica.ultimaVez(cache) -> Promise`\n\nAlias: `últimaVez`\n\nDevuelve un `Date` que representa la última vez que `cacache.verifica` fue\nejecutada en `cache`.\n\n##### Example\n\n```javascript\ncacache.verifica(rutaCache).then(() => {\n cacache.verifica.ultimaVez(rutaCache).then(última => {\n console.log('La última vez que se usó cacache.verifica() fue ' + última)\n })\n})\n```\n","gitHead":"3379fe8b3bafe91de3afb4f138c4ed3bc24a9edd","scripts":{"test":"cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js","pretest":"standard","release":"standard-version -s","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish && git push --follow-tags","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.13.7","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.10.1","dependencies":{"glob":"^7.1.4","ssri":"^6.0.1","y18n":"^4.0.0","chownr":"^1.1.1","mkdirp":"^0.5.1","rimraf":"^2.6.3","bluebird":"^3.5.5","lru-cache":"^5.1.1","graceful-fs":"^4.1.15","infer-owner":"^1.0.3","mississippi":"^3.0.0","figgy-pudding":"^3.5.1","unique-filename":"^1.1.1","promise-inflight":"^1.0.1","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"publishConfig":{"tag":"legacy"},"_hasShrinkwrap":false,"readmeFilename":"README.es.md","devDependencies":{"tap":"^12.7.0","chalk":"^2.4.2","tacks":"^1.3.0","standard":"^12.0.1","benchmark":"^2.1.4","cross-env":"^5.1.4","require-inject":"^1.4.4","standard-version":"^6.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_12.0.4_1585009363459_0.1674006323773336","host":"s3://npm-registry-packages"}},"15.0.1":{"name":"cacache","version":"15.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.1","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"a200a2505aced2154aac9a2150111e6954a5926a","tarball":"http://localhost:4260/cacache/cacache-15.0.1.tgz","fileCount":24,"integrity":"sha512-k427rNJGgXeXmnYiRgKoRKOsF+HAysd4NSi3fwMlSWVoIgGt6Snp8oTNKRH6kjRkrM64aQyOVl5B9hxxV+vtrg==","signatures":[{"sig":"MEUCIFvT13hJhXIoo7x4IIQSTreQ+C+9kqmGEGRRAYMrRW2BAiEA5xQRKy78px3tlM7aVwPZvoftDe4ZWPcn9hkAmxcZprM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":128823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJep3SpCRA9TVsSAnZWagAA+wAP/1JO1xZfz6ZgCNLKpU+s\nW59tvXNvXqHSatX6MlWK7rsxGEq2OqwtDCwn1O2MH+rIdPK8jVH+1eU60PQ9\nU8Hrw39HG+2s1ib1+57x9D9H+vcHgSdvjSqFudI7nPWKUtkjAjwEVBpTTIqC\nVXRKitT4fEoXO0bizfFrHPTeuNl4hxO7SqLSAt2lkpnZbE/GgfBW60RQFc1S\n5roMdnszH1Wog5JFCK0hNXmkdUwgYOSGjUYRpR9tcWsc2Kn8msB9ThlmLq5K\n5y+OFOA2170Su5puPbJNMQzqVCj4wZDz+BH0zwX7leNEnLuE6667Uxr/El44\n1EYrwKn1Da76/hs6sjcNN7jeErvrSMi5dKIJlru9qyAkXT5EpSszBuvGzfEG\ntrNxT5fnOpJXovJoLE/1F60YPDh0tT9+nwBcXqnRu7GbNx14MVxUUQXN9+Yj\n+tAkNE0PytCKRaa//SJAZNvIOLuCL9z9Bm4Fs81n6kf6n5N+3dEI/uc2K6Se\n5LPRYIz4cFrUTpLggN+82GzWaKN5wXsk00SFHUB2pIBEqoxK4n5mxzjgiJQh\nbRPz7AhrjG3E85zsuYsPt4HGguG+++ZLIoH8wHus1O8jZe71jY5mwW4MPDF0\nN08L7zteDEoJT7dxyJDNcpYp/9cWN7HaHBWPDuvbR/RdK/XQ3/s0AIMx/tej\nNrLD\r\n=v9aM\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"14567c3047588938a54f77add7fb6f94214c7fa8","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.14.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.10.1","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^4.0.0","tacks":"^1.3.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^5.1.1","move-file":"^2.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.1_1588032680878_0.9783494568336131","host":"s3://npm-registry-packages"}},"15.0.2":{"name":"cacache","version":"15.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.2","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"e25391962f0477f9ba16acd68a8f301d2e84d2ab","tarball":"http://localhost:4260/cacache/cacache-15.0.2.tgz","fileCount":24,"integrity":"sha512-XVCLiqTL5KaVnNKIUyZ1rTwmPSFgC8LAeV+ZsQqulmFdDkcUF/4y7duJ+tz1TJv0ZRUOdHZtVew4Ztz6LtvijA==","signatures":[{"sig":"MEYCIQDY/OBZCbx4WblMO6oLkmlemsZDYJKYEHMAZlRfyPUBvAIhANKlpw3fQ9V7Mlol97tDNVCTUjdWc1y9Lr9mSjWqNS1n","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":129289,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJep3YNCRA9TVsSAnZWagAA/CYP/3TT0joYz9+vkRD6afX3\n4pmG7ftuSg6eBMvboATE9MfKMPX0fFP5nFmo3+QPwFjZsDNF7WC3LB+W8cZY\n1xbvK8wMatcUL4QKiqeF79+XNBvgRBKdl/C3TXxXIL+axXRWYPx/AG3kKmbK\nsk+1cZW99rPrLvN8elWdxaTrfkt3xfoZ0ViKOb6cITziPlwFK1MMzmmvYh21\n97q5E1wCeySY13iLgpY53LMpPoH3vO89/Uz5T55miOJPw8aDueQ3e2WjF27n\nQ4rp4pl7jjxtOcbz9w3bW8iVTq1zeGboy8+zH/6K5ht9Lqh++LxQ84YLZWdt\ne+7lOuotPkSWPhR+5fxz+581MWYcq8BrDmq1lcDBoB/G8G36qJBldT+MFYnB\nJ2NoWNm69uAbhXWLyvJxXkycW9OnFAOVHWP6YJfMTd8E7/JVD4TXEy6NpM6/\nn5Fk67GLY6XztJuC5SgL4tI+LPJKpNjH8pJeIp5kPOI0R4w4IDSQZkW6aVV8\nYHggkqUIwbjpia9dYFQ9h2SkDVQv0I/1PHykdAwLtrVMe/GoCsoLH4FL+QWe\n0J3HAUCA2fL4ZoBHQCioqduC1d39b+DwaIxjqT6TEGIz48h00Zp+cL8lKPwh\nI0IHmeJZb9+QzhaatUjQUVPdXOVOilFzb1KMCJRB4FrL3LSFVaQAKSkzpZ3i\nSBc7\r\n=EqCW\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"b954f2b1672cdd8f1a05883669f9a8e5e5891563","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.14.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.10.1","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^5.1.1","move-file":"^2.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2","move-concurrently":"^1.0.1"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.2_1588033037328_0.9525403729782369","host":"s3://npm-registry-packages"}},"15.0.3":{"name":"cacache","version":"15.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.3","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"2225c2d1dd8e872339950d6a39c051e0e9334392","tarball":"http://localhost:4260/cacache/cacache-15.0.3.tgz","fileCount":24,"integrity":"sha512-bc3jKYjqv7k4pWh7I/ixIjfcjPul4V4jme/WbjvwGS5LzoPL/GzXr4C5EgPNLO/QEZl9Oi61iGitYEdwcrwLCQ==","signatures":[{"sig":"MEUCIQCBEucisUTxMM/VALV0k24e598SdAVUXfs+cokp8elHZgIgFKxz7Izhs7K6XFhlFDdTW8yVMgUBRVdqpYbBxhAz+MY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":129488,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJep3aLCRA9TVsSAnZWagAApJAP/1Vx0j7hc7C8TL/NIJzr\nhFa7N+S/1iexWVrRtPQpuf9Kj6oxKmTj9VnMO/iJCjYMBWC1D2WQIyGvc7U3\nRkt3B6s++UVmxbM1JX/8OIN4dhK6PwzrYZQF2nUvYd7YJrN76obtysyfC5Pb\nPMB41ARNFIS0Z37rPSkH/kB8wAn4hF+xLUO9tzP+zb40uMMY7gf/l5iGDzSG\nZs8U92yYwB5cSkTqHiv8oPD6N8/2mpmUAXDEUa0JqDvHGtQFeUDtxCiWjWGW\nWgY32EL0Aer2Kiba2jMAbUtXrDcBvuCEiQKHaNyFfqCqhQ08vWlKdzfCqrNb\nEzqn2R5xM1peYkjrrwuy/cYwrehAMtGjW8/ySRssM++/cB/Jt+MMsQmcUL+w\nRaIkusNTNy5iZpDPnqB/3Iow0dnPhAiGubodMQq6bq+R7jNTxpHqt9C2cVso\nAvxrFvYs/PEjEBPhzEViBAgXpx3hBGq90MzAaCl9qODbAB5Jt7063GLJos37\nYMzpBxa4vH9+J1W7ZtjtJiXSqIFpNjqF7drIiVlfoFfzuv7tWThsw3kidSBS\niBlN3XY/Y1at/UMftZtDHvAcDmyV0gYVTmOOAUrFpeXhVg+aC/Ni8NPw1UBb\nnYVUDlmoCEj0FxtPqS4853Uc16QggSa1oPnb1V/Sa78q012/KlfrJZd9j2R6\nGdJa\r\n=tBCz\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"5ce07a7b194b94de273cfda63a9fcfba08517d8f","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.14.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"13.10.1","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^5.1.1","move-file":"^2.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.3_1588033163189_0.6261166999737149","host":"s3://npm-registry-packages"}},"15.0.4":{"name":"cacache","version":"15.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.4","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"b2c23cf4ac4f5ead004fb15a0efb0a20340741f1","tarball":"http://localhost:4260/cacache/cacache-15.0.4.tgz","fileCount":22,"integrity":"sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw==","signatures":[{"sig":"MEQCICXq1IPtOJWd1s4EIDQGapjP3h0ZlvhgnYNvKHjsGEWpAiAUeYAawVm/tUrm6ShTebeVEbJyehmgtxj1UzslUmjeHg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1uhgCRA9TVsSAnZWagAARdsP/3cDCbZiJUoFT8OjL9ME\nbg/6A4JeHMmchM0YNLjey2FhM96SjvMgCcLaBywDtKn87ItuZD4wP+3Env5b\n+NWHSXZrdfFkK4mNnNTNUn499YfZmV/dRbb5alUibDm1LbdjGMqyRghl+veE\neFIXzR/+Am3F902D0S8z0Ig08Rbrt/3NvuAxqfPDWZbO0X7Iy/F1YL7e48Oq\nwvXC2WNXHQ20JpsPgge5CDGZEZOm9+X5kDhCmDIXxKzgTanMaYnBz7GS4nFd\nGhy/5zmhwaW2g/xUTpOENaGjaZSqyWayRcvRYv3DsRFMnGJjlMKx6Kh8bWJc\npWGmc58z/uXCTD4AQi4vgBf5wNiT0zEUpVfWhXWGFcEI5ahJ6ZBhx+RDHDlV\nYTJ6SGB1Dt0v49opaytX9ptAAPL2kWXfYuq6eLDDTHLM10hofBsybGjEwzIF\nX0NUnRXQFUB+aF22rM7nKd+CAjp0GCw4hVv3nm+eXVIgI8QW7imTkNpJt1vt\nzmrAXfRQOOlrB+IxwLmcD3CCjL99BdsRsAqhpAZ3q8thL/Vkyvwyeg6y81cC\nZ/m/3t8AGWUHjA+G2MUyTb4uiQPbVhsV6UNara9Ka2SRirgo+WGPLNxPjAlr\nvV/CHikm29BNP2c2gGyHXntZrv8w5BMJ7Ex3ldDPnWLC8bE7/BlCcQ/pEBLh\n5Sti\r\n=l2vx\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"cb07554c1fe4fe2509a417f89890845747dbe47d","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.14.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"14.2.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^5.1.1","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.4_1591142495512_0.0986317365863143","host":"s3://npm-registry-packages"}},"15.0.5":{"name":"cacache","version":"15.0.5","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.5","maintainers":[{"name":"adam_baldwin","email":"evilpacket@gmail.com"},{"name":"claudiahdz","email":"cghr1990@gmail.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"isaacs","email":"i@izs.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"69162833da29170d6732334643c60e005f5f17d0","tarball":"http://localhost:4260/cacache/cacache-15.0.5.tgz","fileCount":22,"integrity":"sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==","signatures":[{"sig":"MEYCIQDOjiBohijNGmSjippumvasqOrEZM1IhUMC67RKqlWB3wIhAKBdF8TeQH7b+0vdC+MK/Q+np6F8yHhwR8z7osFJuyuJ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101214,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfCRDiCRA9TVsSAnZWagAA3OEP/2xU8xoGxnBmzg7xkslx\nhwlrEXdYkjmoDmAG21tnIRiJD4wlg97cXS/dCVtuy+zP1MHAl/2AgW78O1KG\n0aATiEaB5p+TurkBdM47kuRnKTF5Eq06hXE4PBRuXSKLyMT5t3pSza910JVu\nND3cx54o81GdoOC71XPIrlZIPe5fzn/msvbv+Cjn0O6m6FPIQ8UxPDv2Yl13\nPODTmXYRfVfbaXZy6AoWcusxli7oK6aPe5VN3gvh4gZZo6vlbWKnVFeAAEp5\nrJbU/nSa3TrQ8w4DpvmvU2pq9tp32CBAF1+3+8RgqQ1yCMco+xHJKdHNuBw8\nnvz15togFKmiF3LiWEKTryEaRG6b1YaAsE/UvCFdQHQO98ThZQHvwaVVQ65W\nYGxQTJQX2l9uzYIhYUsEOqkrIOGeycXWvpwEpUkWzJSQwC2cxa4EG1i8irbc\nkF+axrkeWsBOYeiCegZUvcPV0M7R274iYbdGPv6ROgWRj5itCWrf6mMlYKBF\nO/QuKHtuxyQBfxaM5JozrO6oyaE1sVk+0y856b9oYbo0G0QiWEvUS7M3dU7a\nRYp6bZRKNvtHo3F2C3nW2W3ENOrfy0esFyXJz0Y8fZr/DaL4JGE5Hh7kSPrl\nZx4qJeTkaiqJZ3bBXwXyZs6ly5aisQHziam04wZM1aVs0y1MYOcs19LBaUBA\nSv2B\r\n=i2T6\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"1e5d25448f39194f1217047e08613fd726766911","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"6.14.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"14.2.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.5_1594429665586_0.7582732826078691","host":"s3://npm-registry-packages"}},"15.0.6":{"name":"cacache","version":"15.0.6","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.0.6","maintainers":[{"name":"gar","email":"gar+npm@danger.computer"},{"name":"isaacs","email":"i@izs.me"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"65a8c580fda15b59150fb76bf3f3a8e45d583099","tarball":"http://localhost:4260/cacache/cacache-15.0.6.tgz","fileCount":22,"integrity":"sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==","signatures":[{"sig":"MEUCIQDrBAzO/niSUqnY3Gd1VnUw7I9YSKdMOiAyOfwIu4PClwIgH5rOg+jR7ckJYc2SFh6esuFrgZZo17FxI1YxaHn3mm4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101299,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWMVxCRA9TVsSAnZWagAAn1oP/2AFhHClE4AsJ2QNKRu+\n6EXyUj/82b1loPaGKMxOn8M+hpxZi+1gEl0g6exxIN+VizBdtXgA5GdyDSIL\nI0vuTYOCspWjA4hXKz6blCcwTBg3jRA9Wm6t/pwCvDntQWGvFcqrG09ea8Or\nj13ijLlLFDlMYK1bYeWrmF2EbJ0R2TYD2wxjYnyqBtTpLuDipwsbtXPcWVqI\nKMu+/CIQr4x1hkKcRwvXbf1i0Ah6rpWEzf/N9KjH+U4EqpJbl30+X7mJjatx\nEsVJ63dLu4Bv1ejHoji/heT1IsCUi8qvR6ciQN02GSiP7pbXysePeYY8f5jF\nnOg+mYR3edH6UBF9H2gDq4QXOS+j7VCsyaZPL7in5xA/PJqXUTdj6gJtn0lW\n3dtPN5ZDcg1/kJLIlTMkrx4mbBf8S/yA0EjgsSlG3Bmj6uphFGep2aBmCDrl\nmW33/0d7Q3in+3QqWoN8mHGvNhsuQpABMPERHdrPAitGR+E5wf+TlP76F2tL\n3u8v7NKnnEWAdWQoydWTbXtZD2RAggQWN5cOLe2thd/MTv3Zq2CbnP9SGCIN\nODGgVXJuOx2wuHErwS8MYRwbdzbAw+Hr694AZ6Ac88DZHwGeOAROpgswD1Ya\nvqJ+QFsZWM+EgTQ5Cc1qrX+x59dt7dTMrOtBkPz6RFDjFk2c0R/zziaVIcCH\nXOHP\r\n=nA5h\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"0cea105c7bf11014d39363efd4b73f4fd53f0a9b","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"7.6.3","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"14.16.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^14.10.6","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.0.6_1616430449031_0.2831633711080599","host":"s3://npm-registry-packages"}},"15.1.0":{"name":"cacache","version":"15.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"Kat Marchán","email":"kzm@sykosomatic.org"},"license":"ISC","_id":"cacache@15.1.0","maintainers":[{"name":"gimli01","email":"gimli01@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"isaacs","email":"i@izs.me"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"}],"contributors":[{"name":"Charlotte Spencer","email":"charlottelaspencer@gmail.com"},{"name":"Rebecca Turner","email":"me@re-becca.org"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"164c2f857ee606e4cc793c63018fefd0ea5eba7b","tarball":"http://localhost:4260/cacache/cacache-15.1.0.tgz","fileCount":21,"integrity":"sha512-mfx0C+mCfWjD1PnwQ9yaOrwG1ou9FkKnx0SvzUHWdFt7r7GaRtzT+9M8HAvLu62zIHtnpQ/1m93nWNDCckJGXQ==","signatures":[{"sig":"MEYCIQDwt9AhuSeRpVb3KSyY7DNE8wc+6HqRA/c3v5tnTgUIYwIhANRYPyryb3R0/1zApdIe7DTpeXQNtwd/Kzmiizomj+rY","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":75205,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgpTMrCRA9TVsSAnZWagAAEsUQAIpj1n1QTTr3jxNMxhmv\nDR+cFD4/zpRkeFjVckrls5dqFLxPkI8Ka8uuNCplDN41UqLFIipcuSWkTk57\nVFk1ppJTVGKtWrQbPEqkESMlm2/IXBt1ehhcBMbwlGC02ipz23tjYL/KvnX0\nr5m9ZruUUfv5lPqUp6x16sFx9NbFl1ppe3IO2v27z3EpmAqXYmvHr77RGHBi\ngbG4TQa3dK7snPFsNdHuL5nXwO2P3Oj9FXJD0JQcKtA5s2xHEx/LivehpQDM\nfNDfhERfesXEX3RNzf62bo2EB9qYxYY06mXjhzhsQgcjVACbwz6+jQXShVYJ\nLOTTcDdCFQLWRcaO/B3zJYdgq5RBz3zWUp9MpvuB3jImjhGWFxwIb4Tjej0C\nQQ0dAgciMrckTbcd7adyL07DDLy/EiGZ5JmSTJZnM8kXiuPBQmksXCxd/cgn\nBwgEvu2DuTj6Kmh9LZr6c/5mcvZKedIeVgbr44wD/VlDt71dvaKwz9vHHos4\ngwvsXiXCw/oMo8iy5SKaSEydw2X4B0gzAjhXJwD3f3xpJEMxrUO8QMsKi4/j\nNXkeTP4GN8vxYD28apRBsV/lPywzdhpoTPMvP3qMANh2mzXtuOQA6TOjRRjN\nZLYC+r3apAG+z5tlOpJIXvWlr0ueSp8UF7cxvNRI9PJ9EuPBnqIG8CcHY9S8\n8GU7\r\n=AZlm\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"26dda5a1c9627e8ad1449e323ad36f2db4a497fc","scripts":{"lint":"standard","test":"tap","release":"standard-version -s","coverage":"tap","posttest":"npm run lint","benchmarks":"node test/benchmarks","prerelease":"npm t","postrelease":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"7.13.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"16.0.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.0.0","tacks":"^1.3.0","standard":"^14.3.1","benchmark":"^2.1.4","require-inject":"^1.4.4","standard-version":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.1.0_1621439274974_0.7776469708940608","host":"s3://npm-registry-packages"}},"15.2.0":{"name":"cacache","version":"15.2.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"license":"ISC","_id":"cacache@15.2.0","maintainers":[{"name":"gimli01","email":"gimli01@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"isaacs","email":"i@izs.me"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"73af75f77c58e72d8c630a7a2858cb18ef523389","tarball":"http://localhost:4260/cacache/cacache-15.2.0.tgz","fileCount":21,"integrity":"sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==","signatures":[{"sig":"MEYCIQDJ7HhLi3B3o4AUu4fM248uEMQgc7cPt7l413nYHABq0gIhALqrRUyllAVUoCJlemGtWzNACl8DuyOoLWLCk7ET21xU","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76631,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrPsDCRA9TVsSAnZWagAA8pIP/iHbe/smP+5CjiwWd6bt\nm9CwZLyo/NiWWBv0qlqATstmqXnerF+PmB2SeOaFTiciLBYFCQKPfIWu9dsS\nyhQN0EMxYUSNzx6kCmqlSDc/9jdWhOeJ+V4p2A9JDgGfhjT199QI7/8FSZEG\nUhFMrbz3hFdhWpZAfVNb7XFZ0ZREjufCk2CLqDQ4VbWdQ772hknedUdKIEZy\neH+CAO2TSiHzjcdgzaGbIxpQorM+y5h/05/Xzlv0HbaLDe3uDINQ9E1o7hSQ\nurE2I1jKWT9SJoTq/jUC0uvEPgWfxK0d6zKme+WYNNrQCXaSHr+oUDVA09Em\nq/LOfqAqTWPuaDyxiV6pOPWr8X6ZcNL0yaKUwjCYqtkRnJSfizAi/gIliqOp\nLYBCPuxo2i57LIuMWZumPNRlF9sM2Nz63tQEsoQSppvrkZJmCIWGrHvUbMcr\nCRE+2kn0RFR9EgCrLvhZfvF4EUD3JCIXCpc8W71iLs+hQBXCfbx6ml2pFS0B\nGdqbfLT4NT2nGwbvS7tnZUeGPc4NBBolN9xaGJUJueryl8oPcBtj6B4/R8A/\nJbAGwO1cm0ntTxO+gtbvyY79IYveyJHE5ILE9gZDtsvAVTPylOfvmdyRv+t/\ncDPf70Q4hx7btOIe1+ue82k/+DyJ2aG8LH4bV5vEadDVCbiyRPCrGsZ32doA\nnMTw\r\n=/wHH\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"f43aed6ce0b33a13007a675b5b39b0104a304f1d","scripts":{"lint":"npm run npmclilint -- \"*.*js\" \"lib/**/*.*js\" \"test/**/*.*js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postsnap":"npm run lintfix --","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"7.14.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"16.0.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.0.0","tacks":"^1.3.0","benchmark":"^2.1.4","@npmcli/lint":"^1.0.1","require-inject":"^1.4.4"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.2.0_1621949187372_0.9529560729182487","host":"s3://npm-registry-packages"}},"15.3.0":{"name":"cacache","version":"15.3.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"license":"ISC","_id":"cacache@15.3.0","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"isaacs","email":"i@izs.me"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb","tarball":"http://localhost:4260/cacache/cacache-15.3.0.tgz","fileCount":21,"integrity":"sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==","signatures":[{"sig":"MEQCIHVjjZL+4iYdr/5IGpJRHcU/xoSbEHWB+YPz1hly5ZAWAiAY0kMzII7pqNDvCBXFBuDD3xIgCyJdisw+jnqo+vSSgQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76264,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ9GmCRA9TVsSAnZWagAAzP0P/16cO+koLcRkKtrw0kBf\nOQj1j2T0Z4DMntv7NBKjQseEtfOKeY2+uKzQVJsJSPl87yHhzF2raa3L9rTD\nDAKI4vgOnVhGuKB8OHeU4N8um5xBAC4b84dBGsfWD3PuxGXEzU2IjjhkYdkW\naERVgoGocpENWdzdwpBQQr61tr2KA5Q2Len+JM/MMCljqo2Rc9WUPpW7uQiH\ner4eNpkSM2DkXXQjcfkEJ9H5fuTQTdrD/wJV43xRQFHGLZOYcskLTB6A8OUz\nryjVzhjutR4IhnomkpTDxWPGLnMK/oSOUuTb6kUCIQq2wwt/aWgxP5LJUeon\n2nrePNp5t6R9pt7gKW1LVeIm4YMyk4JpjdxsoJ7JPWc3egravArqzo4mls+G\nZbFdV9FmfK3uXlcSJ1bSCz3QcgwEGxFZ0znjNxE+htHKsYkg342vmdzQUYA6\nJyKw0BcG9fa0ChMWPiNoPbVko8aaOG4Jn59BlUrjEqKHAz4KqbvrhwZk+I25\nbLSqXQVO0KzsUIDge6fOykorutnsxZm1dQoMUw/gVs12IV6OvMRIEHE9WlP4\nVX6q7yg/DitSmhDv77xpyF2gnrozLyN1ch2queB4ArDfCQrHXb+fVXVKxFCz\nRuw6L1mYMcmU3VuXi5oXgm6zI8mKyx+VT+5CdVtnIW1sFYQEwCkrwgT2dmka\n0GJB\r\n=XcB9\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">= 10"},"gitHead":"597e833e242c6d33017f9b01848b3646d455ceef","scripts":{"lint":"npm run npmclilint -- \"*.*js\" \"lib/**/*.*js\" \"test/**/*.*js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postsnap":"npm run lintfix --","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"nlf","email":"quitlahok@gmail.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"7.20.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"_nodeVersion":"16.5.0","dependencies":{"tar":"^6.0.2","glob":"^7.1.4","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.3","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","@npmcli/fs":"^1.0.0","fs-minipass":"^2.0.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.0.1","minipass-pipeline":"^1.2.2"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.0.0","tacks":"^1.3.0","benchmark":"^2.1.4","@npmcli/lint":"^1.0.1","require-inject":"^1.4.4"},"_npmOperationalInternal":{"tmp":"tmp/cacache_15.3.0_1629999526779_0.1372406633549923","host":"s3://npm-registry-packages"}},"16.0.0":{"name":"cacache","version":"16.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.0","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"891149a9f9b0c8bbe6cd84d8ac246d6cf5ff429e","tarball":"http://localhost:4260/cacache/cacache-16.0.0.tgz","fileCount":19,"integrity":"sha512-pMX6sqJSlGpxCM257by5syifGb7zH6C30CaJXeGXqmKNrHKqvMmwM8KgKmsZcUAsnNQkt7WvENH2Kl53RpFQuA==","signatures":[{"sig":"MEUCIQDvJOboMqZa2DJv+zCG8992QNyNx3YD3upSBNCY48Z9tQIgafJDw7iv5DS1Dh5+GSvm/j+IHiNP1hYWn9s2MHbSCig=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiL6ODACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr9VQ//aAsgdmba9zKLuSWXVq/Fg4AkmvjPTK3Sb7USAGK+EsTo+Ffi\r\n+wh6qyDwn/hjmRKdPvqJOlW5iBmS1ULRV4TMfZ5H0xVrmq2cNKGP9tjkgtyl\r\nF0ey+LdXtjFZ6LH7f6cru4ovIlttyDnAybwfIxfvnFDOZrwQikKwVg7r01CM\r\nuLVSn4jOJ/ZGY4yM+hUfGZ58mxERTAuG2cW6ZbGXBmFu8cn/NY2ulrqm72Ey\r\nUl8WSVYlCHX/1ARRL1yr9I7ikKknav+gaq9zalJOiQr6rIq7un2SpzG6WOYE\r\na/7UIzM2FK3WmaWRbwTI+NRMXkE0zY/xVPuHgNiOyyj1jQZOKaOCyD64jbqY\r\nkARuN1DM96CUiafJU2detACGDLLHcwF73/DKNRFKQQV01UJCDUkS4BGcxcwF\r\nq/XW+C3IaAk+NTHeLVAXU3a0pwIQGNOvknB3uNMBeNdaJw0pzqUqTqfOB0pm\r\nNgIkukIMQtxUylt0lFh6F81n94Roa3j7N2m755mRDr8pZHl/1Wi5l4mDH4tZ\r\nvBPZ6oRFCkoyj/3VHoT4Xycsokx0IvWHZu1jlb+1umgl+9+Cx2Q/qIATO8sH\r\ngjQ+75q+/8TlHDIyMyu/vic42y0+GyCRF8FAUshWwyPmH8nKIJNAdW75pZXb\r\nfmzpLT/HpUyCTnjlseHujrs7KV2/VsW50IY=\r\n=9vtZ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16"},"gitHead":"a1fadd11b6ad9c2dca6f884322dd7d244a0c20ce","scripts":{"lint":"eslint '**/*.js'","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"npm-template-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-copy":"npm-template-copy --force","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.5.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"2.9.2","windowsCI":false},"_nodeVersion":"16.14.0","dependencies":{"tar":"^6.1.11","glob":"^7.1.4","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.1","lru-cache":"^6.0.0","@npmcli/fs":"^1.0.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.1.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.0.0","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"^2.9.2"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.0_1647289219056_0.18032209704285562","host":"s3://npm-registry-packages"}},"16.0.1":{"name":"cacache","version":"16.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.1","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"bad1d14963d9851840da3dd6c4db3b6a3bdb585d","tarball":"http://localhost:4260/cacache/cacache-16.0.1.tgz","fileCount":19,"integrity":"sha512-tHPtfdZDqQpZ15eaEZeLspIqS5mK5fOBDZi6AjuqaIi53QNVXH3dQv6uKT3YuUu6uxV/8pjU9in0CoJ8fgaHqw==","signatures":[{"sig":"MEQCID3qgEuTfF2eeAKMKkFz1qlSk5J1YiV1IEcWVvkumZuMAiBp48wK0Y0BuR18jxZzKh/0ZFhML4WYHMLTggf4Zl87qw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76978,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMPYyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoVLQ/9Eh77dMoOVbmbMiCyJ9XR+kODvPqxlg9l64tgHsDT5BDnKjby\r\nZORsh7YzL/mFHc9IlsMxPJjCLmPXFLv/2b6bVvb9kbEuCmZktOS5fiMucDq5\r\nBeif4rBP1O/94PS9DS2jY+IdPyJ6hND7DXzQe4kUzYWphoV5LasDnkrUkizK\r\nniipWWfLjzaDvBNs3aHcKbaYTyqRVMjV83o89hJAbXz3ekY4N1Pe6b1MQjjX\r\nzw/b/Morte2ZUBbB/+jtJ0Jz+lj+sv1kCZTMllmbNj/eJ/U+EZAFP2bMrbaZ\r\nQBua/yhMsqPcYmuoqDMG/S5avDF/gcduqpw7pKyfXkpghkbEZ9nAjdVuAITW\r\n2lBgv/yVgljyXL00mbxuHhgpZUo+i0VF2oShGCZS5NrJXcsbspSSEnwSxJ10\r\ngO8R72Hs1rQadDTPJ1+kqd+1Ic2WJyHs1tl9okh0ACtFv8VoXrV2wKiuR/Hm\r\nboKFCwMIeMjhiyscNznTF0mOI7ZiDSkAkk3H6cLaN22Wex6BxEccH9cdY0PN\r\nq/7/VWyxfjwRmFYcrxLk3c4NWWcFLY+Le2inf8zHbxoxBwRSZUYj1x4iO4TW\r\n74Q/tAX7lPu0M9kBPUdURfwfgqHi217UxKtDS2hOcqx6Y+ewFGlQFOg1uAKM\r\nWwqjh1VdrAtOvKqDMY+/G+PZ4J2uKrl3Y9s=\r\n=TXwu\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16"},"gitHead":"a6041bd8daf645651b8c8e1553ab8aad2e73306d","scripts":{"lint":"eslint '**/*.js'","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"npm-template-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-copy":"npm-template-copy --force","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.5.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"2.9.2","windowsCI":false},"_nodeVersion":"16.14.0","dependencies":{"tar":"^6.1.11","glob":"^7.2.0","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.5.1","@npmcli/fs":"^1.0.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.1.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.0.0","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"^2.9.2"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.1_1647375922044_0.4553262213263707","host":"s3://npm-registry-packages"}},"16.0.2":{"name":"cacache","version":"16.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.2","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"b18d630b707554d7d5ce96f53bfe845233c84933","tarball":"http://localhost:4260/cacache/cacache-16.0.2.tgz","fileCount":19,"integrity":"sha512-Q17j7s8X81i/QYVrKVQ/qwWGT+pYLfpTcZ+X+p/Qw9FULy9JEfb2FECYTTt6mPV6A/vk92nRZ80ncpKxiGTrIA==","signatures":[{"sig":"MEUCICkqIOYX5z+E/CoUgexechF4TpAxVEaB2CBdZujI1MHdAiEArJVPxOrxMWNuCIzVlL6cr+XBzZHNMjS6FBtwJq3fQRg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76978,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiM38JACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoiCBAAj3QJjlSYGWjcafex+twbUXJ6abQtLfjM9KdI8fgWJRhlBplC\r\nSz3n9BxbWUR4wingXR1jMEoFHIPDqElVfxtPnb8yLKdihlgsrjg+FwgWFYZE\r\neqTJIbLl/jBMUbNPA51ooJF6d/UiLcA+j8evbKxU4+o/lqy5SUayAP0mEQXC\r\nGFgjp/lZZ13q3MZiJ8z7nJzbeFnJ+CwZnn2Uk1EG5/20vO1F7je7QUJ1d8r1\r\nVz1ss0yNn/fUjgKjQQ1ag4Ikeal31ujZU1bfagq8Fso2KTpJCDxXjjf8rErg\r\nOVOjDZEwVKZsJqtVzKDyP4M2FyOk5VDQDn0VYhaOagcjbKlgWj3LyrLPxzbs\r\n5N+QWFTOY/Hr4XiZu9l0XVeEZQ0JXSlRzVzj4kV3pBt4RUpjTkK/B5jnN4hm\r\njRNYiNHQhOSMTjsXEC5f5KMMufWxZprmy3vepFhw53ez7LZum0U6i7vSox78\r\n1zoopuBMHVwVDx63fKneUM/ZnIzg6PLcbJ+jJM6WCURu9Oo0mQf6TNX1/FAu\r\nUsJpPeWkT0m0LA4bHEKBROWnW5XBuY4BsCSPVU0KCxps2l+PThFgC6DelWpO\r\nw0rQ7Dq2MQ/JiYKDZLY3eIgV5DCibcHtxDEtkQHH/ZxjLKqM0m7Ju/brkI84\r\n1E3+sA9K01i/VCSqtWB8sstas0o0Ylc81N8=\r\n=k1aT\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16"},"gitHead":"4619dbecc9527eb9c7fcd6d0ff62d4cd26d50ba7","scripts":{"lint":"eslint '**/*.js'","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"npm-template-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-copy":"npm-template-copy --force","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"nlf","email":"quitlahok@gmail.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.5.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"2.9.2","windowsCI":false},"_nodeVersion":"16.13.2","dependencies":{"tar":"^6.1.11","glob":"^7.2.0","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.5.1","@npmcli/fs":"^1.0.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.1.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^15.0.9","chalk":"^4.1.2","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"^2.9.2"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.2_1647542025015_0.565092643335372","host":"s3://npm-registry-packages"}},"16.0.3":{"name":"cacache","version":"16.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.3","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"0b6314bde969bd4098b03a5f90a351e8a1483f48","tarball":"http://localhost:4260/cacache/cacache-16.0.3.tgz","fileCount":19,"integrity":"sha512-eC7wYodNCVb97kuHGk5P+xZsvUJHkhSEOyNwkenqQPAsOtrTjvWOE5vSPNBpz9d8X3acIf6w2Ub5s4rvOCTs4g==","signatures":[{"sig":"MEQCIDzGkxN+5eVLxOpeC4Z4I9hzwPuXRjc7SDhEdYnNlQRgAiBZQhbwduMWyXKwhdETbjuzdIHieII6DcYkRKFdOxxSyg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiOginACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqsAxAAirnFcnwR4WaEWeQeX5bwBeAR2ZU8bHEc6r0O0mznlyhayD5D\r\nlsZtLYgPXvjPvXVlP+sXOyCo77jxK2yZ8NuzMlHRptqSW9t7lBsCfeVs5MBQ\r\nfxKzU0gyagVCAsp7WeMwn63VKkpEMNAF8MzBMiF8lFfc/a6nXEBGoJmqIjXu\r\nrK+6SxlwNF1I6uYjWJGpZCuCjMcIv6fPMVa2ybpLkx0ZMPCaI18qafRFxmuF\r\n97RwftbKP+BFoEiSiZfloVmLcomcugsp/NWZPoXX6k6vrhX9sPcMCtga85KE\r\naXQHW/G36IC9NedMM43k/0xfsVc5qZBwLAamLWGC4V8GHAa78rLMUpltbAiz\r\nJ6kaPVucSkDOqjrmVUelBN0L2yqsYlrHTfpENuxBhFGsJ3sA7XfvaRXKsXrk\r\n6kt4SncexHrH8AZtCHr6VdQB1qp/NAimNx7h2C4LwhCNDDXT3ewfz/cbtKhf\r\nJd4+c0aL9jNCSSH1qsMGOk9j+e6EPOnlXbcSbKLLye43yk8OW5bTnwwvqZHj\r\nhqV6Br0wxtunV/+nn31wcyi8aWz5chE4s+cbnJfCfD1VnKs8aWXym2nEQ3x2\r\nLCqOkG+N1J1qod5tp0e2uBVhb4wOYEWufvqHOVCQJpqTD7CtKs3mGICX612v\r\n1uKKQu1YhJzigQdC/wOwSa0kZWBbwgZ2xJs=\r\n=35ao\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"a98f18df4d4ce846bf0fb46dc5d25f4e50a03424","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.5.2","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.1.2","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.14.0","dependencies":{"tar":"^6.1.11","glob":"^7.2.0","ssri":"^8.0.1","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^1.1.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","chalk":"^4.1.2","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"3.1.2","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.3_1647970471163_0.7456997736336026","host":"s3://npm-registry-packages"}},"16.0.4":{"name":"cacache","version":"16.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.4","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"66877ae82717ade4d1416d5b3caa3a870f2c6d0c","tarball":"http://localhost:4260/cacache/cacache-16.0.4.tgz","fileCount":19,"integrity":"sha512-U0D4wF3/W8ZgK4qDA5fTtOVSr0gaDfd5aa7tUdAV0uukVWKsAIn6SzXQCoVlg7RWZiJa+bcsM3/pXLumGaL2Ug==","signatures":[{"sig":"MEUCIQCwOM4GI0lkr/HNqpAaXpz+YbAeskdbXDuoFwLrrtddqgIgLo/aqmR1LKP5TXtL9D6kAcke7ocy4p1kJu8LiRMdfT8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTKIiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpjDQ/9F0lFocPZKKwnpmH3OvecGDcRstbKvNzL5Hmvj96DWrATp1B3\r\ni0eNi40HLSC9rrblNjuU20rrZGIolNQRHaszFBnLad1c60pUWSCFEjn38Lrw\r\n3/hYxLcBm335H7VnkL1mCioHioLLp5PirzSQNKoqlbb1gdanUO+cY3b1NAEz\r\nKpGyDW46XeKMOxafSs/Eb9qSVvdFr+R2aqR0OZxhHIquZArBrcTOicEAC14N\r\nA6NJHfjJPunzUOONRKem80YtUFmmyCCOpcHm4xkxJ1b0dORWNhXk5X2atKOn\r\ng8/pMu38IiR4s6UWo9Qv+PfjWnIaWknuQVz7s0nb/vV1zp9Fh1aEYt3+6eop\r\nKRixPVLoKZALYM4RXO0W0vNxrAC4rrZtjW2SFDenArjttGSIWHzWxJlbrQEC\r\nFSQ9EkkP1cRl1Mn+yYJoLvFE/85n4fMqnsk3sZCxgDdu8xiZiLXIVLVmn59x\r\nJwixqFC7ehTkVT+VcQQ6498dBWVHxUfQBZhMoxuxWJR2+3EX2+cewwQJ4HLv\r\ng5v3wypCY5r5O3idshejfwRIBqkNnrAqzqSwoKoUz/Qg7IfIxWAe8MIqJuFE\r\nflcEqS1P48iZ8r+Fik3txa1C2pXZTY0ffp6b41yXYp/QoDvDRfZDdchs9mG7\r\nr1m8VJ2Cc54NnOsibh81Yk3TwKRrjFrX+lE=\r\n=7Cnr\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"cca946d6829be87edd0cea476400620d53c79ba7","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.6.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.2.2","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.14.2","dependencies":{"tar":"^6.1.11","glob":"^7.2.0","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","chalk":"^4.1.2","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"3.2.2","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.4_1649189410472_0.006959287456077989","host":"s3://npm-registry-packages"}},"16.0.5":{"name":"cacache","version":"16.0.5","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.5","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"149f02b276ee4773896d147f6b1559680c62cba2","tarball":"http://localhost:4260/cacache/cacache-16.0.5.tgz","fileCount":19,"integrity":"sha512-8s/08Kgu5sk9JcmOrekdUTM7cPPewz2FIQWVQOGOCdWPMRxBUD10WXApQD39Qvg1y5AKXcjo+pnOHkeveEFHCA==","signatures":[{"sig":"MEQCIAgaHo/VaTupYZoHE3zo659R41w0zYVDKqTsBC/X4jSeAiBWf2zeKi6mxs9GRLHQfvQNmNxTVvDcFef7tKZtmqnsdQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiYHZ/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpdiw/8CpGUQuEIKisi+GKCQvWwb8vCwOlj4aZJtqxwgswvtjcn+Gok\r\nVRJHk7xyO5alWzWLi28uHcFTMNxC4DRZzY4LRhL6E9G1lgwtxsL5naATG7r2\r\nnBXWTFFBV9KwggEXHt87CRIhtONqPOMhI0QpT4QLoAV6MnYA72iQ7j4JSExA\r\nes3MmEL7SuVROQJ6ZE94RbnP9xnR2Gl6Xo9tXROcGy4t7+gISA6/DfDxmZRn\r\nelpUdK9fHutAT9JXDAZ55TrdobGI5p26kVi79VTDEn+BtcMBLPVEKc4IRQJJ\r\nu6ViP00kCAuskzgmbcQ0v+U053EL4Swt75NEI1KNKipAaFTJ8cwC7wERLXq3\r\nRSb9Kyd4o8i4PF3sn36WhpAYtfYibzEZGnON8PpsIcwWRJKMbcwoyA2HoLRf\r\nKsmyGm0nz9QZ+yS6s+Cr6WGOoSoz46IZzIxX2Q9beHGj1KgvWjwaEwPOUiRK\r\n7X3CJuut/nvL0LJHqB5pJBbH2JLtdVNYmUoA9zZRI67mmyFItiDKXVNlwOOV\r\nF90mWy6zz2+pfL2WlBPgpEFqenobAHbZUX6FQIMbavUcwt2XFtw5awuzmqDi\r\nJycaTCow0Qd9G2DPmP3OItvfthm2l7eX1FLvM3PWntsuMxIEBrAGsNz2h+mt\r\nfjqKSCSieJ+uCWPTeF2Tv7FcHiwRAUKUqFQ=\r\n=Cz6u\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"18666fcbfba3c7cb8bc9c55a0c2e38bce6ba8aab","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.7.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.4.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.14.2","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","chalk":"^4.1.2","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"3.4.1","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.5_1650488959382_0.6826386246266065","host":"s3://npm-registry-packages"}},"16.0.6":{"name":"cacache","version":"16.0.6","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.6","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"3e4b1e8196673486e725a66eaa747a91da753963","tarball":"http://localhost:4260/cacache/cacache-16.0.6.tgz","fileCount":19,"integrity":"sha512-9a/MLxGaw3LEGes0HaPez2RgZWDV6X0jrgChsuxfEh8xoDoYGxaGrkMe7Dlyjrb655tA/b8fX0qlUg6Ii5MBvw==","signatures":[{"sig":"MEQCIBlRDAERvK3N75FvF3ZzvTo+fd+oum1CQvJCr1hXqxt0AiAwiEwW5UsiNwZu0aeSEMvyY5B+Np6zD1Tr3PTu4rEuCw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77252,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiYYM3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpfDQ//SRvwQqHK8jyg8TFYar5DOa+m6mYMgP7j7HZByzY3dRpi2Z7L\r\nCbuEnIQ4n/St7KSNVpIp2MqAjDiIZJnrrTIvIja8KonOl1I3GiM71M2qh5gI\r\nEzABP78pG/GRK3lS0SJeq4cM4cTRDNzjj3FDIU3xA8LnPJL+CdPCVtBZqT4U\r\ndqxhNRLqLVCG2mm9yXLxAGYslF1TNzxjNgvXBTSVJgNNHFp51AnHg1NcwcSa\r\n8L8IUzLtyz5MScQCkN++j53s67GWklGnQMkRBDHyNLbOQe1bP4rhEd0Ia7bb\r\nrjwMnsvF+eqiISB3qDMzE5ZUFBNBgfUggaBwgiprKYgFzJnKPQH/+WiclMaO\r\nyOrnrsNHVsm4BhN5oluB8dyDvcm0WrGvuFWzRYwPvja/FOgJsbiJEL86jxg0\r\ngqY0+p+i4YogNBNEdLNiRMNcuQl3DOqQKp1akZvvwWThgSbW1WcU4dFxtkn4\r\nakDU9vWMm4KXuqgFK8Nnzbt2sULpLvvbTJefa31kGw0yaUoIVfysF6rMLPJU\r\nOxl2L4263g1RcEM1SXO33Tv5vzMdLJvfVyOOSXgdU/789p/HdFBynPQQTvrR\r\neyo0uaAmWr3JeD/HyHDGvs5+ZyK+PFo3EBj6ni/AUe8MTEMeu3DZRJdEZJ2I\r\njyJvR4lJfP0TkwMQ4jZRuxeo3bqzHNkpNCI=\r\n=3V51\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"42799896042eed607902f5ab8671d66f7a8e72ec","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","benchmarks":"node test/benchmarks","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.7.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.4.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.14.2","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","chalk":"^4.1.2","tacks":"^1.3.0","benchmark":"^2.1.4","require-inject":"^1.4.4","@npmcli/template-oss":"3.4.1","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.6_1650557751503_0.7019010886722747","host":"s3://npm-registry-packages"}},"16.0.7":{"name":"cacache","version":"16.0.7","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.0.7","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"100":true,"test-regex":"test/[^/]*.js"},"dist":{"shasum":"74a5d9bc4c17b4c0b373c1f5d42dadf5dc06638d","tarball":"http://localhost:4260/cacache/cacache-16.0.7.tgz","fileCount":18,"integrity":"sha512-a4zfQpp5vm4Ipdvbj+ZrPonikRhm6WBEd4zT1Yc1DXsmAxrPgDwWBLF/u/wTVXSFPIgOJ1U3ghSa2Xm4s3h28w==","signatures":[{"sig":"MEYCIQDsXOxl1/ShfbdFt6cCZfUCSbX29VEkWTEgA0eZ7GS5LgIhAK49OW/2GbAajDyX/TSpqE5tAErFvtRbC7XGcCVwd4ky","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":75549,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiaZ30ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpz7Q//TPN1n3uVyEn/0U1zikLjz8+sTDh8GhovwPtZiYOnDx0dE7tV\r\n9F/I4lTCCtUH1DlhYZlclbuQIUhuIhhbXk4ZBqC9sBkTS1KKPxYvOw3f2l8P\r\nVZWft3hnRrLycWAOrbKnzKXg8PlSA5Z823d8SHmAqqp6h6luPJ62XhZ4zGWS\r\nzT+O0zOk+NXGY8cOa9V1JkB+SadHGGCiIjl06E5lZQBeFUaUiTGeBfmYZtk4\r\nGAJNqXVTBbSe7SLQISaacoPbORcOUvyy5ALbmnMc5fjp7LG1PANFN0YO3VFO\r\nbxUzoyY+Tjd00x3rLrl6c5evlpchOgUhmolLyTlidcRQrTNSJcpKhp6kscxx\r\nBYO5RQaMP2j5zC5YyFvzo5AB7Zks3jXfva0BosJNHBk13luRVKsZcxWZBu5f\r\nUszUZszLmvXVZw1vY3O5I+lQcxGZSKwXXRb4DrKilHnkyj9m/XU8pnn0JpVK\r\nhLvyGzEf0gxABWCzeL9cMztJ5nXKWMUwsQdtIMQ+EPqIY3XIwwF7kAOu39Gc\r\nSJWO93mQDr4FIp/Mq71d8W8qcBYCwrg4wxkNXz2I5/IH7B4fPqYrcjMvZpsX\r\nVlAJ49ORA14c6Su4feH/KxEyTRIxJMJJnuyRr5xoxwCcuMHmiACSteVAPVG0\r\nU1JupXuKKyEtPo8CKIkGnk9nEf78hDv/lvI=\r\n=j+W8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"283e815a84663b47b2ae336a0d046a5efb3c9260","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.8.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.4.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.14.2","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"3.4.1","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.0.7_1651088884433_0.2995734084404891","host":"s3://npm-registry-packages"}},"16.1.0":{"name":"cacache","version":"16.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.1.0","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"87a6bae558a511c9cb2a13768073e240ca76153a","tarball":"http://localhost:4260/cacache/cacache-16.1.0.tgz","fileCount":18,"integrity":"sha512-Pk4aQkwCW82A4jGKFvcGkQFqZcMspfP9YWq9Pr87/ldDvlWf718zeI6KWCdKt/jeihu6BytHRUicJPB1K2k8EQ==","signatures":[{"sig":"MEUCIQC1km3tWBtLXGrVaMTKsObP4LOvWGSl4lesa3vXTCuYSgIgGb5Vb12ov4kWSPMj8NoHhYDXsX0znuf/q1L/vCQ446c=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73358,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJihAFyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrv7RAAiXMefRBe0CwrmsOzKdCwZH97y35IiLPJWoEWODwApKcH3TTA\r\nI3Z8Hx6RlNZjImQIIQu0w5IYr+QREVcK8I/OOk8KPOhn1TYtJqCUWNtD/yDz\r\n23NQNHID3/Oi/jibTVutxXC6/Nn2MZOKtrJbFQSip06gAVTL8jW4YnopDc28\r\nzgLzPPMSToVdf2ujD/wCOhhWIXARKx7TOaooYqnVErPUvfx17yWM3H/8PF14\r\nZhw0KHwC+GoUjp0a+xVhwx+Ha+EsbifzHdyDd9/vwe4iUQ61UqJi9s1RZuxF\r\nw+/0EqJSig4GDjkn8ad27/oVle0BzddoapUfIuOzPMtzIWtWC3v10L3VK1Vr\r\nY6biYOEuon7ezd5IiXUeRcAc4n6PzZsaEQqHo6dNP/lef3bDbLWB3+MeZEA6\r\n19uaJhtT4HVlPgAdEEcYgENn72+xzpU3cI0WzQsiqsDPN9Px5bB/IATg0ZqN\r\nxzuBTjs+5vFyxK7laxiqkNLphEXgqyDSi1UhAT7CXfJ90NUUBDi5SKTBXQtq\r\nz9fXnt7OPpVEUsPwxFN7aF4PKSwZUewc0SQ8NZq2m+wgdBL7hziWFXYYIPtF\r\norXQ1gsmAjQzbaaR1rll+LMBx03A3xje5Q/PVtlzS4AZexUJmGjT6j4eKrWd\r\nZvv0ym/L9sKCbNbHwcOhOXInk1SyyfnVyuM=\r\n=wdcB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"78f0b8b9ee98d2631dbf7fcbef34ff11a1161259","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"nlf","email":"quitlahok@gmail.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.9.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.4.3","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.15.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"3.4.3","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.1.0_1652818290677_0.06729385451171987","host":"s3://npm-registry-packages"}},"16.1.1":{"name":"cacache","version":"16.1.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.1.1","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"ruyadorno","email":"ruyadorno@hotmail.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"4e79fb91d3efffe0630d5ad32db55cc1b870669c","tarball":"http://localhost:4260/cacache/cacache-16.1.1.tgz","fileCount":18,"integrity":"sha512-VDKN+LHyCQXaaYZ7rA/qtkURU+/yYhviUdvqEv2LT6QPZU8jpyzEkEVAcKlKLt5dJ5BRp11ym8lo3NKLluEPLg==","signatures":[{"sig":"MEQCIEa+PxKhqWXWGy1uQFcznrApQlv7MwMnq0PT0gUoplreAiAMXdoSOxuYKT8pnrzTeeZutxkeWg/Lzd5xA8BLOAYNLQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73353,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJimO9mACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrHJQ//UZOTC5isiGefZ2xKr0JyRkIsO1u3kW4p1Z3TBsscr4rC8YcF\r\ngYW6xWBqKUNDREIVrC2h4FJKcr2gmLXeF9qjqPZlGCr1yFuKU8skVA6nuDix\r\nqMKZ3z8Coj623lwENSDa3ZYyVv0Fzy/vEeDheHxhjs55YP7dl6AWFHb639tj\r\nEk2MdrPrIhdnFEQpanxVeM8gT99129jMv0ViN1ujS1ZudOq/GO0rwZvmrzFx\r\nga6nz73bVQvw1n3/udP8aMzYecMdO5NBSZem9mUyvmRLkw7cKfPERSjdoMhQ\r\nh8NCUCGEiZCuNlhaV+oMm/RhoZl0CLhyZP6bVXkw7kkapTtE2R/DXPBbBXLL\r\n6cNNOZL6mNszlOZDnjWWUX9ybPC2BmwGBVXpt7JH1LPI26P5l1OCEYT7rpJL\r\nObLI/rQWMynlajhDDNa/z8shqwGVaQhwqX6WGVSqKBukXxs2Qe6aA8B+SAHW\r\n2dqXdEW/tU7L5haNvKVfyuqg5S87+obp0BU58OvRH9Xm71GZYNn90MjWafID\r\nF+4LWtFd7y8zmZt4NxaTZFXkufF2IlPtSr8gA8SXL4Rp8YwAKLeSw40a93JE\r\ndCZ7y1T05ub6Hv0AmvygPz7MZAsz07DcAh9h018wU7XhDBNoXhGL1mhM7mNG\r\nb4RudeNGPW00MckVPXUMxUXCmT/xFXigKYc=\r\n=0L8n\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"e8d1e85fa97f0d832e45c961497fe1e7dc6fcba8","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.10.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.5.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.0.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"3.5.0","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.1.1_1654189925768_0.21844120721554483","host":"s3://npm-registry-packages"}},"16.1.2":{"name":"cacache","version":"16.1.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.1.2","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"a519519e9fc9e5e904575dcd3b77660cbf03f749","tarball":"http://localhost:4260/cacache/cacache-16.1.2.tgz","fileCount":18,"integrity":"sha512-Xx+xPlfCZIUHagysjjOAje9nRo8pRDczQCcXb4J2O0BLtH+xeVue6ba4y1kfJfQMAnM2mkcoMIAyOctlaRGWYA==","signatures":[{"sig":"MEYCIQCdYJFWizItBmR7cS2pkKbM6ZA7gQN2XcPwgFJ/vfPHJQIhAKv6ZTxMKiDGEEHP9yQ9rzxB4inN23f9OoY+jUCoH0pa","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73514,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi+qTfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr9wxAAlmtt9p2IQuOYFlnI8ibLNqV+6Xedp00xV5VA0w1aSyIK51i+\r\nPZUem4QDdAT+55tDV6/TRuQJst9TBhot2QxAC1mdXhNeI5/MU/+Vjli/wRrh\r\neFqDraPAtp7cm1Wh+TEDFOUOem9BXLxZQbkTbhv8L9W0ndjTy72DXf56AZvw\r\nQhb/UQd8ARxHkKnCnPGa19T81Gl8Vgx8iLxcHSd0oLfVL4L3/jPbz1eLzWu4\r\nXhk+ol3rs4Bad9fEfSD9mK457+N8rtE/E6fjm0R4lgsoWep7wF/nXHW4yIUF\r\nHQ5pOpgWT2bL7cbt0M+VZog81QKNydwuH8BXQ8Tcim6JwUqaUnHL6S0Xu1eU\r\nC8Iz84uKedW6IjPxhIwYk4GR7pko8jxtaFfRrkcJlJiQjRGXaDJ4N5Og6PUX\r\n5sLdjTzqaYQimI1D4wEDjWn8wLtG/Xuq4EMijIDh02YeEmeLlAql18uC6Lzz\r\nnoQMlB1LfF3mCis/5VTR0NI/EYOp/NWiomQ7FiAHL584meZhewMetOZiXi6t\r\ntXmCzvj2/x69uaFIrl2zM+mGNjyVbvxuEBAQzAOA27gaccFsdou0AJf5HlTy\r\nmIZOAh0QYfVXa3/pXf7VoifJ9F3gbe6Y/bWDiUvmA1F0soclpAXoiQ1xjQ6p\r\nmvz/T2JSmsCm1v0eY+pGnuMY46+OPdOWVP8=\r\n=o25x\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"befff62aaace0213f41466be4d2d9bdf8cc35013","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.17.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.5.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.6.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^1.1.1","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"3.5.0","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.1.2_1660593375372_0.6127166958265384","host":"s3://npm-registry-packages"}},"16.1.3":{"name":"cacache","version":"16.1.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@16.1.3","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"dist":{"shasum":"a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e","tarball":"http://localhost:4260/cacache/cacache-16.1.3.tgz","fileCount":18,"integrity":"sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==","signatures":[{"sig":"MEQCIFlRjxgz5KQjF1lQ2QasX7jYlj9784vNVboi7GYl5my5AiAtsAj3U72mT3btjYy0xZihAF2rKXOiVLyROfEATp6ntQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73514,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjBTCDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqWww//dcfkWj2UDGrPiSVloOGNt1eWJTUbd0j3xvbmiajvzbo0zg4v\r\nR8DgM4kCzSKZD0C0qmPccwKU5T7d08sKr3l9mhWfPLdxrSrNG6qnjgxDwdvQ\r\nNeDKx2tR4UYSZoVcjRMHzOuUjZY/rhS/+Gk0rMELu/+LPppJvU8gZJe1PBWc\r\nTqIryjTsgpj7bUsMTrclg6Z1vNocPjOHQAtAxsTs18YQFy3yrgkHZcTKVtml\r\nNicHGrcwbVXLfsptirbGG5ARYFSK8IVh190SZd+9YTGDX0Odl07NbMItgnfV\r\nlWfoJ4iQA5lubbpNNb5AEBtbLAuWk1SATcEiIYgpiDtIELz8vHy701e14D1z\r\ny5IyFSQ3pfvF78EemcZ8FhmD8T9ob1JuRowoWL2vMeKjbQPduYwy6wynzQHs\r\nPqBfGJ0vlUnzQiR27cmEsbpf8XterNLwJYCJfsek8YvxitORU9fPbA7RwPhm\r\nEciuG23/lJ9ZfRlAnYkgiXX8OilMD7eQgiOozRSMVoQhS7dFvFyjXkNLqEQA\r\nyloSQsfJZKAnIL5GOAAFHzYRK702JGKqw8uaq1hy1X9Zvv2PqrGMC6fJfSg5\r\nZZmb0ErmmMYSZZvRaptAxGieqd0DjnvU6GYoL/H2HsN2p5N2hXV5lVGrYs9i\r\nDUnXN8wNPLugg3FmQQVRO8rwvcqJQoW9FwE=\r\n=ld5z\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^12.13.0 || ^14.15.0 || >=16.0.0"},"gitHead":"f9f6f81e5b892e457e154b8bb8f7538dcae23817","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","preversion":"npm test","postversion":"npm publish","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","prepublishOnly":"git push origin --follow-tags","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.18.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"3.5.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.7.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","chownr":"^2.0.0","mkdirp":"^1.0.4","rimraf":"^3.0.2","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^2.1.0","fs-minipass":"^2.1.0","infer-owner":"^1.0.4","minipass-flush":"^1.0.5","unique-filename":"^2.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"3.5.0","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_16.1.3_1661284483462_0.6872558795046613","host":"s3://npm-registry-packages"}},"17.0.0":{"name":"cacache","version":"17.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.0","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"76be0cc410879a37ec08426cbfcc216a5c2f26a6","tarball":"http://localhost:4260/cacache/cacache-17.0.0.tgz","fileCount":18,"integrity":"sha512-5hYD+c8Ytmymo9b8tPgYWrWfHOzaO8M8jMUkyiEYfeLTwo70MUaD/yA1pNONi3upx02JIn3mtpDuSCXoQgtlHw==","signatures":[{"sig":"MEUCIG56f9Q+oWq98M+0U6ooduDdW0LSf+p5a4VfMc7oDaPjAiEA+5m1nWCvw0X4jqvOflU2m4Yo4/LGCkDiKivyD2+iVok=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64953,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSFwYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqiXA/9HUHzSak3gqhYhzDSRFg6n2+CWE2J+pdHPmB3aMHY74zf+Z86\r\nT9G8hV4a2R/zpsiZBBqR2wXRInK5+TBbEVUkZDfJ8Lmz/WjVUvYpXduesLSB\r\nsQWcbIc1gtGZ5wpsHWh/ZxzmPmyuV6KNqSicbbu2TIstsyECiYiOTUo9QnFy\r\nui51BWAmIaj+OsLv/Pl1+GYP3TEb/R4CArO7ze9tsLPGpH2qLZNhpTb6aT+l\r\nldYuElnJSf0rx19iZvcmQ8xVnUummNnPlpr+Eddzsi0PBoH+51ZXwjgGi86g\r\n0FGSXWfb7st6ddXAAIt8FkvFtqTj5vRiwUDMUN2bnmv2b+3lyphBZSGCmsSD\r\n0zJJG5k9N8G2ee0DPqJ6Op44YRnXuq5m4t95nLo6he6F330amqOPIR9I+F78\r\nHCZfSu78KH8E1iRfPPLLJ9pFqmvtmjv2eA3EJG5A2sJfJeUtU7kGaa0vIK8P\r\nbfR0oUCGTSxH6N60zoH2o9ROMVzgbHbn5dbshnyYXw8hJ5HL7YBp+T15jEDG\r\neU97iljo7uAaEeHySOBIOs8q8WoWGHJL0xbxxLTSdDs2SwnhWAWvaH3uqPee\r\nXikHFQLz6tmdny88T9uzhFA/k4e1VXFoiiE+lU5GCCJ27KA6N1SuDPylcSFt\r\nzI0r+7iiCfhMv+xit2SnRu12iPGbPFUq/NY=\r\n=LREw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"33ba55be58140297c9826ab92fced35f31ba6928","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"nlf","email":"quitlahok@gmail.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.0.0-pre.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.5.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"16.16.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^9.0.0","p-map":"^4.0.0","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^3.0.0","fs-minipass":"^2.1.0","minipass-flush":"^1.0.5","unique-filename":"^2.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^2.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.5.1","@npmcli/eslint-config":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.0_1665686551803_0.25169488534547857","host":"s3://npm-registry-packages"}},"17.0.1":{"name":"cacache","version":"17.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.1","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"bcba581a1b311b552b21f71d6205c67551a8d6d5","tarball":"http://localhost:4260/cacache/cacache-17.0.1.tgz","fileCount":18,"integrity":"sha512-HRnDSZUXB5hdCQc2wuB8eBQPe1a9PVU2Ow8zMTi82NGJZmBGNTSjEGzetlndKlqpVYBa4esdaJ2LH6/uOB4sFQ==","signatures":[{"sig":"MEUCIH8QaPMXwyNcihIQxtfW7YsaUb74oqBiiSn5o0NjNQ1GAiEA69L/XvkOvevJIVS6FDjTP8BOwDC6fP3/T3NaQ7JEKjI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64954,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjTa5/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpBIhAAms664cOOSVNx8AR31W435FP7FXHu707c7cj7xMKqAJ6gLFTE\r\n1k42gUb4j3rPix5bB7FHNst155pXP2V9MNXconIodX2FVSLeuyMKJ7UtTmQA\r\nz6rmufTQXvDufFRwmlY+bqJZu0pY9jFZgAcaHGVycIIadlyanF4l36K0j2Bg\r\n+FxAgOiNhyib4YQWcl0lMmYAa3f6xt0ULKVXVbUgOGwqAetX9fzS6uS/gjSq\r\nrOhNchPGcXSkkKB6Yuq60RppDkgaAHLvgpwJQEIBo919gQtV123tnEHKVxFs\r\nikyDseMxdB4N7g2vugptBrr/xexTn4DjKYFDcS0RriGypuDCVpH0lavkOzPW\r\nbH1wGwQsS2hVjPtlLWKeGsp6mWXaCwXVifEXeLCRjzOOP1FYlsMyBeSHWqwq\r\nilTpyFgXdMoeGd1/gMIH3JfDlJilQ99Ht3xNPMSfKkpQpPqz6YnwhlacAWwt\r\nw+Denf5qSe0TUIsX2Ak79Iu579p307qpafnfXMEFtmlcI6fyXpCtIvy3ksLb\r\nFjQ6c9u8S5r6UL/AdKLmLuG2v7z+5Zi82sHB+j8OEy2ri/vR3CcNg1QY6m8h\r\nlsD87GUSwJJ7/gQPw9J9IMqADm+JFRsLtVKv7djH5Hr+w1OEbrrRQ4Q10rvI\r\nKiJXiasvsURwmiFXDGa/aYYF4GfCaRiGg6o=\r\n=BT+j\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"3d8eab92c53f2ca6afafec1861a49bf840412e7e","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"8.19.2","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.5.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.10.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^3.0.0","fs-minipass":"^2.1.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","@npmcli/move-file":"^3.0.0","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.5.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.1_1666035327667_0.24274961223933156","host":"s3://npm-registry-packages"}},"17.0.2":{"name":"cacache","version":"17.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.2","maintainers":[{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"ff2bd029bf45099b3fe711f56fbf138b846c8d6d","tarball":"http://localhost:4260/cacache/cacache-17.0.2.tgz","fileCount":18,"integrity":"sha512-rYUs2x4OjSgCQND7nTrh21AHIBFgd7s/ctAYvU3a8u+nK+R5YaX/SFPDYz4Azz7SGL6+6L9ZZWI4Kawpb7grzQ==","signatures":[{"sig":"MEUCIB8Oaei/g6yWVxO9frxRE731BosYayeMOy7d2oGlIzeyAiEAtt18Csd7bS4lm7GY5L1l19A43xtbyfLnJSAIzWVIbyE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64923,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjZIvWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpiUw//QAsrOjAq4yJyICviLgrmxK5w/ba5QLI7+uOm7/0q2v9qe0Ao\r\nt69c/0B3GOLiVBav9UTvJjjy3AzB7urU9Tm5hLF8VE+j91kAd/NrKzyfjmhz\r\ndN8A/QmKoCAXRIQNya0HC0KAZohIgOG4b5gxRvmpfVCpL7GLdyo1qw7f3Nrm\r\n0n5IeuC3U1rVEnAucFDfkiuP1IRXlt+BZgs4xtoOPRGiQ0MLLOU3ZtsARk2X\r\nnIX/u4/Mecc5ifcXwtY8KK6agoY3Souk1Q+gjEz35/0koicOrOwRM+kf+0Lg\r\nYTeqnX9LjTGWN8xy2fRtb9LlQsUboo7H3R/5XSVyP6Xd/djFccys0g+QPrmC\r\nAaxOMMc2vzkeJgJxRp2AubQVwDo555UC3DLStFDkSw4iI7YmctxIiLzmsmNb\r\n2ue79iYQmYDGFsppsL8uwwEg5aYVYThHfsiYSxQLDIU3uH650W2LGmWMxk2H\r\nLYBdjwXxtpFieHHYVtnKLj3al23J++TBiVseHASzPejm6mit9grXLfNI/gvQ\r\nYRrYEbdP7o94M79S89pFO7L2ciwvxGVeoqdtUKAJBSoG7tNWCQFPKITy0vev\r\nGntRkI4Xow/E4K7K/6arl1GCeWJGbNg/g8qtnxqLOmArw07yDnUQxTQ36aW0\r\nwDTtxIYz5v5lk5ovAblzLe199neczA73vvQ=\r\n=OMbz\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"e96228862f90cce4bb4ff803e9311dfb1d3a2ded","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.0.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.8.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.12.0","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^3.1.6","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^2.1.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.8.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.2_1667533781974_0.5257706411605336","host":"s3://npm-registry-packages"}},"17.0.3":{"name":"cacache","version":"17.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.3","maintainers":[{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"9ba14e0e50eca763ae7e2ee89036a948a13035ed","tarball":"http://localhost:4260/cacache/cacache-17.0.3.tgz","fileCount":18,"integrity":"sha512-pwsIK/grdM0cHpfVaNFxMdzElBtLJGsVPE+JnxqXP1l40O01Z1mfDE8MbRTuwomGq/UwEtGisOylutOEVJxEqg==","signatures":[{"sig":"MEUCIE/1DlQF2iTFasMgOwF1HrOob5DfZRm7N6KdXpmeU7aUAiEA1j48fzeqD4QPNYBGbpk6CVRmRsblyaBCJkJ7rtMGB8k=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64925,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkPhsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqXIRAAmL1KbbMe+Vl4ypUhnJCxY1K2k4UNtIL935vbrSU+fCRQdfxQ\r\nGvELkoCE1ku1Bjr5N9gmnjOzsvQQyX0FQPPvO3sk2NFn9GM0v5sorNumH37Q\r\nJU3eZOzajchCPrKtUtCn3G3/mfqlXsqtfb5x64XaBzUnwPkJtDobRSMyH4VY\r\nnSdkKmQHri4iQHC3LxB5lTfwdN1gwkzfehX1QHyLMTlbn6aC5/04yuSdaucR\r\n3+QyRyvy03u5V5sWshFRjzJ9scXhvH+Ko9apL/8OR+ijaXkk6FRndP0itYjS\r\nPsvaiR0SDlh31ZOWx7LQ4JwN0b/l0j5v6itu4K5+yOmVm2LO3ZKIl6jt3T+d\r\nnHZ8HqJrUl9T2zfienU4vnbSPyj8eIDPuFO5S3C8M0bnpW30MuJQ4Oj7xsv0\r\nP9zQ5LQPPpmU4iGkfJPr7lapYUN3rzE3WF9ehggBAi31KGurC7z3WAl0KsOA\r\nRv8dyIZuQ1ZRgPzTlW51UFLqecPcZUyIg8LR44ve9DVDc594s2KxN1h37hEd\r\nOuFaPAk7lp5rAjxuDmfGPnB4+fYc6U1OGgC4dN14TLOcKZ8JRJIhtoaIoiqP\r\nmD9CDRKrhRFk9rM/Xbup9C3vRroJXNPTUvydQx0hKGkBV83NaSBX79uXhHMi\r\ns5U2cYZdQvVna+iJS759cI4B+hol/9uzN6w=\r\n=nYf3\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"772c49b6639629ab786b68d1530457971f7f34fb","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.1.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.10.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.12.1","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^4.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^2.1.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.10.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.3_1670445164128_0.589394979687702","host":"s3://npm-registry-packages"}},"17.0.4":{"name":"cacache","version":"17.0.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.4","maintainers":[{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"darcyclarke","email":"darcy@darcyclarke.me"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"5023ed892ba8843e3b7361c26d0ada37e146290c","tarball":"http://localhost:4260/cacache/cacache-17.0.4.tgz","fileCount":18,"integrity":"sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==","signatures":[{"sig":"MEUCIQDwjWEqvx0NsHz65owHKg+29xqgy7Xh7LZOMYTZFhBQtgIgUrl8Bg4oh2Npzboi0K18sC6RbUY4pE/xmJ/cS+lwTdU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64925,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjm3pUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqlQxAAhDVf0mY0NHA7Eem6ZCJMyxR+P2YfNqqvi/3X5qaWhDTejH1i\r\nXFtxs8He+6m4ZgOdsU0OMHYIqgCAX9HIEi4hYlQiwLYFOh03cUomx6p5UhBe\r\nFV5Tw/pzv1/0QlHB7ahDgw6flPqSe6qkPblrst9pfrrAunw05rhszPkcL/5w\r\nmJeKPt4UEhvpH59CavUIkLfzPSuy3xQHqMy2PhWlkY9Cd9M2UoGhQWqtwnjt\r\n0k8ExjZwGJEXMFaxV99ptQ+oVVJMJ0NfKjJ4VplrEoGN3I2Okh9WWPhX/PmV\r\n1JBSsKUpXq4UwYixwY+tldZRPATOUV3h0qdcbwZ4L0Uu+LyTGZx/QiVuckYW\r\neROQX5rN7tR3R8o++BPtA1lzT7JcnNBvMFLB4Wg+VHUOmRHaER6X4XgZ/GzY\r\n70ZnGTvlZp/YCAADbpIEGh/fnk41P7BtFAnanwUzOveLqPPGPkQc916GVWMF\r\n51N+cbWjFx96pNwlh99xv6K6+boix4KRTLH9JPV/9Sm3W6EHIrFPZgD1Nw4A\r\n+9s527GsBFaB6FMvQHnHWOb/hmJaUIEBecv1OBXSltE5PvexjlVA+7W+XYso\r\nN/tRdm67sTypNmebDCHDnqoIh/Glm2qlXVINf97EQrZEx3YT82ynua7ss418\r\nddpe2WIbwSry7a4QDODxA8V897j//61GeqQ=\r\n=zdtv\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"d95b9591c55ce15ee18c730efc634c0db37b7c21","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"lukekarrys","email":"luke@lukekarrys.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.2.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.11.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.12.1","dependencies":{"tar":"^6.1.11","glob":"^8.0.1","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^4.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.11.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.4_1671133780243_0.9715188203027696","host":"s3://npm-registry-packages"}},"17.0.5":{"name":"cacache","version":"17.0.5","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.5","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"6dbec26c11f1f6a2b558bc11ed3316577c339ebc","tarball":"http://localhost:4260/cacache/cacache-17.0.5.tgz","fileCount":18,"integrity":"sha512-Y/PRQevNSsjAPWykl9aeGz8Pr+OI6BYM9fYDNMvOkuUiG9IhG4LEmaYrZZZvioMUEQ+cBCxT0v8wrnCURccyKA==","signatures":[{"sig":"MEQCIGDHRQv5hKP604ho689satt+9YqLuR8RO+GEqa0/XZdvAiBApWIoPQ7R7xNj1KRX5aJF3r/loRhE9Ko2rsE1hvB33Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":64876,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGerZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmryYA//aERMEHJ+7dTbEbVXh0pdJoktYOgOEytOdFYVwgOgVmWvWGif\r\nCpZ+Sln5RNanWUE0sEHTQjlNs1st8S5CSJd41mpl3cwPzh9boYZkGeWKCajF\r\n8XYcyRH52dVWOfAHhdZlNmUU/tWmimBnFjxPG2sZtKjuV5Hg5gCriPw9rrGu\r\nNw3XhzDyqQvy/c6SQnHwDBfWrHgEASPiFF/qiXoxUxCk9KYjgriAfVX9/AyQ\r\nbmLy8DWN7/NtVw1Je3GOiJf9suguff2Y/BK7FUfCHtKrdy4S2NcBm4sZBms+\r\n1HDo/hBfBGzAetnvabTBFrs2pPpR2ahy2lHU94oTJx8ku5EJ88Z+uaLtqRwE\r\n2LEPSG6N/nBWtF3k39emASGaLiV0ujbVZRVUaGATtIe9UYLH81cxm+2SUNcc\r\nygpPrXtX/OGXPqhzwz6pxTw8cET0ahWHeOKajoVx9i0WdZ00UScnaoQGqeY2\r\npa+V2RUA/r9vSzeXem2FNuKXHoU871mtgPGYsNVupoeQb4khOGfVBWHS+aLY\r\nsOuGBm0ibEDQTXhzKvVITRUH+L6q6hAcIR4PUksEuzfdG7ABF5oL7OceO4U3\r\nOm6p6NxlOODLAxzNb17pFC7EG61Gjh+UyFLb41aljpnrkVhWK5r8f2wX0+6V\r\naqtwQyQXXGaepKIGsxmzxzNHxznAkqWiy7c=\r\n=dcEe\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"gar","email":"gar+npm@danger.computer"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"version":"4.12.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.13.0","dependencies":{"tar":"^6.1.11","glob":"^9.3.1","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^4.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.12.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.5_1679420121223_0.4817993422790383","host":"s3://npm-registry-packages"}},"17.0.6":{"name":"cacache","version":"17.0.6","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.6","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"faf9739a067e6dcfd31316df82fdf7e1ec460373","tarball":"http://localhost:4260/cacache/cacache-17.0.6.tgz","fileCount":18,"integrity":"sha512-ixcYmEBExFa/+ajIPjcwypxL97CjJyOsH9A/W+4qgEPIpJvKlC+HmVY8nkIck6n3PwUTdgq9c489niJGwl+5Cw==","signatures":[{"sig":"MEUCIQDfqTLxGi4phuYlN1vSKf+SiSZUCRDf1o0yWdplQ1MP8gIgNNxd6upVyn2hCD05ydq5uguLJy9iSw/AFIMbZYDHe9k=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.0.6","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":64916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkSr6eACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq+UBAAopVISe3RTziAppSDWHWnG/XjL+IHqq98EqCp+14KnV+BiwDZ\r\nWWAiAbfaSFA3a5ge9zCoXJ4fPv7FvYRbwLFAMfc5ZxpnlCYVkDUxdo76iZAa\r\nGU4Gzb/fvDUwO38q8kJdE9vdoy4fEWYrLonCN6z+Mzb4yuMQQC7uKPzqeRUH\r\nO1vnnk3e197SR9gDWlU1/nJPrzImX4hq3IswNz6cYhUenNwFpmTrdV5J7a/M\r\nzG1DBHe2rFX1HVHZV9omHNlFnCnvSnzvQny6aKmv/uZf2HO3HYoklRYNFrlY\r\nhXx/Lr0Wc83OSKiL6QMPcVjmF57f0zbFaAe2Sg0Php87worhWRlygVOEO5HR\r\nKZohpGILXO5M3L7lgr5WliLwyYIHf2ZNWI6zd8MlJa+zyxD8TGyFR8/oJ1zZ\r\nYQSje8D2kTjkHcegUcLKQcmne25FuEzdDJrJ7+37ecCHPl85yUzAddiq5hKJ\r\nnFTYgcdHCm/lWbrqCkh2HfbN+0nSBhTINujK4Mgem1TD2GgiSQW4RuBVPBQ2\r\nq22/mcktS8iCuJ8SOe2hqIj7DnAlLflV5JG6+IqywYcOuCwkKXBeYjJyMP5i\r\nHyJdxpHOuIrKR8yipY0nsrm6o5ufGevXvg9w4lm7M0CvvlgeDDjHJy0BGSpD\r\nq3HDG51760CULOxzvQtizVT8DyS7GTyzbOQ=\r\n=y7F8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"8bc48972bd07f91b5ce33f66ca6ba0afb94666cf","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.14.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","promise-inflight":"^1.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.14.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.6_1682620062220_0.5806099157684337","host":"s3://npm-registry-packages"}},"17.0.7":{"name":"cacache","version":"17.0.7","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.0.7","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"f42bcbdec4886f55bb4e44e62a934b4792a98145","tarball":"http://localhost:4260/cacache/cacache-17.0.7.tgz","fileCount":17,"integrity":"sha512-2GdqQs7hl20V50cB+JEuGeR6YtcNsf1Y9+SP8YXjmGlZz4hM5Ds9s6mKo7e27r6sfF/6MhN4DKRrGldidJJWow==","signatures":[{"sig":"MEQCIGcUEkUkC075449SkMJ0O6a40hm2pPQSBFFhyCLOuCelAiAiS1jW7DavafuTIyWJPQJ0dRSiMmDFy6pYVZd2OuaiOw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.0.7","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":63150,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkUCTKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqU3xAAkjC5ViScKF6Yyptr+Mmh4iLGSnGYqOnJ1DpyH+KVzl2K85yV\r\nvY+vGoYTumXe25XMV5+S/mSuHpopSGnwpzXTRmgW2jv+I+koFOE1RZeAZAgs\r\nSo3x45WxxvjNHhHyiXNIxQzKv/Psxirbw6AAJ+ke78EX7suckcw14YnX8lGx\r\n/8ubtHw7rkT5XPLvj5AjkmH46+fKiPOhDE7BBJUyk5MnzkjH/5K2/8IZtB43\r\n5jWAYSb3klctZwHJniUVe8kEQ/RHKbdCy2YJ0hLdWYgoZg3OobYjYPHTruiW\r\neuxNFeqmy2jLmmX76rOlRISCQZf/lKN9sJnha57/Hj/pRUrJjSmDJlxsK8ZJ\r\nftqtR4EgGwlI+QTtjj+JfXXKEXLMHeXyYbqth+Ip6nfcPqOD2dcXTilaBqc3\r\nljLqF2DU6KS6sTqBufFaE64kMVJP8466S8BV2rL3LGnDUdNqGnjaBD7p6v7T\r\nLP00OyJJOE6ecJ6nffQboD07v9p1RUeB6qc0aN9j+Ppuf69BW/2augQmPPzV\r\nYA/+Wr020VvIaV5Yvua7+clFcAWTwlVXXqQcnlLPs0lOYl4mYCA9U8r2cLbI\r\nJYIvoZe6HwuCFEc/pqBrJxBhjq8cz27COFm577mqMYiuNd7/qA4jZ1JZ6J7q\r\n/oTdjYTVtqSfUj4XXZPXzwjpoY/tX20ZRqo=\r\n=WzEo\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"07a8d3949cf151cadf6e85345226568c053f52a2","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.14.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.14.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.0.7_1682973898036_0.8353297602360361","host":"s3://npm-registry-packages"}},"17.1.0":{"name":"cacache","version":"17.1.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.1.0","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"b7286ef941dafe55b461cdcdceda71cacc1eb98d","tarball":"http://localhost:4260/cacache/cacache-17.1.0.tgz","fileCount":17,"integrity":"sha512-hXpFU+Z3AfVmNuiLve1qxWHMq0RSIt5gjCKAHi/M6DktwFwDdAXAtunl1i4WSKaaVcU9IsRvXFg42jTHigcC6Q==","signatures":[{"sig":"MEYCIQDfEXwf13BB8+9EnEX7dIl6upnDqC3inlVOgTKHNj7l8wIhAMOnbONE9PCkUF1hBpywQhK1xF2FLPmkNTNmCjVsq4DQ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":63165,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkUXX7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq98g/+IveAWT1LkBZIULeDxGcxy0J3rjflG13x2CPIQ1vSn6FcX3r9\r\nJRYg+a8cgTkUT4JlFeuhjzAeLqkkmbAgBcB+Y7jSV/pIWFlIIHdL020yCUCE\r\nLEKOLXwlMs3awf19nh3/zs6QYbKZR56bfPaa26sFhSdCtiVFzWVN5+wCrKHJ\r\n0kLJPaNA6m6XnPKDeCTCls6jvawz4S6CxhjBZDCgaF1aY4lPreCpwrKfKFcC\r\nmEjrfPJSlc4JXNxA2tp0UXpd46wDTL3NBtaGlVRDODiLu/KqykOcrLRuYFzv\r\nm0MVFolNJCtf+KGxUIV3sMgy8tep9t3eM2NSZAwjCC5uU/leCnXd9irpccpC\r\nmfvn8Q78LFbyr6nU5X/8137Np7bPPuQ4QVcdmP8CwfurTAhTtdqCSLIRcZXA\r\n4V2IDIO9wieBYUqxpiqYu+TmUcnYvlnA9NpbeuPvdaIrJwdu296JS5fmOV5e\r\nG/iBry5zS1y7yljBLNxQ6tDuUX26ngpah2S5RClmiS3FBB64SzvnfGJTOBcj\r\nPieA6Vx2A53sPoIZomWIaDXtb5/0/Ffsid+gkzKwrI02A3lKCdcuqF4zk0aW\r\nSliO2pYP20BDQNh0qBFALcAl0eKrF/hLGtaKsV18ewv3ffaDB8JT5ZeGAnR8\r\n22rRSv1D6ttgHspXXFAm7lbES6uVLdrr3m0=\r\n=r8v3\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"d85abe26a4b58c056a04dccbc61bd158c8f6fd43","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.14.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.14.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.1.0_1683060219189_0.44364405651679917","host":"s3://npm-registry-packages"}},"17.1.1":{"name":"cacache","version":"17.1.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.1.1","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"f088b8cb6c10cfd3cb9e5f52e9b8fcdec315c412","tarball":"http://localhost:4260/cacache/cacache-17.1.1.tgz","fileCount":17,"integrity":"sha512-PfSvLwoYQT04wGpsivFhKyVG1i4mpA0LoxF9WdE7C46E7K170GvvXgVNiTgxmagNcXItPjzGrOBc7CBQ7HgPvg==","signatures":[{"sig":"MEUCIExu4AEktG9lD9N1Za3tb3/9ScevpaQdFgWWitLmVgr6AiEAwKPfhSs+8G3wXhvVq5EFIFZFYcVIaRZ7lSeI/h2agAk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":63490},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"747320fe2a50a3f9ab50645bd938f3fb85f104d6","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.15.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.15.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.1.1_1684255515060_0.18980390304349615","host":"s3://npm-registry-packages"}},"17.1.2":{"name":"cacache","version":"17.1.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.1.2","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"57ce9b79d300373f7266f2f1e4e1718fe09e84b4","tarball":"http://localhost:4260/cacache/cacache-17.1.2.tgz","fileCount":17,"integrity":"sha512-VcRDUtZd9r7yfGDpdm3dBDBSQbLd19IqWs9q1tuB9g6kmxYLwIjfLngRKMCfDHxReuf0SBclRuYn66Xds7jzUQ==","signatures":[{"sig":"MEUCIFnXW5vFseCFkgw0YMI55WUnG2TZ7mKC6J9h0KV0+4CYAiEAq/orMOdG6hG+d6lH6bm9+InVV8NoM1Av8nsvwVREoZ0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":63577},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"13a4ba3423d8d33b7d718e7200e5d3a5ec720a6d","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.15.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.15.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.1.2_1684262574859_0.32213319679905705","host":"s3://npm-registry-packages"}},"17.1.3":{"name":"cacache","version":"17.1.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.1.3","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"nlf","email":"quitlahok@gmail.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"c6ac23bec56516a7c0c52020fd48b4909d7c7044","tarball":"http://localhost:4260/cacache/cacache-17.1.3.tgz","fileCount":17,"integrity":"sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==","signatures":[{"sig":"MEUCICH3oNM9eo4wWXRJ6iARYwrn7rM4kUJWq52kanR3V0K6AiEAuCBVCKpjRr2RO5GBB9X3s5E3BCXqRSg5FkgNXHbBm3E=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"unpackedSize":63627},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"2ae6d2d9dda028700e0bcfc7f0b5f8dc9d9c6e40","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.6.6","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.15.1","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.16.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^5.0.0","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.15.1","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.1.3_1684376571186_0.8702834930698953","host":"s3://npm-registry-packages"}},"17.1.4":{"name":"cacache","version":"17.1.4","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@17.1.4","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"b3ff381580b47e85c6e64f801101508e26604b35","tarball":"http://localhost:4260/cacache/cacache-17.1.4.tgz","fileCount":17,"integrity":"sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==","signatures":[{"sig":"MEYCIQCW48GM5Oz3aJduR+o3Ry/4qcPlrqsNxDhvqGs+9fXlcwIhAOjF34DfTe4/+/d5YPm+ukDMa5HOAVAfTtErpsI3k2lm","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@17.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63627},"main":"lib/index.js","engines":{"node":"^14.17.0 || ^16.13.0 || >=18.0.0"},"gitHead":"e01ad9c394a56832d03aeaaf5bbcfd5684c3a1ce","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.8.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.18.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.17.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^7.0.3","lru-cache":"^7.7.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.18.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_17.1.4_1692039389799_0.18565667933733687","host":"s3://npm-registry-packages"}},"18.0.0":{"name":"cacache","version":"18.0.0","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@18.0.0","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"17a9ecd6e1be2564ebe6cdca5f7cfed2bfeb6ddc","tarball":"http://localhost:4260/cacache/cacache-18.0.0.tgz","fileCount":17,"integrity":"sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==","signatures":[{"sig":"MEYCIQDAOQfYLF22FTpoGZ8BP0O88xStckklHYKXOCBhI9DI4gIhAOVjjv6P7rDSnD/I9ago995N1jWdfsx7KrgWZWz7oZgC","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@18.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63717},"main":"lib/index.js","engines":{"node":"^16.14.0 || >=18.0.0"},"gitHead":"fc8ab22de5f5bd41e7eb5d44a88f497e5c67afb2","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"9.8.1","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.18.0","windowsCI":false,"ciVersions":["16.14.0","16.x","18.0.0","18.x"],"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.17.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^7.0.3","lru-cache":"^10.0.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^1.0.2","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.18.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_18.0.0_1692055311794_0.3613923232353424","host":"s3://npm-registry-packages"}},"18.0.1":{"name":"cacache","version":"18.0.1","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@18.0.1","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"b026d56ad569e4f73cc07c813b3c66707d0fb142","tarball":"http://localhost:4260/cacache/cacache-18.0.1.tgz","fileCount":17,"integrity":"sha512-g4Uf2CFZPaxtJKre6qr4zqLDOOPU7bNVhWjlNhvzc51xaTOx2noMOLhfFkTAqwtrAZAKQUuDfyjitzilpA8WsQ==","signatures":[{"sig":"MEUCIQCNzwSrBbPhHYzX0wL+JRPT6OrHgdXW5aD6ds7UrxciGQIgPHJIBPTu37fm6GptUjcXcYuBkrBog3BuhVmREZH5+WQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@18.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63661},"main":"lib/index.js","engines":{"node":"^16.14.0 || >=18.0.0"},"gitHead":"5e21ec98b1ac5744b7f7b86623a29ca0480dcfe6","scripts":{"lint":"eslint \"**/*.js\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"10.2.4","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.19.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"18.18.2","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^7.0.3","lru-cache":"^10.0.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^2.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.19.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_18.0.1_1701121815270_0.10363816097495238","host":"s3://npm-registry-packages"}},"18.0.2":{"name":"cacache","version":"18.0.2","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@18.0.2","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"fd527ea0f03a603be5c0da5805635f8eef00c60c","tarball":"http://localhost:4260/cacache/cacache-18.0.2.tgz","fileCount":17,"integrity":"sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==","signatures":[{"sig":"MEUCIB2qi4F+GiDU36NGTVPL6BfSow+8XG3/lE/ToZk0QZd/AiEAopfjPM6DUkXkywikDi7C1Puonzb0xu3UjsId8nvqryY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@18.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63559},"main":"lib/index.js","engines":{"node":"^16.14.0 || >=18.0.0"},"gitHead":"3de26afbacddc2ff8a7c62536bee9f092b851c61","scripts":{"lint":"eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"10.2.5","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.21.3","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"20.10.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^7.0.3","lru-cache":"^10.0.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^2.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.21.3","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_18.0.2_1704385826269_0.5614958732143231","host":"s3://npm-registry-packages"}},"18.0.3":{"name":"cacache","version":"18.0.3","keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"author":{"name":"GitHub Inc."},"license":"ISC","_id":"cacache@18.0.3","maintainers":[{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},{"name":"saquibkhan","email":"saquibkhan@github.com"},{"name":"fritzy","email":"fritzy@github.com"},{"name":"gar","email":"gar+npm@danger.computer"},{"name":"lukekarrys","email":"luke@lukekarrys.com"}],"homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"tap":{"nyc-arg":["--exclude","tap-snapshots/**"]},"dist":{"shasum":"864e2c18414e1e141ae8763f31e46c2cb96d1b21","tarball":"http://localhost:4260/cacache/cacache-18.0.3.tgz","fileCount":17,"integrity":"sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==","signatures":[{"sig":"MEUCIQCC/lkDf8YH7ovTQqLbvK15fnzGfIJD1adj7kQqKK+peAIgWnG8F6vXojVvrsufossNxTJRwkt3kB21imzmvzAlRxI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"attestations":{"url":"http://localhost:4260/attestations/cacache@18.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63516},"main":"lib/index.js","engines":{"node":"^16.14.0 || >=18.0.0"},"gitHead":"f9ebcea7e36403d37cd46da1567f40302b950ea7","scripts":{"lint":"eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"","snap":"tap","test":"tap","lintfix":"npm run lint -- --fix","coverage":"tap","postlint":"template-oss-check","postsnap":"npm run lintfix --","posttest":"npm run lint","npmclilint":"npmcli-lint","test-docker":"docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test","template-oss-apply":"template-oss-apply --force"},"_npmUser":{"name":"npm-cli-ops","email":"npm-cli+bot@github.com"},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"_npmVersion":"10.7.0","description":"Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.","directories":{},"templateOSS":{"publish":"true","version":"4.22.0","windowsCI":false,"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten."},"_nodeVersion":"22.1.0","dependencies":{"tar":"^6.1.11","glob":"^10.2.2","ssri":"^10.0.0","p-map":"^4.0.0","minipass":"^7.0.3","lru-cache":"^10.0.1","@npmcli/fs":"^3.1.0","fs-minipass":"^3.0.0","minipass-flush":"^1.0.5","unique-filename":"^3.0.0","minipass-collect":"^2.0.1","minipass-pipeline":"^1.2.4"},"cache-version":{"index":"5","content":"2"},"_hasShrinkwrap":false,"devDependencies":{"tap":"^16.0.0","@npmcli/template-oss":"4.22.0","@npmcli/eslint-config":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cacache_18.0.3_1714785247620_0.3833161554053286","host":"s3://npm-registry-packages"}}},"time":{"created":"2016-11-18T10:01:40.775Z","modified":"2024-05-30T15:08:21.612Z","1.0.0":"2016-11-18T10:01:40.775Z","2.0.0":"2016-11-20T12:47:12.844Z","3.0.0":"2016-12-03T20:31:31.664Z","3.0.1":"2016-12-04T07:06:51.710Z","4.0.0":"2017-01-28T00:31:34.951Z","5.0.0":"2017-02-03T01:59:49.395Z","5.0.1":"2017-02-18T07:47:56.870Z","5.0.2":"2017-02-20T04:12:26.669Z","5.0.3":"2017-02-20T08:50:56.237Z","6.0.0":"2017-03-05T07:20:56.329Z","6.0.1":"2017-03-05T08:45:40.039Z","6.0.2":"2017-03-11T00:12:03.825Z","6.1.0":"2017-03-12T05:52:41.529Z","6.1.1":"2017-03-13T10:15:54.281Z","6.1.2":"2017-03-13T10:25:30.310Z","6.2.0":"2017-03-15T01:42:46.629Z","6.3.0":"2017-04-01T06:50:14.779Z","7.0.0":"2017-04-03T08:13:10.557Z","7.0.1":"2017-04-03T08:15:59.614Z","7.0.2":"2017-04-03T10:41:41.723Z","7.0.3":"2017-04-05T06:24:54.502Z","7.0.4":"2017-04-15T19:38:17.734Z","7.0.5":"2017-04-18T10:04:33.337Z","7.1.0":"2017-04-20T10:14:09.501Z","8.0.0":"2017-04-22T20:20:21.398Z","9.0.0":"2017-04-28T00:44:59.151Z","9.1.0":"2017-05-14T07:15:34.400Z","9.2.0":"2017-05-14T21:09:29.128Z","9.2.1":"2017-05-14T23:00:32.415Z","9.2.2":"2017-05-14T23:46:58.837Z","9.2.3":"2017-05-24T09:28:08.061Z","9.2.4":"2017-05-24T09:32:40.754Z","9.2.5":"2017-05-25T01:23:21.470Z","9.2.6":"2017-05-31T05:43:30.722Z","9.2.7":"2017-06-05T14:37:10.629Z","9.2.8":"2017-06-05T21:18:32.135Z","9.2.9":"2017-06-17T20:42:04.971Z","9.3.0":"2017-10-07T23:24:48.894Z","10.0.0":"2017-10-23T18:25:38.782Z","10.0.1":"2017-11-15T22:34:11.319Z","10.0.2":"2018-01-07T03:40:51.113Z","10.0.3":"2018-02-16T20:00:46.024Z","10.0.4":"2018-02-16T22:54:14.873Z","11.0.0":"2018-04-09T00:38:06.331Z","11.0.1":"2018-04-10T18:45:08.936Z","11.0.2":"2018-05-07T18:53:16.124Z","11.0.3":"2018-08-01T20:29:03.150Z","11.1.0":"2018-08-01T22:10:34.698Z","11.2.0":"2018-08-08T00:48:44.693Z","11.3.0":"2018-11-05T04:21:57.822Z","11.3.1":"2018-11-05T21:17:11.461Z","11.3.2":"2018-12-21T18:59:01.184Z","11.3.3":"2019-06-17T16:14:40.006Z","12.0.0":"2019-07-15T23:29:07.778Z","12.0.1":"2019-07-19T22:34:43.049Z","12.0.2":"2019-07-19T23:11:07.852Z","12.0.3":"2019-08-19T19:31:55.390Z","13.0.0":"2019-09-25T19:03:36.816Z","13.0.1":"2019-09-30T21:02:21.704Z","14.0.0":"2020-01-28T01:52:06.125Z","15.0.0":"2020-02-18T01:33:48.426Z","12.0.4":"2020-03-24T00:22:43.621Z","15.0.1":"2020-04-28T00:11:21.041Z","15.0.2":"2020-04-28T00:17:17.546Z","15.0.3":"2020-04-28T00:19:23.392Z","15.0.4":"2020-06-03T00:01:35.657Z","15.0.5":"2020-07-11T01:07:45.796Z","15.0.6":"2021-03-22T16:27:29.180Z","15.1.0":"2021-05-19T15:47:55.070Z","15.2.0":"2021-05-25T13:26:27.490Z","15.3.0":"2021-08-26T17:38:46.944Z","16.0.0":"2022-03-14T20:20:19.258Z","16.0.1":"2022-03-15T20:25:22.270Z","16.0.2":"2022-03-17T18:33:45.186Z","16.0.3":"2022-03-22T17:34:31.368Z","16.0.4":"2022-04-05T20:10:10.629Z","16.0.5":"2022-04-20T21:09:19.576Z","16.0.6":"2022-04-21T16:15:51.770Z","16.0.7":"2022-04-27T19:48:04.598Z","16.1.0":"2022-05-17T20:11:30.881Z","16.1.1":"2022-06-02T17:12:05.989Z","16.1.2":"2022-08-15T19:56:15.534Z","16.1.3":"2022-08-23T19:54:43.642Z","17.0.0":"2022-10-13T18:42:32.034Z","17.0.1":"2022-10-17T19:35:27.893Z","17.0.2":"2022-11-04T03:49:42.194Z","17.0.3":"2022-12-07T20:32:44.395Z","17.0.4":"2022-12-15T19:49:40.439Z","17.0.5":"2023-03-21T17:35:21.422Z","17.0.6":"2023-04-27T18:27:42.461Z","17.0.7":"2023-05-01T20:44:58.216Z","17.1.0":"2023-05-02T20:43:39.346Z","17.1.1":"2023-05-16T16:45:15.280Z","17.1.2":"2023-05-16T18:42:55.035Z","17.1.3":"2023-05-18T02:22:51.377Z","17.1.4":"2023-08-14T18:56:29.949Z","18.0.0":"2023-08-14T23:21:52.006Z","18.0.1":"2023-11-27T21:50:15.525Z","18.0.2":"2024-01-04T16:30:26.439Z","18.0.3":"2024-05-04T01:14:07.783Z"},"maintainers":[{"email":"reggi@github.com","name":"reggi"},{"email":"npm-cli+bot@github.com","name":"npm-cli-ops"},{"email":"saquibkhan@github.com","name":"saquibkhan"},{"email":"fritzy@github.com","name":"fritzy"},{"email":"gar+npm@danger.computer","name":"gar"}],"author":{"name":"GitHub Inc."},"repository":{"url":"git+https://github.com/npm/cacache.git","type":"git"},"keywords":["cache","caching","content-addressable","sri","sri hash","subresource integrity","cache","storage","store","file store","filesystem","disk cache","disk storage"],"license":"ISC","homepage":"https://github.com/npm/cacache#readme","bugs":{"url":"https://github.com/npm/cacache/issues"},"readme":"# cacache [![npm version](https://img.shields.io/npm/v/cacache.svg)](https://npm.im/cacache) [![license](https://img.shields.io/npm/l/cacache.svg)](https://npm.im/cacache) [![Travis](https://img.shields.io/travis/npm/cacache.svg)](https://travis-ci.org/npm/cacache) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/cacache?svg=true)](https://ci.appveyor.com/project/npm/cacache) [![Coverage Status](https://coveralls.io/repos/github/npm/cacache/badge.svg?branch=latest)](https://coveralls.io/github/npm/cacache?branch=latest)\n\n[`cacache`](https://github.com/npm/cacache) is a Node.js library for managing\nlocal key and content address caches. It's really fast, really good at\nconcurrency, and it will never give you corrupted data, even if cache files\nget corrupted or manipulated.\n\nOn systems that support user and group settings on files, cacache will\nmatch the `uid` and `gid` values to the folder where the cache lives, even\nwhen running as `root`.\n\nIt was written to be used as [npm](https://npm.im)'s local cache, but can\njust as easily be used on its own.\n\n## Install\n\n`$ npm install --save cacache`\n\n## Table of Contents\n\n* [Example](#example)\n* [Features](#features)\n* [Contributing](#contributing)\n* [API](#api)\n * [Using localized APIs](#localized-api)\n * Reading\n * [`ls`](#ls)\n * [`ls.stream`](#ls-stream)\n * [`get`](#get-data)\n * [`get.stream`](#get-stream)\n * [`get.info`](#get-info)\n * [`get.hasContent`](#get-hasContent)\n * Writing\n * [`put`](#put-data)\n * [`put.stream`](#put-stream)\n * [`rm.all`](#rm-all)\n * [`rm.entry`](#rm-entry)\n * [`rm.content`](#rm-content)\n * [`index.compact`](#index-compact)\n * [`index.insert`](#index-insert)\n * Utilities\n * [`clearMemoized`](#clear-memoized)\n * [`tmp.mkdir`](#tmp-mkdir)\n * [`tmp.withTmp`](#with-tmp)\n * Integrity\n * [Subresource Integrity](#integrity)\n * [`verify`](#verify)\n * [`verify.lastRun`](#verify-last-run)\n\n### Example\n\n```javascript\nconst cacache = require('cacache')\nconst fs = require('fs')\n\nconst cachePath = '/tmp/my-toy-cache'\nconst key = 'my-unique-key-1234'\n\n// Cache it! Use `cachePath` as the root of the content cache\ncacache.put(cachePath, key, '10293801983029384').then(integrity => {\n console.log(`Saved content to ${cachePath}.`)\n})\n\nconst destination = '/tmp/mytar.tgz'\n\n// Copy the contents out of the cache and into their destination!\n// But this time, use stream instead!\ncacache.get.stream(\n cachePath, key\n).pipe(\n fs.createWriteStream(destination)\n).on('finish', () => {\n console.log('done extracting!')\n})\n\n// The same thing, but skip the key index.\ncacache.get.byDigest(cachePath, integrityHash).then(data => {\n fs.writeFile(destination, data, err => {\n console.log('tarball data fetched based on its sha512sum and written out!')\n })\n})\n```\n\n### Features\n\n* Extraction by key or by content address (shasum, etc)\n* [Subresource Integrity](#integrity) web standard support\n* Multi-hash support - safely host sha1, sha512, etc, in a single cache\n* Automatic content deduplication\n* Fault tolerance (immune to corruption, partial writes, process races, etc)\n* Consistency guarantees on read and write (full data verification)\n* Lockless, high-concurrency cache access\n* Streaming support\n* Promise support\n* Fast -- sub-millisecond reads and writes including verification\n* Arbitrary metadata storage\n* Garbage collection and additional offline verification\n* Thorough test coverage\n* There's probably a bloom filter in there somewhere. Those are cool, right? 🤔\n\n### Contributing\n\nThe cacache team enthusiastically welcomes contributions and project participation! There's a bunch of things you can do if you want to contribute! Please don't hesitate to jump in if you'd like to, or even ask us questions if something isn't clear.\n\nAll participants and maintainers in this project are expected to follow [Code of Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other.\n\nPlease refer to the [Changelog](CHANGELOG.md) for project history details, too.\n\nHappy hacking!\n\n### API\n\n#### `> cacache.ls(cache) -> Promise`\n\nLists info for all entries currently in the cache as a single large object. Each\nentry in the object will be keyed by the unique index key, with corresponding\n[`get.info`](#get-info) objects as the values.\n\n##### Example\n\n```javascript\ncacache.ls(cachePath).then(console.log)\n// Output\n{\n 'my-thing': {\n key: 'my-thing',\n integrity: 'sha512-BaSe64/EnCoDED+HAsh=='\n path: '.testcache/content/deadbeef', // joined with `cachePath`\n time: 12345698490,\n size: 4023948,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n },\n 'other-thing': {\n key: 'other-thing',\n integrity: 'sha1-ANothER+hasH=',\n path: '.testcache/content/bada55',\n time: 11992309289,\n size: 111112\n }\n}\n```\n\n#### `> cacache.ls.stream(cache) -> Readable`\n\nLists info for all entries currently in the cache as a single large object.\n\nThis works just like [`ls`](#ls), except [`get.info`](#get-info) entries are\nreturned as `'data'` events on the returned stream.\n\n##### Example\n\n```javascript\ncacache.ls.stream(cachePath).on('data', console.log)\n// Output\n{\n key: 'my-thing',\n integrity: 'sha512-BaSe64HaSh',\n path: '.testcache/content/deadbeef', // joined with `cachePath`\n time: 12345698490,\n size: 13423,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n}\n\n{\n key: 'other-thing',\n integrity: 'whirlpool-WoWSoMuchSupport',\n path: '.testcache/content/bada55',\n time: 11992309289,\n size: 498023984029\n}\n\n{\n ...\n}\n```\n\n#### `> cacache.get(cache, key, [opts]) -> Promise({data, metadata, integrity})`\n\nReturns an object with the cached data, digest, and metadata identified by\n`key`. The `data` property of this object will be a `Buffer` instance that\npresumably holds some data that means something to you. I'm sure you know what\nto do with it! cacache just won't care.\n\n`integrity` is a [Subresource\nIntegrity](#integrity)\nstring. That is, a string that can be used to verify `data`, which looks like\n`-`.\n\nIf there is no content identified by `key`, or if the locally-stored data does\nnot pass the validity checksum, the promise will be rejected.\n\nA sub-function, `get.byDigest` may be used for identical behavior, except lookup\nwill happen by integrity hash, bypassing the index entirely. This version of the\nfunction *only* returns `data` itself, without any wrapper.\n\nSee: [options](#get-options)\n\n##### Note\n\nThis function loads the entire cache entry into memory before returning it. If\nyou're dealing with Very Large data, consider using [`get.stream`](#get-stream)\ninstead.\n\n##### Example\n\n```javascript\n// Look up by key\ncache.get(cachePath, 'my-thing').then(console.log)\n// Output:\n{\n metadata: {\n thingName: 'my'\n },\n integrity: 'sha512-BaSe64HaSh',\n data: Buffer#,\n size: 9320\n}\n\n// Look up by digest\ncache.get.byDigest(cachePath, 'sha512-BaSe64HaSh').then(console.log)\n// Output:\nBuffer#\n```\n\n#### `> cacache.get.stream(cache, key, [opts]) -> Readable`\n\nReturns a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) of the cached data identified by `key`.\n\nIf there is no content identified by `key`, or if the locally-stored data does\nnot pass the validity checksum, an error will be emitted.\n\n`metadata` and `integrity` events will be emitted before the stream closes, if\nyou need to collect that extra data about the cached entry.\n\nA sub-function, `get.stream.byDigest` may be used for identical behavior,\nexcept lookup will happen by integrity hash, bypassing the index entirely. This\nversion does not emit the `metadata` and `integrity` events at all.\n\nSee: [options](#get-options)\n\n##### Example\n\n```javascript\n// Look up by key\ncache.get.stream(\n cachePath, 'my-thing'\n).on('metadata', metadata => {\n console.log('metadata:', metadata)\n}).on('integrity', integrity => {\n console.log('integrity:', integrity)\n}).pipe(\n fs.createWriteStream('./x.tgz')\n)\n// Outputs:\nmetadata: { ... }\nintegrity: 'sha512-SoMeDIGest+64=='\n\n// Look up by digest\ncache.get.stream.byDigest(\n cachePath, 'sha512-SoMeDIGest+64=='\n).pipe(\n fs.createWriteStream('./x.tgz')\n)\n```\n\n#### `> cacache.get.info(cache, key) -> Promise`\n\nLooks up `key` in the cache index, returning information about the entry if\none exists.\n\n##### Fields\n\n* `key` - Key the entry was looked up under. Matches the `key` argument.\n* `integrity` - [Subresource Integrity hash](#integrity) for the content this entry refers to.\n* `path` - Filesystem path where content is stored, joined with `cache` argument.\n* `time` - Timestamp the entry was first added on.\n* `metadata` - User-assigned metadata associated with the entry/content.\n\n##### Example\n\n```javascript\ncacache.get.info(cachePath, 'my-thing').then(console.log)\n\n// Output\n{\n key: 'my-thing',\n integrity: 'sha256-MUSTVERIFY+ALL/THINGS=='\n path: '.testcache/content/deadbeef',\n time: 12345698490,\n size: 849234,\n metadata: {\n name: 'blah',\n version: '1.2.3',\n description: 'this was once a package but now it is my-thing'\n }\n}\n```\n\n#### `> cacache.get.hasContent(cache, integrity) -> Promise`\n\nLooks up a [Subresource Integrity hash](#integrity) in the cache. If content\nexists for this `integrity`, it will return an object, with the specific single integrity hash\nthat was found in `sri` key, and the size of the found content as `size`. If no content exists for this integrity, it will return `false`.\n\n##### Example\n\n```javascript\ncacache.get.hasContent(cachePath, 'sha256-MUSTVERIFY+ALL/THINGS==').then(console.log)\n\n// Output\n{\n sri: {\n source: 'sha256-MUSTVERIFY+ALL/THINGS==',\n algorithm: 'sha256',\n digest: 'MUSTVERIFY+ALL/THINGS==',\n options: []\n },\n size: 9001\n}\n\ncacache.get.hasContent(cachePath, 'sha521-NOT+IN/CACHE==').then(console.log)\n\n// Output\nfalse\n```\n\n##### Options\n\n##### `opts.integrity`\nIf present, the pre-calculated digest for the inserted content. If this option\nis provided and does not match the post-insertion digest, insertion will fail\nwith an `EINTEGRITY` error.\n\n##### `opts.memoize`\n\nDefault: null\n\nIf explicitly truthy, cacache will read from memory and memoize data on bulk read. If `false`, cacache will read from disk data. Reader functions by default read from in-memory cache.\n\n##### `opts.size`\nIf provided, the data stream will be verified to check that enough data was\npassed through. If there's more or less data than expected, insertion will fail\nwith an `EBADSIZE` error.\n\n\n#### `> cacache.put(cache, key, data, [opts]) -> Promise`\n\nInserts data passed to it into the cache. The returned Promise resolves with a\ndigest (generated according to [`opts.algorithms`](#optsalgorithms)) after the\ncache entry has been successfully written.\n\nSee: [options](#put-options)\n\n##### Example\n\n```javascript\nfetch(\n 'http://localhost:4260/cacache/cacache-1.0.0.tgz'\n).then(data => {\n return cacache.put(cachePath, 'registry.npmjs.org|cacache@1.0.0', data)\n}).then(integrity => {\n console.log('integrity hash is', integrity)\n})\n```\n\n#### `> cacache.put.stream(cache, key, [opts]) -> Writable`\n\nReturns a [Writable\nStream](https://nodejs.org/api/stream.html#stream_writable_streams) that inserts\ndata written to it into the cache. Emits an `integrity` event with the digest of\nwritten contents when it succeeds.\n\nSee: [options](#put-options)\n\n##### Example\n\n```javascript\nrequest.get(\n 'http://localhost:4260/cacache/cacache-1.0.0.tgz'\n).pipe(\n cacache.put.stream(\n cachePath, 'registry.npmjs.org|cacache@1.0.0'\n ).on('integrity', d => console.log(`integrity digest is ${d}`))\n)\n```\n\n##### Options\n\n##### `opts.metadata`\n\nArbitrary metadata to be attached to the inserted key.\n\n##### `opts.size`\n\nIf provided, the data stream will be verified to check that enough data was\npassed through. If there's more or less data than expected, insertion will fail\nwith an `EBADSIZE` error.\n\n##### `opts.integrity`\n\nIf present, the pre-calculated digest for the inserted content. If this option\nis provided and does not match the post-insertion digest, insertion will fail\nwith an `EINTEGRITY` error.\n\n`algorithms` has no effect if this option is present.\n\n##### `opts.integrityEmitter`\n\n*Streaming only* If present, uses the provided event emitter as a source of\ntruth for both integrity and size. This allows use cases where integrity is\nalready being calculated outside of cacache to reuse that data instead of\ncalculating it a second time.\n\nThe emitter must emit both the `'integrity'` and `'size'` events.\n\nNOTE: If this option is provided, you must verify that you receive the correct\nintegrity value yourself and emit an `'error'` event if there is a mismatch.\n[ssri Integrity Streams](https://github.com/npm/ssri#integrity-stream) do this for you when given an expected integrity.\n\n##### `opts.algorithms`\n\nDefault: ['sha512']\n\nHashing algorithms to use when calculating the [subresource integrity\ndigest](#integrity)\nfor inserted data. Can use any algorithm listed in `crypto.getHashes()` or\n`'omakase'`/`'お任せします'` to pick a random hash algorithm on each insertion. You\nmay also use any anagram of `'modnar'` to use this feature.\n\nCurrently only supports one algorithm at a time (i.e., an array length of\nexactly `1`). Has no effect if `opts.integrity` is present.\n\n##### `opts.memoize`\n\nDefault: null\n\nIf provided, cacache will memoize the given cache insertion in memory, bypassing\nany filesystem checks for that key or digest in future cache fetches. Nothing\nwill be written to the in-memory cache unless this option is explicitly truthy.\n\nIf `opts.memoize` is an object or a `Map`-like (that is, an object with `get`\nand `set` methods), it will be written to instead of the global memoization\ncache.\n\nReading from disk data can be forced by explicitly passing `memoize: false` to\nthe reader functions, but their default will be to read from memory.\n\n##### `opts.tmpPrefix`\nDefault: null\n\nPrefix to append on the temporary directory name inside the cache's tmp dir. \n\n#### `> cacache.rm.all(cache) -> Promise`\n\nClears the entire cache. Mainly by blowing away the cache directory itself.\n\n##### Example\n\n```javascript\ncacache.rm.all(cachePath).then(() => {\n console.log('THE APOCALYPSE IS UPON US 😱')\n})\n```\n\n#### `> cacache.rm.entry(cache, key, [opts]) -> Promise`\n\nAlias: `cacache.rm`\n\nRemoves the index entry for `key`. Content will still be accessible if\nrequested directly by content address ([`get.stream.byDigest`](#get-stream)).\n\nBy default, this appends a new entry to the index with an integrity of `null`.\nIf `opts.removeFully` is set to `true` then the index file itself will be\nphysically deleted rather than appending a `null`.\n\nTo remove the content itself (which might still be used by other entries), use\n[`rm.content`](#rm-content). Or, to safely vacuum any unused content, use\n[`verify`](#verify).\n\n##### Example\n\n```javascript\ncacache.rm.entry(cachePath, 'my-thing').then(() => {\n console.log('I did not like it anyway')\n})\n```\n\n#### `> cacache.rm.content(cache, integrity) -> Promise`\n\nRemoves the content identified by `integrity`. Any index entries referring to it\nwill not be usable again until the content is re-added to the cache with an\nidentical digest.\n\n##### Example\n\n```javascript\ncacache.rm.content(cachePath, 'sha512-SoMeDIGest/IN+BaSE64==').then(() => {\n console.log('data for my-thing is gone!')\n})\n```\n\n#### `> cacache.index.compact(cache, key, matchFn, [opts]) -> Promise`\n\nUses `matchFn`, which must be a synchronous function that accepts two entries\nand returns a boolean indicating whether or not the two entries match, to\ndeduplicate all entries in the cache for the given `key`.\n\nIf `opts.validateEntry` is provided, it will be called as a function with the\nonly parameter being a single index entry. The function must return a Boolean,\nif it returns `true` the entry is considered valid and will be kept in the index,\nif it returns `false` the entry will be removed from the index.\n\nIf `opts.validateEntry` is not provided, however, every entry in the index will\nbe deduplicated and kept until the first `null` integrity is reached, removing\nall entries that were written before the `null`.\n\nThe deduplicated list of entries is both written to the index, replacing the\nexisting content, and returned in the Promise.\n\n#### `> cacache.index.insert(cache, key, integrity, opts) -> Promise`\n\nWrites an index entry to the cache for the given `key` without writing content.\n\nIt is assumed if you are using this method, you have already stored the content\nsome other way and you only wish to add a new index to that content. The `metadata`\nand `size` properties are read from `opts` and used as part of the index entry.\n\nReturns a Promise resolving to the newly added entry.\n\n#### `> cacache.clearMemoized()`\n\nCompletely resets the in-memory entry cache.\n\n#### `> tmp.mkdir(cache, opts) -> Promise`\n\nReturns a unique temporary directory inside the cache's `tmp` dir. This\ndirectory will use the same safe user assignment that all the other stuff use.\n\nOnce the directory is made, it's the user's responsibility that all files\nwithin are given the appropriate `gid`/`uid` ownership settings to match\nthe rest of the cache. If not, you can ask cacache to do it for you by\ncalling [`tmp.fix()`](#tmp-fix), which will fix all tmp directory\npermissions.\n\nIf you want automatic cleanup of this directory, use\n[`tmp.withTmp()`](#with-tpm)\n\nSee: [options](#tmp-options)\n\n##### Example\n\n```javascript\ncacache.tmp.mkdir(cache).then(dir => {\n fs.writeFile(path.join(dir, 'blablabla'), Buffer#<1234>, ...)\n})\n```\n\n#### `> tmp.fix(cache) -> Promise`\n\nSets the `uid` and `gid` properties on all files and folders within the tmp\nfolder to match the rest of the cache.\n\nUse this after manually writing files into [`tmp.mkdir`](#tmp-mkdir) or\n[`tmp.withTmp`](#with-tmp).\n\n##### Example\n\n```javascript\ncacache.tmp.mkdir(cache).then(dir => {\n writeFile(path.join(dir, 'file'), someData).then(() => {\n // make sure we didn't just put a root-owned file in the cache\n cacache.tmp.fix().then(() => {\n // all uids and gids match now\n })\n })\n})\n```\n\n#### `> tmp.withTmp(cache, opts, cb) -> Promise`\n\nCreates a temporary directory with [`tmp.mkdir()`](#tmp-mkdir) and calls `cb`\nwith it. The created temporary directory will be removed when the return value\nof `cb()` resolves, the tmp directory will be automatically deleted once that \npromise completes.\n\nThe same caveats apply when it comes to managing permissions for the tmp dir's\ncontents.\n\nSee: [options](#tmp-options)\n\n##### Example\n\n```javascript\ncacache.tmp.withTmp(cache, dir => {\n return fs.writeFile(path.join(dir, 'blablabla'), 'blabla contents', { encoding: 'utf8' })\n}).then(() => {\n // `dir` no longer exists\n})\n```\n\n##### Options\n\n##### `opts.tmpPrefix`\nDefault: null\n\nPrefix to append on the temporary directory name inside the cache's tmp dir. \n\n#### Subresource Integrity Digests\n\nFor content verification and addressing, cacache uses strings following the\n[Subresource\nIntegrity spec](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).\nThat is, any time cacache expects an `integrity` argument or option, it\nshould be in the format `-`.\n\nOne deviation from the current spec is that cacache will support any hash\nalgorithms supported by the underlying Node.js process. You can use\n`crypto.getHashes()` to see which ones you can use.\n\n##### Generating Digests Yourself\n\nIf you have an existing content shasum, they are generally formatted as a\nhexadecimal string (that is, a sha1 would look like:\n`5f5513f8822fdbe5145af33b64d8d970dcf95c6e`). In order to be compatible with\ncacache, you'll need to convert this to an equivalent subresource integrity\nstring. For this example, the corresponding hash would be:\n`sha1-X1UT+IIv2+UUWvM7ZNjZcNz5XG4=`.\n\nIf you want to generate an integrity string yourself for existing data, you can\nuse something like this:\n\n```javascript\nconst crypto = require('crypto')\nconst hashAlgorithm = 'sha512'\nconst data = 'foobarbaz'\n\nconst integrity = (\n hashAlgorithm +\n '-' +\n crypto.createHash(hashAlgorithm).update(data).digest('base64')\n)\n```\n\nYou can also use [`ssri`](https://npm.im/ssri) to have a richer set of functionality\naround SRI strings, including generation, parsing, and translating from existing\nhex-formatted strings.\n\n#### `> cacache.verify(cache, opts) -> Promise`\n\nChecks out and fixes up your cache:\n\n* Cleans up corrupted or invalid index entries.\n* Custom entry filtering options.\n* Garbage collects any content entries not referenced by the index.\n* Checks integrity for all content entries and removes invalid content.\n* Fixes cache ownership.\n* Removes the `tmp` directory in the cache and all its contents.\n\nWhen it's done, it'll return an object with various stats about the verification\nprocess, including amount of storage reclaimed, number of valid entries, number\nof entries removed, etc.\n\n##### Options\n\n##### `opts.concurrency`\n\nDefault: 20\n\nNumber of concurrently read files in the filesystem while doing clean up.\n\n##### `opts.filter`\nReceives a formatted entry. Return false to remove it.\nNote: might be called more than once on the same entry.\n\n##### `opts.log`\nCustom logger function:\n```\n log: { silly () {} }\n log.silly('verify', 'verifying cache at', cache)\n```\n\n##### Example\n\n```sh\necho somegarbage >> $CACHEPATH/content/deadbeef\n```\n\n```javascript\ncacache.verify(cachePath).then(stats => {\n // deadbeef collected, because of invalid checksum.\n console.log('cache is much nicer now! stats:', stats)\n})\n```\n\n#### `> cacache.verify.lastRun(cache) -> Promise`\n\nReturns a `Date` representing the last time `cacache.verify` was run on `cache`.\n\n##### Example\n\n```javascript\ncacache.verify(cachePath).then(() => {\n cacache.verify.lastRun(cachePath).then(lastTime => {\n console.log('cacache.verify was last called on' + lastTime)\n })\n})\n```\n","readmeFilename":"README.md","users":{"jhq":true,"ferrari":true,"sharper":true,"zazaian":true,"losymear":true,"max_devjs":true,"daniellink":true,"charlotteis":true,"flumpus-dev":true,"wangnan0610":true}} \ No newline at end of file +{ + "name": "cacache", + "description": "Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.", + "dist-tags": { + "latest": "18.0.3" + }, + "versions": { + "18.0.3": { + "name": "cacache", + "version": "18.0.3", + "author": { + "name": "GitHub Inc." + }, + "license": "ISC", + "_id": "cacache@18.0.3", + "bugs": { + "url": "https://github.com/npm/cacache/issues" + }, + "tap": { + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ] + }, + "dist": { + "shasum": "864e2c18414e1e141ae8763f31e46c2cb96d1b21", + "tarball": "http://localhost:4260/cacache/cacache-18.0.3.tgz", + "fileCount": 17, + "integrity": "sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==", + "attestations": { + "url": "http://localhost:4260/attestations/cacache@18.0.3", + "provenance": { + "predicateType": "https://slsa.dev/provenance/v1" + } + }, + "unpackedSize": 63516 + }, + "main": "lib/index.js", + "engines": { + "node": "^16.14.0 || >=18.0.0" + }, + "gitHead": "f9ebcea7e36403d37cd46da1567f40302b950ea7", + "scripts": { + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", + "snap": "tap", + "test": "tap", + "lintfix": "npm run lint -- --fix", + "coverage": "tap", + "postlint": "template-oss-check", + "postsnap": "npm run lintfix --", + "posttest": "npm run lint", + "npmclilint": "npmcli-lint", + "test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test", + "template-oss-apply": "template-oss-apply --force" + }, + "repository": { + "url": "git+https://github.com/npm/cacache.git", + "type": "git" + }, + "_npmVersion": "10.7.0", + "description": "Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.", + "directories": {}, + "templateOSS": { + "publish": "true", + "version": "4.22.0", + "windowsCI": false, + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten." + }, + "_nodeVersion": "22.1.0", + "dependencies": { + "tar": "^6.1.11", + "glob": "^10.2.2", + "ssri": "^10.0.0", + "p-map": "^4.0.0", + "minipass": "^7.0.3", + "lru-cache": "^10.0.1", + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "minipass-flush": "^1.0.5", + "unique-filename": "^3.0.0", + "minipass-collect": "^2.0.1", + "minipass-pipeline": "^1.2.4" + }, + "cache-version": { + "index": "5", + "content": "2" + }, + "_hasShrinkwrap": false, + "devDependencies": { + "tap": "^16.0.0", + "@npmcli/template-oss": "4.22.0", + "@npmcli/eslint-config": "^4.0.0" + } + } + }, + "author": { + "name": "GitHub Inc." + }, + "repository": { + "url": "git+https://github.com/npm/cacache.git", + "type": "git" + }, + "license": "ISC", + "homepage": "https://github.com/npm/cacache#readme", + "bugs": { + "url": "https://github.com/npm/cacache/issues" + }, + "readmeFilename": "README.md" +} diff --git a/tests/registry/npm/camelcase/registry.json b/tests/registry/npm/camelcase/registry.json index 5d99ae0816..850775e1d0 100644 --- a/tests/registry/npm/camelcase/registry.json +++ b/tests/registry/npm/camelcase/registry.json @@ -1 +1,66 @@ -{"_id":"camelcase","_rev":"67-3c23ff2ea060a6f90508b3f2e8f42a6b","name":"camelcase","time":{"modified":"2022-06-13T05:30:29.295Z","created":"2013-10-30T20:39:45.449Z","0.0.0":"2013-10-30T20:39:50.719Z","1.0.0":"2014-10-12T11:06:54.223Z","1.0.1":"2014-10-12T12:07:56.522Z","1.0.2":"2014-11-25T07:46:37.286Z","1.1.0":"2015-05-15T23:13:02.556Z","1.2.0":"2015-07-30T15:11:19.077Z","1.2.1":"2015-08-01T10:38:13.833Z","2.0.0":"2015-11-15T12:49:16.601Z","2.0.1":"2015-11-17T14:12:18.285Z","2.1.0":"2016-01-24T18:40:18.240Z","2.1.1":"2016-03-12T17:30:36.527Z","3.0.0":"2016-05-04T17:33:27.903Z","4.0.0":"2016-11-08T15:54:49.686Z","4.1.0":"2017-03-30T09:16:02.724Z","5.0.0":"2018-03-28T11:08:34.664Z","5.1.0":"2019-03-04T05:21:30.689Z","5.2.0":"2019-03-05T05:33:09.693Z","5.3.0":"2019-04-01T08:20:50.223Z","5.3.1":"2019-04-03T13:34:32.701Z","6.0.0":"2020-04-07T03:23:00.391Z","6.1.0":"2020-10-10T17:04:08.402Z","6.2.0":"2020-10-28T22:19:50.567Z","6.2.1":"2021-11-15T02:48:10.463Z","6.3.0":"2022-01-01T20:29:34.388Z","7.0.0":"2022-06-06T05:08:17.147Z"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist-tags":{"latest":"7.0.0"},"description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","readme":"# camelcase\n\n> Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`\n\nCorrectly handles Unicode strings.\n\nIf you use this on untrusted user input, don't forget to limit the length to something reasonable.\n\n## Install\n\n```sh\nnpm install camelcase\n```\n\n## Usage\n\n```js\nimport camelCase from 'camelcase';\n\ncamelCase('foo-bar');\n//=> 'fooBar'\n\ncamelCase('foo_bar');\n//=> 'fooBar'\n\ncamelCase('Foo-Bar');\n//=> 'fooBar'\n\ncamelCase('розовый_пушистый_единорог');\n//=> 'розовыйПушистыйЕдинорог'\n\ncamelCase('Foo-Bar', {pascalCase: true});\n//=> 'FooBar'\n\ncamelCase('--foo.bar', {pascalCase: false});\n//=> 'fooBar'\n\ncamelCase('Foo-BAR', {preserveConsecutiveUppercase: true});\n//=> 'fooBAR'\n\ncamelCase('fooBAR', {pascalCase: true, preserveConsecutiveUppercase: true}));\n//=> 'FooBAR'\n\ncamelCase('foo bar');\n//=> 'fooBar'\n\nconsole.log(process.argv[3]);\n//=> '--foo-bar'\ncamelCase(process.argv[3]);\n//=> 'fooBar'\n\ncamelCase(['foo', 'bar']);\n//=> 'fooBar'\n\ncamelCase(['__foo__', '--bar'], {pascalCase: true});\n//=> 'FooBar'\n\ncamelCase(['foo', 'BAR'], {pascalCase: true, preserveConsecutiveUppercase: true})\n//=> 'FooBAR'\n\ncamelCase('lorem-ipsum', {locale: 'en-US'});\n//=> 'loremIpsum'\n```\n\n## API\n\n### camelCase(input, options?)\n\n#### input\n\nType: `string | string[]`\n\nString to convert to camel case.\n\n#### options\n\nType: `object`\n\n##### pascalCase\n\nType: `boolean`\\\nDefault: `false`\n\nUppercase the first character: `foo-bar` → `FooBar`\n\n##### preserveConsecutiveUppercase\n\nType: `boolean`\\\nDefault: `false`\n\nPreserve consecutive uppercase characters: `foo-BAR` → `FooBAR`.\n\n##### locale\n\nType: `false | string | string[]`\\\nDefault: The host environment’s current locale.\n\nThe locale parameter indicates the locale to be used to convert to upper/lower case according to any locale-specific case mappings. If multiple locales are given in an array, the best available locale is used.\n\n```js\nimport camelCase from 'camelcase';\n\ncamelCase('lorem-ipsum', {locale: 'en-US'});\n//=> 'loremIpsum'\n\ncamelCase('lorem-ipsum', {locale: 'tr-TR'});\n//=> 'loremİpsum'\n\ncamelCase('lorem-ipsum', {locale: ['en-US', 'en-GB']});\n//=> 'loremIpsum'\n\ncamelCase('lorem-ipsum', {locale: ['tr', 'TR', 'tr-TR']});\n//=> 'loremİpsum'\n```\n\nSetting `locale: false` ignores the platform locale and uses the [Unicode Default Case Conversion](https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#simple-single-character-case-mapping) algorithm:\n\n```js\nimport camelCase from 'camelcase';\n\n// On a platform with 'tr-TR'\n\ncamelCase('lorem-ipsum');\n//=> 'loremİpsum'\n\ncamelCase('lorem-ipsum', {locale: false});\n//=> 'loremIpsum'\n```\n\n## camelcase for enterprise\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of camelcase and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-camelcase?utm_source=npm-camelcase&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n\n## Related\n\n- [decamelize](https://github.com/sindresorhus/decamelize) - The inverse of this module\n- [uppercamelcase](https://github.com/SamVerschueren/uppercamelcase) - Like this module, but to PascalCase instead of camelCase\n- [titleize](https://github.com/sindresorhus/titleize) - Capitalize every word in string\n- [humanize-string](https://github.com/sindresorhus/humanize-string) - Convert a camelized/dasherized/underscored string into a humanized one\n- [camelcase-keys](https://github.com/sindresorhus/camelcase-keys) - Convert object keys to camel case\n","versions":{"1.0.0":{"name":"camelcase","version":"1.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"f04fb9e9f67a015b74d3686a8f9fd39f98a0a501","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.0.0","_shasum":"922e65c1ca86276972a94de002b4e06e215324a0","_from":".","_npmVersion":"2.1.2","_nodeVersion":"0.10.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"922e65c1ca86276972a94de002b4e06e215324a0","tarball":"http://localhost:4260/camelcase/camelcase-1.0.0.tgz","integrity":"sha512-fpWAbaR/oqERzTdXNqmh12wTeBxl3vFe8caG+6QbpWwLzo6t7f4UHi2/qoKrROi/GDzc2bumYgMbZKbeYAYSiQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB2UAFC/MMcv7rK37qXHraqGZDPHTMEkyYq26o0wFRi5AiEAjNdax3NPYlmFRi4xZQmTGd7jL21EmfDy+5FI/mFRsOY="}]},"directories":{}},"1.0.1":{"name":"camelcase","version":"1.0.1","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"4cdcb6a37bc99bffbc5645f8b1be88f9f512f486","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.0.1","_shasum":"f4f09e56e00a7749a4579f7741a61a2180797220","_from":".","_npmVersion":"2.1.2","_nodeVersion":"0.10.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"f4f09e56e00a7749a4579f7741a61a2180797220","tarball":"http://localhost:4260/camelcase/camelcase-1.0.1.tgz","integrity":"sha512-dBi8+nyjQjeS2iC2u0xOrUUv0riwpNpCnjySvvbFjpoxi8JdAxWSlF+8nmreIdfVfhMlrPNQvRMPoatZZWKVmQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMwwPRbyR3yAIMuODbS2sNRJAN0mR9PD+lEVaBJhdeiAIhAKHKm4XRrSt3zHHCMITS0fz6pXWkuW5LzYm0VzUWeqt0"}]},"directories":{}},"1.0.2":{"name":"camelcase","version":"1.0.2","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"9d492d45989e5c47a1b3a314e2c132837d3ef295","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.0.2","_shasum":"7912eac1d496836782c976c2d73e874dc54f2eaf","_from":".","_npmVersion":"2.1.5","_nodeVersion":"0.10.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"dist":{"shasum":"7912eac1d496836782c976c2d73e874dc54f2eaf","tarball":"http://localhost:4260/camelcase/camelcase-1.0.2.tgz","integrity":"sha512-5jmcHpJIKH03K+TT918DJAfRWMclqFUCP+H8MGyRzVKu0S3qoiD9o1wOjat1ac5TdZQVBeXvGNxIcxZH86KvZw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1tvv9kUzNrTbk9SepuBf+vRoeiba1vM8nWJlHs+w9vgIgTn+QzDrVqtpE2H9PcFH6LlJvy+sAs5s3MdfQF6yUAtM="}]},"directories":{}},"1.1.0":{"name":"camelcase","version":"1.1.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"552dafacf307f3dd97586b0f96b1d608a2d48b7d","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.1.0","_shasum":"953b25c3bc98671ee59a44cb9d542672da7331b9","_from":".","_npmVersion":"2.9.1","_nodeVersion":"0.12.3","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"953b25c3bc98671ee59a44cb9d542672da7331b9","tarball":"http://localhost:4260/camelcase/camelcase-1.1.0.tgz","integrity":"sha512-6Pk70dNCOqZqdKzleSY290parUC4Fn8kuO/GEaAZnk45X693jwW5gONOPULFqkvTL6wux4afSP1aeALN2m9iBw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHU/XomroxaaYxO0LifBfTiTDmvUoYK2L22sSBPET9KXAiACpQdzNBNeijiXX3jaPpdfNBIe07VgAu4ECooNcqZAmg=="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"1.2.0":{"name":"camelcase","version":"1.2.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"ca0d7611a290b9f4bfe9720fe36fa1700da13541","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.2.0","_shasum":"44c851ab95bb936513844be4abd4529337838530","_from":".","_npmVersion":"2.11.2","_nodeVersion":"0.12.5","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"44c851ab95bb936513844be4abd4529337838530","tarball":"http://localhost:4260/camelcase/camelcase-1.2.0.tgz","integrity":"sha512-JUtTqMqthGwzQEGOIfkJ3S06CpC62AbGii/ZM/Y6RczZ9c+3tKbn/R2NlXEwWU3bEHTXDmTMlRp3o8F60E2GCA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC31f46MTZ8f1BDn1lyx3aNfodZYEVkujtMWWLyGHIsTwIhAPeQSHZ/5i9+2WtjFj+HtkE5iyWBM/69O4MWFCvjtdgU"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"1.2.1":{"name":"camelcase","version":"1.2.1","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"node test.js"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"0.0.4"},"gitHead":"185ba12da723be9c1ee986cc2956bdc4c517a141","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@1.2.1","_shasum":"9bb5304d2e0b56698b2c758b08a3eaa9daa58a39","_from":".","_npmVersion":"2.11.2","_nodeVersion":"0.12.5","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"9bb5304d2e0b56698b2c758b08a3eaa9daa58a39","tarball":"http://localhost:4260/camelcase/camelcase-1.2.1.tgz","integrity":"sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICA/82NB8hUaHBXNl3dMGkyo17jorcMvL1o6nknBql4LAiEApOIEU8GFN8tQPQVKvMI32Xt47dhFqNjM8ivyse3fZCI="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"2.0.0":{"name":"camelcase","version":"2.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"2911efeb93b84c10406391c1536edfe73c658588","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@2.0.0","_shasum":"ce69bde576ae24cb4bec697eec93c81809ecbefa","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"ce69bde576ae24cb4bec697eec93c81809ecbefa","tarball":"http://localhost:4260/camelcase/camelcase-2.0.0.tgz","integrity":"sha512-OQAg19G31J5TwLhsEfcWhJCUTAU/U3Kyn79Kb63edi92Ew7d2CDCInqQvBk8B2URwjLHfx3q50TK8QIHj1SYHg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCY/sq0sn41vyB+GP0ERaBQcl2ntOPTOiueD5ottA5PMAIhANw9e+xVzSRitAiT2O+UA78Z+ftFS8f07vsS72FVtz29"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"2.0.1":{"name":"camelcase","version":"2.0.1","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"fb178b39412e3b63ef86bf6933089282d74d85c4","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@2.0.1","_shasum":"57568d687b8da56c4c1d17b4c74a3cee26d73aeb","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"57568d687b8da56c4c1d17b4c74a3cee26d73aeb","tarball":"http://localhost:4260/camelcase/camelcase-2.0.1.tgz","integrity":"sha512-ko1zZK+aZg7Orkv4yPBpFX80JTT8E4DR2XP4CXgk3m+Uy2KLy/vrMzQUtSY2DCXr3j+zhDEOZbyf/FQnjyHTcQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZux7/AUY6Plm9xmzvV1MsJWIh7yPU3CYX+SO2vZ0HrwIhALmGIBBlPUx24dM9uPVLdLsKjtSqtiNKcqZFb+F3GmOc"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"2.1.0":{"name":"camelcase","version":"2.1.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"9b73ccb3f48ab86eccb136c155f0eb2e67f40dc3","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@2.1.0","_shasum":"533ad4cd7f8a1080ded31aba6c79b4bf437ff30c","_from":".","_npmVersion":"3.6.0","_nodeVersion":"4.2.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"533ad4cd7f8a1080ded31aba6c79b4bf437ff30c","tarball":"http://localhost:4260/camelcase/camelcase-2.1.0.tgz","integrity":"sha512-B9NrxP4E6fldGR2F81O4XctfEZOOZNXL5dXmXiOQiWUkmBM1nHCem7BWQtetqEynu2137PlKjvEmjv46wJx6Ug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmLeRWIFTMOUGWLfEZwwUXYRIUsqYtwLotEXpQC6QgRAIhAPmkpC6Wrfch+Ai6jVvpm6U9gm8TS1otXaY5QOYXa5gP"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"2.1.1":{"name":"camelcase","version":"2.1.1","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/camelcase"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"35c9c8abce5b9cc9defe534ab25823dc6383180f","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase","_id":"camelcase@2.1.1","_shasum":"7c1d16d679a1bbe59ca02cacecfb011e201f5a1f","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"7c1d16d679a1bbe59ca02cacecfb011e201f5a1f","tarball":"http://localhost:4260/camelcase/camelcase-2.1.1.tgz","integrity":"sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIChVUk69qXQ110/KimTVtm9jPr35LkIK3YGu3gZIaO9CAiEA26djF5phdIOb+6X1GnSRQvnYUaLoWqKl1yf27WRw0oo="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/camelcase-2.1.1.tgz_1457803836074_0.4515206723008305"},"directories":{}},"3.0.0":{"name":"camelcase","version":"3.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"d4de0e37b625e38a880efc6517194917a5beda01","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@3.0.0","_shasum":"32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a","_from":".","_npmVersion":"3.8.9","_nodeVersion":"4.4.2","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a","tarball":"http://localhost:4260/camelcase/camelcase-3.0.0.tgz","integrity":"sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUECihlQbKhHsgSDfuJ6Ve9P4ArY82BEd6ZyVJHEZ53AIgQB9k9ieqIPxkFkz6s8oZTUAza2bNzZ1WM/7gjxr5ECA="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/camelcase-3.0.0.tgz_1462383205197_0.03801905922591686"},"directories":{}},"4.0.0":{"name":"camelcase","version":"4.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"xo":{"esnext":true},"gitHead":"b1f77b8185bc99f32ba6fcf7a9ffd87a802f1152","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@4.0.0","_shasum":"8b0f90d44be5e281b903b9887349b92595ef07f2","_from":".","_npmVersion":"2.15.9","_nodeVersion":"4.6.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"8b0f90d44be5e281b903b9887349b92595ef07f2","tarball":"http://localhost:4260/camelcase/camelcase-4.0.0.tgz","integrity":"sha512-xi6I2qnvM3JgpP3rfhe0htvuqk2EG8coOfadGaNBiTVemKQCphPKNEvuq3TlMBmIIoSdQw/VZdeisnVaqaPB0g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyPr4FFxQi3a/ckk40Ne7IKIuJKj3en0hxvzbyJS1H0wIhAP7l5Si42uxBNUMIwoFPE4kQ9Ytj1hdd1+PjvoqgWv3S"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/camelcase-4.0.0.tgz_1478620489451_0.9916922175325453"},"directories":{}},"4.1.0":{"name":"camelcase","version":"4.1.0","description":"Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=4"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert"],"devDependencies":{"ava":"*","xo":"*"},"xo":{"esnext":true},"gitHead":"0e6e4a2752aa013b8e9477145c7b8132c95a82ef","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@4.1.0","_shasum":"d545635be1e33c542649c69173e5de6acfae34dd","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.8.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"d545635be1e33c542649c69173e5de6acfae34dd","tarball":"http://localhost:4260/camelcase/camelcase-4.1.0.tgz","integrity":"sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIETEa+wptnVyAB8yMPWHboi6ZLAkmqWMS26aRaf7gQe5AiBApVswv1QsT+NEpIYUMV9u8EOBZQGdZ8VYMzLdQE1kwg=="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/camelcase-4.1.0.tgz_1490865362489_0.433825216954574"},"directories":{}},"5.0.0":{"name":"camelcase","version":"5.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava"},"files":["index.js"],"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"*","xo":"*"},"gitHead":"a526ef0399f9a1310eaacafa0ae4a69da4a2f1ad","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@5.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.10.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==","shasum":"03295527d58bd3cd4aa75363f35b2e8d97be2f42","tarball":"http://localhost:4260/camelcase/camelcase-5.0.0.tgz","fileCount":4,"unpackedSize":5089,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA10dWQJ/Lelzqu9pRRsP6ehAI1G9DUOn3KVEpMgJYunAiBZNhT8Es8eMCmj3wJqthjdzWcO5+ExFx/FGBsYH/2/5A=="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_5.0.0_1522235314616_0.509666479685914"},"_hasShrinkwrap":false},"5.1.0":{"name":"camelcase","version":"5.1.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.2.1","xo":"^0.24.0"},"gitHead":"134172c3ecd5a7d098cb905fcc503ad82614c5ae","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@5.1.0","_nodeVersion":"10.15.1","_npmVersion":"6.8.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-WP9f9OBL/TAbwOFBJL79FoS9UKUmnp82RWnhlwTgrAJeMq7lytHhe0Jzc6/P7Zq0+2oviXJuPlvkZalWUug9gg==","shasum":"29e83b9cfaf7ad478f401a187ae089cf83c257ea","tarball":"http://localhost:4260/camelcase/camelcase-5.1.0.tgz","fileCount":4,"unpackedSize":5948,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcfLXbCRA9TVsSAnZWagAAkQAP/irBPeRWGxnADjwJL0zL\n+AAANPU4El4ND0mjeZqy0T/2hdfAGxUU1H1sLTou5GWo0ybf977gIoQaNelh\n3NgxSQY1JD0rI3RxMShfF/gfOccwhbdAuGe0kjl/m+TeOz18j4Z0ZYd6Rmqa\nNRz2Lxj+Oc0Prt9LFHN9SiPlj6w6tcquh2E1Dyxzn83KrCWHX5lsZaru3vly\nNfnPVI5GheT9ACTqTbOjj4WUvEGGb66uMIYYq2YqFEbcq1A9/82WUf4T6xYD\nySOPn+PDf88BzUmG6pdKRWqiMZcsmNI+oZvoemAtpIoa0qNmcFcTJWyrVY+b\nr3xAX33kQsKatkN3cR66eJdOlu0alHYYN4hiQOtdPhpDnXMyFq/I6fJ1DQ02\nuLl7EGYOMTNjOWcqb87Xqo1hlaoJH9q9Mk5HAOxsXGyW29Ew7WBE2I8lUEV3\n4Wo7Ktrz/l1qmG4juQ3CTdDjI/QykM1eau1JCBW857LXAL1pXHiU4fYZ8lG8\nxtQRkpX1dhcVc7c7uZkaFeKr+NkLPQ8+uLsTu8XvUKafcc0glPU7QqyNfIN/\nyBkGqQ4J9Tl6rCXefSijGsFdaOBgMhI7EQQWDM7ANc00Arbm9qjMjlKjfK6P\nIKGBVV+wcxbONy/ciUFMOIDbI7gUa6UM6F78YLYjtCJIffCCnTYbVH1rmszJ\n0gYy\r\n=ErOn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwSe5nYYD8DkZLiNcodEy0KKIZvy4KpTY562RLfqcyWQIhAIYQ/B28YYWmbR9hPBkyjR/aNUqlTKkS10uEyN9w8qmi"}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_5.1.0_1551676890480_0.9018404055431712"},"_hasShrinkwrap":false},"5.2.0":{"name":"camelcase","version":"5.2.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava && tsd-check"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.2.1","tsd-check":"^0.3.0","xo":"^0.24.0"},"gitHead":"3eae33df5e286fcd550c52da971c675b73294cb3","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@5.2.0","_nodeVersion":"8.15.0","_npmVersion":"6.8.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==","shasum":"e7522abda5ed94cc0489e1b8466610e88404cf45","tarball":"http://localhost:4260/camelcase/camelcase-5.2.0.tgz","fileCount":5,"unpackedSize":6497,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcfgoXCRA9TVsSAnZWagAAg+4P/0jZzN99uGyHnMq9wryI\nLWEdeWcsoTnFxTBUQ7ibRwpYzRxJC7rkaIlL8Y3omJ+0uLs4XkF7nxHbFiEs\nJOzLLDfenlVIdd6g7meck9Zmj37Z/RacwlElrSq37VB4TP8a0AUzB8aGsABV\n74BxjTOmq1RfoiPf1pW11ZikgOftc2IfT7I6Q2f+I5Qd07Y/uy6DqcbH+1Dy\nRlIiJZQjr+4iwDcD3hxqVPAi6Ie4Jq3u1MxwLT5fc3RJ7ONckJi41kEM0fel\n6Ev2oMq3QyLBRR/7EnDdytXN5cZhlT7X5vIzjpI0ceI8MsNNAMtkPNm5E+eW\nEkrLhn7cfJmi2voLgixVLNiFM7DJwKIhlZiFDt79sOPbYPd5/7Uukc6yYc9X\nkKNMF8qa0/AerZe1H9LajJsE19VFzG9cp17e/wyn1+tKap+KROIUfIZhUVlH\nVqpatcvEjnSiNqK+/KISJ//Hw12aFZ7yQCGB9srHfzm/Xgg1p1uXawWjHW//\nj76q+0o/08AMnKxS7uoBLq/xcDq2rFWMNF0fnl47aKoA55QjD4IAW9HvMY48\nlQ0uwlHw65UElMzOM/ZXu3LZDENA2nntWXvX7SOl5DCMtzoj737EmQ82Xey+\nVsCxh++n4Mb8TV3k3sVDbCtQdW3OucQx4bWn0vN8cg04MS1pb5CIAhl+kT45\nRHlk\r\n=eypF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvtolOQWzIpxbewxoTcUbzxgfltp2rxUV1vFX2/5GKMAIgQR3HosHPeKtcdA8xS0IO0hzv5NdDgL4T74hiMnfVIlo="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_5.2.0_1551763989562_0.7397484159919618"},"_hasShrinkwrap":false},"5.3.0":{"name":"camelcase","version":"5.3.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.7.1","xo":"^0.24.0"},"gitHead":"75014061a127d6e2c35503059605c4f655fe66db","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@5.3.0","_nodeVersion":"8.15.0","_npmVersion":"6.9.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Y05ICatFYPAfykDIB7VdwSJ0LUl1yq/BwO2OpyGGLjiRe1fgzTwVypPiWnzkGFOVFHXrCXUNBl86bpjBhZWSJg==","shasum":"0a110882cbeba41f72f99fcf918f4a0a92a13ebf","tarball":"http://localhost:4260/camelcase/camelcase-5.3.0.tgz","fileCount":5,"unpackedSize":7466,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcocniCRA9TVsSAnZWagAAxccP/jOyplmYsEKSaSjqTYGh\n7ct5y8VLjlhXhWkO/b24qsIA5d3cbTkL3kwBZ3ZnG03WUq3atayhj86FtJ/N\nsQTJd2C2KwA0OdiWZLK5GuZYuWMcVWoEq3Rbl2I1usurlc7oUbDXN3gA1PvJ\nOliOcYqQrgUFGtOjS1vATqM2G0mXiDjDtnDqr/jNOzW/xbOULVBUMLYWRk6X\n3xd1knSqRT5xI0FQoi6aUNF6EU8W8V7AlAGks7S54PBAmzTsTnbd6O3oEsif\nc5KWyLtpu96Ocb4WzNDCNVADTnhtQ1EXquloj9Q3/tNdTmiGYUOCsiPWJh1Q\n9chFROUIBePUJDXBTnO7Vydw7J9VQc8BBgDQ7wJJ8DrEG0ppUUl0EALK4tRv\nGTsW9+80/mNgJjtIMwbq7utDzJbLJjtXP3A2Pvy0wBZK3hqWD7GZTbp1GVOV\n8MnLz84vRpFiSf9Er+jR6I9x54wzTMeIlLgzrnrqupmeFYYoa+Wyrt83ctIc\nm3dWqFwRXUHbFtToDD/nh202oiS1IxQ8O+dX2okWDYGzsokUHBp/oUQTy9LK\n665Hd4r1jCd91qAPyF9nbSLEE61wR44ZBTWoPiXFPck8iyu7U3T6i8SCXcDy\ngOgBMMkl98K4hlePGMckHKh9f5qoRztOSmBK8ZmTVxogdaxQTc9DRUqjM6Zl\niJ0m\r\n=P1Re\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDuhv3xahPE7JApoRKkhJSJju4V5OpFgxEa9C7WkV155AiEA5iWto5dO8nU1BppyzDz6ZooCxdz1KMzacIcw/FbhMT0="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_5.3.0_1554106850085_0.4588034976342792"},"_hasShrinkwrap":false},"5.3.1":{"name":"camelcase","version":"5.3.1","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"sindresorhus.com"},"engines":{"node":">=6"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.7.1","xo":"^0.24.0"},"gitHead":"cbe5a519ec6745adbb5283d5ee8c5c9889050d74","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@5.3.1","_nodeVersion":"8.15.0","_npmVersion":"6.9.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==","shasum":"e3c9b31569e106811df242f715725a1f4c494320","tarball":"http://localhost:4260/camelcase/camelcase-5.3.1.tgz","fileCount":5,"unpackedSize":7447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpLZpCRA9TVsSAnZWagAALTcP/1baON6MQMxgPLfVLfwR\n8QRj0qzMyFh7kG92DKB1wI7/9aMYWFPLaYb11734w1mL2omq9SqlTP6BKXOE\nZG4Yl1SQtAA3OUzJbFMi3t9m+/G2yBHHDAFIMQy8l0yXFfxbUmRlQ9Ix5AbR\ni/yU+r9PaJz0qrtRb4dtbTavI/Aj3bBA35lF1PQr/SPFsAGJEMBg7wDL2TDk\nyRQur7ssZjrfr313E1v9hbeWkUrp+i1fiZd9dpSic1TsRutbrCjZLxtWsHMc\nfAQPKqrx94gPgn1qqyYDxtCBdEoKIAhHN9hvPTGJ8r0ueR07DyyaVvaxlTfV\nfAjVDOH6cS5D9y1121j3++MCv7DL3I4XgfYtGkVZj5a0//UJX0aj4GmxFBU8\n7YppCnQiAl9r8Vhz8fHNPlRnx52X/dWxZHD8bDRXsYg1OxiwZecCJJtayB42\nYzX8QB9Wq/u2/EojyyW+4w4CrcVC8wgOMlQP7gaueNHLV/FefEPP+CTshyk/\nwxFS6vkd/tARb5gdQLKxxkvpcvJVyDl7PDXfsYO86rUA2JNf9wCIeAKmC0nX\ngGcEn8Ew7oe5rM6UaTZGBiOJER9Kcf5xZ24/01J82vGWnuqX8tC/C/iWrBKe\nfyXXqmZ38xENnHfb/W2HqTxCuEzg28Imms55Rmi14FmRr8s7ekPdo0PuSwPW\nGg2u\r\n=OQtl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDuztwb7jkQu1SGrBiLhWlKTz4LQmOPO1cvIa0jaYKlHAiEA/HsA5Up0bHLv4nO7dBYAx04p4PXcfzIvW7jFvYNmDzs="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_5.3.1_1554298472491_0.4347901486248773"},"_hasShrinkwrap":false},"6.0.0":{"name":"camelcase","version":"6.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.11.0","xo":"^0.28.3"},"gitHead":"5a0d0919eb2228578e1670f42675d1acb5e5c317","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@6.0.0","_nodeVersion":"10.19.0","_npmVersion":"6.13.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==","shasum":"5259f7c30e35e278f1bdc2a4d91230b37cad981e","tarball":"http://localhost:4260/camelcase/camelcase-6.0.0.tgz","fileCount":5,"unpackedSize":7415,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJei/IUCRA9TVsSAnZWagAASEMQAKA4Tx3t3ZP1i8OfRYn3\nfzHKf7hELGzAHO9DjHzVSq6FVk4fq2NRF8GKXR9DFbAdaE4wfjfgZ4y/cnQz\nCGbMIT7TaplnZ2kuARxLnyH0/7Y5pmBzKrYsJ2yg+RphWHUj/zDuskKbvnm0\nUSVHCvXkViSAqeui1V/v1MgFkrseQoWAqzj5I8kDpgr9Rx3hgCIpGjUdj1OB\n9HkvNax7VVmjGl8ufSGe+cBiHnaGtfDHYh+cnkLMhgoFlY59zvu33y9wQTHO\nqNb6HN7tGwxhEot/2zT450deXsNTpt8eG3kg38fqgM4m5U3ExS9V+JKRr/5y\nRF+UT7JI4hNdoGk6XI7cZW9u1AnipN0VJPrcD0+HdHrqhWJwXfVym51I0DiL\njcR3q5GilfgvKVAC+YmCtTTGc8VbCI/1IOmmgqwfmmSfc8fn85JJMRY0fMMk\n8qyDJRZLPfruC+Et7VGGf0NMvQMeQdp9w+YACdGh+YEvhTNvvypW+9qAC3Ze\nk2Yujb36WypXq/HiXeOCvIQ6ZqtXD6qzu29Cv5uCe2xk/Q9rOONTy/ZW8qTW\nkkm+Ai90TqbWBq33fsR2qLS4DivAfK+8a+o0yRI26P7bF6T0UvW7y8rlReNI\noLh1rxV610f+PVSXG17pkPXWo6eEX1DuU1fo8Z70l0VNRoS6xbPC/drqRgbz\n+kOJ\r\n=RKdy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC33kpEuqhQFzesBNKu9mG7oAGxPpQWPB5kgy0S5U3meAIgBByxe0bWWZN3cwzdhfa1/d1zjAYecmzGcNXzp9t3qYc="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_6.0.0_1586229780284_0.34572182948635266"},"_hasShrinkwrap":false},"6.1.0":{"name":"camelcase","version":"6.1.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.11.0","xo":"^0.28.3"},"gitHead":"a077c7bcf5a37630f3733fd7dcd377991377ac32","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@6.1.0","_nodeVersion":"14.11.0","_npmVersion":"6.14.8","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-WCMml9ivU60+8rEJgELlFp1gxFcEGxwYleE3bziHEDeqsqAWGHdimB7beBFGjLzVNgPGyDsfgXLQEYMpmIFnVQ==","shasum":"27dc176173725fb0adf8a48b647f4d7871944d78","tarball":"http://localhost:4260/camelcase/camelcase-6.1.0.tgz","fileCount":5,"unpackedSize":9234,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgemICRA9TVsSAnZWagAAsXAP/ifYJquEDBu39tTtVUO3\nvRqaxrDY0NGAqP8TZGPoGJD30dDenPh93MzPonvziOweD6rrQd/iIKSLCnLh\nLgpEtiLIn07Vn/17Rs3bVDQ0nQILusNNk/2GoFy3TfGB+cSsZqaiVKPsG5X7\nnBxU4pftZIhGHE9uuEjm9zVgFUJ3K5VWIAiNeANZWxFwLZ4WyqsJvFw56Koy\nbw3JR1Tc8jO0qRLwyH4UD9em9u1bYXc3p3+6Ift/Shk00KQ8yatSufXCvYrq\nI5+sBLEQOMquLYdOTpO1UO6hcV8HpOk1vD1tjr+16VN/TCrHAAxWuD4dkQ3Z\nkIN5lyJj2eAY9gwqhxwDygdevYIPQaDJf6xIr71jpx5ylJz4ijD1ec2lOA5H\njFCsNanofD7JZj4FVZt8IE0Sx6VGW2J9bFEpDqSxsr4jsyhqF9j0ExnJ7m9U\nCBm/gQSjPglm57j9t65oI4CP5rd6BcaR7CH5zl9E5KG+YXE8WRJ5sMsf3Zek\nLorSWcYDqjBynCcwAnYqJsnqNolkH9nAWcf5VQTLZfCqFnGYT9KY343BWkGc\nRiO8zPJRW/2p4ljJ4cPHVq0H5pJnD+b0CJC3hfOoQlVtUHR1TzY1+Di5uvz8\nmjVcIl0JK176h3Ct/6i3iCxsWSIzwCK0UBwUOBECSfNiBhOfWvQy/kHsaBGI\njD+K\r\n=qVFq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBMFXhWKRCcS5kaK9qpUwZR+owh6XobERjhu0VeHLTWqAiEA+nQkKg5sb131JQ649VMhXKNqnAZ/6VhCI3PG+u/NmkU="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_6.1.0_1602349448254_0.9683442945546847"},"_hasShrinkwrap":false},"6.2.0":{"name":"camelcase","version":"6.2.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.11.0","xo":"^0.28.3"},"gitHead":"1321775c740c20bd93d0bdbd844703464e0e6de4","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@6.2.0","_nodeVersion":"14.11.0","_npmVersion":"6.14.8","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==","shasum":"924af881c9d525ac9d87f40d964e5cea982a1809","tarball":"http://localhost:4260/camelcase/camelcase-6.2.0.tgz","fileCount":5,"unpackedSize":10385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfme6GCRA9TVsSAnZWagAAG38P/1ERwSZBcvSye2Pg+iwq\nK/cPpP3CgGwupCLBFX5ATzJJm0ai4gI2T127MZK8rVPSw266HKZleXKU+SNQ\nDE5cVkwtSGfQXqXAPitbEbRdquSSShQijGcTAShXQ67LNiOU4n6yKWsHpXCU\nECHgbOHIa6WrGhw8GuRECIaARPY/sEVmsk6B7LJo5SExwfViAJD0wk0uf3l9\nwY/IVPSBDMHZASpwRf9y+C2Y4w+NX72gOAua7wpKcXrI8hfsHS5vDTzV+Xb2\nwlODU/RoFqlNwoVgHcNN09LUV3fZg7dJCb0B7lzcQ03EZyaDl0E6/wLDc/q9\natrqcwaN78aOkivcbAKme9xGE6d+XVdE1f5sklOzo4LRr16Nsd3xsOXNRB6h\nPhYkN6oFt87UFIk5eFeJWsEaCx+9iE1r0zI9F1J26JneZ/amT8vOERLisI7M\nDD+KVEx/neqpmQYvaBpRe7BbrCEsaU1yCMET2iDEX1h2vkAn0LmYLO7g42SA\nhFedWysqH5fHWPadQUorCm0iOkhdtVMSHX7QAFi8Hlna1zVSse7aEn+TCWRM\nZc6H31yJfD4rFTZ3BWNsjTFiCo1KOv3TwalSFyJwdUeWKVBRrmMCVVKf4+zp\nZEnGUKPgdCaFI/Z0ck1/QOJB2YUPAYHAZttzdSlnG1IWMEy5R8014hCr0mnx\nNfet\r\n=36QW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFf25wRdhBTACDJHMlBUM+MPRRsj6OkQviuSP6Pb20PvAiEAi2eAvYS4UUfK6izsaNs1X8+mS2OMuu0UQznFLXFkjhc="}]},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_6.2.0_1603923590373_0.6280326369817386"},"_hasShrinkwrap":false},"6.2.1":{"name":"camelcase","version":"6.2.1","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.11.0","xo":"^0.28.3"},"types":"./index.d.ts","gitHead":"f28c4631fe879bd430e21a3c1b380e158c53184a","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@6.2.1","_nodeVersion":"12.22.1","_npmVersion":"8.1.0","dist":{"integrity":"sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==","shasum":"250fd350cfd555d0d2160b1d51510eaf8326e86e","tarball":"http://localhost:4260/camelcase/camelcase-6.2.1.tgz","fileCount":5,"unpackedSize":10892,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDKBbpz1A/dKnTeZrGWYYwXVugvVfEEUS4WYD8i1UE6uAiEAnECDhCzj/NNrTDl2UPk7rh16COKj/nvmOhCOQs7JidU="}]},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_6.2.1_1636944490324_0.49364627338998623"},"_hasShrinkwrap":false},"6.3.0":{"name":"camelcase","version":"6.3.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"engines":{"node":">=10"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^1.4.1","tsd":"^0.11.0","xo":"^0.28.3"},"types":"./index.d.ts","gitHead":"497d7fc3ae98b2232af1e56aa24f82878d7f53f0","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@6.3.0","_nodeVersion":"12.22.1","_npmVersion":"8.1.0","dist":{"integrity":"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==","shasum":"5685b95eb209ac9c0c177467778c9c84df58ba9a","tarball":"http://localhost:4260/camelcase/camelcase-6.3.0.tgz","fileCount":5,"unpackedSize":11697,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh0LmuCRA9TVsSAnZWagAAP4AP/1gUxyZEJLRQeUFqXoAl\nEWAsu3QGU6KkzCmfcbAtMhJe4YTcofQE6ORuZURsEFLvT+gfY7yemgBNMfMU\ntjoVWvz3Q0eM5qoquB3WLD6WncKPCDQJSZybKcxFH7KgO8fbL/aWnVdpX2jI\npuD0SpXryCZFQo9KHPydhEgPqW28WsDxK40qxfDcYee7ibCOUTkYybk1xg3F\nsl1G10dp6knF/PBejgWDp3nh8jNED4aRI3EBdGEltoLKVG7XHUL978tRhW/4\n2zPExJ2BCST0E+57Ez7Rmas9pFazZXIZM0lCOkTYoFEVoGB5lx/a4J6YbrNp\njg07zcSTz2W3AHCy5/E1EzYRsPsaeDEg/rrOnP36xPnIlDh8Vq6Y+eqBPG+U\naW8E531bKCJrDL4tPIuGh6zx21lK5MS8WCWOL80Frvb64pu00AM3pE88rVSS\nWzY9SExOm85EEctMptR1+HkjF1fECx7jxcGKRBHJ9DF3I5nrhmxYYmRb4rym\nkIkaV8ukB/E8imf90FzID7GdxC7349JOway4SQ1yj2RVZROYskkbGsLKSCB6\n384B/sjGkA+17U/MSNl8AJBTOPaKdfbe69q3+8vsXoYu6DjYXzyk5OyVmgwq\ncQ/iMmCersknIFYhcPUm/IHN16pwFz5hybJg28aJLMJeei8CMldgPM4GiTsM\nIo/4\r\n=dAx5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB6upqnQaGJh3JKO9Mvp1LiigRYrUZK4ad1Es2msau47AiAlnoIeAVTN9EOPEH2GHN4epICDI9fLib2cQwOHGeXpkg=="}]},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_6.3.0_1641068974256_0.6782005025667823"},"_hasShrinkwrap":false},"7.0.0":{"name":"camelcase","version":"7.0.0","description":"Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`","license":"MIT","repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"funding":"https://github.com/sponsors/sindresorhus","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"type":"module","exports":"./index.js","types":"./index.d.ts","engines":{"node":">=14.16"},"scripts":{"test":"xo && ava && tsd"},"keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"devDependencies":{"ava":"^4.3.0","tsd":"^0.20.0","xo":"^0.49.0"},"gitHead":"6f5439a78b523b157b55546b26bdc5e14cd2b923","bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"homepage":"https://github.com/sindresorhus/camelcase#readme","_id":"camelcase@7.0.0","_nodeVersion":"14.19.2","_npmVersion":"8.3.2","dist":{"integrity":"sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ==","shasum":"fd112621b212126741f998d614cbc2a8623fd174","tarball":"http://localhost:4260/camelcase/camelcase-7.0.0.tgz","fileCount":5,"unpackedSize":11478,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHT7aJC5XqgkmJjw8JRZ2iq6L9htWM/oG0KqNdqMXHVsAiEAp/sK++7BIiiiQOVvfXZw0rRUQVrixXGZu7JnND6+EBA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJinYvBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrfSg/8DakHOicB1Vdv1Wn2ELIqH9ES2mB0EVvuQv5N6/15KbTHpFLe\r\n7kv/pp3VQlkv9N6fCQqFh7qo+UHuKXcZiWzsJvNsad9gY2Vwvd+qxh/4hI9t\r\n5UUop3uLGZyzQcFT65CRXwNWpj+ZYPnpdMyEvERVlxQlngx2XYTmQyr/sX5S\r\nXQNNVs07/wcYmTHRkgR7myT748cqVrmNd4LKYD/x2HDAZ55hTGcKW2V1MBdX\r\nNXShpEiVi27n6MwcZSt1bE1ahhSXLibu6MOlK6PXL8i00zAt59d5ICgtK40p\r\ne0rpTLAgg9tw9EZP2TIxNARnBFZSLgc/XsH/pGJQ2DQ3S2tCb01UxgcWQSIT\r\nmhd3IW5FTd3JDmoso2P/VgFoWwgZgNufe0+fELm/MsaFfXu8gAJYwJF8kRH0\r\nqQdK5LC9BsleCIINMBLdr5Okonbupf3X4rIbuOi6HkwMm06u4vRwRGpiuVv/\r\nt9kzh0B/lSUBUMsEnRGCyoLTZ+KvRbhfH7YyfpLKTZ6YBOv1UZzUv6gkXRC2\r\nPvtiu94HXlKgz3XHO2g0MxL8rvbADDvwQqU/iC0N28NB7zu6ybyHniDxOesw\r\nEgiVOaGSHo3DxzH3hFP6gSh1I5CvVbIThPev3ter18syBXFbExGyGQX/OIJ3\r\nQwcnzmvm/ehvKaz8LpMDimrujSqd+ECcZdc=\r\n=Kkhg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/camelcase_7.0.0_1654492096987_0.5837998318613613"},"_hasShrinkwrap":false}},"homepage":"https://github.com/sindresorhus/camelcase#readme","keywords":["camelcase","camel-case","camel","case","dash","hyphen","dot","underscore","separator","string","text","convert","pascalcase","pascal-case"],"repository":{"type":"git","url":"git+https://github.com/sindresorhus/camelcase.git"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"https://sindresorhus.com"},"bugs":{"url":"https://github.com/sindresorhus/camelcase/issues"},"license":"MIT","readmeFilename":"readme.md","users":{"andrebassi":true,"akiva":true,"gochomugo":true,"bret":true,"galenandrew":true,"xiechao06":true,"vwal":true,"docksteaderluke":true,"vzg03566":true,"ridermansb":true,"monolithed":true,"joaquin.briceno":true,"esenor":true,"jetthiago":true,"alanerzhao":true,"mehmetkose":true,"vonmauser":true,"quafoo":true,"domjtalbot":true,"ansonhorse":true,"terrychan":true,"xhou":true,"zhenguo.zhao":true,"vunb":true,"rocket0191":true,"justjavac":true,"shuoshubao":true,"dwqs":true}} +{ + "name": "camelcase", + "dist-tags": { + "latest": "5.3.1" + }, + "description": "Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`", + "versions": { + "5.3.1": { + "name": "camelcase", + "version": "5.3.1", + "description": "Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/camelcase.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=6" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.1", + "xo": "^0.24.0" + }, + "gitHead": "cbe5a519ec6745adbb5283d5ee8c5c9889050d74", + "bugs": { + "url": "https://github.com/sindresorhus/camelcase/issues" + }, + "_id": "camelcase@5.3.1", + "_nodeVersion": "8.15.0", + "_npmVersion": "6.9.0", + "dist": { + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "shasum": "e3c9b31569e106811df242f715725a1f4c494320", + "tarball": "http://localhost:4260/camelcase/camelcase-5.3.1.tgz", + "fileCount": 5, + "unpackedSize": 7447 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "homepage": "https://github.com/sindresorhus/camelcase#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/camelcase.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/camelcase/issues" + }, + "license": "MIT", + "readmeFilename": "readme.md" +} diff --git a/tests/registry/npm/caniuse-lite/registry.json b/tests/registry/npm/caniuse-lite/registry.json index cc953ec71a..f8bce0b593 100644 --- a/tests/registry/npm/caniuse-lite/registry.json +++ b/tests/registry/npm/caniuse-lite/registry.json @@ -1 +1,34 @@ -{"name":"caniuse-lite","dist-tags":{"latest":"1.0.30001473"},"versions":{"0.1.0":{"name":"caniuse-lite","version":"0.1.0","devDependencies":{"all-contributors-cli":"^3.0.7","alphanum-sort":"^1.0.2","ava":"^0.17.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"^1.0.30000605","del-cli":"^0.2.1","json-loader":"^0.5.4","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","timsort":"^0.3.0","webpack":"^1.14.0","webpack-bundle-analyzer":"^2.2.1"},"dist":{"shasum":"22360b6b6803dd211d60415162f0ec33a0a66157","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-0.1.0.tgz","integrity":"sha512-+bl/1LnMUcEnrSt43qw6ATvL0AMV90REcIwNnLJ6DaxaNEB5O+GodKZAJiqP0ZPkAx+QlfqZJhAJYLAy7z1Z9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE51iaglOHbWohmo1OjTkA6zTPOk9o6xJww61UAA/VyvAiBLsVtfGfQlrV7gUNBa3P3mYqDMMYyTz23wDnH5obzvTw=="}]}},"0.2.0":{"name":"caniuse-lite","version":"0.2.0","devDependencies":{"all-contributors-cli":"^3.0.7","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000649","del-cli":"^0.2.1","jest":"^19.0.2","listr":"^0.11.0","mz":"^2.6.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0"},"dist":{"shasum":"9f2731421eb1638cbdade62989176a5a69474128","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-0.2.0.tgz","integrity":"sha512-XVmzwoN7u5WM1H++Mrr+xcT/P167HDdqsGghyqWkhh/63jpy0VcBFQxz4m/0vURFi8y/sTl0Qz+vasGralBH1A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdlzexxvHrtkoO6830AT0q8fdrF/uylOm7EJ284UU2sQIhAM/CZKhwg2yfsmESP6bm3HOq/iPyZmsJ0nXgtfEswxFy"}]}},"0.3.0":{"name":"caniuse-lite","version":"0.3.0","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000653","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"7e182363d002b23e167a8e8f6082147ce7453627","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-0.3.0.tgz","integrity":"sha512-Ca5sPBgZZeEsLzKJ8Zdyw+2a+91yxX3UxrEMTwlxdKTHS6/nJSG5PJkwpQJi3ZNU2w8SkHjdapqlukaURHECzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKlOArj0rR3i7Nb8xJxdUZ8D7uta0bH7DNskEFZkyNbwIhAJVf4T4NhTxN/gjaJZfggGbQiUSZSz1w6r0RLsSZQdjK"}]}},"1.0.30000655":{"name":"caniuse-lite","version":"1.0.30000655","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000655","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"20613c829e27942b3441d47da4a4b9b67e056b57","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000655.tgz","integrity":"sha512-Elc3j0MtqwslXZBU1Y2P9LKTAOBoG5he+uhXnZLVK/Brq/0tTc1zXzcCwq61DxytbpnP8ire+ehEOnRKebqPYw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJ1WRWASCIAQxGwoC6mI54ieX/2FSwulMqlO7/9qXtCAIhALykon9RmQvJ6OB8hllsIaK6LDyfwNDTdQL1tkmw3Q3X"}]}},"1.0.30000656":{"name":"caniuse-lite","version":"1.0.30000656","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000656","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"e6beefead44e0b6d82314fd42f57101270de41a7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000656.tgz","integrity":"sha512-SV33VueQY5fdWcgHHJzUCs7BwaHU7zVyzRXw+lDA5KYXmhqpO2ReBIfsRm2rL3Ubgi9q8KxJXG69MpyXv8SMxA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICUuanxGIHhkxBB+b8+jO087zfAfj2Z4CHETz55NzjN+AiEA4+wQ+gA1ua41W/1FbnJm9ILTebcBSMdNv9z+MvNtT/Q="}]}},"1.0.30000657":{"name":"caniuse-lite","version":"1.0.30000657","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000657","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"43ff22428ea436da7ed8cc38d418347944862f62","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000657.tgz","integrity":"sha512-/WVcQQaQl3ddsUoXUfgKSrI+NCb3DggIbzjd1fZiEjmGM2NezQDBdNzd0ObIXIbN7mdaujoIYQk77Pe/2v49tA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDt8E/wY7EyRwo2tIUz0Qwz8spjQTyH9ZJd4QHnSDaItAiAXeWx16svSBdzM8aqVkOgf1eUqZ0OobG++POHZdG2KSg=="}]}},"1.0.30000659":{"name":"caniuse-lite","version":"1.0.30000659","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000659","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"7eeac0aac71930ba95912c61ec69baa3301a330c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000659.tgz","integrity":"sha512-azbLgyzX2VxBIyRN7CgA4ckyO6d+R9S8lbRcnCoS/+CT3Zk2aV8YPqDa1GR5MUUlHQXH+n0zGPLrFKJpW+JB+A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDiABUCvC7hK2gxT22CilqjI3m2nhlBX6j5aNz1xvGAYQIhALlJ+JltmtpyNGCyGWO140VhFc4bnOfUVZWpNdqwgCwA"}]}},"1.0.30000660":{"name":"caniuse-lite","version":"1.0.30000660","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000660","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"49f8572c3763b64aca221ac2b4da87bc214f759c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000660.tgz","integrity":"sha512-+a+ATv/UozbopqCBo4PhQklve9Esc0FEPsfTjXT6inU9I7x/L2bbugtlRsiPXiJd2N04IXlDoBs+IPA4P3zlfQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIChWz7lD41OPuipyWtu7w2Gr/7Vr3jDQQxHF4ygBD2/gAiB4I1GbwgF/og2mfynhaCxAQvRKgeBvB4Ki9k4ESrB7cg=="}]}},"1.0.30000661":{"name":"caniuse-lite","version":"1.0.30000661","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000661","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"d0de936b38e037f76803150ff1ad2914d17c9c36","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000661.tgz","integrity":"sha512-0PcE6iqwT/olvJoAbdtm/LoJ49UY1YzIJ2xQYLYNfK2u3qUEhGOkek99IVsHpf2YZWAQlaW083gVOWVO8ghs9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8/dmboYV7ygUv3zVx6mlG0jGF8gHa0/RxF96ZOC9AyQIhAOBcVmJYIk5MIOWLL1M2A8x0iIpx/NHQVUsBXYtJl11N"}]}},"1.0.30000662":{"name":"caniuse-lite","version":"1.0.30000662","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000662","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"4b3af71d1c13ce9dfcbc6bc7830afac958ad19ca","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000662.tgz","integrity":"sha512-I6jPZFza1OB+lHxkB7HiygIgm2vsJMs3f+UIAya+DE0ShZCzFTNj0EaBOt+PlMRpdhj0QY5Lnbi7lIetOAoOxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEoBPnLa+U3V1Zegj1zbJ036Jrm2YGONJiwz1DljWR9YAiEAi/EiiqPqb415tMxIrdcxsrxYzZxDR/YcwvKRGy7je7w="}]}},"1.0.30000663":{"name":"caniuse-lite","version":"1.0.30000663","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000663","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"fc34de11ddc9289510be92ad8a277976497d1a96","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000663.tgz","integrity":"sha512-bWC/c6NUZHB+8U5yJ+LhNAEjZ+gmR4jAay3wS+WeKcEQ/pSm2ymF+MVV9Jp/QX+qRVTaMNk42r1ALvyxzM7hcw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAWqnVc3HGK0k9YFvjc1np6vhnZ+N74TSsphvWoHMwzrAiAZ9Mn2tgU2NblTc/SWEN+qVidNUqx8JzvwIJYXYRDhNA=="}]}},"1.0.30000664":{"name":"caniuse-lite","version":"1.0.30000664","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000664","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"33f5a8eed8c78caa89de2df592913570b3a4f6fb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000664.tgz","integrity":"sha512-Y0y3QhtfZnkMLPJ++QkmLB3oSt83iBvS0KFch6eP4rzEiLONiAcoeTX0c7/9n+M3QOxVj+K4HiBhGpdQ7QxESg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID9zzeav66dZiQwqwuqGzOrwIPCHK34G9uhY5dwWn33rAiAHMvxK0qU1G+doGGXl/fqoh4vyfQT9ERAsTg/zPttCOQ=="}]}},"1.0.30000665":{"name":"caniuse-lite","version":"1.0.30000665","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000665","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"62cf1283afb9b7b42d5ddceeb0345ce1ec432a1e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000665.tgz","integrity":"sha512-jltbFMzxVCLcue4oIc50Wq62xlPeoARyPYQ1Ntfw1OcY2u7nt/Ta0Z8xxJZZlPKYXOxNPjWD/dBGmZrsjraoxw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWvcS1vYFxrOZiMmnGbiD7g8uAz5ZZOfYiEItrz41y6QIgWtuGTg4iYCBIrGOJlMeS3xVFPwukdiJPsZcr+sq2Qwg="}]}},"1.0.30000666":{"name":"caniuse-lite","version":"1.0.30000666","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000666","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"831b63247e24fa408e20c6c546c4173d27c5a1a5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000666.tgz","integrity":"sha512-MhrsyfkMze492fVgynueSqDbTsYTJdcagvx0XJqqMDY2xKJNRa2hhjtvH+f6/4xA4oS/EMfNxF9FcOx30YJk8g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4kJNwD0wF0B8aiMabtYy4Jdl1FYBlgq9GjPqTAjnS4wIgAj13813M1jJ/IZDJTJB2Ivfxn602mYL8ZSLoGbjDW7Q="}]}},"1.0.30000667":{"name":"caniuse-lite","version":"1.0.30000667","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000667","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"dcbf8f19fa3b7ef447e7d514170a9ef949f4e347","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000667.tgz","integrity":"sha512-d+H//hSpNNFAU9cJKRCWbsmdshpD4RNjicof9IFZfbpArInfIxDCBObMdp2xIt3oExp0yKGK+4irUB5zHjdt4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEKfMuNPllTn3CbYU2vG+B4412oZ1SU1sZc7LaUX9GeIAiEAjq2KTCl+zy5i8WG7nQiIqZgV9Mqf+0pZvsE4zspAdwQ="}]}},"1.0.30000668":{"name":"caniuse-lite","version":"1.0.30000668","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000668","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"e48b1a95270e3a0245fb2f90a2b89702599bdf98","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000668.tgz","integrity":"sha512-MlbpZLO3uA4n6SzuVMHTLapHE96NloIPKJ44sdUzHz0Spq/0S0z/vD/V+bgoHJYEZ6YLSVkS31aRIa7+XfpCHA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCF4Px54EvYfqtnPE2IGW0hYuRbdr3sMF2XAV1kBs6rTAIgBhZxg5K3rsX2T0FZ00Dk9Obig80uUnC2ISwnBPM9uKw="}]}},"1.0.30000669":{"name":"caniuse-lite","version":"1.0.30000669","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000669","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"f312f4868722f3ce869ce934da3b536e0e393845","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000669.tgz","integrity":"sha512-IZQowHveCa3Wl2z5aimbhzGRfkPcWCpPJmABM3bwjkhXUXrOxRMrOsAgkteI4ndpzXkAEX2bZfdPLJBnf/g1Og==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAvxNInYQtCDNm9PgFDuVEFLVvgH1uXjyBNe/zHYgo8YAiEAkA/40wy/EtrgWHu3zX/pPktoZ/BQUNmpZhkHGZAN83M="}]}},"1.0.30000670":{"name":"caniuse-lite","version":"1.0.30000670","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000670","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"c94f7dbf0b68eaadc46d3d203f46e82e7801135e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000670.tgz","integrity":"sha512-i+lJmoLGEAX3V34aCWEPGMMo9wnkgl1t2+yNs4MpRBkC1Vm5pTm7rs9rPpqhocOvvSSrxPCWQ8L4/MZQa/nlWg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXnVA9noopLTyY3JySHLalETCbEYOuE66V6C3ycBsx3wIgFy+/x2g3Q/Pve9lX6D9xTqxDkQckyvPSyLQwWo0WaFc="}]}},"1.0.30000671":{"name":"caniuse-lite","version":"1.0.30000671","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000671","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"c206c2f1a1feb34de46064407c4356818389bf1e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000671.tgz","integrity":"sha512-pzGTKRfUwXeBmKk1PhbIf3vkrwLwhkQADBj+DIpTw9kQsW9EocS5JhC9m1GsM6PnIRQ8hiaL+COW9mmaccLJ0Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICx+d69uLdJWHwH/+XUOiET7g/oVLY7CxwNgf0/Z1fZRAiEAhb1mfFAs3NiAmEmVqyXgsijPBAcRi3vPrav52oaJaWE="}]}},"1.0.30000672":{"name":"caniuse-lite","version":"1.0.30000672","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000672","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"3f89b9907db78653f88bc4d056ed626e8ec74357","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000672.tgz","integrity":"sha512-olj7tsqoSYjHgFubtPUOHNsX0jXCzfIIUBJZIPZzIdFCXOK74agIa6WA0IotudY1yxuF5LbmZLe0hM0ZKAHx4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGP+7K0SYwkzVhzGh7hEzPdFXXGD5z8KDMTUoEPpZmSQIhAPbqX7NeTue/TyzbSUW6AO/kBvOtMOIUGPe1RIVDowz2"}]}},"1.0.30000673":{"name":"caniuse-lite","version":"1.0.30000673","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000673","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"4f1c5fefb304f712c526614d83b19476c16e662a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000673.tgz","integrity":"sha512-1mfiAsn3ZUafjb3sqZq80ccbPaTuVSmpjFGfC4ESQYbkFkgtRiCQ6/cezU9zr7P5inWbG9Tsja8Vrf0eCmqVug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICsntKarBpEf6wTR4M9EOQfWS0GTThp4nF9rXtE2UoxjAiEA5BjZWJccY7NxJC2tkjMPmitZRKrd+M6H10OexFEfaoM="}]}},"1.0.30000674":{"name":"caniuse-lite","version":"1.0.30000674","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000674","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"3eabc5e40ae2dce6375dd292f116b9e25bd505a7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000674.tgz","integrity":"sha512-myQZQVrVmeeZ2JxZNjfqT1ktxeubRORMGpm1nuo6hgPWVjJnuKYtAPdSkie8MS6HfkSSVguajM82ImQOP9rnIg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDbbRJgh5YrACKcCjw1UIc7twaXOFGSMPxl6vB9scB22AiEA502TWOOD6JlL+SOzzzP4ByE2Qd9sR7KBzW6yevrkQEQ="}]}},"1.0.30000676":{"name":"caniuse-lite","version":"1.0.30000676","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000676","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"1e962123f48073f0c51c4ea0651dd64d25786498","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000676.tgz","integrity":"sha512-Xb9x72cjcuezaZuF5p0PW2hu8OJdVOZj3Pcx7f3rV+Q1GBfnFp7udkXk4rihQVgAiNlC7nrpndmoH0JI7Guzng==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvP8tQPndxjAkvvmRQ7XzjhdfrZWljI/xjVaeTIf509AIgbvBGhkwiCJ73lOvQPkQ+Pr2xEmiZVxekDf/Rn+ZSFSU="}]}},"1.0.30000677":{"name":"caniuse-lite","version":"1.0.30000677","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000677","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"43090233d4b2c7190657f95455983d94d264baaa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000677.tgz","integrity":"sha512-82T38yoNXmS/1iVrUBd3qWa2+rzEEcLAB0hp9RJZf0jlqWzIsAWrIVcA2nGVanjVxzBBha6nahbEjYQTlNjv0w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGYW27JyuuTPBwXrg43zjZ0ZTwNvIE3WQpfBfs96mYcpAiEAvpY6EVlcFBN7/ax2pDPwm9frdzEvG55r7RwsOo/Uruo="}]}},"1.0.30000679":{"name":"caniuse-lite","version":"1.0.30000679","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000679","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"0fb5bb3658d4d4448f8f86a1c48df15664aa05ef","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000679.tgz","integrity":"sha512-3FATvbkQ3qGAEqID9iNSALBlptmkP4ZJeEyLsd9r3S2fHnPGYQCzwmEfc6vo6g2s3WKz+MJoiHLn2V7zNNtNXg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCexeZudml+iLFiIAe+2VBHGPWVFsKoQY4ilWe6QB0GfgIgL+aOa+8v067qFfikbU/Irqvvd5vjDvpNvgSN0J/YtFo="}]}},"1.0.30000680":{"name":"caniuse-lite","version":"1.0.30000680","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000680","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"d94d81294471617e86500f0aab90f11d22bc8934","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000680.tgz","integrity":"sha512-Gun7m0O9WT/yHCZMFn+bVdT8jvZjlo4fBZ1Em4QP9Wp7ratMEWyKjUOUwd6xmpcaZap7pBwTGa3GKa2L1HbbwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHDzW69DzET3fLB94vNrmnxk4a0Mn80hvkEZNnrscOH2AiEA9F3/iuoKwXQUNqBscGv2+cDO9T8BBu/uUtIUKyG/zCE="}]}},"1.0.30000683":{"name":"caniuse-lite","version":"1.0.30000683","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000683","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"a7573707cf2acc9217ca6484d1dfbc9f13898364","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000683.tgz","integrity":"sha512-OyR3O6OCwBfBGz4Av7cNT2ZRaDu+Qb9JMVxPtujh9VoJOnJK4Otk/9WOhFYXvQ0T2uDhM5AZw+1TRtYNA1jltA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAOe+hs3I04uNZkwtxlE5/XYH5Ku5tA6jUA/Ov65hG60AiB5rCGI57N6JszZ3EY9KvSXMuoq+lUKy5/aPZKefrV/cA=="}]}},"1.0.30000684":{"name":"caniuse-lite","version":"1.0.30000684","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000684","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"0c1032d0b36e14d1ac199f93ef2d1c42d3f03fd7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000684.tgz","integrity":"sha512-cxtl6JLdWXLF73NBuHrwX484AFkl/r+wbrGKd/7yyKR4lCyZ8jXHcy04nISp0PM/qqGxjNwpmeklyrbIuVAc8Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICT2FqMUldZ2HhD6B7i0tkUNTUaTcbUnjo7rRDvyqRvnAiB2CgST9AE88ytRPNbmvQZLt1Hu/dHMjoNl/EyIfOb7KQ=="}]}},"1.0.30000686":{"name":"caniuse-lite","version":"1.0.30000686","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000686","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"d9d9ec6110e5533be544a689003f7596532c67d3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000686.tgz","integrity":"sha512-kJCVdSVBCgiLDq7UYlIlKyHhrZGBiKxGiUJbKrFMy5Cnu8EiFDUcDUo/2csKoDriGPCtfXtoJrz6GozkpYAVzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH/XZOfveP5miHHF85HvDGNkk2PuDJWyo7XDZP9Jrl7HAiBU2SnbEDLWDWraSDrhZFOUuwsPvNDnVGSo8F7CH0b6Rw=="}]}},"1.0.30000687":{"name":"caniuse-lite","version":"1.0.30000687","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000687","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"06763368260f5257e0c98f2b0c8d23cca4c160bb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000687.tgz","integrity":"sha512-udtWEIEUDVD2h+62DrOpaGZ72TCAgBsWhG1kckrOjLvKQjIw6VDB6RFkCsV7t+/tcx1lt40HDIaiRPbvT5JdMQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUZmfVqJrPwbbwV4sSBqZT95Rtt9FcGqlhXY9OFPvtXAIgZUvAWOKo6K/X4ypfVphoLWGMLHJWQ1hzhjYwCY2ZLFk="}]}},"1.0.30000688":{"name":"caniuse-lite","version":"1.0.30000688","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000688","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"95036716b9459bb7471aba617516461ff562b359","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000688.tgz","integrity":"sha512-6GqAuqpE2/mOh65kZpiJlP4gMOhQ1IWPpSHdSnQS+M1ANuFBLRkSj6LQIYVunkPlrHQq3kEGF+CUB29YliQxWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDAuFh24lqdTlfb68XFAWgKXYdbEAsbh0Ue30R3L9QOxAIhAM6auzcrBfNbAjhAWvVykX5mf2o+UX5YqQdNJnP7V7cg"}]}},"1.0.30000689":{"name":"caniuse-lite","version":"1.0.30000689","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000689","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"729b6fc3afb0d92df93e0aafd539367e771a0fd6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000689.tgz","integrity":"sha512-lYvRMKHMPTzrsFLEud/mh3zAznNk8+U0LRSXSN0Ig1BUM5EyCZUJ6tntpLuvnNOKnzqV4CGVco5Pc+rxvmPeHQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEe0oZFRnuSCu5OgO4WIHxkN+k4Swo8Zsm7bStqyB5QqAiAUrb/lAmGMUre4bN1h+X6t6Ghl99dJPsLQwbEX+LBhxQ=="}]}},"1.0.30000690":{"name":"caniuse-lite","version":"1.0.30000690","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000690","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"3b232dbc0cf32bc2a888ec199852a50afa37f5ef","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000690.tgz","integrity":"sha512-CZ6uMkzOPPqTgknFzJxV7t8QyeYn0R9iAP7spD603xx6bDwUclSdTYbjeJLFskuAVocD1EO+qke/H9y9/ieXmw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDaFzM+SCtl86Fuad9wE3MaexN6/Evzo3KUUjmuN8j5+QIhANfyue2/DS/fzkVDj+rLyF6RPkks3Xft64RLj4ollc4I"}]}},"1.0.30000692":{"name":"caniuse-lite","version":"1.0.30000692","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000692","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"34600fd7152352d85a47f4662a3b51b02d8b646f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000692.tgz","integrity":"sha512-72FlfTWT0VBqacsYLmNK2bsSlfHICmL4T0A297lkpnkcf7yQvk+rCZoJCFvdArL0Syds0KbOjJ5A7wZSxX9V1Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICBPTeWiOIhLmHQ1K6Jk18vTfeOZzKKa2fTMY/qG8RCwAiAJEDtHHajYahcfczc+OvEzouXHxnk7L47I2/C7eKIr0w=="}]}},"1.0.30000693":{"name":"caniuse-lite","version":"1.0.30000693","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000693","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"c9c6298697c71fdf6cb13eefe8aa93926f2f8613","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000693.tgz","integrity":"sha512-8vMiuCfPlrMu00rp+GIpSpLHCocqoCJW/m9LecB6VHiiI/dePGlV1z7GcXGFtoEHHh1Lny0fR4wpdHKSkjG6tw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICssAhItr2cq5woeTcx7Cl3CvWmlwNoFWjokE7Q96zDQAiEAz82a9ll+FlfUhGryPkwNUmvNEn4RZQsMJsOscrqW1lo="}]}},"1.0.30000694":{"name":"caniuse-lite","version":"1.0.30000694","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000694","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"1492dab7c10c608c9d37a723e6e3e7873e0ce94f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000694.tgz","integrity":"sha512-QNn1FDZ0AICS+hLgMalZSIlUOZ+sSRaf+mZPVLAoJN4tsA9sLB5e9pHp31zKuRAzM1L8lfRScNhHeRac1raqdQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5frXxRxQagg144yr76akKxho6b6zBhYa433J2VfGGmgIhAIs1Sh0KMHa4HC2DfMjW5usSLnnwZljr8poLrAZxXriA"}]}},"1.0.30000695":{"name":"caniuse-lite","version":"1.0.30000695","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000695","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"0c2f711d49b9979884fa74349888aa48a8689dfd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000695.tgz","integrity":"sha512-fld/bkhp0pn/UPHJzRSguVeuUL6LNz2rmTn7jdHbqYX4cJza4YlKdV/pzPpnK4phM9iKHL0kO2kDH2o/BBue5A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCog8gOWL2IwA+WyyqqxFFWvYAqS1eDfvt6qhCqf9ZRqAIgOxTos2yR80zq2GTDaxYhv7MoqlDviQEJUn16xsC0Vbg="}]}},"1.0.30000696":{"name":"caniuse-lite","version":"1.0.30000696","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000696","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"30f2695d2a01a0dfd779a26ab83f4d134b3da5cc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000696.tgz","integrity":"sha512-d+SINfP3Vp1IqXiFLQVbFAyxlBVBbFQhy++COLoeQnAWvmMpePGl1xnZY+8PhYr+1wEWi5eVoqFIXNkNTbJ2zw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDH/kLQ6qJKroYwA3cin82yT4/pxuwcdAyYQffDUxoISgIhAO5s+9Tr6jMdQnaFhD+hcrllw676FixCfQumw71oFrJe"}]}},"1.0.30000697":{"name":"caniuse-lite","version":"1.0.30000697","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000697","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"125fb00604b63fbb188db96a667ce2922dcd6cdd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000697.tgz","integrity":"sha512-Dfq/h7Hq6KdZqlDFcejX/9l28JH1FnbqGjg5+wTGNGWezNNgIN+2BxcDJPd8O2ls6C0u0tb+MeipoepiuUz+Zw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3ESSOtXOwj0b8Be31go0QRxvvn6lqMUWb+iCr3jF9+wIgLSTzCcAO9PZ76tjmKavQj+OR4zDLzJNauz7ad9XLzmU="}]}},"1.0.30000698":{"name":"caniuse-lite","version":"1.0.30000698","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000698","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"8102e8978b1f36962f2a102432e4bf4eac7b6cbe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000698.tgz","integrity":"sha512-WtwhG0Gx8LbXNmZVysrtLMHPdYn40fFZWCZ/EmVS2sfMb8gGV5fVwJp9ce9HYxNPO0rj83OZ45j1i89DT6ZSrQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEv3aYfa64wUbmNRyDiMX+Hiww2rDBcwLMeKFicC18JNAiAa4wE3gjoOh8wIVJA8vMHEccHTPZ5vz1XdFQ0kzY07ZA=="}]}},"1.0.30000699":{"name":"caniuse-lite","version":"1.0.30000699","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000699","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"2a187b737edaa9ebedbbb56edcb53e994eceda0c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000699.tgz","integrity":"sha512-rN8Wnx97QB9wKRy8MSdnlOL8yBL1Jyb2T5I3qkM7Fahy984MKvs+TbAkag4ZIYb528h4VLKkPiIvk6iWfNoZdw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIECnIx2qGwF0K63tJ2KWs19Rr4h6/Uec7fz+mswBnRecAiEAlAZ/SrF5JWsKz/UzOCwCa14z3E8N0Y8xYqpOBFtvoaE="}]}},"1.0.30000700":{"name":"caniuse-lite","version":"1.0.30000700","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000700","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"6084871ec75c6fa62327de97622514f95d9db26a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000700.tgz","integrity":"sha512-/4eZuPAgITj8Z9J+5YdPzUZODuVe9osO60Dt/IxvOh1fAALJcEqE7SeW8N+yOr6x0WmfY1UaxgbLaGAVsQJ2+w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBC/ji8nzkTrLzCaUYioTqmlntJ6XvH2EUiuvW9bZxttAiB8eu3nouHWnvZiAjguQDMjQciG46wLfqP0uU3B9FnfZw=="}]}},"1.0.30000701":{"name":"caniuse-lite","version":"1.0.30000701","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000701","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"9d673cf6b74dcb3d5c21d213176b011ac6a45baa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000701.tgz","integrity":"sha512-opYn39Ifj40foYfN7gdA7yJ9MJcsJ7MQH5og3VBDSD9sI9J1C1ZhtijO/E11Pj7tSbSYVKeeY2pm1xDxMNQwXQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDySFMLsnFtv6tDFDiYGH7tMAfXPXUVo3aLvKbcptSARQIgKYFQMZVHDhIq0R+xghTlvnIXkRsWHB8LOxnXMsUoJdc="}]}},"1.0.30000702":{"name":"caniuse-lite","version":"1.0.30000702","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000702","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"bd66e40345528fe0c001917d1d3f55454df634f1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000702.tgz","integrity":"sha512-0j9vrBnA2uJZnkyepBfXfivQbCtUypMwx59IUycR0GLio8bbx5tjK6defOe50/G1sbM0u+z2WSglc9RVhRj5KA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGvbcZqD7/1nAP1JkHf3BidW58MXM0AvVpjhtXhdsGt5AiEA0b7VhDIu6/XYCTotkXkhcTuHCRyR0rRLM0RZ0QH9w0k="}]}},"1.0.30000703":{"name":"caniuse-lite","version":"1.0.30000703","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000703","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"666e8c3f1e4f7abb1d16d48e04e7e9e8df934925","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000703.tgz","integrity":"sha512-Kd0FHXjPZBEca5tkL9xQHp7TTYqFDHJ+ZN3101/DdugTZoBCbcUzcAP5cNieXyyb4SnjOHEnOdYEdmXnvmBrvw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQVgnBOSddlsvkM2EFPNt751JunbbpVV5D0aFCho0aqAIhAMps7N+1g810LyftuA4Mq2On3y50OG8DoUT2YodX66Bk"}]}},"1.0.30000704":{"name":"caniuse-lite","version":"1.0.30000704","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000704","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"dist":{"shasum":"adb6ea01134515663682db93abab291d4c02946b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000704.tgz","integrity":"sha512-0RbSIL9fKimhbQhkhtVZ4lamXw58eX1bBzFlRoorba77lqWb0e8uSnYEwU0LLZktYL6N7lkQP401cMh1n8Nxjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDk6abUipxujK39DSxMyyN+QslHIX455tJYmko4IsFktAIhAN3ZbaPlZNmG/s47/qJV+nG+RDYydQA9hk52hOwe1nlr"}]}},"1.0.30000706":{"name":"caniuse-lite","version":"1.0.30000706","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000706","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"bc59abc41ba7d4a3634dda95befded6114e1f24e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000706.tgz","integrity":"sha512-WZWwIRdJNljRJndZhkCG5Qi4sBOEgixvudY9lEQXqrARQSM2HwRFCB8AQKcTm5vhF+y6fONFIQYw5RQpwHCB/w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/CTE9Q2K/ufJkDwYPZmJdAAPMAF1lHC1IYq5LOkxCdAIgYXtWQ5vKoPdCtqlKRrj6+FX+DhBoCe+BmZ/O28mV/eY="}]}},"1.0.30000708":{"name":"caniuse-lite","version":"1.0.30000708","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000708","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"71dbf388c57f379b1bb66c89a890edc04c2509b6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000708.tgz","integrity":"sha512-J6HpQjLWhxUSQUr+TyVW8Qt7YY1oKmVQgnnH0z1thtMXqWUr4dpZuX+9Vn2h9tFDdFN+rlhNJKOcTwcATmloCQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB2ZU82qSNVyh6KrvGZUe1e3iDtSpizgcPFJa+Lza1GkAiAuhV67CqFH3EmArLILGcf8n8X8Dz7p7HMjDjPVQlmECQ=="}]}},"1.0.30000709":{"name":"caniuse-lite","version":"1.0.30000709","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000709","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"e027c7a0dfd5ada58f931a1080fc71965375559b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000709.tgz","integrity":"sha512-4iqoip7Z28NLHFMPFBzQ9xpYH1SG1w2RgdWScynYQYIW/yPnHFpJICkNLDy+Sa/5P/jVvRr0PgXrgqsFjqULSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDerxa9zviHH5EudqDH4OYqleng4lvlNLmCDpmdwR4rgAiBhBjeJW5+TkqSRiQ0uoEj7VaoF2m/Sy6oGawrEESNzCw=="}]}},"1.0.30000710":{"name":"caniuse-lite","version":"1.0.30000710","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000710","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"1c249bf7c6a61161c9b10906e3ad9fa5b6761af1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000710.tgz","integrity":"sha512-KWbS7TjsWsTzFoAxHtKRHwCxAeqfAAhOQFASwgoNJY251Vid1Ah8uyvqT2dpBNdJviXuuC+HYtwc4BRRe2/iVw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF0V1AIutVkgRqyb39DntN2Iz6YNF2QkbYyR3iYgJ7OIAiAmqWqnLgp1N3WaAObqy1lrgPXAcripJJ7YoSaUTnPIPg=="}]}},"1.0.30000711":{"name":"caniuse-lite","version":"1.0.30000711","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000711","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"90f632a4ede34d40b3e49622e58e710dc187ef6c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000711.tgz","integrity":"sha512-e2pdnNwPjHoPSt68z/uAy+qRIuV3vhYhLGAeeBXirKWI/HXq8Xx058oupkhBH0b5otsSg2ueNK/ejm8QWf9MYg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1o5+oazE01PwHPGLApEhfgCCWQefUEjVZLZG+wToJ0QIhAKiWvkae2A/9Tp4EsKaNqW2wEcRJoUZFgwqu6Wz0LrMZ"}]}},"1.0.30000712":{"name":"caniuse-lite","version":"1.0.30000712","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000712","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"b4732def2459224f3f78c6a9ba103abfcc705670","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000712.tgz","integrity":"sha512-k0Oe6tijnAUB3nS4x/aeXhrYbSTjtlMj/bAfbHJ+i8klGRB28FgcYqB5pbBl8GzdRvLpfAp/rPY5VZOam0TRqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDd0XXte1jVWWI8xaV899mGVBu4bzd54nG/+MvtARRpcwIhAKBXvSrUnQsZniKw32Tzky+YnanBYiAPp4LNWfPGHgJk"}]}},"1.0.30000713":{"name":"caniuse-lite","version":"1.0.30000713","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000713","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"33957ecb4a2154a5d40a60d13d8bf1cfa0881a8a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000713.tgz","integrity":"sha512-GZUGnmqZBwNVDw77jEGdXuDotfXbmIBRxONX4+YtRK09HtnYgHs9ryKEoH/XdYopDe64cLfiMhy1CPi9w+4UMw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAUP5H5AZqoXEeNFOsIHhVKWq+kiyQ180M2qNDt8PLowIhALZvNoDJIoYBYmE/dXWl/+mOdngw11bKho5UBOPgj8Uj"}]}},"1.0.30000714":{"name":"caniuse-lite","version":"1.0.30000714","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000714","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"e7e5b43172f20c9fdc2f1e4204b37140c447739f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000714.tgz","integrity":"sha512-exQTzAQ5Q9PZzIrrm8bSKMAiphJag+0wYKD15g+0JP4lp3dBPAYIl06VXCJKLbkZf74ocg2KyXyGWBSmcdPa1Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfh0a+CVKwCBDJeaAD0MTt5ivcs+HGzLJeZnJqQ9toUQIhAOjtV/JPc97Ji/+KIgKarJBMPosFySzplxskpf023LfO"}]}},"1.0.30000715":{"name":"caniuse-lite","version":"1.0.30000715","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000715","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"c327f5e6d907ebcec62cde598c3bf0dd793fb9a0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000715.tgz","integrity":"sha512-+s1I9H7/Km48QijxfhQDalWQYHBdIF6DdeiuZ5IvMRyILUWrcI3FJ2AlhE/Su7l8qU+jefEJ4oxtEWsdhZSNUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEzylBU0TiQPt8ZknJHxK7l97Rx1R8JK0e9STMDHVcheAiEA6NKY4z8mSOwJJ2IR9GbVlQRClXOjRGDq5lLhSy/njI8="}]}},"1.0.30000716":{"name":"caniuse-lite","version":"1.0.30000716","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000716","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"2b40dd4a7edb7f0c468643b899b832b315988e6a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000716.tgz","integrity":"sha512-MLw+UWM+1PEWETgrb7CF/TPSwN//xP8LS0ZFFbf4GY2aCxk+dabY25DKIOn+7L0YjfKW3yGYhBMFhD3I57Ma7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAjbvARddyFTPHCT21W2KpHEA9b9ysnQHIxGLyxHfcCPAiEA8wT0dRhhGaRT8j6XcgFDHHSkhvNQIE+08cWPgX7PPFo="}]}},"1.0.30000717":{"name":"caniuse-lite","version":"1.0.30000717","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000717","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"4539b126af787c1d4851944de22b2bd8780d3612","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000717.tgz","integrity":"sha512-kDZYDDk5GHvXxQUj1iiP1YSkkAi/gmLCmUznnKcR6ycMe86S72GeviuqFN46uX/986GIYVAWzK7T2KeBNTTsaw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFq0/vOMOKODVxbJFljGAbS8hscv03blQgAjR9CrukyEAiBEG79FLV/rytzFk92QaH9EREKNF94FL+hE9fL/06g9Cg=="}]}},"1.0.30000718":{"name":"caniuse-lite","version":"1.0.30000718","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000718","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"0dd24290beb11310b2d80f6b70a823c2a65a6fad","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000718.tgz","integrity":"sha512-CSjkpIUUxY+hte0OEO8QepKk+D1kxIneoq19KhqBDdyDJWgfCo+1wgL4kHYkdjFa9+05dV0quAu9+Nb9vtPsOg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmxik76Q+zCpguqQeDxdntLJEozKqdilr2E+F7o24+JAIgXJwz9ktaDyMk1xsG/BZWSiz6cV08jd07T9gdc8SK/PQ="}]}},"1.0.30000720":{"name":"caniuse-lite","version":"1.0.30000720","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000720","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"9313aba5b923fab5c78f6054819b6f0cbc626352","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000720.tgz","integrity":"sha512-wuknFrSnWxuH43tzo1XuduN/l2kaAwCAY0z4PC4uItSn0A5pfU3msb6ZkSQtiKBM7Xx9vpXKmR7AYkKR4mOFwg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKT51h9+rXBJGyvXqUlN9NY32f9xAqYGr+7WdTsBx38QIhAMKCwcHT4OXJutUDPHXA0gq1kVOxYCnhkbLXBIaDpFUW"}]}},"1.0.30000721":{"name":"caniuse-lite","version":"1.0.30000721","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000721","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"931a21a7bd85016300328d21f126d84b73437d35","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000721.tgz","integrity":"sha512-lAE3k0NncmPerMxn+HOcaxdzV62pHNjr/xbbXK3yoQS5v5dtl1lUSw9xC1m/mg9kBgJU9xV/HsXXSfoRw5T3gw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDxX2XH+kxEQzUmfFN4Y0rl+XiNYCXVL1JvIdC3tA9UswIhAO3VrJWWdHHFHSeTTpk3mgGUJF9ZwuMIL0x6+KwH/SCT"}]}},"1.0.30000722":{"name":"caniuse-lite","version":"1.0.30000722","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000722","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"8cbfe07440478e3a16ab0d3b182feef1901eab55","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000722.tgz","integrity":"sha512-aSwWv5dye1VAio0VsXvny9kesaaEHB/lwljhOM2a4QzWOXITC7ualPoZl/tm3U9KB3SrfvdXKsIBKKrJb0OrXg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJthZ2Q9WDNsvIUhN3bjMOIpJmWFzx4nkzhwXqJo5MDAIhAMVogyfT3DiifvoIOVDeDjKOfs46r+wlPIuww3i4/IIk"}]}},"1.0.30000723":{"name":"caniuse-lite","version":"1.0.30000723","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000723","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"f9db1e2868caf097b00265ac2e71ba44b608fb1e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000723.tgz","integrity":"sha512-TAnNm5PK++a9SyAkdiwC79+OjNAR/n8EPvE2P0r0Mlrg0SjqLtngIObIOuacbn7fNvJTVe9on6DLA9Od0W+GHg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHqyAabzDuF43iDfaHbIAtMTuvdgT/oi8G0ZhnX9hsyRAiALHDIkeHouWC2BOcZI6A8C1gcjzvG910jXhcYU1vK9Bg=="}]}},"1.0.30000724":{"name":"caniuse-lite","version":"1.0.30000724","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000724","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"b9711be59257bdbce6a872ade51a11e864c21ec1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000724.tgz","integrity":"sha512-1npwllD+UrxO7CP21ZASDdviRVzIynCf9nbCAGA1uBsLFTANIbxRaqNMhQTVwT0vDwzaMPeWNYqK2LmDBf0RRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFFMN46GwIctT5RVA+BvEGnycLlLqxjThqh0PfLh3Up0AiAcb+AFVtUAA8Ak4uaxTKXaS55RsPi9Qv5wyxvF9PlooA=="}]}},"1.0.30000725":{"name":"caniuse-lite","version":"1.0.30000725","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000725","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"4fa66372323c6ff46c8a1ba03f9dcd73d7a1cb39","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000725.tgz","integrity":"sha512-sheZX9d5WmNedsJ4OM7cCmrr/jy74dqCExsgb5elIsUHvTpOlVjs9Z7KakPHZA9O4RE7l6bflCWDBL8dpt6YmA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTJsUkNUzl2VvxMx8WuJPqQhAY2B7UJ9W/QWUIz9zVvQIhANHAikcYjoYv3Eg+B4GCR4fcKKo046oreitWiUt7sGTu"}]}},"1.0.30000726":{"name":"caniuse-lite","version":"1.0.30000726","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000726","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"966a753fa107a09d4131cf8b3d616723a06ccf7e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000726.tgz","integrity":"sha512-6dI2gTJNjelfF/Uzns28eOgvIZIWLfHamj6ahHSP/J5y+Gj0C+9+JK2do2u1MoNfX7dK49mKT8aWoR3QF5QWpg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHgs5DHXWS2+08GtZKIc4frRYPsL1q9vk78vIO/IK4xhAiEA3LhCgX6Gevby3kBDYIzZ4qeZLugmhxk72rVJ6qhvLEU="}]}},"1.0.30000727":{"name":"caniuse-lite","version":"1.0.30000727","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000727","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"20c895768398ded5f98a4beab4a76c285def41d2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000727.tgz","integrity":"sha512-Uy7r0xo0rzv+I387HG2GismUvtvl0PZ0Qltk+ERysZRXUWAcZLNqIcm1BkgbIuW1JJSj1ruwcVGagc2fOrjOpg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGdQGE7vpz0Bx4FY8E4Jn07IllY03UmJ1P4yGuZuqo3cAiBepV7M5ljmAc0pA97gXZf/yJP9IKJxcydaoNSHvCQCxw=="}]}},"1.0.30000730":{"name":"caniuse-lite","version":"1.0.30000730","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000730","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"26a14ff1b3bfc1f1cb4da75c2c73451b3f1ade1a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000730.tgz","integrity":"sha512-u2E7SEC1Gun5YE0qplKBPINrv5R4VYbeH85vSGTKkSUnosom6/L1neUM/ZivY37FTkz6IRo69icKzSSAO0GsOQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGShcbpkXX0qqBt4X3SuWs6FMkytiK1fNxrtgAiBmAoLAiAjpVgrTajtw8/WXnCGvtr3l/TADUvLUflgBgl7FI0fQA=="}]}},"1.0.30000731":{"name":"caniuse-lite","version":"1.0.30000731","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000731","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"6f2b9096285af3c7bcf2abe39647bb525d68c842","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000731.tgz","integrity":"sha512-NHZ+T6QCXv87QKuAZ+Hlr2ej9caWr4Gm2T3qkHXOwB7xOtJRg9EEYDahwn8s6Gf1AzuzIiro6esEpnWPEAS+uw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEP4UqKtMl0V1SxAjP1mL+eL3qqEa6JcfdNz2ZMKvshQIhAL+xip3vwnFT7Msnq6VYdNDBQGpgYOMxzTD+TD6zUkEr"}]}},"1.0.30000732":{"name":"caniuse-lite","version":"1.0.30000732","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000732","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"7cf9ca565f4d31a4b3dfa6e26b72ec22e9027da1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000732.tgz","integrity":"sha512-YcuEGqQFKJv9bMadv2Sur5kSOJpGUl7eEnwtWcGheltJm3J7tFb41yOHHzvSnE7YgoDv632tLBp+RFfgEsnRzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDmndDahFQdEg0uDcm7fpPAaN8TeUNvFDhL8nzW3OPGVAiBie8IqWkXLi2XlKMVvOdvVDaKB+bepljRk/si9G+gM+w=="}]}},"1.0.30000733":{"name":"caniuse-lite","version":"1.0.30000733","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000733","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"ebfc48254117cc0c66197a4536cb4397a6cfbccd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000733.tgz","integrity":"sha512-UETUHm3Ycwf6jS+clI198kJCKJMD5szC9k56Qp2WdjwojHKxcl+g8g+opLH9pibzGdBaVQXA+1uiYsW7jy963Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICg1HrkWAw8MC63JZOFLOoR/E4l1VKqBMP1j3PbvA29wAiBQUbQ1aJk9pVar3oPGlUSWauiIhd7R3RTCeDASG5/gNg=="}]}},"1.0.30000734":{"name":"caniuse-lite","version":"1.0.30000734","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000734","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"492791fb0557978fcc1b7a8f486270b35ea6e569","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000734.tgz","integrity":"sha512-fta8OKoEAK8+647nkcum5ajBmAYaFsVTEd+EDL+U2kHy7ky+OSnHTUjGBsbSV0K3Nat8FWWHuyKcvqItVE5paA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH7mQmp6478GR0qVt2gOkZV0rkLTttq7jGbSz0xqmdftAiEArFfcIN005XY7icpg4/Cofwdh7T8t19NAhfXW/bliVtI="}]}},"1.0.30000735":{"name":"caniuse-lite","version":"1.0.30000735","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000735","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"aab44016ef243e215ef43fd1343efd22930842f8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000735.tgz","integrity":"sha512-sywQdpvTKwXMNR+IBMxoldrkPVZo87S1Es0IYXqW8G4ZhJMeRSc39HVctJS9H1KZzW+4+FoP9o3cmL+OhdN1sQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC4OPyYTDRIb8sGCZ1+9OBvgVGTTLHWn6P2pozPh39glwIhAI8EjSnB2RzclzRaygdoCz91YQCTPrJgPR3YWDmRL9OM"}]}},"1.0.30000736":{"name":"caniuse-lite","version":"1.0.30000736","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000736","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"df369dfb7ed4d77a8a01244252c6e2f7db9cc689","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000736.tgz","integrity":"sha512-hf1XK10iFp8F4ZkLfRI9heXtHBfNVlEH0rqL5IjdJlPPcLB7KIQ++eEOKbyQXh8okOf7GtDTOSpMe/VXYX4lrg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFqslwPEaGbgy4QCpM+cTJkBP7wn9xEwJ/3wxjsXI6MhAiBUWC+hCYp3TGVbLlTxNhvj5GxDx4HyBfXj9+UnSTXXDg=="}]}},"1.0.30000737":{"name":"caniuse-lite","version":"1.0.30000737","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000737","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"8199a601dd54c096e1f8567bcb7461b94f0d4509","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000737.tgz","integrity":"sha512-uQC76Enq2L0VsDGfFQ8BjIs69if67fPBUyvI9UJnlK0zCh7lM/nDa11qMTPSHs69SyDDU9FblV+ksHC7u6Z3tg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEibg+TCOaEO0ZUPQTugZjPGf1oO1EXkM7CwfGznIDMoAiB+rrjg3OYMacYIysXlcUWcmtcqO1zFw36biTG7f2qIkA=="}]}},"1.0.30000738":{"name":"caniuse-lite","version":"1.0.30000738","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000738","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"1820c3c9adb9a117e311a5bdca1d25bc34288eba","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000738.tgz","integrity":"sha512-bxBiw6CZcgmNK9waN5w6eV1bbVtslKxjZq9peqfVPmu0zgPCThDQykHo3ky7Lagbc1nvQpFWPUY/dR3OXOzJdg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID0JbuqWL55KiwyvW813UKX6B4SD/BvMqTlOuQBADfgXAiA8IrT3wp7mVbAlLxvEwZDUGCqjH98aa0jm/uPlxyuWbg=="}]}},"1.0.30000739":{"name":"caniuse-lite","version":"1.0.30000739","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000739","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"9ee8c7016f5c522dbb0c0863d55c61efb453ae95","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000739.tgz","integrity":"sha512-FjuAKTBd1XoVpK9PBaHc0pKFi54Bf9AQ7O3naWUN7gWM6Rl5Pbz7yaF+6rheNKuycdYS/W+2TTLCaH/vY+S62w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICAKnYY8YLR6ky0G1iFv6bfQ70RNlZG0OtFZjo/oZk5QAiAUGaqkJuR6HfuDx3SXjHi9eMlylM+5/YPNdIM1kQrD2A=="}]}},"1.0.30000740":{"name":"caniuse-lite","version":"1.0.30000740","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000740","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"f2c4c04d6564eb812e61006841700ad557f6f973","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000740.tgz","integrity":"sha512-HOpxICFvVsPskvNzh06NlNmBhY02XnwwqwAosccUJ0L4TepOlX7qBIRDpPP3z5gG13RYLxa+wKccCTUJBNoa/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1odhwweRMGJpZmGICb/Wlu4oDNVyqB5DiXKbwplI7JAIhANbC8qGUGGONpEoNsDRfG/7hte51/sM9RmF0FC/AcONR"}]}},"1.0.30000741":{"name":"caniuse-lite","version":"1.0.30000741","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000741","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"bc526bc2046e6bc38737cfd77d3026ef04b8f464","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000741.tgz","integrity":"sha512-KwRwbpuYwv9SXKVSIs9gR2+/tS4F+t263HngzCyls1XbZXadYOAocV11Q5b3yUkHYDTZDtTOveP3DBZe5fXxoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBLWBGzmP1EniUjTqUMtk6F+0sRNFvs0YpfiTdAVznI6AiEAkb9opMx6SX9SSMSvnzyqJDs/SNikFJrc3jEwwCRMA3g="}]}},"1.0.30000742":{"name":"caniuse-lite","version":"1.0.30000742","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000742","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"b5ac8a4a6f36e40a33a6188a8a8bdf8460c32d25","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000742.tgz","integrity":"sha512-JIyFpiQEqER6gsYOMRNVSnk1xbREYtMuHrMwash9kChAPbUQ+Bx6hYvEiWVRY8TEPSlEs99SuPvHJRqKpM6SCA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIETW6O/9snOq4MCIEP2l0xsd68EEeejw9h6YwRTXgzOzAiBcrX1ZyhZyGUD6ojph4rjqIbRGXaTp6HZCwPCOlBvP5A=="}]}},"1.0.30000743":{"name":"caniuse-lite","version":"1.0.30000743","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000743","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"f4f5c6750676ff8f6144ea40456c3729d5341769","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000743.tgz","integrity":"sha512-O+piiJnw0e1Yen7oBuQqcf3oFCVG0lZPuKt4emXtNHuKkULpJkFJUSBeS7eszKyWDTo89Rv0kWRzTV3NyZy47w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBH+1X9S6z72otjz/7JKGsQRaocZ+8khX6YhefTek/xNAiBj2R6WcSWO2PA4dPlZe58Bnlh/wO6KKNEO7xa0GMU8QA=="}]}},"1.0.30000744":{"name":"caniuse-lite","version":"1.0.30000744","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000744","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"860fa5c83ba34fe619397d607f30bb474821671b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000744.tgz","integrity":"sha512-PnlvzNJ3Acbsj7psV0XBflq3OG3BKxvUnAw/la3VXXzqg51SxrtRa1GtvsC76Aop9EbylhV/glib/bcYNk5CWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEyq58BAAXZgD76XVjGzljMCBw3eQMjXgOoe+Gr5Lk3QIhAMlbszBsCbg29Izh1pMn2T/tVJnHw3zG+xnN7Dv5l67O"}]}},"1.0.30000745":{"name":"caniuse-lite","version":"1.0.30000745","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000745","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"20d6fede1157a4935133502946fc7e0e6b880da5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000745.tgz","integrity":"sha512-f3jztnZf4duyRHzTZwRhoE4Dvgs4ISN4LAo4jtP5QJGzOv/f4xRcbJi4ghgRRVTz169ZNFtmLTLW6Oz9m7yJuA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbxNpiUGmR3zxCy49xPwJG2kk4uP3kyuuhrXx6YnnWDgIgMyS4znivb12rCIEc5qj/SVi1GGHe2dHORxVz2a6asEI="}]}},"1.0.30000746":{"name":"caniuse-lite","version":"1.0.30000746","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000746","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"c64f95a3925cfd30207a308ed76c1ae96ea09ea0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000746.tgz","integrity":"sha512-IzVDkSJWtQn6v3sH2beORKEhmnW2qcAP0TVB+tPazozkAY+De+iyXO4Drjsf9avHCf/G2lo0G6Y59Qnn6xkECA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDkQsZvCGF5SQFFjKQv8VYvm7E8YdwKYDsaBYmwIJ/44AiBHYDfW+mD94NTtR83QuG7auVWSSFbeCUNTfMuqMkrHeg=="}]}},"1.0.30000747":{"name":"caniuse-lite","version":"1.0.30000747","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000747","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"da86e78e12d0641abeeaee6ecd55d81bd9bd3b5d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000747.tgz","integrity":"sha512-7w9q7P93erJK7FSIIiFMcbqD+LRp8MBZ0xB6kldbceyDjyW2ZyXq5nvVgmCOMvt/qGccyQoBy0Oy14ue0xePYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKPjiOlScThiML/3vhd3Eh6Yy5G+IkFe5HJv4YvLppDQIhAJ2cXAK4s+QmFzMO+ohCqm4V8oI51wAczwWOmPML0i4J"}]}},"1.0.30000748":{"name":"caniuse-lite","version":"1.0.30000748","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000748","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"44c8d6da52ad65a5d7b9dca4efebd0bdd982ba09","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000748.tgz","integrity":"sha512-+5vcNr7kmZSsIDFSdLtvNDIM7B18Gmpl0vBDFh2JbvXl4D2oIy9I0CSYXJgRot8wAQcYXvr+8QL4whAR9OaARQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAvv+NX1sS+y6ITs2kBpNbyNeCWIn78y7NXktd4q8yiSAiB21QpFyMjQBuPvpdzsQpua07/oalCwX9g5cQ+F7DNY8w=="}]}},"1.0.30000749":{"name":"caniuse-lite","version":"1.0.30000749","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000749","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"2ff382865aead8cca35dacfbab04f58effa4c01c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000749.tgz","integrity":"sha512-tcJDjt1KvJ9KYx/7gj5obBZwL5H7WrmuXhFRPuSizsV+psG7qqavBwj/ThwDBwyRz5+ETMSy+eVOYVhGgMoBAw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDt5zUHXHJoRybr1p86LBWBTmOo4fxARJrvLZ5uzRqidAIgRBtta38NeOKrLi5ahpwHx+2YFuIDM9jmCUA57O/18WU="}]}},"1.0.30000750":{"name":"caniuse-lite","version":"1.0.30000750","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000750","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"38ad19aa4c6d88da38e8900d3666b4e3bbb65c22","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000750.tgz","integrity":"sha512-rEc7AHNuV7UIJpFBs1Vw5Gs9msjfOgjpgOtOLlasnM+e7C/RtMwc5ttxeOOBJjG+pwl3tCXgyhA3HsnsPqNWgg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB4aFKzaX0ivx1VT5BulsVrzg9lvCpS25Z6wz3/mEQgeAiEA0uYzxWB2fjz9lbk3C149DDK21k3sFQHNQDFzABnt8r8="}]}},"1.0.30000751":{"name":"caniuse-lite","version":"1.0.30000751","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000751","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"298ad34182ca4359757b4a93afc681b7b917e358","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000751.tgz","integrity":"sha512-nIuMHfzDF91mIJGQfWDUuQ5rXT1K7MaDsVjotrZMzQ4P4pBDnPKiHF3xmUOiDvuLVRGS0SRZSWbj2aLs10nt/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEoWtOevRCHZpn65F3Zg7RlSsBsZj64A6nmBoHPqHMDwAiBN31zlm31+uUDg6eCfh5zZ7uVUI2sr6+L1JPvCq7aTMQ=="}]}},"1.0.30000752":{"name":"caniuse-lite","version":"1.0.30000752","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000752","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"0a79df520669d92ddc7f57406eed935948263130","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000752.tgz","integrity":"sha512-4YAaW8noC/dWKpJMUQ7x7DgNfNl5yP7wCS/dAu4sZKIm48/gmrF0tHiKsFZP1uIAsNHwVWqYVAI/uLI6bU+Qow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCl8gcpmbM7Ec5+HtPyzOR6bVOW1zHlpOH8H3EFmKWAtQIhAImo1KjLRHoEztTKnZX8JsAXXtGfV3Pt0UU0OTa409zY"}]}},"1.0.30000753":{"name":"caniuse-lite","version":"1.0.30000753","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000753","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"10d7683272edf94e5f4a8e94710e60c218f6ced7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000753.tgz","integrity":"sha512-2eF8CWbtpP7Zcd6HV+gBpFC74odneZWbrXbnScGwvn0N8TKsoGQ8w9rYz28k9STHSkjXnIXradc4SY7pU3CbUg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQComhe7rbn7ulhzde6a5dPdP/GKf5qy2AzuxyGCvFSI7QIhAKeF+g4rKKyBU2m/14+ztIwfv7xa2cgNSJPYkKb5heRr"}]}},"1.0.30000755":{"name":"caniuse-lite","version":"1.0.30000755","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000755","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"9ce5f6e06bd75ec8209abe8853c3beef02248d65","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000755.tgz","integrity":"sha512-AFE+UOyxnsl0PY7FZxjxd74gGXi19Z/hA6YzdiAw12Fe4MnAV6uQH8CxEwh8Yg6VPS0I6inxc3Ns8f8pULcLzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG5CgAsQWp3ix5pF59MSY61rCBFWzS5CeSnXFGKiATeMAiEA1rRJS/GMSLiDHKSqJjcOuKqHy1C9amkhF1lz8uSmErY="}]}},"1.0.30000756":{"name":"caniuse-lite","version":"1.0.30000756","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000756","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"3da701c1521b9fab87004c6de7c97fa47dbeaad2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000756.tgz","integrity":"sha512-YieS9mBflxDMbcL580d62tK9jU3XqmhLqARmqfrC7V6lQDZkEU88UH89ye9Q+hdigaa6DXVmSUXaAb8OfHX6iw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE9cPyn4cinf6GnaRgNU9gjpUHzmDAykEdSPT3+fnClJAiEAjyUJVgQLb0giT5lFekkO87nDI5gE1+y4dMC1Ot0Ioww="}]}},"1.0.30000757":{"name":"caniuse-lite","version":"1.0.30000757","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000757","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"81e3bc029728a032933501994ef79db1c21159e3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000757.tgz","integrity":"sha512-GBrbVlivLyFlmXPjU8WQXJ3tNR1bV5zUylcPYRY3mHmsyYq3j/mvevng70KNr9xocdaUxe8os4NffNo4M/uSYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEd+7eG3yoTedqYujzGuk4ccAW1xSWnRLOQ/iGnwlkHhAiEAhCb/MO09VcjWvG0ZOQYdiP0sCCLTAIKY4HT8nE8Mwro="}]}},"1.0.30000758":{"name":"caniuse-lite","version":"1.0.30000758","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000758","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"e261140076651049cf6891ed4bc649b5c8c26c69","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000758.tgz","integrity":"sha512-aCa0pjOHRtqEnn5lmPVum3kkc2M8YpTTPm6QnPa6WWskXCccZz9n53ED7jbs05KEed/CLcyYYuiH3OskeHY+PA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHMQ/HWYwLy8UPAQVRRZgX/O9kxSNhqX256nZnUFs9p7AiEA9o05wUA7CVyqYKHaK7VvUY2LwLcR5XXoXX2C/3qRcrc="}]}},"1.0.30000760":{"name":"caniuse-lite","version":"1.0.30000760","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000760","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"ec720395742f1c7ec8947fd6dd2604e77a8f98ff","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000760.tgz","integrity":"sha512-1yNR7Qxw1ctm7JMRradtaB2LZA9/wBKGMyqny1wv056SGoYCTqkchRJZkyWXerJYh4ghSlp0eGbGVkW9MNNSTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIn095I7VGa49GoOG1xA6pmmI0w3q8JblSatfeWMo8gAIhALVfLnwbzEUElvGD/oAZcP1S2rNLztYFUo1CwtDJTjwK"}]}},"1.0.30000762":{"name":"caniuse-lite","version":"1.0.30000762","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000762","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"0591eaee7e1fc3d95399a8869f2e00092c16ecd9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000762.tgz","integrity":"sha512-KorsLjOe2BYvd0uKByZC4IPNjNhkKiHjq4rR47S9fhCXN1ZRkCTH7lMhRCbFIecEE74mGjN2RGE3YDYzWOR9Dw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFy8R1RkH261rQFpKEsyH3eeWm+9g3lCqAluC/jCnqnIAiAR5MyC8z69M5xo8it/nFkr343+iHbRkrWgRbzk6+EKLw=="}]}},"1.0.30000764":{"name":"caniuse-lite","version":"1.0.30000764","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000764","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"97ea7472f9d3e691eede34f21983cfc219ac7842","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000764.tgz","integrity":"sha512-7Iwv5AdRtNkyKLAL4wpIM+QEqgppZNn/GL45iSMRCkowus7KUT/A+21dBjYGZgk7mxWP6nT06TJJgqTemQXvcQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH3mM8QemqB4w/SVzMNOpkSypdEvvhn06VPGD+/edWapAiEAk75WxpKd6qQsqrC0nbNGh2P+0/oXzEEj42g/hM4K55g="}]}},"1.0.30000765":{"name":"caniuse-lite","version":"1.0.30000765","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000765","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"aa1a75019276b48463c0fca2a5257fb9f26a7c9d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000765.tgz","integrity":"sha512-GODDEoxzQ/5WF+hLM+zDS/Zz99/+GaBHh3QdnVP/ue1+zPcvE/ccaUtLaHK68q6KdK3zVgIZaRAgscGd2q9usA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYU4vfqAHniuXewtb+9b3fg81HzpgkgsPkFTSthnw38gIhAO119llmb/sydylFzf7KVDpE4wpR7xGvlyuFPYAbd/+o"}]}},"1.0.30000766":{"name":"caniuse-lite","version":"1.0.30000766","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000766","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"8a095cc5eb9923c27008ce4d0db23e65a3e28843","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000766.tgz","integrity":"sha512-dHLsLSAe0YgralnLzAKGEhIgIt43vaIHr5OtXEQD4gNJUe4c0wWQLgDfTDKlE+o5KJT0X8a3dgP79gNu5AJU+Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1n9tcYoU4Ulo0ii5cVuqaA4S6Ns6JPc73yf7EZvFVnAIgDNPJfAPgCpaLi/E4RxywurlsZWN8uURg3pLEjRHpgb4="}]}},"1.0.30000769":{"name":"caniuse-lite","version":"1.0.30000769","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000769","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"d68c5aa0772ea3eac6c97d42e239c9b4d3261b93","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000769.tgz","integrity":"sha512-N0rppp/z1G6emBWZaXwhOkWDDgtSAn7KmLTO231+IeAk2q5zZgfHMk5S1lUE5qT8XfvAV8Wiuomw2tYx9dx6Kw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGfJP97vIf/3JoXzPeQaTUNZhjuQOEj4CdxtaQm4/r4pAiAXrlcwW/S+/Hcb8VTOOUjuCse071m8h2JXrXfNPSphpw=="}]}},"1.0.30000770":{"name":"caniuse-lite","version":"1.0.30000770","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000770","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"bc8e7f50b073273390db6ab357378909a14e9bdb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000770.tgz","integrity":"sha512-HbU6p/MWlHmYMpakO1it/bilDlP0IedKTy0HAL916f/ng6f/8trHPk+bq3TGIZPsj/IYPuiwyNBeCuaQCif2qw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEgdTpJPLUeUnxwvXZ6TsyRnhgd8enRiNoblF6mIlJQgIgNtyZAW0hs1vOa4UzFLVK6yk/w3lYNkx0Wxt6UnO8TG0="}]}},"1.0.30000772":{"name":"caniuse-lite","version":"1.0.30000772","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000772","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"78129622cabfed7af1ff38b64ab680a6a0865420","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000772.tgz","integrity":"sha512-GTMAB+imKKv5ZTI9iBJk9D0SNBYVT0WiOzg+aOQckw3wzIlmWjdqMO6C5Y/Do8GYPDefIGGTbGXWKdlN+rIQ8w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/Z7FQZNBrQb9nXYSZLb4SskankxB9HRCG4Q71kmJBDQIhAMgf6wvJ/2gBhSVBE7dTJQF1pFn2RkSJJvnHGjcG/I/L"}]}},"1.0.30000774":{"name":"caniuse-lite","version":"1.0.30000774","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000774","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"60f4ecf5d45980e7ac5901f03ce67f1ae08df59f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000774.tgz","integrity":"sha512-7FQt9FocEb/zRMGcI54VjSZVFqG753QhlE4KhGMqSlGP7fA8Q2ftSsq50TWOGAWgXEANoi3HyyjhRc8TwVYRFA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEgpNUvmM9nSIsOqLr3bV44cH4zAyXX5XXpEahe1JtjRAiAuEVkpxpgZu5w34CS8gDxNJLeZgB/WiFjcPbcmOLqU8w=="}]}},"1.0.30000775":{"name":"caniuse-lite","version":"1.0.30000775","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000775","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"74d27feddc47f3c84cfbcb130c3092a35ebc2de2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000775.tgz","integrity":"sha512-2xirjPAkYE2JWuShreLteoZ707FhD5gIIz2yj+igqC/MmaoP6KdRDyubu0s/NWZwf/asMfcehrEjXDuWVl+8PA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGlf2HizluJEYpVWBMG75/7aUzSTleEwnEJpZX69hLehAiEA0/vnUfCp1sc1MbDscYhD+2bfwvQZndkNFC7ndE8v/Yc="}]}},"1.0.30000776":{"name":"caniuse-lite","version":"1.0.30000776","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000776","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"616d0f16fb8c7ac69f2ca344fbd501a24879816c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000776.tgz","integrity":"sha512-TCOqVx5+DJtCmdPpKlCYKjwhXo/PTms3vJcg/dcKxpGrrZs7GkSCVVIIaKQsUmD9oNUFUxwyNd/LnCbO72OTNw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFGKOZwA3BBC/2oJaZ4gY5n/TvCNd0G6incEkmZCfdxYAiEAzgecF6ff/ptJlXMG4YYfpqILpVO6tS67+Qpki6HCn84="}]}},"1.0.30000777":{"name":"caniuse-lite","version":"1.0.30000777","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000777","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"31c18a4a8cd49782ebb305c8e8a93e6b3b3e4f13","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000777.tgz","integrity":"sha512-wi8aOb7V0ODAnp4HliTp/9hD/hDd9l6MJwpvACcahd/JNiG+cJ/3w+/iBSPNbHxkvKU2pOrrD24Q6KictVxK/A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICJ1otQA6Rn6IQiVZnBg4jU4TFCJOYdxD+4NMwgb/gG4AiEA9ZYPD1I5N5JzYJTX5KchS+yZvBDg1x5XcQsxAt344go="}]}},"1.0.30000778":{"name":"caniuse-lite","version":"1.0.30000778","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000778","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"f1e7cb8b13b1f6744402291d75f0bcd4c3160369","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000778.tgz","integrity":"sha512-Am+gaLIhFEcx+oF1xWtizTTN0/2QmA02iKUPJkqaHIK2mHoXzxYMN/KxKKioR73mxHNyExnLja6X4kGx32CKjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICC0nEvn+OetY07S03gQe9hY3zgAedCGINdQKEOpejqaAiAoSK8D+5rQXTcpNx41YuOwnT+/iqNa7oqdG7/ZZ+Bdxg=="}]}},"1.0.30000779":{"name":"caniuse-lite","version":"1.0.30000779","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000779","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"59285a00d3ce84361d2c668f251fe46baaeb951b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000779.tgz","integrity":"sha512-xqEXiFIYtVl6tltYO5icCYi3R3pz2sQkOy0dNtXwFMlOHBHXOCdFgMoRiTkJ04FVlyagxK61h4Wwpq2WJPpwEg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHTpMTwhDhaFxyGAIR/N5sis25bwsnq0P8N2IkiQ0DI/AiBsCGimwh9e+CjFFVIv3xKws2lkCXIOPkqP5k0pq1lDYw=="}]}},"1.0.30000780":{"name":"caniuse-lite","version":"1.0.30000780","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000780","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"1f9095f2efd4940e0ba6c5992ab7a9b64cc35ba4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000780.tgz","integrity":"sha512-/hz1j3Aqhqd2DznjwCXVGEcMmx573ApGntHnfdCm3A/NMg0ly+0oIFfeocMrqN7jItEuZowzVELMphM6+KFp3Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyR+2UAd4Ko8FYM/hczRcMUjgqt7tjCz4nIcsebIvMHwIhAICjhdV4Udhr19/OXZ98p9pljHInx3zCHjkK4ipftQ1D"}]}},"1.0.30000781":{"name":"caniuse-lite","version":"1.0.30000781","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000781","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"d5afb556b65d19eb499ebd1a5ad990633f85cc68","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000781.tgz","integrity":"sha512-XT+g39olKvqPCuNdT3TAIWSW4j0ms4hgCXZ0yXYC3FnqAbW+Tw3vG0FyxAD2eH0aam6Mnthg3h75G4/KW1Jy2Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIBfhT4+djRgU9nZ/g4SZRyjq5yVh77zmGLRPkbKJkMgIgerrM3vmJis2LdNeL5hDSdEuIhoPiN98N13Qn8+ZuUx8="}]}},"1.0.30000782":{"name":"caniuse-lite","version":"1.0.30000782","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000782","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"5b82b8c385f25348745c471ca51320afb1b7f254","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000782.tgz","integrity":"sha512-DWvadkFesBCYcwebzZWIVkiI9Zp7mrm3aS20WIDg+HC7Lxc6n+hVeYjevUWxBXgNu9IO1odL48kJcBViydiZKQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB0MzIT5GBbuAFfl5wtboOhwn9gZjS2AGvNuE9Y7i00aAiEAhAF5st5iUF7OC3ZivQYUSEcMy8yQQlkDUERsykcYmp4="}]}},"1.0.30000783":{"name":"caniuse-lite","version":"1.0.30000783","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000783","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"9b5499fb1b503d2345d12aa6b8612852f4276ffd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000783.tgz","integrity":"sha512-qqvp//XWFaDaX2pjtVC729ZiDLi2BQa0sXn4FPbFyJW4VAelk+YZwqMQfVSyZg3HhX/QZjzROdUIR3XlbIwHKg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEY7UZynD32OpmZX3TvFdg4CuRtb7AbG+fc7EBxAX/HxAiEA6Nok9PZJo25AYSsvZE+TAXJXa+syJYtKJNn5V2d1u7k="}]}},"1.0.30000784":{"name":"caniuse-lite","version":"1.0.30000784","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000784","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"129ced74e9a1280a441880b6cd2bce30ef59e6c0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000784.tgz","integrity":"sha512-/+IMUeBlyeQL573u/gzSy6Y0KAWSYrVkiZSF1OZwnvcn3/Kala9HKSCTFoIzQjdosph8hyq/IwIKJYPY4gktUQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB0H6XlQr0QjBvnzOtV1AsYBDspZHNWBlmJCjXGzGFuwAiB6OUdTSD4i5hQqVCmGJxJrN8xXgO1kpKD9yPvOHOsDrQ=="}]}},"1.0.30000785":{"name":"caniuse-lite","version":"1.0.30000785","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000785","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"7718192e82b518ae30fe7a8f41bb19b47eaaa04c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000785.tgz","integrity":"sha512-G+tIY9yZ3Aa1lxo97afHZ1kSqxBOQUxGVI75wu1Q4gbE2AGZ+k1ETLIApQNTZzBYQFxMhsnkjQ66xwqHwjkjFQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUA4/wi+EflBg0Grn52TKaID/Wi+qfdPcpKcbUUp2jGgIgJp7laDlHt8pmZ6+vAdjYzodOdDkanygPKidBF/id6U4="}]}},"1.0.30000786":{"name":"caniuse-lite","version":"1.0.30000786","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000786","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"1b425cd8568d805bc5638bde4905cd8635687746","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000786.tgz","integrity":"sha512-SBynnSPo0e/T3PNrLZvbK3Q/levgkOYsWSjOBwzFAulyQhTsh1kGWdhxF6SS4m2bsr+dptdWU4rJ8ngSUtL0bw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICNENNrLxHkw98gVjHbHb12411zr/IoxfwPk5EfPSabCAiAzOz4zKrjinoUvhAqzBnmIRu8xT5jzMr94lcsoFcS7hA=="}]}},"1.0.30000787":{"name":"caniuse-lite","version":"1.0.30000787","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000787","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"a76c4fa1d6ac00640447ec83c1e7c6b33dd615c5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000787.tgz","integrity":"sha512-soE7AquQ37+7U625S1MFG0riRQRtPf5xkLbjV2L5MS8wS9JHf91Qo7jDyHqbn4tB/7q73AdUiEmacZ+yo7C8PA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDe8rTHZy/iZrWuAx0i2nqJkP+KXcY1WZrU+GFMWQI7GAiA9eis2ZDF9CvORY+eUs93E1odARSkzxDQI6Uw7zr5eXg=="}]}},"1.0.30000788":{"name":"caniuse-lite","version":"1.0.30000788","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000788","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"b96920efca1960965c3b0e8690a06612db97e4df","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000788.tgz","integrity":"sha512-uOjB4OzX7Ef1HK/v4I11T+HAm/ZtNnDkTht1OKRn0eATli86kwcpSWQ8ucJvLEU/Y8bw07jf2BfmNXbfwXmZow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDPQt9JG6A9jyf9z86xZ/pc8XWkIsn2FI+PdoRXaT+6eAiEA6/+sV2mp33Yo9XJzZ0eyw+Ez1ThkOhi/X1XhumBV5Iw="}]}},"1.0.30000789":{"name":"caniuse-lite","version":"1.0.30000789","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000789","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"2e3d937b267133f63635ef7f441fac66360fc889","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000789.tgz","integrity":"sha512-B1K38ZGHkbPTHh9vCuGVVFHG0Rpuchr3GQFuuYM3cIWnpfgApAEo8V1ozgfYazn1Ne2MDCUKl8HSCwuwc+1bhw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqKiw0y+sp+lji+5ky32dCgIL+HFsyLb5oOIWC0WqXkQIgHoThBFVX5SGercy0RZEjqs/g7m/8a6MK2DPYWhvoB4g="}]}},"1.0.30000790":{"name":"caniuse-lite","version":"1.0.30000790","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000790","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"c954cca780046f34c4b433d324ef419e1db51a53","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000790.tgz","integrity":"sha512-2Hsw2a26TqPv8uxT3xkCoN0FRenPpCTlLdQVK6detTYQNl1Rpblnf7Bt6/k9xvMj1LzSm6dSCCjyrEEPEOcaUA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICZVSBe3OQM2B184tic9jfPpu7AZfTDiYPed1j/gZsLuAiEA1Ac/IwWoNWi/i2YYPL49w0rIN2p4FDZYu+f1gBk8P30="}]}},"1.0.30000791":{"name":"caniuse-lite","version":"1.0.30000791","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000791","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"8e35745efd483a3e23bb7d350990326d2319fc16","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000791.tgz","integrity":"sha512-XSAiVuTynrhnozasrrukoy+Eq7jVUdDhsw1mWKZa5jwkxHaH0vy6fhz52Nk9CSZuiYcPp340kTgYOy/sWqDaRg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB4uF2ufoz7djK08zxrF4rWvqD/CGCHdM28/x3QI7byIAiEA2dKtg8tI/Sruj3lbaXMnQ4NuuGT0YGO7g9r0RruaoI8="}]}},"1.0.30000792":{"name":"caniuse-lite","version":"1.0.30000792","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000792","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"shasum":"d0cea981f8118f3961471afbb43c9a1e5bbf0332","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000792.tgz","integrity":"sha512-d+WmDr8VKQPQfyNba0TwGzyJQPgd+W5g6umqFGH7lDKMerC8Ne0gw//P+opYdFTFnBXGh8D+Ok55MKm50TG5MA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCNwgjpy2jGbrJEMpYRsrdykavTUDu+t20xgUMPFWzfLgIhALlX/ij4uzw8XH1wOqODey3EbOIHX5uDkkNmqlvscthw"}]}},"1.0.30000802":{"name":"caniuse-lite","version":"1.0.30000802","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000802","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-mpow+br11L9xGh78AtiSw4643VkbiHvQ29Us681n3uOcBsThpzpiLVNeXAN6r8/BWe0syBLOqEJIeuBbv2JwGw==","shasum":"807ead8e2b59a3b90f26702fb0b220623ad9f287","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000802.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHcJ4gu2D5eCsL4uTZsVzGNpLI5//Zlh+X2SJKm7Rs+AIgS3ODYKySt3SagqDBRxMFqg+z18aupXLywbxiYBCRRVE="}]}},"1.0.30000803":{"name":"caniuse-lite","version":"1.0.30000803","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000803","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-AoROHIFLv2iv5CG4nonOfT9ZCQ3JTN0GyEn8LG2sPb2Wc5cIyX/UwLYP0pnVajVF3LWH+mrO/DXBzmte0BK9cQ==","shasum":"9939c37149d38d5f4540430490d240c03106a0f5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000803.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9b8BafejO6gVhEBAciPAUkm/XusoSF0T7VhZmG7te6AiAyPE4TEEZO6sdo39hO/Lf/I/hlQaHNqv8Gj92AHh7YFQ=="}]}},"1.0.30000804":{"name":"caniuse-lite","version":"1.0.30000804","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000804","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-HDZPSHLi18Bac8YU+bDJPtJLf19DwoNTM7Qp1alhltYW9FxNUlwCgk1xk92H0hB+xiKW4Jb9LXQv6M+riQyxFg==","shasum":"8729a143d65378e8936adbb161f550e9c49fc09d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000804.tgz","fileCount":731,"unpackedSize":1159282,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDs4rIMR2oav31E+KU82X0y06iXRT1ub5yTqLQFnyGp0wIgM38w2B58brNxTaJI6QVP33MygOdxoYnrhMElBF9H+W4="}]}},"1.0.30000805":{"name":"caniuse-lite","version":"1.0.30000805","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000805","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-g04TTapYF47M05D8dshTSTfuAHTaAyfYUsD926QTcNvnqitFJb277L3y3RdDbcrjxmqzJBEqorkc0AykqMv8Ig==","shasum":"83a5f21ead01486e67bccca6fae5dca7cde496de","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000805.tgz","fileCount":732,"unpackedSize":1160237,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC0Cxyt0P6Z3TteZ95BdAyFm0OOUJe2mStyF2LhfVO3LAiEA8vKiv1PwsC3+ki9CyCHYLpJZhVi7zj4TnPNIMbgm04c="}]}},"1.0.30000807":{"name":"caniuse-lite","version":"1.0.30000807","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000807","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-8Dff3cZA8nUOdzGsb7BOzwAv69jzzpx8/MS9YMM169sCxIV+80rRiMWggbu1UTO1HR7qf+cxg4ERRF60JhX3/g==","shasum":"51ea478d07269e9dd4d8c639509df61d2516fa92","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000807.tgz","fileCount":732,"unpackedSize":1160365,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICA+8hrenYZbGK/N3e3afc2bmG5CwFx7ZGcBp/RpH85GAiEAhJjIrKdXYO8y8G/w+t1KktTnkxFk1+X4/tk8lbKMorU="}]}},"1.0.30000808":{"name":"caniuse-lite","version":"1.0.30000808","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000808","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-vT0JLmHdvq1UVbYXioxCXHYdNw55tyvi+IUWyX0Zeh1OFQi2IllYtm38IJnSgHWCv/zUnX1hdhy3vMJvuTNSqw==","shasum":"7d759b5518529ea08b6705a19e70dbf401628ffc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000808.tgz","fileCount":732,"unpackedSize":1160467,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZ0quHhR0tET1lz6QEqK5OcQHNHKMZ93VfqXXokC/xPwIhAL7TovQpgWNQIfsxwjgqWLI0GUIeU46cpPM3zxpb3+rw"}]}},"1.0.30000809":{"name":"caniuse-lite","version":"1.0.30000809","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000809","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-tLn4flj2upmMsko3larTkQh21Vp9pylnNPUOhw5+mubL+67U5Fpm4UG5AutzGBc+gBIPSsPFHDynsiMWp5m46g==","shasum":"1e12c1344b8f74d56737ee2614bcedb648943479","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000809.tgz","fileCount":732,"unpackedSize":1160575,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFjrspdc7yejY3G5omwCsIywyUPNJYLFjUqaHvfuvFVgAiBGpc+frSABoU4lKSPOv0G//A0OTJu1P4Sd0wFK/vHH/g=="}]}},"1.0.30000810":{"name":"caniuse-lite","version":"1.0.30000810","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000810","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-/0Q00Oie9C72P8zQHtFvzmkrMC3oOFUnMWjCy5F2+BE8lzICm91hQPhh0+XIsAFPKOe2Dh3pKgbRmU3EKxfldA==","shasum":"47585fffce0e9f3593a6feea4673b945424351d9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000810.tgz","fileCount":732,"unpackedSize":1160660,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIErXOh+mKy0TcA//Yx9GaNZP6b26iVgqnJz5FxaDUSSWAiBQ/gOfaEZtbl4AeEZypiQ7zaLjLNwhRYSF20/9pL2EAg=="}]}},"1.0.30000811":{"name":"caniuse-lite","version":"1.0.30000811","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000811","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-IPqVics/FqTQqdgcUZLTIe4BBwK3ndvzrAP7NX2meM3kk/w3oGivwWXJ5yvh2PXhWsU6VIKOM4dZCYKgNFh5tg==","shasum":"0b6e40f2efccc27bd3cb52f91ee7ca4673d77d10","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000811.tgz","fileCount":732,"unpackedSize":1160700,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAgmzBwvx8pstZitMdAVZ0kfKqB9IsSOVroXAScRDaAwIhAKcHWo2Wg95hsrg/JPV6M7/kdmZJvxcEonTq9Nx07ymX"}]}},"1.0.30000812":{"name":"caniuse-lite","version":"1.0.30000812","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000812","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-j+l55ayQ9BO4Sy9iVfbf99+G+4ddAmkXoiEt73WCW4vJ83usrlHzDkFEnNXe5/swkVqE7YBm5i8M2uRXlx9vWg==","shasum":"d173b686b49bc941fa18ff2e7e533048e20ed92c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000812.tgz","fileCount":732,"unpackedSize":1158369,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfno/+UOlBioV5MJpz6ORDJfnmtSdm5jxncb20JhpAQQIge+vMsAvAlrjsh1RRfo+O1sWkSxjYl+S+22H8iQLNrmQ="}]}},"1.0.30000813":{"name":"caniuse-lite","version":"1.0.30000813","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000813","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-A8ITSmH5SFdMFdC704ggjg+x2z5PzQmVlG8tavwnfvbC33Q1UYrj0+G+Xm0SNAnd4He36fwUE/KEWytOEchw+A==","shasum":"7b25e27fdfb8d133f3c932b01f77452140fcc6c9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000813.tgz","fileCount":734,"unpackedSize":1160235,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBGuRirVNKtXjjYsVmvk7ybCfNo5HSd2U8ZEdjQd7c50AiBaB2JllQzM+VSZ5dqNj3yuiTfOdWsIH+GEiwbAdxFRlQ=="}]}},"1.0.30000814":{"name":"caniuse-lite","version":"1.0.30000814","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000814","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-Kt4dBhVlnTZ+jj+C8Bd4WT6RT4EJoX5/tlktHQfpqIMgLVrG1KBQlLf010ipMvuNrpQiAJ2A54e6MMbA0BaKxg==","shasum":"73eb6925ac2e54d495218f1ea0007da3940e488b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000814.tgz","fileCount":735,"unpackedSize":1162692,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBIWdhqd/MSF98o7s83v1o4o2H8AcnQ8qK4TUUEJMDYRAiAnjEihMTeV0pYsbpUqhtjVVOmWfZeCpoLoSYjBcc+gww=="}]}},"1.0.30000815":{"name":"caniuse-lite","version":"1.0.30000815","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000815","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-PGSOPK6gFe5fWd+eD0u2bG0aOsN1qC4B1E66tl3jOsIoKkTIcBYAc2+O6AeNzKW8RsFykWgnhkTlfOyuTzgI9A==","shasum":"3a4258e6850362185adb11b0d754a48402d35bf6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000815.tgz","fileCount":736,"unpackedSize":1163641,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGTXb9GQ2uq+ZqLoFxm9O9Ju0am16dyTHOPGF+4jMa85AiEApg8pZebuxSPxxuU0nd6WcuvZTkXhimB3zC7gu2Eblfc="}]}},"1.0.30000817":{"name":"caniuse-lite","version":"1.0.30000817","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000817","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-O68CSiZY4NuxdGT0gQO+2vtU07/FOrCUpGPYincrOjybQIdsSyWC9CWx+hhm+SnCTAwpG/AywH4cU5RAkqbFXA==","shasum":"e993c380eb4bfe76a2aed4223f841c02d6e0d832","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000817.tgz","fileCount":737,"unpackedSize":1164638,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmHCa02Et3rkYn1K1AUdmKXGM3KChiFYS93MxU6x/FAwIgW3Th8koWmdv+0jDESRynvRcoSMvyWqNW8CoYmbvHmAg="}]}},"1.0.30000819":{"name":"caniuse-lite","version":"1.0.30000819","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000819","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-9i1d8eiKA6dLvsMrVrXOTP9/1sd9iIv4iC/UbPbIa9iQd9Gcnozi2sQ0d69TiQY9l7Alt7YIWISOBwyGSM6H0Q==","shasum":"aabee5fd15a080febab6ae5d30c9ea15f4c6d4e2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000819.tgz","fileCount":737,"unpackedSize":1164708,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID6V2rbxh+mdDqb7eG7Mx14fOQ2qSeDrQhUxkRfco+atAiEAk8j2zX2/aR3oq/nHqkYpXsqfzRxRWw38uZo+syEnMjg="}]}},"1.0.30000820":{"name":"caniuse-lite","version":"1.0.30000820","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000820","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-E0dpVjnt1XTNmWlGgdiae/tOF0jrJ/s+dOnwk8PLmPdu5uSu8wTLJhhbhcgUWU4aO9Iy5yUMZYxT60JS259sbQ==","shasum":"6e36ee75187a2c83d26d6504a1af47cc580324d2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000820.tgz","fileCount":737,"unpackedSize":1164764,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpGItQsynEBH9LbhEXdsDq7VIkDqJs2MztAFpb6gXsdAiBYAV2dEvKOUwTbI5UULIDqbUCaLY0O/sX2qlsBTtT1ng=="}]}},"1.0.30000821":{"name":"caniuse-lite","version":"1.0.30000821","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000821","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-qyYay02wr/5k7PO86W+LKFaEUZfWIvT65PaXuPP16jkSpgZGIsSstHKiYAPVLjTj98j2WnWwZg8CjXPx7UIPYg==","shasum":"0f3223f1e048ed96451c56ca6cf197058c42cb93","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000821.tgz","fileCount":738,"unpackedSize":1165723,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICkTxPHSYj6lVhkWOpd8AVsgHGIfXUefKMvY7IFJR1Z3AiEAnEHuo/CbKGdA11rf6XAZBCK/w9ZiI6EvHD/mDdpFNw8="}]}},"1.0.30000822":{"name":"caniuse-lite","version":"1.0.30000822","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000822","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-UDZ2QUH85Dh1WmeD8P0XNHJoPwAFFw3DabBvsRe3DAa+bQ3CNDpCGqZpoMpCDaKXPXLCM8ifisFl/NGijJ+NPw==","shasum":"723bda91e39959a1d3223a05a70ae0e25441d528","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000822.tgz","fileCount":738,"unpackedSize":1165786,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBN1+GkvJFcJtqM6yEQKHiEgw3jRZRiylITfzBhT55vGAiA6a1CLKycsyepvJeEMRTYdBzL28f0rBWCkT6KLKMgkYg=="}]}},"1.0.30000823":{"name":"caniuse-lite","version":"1.0.30000823","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000823","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-3rrhqUxwBgrwNlWVUEwIJfqdZNwLPX18eTo7MGXb3gueDpbOFW6w5OXyHscdBd6IJcu9wnKmKVd7nSl+r7fmgw==","shasum":"b79842a5b5a48eaa416b73f5a5d7a23f52d26014","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000823.tgz","fileCount":738,"unpackedSize":1164031,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICz+nKZjt1kGp+e1UonD4LV9kJw7/alwxKyY4hh6GrZAAiEAnWXqYl+DPfz9S1FvKunZNuuAduuV5HFB3WIn+QYGSg8="}]}},"1.0.30000824":{"name":"caniuse-lite","version":"1.0.30000824","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000824","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-KcgeAvVkpzN05Mjiyz5vf0le5AWRwfRGqGkKXWWsdrLQd4EIBevReSy7mYCdwSq7MqKrmJ0lEQEkUQE2VspRRw==","shasum":"de3bc1ba0bff4937302f8cb2a8632a8cc1c07f9a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000824.tgz","fileCount":738,"unpackedSize":1164102,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGs9eFJChKvtAGO6FhHZelUGwxMG3CdkE4CKjDFxBMgnAiB9IYSH75OxDnZYBSJ+LIXTuCza08a2hJe356Yq76LPjg=="}]}},"1.0.30000826":{"name":"caniuse-lite","version":"1.0.30000826","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000826","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-GdavL9y/J7BGo565ZZbdkLQ5vW3eMGopGB5Nmwnjnn4v5ykvdiVLJfbKuzVz7rq1dI1gSeaYy6tuy4lOOapJJQ==","shasum":"351faeed7f90a84b676598d4371441ec452f8372","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000826.tgz","fileCount":739,"unpackedSize":1166015,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDn4dESAtkylqnsnKylkRsD8TJRa8MFmvpVdFXo8KVOxAIhAMwjiUwxL8+OgmkRfpB8Axfp2a313MBHkIHfk55CZP6/"}]}},"1.0.30000827":{"name":"caniuse-lite","version":"1.0.30000827","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000827","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-j9Q9hP5AhqOARNP6fLdctr3XrGhF921sBSycudf4E+8RCWpFT3rJdTfp/5o8LDp6p0NJTpYWEpBFiM+QEDzA6g==","shasum":"2dad2354e4810c3c9bb1cfc57f655c270c25fa52","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000827.tgz","fileCount":739,"unpackedSize":1166079,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxVfe0Qb8hUoVJhIQB4B6MaXmxSDeRaPr/qPeedRMO3wIgDVJgtJvSm39OoDbfC+lcqxkAAPlYL1F2GiQ2nerXqG4="}]}},"1.0.30000828":{"name":"caniuse-lite","version":"1.0.30000828","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000828","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-v+ySC6Ih8N8CyGZYd4svPipuFIqskKsTOi18chFM0qtu1G8mGuSYajb+h49XDWgmzX8MRDOp1Agw6KQaPUdIhg==","shasum":"048f98de213f7a3c047bf78a9523c611855d4fdd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000828.tgz","fileCount":739,"unpackedSize":1166200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHfPBsKUVwE/RfxrqxAA8ZCU09csqjZ2NK88XYmElba0AiAUfAvCliL+NubI2YYhTgeBIvSfS+tvdQRDmxVGlA5rsw=="}]}},"1.0.30000830":{"name":"caniuse-lite","version":"1.0.30000830","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000830","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-yMqGkujkoOIZfvOYiWdqPALgY/PVGiqCHUJb6yNq7xhI/pR+gQO0U2K6lRDqAiJv4+CIU3CtTLblNGw0QGnr6g==","shasum":"cb96b8a2dd3cbfe04acea2af3c4e894249095328","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000830.tgz","fileCount":739,"unpackedSize":1166296,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa0YsJCRA9TVsSAnZWagAAoTUQAJfrGKZvYsyEemkN9rco\nxYaRFUqVOxhW3oWkYej9RdFwVcb94hY5wEZjtyScbtFJ9C9QfhhLp3Cy4rRm\nHAxnuDYj4fMpgaSbOpMD2h8lxljtWYRSDl5VgE3vnBEHWc0TovV23Fm07Rre\nIaGU5zr8lQUBrpJz8YVQvgresG/uKUhUJ2QEmFTyM2DBsDpOTrjesWHyqM2M\nG06l11Nxxt7RN5sXSAxt7cjf3437YojmEkzaO0lfnu6XvrO3VZS8amGDr1nY\nTMKPPt7AX48vFFs1lY/e5uSOYi/6HiD/KyS5TsFaIcYa54WTwOxND5n/1Iho\nOZMpoOD1E0z2FZYQuO0YUzJ+O2YxYoMP1lEee6/ntvuMA0zoVOlU76IK4heC\nhAjeDqwPVvXHID9IghZQpjdPlflIsQmxnAB5fanXrFlf9CiOEhOzBpDo5ePu\ncEaqGbEgswDktzbP3UexQN4uXje1nf57nUBw6rjueXjcQwhdjp6YaUsMHFmw\nJDzscUvMu5RegWc5E7UsO+Jh0jiTric6vEU5O1lGXWvol8RP2cJuBMTI2jwe\nEvTzV/PXXSPamhLgEnCN9hF9vq5EdFysVu93+f02wbhY1Nh4VJxMrRQapn40\nLRJcmslATd5asc95krfZzWRdxjd4C06ROZtcoMyTOr7yaW23US6baBdGpoY7\nIC/x\r\n=Mua2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0eyyMtdE4dXFMHCgOnNOfexmTQ3UM5cyLFA/CidolFQIhAOQy5rEl4dWFHkMze9daeia6GkZTPQSpmP1l99XZn5BA"}]}},"1.0.30000831":{"name":"caniuse-lite","version":"1.0.30000831","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000831","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-M//iCiTQy27XDFAiUKwooxCsvvPA5zrzejAz4I9INUUlsOXFvHaE6Z0WrBKk2QkNRbNatT9T1B/YbEQzfa+yzg==","shasum":"ae109aa23218f721ca87cf45cd2ce56de3d2980d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000831.tgz","fileCount":744,"unpackedSize":1170624,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4+P0CRA9TVsSAnZWagAAaxcP/1+1Zhz+XUDDVuuWF8Tr\nhDixiXnMXx1XDvuSdIcI58yMu/BUcIb91fVRILxWz/5GqHcXBkmU78X5/oiQ\nOzgJZAUtbtCgKOs8cV4dTEu8ginuWpNH3rE/sdMnVy7JxMqBM9YqwP1PdcH1\ngr2g0R25rVDENjQ0glvDzk6oorVp39muVOq9f6N3c/9VT8p7bmtZoJst5GQM\nb6vCwhjaRGJpEbZYe5EJ9vc+ZIkLIbfuEEKmauUK2m5RhVrqkranyAfWInfS\nb272ZLo3846I2b92WpFS2IM2TL0dHle5EmHiefx6XjXrlVtp1fZuS+KvEzOz\nXc7bmFQXSY/ibPkaaQoe/xlt2Lq0H2DHw5gCTB8QbZiqzoVrVHAjTXKRAoq6\nDuF023aOhiltg7I78vdSs3cacJjASzq7KH7I0aPr0RvLqnjJYwCgrcV4WS89\nCcOhaZseUiF9xQRMPAwfjHMPzZvYPm38ksTKLCfn52N7CIeC1cpXYvyiXgNj\n8uLsmQcfMYYrfRNGvo+1soM0NGzwFESDaYCFtGBxxglBZMsP4QaJE93Kdcjz\nsv7Y+WJwrYmFxSU8UKDgZvMTi3nJbrVSKrl2iD4Ph313hW/P6nmV5nyEwGkS\nNpeHSSswkG++aSR/uPRr+UQ+wH5yVVxjHX4Wo59OuIg1c25+AoR89VoquFn6\nd0ui\r\n=358u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA7HxCd71NVGrwNixvio7CWbxhnlm3TdNSJtzVNtYuckAiEAyoGALhr0VCXNUpf8lWeZiYkf4kSRYDVl6BC8M5DF3Q4="}]}},"1.0.30000832":{"name":"caniuse-lite","version":"1.0.30000832","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000832","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-WMC2GiGTPxGywFL70h+CnP7GAYo6LM6JSI1sF13vAZfXCzOeunHzl20DpfbDGMdvtT2wpqvabY96MHEp/la+BQ==","shasum":"22a277f1d623774cc9aea2f7c1a65cb1603c63b8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000832.tgz","fileCount":744,"unpackedSize":1170690,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4/IDCRA9TVsSAnZWagAAmQwP/1Q4Po0ayO1Y9C9GTzQU\niexVr9uu4dMtS3htareFBNE4MVoAMMBm2Bn20UKGfiQ+NFvrVnxypjFA+k2s\nS/M6tCR0V8T/bwH/4dqRbLu0LIGIlHZonPWAnqk2p1bjdPY/vU0Pi6Nce8Al\nqtNLnz2dxxUjdnf0yPEZWYIUKwTzRFBS4etqRzzHJpYBfHbZQBBsSAcdX1Rn\nf+GLZAl47CEiKs69XqOAOKocOI2RR/mHLtXh03xSj8+3haNY789gTQbWtAOz\n/VCQUoq/3mpQaHf1J4xvLe65rTpk54I6L0fWF9XAkvG4vSTXWgEZO23Tvbrv\n7cg+HqGTKjOs0Aqh/EADzyzkOjYcKaM+ryKqprsg+HlPwdeWo/pc1Ve13klp\nGPiu+jiGRSMNs02LtSOf5VM+GNeTBBbg0Vb9gFh3SPWhEkRqVp2wQVBPScfx\n1D/J+KjLAvm8llQ3/isADVK91UKKiqIQqlrRB1jxhu5tHFwGsLzxXsyPy7WG\nirDzZnmcV1tHizPvSiX2rrX+FXXzo39rLJTe+LMkVORjvvACqxLiHvzMzGrJ\nnNPA9uYPRmPfyHlIjKVRgjtp/g8K7AVrese18bV0PS1nxWacfjhVJISM+qZB\nb4+rOVxuvrJoDflMrvBfeR6PJGpSwyAsyRBIjo8caIZUEmeCGXiQBpu9yLJL\n6pAN\r\n=JI6s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFW7ezpopSZsXFpWeTO85o4Z8rQ6KPnvEebh3VfnCKwAIhAKDuATSl2vdEgyK97AtnN8XLL380F2+s9Ikosl36mOPF"}]}},"1.0.30000833":{"name":"caniuse-lite","version":"1.0.30000833","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000833","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-tKNuKu4WLImh4NxoTgntxFpDrRiA0Q6Q1NycNhuMST0Kx+Pt8YnRDW6V8xsyH6AtO2CpAoibatEk5eaEhP3O1g==","shasum":"98e84fcdb4399c6fa0b0fd41490d3217ac7802b4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000833.tgz","fileCount":744,"unpackedSize":1172283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa6TgYCRA9TVsSAnZWagAA5UIP/02WEqcagGnr3EB9BqMo\nMieX7pOJ+axXC3hVEaGdqK2AvZyorkgtEFanHNTvyKqCfT6+5ciddJpbeBi+\nt7LeqGU5TEh4M8pc9Vxqkx/jKzzBu5FaEhO0ODLG6LUSPTk7GzgkFV0LNvbS\n6RngJRjIq0bwiLy4+RcFQNkiCkQs2A/jIPGkY/AIEJpXquwfim/wyWmpt/PS\nHSlQ1NiheE8VlnsYgnVau1HlCNy5vI2oCScQ7gnpTLBU31ISk06hQgBITB5Q\nahOLjFlGal3zOSVQBX+ZJyXIcIprzSNPkiVC5/KrrnL917eS3D2k2YgFyRxt\ne7GRfZ4QTiCW4ztP42oWzbqPEGrMpUNxEJwXSuPIbJGEnxB6Qia2+M6WRgI0\nj4psLZQQsqEiJBfY4U4VitC6wDtMkmCZUANjkiqug0MsTlNyzt8RmnYUweS1\namy3aJxDotPvCYrHxE9yDdDpgkCnNmeiGqwWiz7FlRBbFexRSL2xX3+bfJs2\n1svrn3X76i9yEfCQBDXIRPOiOti4M5P/a5cLVVVhZbX9kv+fE9ENseY76JbL\n9McsxRFmKM6NN6TugHycGfSlxdBzBVyXqFLXwPv/I+oKKGKKukLejWR1J5MH\nf4pm/mZAI8O7+cm4h6WQBcxtzoPBTLKJ85aCfbqbYt0Ji0i+h4GOi9Bz2eX7\nAlBS\r\n=Pj3+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDSwr3erlldbG5JVM5zB7GoFigpyQmibHFM2MU3EL/JhQIgSSDt55F9gQlAz0WBmIdOPNZpAO7tU+JePigToERSW44="}]}},"1.0.30000834":{"name":"caniuse-lite","version":"1.0.30000834","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000834","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-HBQ4JDggVOYGVxhKueuSOJAS/+UnWI+CdQbbpfOW4B3o2SVPueiyTe3JCj1yq9IN+kkskAUIx9tq9ON+oaQfFw==","shasum":"918f42510915356c327e5fb79e7d856199f8e786","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000834.tgz","fileCount":744,"unpackedSize":1172376,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa7n4CCRA9TVsSAnZWagAAleEP/irk6A8aWWgRY2bkbYHS\nSHxkzdNpGmRaezvYr5aQVhuZQNaR112vl90AyTiU4Ldy6zkgcV3WW67xKCXQ\nHE+/nHzqhYR55PltXgV01Ps9j6+4b6S7JAFU+f1sHazWjIWmn7JMOEhttpOG\n8vsNxStk4jdAPeUZzXMENVWDtk6FBc22uQs/TgQNK9x0QW3Hx4UDa3fgDFJA\njOcrlaJkwcJ4oiiZcp3wxYjOVnshCfgYOZKSrEZmZDhUWmjunO9BgcKBLmh6\nuBvxmBB2VZuYbLfxUXLK/pAf4ABUeWLXHkOvlXeVEyU3ussMpXjl8rFzkZf6\nTzeOqnro1YBPsxf6vbmcvmqaawm2TwB61xM4reZgmWiRVWpnVHCiVUCbiA4g\nmYSE4Ok5e1sO1rSQESI8Y+45RwCAu9827OIHeQ2RptL9aefaQUGObprxtF7v\n6rrR6jhU8h7Dd1DwkBfuwPa70jcnJdLMkNTuCyjYD23kORWazK4oRXVhAalv\ni1SsvTa6HwSFof5Cce6JlzzIsJXKrGENSguduEpQBmkauIoMl2p+qy3kOz+n\n9etLyly4NVtqC68Ughdhg/VItWI+Ka66gn6PrMMVXoU7iiy+FRG/vt6bp25z\nG4pt2ake/B3fF4KRqSC22SoHUDm8H5k1IDHATiwfm3nxt6gYnOsm3fVX9H3I\nk65R\r\n=kSOS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBuAelKbpQ96Tr2PPKEjo8EYVb9AB8sXK1w30bLPl7o+AiA+lSSBKC9kzbvzXMyg1y4Tl7FVORYYvrj1DvvzRb38+A=="}]}},"1.0.30000835":{"name":"caniuse-lite","version":"1.0.30000835","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000835","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-88MbwAwuVWfwC4xHwKx9Z/VSvmIfLPwURhmxTPqP5Cx6zHQ0xa2AFKJvTdC2aUn07f2tR9yvYL83CollBFANEA==","shasum":"517c4d3807a8527b0cbce1d84c85d4487f877268","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000835.tgz","fileCount":744,"unpackedSize":1178365,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa7owTCRA9TVsSAnZWagAA64sP/3VXabkYEmIFvrTlyGXf\nYijTMkoRso/Xb9ivllUCVla4kRHHeNabKCA2UMZ2YWzAMsjuJcmr58psy1Qk\nnt01bL1QUmD+0d2eqrktppqqMj18tLw0+2FSCmIEdJZtpbyL5+NytK3LJ7fu\nDRLOamS5k99ouSCIyWXoZWflx82wtgqj73IRVHiDa854IafxEBrJNk/vHgBk\n0EeS2Mn5pOGxucE9othnLPwyrfxTvx3kofYPt8/lvF5nAcaVqi/5xU0FzdYG\npmK09r9+Tnc5H0GyrnsoOwMxNUoz8Rtf4/AfqouiZi+wp/+Zr+7SUatf4RC0\nuOBnqT17AiLs4xiF1obEJzFc1M6Gc6Y/j0p96ru13qljgMYUvyPm1sWrpfzw\nVR79N6SlvBzqLSvM8Kys7OCAdzxwWLOMvijA33m31vw5N5Eu33ukyxJhYU1X\nBf9Z1UWx8ZnztCusJ2SGixAnFQuUZbNBo/EIqduOaeDCtlJcKU/N3NppScbq\n27CxiuabPBWiVnWLunEPFDYCd8KZqJ+953dZxcszgzWf+k1y2IDgh8saxTyc\n32UrO0E68mxTSjkfbKudhwLIw9Z6GoB7ceE8gIjlPNqaz85qvrf2s86pOFbH\nrt3p+8O+J931Jq1hWQzuEkkcQre72OX63KAgKPNQ0rBENIvcf6NYALY0nrC8\ndCdN\r\n=q10p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAsBGWR24t8VulDAAW3j2GOND6p3sdVhR7n1tkndBAlAIhANkub7UiRdkt6T0BMlb9bN4iEDR+B+u6Es4IBW77JaOg"}]}},"1.0.30000836":{"name":"caniuse-lite","version":"1.0.30000836","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000836","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-DlVR8sVTKDgd7t95U0shX3g7MeJ/DOjKOhUcaiXqnVmnO5sG4Tn2rLVOkVfPUJgnQNxnGe8/4GK0dGSI+AagQw==","shasum":"c08f405b884d36dc44fa4c9a85c2c06cdab1dbb5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000836.tgz","fileCount":744,"unpackedSize":1178444,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8S8OCRA9TVsSAnZWagAAkC4P/jeSMvwpsd/3kYWSCPtv\nfDlTiruAG+omDlmceOi1Y9n9EYkXACNWA+m+5WA1Zw7yuJAOI50rt+ZgHB3k\noUAio3zd61CXr+lma17dhoublxVAWG3iB5ZpKq/AqcAXEdg+q4qRP+Su5BNa\n1RK6u31UHH7V3Ek8ILFb/O7y4KKNHkNvQvcW49vP/GijLbTaB53Ujat3plzU\nq6xdtYScd5KCGkRKDymhUAvwD43f6IOOseTl/Tx6GLLNAiLQNWNcxX5V+qNs\nZXSWXhfXVArrvuwrILcPaIPwxu2U4SePH5yfs+L4Cp+WsbHTOSXbDW+UyEfo\na6bE9yJwpdPagqa0iVBOQ/z0vdz6j70QTjpOtNbMmkNCl461pRp1UJXQjo2/\nSEKfXm6MnwnZIg+O2s0slqvi3cAW//CoFx/OnXLiB7/71Jrxq1eOy5AzqLnC\nr3DFq9zKd0Nbug0wKkKYiyimZrtrdiAr0Y5rU3WO0/OUn7KBUX+sq8wWzd0J\n7bB45yKBmiDa5wTUBErEBsApFKBUdTbTP1E8cnTmAcps+nVvk/9gOZjfA4bF\nuImhWylZQBd005wjE58L6DW7p7sVNoZm0mE7LMNzB7hjWDQVF44NBR+bXE7N\n1aybs3Gx7ZYYtU3Wjc9G2z/Foa3EtBLh+k6Q1Gjarn6icfGr46M/zpheVBvI\nASaR\r\n=Qcc2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEOZR7ASo6fyMTgv5qtKpnev1Qady+V7PrEyM0MHE1/gIgU/ryl+QNTSC+6rMekCnA0ywXwq7dU12XATO40gljPgA="}]}},"1.0.30000838":{"name":"caniuse-lite","version":"1.0.30000838","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000838","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-V/X/i9xkxvin36IML08a5HSseIwOy/P1VBP5VRMxFixseUsHuBVM5E8rtpVZkK/Yk6rcib6YrSdg1JeiNYEVUg==","shasum":"244487117daac6ea8ddfdd5f32a5ef9b3285bc20","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000838.tgz","fileCount":745,"unpackedSize":1180355,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8+AmCRA9TVsSAnZWagAASUgP/RT/K3mMYCJfHmCCmzFC\nQHzhgU772WXWBd4r8NLEJfVzF1QjW5SHWz1HHcLahy03kn7IHh0vYpjtsyRY\nng98dUJe6pr5NZuOVvFOwyISxesOAlHY/5iY4PnLYmAH/e8H12V6jS96jW9Z\ngRAWMv30Jo0RH5DrV3tFf8un7bGNbBqrB+O583cDX4T02ln7aHDZcvLvlpgX\nQS6oDDCnRaV8Ww48HB99n5sUA0BMcQo1UHAlkIsle98B7oFnqOKkIDq5HNlZ\nBWwiqUuCJvXKQxAjCxuAcf8c2YgJQgS9tZNrpdfLAX5Gg4GkHX5z5Vvl2TKq\ni1bml0amKEGwNdPH9eKDYFbpuz/6kNQegG8qwlSAsZcvVCVBlP0sr/6daDqX\nqwNSa1SjMbikoP74rakot2tax+H1HPcroozcx4WGj45sbd7zFGnH8iqys8O0\ngyOhiIlI5Wr1hczRd/T3drvoUTfKt5S/te8lebIBaVTK0LM+hIAyl0otEbDj\nrC6apmXgpcL26YczhXgPusU2VcgwETDvHnJKE92+h/BsuyC5enV7jzTklGDk\nl7KU9Abf6Gdf4NwXN5V5mW66w0qcnPDbKlvZUTAbDxHaAXY6m5ws5bU3ukh/\n2uu19izIninuf3WTUXbL1xdifFBBwl1KJ7WO5LD9LujuJ1oWwOgHIXVj3B50\nAfHY\r\n=6TNM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMRgbB3YUbB71cdAWY4gqYj8h5AxSu5pC105rfuhlzVgIgcnUY6kPSgL/SFH44+o1NpHr+6iMkT0Ty986jn+GBA0k="}]}},"1.0.30000839":{"name":"caniuse-lite","version":"1.0.30000839","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000839","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-gJZIfmkuy84agOeAZc7WJOexZhisZaBSFk96gkGM6TkH7+1mBfr/MSPnXC8lO0g7guh/ucbswYjruvDbzc6i0g==","shasum":"41fcc036cf1cb77a0e0be041210f77f1ced44a7b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000839.tgz","fileCount":745,"unpackedSize":1180423,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8+4xCRA9TVsSAnZWagAABl4P/1uGVmrliF850QGYAG/B\n396oRvJeTAu1hS9A18UCOfyncFBQflhvjUIQABtWf3oJ+pDWSZhPVfZVY8pu\nlLxoI+EQRFmhDtDFkK3MDmHk/UVrWjZtXQq3WVIJliDAN1LGvVwsAyOO+e/k\nFx1cpY9mkjmHTnjReKqDFdcgehMp2fHu9pbXAAlZ2LnnHkzgsnJ0MFv6EUmI\nhvZVWZeDfuTARdscL5VgnZHOggyyKlsjBElbfYp4zBcFEVYGHSOh5EemvJCC\n1XD/y2nPBjxQb5odtGO/UO1vW5p5zmcHIzbr1tUGA7ct0IiyrWrtmZCLR/Gp\nj5rgig2GqIP/wouXTOXE7/P35KfW1BIeA8l0lk5F+g+5o2gdTCGm4E98GQfy\nuBAckPF9auE1YStBwH2vloKvO5PZBvYdXPXxKg5Ypb6vabssr4Row9tL5vPi\nqYHzRY8nRmwdxNci5R8Dv3pMkF2QvSaMdYoUjAw41QGohA5Co2u8fe5gVXjq\nnCntynMhP6NzmvZdROOcpQ1XW+KVi/qVheS8S2zOZPHhwEDOtM2xmGaJFREc\nI05E/AjC5tLgFiWjNomff9NQaGgRYRaTMU/VfIBTRdUwiYJx+nlRLSYJST83\ngT83cVxAMgZ8WsMnkTdD9BmGlZcTsKCH/WYm+9K2UkIoDt85uIP+93HznfeS\nBDMe\r\n=YTIu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC73DJoPecjNkJ1T2Q68Cy6LmZthYsk3wGSMlC0oXOVCAiEA11I5dOT0Q27QKkIq6OAJFGhMZPXuxasN6NHL8FGoREE="}]}},"1.0.30000840":{"name":"caniuse-lite","version":"1.0.30000840","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000840","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-Lw6AaouV6lh7TgIdQtLiUFKKO2mtDnZFkzCq5/V6tqs4ZI0OGVSDCEt1uegZ3OOBEBUYuVw3Hhr9DQSbgVofFA==","shasum":"344513f8f843536cf99694964c09811277eee395","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000840.tgz","fileCount":745,"unpackedSize":1180484,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa+SYgCRA9TVsSAnZWagAAYU4P/3ZAv2uSkglipzkX3Jte\n3cwsSaKh9xyIYAFHXDCyVmDf+3jupYPsP7pBskc6ZhcWcXP6RsOLlhAdA+on\n9DAmyE2c5PMxwU6MVhwDoWmLqdqm8r7IXaQXrTfcLsGY5XgqN4sG3gCOd+/8\ns6Rhi1xpIvO0IKTm6LTuKK7ezsy+3lYSp0j3QIR78AjwY74TgUnZ0JhbA8TH\nlPzBQHIAWetc/8nKhw6DdgXZmPptEKzsMFIBAQcfOrPATZIah+JzpcNwbckW\ncm4oA7NIM+XkFJBCmVm0LJZBBih39IJ6zU4xw3+yaoDCiECztTfzKog2VIEt\n1NAmGJOukpJOavcfggdDXW7p4j6yCHZQIZW/C/ShXGgZaJxDRuXj+pSHLyPa\nS0l5eKAq3Ub2Up/Igtk5RKEsiMQfXF3tugh2jsW2WbzLPyvn8XpLFQNmxtY4\nQHzlEC0+ahwZhyHjhjCM2dGQjYltWLcBbQhwXyR+paQri2fICKwVA1M87q6m\nXlJWzriAhM6gST4Uc9hrRotgbuOMeT71td6QlMerm4VDVdxZBQ1TmyUynfH9\n52g2g+BnIT+bjCacgHvOUOcXwTyEBkMs1oxuJ1WuQP+gaFX6QSd5mwilYJVP\nO6+u08zH02PCxDX/uzB2t/vBnX8ScHLef49La6phdm40l60eeztsdM/luYH4\nDM5d\r\n=bsr1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHv3AMXbcLdu04O0/VCRh6C8K2lrNONrLCMysBawI7wEAiA3aWpOHml1ajmPOS610i7rd8vsjF0uCDfr6Mx0vFbohw=="}]}},"1.0.30000841":{"name":"caniuse-lite","version":"1.0.30000841","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000841","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-LeOGLEY4hl6xZc/xMYOrVmSrHOybyHWNShFN51qCmDXo69nEGKHTJTfe6jdWe4hLxSJcwEIYtKHFFh93fF/kNA==","shasum":"200079f853ca2839cb80852348d09a551f92f70a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000841.tgz","fileCount":745,"unpackedSize":1180559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa+8kjCRA9TVsSAnZWagAACYUP/2qskOXksXAh3xc873eL\nS9TROxRhkwMcpGq7BJOj1D9Z2Zar4ldoeS7anmb7qDvMW2FZ6wVmFDgm68ie\n0KkS9w7Rw/5M1kdW03CAd+v3eNtMvE3LzyA46DC5LV5nIuMA4iY5QAlAqGeN\nbzloSqLq5vtNuKKwHsKzzxVoeSjNjkZP5Ea9+GdnmqkicY9AQDkxgnHv5YMH\nqyP8CYoZ5wPVR+botCr8IRo819JpYPXkWI184pidjliHv+xnapv/rSmT3PCL\nwKHyGcU+a6b6aQA7xe5XHETfvQvaSvnALRynRtG3yn9BPzVhseZVNLSFFYHa\ngI/+RE9u9Mv3zlp5lRZ4cE9OWWYXXNPovabKbs13le2Z5qCbYD7rUUs1w8PU\nZyi1GB/aOIY+q+C67qw1rHJcHstXI9SzY4RBpteF1Yxc8lDhjxaa3fQCMyd9\nOOIQ8eGyDTl8YNkyPIXK0/yFKYEy4u/zDmSca0ZRzoArsgpM22f0iFiCHY2/\nOrrPkaIeFcs7PbiIWohDoeV/2/Uu/CVdOEEW7ehAbYcOl7Q9tZH2T/w3a9f4\nFj01Ofjpk+ZIAIy2X4E0lQkj2hfQ57ghYfRVctUrC7TUldf0z51cQZPt1t8P\nzrik6ZjuB1SDNUzMi1e/+rUVaolemcGUML2RfFH9Qr6VF0SrJm9BDJn3LAJV\nCGUF\r\n=jrO4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDg3Bxkd1faZ61xo8N4uJVekKa2f2EZ3EBpSPq35KoYCAIhAJRzwmiopkB/GPJpNZsqTMJ3NPLOl2ZZ9XPnsVgmGMhh"}]}},"1.0.30000842":{"name":"caniuse-lite","version":"1.0.30000842","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000842","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-juspQHLwQRgptEM03HN66SpM/ggZUB+m49NAgJIaIS11aXVNeRB57sEY1X6tEzeK2THGvYWKZZu1wIbh+W7YTA==","shasum":"7a198e3181a207f4b5749b8f5a1817685bf3d7df","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000842.tgz","fileCount":745,"unpackedSize":1180621,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa/Rs4CRA9TVsSAnZWagAAP18P/RRIQlIrcXzBCxyywqog\nUpZn/aWuf9v4a9y+M4EZUqLT1VsePcbUgi5u7ra3AJHanbmtX9964AJKPRUv\niOaKEWsheZma+piyHDsFuZieMXsJCd+X7H1dOCDD3DamvB3BE/PIWMPMKNDT\nDKr/5sOMxxTJmFmYWXKKsHgcB0ZNGGdF5+hJ6EDdVPSnCtaQVZWnm6n5GOru\nsob7zMg/ntDIA/V+k5er/ZwMTyO5u6jpB6uRr98aKC9vetGh+ILEpOcQ04aO\n+rqihqpxFRI0Gw+LeIU2ExZ902mP6U9xajEWAghtwoNbWzw+mzTa2u6WKiQd\nUNuWNKzctW+YvhV3Inwfptkj7Dutz73FMI8WISupqmQmMn43+SpY307Ah/gc\nT2XvtBs7U8VWOELygjveT5cgWklQ17oMb3oDO7iDb1SZp4ojWETIp3qNZ+xN\ndiqUPLsEMqK52wIbYzkfbI3TnFb3RyrwokWTIwpbjpvyS9YC4KkS1VtWreTj\nd8IjE+M760k2GxFo7NvrqMZ6K+4dPx5R56WkXkEbzNNU6wcDeWdKgiaN0AZ3\nzHwbd5SX2IMo4E8lkDAmRq5z3k0Z/jpd+KcvdCDthVkeTSqW1V5lyTV/pB0O\nxmmNnxKnTXPdf+G6plmxxRnRjvFC5DT5EUOiresp5Vj0kiiU9EAItqL4QdPV\nYrOF\r\n=R9cH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDah3Od6o3ureNWjdbOPU3wEoxYWCWYonz6nIz6Wi2DAAiBFFCddLod5WKV9gxqQUaFUmSb5LGCz/lnD7cQEiY6fGQ=="}]}},"1.0.30000843":{"name":"caniuse-lite","version":"1.0.30000843","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000843","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-1ntiW826MhRBmM0CeI7w1cQr16gxwOoM8doJWh3BFalPZoKWdZXs27Bc04xth/3NR1/wNXn9cpP4F92lVenCvg==","shasum":"4fdec258dc641c385744cdd49d23c5459c3d4411","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000843.tgz","fileCount":745,"unpackedSize":1181855,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa/no3CRA9TVsSAnZWagAABcUP/RwL6Qo//n50qEe8ZN4m\nsZJQ9zHDjuE8PEgH6j3AknbY+A9lJxl+l7tMmCV650/MHUFO94kmbbiHk8rR\nUTvD1BDPbhbDgNMoFzr4ce0xzue9Z/AKQEQ5bZD+UJapMWlrgHej+mphO+N4\nIa9Am/aE5ZF1503jfP0lnGuuWm/LsYlKcSNfEWRkE7N5hzAR8w043oaHs4gm\nQdusxvJ1GNorRSFxQ0DHlpiHt/dkNH1cSJfA866g4DJCq1iZObnIIow6YVt6\nLA4kIlVwoXSkc7DB9YDNzabr3fjfXeq3ZcSoyBECEjuQCivMZsNDIp4+wmUF\nHFOu3IRCAQeOiXXTLtbzmznAdFvKP49Olm4N3kuQDX1tAc94x3afyS3mOFio\ntZ+lAMxtWOiNgsg4X6BEQF37i5zWdPTATFggeI0+BS+YcMtNAVcSmd+YTLHm\nYNuWRDh+gxtQeLprHVnv9R2i6dyl6kkDZp8U97PbCiniIm6oiLpNTfQKWelB\n8W8xNbwDglCCRAK+q2ZcQsS+TyLGjswXe8YOJL1IFZfdGpPN0zqHDwqB1Gqt\nLIwC2WRCDCr7dTVFDgMwNFr202Ykto1UUB3dHNLAAHGlqmSufWkW/6P7THof\nSklCzLT7NeJsdixIWQTX2VLPNHnlmMMZKyO20d1hNDchLIF7aE+FHnw9jvDW\nVdnF\r\n=5822\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpHn2aJw5DbwfQ/GrY1gUmj9n5V3G4es68wtrdnK2QvAiB2pZlhf8Jalr1SAXCulzBOVDS40iz7SNjuj+5Wss7VHg=="}]}},"1.0.30000844":{"name":"caniuse-lite","version":"1.0.30000844","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000844","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-UpKQE7y6dLHhlv75UyBCRiun34Q+bmxyX3zS+ve9M07YG52tRafOvop9N9d5jC+sikKuG7UMweJKJNts4FVehA==","shasum":"de7c84cde0582143cf4f5abdf1b98e5a0539ad4a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000844.tgz","fileCount":745,"unpackedSize":1181935,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbAkSDCRA9TVsSAnZWagAAT/QQAJp6SpV58eXwEzP6LJXk\nf11vW++eHPlqqw3Zfj7PLCyWRR4HPHMEdFjkHJj8sQUCUSXGD/mUqIWbFRSW\noJ3IIHlJmYtGgNNoa/eZjSjbOma9lgrW/LCfGtZJ36FDmDqrbmi/Dn6qgWpn\nfJPYZcf2lBGJHPW2AbsjU+kZiiv8SorsbIBAgNA1ffV/V7cnpMOulgk2we68\nCYazCa2fhUzJoUGftvnUjQtuqw5qoN6liecjxj0Sz0UqDjYYcION4kO9TnLD\n60dQ6tGqMedbzHIsXZK+PTmoJ2S/mh9dXXiAv4Qk4bf3m+nCt3HZNnKfJTbC\nInDKzDmrBhU0SLWSvPGlQW4YBoHhCiNJZL2zBz0lgtNGpxBwluHCivx9259a\ntg8Xg0M3DkL/D/WVIC8eYkyQFxLfqDPk1OeY9wjlsoIpzrhfzlt8Aikx5z/W\n9+lfnglEhyuyALQIIuStxkWdcgd9QuolGqO7bO4TO17qe5TwxVJXB8QLqlxS\nxHlm2yuj4TUMnn4YbnR7zdLbCy0iikgL1fZByV7a0PMzcAGVjxlbrrSX2PyF\nA6WRqFfHc0EJmT5CoPaUD2DJ3QmXlyaHspVCvOzk8CaWcxxW6JVYrNL6gX+7\nx3ze0UqlNKKpgLG96Jqey4fMRrqPUcYIm4L0q7Z9ieJlOjwD7MH9Lr1YakZo\nwE8l\r\n=MtK+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEm1+XEDAJak+qKv8DWedBE+ovBx7iyUWMrw1KxrAD2tAiAYqjSv2Am86yDFeytOvQ0RU0c9YrIwUQHvWMdYbL4nfA=="}]}},"1.0.30000845":{"name":"caniuse-lite","version":"1.0.30000845","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000845","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-/jwfsl7otQW+e3xvPuoW3M7ZOBW43Y/p9OS9TteZs+zhLH2UbHEZRnfNFoqUsHNnyqw18c/UNAPfUikqyTcDdw==","shasum":"2df2d8d73c67476b5f8d05ca5771f87365581c5b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000845.tgz","fileCount":745,"unpackedSize":1182318,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbA7JxCRA9TVsSAnZWagAA7QQP/1mQHhjblKvWnUfOoz6s\nwMMoorfa4FYu4XbFUo1lGJfGSKpXjW/oXcZMwiXc8cWioQj/gEiOzAsJ8Oaz\nzt5e9i+VNCkldhnAbrimOjMPn2RHrdYUJKjle0qXvtUGacaCEenF4OmkWT7p\nRdGQ1ITxBj/Sf+nWISmc0PbYUwGM6uawqUzmAgbhjaThRAqG6MMoCeV6U9cS\nk3Q0UtHOv2bccIE8knbZPyJGQbrShnQLZmgNkj6Ix2S2cO7yvVbqcbCaDxOS\n1dH0Akz7Gj7gKptzgRkmoKDZSUVuFxO1dcQCCFkxFtKDuKksAGEY/wgLBsls\nvoZm+cznjoCFuLIAUaOzbGKzq+Gk0UQCfy1LFJzPtbz6fdF2TBh3CwvNgnm9\nwwsIpnfnOXcH+OUvEdxYuA9/cTcxzOyNpqtzNUmbdTS7k//xLYpObM9RQcoH\nkWDYb/071nEfw/FRMYZL34R7yGHwb5XpkZpd6l09qi97Nytbd4rCXAOgRg7a\nMdjpe7jAqQt7+6U5cWyLtyoV1Ic7mwmfFgpYu3yzfLBmAVBjv5LYsC1eDjHR\n3vmSrs2wCzmkvMjOOZMEBLSTT748VWZm6KxtyK33RnX5o+Sp/jztkZ5yK0BC\nC57SXq6QQNB46w8yFp/Q6SJIzaqE1PsQS4uAft37TpHgxFTzTPCT7jcTfENA\nEtDW\r\n=Ojl4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF/6vac9a+0qUGKa9vtx1tEDWk7i2mdvCgIET4fVFu/SAiEA4o8EIjcGLZd7PlvCacLd+ARChQ0xZHb+KLIWQY+0rV8="}]}},"1.0.30000846":{"name":"caniuse-lite","version":"1.0.30000846","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000846","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-qxUOHr5mTaadWH1ap0ueivHd8x42Bnemcn+JutVr7GWmm2bU4zoBhjuv5QdXgALQnnT626lOQros7cCDf8PwCg==","shasum":"2092911eecad71a89dae1faa62bcc202fde7f959","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000846.tgz","fileCount":745,"unpackedSize":1182504,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBmMxCRA9TVsSAnZWagAA5lkP/iGH0/b+bYWGT6pCdByK\nd1O8pqZfhOuXraIuhsDMT/Sde8fQ7Va3txAigCPESxBQZ83NpkFiJnqqDA3K\nIqg1CssCIwnezYu9TEDz49tDq9Ac6PQu+SPBQMLzHC4ngQVgQFs2Pcv2PV+G\nGD1ui8l0X08Ypk8yJ1kH2k9a5gH1JgoubZESpFDDajdCc214JWca+5vZ4jm6\nobhB7ev2z9gDsZp2E41f5nNPl0s8T+c0cXRk9dk+dnoEWe87DLnR4dSyXzrE\no7ixdY2dZ82DwkMPWeNlSgAnlwdOYpGxR7/K4SEwDU9AbxqanPACqcbtg93D\n11usGbEkH5KlQiZ7sRXwR1EP9qOJpjLqn2OwtZC8SUQvELkcPlikXR7RCVMf\nAR8l0kFjw6ZO7TUFWCI6nJjGWFGFQsugrv3e5zXq+8v8sYq6725ElW37Sdww\nz5V55ulKTU57FqQqRKm78HoCSdE69rAKEhaBmUYX7I/iSWPYMCeaXxTy7oHn\nJpCA/FOlq79ec2VHMqPJa/7EUKQ9G1MQkn6wjE4BODsg0z6yPZJRusf0A7Hm\nwOu+ulzn5sHQ4XS5wPDkfUOVULYX56TIuVjCPM6dWMjylc0zfjXi0GaThn7m\nTVScsxl07jlCtC7rjLDRgJW/avo5SmWnhQnxq3sEt4wpPVqkzJ01g7p7tJEY\n+E5Y\r\n=CbpH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWPVkUFOphRLTuVgpWI7d+gK05gcC2Ohvw6JeXvPYYXgIgQNT5n/6xWD4z1lL+jEuS58grejMMg98m+FrfBtTTlQg="}]}},"1.0.30000847":{"name":"caniuse-lite","version":"1.0.30000847","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000847","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-Weo+tRtVWcN2da782Ebx/27hFNEb+KP+uP6tdqAa+2S5bp1zOJhVH9tEpDygagrfvU4QjeuPwi/5VGsgT4SLaA==","shasum":"be77f439be29bbc57ae08004b1e470b653b1ec1d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000847.tgz","fileCount":746,"unpackedSize":1183465,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbD52vCRA9TVsSAnZWagAAJ2oP/3dbIqTgfYMdg5Bnbb6h\nvmO1CiT1NCCjdIHUDIyvdMw3F07kKxGs8NSdRbZ/Aqj5DbtxK42pxZhWEqHJ\nyYfXjadnXWby+ZmyOWwBIqgasv32e5FJnNZgzW7bwC6DZzTs4o5pHzUWI5K1\nY/Pv7vbFDbwgowCIDQwDaqq0gKucgb7aXQfTAhsVz2YhFfqDJ5nq/Atwb+pL\nnnNxGl8FFItPNpfWsZoHviKp1BO3HADN+UyIGcE7aL5oMFURsr0YzCOnHS4V\n8M83EU2K8d2VqOxvyOO8shJEH7EUWyg+bap/zplZB/tbXyOm8KMpPwuoZwNF\nChX/0/171C+zbTc1x9159Mnw4MBOE6qQs1O4ZhcCLZqlfJ4lwktbPyKncGVA\nCrmV4Te6stQ6ZapQDAgujpjpMLobXj2lLuSxYo4tttvrRVKPTrmimvJY+Knx\nHWAwlCG22Ke0kQ9exZuPZECyWYVGlvUm8kJy7YsM+hWfYhW734K0xM0Y8tsS\nyfxn0+N+kWuVdZ9yqgPIyQt5e9TOq1uO/D07D26gonfmdi7juNyy4f0/W3dg\nM2eo31BjIw0lSOIUvBIA7pwShLrMV3AJX7V7UCIffsliJVDzKde+L/A7K+Vv\nVDaYXMWRWZwNo9pD6sFwnwnhisXcNTuXRoFw3QYTYuvaaEHAzd+HDqUbqU91\nW76l\r\n=nyPd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQnHmIucbBc5wcCMopEyzO4loWgG0aHl831tUWJPHPggIgDBB60QULLYFjts4Exwfs7lVSh0KZiHVks5e1DPdvCRQ="}]}},"1.0.30000848":{"name":"caniuse-lite","version":"1.0.30000848","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000848","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-9Hu5LvDZ+vTqHNDQXJpceg3YJZI2YFx+OuNDwLauoswT6dycZcSZ9NZIO3MJSLswRpR3HL1Pqitz0r6H6IdoCA==","shasum":"ec9c0a72ec8f9ef812e4f4b8628625af9c85ade0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000848.tgz","fileCount":746,"unpackedSize":1190265,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbFVQ3CRA9TVsSAnZWagAA3b8QAJO6YVr5a0DODMrJP0bG\nERNOm9XK5Y+Y2tYn5mXJ4RKGunjdOeYTm292c+VnfTvR0EuYhyo07zB1aa+E\nfoiWoBjmeOfYkl1I4Z1yLfg210vH5sLea1/DyYnRtu/6xiFudNihw44J45Rd\nWoA5DeNgpvhhniFqItKHXqcfb1vd7yysa5jipYxZTgwi/9JK3tHKqXQJ0tK3\nCbgSh87Cfj4m1LPPOXsImACSa85k2D0VghsDoNXUa0yBoiRUBFHXRQiiECPd\naoMgksQco0Q5TCJKgWQEkRvdT41ZlK3TRD3aitNXQkQjMtPXconrlMgAABlB\nejpEAG+QZQoMfLKZ7E6jzut1S/IJZcjAuVBcTA9mMPIocOl3muSb1NnbDdT5\nCz99Y79F+xd/GJ9M+XghC8chj66XevvZXQWToIdNrmyrWAMDvhHXGIGH+aRd\n7WU25b+IvQsuBbXVnv46oeyNJBAc02pGIL/DW8p05WKIlKLdIFmy5Kd2ioq+\nOmBNUuR1kJDpcy1DaILJFguA/YhRH1mgVIy7+bvsDzym8fXRzUBdel/o5T4z\nKtOz7RvuocZ1b8X8ZlMRF0kTF40IE/iT8TT20ztDuEC3tXlSBMb1v7VHbsev\n+swrYpiDAunnsxbj0ovk5AjQvR0Gh1SI0pEB28CYhoetAPQa/0E/+rT/4TGP\nhDkm\r\n=s7Da\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2tzrY/LLMsxTtaqnBbYXwTSjmt0ZDwx79FLNFswSBWgIgED110e0rSCU/QhkoHe5J6he8zobGwxihkr18TOmBzcA="}]}},"1.0.30000849":{"name":"caniuse-lite","version":"1.0.30000849","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000849","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-hlkWpyGJTDjjim2m+nvvHiEqt2PZuPdB9yYRbys5P/T179Aq7YgMF6tnM489voTfqMLtJhqmOZNfghxWjjT8jg==","shasum":"7e1aa48e6d58917dcd70aabf7e7a33514a258f91","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000849.tgz","fileCount":746,"unpackedSize":1190345,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbFjUtCRA9TVsSAnZWagAAOX0QAKRbGRy12vQ/q/lnsMSs\n4zfIMkhUs9z0GOE0KS+2J3ZLuab3QFkAB/1rhvaMw5Xxfq0mbb0BUVK+J7gi\nAzHWme86kWXoMYjBI+yh10QeYNKeN2eNYG5Tkta6jdq0LBqviHeX9SNDusFt\ndnvgS39MoIb3bTNQycK4PR1Znnm4n/m3K/j67eO056lX0B5kWXmj3vZe8z37\ncLefxomZZp64j4+qr3vVCjedoAZO0euffFJF1JXh+erEE4ap8F35g9FEXYbk\ndzu+Ggw05rQzEVFDUH0DC03zwGQQ1avcgl2nYXRzxIJ+lponSovk9QZDVuDr\nQ/f55mrb4BbiF/zBLfW8H4b45+vP1OyB8NvNgQojSUTzjQsO8KTpaMNKMuiU\nv7ej/C3LRSdD64+U7o+yIHS8rAQgTGNe/daCxwBAmqHUutIEa9aOGTbdNn/C\nmuRoRqtzTkayKaxHKUAzLRQ25/KHaMjiFs/9S38DOh+IzPXzLmaolNfUomk6\n8CBpdX9LUyeIpRg3jlmYuC3AqtVnO8AiHykKdN0m9tGIWLWjIX3o5PbNvyA1\nCwGUEalU3Z2sChvqMjSyUyDAVLIs7onflTOBRvB4sqj+ha+28vSNVXgANSNR\n9A7mD76Ih+wUAM4hxJpveIjC37F/1kpqfwcWdC71ik/hFvVMvNwPce0GJpLs\nrfz9\r\n=CdRR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJuz9soHO7Vrx1UtDuiwQFIOBJ7t6ePMR8r+a3KPVApQIget6j8DqTJWeOpfNfdRHyYRBbRyeeYGwsJXAQF3oRJ/c="}]}},"1.0.30000850":{"name":"caniuse-lite","version":"1.0.30000850","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000850","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-iHK48UR/InydhpPAzgSmsJXRAR925T0kwJhZ1wk0xRatpGMvi2f06LABg6HXfV4WW4P2wChzlcFa/TEmbTyXQA==","shasum":"e68a88db4ea598b4c33b8419f7385473e4802495","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000850.tgz","fileCount":746,"unpackedSize":1191387,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbGNg0CRA9TVsSAnZWagAAHkgQAJcmwFXtQ8+9GN38rSoe\nDn/5EsmuZzzQwtVw1QXuImQ8sNtYhGeDOcyOhn7HV0iC2Fa/1HZZGLXxYo+9\nFBEYC/Qak8oM9nC9KvRnpXIqvoHKS/0ES/nV0+f4/AiJQEizj2N1S9rYlA+5\naWshZ4RE3fs5x9Q4Td4aaIiB3vtmjZHj5o0UZB/vqupdjRPdjS/XQ3Oa6Fgw\nTyHKaZS3oGiv1/pSiY5K/vSzYsJN7z9vYH0y4bnjHl0JIeknIa4/ciOVb1qu\naS8mMN74grjbEU17LaQk+e+f/fNaH/nXfrti1DvgvsLBBXa4xaVX3S/uOANC\nIvDy+BBxd0JmyY3+Gdwp/wir1eRWlY1IMn7F5sxYBh1vVbwqkqEH8DkonhRt\npxwD3fCKGC7sdwLlVTpMZD5kdjPFmbKQXHNn5xk09PLJYsFvZrEOzLkyToar\n7n5k+Ub3+CfBWAcwTM3BDJG6bv990R3a5x5G0AaCmeU9wfcXw8Jgtt6wwBcJ\n/mveBAwmlZbzDUkrXv1guCXKBiLluAQ/FKCKvr+OaiF833q6lceniBTjuvOS\nlHY5D5ibVYPNh9VwkigMbMfUC4kfFIv0uvZ68hWPJW8uT55CG/52ufhm3IAU\nwhM6hgdh1Z6/kPwyFIHMIrD+L7OzwSQYwLGqYIF4+6yZwvSvTPLQTm3gqxoV\nPPng\r\n=L5CZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDsEsFXSGFohqHx4w4AySyChxvAmrq+bSe+wrkyCJl/UwIgEICQEX0p6GTWNLc1/5Ps5nbRWm/xzDxRhjdOOTc8WUs="}]}},"1.0.30000851":{"name":"caniuse-lite","version":"1.0.30000851","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000851","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-Y1ecA1cL9wg0vni8t33nBw/poX8ypm+2c3fbwAESj8cm4ufK9CBFQ1+nUK8Dp5dtFo5Fc3JzkI5DKmQbuIo6hQ==","shasum":"3b498aebf9f92cf6cff4ab54d13b557c0b590533","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000851.tgz","fileCount":746,"unpackedSize":1191449,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbGhubCRA9TVsSAnZWagAAHKoP/3WaQehUJuCA0Bj8W5R8\nb4MIzvj5NrDOaJSN35IoLRfRY7bOKy6JYDVvMl5r2ISd7oUi44+DBBp9G3qH\naVjAxb0Lg0vcHPOD2o7ey2jqFrTl/UPQr3uvTgrmMqLo6bNyZ7xbadAJZM3j\n+J1ZlnsyqtDA7TWwIN9WpiFjBYkLzoGF1dJ1oUbglBELavqgw5u7FW3Jl1gh\nSckUH/sfvNMaxrwQGqXKyswDinFYZSm1a2TfuoMSHjpN81I2NESkii02kkCH\nSHT7nPaDzzszUixzKqQOluBTQqmVr3oJ59dn1GyKpBMzxp+clswZy9wieQzQ\npOw9JqpkB+QRHD4w3JG169j155wMg1hx/7SyTjSRWIvfilRevArhMpUQhHtw\njbHbUSBjY3yfaL28beIDsCcV63YtwhF3EwS/sj9SJ+8Hg9ktz0Foyka8/68/\nCb48uaxyrWATqoNjiXPqDGuTva/sGrbRoVtbfepP/XpoxfTJ77/8sGgH698K\nFpNzqSezVHiJNKkY3q2XiUGoZ+uG9d2hE1Am8pZp/pkVDU3fzS7qNSvtevQL\nqiyVFOtBlQgUK/xDmhSwqjUHDjQgqPil3U/k/+jac2UHyRhly5W44SFpNv7r\nDnTFQEYrMKp5ow210de9RwJ2kTU/o2K0on/+cX51x0ISDBT/EXCAmzA6O5Lq\nem7l\r\n=+U7g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSyHR7Kx6kSq3jaIKHA9ApxQBOayAs0xGT2XAOCsXKLAIgLxHtdvUpqxYPdIf3SL11ar2xvLVVOpN+GGg836hNhds="}]}},"1.0.30000852":{"name":"caniuse-lite","version":"1.0.30000852","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000852","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-NOuitABlrRbIpjtC8HdDnHL9Fi+yH5phDoXlXT7Im++48kll2bUps9dWWdAnBwqT/oEsjobuOLnnJCBjVqadCw==","shasum":"8b7510cec030cac7842e52beca2bf292af65f935","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000852.tgz","fileCount":747,"unpackedSize":1192391,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbH2+qCRA9TVsSAnZWagAAvGMP/1on8YmXo3dJao+XACXQ\neBdmeJAOa1/PGVrGwkH+GJ6AeEoQLYwQxw3ib2N6A7zOeFjZylC4S+SK6wMo\np78ik0AQirZkL2Lq1aSiIVwRkhl6QZWC0EJUvsw1hY/Z+427CmiQYTJT8MIO\noscljpf6M/NfhIYVgS2NN6MZkZaVCHtoDtVIT2SWK2Kl087sHRdx/uwk3jnT\nnMT1vCswSH0woLkIuYG8f24cujzTlQOuF+zD8bpabLGPmw5amKArnFa8xOvZ\n1GNpshjSCE9DLTSNNrj56mAACAkrlsq9LS5KCl4G2mJFwOOcpyw20vrbODMs\nKoQcsMOVWxkpUF+6t+1pPbVnj94WV9tFLFeBKNSuWKQ/VQcUNUD/Tm8o5Upy\nJWJw8n/b+WmQhms56mJQb7ihgd3Cqhcq9qeIXGQs4ZClfBQyV4s3o7o8R77J\nvXRDb/GFjGJu5grYNnZqgUV/YlgakcjAPzvJ81Rz8MoiZuDbTtcxw2PMfV8B\nrwoHDCIbsD5c4afsqnyqoovx5huqmyRrvb5PeRxHk09Q5HipFM60epYbi7Y3\nKYGLpAvdk+qjrf244md0o84YMIcbMbrhJIA05ZNc7Rg/Rtks1fjRjufnuAQc\nCMRQZ2CRl8wg+IsbhZAQjFtq9qXjC57mdCv1LXAbXlRca+odRTCunJ8c1YHI\nycmE\r\n=ZLap\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD6cwpF/XrvKPlBrrhSEi2xUWbqXQ6FXFeysbNcddDVVgIhAPsN3UyIxvGWfDzoGZO7K+9cpXncYK3YMgVhT+YRMgH8"}]}},"1.0.30000853":{"name":"caniuse-lite","version":"1.0.30000853","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000853","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-vMrE8BED4MJC9IhDJKP8ok6bJUfn5+YHvxwXMYfiPqQOJ3r2B9ihcArlUnXu6yPWf7b3jHqiEBwXZEbrbiFUqg==","shasum":"505249fc78d60e20ad47af3c13706d6f9fd209fd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000853.tgz","fileCount":748,"unpackedSize":1193291,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbIME0CRA9TVsSAnZWagAA4SAP/12c1oFTUgS7/n546uJd\n+TnJChn1Cte6Mi/vAOgrbWMbEj6xr2ye6uh/hOr5J1/P7nqVDc9VzBiZoqpE\nSE4ZM9Kf5YgGWDL+NHdtpdlAbW3H2p27XT1/rSj4oQQA9CU8JiSbyH+3BYSR\nC5I/7q5ZAKwN7ycSyc/drtjAg0YO2jQnqtq+ffWeusOQUXo0Ugnh1KrcrJfx\nybqyUovXbcVcUpWRNbAtbHok6cez14x9ktYSo3OpTBk8unBLfWheVOjgDOp0\nsskuC1qaAh0FXDyouwfIbYYZowlp0BtYLYMcIzdjZ7vQ3hZ7aESKUunXzuUX\nbYBmiyJStkHSSy5Gkn/lZtgjfnQZrPEuaEtSbnk47MiA210oszi/kjs7GlJ/\nRC7hc5p5eJowfSxycVHC4TD+7BvWRGAR9cg00+aPNYEmLfDSSufBP2HWTaAS\n2wmpqskmtu/hsTa8zaowtzVzw2dvNyANYreATp4wcuTFi8M9q+51ev69gyaw\ndmQNIrEKy9Ac+5eIhFeCBYYIGeQBomVlbQnqqpT+QcpBqkWsqIFqreORCkru\n6B853DXxMk8RYJlI9Pv+sTanwCUfH2D6e20AToHe8amg3Pqi/ujavS/28pgI\n4fwnIIFc3y8ThGCtNjQIVPAzDRXav2utB+4zTkOaIqENYLWPtDZTiEO7mg+O\nvabX\r\n=ploc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFI+G9bmGP9uJWMg2sq9k0nvip2qymECQJ+cTyur9d0jAiAnjwLe9L2FFc/a0SXj1hDJWH2h1zJ0rqS2X8GuxPD3YQ=="}]}},"1.0.30000854":{"name":"caniuse-lite","version":"1.0.30000854","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000854","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-6PRMSV9FQWXl1mCEaeaj125y6TNnqQUtWvR2fpC8fJwSKkeaJ2YXkPg7HiZm4ANoLRFCIW4a8Vz4urKm48LqTg==","shasum":"3a692706a6d9a591418dbc612d61cc412ec5989b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000854.tgz","fileCount":749,"unpackedSize":1194238,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbIfaOCRA9TVsSAnZWagAAv1UP/1M68vSr1mqhHWr8i2AL\ne3sA0lV+S8f169iBhuGATFJOFmouMhX4tOy9Zl6NShXYLeAGJgf9oVUkCk6f\nW/oFVheKURCPeq8vHPVQ+yj0OiLni30yrXhSpByEbROGmx3PXmZ9Y8wvUruK\nMQBWqAqBTzraJXKL9bb/XBaA2mjqxdtn/M6/ZxAmnBZxJrGOAqR1AQz2KOsL\nFqSj2WKpLI3RYbxXEG8iBDhLAbGOJRiEKKdha2a6nGME1e4w4ag3MJi0yMOK\n0JFwOHGYVATlIZ+v9E/6TUGOe93wJsCrBdIbN3ys9kzLTQj7AVira6yvxDbv\nB6+PANHYUTL40EER3bXI1/zgGGdGHiC4LMmVa9cZ907GExH+mMIUE+2kaZfg\nEZ3uD8gvH5/ZhoopCBYEaRY6Vy/EY8TKKINo1hYK13+wasbyD2IhMI71UlGp\nDhr6G0fQt8t21UcChEue6e2eSQbQmuq29fKKAcqHyOHxq0zp0fNbcycyJxhl\n0EmGbR3TU2bpnKtpjHSt3DGNJxf388Fvm204e+svw1bmpCYlC2f3tmXDJTjg\n8BKH/Ia4/VvGCTZwP0vqZUf++YssDodV6qbjHGeciOzKt9BPV1AALVY2OIWQ\ng3FzJ/4tFtOMJW6brbeG8jXaHOpRce1vHqhXiCB8TFoytZzWGSs9x7txZGKD\nNgQG\r\n=6pyd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAEPCeRuaY6IMeANMmIwK8PkYEpMCFhGfZ563g69LH8mAiEA5zqdentTa2ubeaXmmEpZ2CQQ8Ux+BATvJc98b4kWdD0="}]}},"1.0.30000855":{"name":"caniuse-lite","version":"1.0.30000855","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000855","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-ajORrkXa5UYk62P5PK6ZmBraYOAOr9HWy+XxLwjDg8Ys/5KiSyarg8tIA32ZVqbFhtz67wyySXnU9imkh2ZT2w==","shasum":"d5a26a9093b932d6266bf4ed9294b41b84945d14","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000855.tgz","fileCount":749,"unpackedSize":1194309,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbIgSeCRA9TVsSAnZWagAARbsQAKTwFfpAgs9ThRgLbzZ+\nUjQ9LH8QBZQXdbaDpwZNIONBGmzhsKw2FqRKjGeDn1poqkJ+6taQ9+sjJ84A\n1gZMFu6Wq1SoibyX/e/Dvi+dQW9d2Z74k0U+wKPsP971dju3LT9S+niILXBI\nScfXEleB77jaNupWrk0yjURpSCQBTl+XbKAoicqFPu+TJ1lg5+Af/Ed3xbGt\nrR3kgkO/rJG9I4FeMG7Wu1MC6ylPHE8T9co7tB0169N4UCFyH1B0rZ6qZr/j\nR03x9ny8kTZ3o/RZw9zE3LY8w6iYROnf0lcEAUq8eg6vKxwMfOU+qd6c2oUF\nv7FRYM1KQLRq4XbkFnju1+Fd35QLlkeCsmbIxRafgXJbPA5p66FNYauKNpjG\nkF7s3UN6iouRyjCUCwzCaDnw1heMQiMCJS4IMZsoeTtKuGhjQX6au7ODyplJ\n11VVnSrxuDXwXDmfO6k7bGNp6qDEa26qxk0ZltRdtlJ+eHcQ9cfIiQB6FFrv\n/T3wLCKuXIjRqF8tLUUK0CcvRPNub+BPbMGl3iVFEuK5hPuNne1ftzkk/YKZ\ng9GyJyDZRwxzU6rfBOv6B8xCOOBXNfHZOsRkxqDkA3ZedvWcV0CKIM/Sf+hj\nrp+mp5o7sv++5w9ZeKX3QxnlZ55ZyGhAXG4cvtItUrXrYdcFAsw1MUa9KZpZ\nC6zL\r\n=j8AY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDY1lWBU3rLwIVxChB4ExZnUZy4LQ1qnQcExBnNMruJqAIhAMEUodBF5zrAjZLvxfbG3IbSgV9y2N3ocdbg444m/i9t"}]}},"1.0.30000856":{"name":"caniuse-lite","version":"1.0.30000856","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000856","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-x3mYcApHMQemyaHuH/RyqtKCGIYTgEA63fdi+VBvDz8xUSmRiVWTLeyKcoGQCGG6UPR9/+4qG4OKrTa6aSQRKg==","shasum":"ecc16978135a6f219b138991eb62009d25ee8daa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000856.tgz","fileCount":749,"unpackedSize":1194426,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbI1YnCRA9TVsSAnZWagAAB9wP/RF6oaZp2TioBzNFkO0l\nPFfO8Gh0V0HBsMuuIaRX75YN/f6GrAG7/QxKwvsDKhMf/1Mlys7q9bAtNnP8\nI3+/7+ECgyN3IwXUKqR+EzzoSx4WrI3WlH9Wn0bQWyweUcCCSJkokeuWZ+YN\n4e3yeTmZcpgCAaeNA8cWYFxYV8eH+yAWnwbm78WAGD1kQQvmq29Fn10W0P7i\n8NKTmshGbx/SaIjvZ/Xx5TGwrtT/ZUifO5Ndsmj9SDlw7xSNovHU7+ycsu4P\nAPIFGhv68VXD1AOHmk+Q0Mf+6zmPYvxOcpEaO+05nkZkrc5/j5BDyHQ/VYBH\n/1cyqS64SVfCgdWeZPhjShuwfvS+mvohXWztTar5ZPL46UTCZF2e+yiQkbC+\nz3TZw+QqI+vyIVRp6P226hJDhtTmTqINf2AMSr2bg3dUawhmhsViGKs/zhow\neFr07Ng1LLUkuhkbWy7p0wemBU2nZjpo1EqDEPDl2jtiOxzfvlk+UhwCRnA2\n5pEA51vuKOnmdeRKwviqiRqysO5kXml3URUdWtVh8Ci/6LiaYz4c4MPz5LTp\ngUhVIj3WHudcheb1tZXC0RKgtQWKRXTEw7SSmSMZRLuw94Ykl213Bj3U+WnL\n2Re5npeO3u71gcJi1+XapApsCGYybIt5kx+kHhYlgnGb+s2tHsBbF/D49Zz6\ntR1u\r\n=xh3W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGzVHIYxvRU1QrkpDSMGpF1bI3n4nNPvhqJqrtbfGLFyAiBoWYBCcJCx18QrnWD8N6hjcz6s2E3PMc9kEN1+l7n8TA=="}]}},"1.0.30000857":{"name":"caniuse-lite","version":"1.0.30000857","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000857","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-+GgZ+gQMARhUSnNfF5KrTb3ricJ9T1GebQBp6yfOyTPn0DSwiSz3GBfLri/l3mmPkNymRvg7idZuLmR7OTCq/Q==","shasum":"4b7bc9262a18abbcfef3e0790e120254bfe25cb1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000857.tgz","fileCount":749,"unpackedSize":1196129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbLtEzCRA9TVsSAnZWagAAbPUP/RR4mcwvcX/U59ewbihy\nvQjOpcxufBADIpvUo+uAaU9rHU1xVqbO0E4i5gr8HSHSlxSfT/gjlgELbkad\npcMsm4hvobuEWnrxMR4PFPV70im3Ca3fWvqCBH7KgfZ5P1LXcG0cBGINfZGo\na0AMiR8QPmcCTyoSoEAheDAlji3b6uTbaUUwVy20yp5BirGn5D4lyOQwtZQc\nrhIzyhGDlmr4h8j1amivqEphVIEYIwQwYFUv2x3rHV/m8I9gajsWofjJWVW+\njvAzHIpd4xSx5LtAmskJ5b2ra4lEf//kugGYJuwCr1OpYOEyyMXZLL0GG47a\nxnE1qqTr9136ri/uXNcOb1AWtO42uoqqs/OEj9aQduZ5zbyK0iFSccU3yJ5Q\nTMaHMoiHAJTRPbm55XScjKDCsNxMYJbwgimVji5KkH0cizngVi8mplED2jMQ\nX3miOFys7bHKSj30ov2DZZWwW9vgTbmd4xJvKGzyrIQ/87J0XnXkTUqELD11\nod0NEyWtzI4N1cKrhVC8hhMO9wyWV7RuMjQFCkOUW/5ObwNdetH5ExVYNNYs\nYG4UmUKAIeqcZjoz8IDLnhREf2+ZN4q7hYrrIy8eNBkyV7pFjwpGD5KTPhiz\nECRXtlSxCZfHYyopqMp+WSuir2e0KjQh9kmRN8FlSgSl63tlySOkNWXbDMYr\nNggm\r\n=mep1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcUIePr9R74lkfaHeYTHFcA4AacVYlhMsLQKLIQF26hgIhAMkCb6Nos1admGoXVp1NcmzITmH9Lha0DEaxePNut7WU"}]}},"1.0.30000858":{"name":"caniuse-lite","version":"1.0.30000858","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000858","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-oJRGfVfwHr0VKcoy2UqIoRmQcDOugnNAQsWYI3/JTzExrlzxSKtmLW1N4h+gmjgpYCEJthHmaIjok894H5il/g==","shasum":"f6f203a9128bac507136de1cf6cfd966d2df027c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000858.tgz","fileCount":749,"unpackedSize":1197767,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbLt9GCRA9TVsSAnZWagAASSoP/29GpzA61fOR6oACvou1\n0KE9L9O9MP0ZyYWR8r6uvTUxxK4SW1lsbQROuZeEDbgcgRCpq3Ho/TbiMZpl\naron7oMPYHWJX8HpX9vQ+7B8YG/tD+ATBcQd02+fe5kTG+nhhJyUIA+cS96J\nZV9C8ybJCMW3UtLGMBQfkDGh81KVSSuTSKUZI3N3fUMLSH4o07Y7XhnzaoJn\nLz99ikpVLh4Z98ol3o4O1oR0h8Go055OUmSVtWmNZkrzMBbcVQ5IU17BKaPL\nHKaZVznUdQoLIhWpCygBW9lSqiC+rYrNaP/5rBwsEHivm/ePpQPOrDfO2dhE\nQYNd4oL4bGaK61zpCe++Afsks9mvV4p+t5P3/jRlMhvIMioEDZ1pkmjfWzuM\n7KxJuY9t+n/R+DNF97USRwZihfe84pYFH5+0rWhzDdWhgGN8J0Y+m6aq05Vy\nR3102V+NvsGyBdi15Hcc56mHp96gSXx9HZzJzPyWkxH4aVaJNX+yBPVm/M2n\ni/OKz6/MeI4NDdEF7EObEnzXOwY77wcaFnzl52SAenhZH0kB68zKaCG2Nhge\nMG1uIrYjOt+16cSZUjj+2tSmgQnMDjPJ77y1wrL7XiuLbfawcg67k+UR2GiE\nOCrHTDmsXnGXr27az4VdgveMRAvTixDtCi6JW3wWP7SqhkGfXxom+84umSrn\nGQz0\r\n=YTZE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTQ8kbRrPAJ3GmtUTLRulhCBf8nO3cqpyh3WVNfDOwFQIgH0+plDox3UG07he6OZP+O5S3V5n7I+D7JSQ9DR9CYoM="}]}},"1.0.30000859":{"name":"caniuse-lite","version":"1.0.30000859","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000859","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-BucSdVZocKyKAdThos0fx7Ds941M1jddFazv7U3stFqxyWOc2JrxVn87Qo02DzP9Txb4lw9jIQddh9IT4WA3dQ==","shasum":"da974adc5348fffe94724877a7ef8cb5d6d3d777","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000859.tgz","fileCount":749,"unpackedSize":1197865,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbMdaeCRA9TVsSAnZWagAACcoP/3P1MGC2POAHjW8E3jdM\n8H2pdLhEdL6mJe435X6X0+1jt9OZI1ewJic0z0jwN6ac5ydSkJeGBX92HrDq\n6cwY+o/QifmkHPm8sU8LOf/D6RE4gic6UW22nFdWP6/Ely/L3H1nd2VmA7+S\nB8JFb9gqIKnOQgkXIrVDZyGhoRqHpS5FxGPQYXydA6Ap4oahuKnT3/PC84qm\nxozaG6Gta9Icd2ti+iwF3D222ITOEDD58vyK3liajhNBZ1vZZg9TpnUiVTMT\nRkEnPAFWfpT5RHVt+Lik5RecDVvtmTuVEqailfpKnlmOu4fELbcMUMGt36VM\nextX6fJZwwKGEj5IIR1TM5mZHlhxKvaRxqjnE7sXR7J4lF+5P6OcZu9aON+Y\nmo9vnwXx4fwkR9u3JgE77xZ/d/7VhvaSmX0KtO8FKCnMvlSC1uBZOmkqk5mv\nv7U8Acx9d3FYmRqkvMth6ddLRW2WWwu0A62uzTvM5/jYcILJ9QPeHN1luZNo\nsQDs1rHebpEnxZFsW2P0dJpdRiT2hF7DK3MFc7c645ILlSfBPyAAyQU8xb39\nsrBChmUufj0QNH4vyGoeypsbuhS2X1cLPax5d1WXzsNuh/fmmbQ34w9rBdoX\nMvZRGgqHTzACWAeQy1Tlfu8I20p0FMSPdYa+j2L1h/5F4PHIs4hnnJnzCTLk\ncOfr\r\n=hxXm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQSX5EU059gSgYh1au8jAgxkR3AIVTSZj6BJ+s1cFIWwIhAM0aXqsFl2TP/Pqx1OGowzpae0wB4tuAEU1WCbgeIORQ"}]}},"1.0.30000860":{"name":"caniuse-lite","version":"1.0.30000860","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000860","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-6HCqcu+cCwWCY+WLL+rtAsAFt1ufvqMhA8dTfhMQhCJHYhJDhRRrh105DfjqRlTrDK3vvbEq8K0drNsJbymDtQ==","shasum":"c902e3df3cc4303f631abc7a1579a3ce0a6153a3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000860.tgz","fileCount":749,"unpackedSize":1197928,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNHmhCRA9TVsSAnZWagAAgw0P/1Ko9Sedo4s0u6bzp5rb\nRenaa6ciS05FMf9V6SNHLYL4Y2Lc93MmNp+GSwsRUpoXInPLBK3yOQYL5Wbr\nxdyUXcnWsysUAu51K+xpYYnH9eINXF4dnbCN0wZw4O0uilqu/5as/gnweSSE\nxPjScFAYMll1z9sU5/HFT5MZwApJr1gDZaypJwFWbOjvnnqpMRxdiCGd7FgN\nkNfrYIqn/dcmA4yWkWKP0bUKBIMRaRmpJeUQGpbElgzRTTp60+1IZrZ38QMS\nzfvTMDLKbfT+W9wznOA3foaYWvsscZI6V6E4gb1egg8EP+gn1S2r1gumrdjQ\nAJgRsfKd7XQcbLYna2ZOgHsg50wx4NDgGgBsxjjSf/drszhyxwFKSnz2oaHX\nIIYwykVw2uNWjo7xPBFA5ceUgIeyrFFy6KyLMxHXu46Cm083aGr2L9lnqyDb\nCJsgTRWJAWjplW6oVWWGw+nZYp4+ww8jEgOP3gFn2OSw1yE6OoLc6Ui1XPSa\nGBzCBZVNSAfKcgjkMH18sHTDDi1wAmqvu9lj5GF5JLjqWsnw7XR+zuqRJ01V\nPSyTal0par3hi/Aqu1DX+Y7327SUsohrzrOw7YIGaxZHqRGjzNRtco+I6My2\n95pUx2xeCI+yVVFJ3Tjn4KTYI5vQiLMD2s2bi0WdlS0ucl0ppxDKtoQct/Yw\nmRoO\r\n=MDuA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCYIhHKN5VW1/2sP0i9ibb477kLVA83qRODz1wnmdEx5QIgei/VhRHl4dP7RIHNk/7IIAdk0hju35N6TAc+ALJAtB4="}]}},"1.0.30000861":{"name":"caniuse-lite","version":"1.0.30000861","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000861","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-aeEQ4kyd41qCl8XFbCjWgVBI3EOd66M9sC43MFn0kuD/vcrNqvoIAlKon4xdp8yMCYvVjdCltI3lgArj8I6cNA==","shasum":"a32bb9607c34e4639b497ff37de746fc8a160410","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000861.tgz","fileCount":749,"unpackedSize":1197994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNb0NCRA9TVsSAnZWagAAzZgP/1vTYERthWkWnVUs2run\nUluE2fgCOJPDSxSdEOlNfqHPyyYubN13uCmLBPEormjlhK+JQbbY7QZvF5Zt\nXibPyyd2xBaQfFX1odi+KcgTix0M3tYtKsQmibaDX4TkCsiSfSL1AgC8bgwG\n4501FKqNvmwu3U2FoEN4/A0YeV8jsjtMg/4gMP0rU6Na2FbJCjW09ZoyK1nC\nUJ4gfOxvhth0bJXoHr3ohRimDd6md+Xr1lHzmiDAHCJEKo1b1bDEjpTPoIAN\n2uReMYO7Aqk3+zxsJzdmn/dcvZFVDqikqaTVzJHv2nqRd5zkd2tSYuQjKEHw\ndy9us3aLfWVjIU0GzoZ2O7RlVgmib1rmmYyUr9cVIs+1MwESOT26ZrKnqwZM\n1ZqxTM0loRz740/jcMDj3QNueAcksaXD0ksCmZ0GKUbW34TYgZRyf86zS0JS\nNuSjMPVWGhL/Q/1ZmPvQYcO7SXg8UMlhiQneCCo3bShDVua9FRlQIh3dj67Q\n2ofvm0K7KMtavPbGAYyZCUhgRY41qoRrdwIhe5JgWHR7Ij2sZ617KX/4eCtp\nw/+oAC1PNtKWFlyajoJ4BRu+22a7gDAjKns3PHtmEHPsMktH1KiMZzjQ650/\ni9LSYFVJXFByRKYvvZG9wwY1L0K4xzTR0KH3tuMhjrP5VMZPTdIfhstSXd2v\nmELm\r\n=h+pQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDRYDJVhm0tKb+sVtx6j0Od+QtgTnXCFkDsDzI8fWkzzgIgWIYFSzJxNO5MW+RJMZDynA+Bt2MX7gM3Hsbf2Op5/HU="}]}},"1.0.30000862":{"name":"caniuse-lite","version":"1.0.30000862","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000862","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-e9DBeH0Oby7EbUQN3DRWKxgbpEJO3KAZUhP0xDmPA23Qr6PmvXI7Ojy8ZthsOsz+1iSoaV9G7eWJXUOyryJ6NA==","shasum":"7ca14f5079fa8f77ac814fca92d45deb4b7eff9d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000862.tgz","fileCount":749,"unpackedSize":1198053,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbOxEhCRA9TVsSAnZWagAAizwP/0KnxGXI/PR8lTITzDz8\n/CJC61anXni+42iQbeScrpXSjeWqHbJGVfDfkZb2g8Yw5NnLdqgYz8YC0mf0\nkK82lyAlVf+0ucFWRRylXJTkSA0HeyIZQ5HCu8+oPsARQv6h0nOZIULPBtyE\nVerIOhtC6r/VAPtSHeHhCOiXaXvwjn0f5UCzfRnd8JmP7V9tN3cxTo4b5nKA\n80mt+uigKK+1MQd2tluzB2+w0BR/Aszxe40b+g12uvVvl4CA7O0/6D+rbKQ3\nT5dNFMrHlTiMH7xpvwlHkgGTFrKNlsLYD4JauZFJxvkE7AeyT/CjJMEjCcxc\n6FI2yTO2lGXvJxtIbZWuGCdfLVMjoHRMb7H1ngTeJuP3tb2wNfj/BUXoDuqf\nTVtcUA5FDZBX86ODYR9dJptc2B6zvh2HTwZJm2+U9fCRc2i64klmU1b0HGoD\nBmqWWnP6MduVNgYDuP9bQ3EwyTun/tGIPc6/0KaiMh1nfZBPK/aZ4ci3oyqU\n+PQqA3/Z9NN+r+e2qLdn+Gc4GYjhcz25tX9WdAiFtVIn6i1HNltCZdCpie1B\nsdtpx7GdSI0LO0ofl+Mbqn5xkFDAgtb00WbGfp7RqdYiXEcoEyY5WK1i90H1\n8eJq++o7yZBNj9SS00DgFW4hcf54gL4uZlRfwE27l1wHcjR10c1ftJgEx/Fl\ncVPv\r\n=PSLu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC/e8DlxAAPKlbjKbqwcWjc7DS72Fx1e53YpQJkqA5GdAiBFO6QJsr3elg1vfHk9iwJ7/BJfVOA5frB7SBycDGrqNw=="}]}},"1.0.30000864":{"name":"caniuse-lite","version":"1.0.30000864","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000864","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-8fuGh8n3MIQ7oBkO/ck7J4LXhV5Sz5aLyFmfpChWpK+rJhqYrOsGDdbBVDdyKIRBWamZpy6iM4OmLCFVudOOhg==","shasum":"7a08c78da670f23c06f11aa918831b8f2dd60ddc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000864.tgz","fileCount":749,"unpackedSize":1208190,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPYn5CRA9TVsSAnZWagAASCYP/06QnSg/YjI0V7oeJru6\n6L0HclCCyuYwloV0KTeqoBLFlwJyTeuYUSyaHXQOzyiJOBf2dTeQz3ZBVc5C\nLZv0vBwGkION7kdhdiWKruXgcjnAJkrFzJ4xBb19dbW65xE3oo7wAgGopNWg\nkFQgHWonT3cIIi4cWDnTFzFMn1D9BMJZrvJm7L+V0NOWwbc6uI3jcC27zE5t\n+2z1neEmKhrAhC2T2zqQixeaeBtffyRbUeQv/6E4bqAoWTs2ynTo9C2ykwXT\nJya1RljqAKKFQ0PEQ56G9ugSI0Y25abUOkBhaeIT3JV6XDhCPt5BmOxKJkjY\nWwUP7NhZo/JEx+LfqNu6jLMWZEeBe3BXLhYb7E8lvOjKDPNMwNK3PyE5k3sA\ntNTCcbRMgz9ozaV9p5X1MoPnvDH/9Q9a3ZvrR4RkphRYz0c3JtNJZvAqWxQs\nnuO9UGQceP3zij0WyPLNNBXPEieV4tDdHgcwLZY6Hm4GT2bqwhfTGqQA1IB1\nafdp0DiwpA/CkwmEokJLXSY74O1yAzQMamQ+RAwmevohz+3N5McXqLE1wdyc\nyihEo6+ocTMlI5xsfQp1i05WTALuVqRuBolsZdC/nSupKwcf1shmJnGlV1sa\nK30nA6BVzjB+RI6Yc0qd5/ZX96/YXS79RBbSLD+R1wN2S7ru03VAkFw+qGsm\nYcXx\r\n=+DLg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGBNktjk2PxSX9xLqbfLyNtCaFfxJ49vuH1EkBeCb4Z/AiEAiWZM4L29i1NecF5DHjiJq4i6/boATyRYtVepqI+xhgo="}]}},"1.0.30000865":{"name":"caniuse-lite","version":"1.0.30000865","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000865","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==","shasum":"70026616e8afe6e1442f8bb4e1092987d81a2f25","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000865.tgz","fileCount":749,"unpackedSize":1208276,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRD2MCRA9TVsSAnZWagAAzsgP/2B8UwBfFH6C5Z4E1mOO\nOIvjIfQAbBXAPvI5hdCE3CW38B3Em05drjk+f2WuMbMIuZVGF5zN+qxkbr2d\nbXYco47rtEKzNPpPvTfiHuuoWg8IlDYOtITjpKBihvZAKH2Ci6AGn3+5+DeO\nrW31FqkFsbVRyAwfzV1zEy2JFKQFZYOEt7lE5TPyIpkB8dGr5ld5Kr85xGfU\n9djenwn9D5AM7BKtrelkkfBoIZZ1dV8z5vs3q7FDsVTrt0ifFOZI1U239KvP\nEwfpldqcgvyKMebBA2L8wA3jQbwZxk3tvbX+RuXHPWegoIavKHLcIhHoBzji\njm4rQXdTlLiBzmFZOb34qFKW/wnS7QVeTMrUPpevFyeM15t49T3QctioYt6c\nJ7vD3rp6tYr+PCxwK4yGxQV5AWjRUXBb0N2GdjTAATE1+BL/p0enON5fcW7P\nN+9N1IzkcKFOhDk1dcZMVx/fSg+Diwau6HCqOdHSz0KUcsx807c39k5OCEKJ\nk9CGAhEvL34sb/kItE1NjFZiZiTXndVpQpV6qNpGTZpNi7ya8LSfCKpO026W\nzhbDHtsPzxXBzfDE6bpKXa5ruFx5yg8jGg39NB98zHe6aOeEOOW8KNsMtwDw\nPlw+3kTx3HYlP2R3AaV72hnfNYfoDjQO5Ec/8LYxpUPUm20fVO6DAr/8sbpI\nX774\r\n=cNKQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkaB8WaZuHr/7+BqEdhxg6n1MxyWsS/5SoY+Eio3Pn8wIgMBlrLTl8QymHmQEIkZkOSxjUPUlfY6uqqTEZ9GRHcfw="}]}},"1.0.30000872":{"name":"caniuse-lite","version":"1.0.30000872","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000872","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-JcuiZ3a/2X5vAQQzR/BBTv1DDy964X4A+ecG2ocdMh1Lx6bcUBufYrqFlNgd1F/eAqUXHpNgiIj/B2kXl1ZtWQ==","shasum":"aa1346ac88ed8dcdc7e372a42989bf9bea696f06","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000872.tgz","fileCount":752,"unpackedSize":1212752,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbY4g7CRA9TVsSAnZWagAA2xUP/Az6zCtWrXKY77PtbEIy\njVVgAir7sj5HHXMaxWo70W6atcvCbHilgYj3AIUgLjq43ZKa2u4hcz+IornM\niwABJfSprP01TomMSWdzU8SHsV/pB9YmZNrr1/PA/6TGhxT08DLWt6oeeoj3\nyuEgjckfF1wUZBZYWgFu3iBx9ipXDol4v0SZRB51nOWA/pUnh1VOb+s86PO5\n8JaJ+9ijC9rsZz6oiU03rBCYkwz33RZ9rncG/TQAaBriubDAfYfCa+WDv4D4\nVnoI6TaYFnsQCBx8s2dfIufEKwxsou9/eNE20YkblK9RpS1gcwELapTQL7gd\nCKWMJUrjx3/bDTp+WYEonv/pPoa4bxr5HzztEW9asG7/+XcWIE3BDA80J+ou\ncvKvvyHGnIzYFOZ5FmYs6/yq5JTZYsWmwIUxnUvtyNNQaIJRdyD29pq0ta9p\nKRl5u3FX0gNZxBqflDWw4DxK+dGrgis4IpQO64F6pQ4VXDnfBFkb+1F5g338\nv00cnSszknrQOGzX0Y/Gs5kkromMbiLs7DDtYlgEDqZCLGcfYph4+nAfEnVx\npqhqxhOz9C0GYALzr94seTajX/nCrKHVLxvaAmuDIjIStyeKyI6WiQD87ZT1\nPzsvxifc6yPppnFkKvhKlcOMad0E8F/rSlkG3BRMPTOdomIhSYEBeWgQliSm\n+hzx\r\n=3k8k\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCFgqwmFYcHpo41usmMwpnOdOxUioe2Qtsh0PgxVjc69QIhAINEmSNidpPqCeq6W/mSrhJ7rSr//1CcbPWs1Jf89+3h"}]}},"1.0.30000874":{"name":"caniuse-lite","version":"1.0.30000874","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000874","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^22.2.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","ramda":"^0.25.0","remark":"^7.0.0","size-limit":"^0.14.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"dist":{"integrity":"sha512-29nr1EPiHwrJTAHHsEmTt2h+55L8j2GNFdAcYPlRy2NX6iFz7ZZiepVI7kP/QqlnHLq3KvfWpbmGa0d063U09w==","shasum":"a641b1f1c420d58d9b132920ef6ba87bbdcd2223","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000874.tgz","fileCount":752,"unpackedSize":1213330,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbY/qiCRA9TVsSAnZWagAA+u0QAITkm6pdyC8Ari8EOcTN\nUF+Qs7lSIh8yzymcciT6Lcf+A7T1VWHwzwC5ZIQMB8tRI2+TSRP9/g06NZdc\nxkO/CyARYwrXpvTuxy3GyWeJqBtq2WY7BRiCPnGIrtXMETbaqzYQ0JKtZRBF\nyR7O5cYLt8f/z5VbLX3R4NX5TDaM1UAjrSXgY7k3XZ9WAbkq+Nc5O7ap20fP\nHZDUlikFoXMro0nff9jaF+nn0nDkGC2LqajGDVeX+NFYRuOs7y8UCPi+Y1vf\nKP8ZWtGp6KWIajuIqD/MUEzayPM+6ct4YqU5kZdvU8Y9W6X8hrjLMyFaMoDK\nPE0/w5yP0wSrstD5psChzgkQ1A6698fupBDV80LPNYWlLUi23o5uyRn1mJ9c\n5PakI/ZuOWssg8U8STJDmIsY7dTnUsFpNQRWeujAaBkO/oSYExTR9cs5XZOs\nl1jZPar99P1AR5FGmSPG3GmU2fMZaY74UjR6Oow/jXKzXW6JZ2PbIklZp3er\nsodIhS5p4BsnuZKWiNKk6Sn6rgEEA8dTg5sNN50nHXyR3mSgZwdYujbDlkqg\no5t1C0rc0CK4oCBHZTd/FFLSrKRTqgvym9YWXX0YXy+SsQn7Q7NX7/0p5jBk\nTHgOiZwjSiap7Bff6Mfu/9SH4bmQ85mUFhM4gZyPSO6T5IOSHhe+5nWdlk1u\nagpW\r\n=zXLZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA7yWly4rcpwGyahWC5vWG3l9NKOueeBKw0Zk5FHEKQDAiEAzO32+O1S5cKw0IOoJkdRLjHkXqKyQe71PMo1gB86Xyk="}]}},"1.0.30000876":{"name":"caniuse-lite","version":"1.0.30000876","dist":{"integrity":"sha512-v+Q2afhJJ1oydQnEB4iHhxDz5x9lWPbRnQBQlM3FgtZxqLO8KDSdu4txUrFwC1Ws9I2kQi/QImkvj17NbVpNAg==","shasum":"69fc1b696a35fd91089061aa916f677ee7057ada","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000876.tgz","fileCount":752,"unpackedSize":1212513,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcN+zCRA9TVsSAnZWagAAnMQP/2T6smOigYiL7Q/7q0Xe\nkX5ockyAcepuKKcByM03BfwC/TuX4Rjr8eS0D8Xy/tI0LHcfsN/STl+17GLp\nI6HhXbyXD/OigYDA9NGkKLaivBSIljgUQcKGvi1fZkNl56W8mWxIEcJqmXG1\nxvBQbSI4botsgWfFhZ5OCmcNF1s9quKxZHJbmWcolfwZJrwa9eMbJHCa6Nt+\ndmLIQAMgPULGiWnmt++VetwRsViSlcgsNQEw8NCU1C34I1dqi8p1XbBvZ0Cn\nMsfADiKiwLRSi3atiTwyPdsU0zdCX8UfDHSp4lWB/RDehtovSyo+3ZFCmhyk\ncKiIkIcW70ec1D9WAjC1JN6LQdFQdUIgqzFrRyPc8eJ6TS3yuZaEUnX8osMX\n+SvbsQjSNqdm00F4K0XcZRD3MbsB4F8OlMkd3ZLwkC/NddJYW6R7kl5BJpc5\nFYLV7Q4pWmEqxcujucWu6Rt7llxsqAoEpZ9sGckkKspY1eQZ7RmvgWFBfuG6\nfejKEDlzYwxL7Il4j8wmdmFNmmnSM+ZRjlQamnmThSUVF5O8eWAD2sD/Mrg6\nCtsEiRvblZ6s968hDQ5nopper0JNfOTzGcKz65I4ppCpzcjGECeqPRhL4l8v\nQRYZInMc6x80qqTb39CgLg6YF2XN7P8QcF+acDzkrkfM08aMhwalBYanfvWo\n6Wmh\r\n=qBKp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDI1PTfUcuI4yrHiXH+nHmmmx7ge0yPD/U5I29s4+fvwgIgQbi/HHEIzfCO3XTlIevLwtI2pISAEBvCyXUqwmIeVP4="}]}},"1.0.30000877":{"name":"caniuse-lite","version":"1.0.30000877","dist":{"integrity":"sha512-h04kV/lcuhItU1CZTJOxUEk/9R+1XeJqgc67E+XC8J9TjPM8kzVgOn27ZtRdDUo8O5F8U4QRCzDWJrVym3w3Cg==","shasum":"f189673b86ecc06436520e3e391de6a13ca923b4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000877.tgz","fileCount":752,"unpackedSize":1212578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcmlyCRA9TVsSAnZWagAA1UAP/jfyHtI6mR11Pe34XQr3\nWd0saTn+NmCSBdtbRCfyP/1RHLLdN9rJPz9QEaruQr2W89PVHcvglQpMRqQM\nTTc5DlsLmEhnOVcatWUNoSjureMoSOXjYxBX/jHt2zRtQ+/G6KHtppkczBCY\njDc4u7K+EHLhtadzpMd6T3ydD56J3VlWf74z4lyQ+NxKmM/cftmqnHs3NaHa\nL8rTUEaZuqfe01vcLGgSaDdtRPFk4GR23lI4MChoNXQ0e7gCDTQACtANwhbM\nGpprG0OlCcjYVnkdEyvjccWbBOpW4nLJaOn5hUigDnReHWBSHo5Z4pFJkqHN\njCO6gSUgX0HfRgwOzgaOiJ9dyijHxLCYaMJTwjGg8PPVyFJ5DHeDpOhK4cC4\nMXhervMQM6/BVAmYkYyqqtT4APWeBwKSDdcMgVwiaDWBTRPTbGaGMz7vtH5F\nWPbAjyyXEVd5arFil+1sXKIe7BLaXzaZ548c2EyZKOOJnuyUbb3v9UoqbxEh\n600Ga+DGMJzfbJG7aoym6cxyNFKjtrzlQNJVheUXYdo2Ut7a2yuJzaG0b4XV\nts1Ph7UbO4vnDWRXO8PxhsK2Lk2NgYFQdiGXwekFyODq7tGOVaX1ysKQJqrW\n9P0jjP7wSjz0GRYHsfcRotUyY6RQq7lyAqI+jlmo/DpwxVg0OvPr+dmGOuC1\ngNpi\r\n=aWpl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID11cAU+SNOjKQj34BEhZoQxLwzz7xMww8jhZ25H2mKQAiAkJoNMglFkpAJNxXU3UnpS/zWJSYJ2aX1Q21m/VYYrVg=="}]}},"1.0.30000878":{"name":"caniuse-lite","version":"1.0.30000878","dist":{"integrity":"sha512-/dCGTdLCnjVJno1mFRn7Y6eit3AYaeFzSrMQHCoK0LEQaWl5snuLex1Ky4b8/Qu2ig5NgTX4cJx65hH9546puA==","shasum":"c644c39588dd42d3498e952234c372e5a40a4123","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000878.tgz","fileCount":753,"unpackedSize":1213602,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbe7ICCRA9TVsSAnZWagAATqkP/273O1ydQ9h7pvEf53vX\nx/fIGWRj56ppGSAh4zkGFhNagwboGV13hHIMp9Wnj5tHagEVz4Kiqq1oiUDs\nmE+zxr8xmZcmEWiiXWh5avz5qzukyM3MNb8Lgy5UgYEvyaGKWlRFKsfejB/a\nxySwqX6JclA6RvhQd1bn4WH4tCbiBTUq/tISAxuLHt4G8+NAn6/x+la1Y2ix\nbjaNUILBvHpp9uLOtv6zj30jkEJqjMPqGkF/EDiFjeXlNk6JorYEvxr/kMW0\nZo57cbBrcP4D8aIjhGD2SIOSxL4mXiD07scryRyvOyVlPYQSdBGoebuPQJs9\nh2kogQnrFZnAqMy/38alL93z8/SzhlIIOmySvBs9v1AcLD2jjliOvrL25A3T\nLjMd4fMkEXs/WfHNjzPRdvKvSyP7jPu3xjGtyniDk1o8GnP7T3KEA2wF2lqJ\n/VODb2b73Mf6r0+2qLnFxlS6sOgF3GI8BoA6cwgf/XbEhO74OUJ9cvXyVXNw\nRgiMgfWi065iiE49ta02eNpiZUbmFazoccVm8906RRoe9mxRnuCOYGhnDrxy\n8l8qy9EsLYYzS0axsEZaMrOA66siHx8Z9i6OQTpFFIuO4CMnXGxmrSIBrj8L\neesRIMbuvW2Mhy78buaAr+hv2xlA7+MUlLrXX2CV0vPHG6gYNROFyRRAndbC\nvfsw\r\n=dK0U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcTaJ0Xl45MHL1lUbDH19xk3/PNAiv3D3P1N0dnUMNMgIhAMTzKLFLr3tJiuVXFUF9JQ+jr59CvJii+5Q/6zIGYYHM"}]}},"1.0.30000880":{"name":"caniuse-lite","version":"1.0.30000880","dist":{"integrity":"sha512-G2cDhHp0DshhwFJSurN7PByRTXgijs3eA3F9tGd5tf5vnTttDVuRI9bFna0WDMID4VYhGs2ob9U/K1A5+pm8pw==","shasum":"b7b6ceaf739e17d0dda0d89426cba4be16d07bb0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000880.tgz","fileCount":753,"unpackedSize":1213685,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhOyDCRA9TVsSAnZWagAA6mgP/R+sNlzYO8FhbtH0vKrR\nXrC6bTH6UuOx3VG4yFBOryH3UX2n1WEdjgfcEK0CnWsj34M3oF4WUGYGbO5f\nxyqmPAvHmjapRmk6109NtlBoNx1ijpfN7nEpEwQ1GvlGsdo9VPllNk5qiBfh\nm/J4ssxQM8etSBnhK2rM7bhlMvV7xSa4GUqq4Lj45XugrxW4W+RLFMoNuTNk\nqsODQ7gwTHx9ZgAVVD4c3pOd0TlcoqI6AEhUs18jNtyAKo/0K2EZTmMywKgO\ncEotvR1+u/kJodhRyNjT0b+BsII5pvs0K2NkyUZd44p300Lyat6Yldyff0vy\nLTNF5VvxU4GT7bQ3W13My/bbyqvcUl0OAtaoK406kU3oUsTK0R3DaADAWMHE\n2Safk1QhypjlT+us5Er5grn2t5sXXOjKs9tGwOpbnsK7etXWhS/Fu5BZhMRj\nwKHdmuA60Ku09qOKjaUadUk3TqjuDG1q/xwoKVIcNvxc6Oi46et1KPJw8GbF\nvam8PfIafSrzRIyhhldZ4dcrfuVp6vzJFffCOfspcIpA8A3qYR5ToL3lN/K0\nrrVQRg96d5N8/idMsB4BWPCPoR+bo7jzCU8v13bpwSNQFEiwlIxDxc8r/qEV\ntIHdd/3O15M3a/0eF7NuMFOB0zwIDJee/waXAsMHfCXfwPHBNJWX5AOxadk0\nzA58\r\n=kKUB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDmWPuIsb6pA/gXkmzvsGQbwplYrikP/DSzNTlMhsgEUQIgRPDFXUVUJKIF+eDGlhi/UWaL60DBn4rczt6uC2ZtQas="}]}},"1.0.30000882":{"name":"caniuse-lite","version":"1.0.30000882","dist":{"integrity":"sha512-8rH1O4z9f2RWZkVPfjgjH7o91s+1S/bnw11akv8a2WK/vby9dHwvPIOPJndB9EOLhyLY+SN78MQ1lwRcQXiveg==","shasum":"0d5066847a11a5af0e50ffce6c062ef0665f68ea","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000882.tgz","fileCount":754,"unpackedSize":1214780,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhi/yCRA9TVsSAnZWagAAG+UQAJZkl7Przgf9nWJhshG0\n4jF4bI/xahL8RUUd8l6ZyGWfZhwvcEWrKzlIMAeiW9jZp1qwDAvMgaI+hx95\nl0TbNlfnwY1Owf+w4S6RjCwvpXPDNz2snSfF7nB8VFVKF3BbpVDGyPec3AZF\nyi8/SLp8LGWEdNHRv24VqtQhUCK+AOItqqAJspqYdKxvLowUlmBdCW+vqxOJ\nrSIUPe5idOy4NS23NjMwSiGRmwvUxOMiXYAKR98JjYisI7lGEms8JXxXp5Z3\nih7tZmM8ingYxjewmXOc1lmrLgXfE+VfT4iQv5bulQsdPK/WlSgIng5cqjbD\nExbFTrM0LkFJFAKEB7GCcPia89TB2ZlW6E+g9Sp06Re78CAjYPpIheeR2pWX\n7hpwa20OVuyB/freQvzaX+YDZ1IxW3NwzbkxC0qzj4RlGFj91CzxdaAsvw6B\ntHZxqVhEF+TSqrNIj2UR7uG/unjoKXzZYVIHONJlbA6STU6MPjoAOBlq/L/6\nmw3ai+ZvAtfyeDoMmBrVPPzuIRdlBQN7vcksq1ev0baNj9NWVPdHE+teXeSm\nBSBVOMVal13EUpYLsVk0cetEedHR1UNv7iHf2LkncEdyF4g1Nfq/2aKFFFN7\n0ryLlF+SR92qYu45bvsZrzbXh9NEilIzyrOU9vZ18UiI0yZj4TXMR+WKC9bO\ngvlf\r\n=ydLC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGDjQwbisamk4JeKNRwsbPJtHqsahpV6h/SIeo/KdKh9AiEAwxPMmRhcfVmhTbYIDfqWye1fD6LueMHFjmiedGKuQw0="}]}},"1.0.30000883":{"name":"caniuse-lite","version":"1.0.30000883","dist":{"integrity":"sha512-ovvb0uya4cKJct8Rj9Olstz0LaWmyJhCp3NawRG5fVigka8pEhIIwipF7zyYd2Q58UZb5YfIt52pVF444uj2kQ==","shasum":"597c1eabfb379bd9fbeaa778632762eb574706ac","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000883.tgz","fileCount":754,"unpackedSize":1214851,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbh3NkCRA9TVsSAnZWagAAJlMP/0jqORT5uY8D7rwazMCa\nyGVMJytEuPM42TTEMrHbAp3JBLlj3N6pLyuRbbfiCY2bJspWTbVvuSUeuDnK\nADLh+bocbDLSpX6wYDoTGN3F8TJf93UPLzLtREyX3ot8AsQifzWsfU87fhwx\nU+65PjpCCHv17UhsNRh/JvAuW3CCS+O0TsYHVeynYmK1ceYzH3j6+ES6g+Bo\nB4sphoM7CrK6cZaZ6if1PiCrfxbHt648AHAJeZuhWe7JLc410HIbM1ce7uz/\ngwV4mLyAljHhwvpareU87AOjMMDlcnnW97//i/Hm8MRx2CFWl69tvI19I8Wo\nVsCQ2nrqKT2F092ChYDjrSEXg1sGxrEWQw9F3+yjThR5QG9tmrjryj5BncYm\nreleshqIT4cWk347BFcdWKSHVznKIRWdHzxP+GomhL5/eFaqlV5rO5dw4jAz\noFzWEr+tRYbfdw8eEhvgDOX+T8uZ7MmbxiGY3ssQv0Gu1y3YuY/H7pe7Occr\n8wueoXW3MBknlWz6RtiX0CHFr+krs3MhBY/bOaMrer4rCMbWcCz4Cpt9hRON\n5uGSwL6HodiyjSUhlGn5jSxezkC2CkHBVpQx3BakIFfJry2p59EzQ5wRM5yR\nal9XFRY+4rgkkWQg3nBOlkxQl8KdHVkVgSSIeWe3vfihjzpz+GPqdGiI9QSS\nQ+JM\r\n=PHhu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAV0LeTh4BE/Ho6RdRVYrNiaxDt+C1XAKYk72Aok06AwAiEA1ZLrrntPUU2KJ76eShCMaKsuAdvIQPncT18AFaCCJ14="}]}},"1.0.30000884":{"name":"caniuse-lite","version":"1.0.30000884","dist":{"integrity":"sha512-ibROerckpTH6U5zReSjbaitlH4gl5V4NWNCBzRNCa3GEDmzzkfStk+2k5mO4ZDM6pwtdjbZ3hjvsYhPGVLWgNw==","shasum":"eb82a959698745033b26a4dcd34d89dba7cc6eb3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000884.tgz","fileCount":754,"unpackedSize":1216976,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjgrmCRA9TVsSAnZWagAAcoUP/2SR1eP0iYgMll1BN3pI\nA4a56atBJHHuA23oShw4uegRCNTS4te8cOH+3WteP3+PB19Xk5ziT5r965HB\nDTjOLpuHA2ULEN3ZWyZYHU5PlkQRgv5J3fBbFyZfG9onMEgjfLfwc/0JS8Sa\noj78Cd1NxMtqwgC4rOp2YrdXu7A5JXh99Icnc4hXozFNG+Nif58UpCMh2aHx\n20FimHpL4Rm0rydt9C96FdEw3d4fNeWVB1zWVT6iA66mLe8ukfxNYxt9+ky7\nxfrRL7OJ1cUNzAqxEXy2jnpevhkPelRri7Cv3wQZSrPj6BYslwp+4Igb02K6\n2qjF249YDl1fa4ctjlMThgLvXWD3knmJJ59Ox3QdXaxpPCE2HX/xWTtYzs6a\nSzMLyKEQgrHrCizfECPLGQ9H3ICpJwhcTdWqrv6KYat7SYynmN4z0SaHXA7M\nD1LHJ47y6GLUN4wijIHKPqiMQvcrHqJ/dbLD7s+xXlNBVKVQA4AXWnvjdOjT\nDNFLmEmTSVC3gv+5JBMzurzDOvdM0wkrLQnAebOWSRamr3RVECzl9SYCndj5\nvrhuAnSW0AouejPYloEu5VBFoeiC/RSjPhchHz9TnUIWzotSG7ZA1l/yu1Ry\n34kqgpr1eBQMxuhLQonVA8z7I6joGq1QxjV7XCzbY3t1axT0kyEaZctPpgpc\n1ylf\r\n=60D/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDS/ht4gJi27Zo/JO8fkzrl5H5to6B6Sb2Locy/v/PN6QIgDNg5LLv5N2+dOyTkLD3SKLXQpu6XXgyP4/eG/IrrAPk="}]}},"1.0.30000885":{"name":"caniuse-lite","version":"1.0.30000885","dist":{"integrity":"sha512-cXKbYwpxBLd7qHyej16JazPoUacqoVuDhvR61U7Fr5vSxMUiodzcYa1rQYRYfZ5GexV03vGZHd722vNPLjPJGQ==","shasum":"e889e9f8e7e50e769f2a49634c932b8aee622984","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000885.tgz","fileCount":755,"unpackedSize":1217968,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkLv2CRA9TVsSAnZWagAA+BIP/jMuyi4QHxk/izrC6k9P\ni/5ASG7h45QCWFMx41OdwVsb/VwKCiCYfOnfsahtybSQne6DfQs2daB+kk28\nF2kzc8E9R1juq2BMYe8C+l+Zm8qlNHpBS19hfQZpcvLROv+HDRpk00691DlA\nGMN3khsXicOZ7IsEXk3CHCtyV1FKQFUmgJOX8g87kjtPtEzXUc0EGYf6aEqY\nFzKU74C/IPl5OYdhIdbut3J/UBgv9AtTam90K+0+2K72RUiOdISABcg072LO\no+4OXOpnZ/noW0Zca5sNsrIaFFB+zJu9iprt9Vz1B+Mva+zR2Lu98lAjQxe3\n3g1RZlOlWM20bSqQSCC0v+t5Umwdx8KsdMyVj+BOR/G2jgh4IBzMK+WruZl2\nCD5e05fWzOQE5hXKON7N4HvWQ99Jl+ctIqklV48loSl4BuxMeyEzLlqIFWUv\nUteuMorw8y/m20nQDs85iRSB7nf9y6ED2fFggAn9IxpyWcKsWi2URSsfJYYw\nl13dcK/vTOrBMnK764bNXCfR3buEfUWdoqtfBRA8zS3JDLeZLgNj9STNFDOL\nMKoCyQlBWPxXJOSgCrZ4AnA4QY2WX/No/FNsas7WzHwDT3KHwhakK58GjpOG\nhGGlPqgUHMTPys+NC0xpFNQy9goVGqGrqLnYRFrg0ZCS14dXz00d/5kEqaCg\nZPw/\r\n=WM1x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFcunDEkwWkSi1TFP9N9MjF4vEnsRlhuvCZxDg1UlFNhAiBejSL6UxHpiXKGu9v1hdlWH0tCazMQ7rIQYhZuEGc0jQ=="}]}},"1.0.30000886":{"name":"caniuse-lite","version":"1.0.30000886","dist":{"integrity":"sha512-xpYuY7rqc5+4q1n/l1BfSgIndaNqvXWKZ0Vk0ZXzVncCAkn0+huvIIPwcSL5YRJoW4MSRsgyNbjnKuh45GmknA==","shasum":"2127186c4f57da10d3ba26fc3e87dce4a5ddd3ae","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000886.tgz","fileCount":755,"unpackedSize":1222901,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpJCECRA9TVsSAnZWagAAycMQAJUWt9+6EfrmdI1rHsOX\nwA/TFRrF/X2JzMHHz0BQFan8Guw5Fx0AJEjY/zJoXLwiYC7qWIkyL25z76sO\nDkQ8Rls51mopJb1q/MpFQOKlF8E5YDkg6ayiu71KR0qAd2d2gPYe+vFem7gh\nSI9LTRCbmdTngZGZi2f01BxATgh5Hcb15aQeNoFNMoLt59djMQnovpVwCILg\n6b96crn4jxfXB0xzmdDD1wa0qxE+Pi2KPO6JIZrSnHxIeweTDWKOIcz2ebtr\nc4fqUNHrtwRTCqFqOGkVxEkJ3SUA9Taj3+Z/wYT08e2V76ScbmTO+lnedmPC\nGScTor7rmKsXEETDi7F80wZ3Z9VKz29gExkfDt+2rsQfkV9TzEqppyQO5CqK\n25KEuS/pLpzEMtubrICrdPmIUWgucgAlaYSh0NUTIgOUB0uH/DAuEeKGyjKM\nnJMpfLE/aQ1BDKlJT8c1eQWr6MpkNkdFs4cq3e+nUpJdnOxEtfwWda/WqvZM\nAFwG8tA0Jwc9rTEVcghOZ0t8y5wPW1ymyBMugElJwLaMud255QwgZ9Rq0DgX\ncaPCij10rKkmZXTJry828owA1WSTSC+L3DHzXyA8jvgnzR5ltE/srrfN3ARI\nw+BFxgdZLBmfJeVyku0GIBj4ccVf/bUtiRe9VvHBve3RZCJu/HZkfatQtq3J\nxtJt\r\n=lfdo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHme+D3DgRlf7jYcj+1lLJERUEJ5Z74j7pqOi1mT1QcQAiEA5cKLcUVnQqPhVdzgtSzes3jKkmMP9ZfeDH0hnJE8C/M="}]}},"1.0.30000887":{"name":"caniuse-lite","version":"1.0.30000887","dist":{"integrity":"sha512-AHpONWuGFWO8yY9igdXH94tikM6ERS84286r0cAMAXYFtJBk76lhiMhtCxBJNBZsD6hzlvpWZ2AtbVFEkf4JQA==","shasum":"1769458c27bbdcf61b0cb6b5072bb6cd11fd9c23","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000887.tgz","fileCount":755,"unpackedSize":1226031,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpxdjCRA9TVsSAnZWagAA2AYP/3+GV72TR6Ds2wPpbGkX\nUpMPyyvhG33iGBlbNKE1KIKsJ6BBic/W0xoVFUq03FqvLYhsuF2+9wFHnVBb\nOvNUqmaNFgDijG+aVbdMTLzasXVBLVHLQIghrtw26c7MbLbksa8YDD1n/6d3\nXTMs/CsYFqdjijs5f6bObFGiplmGaos/SzSqsXE1oW8g7dPZ4882mdgVxRFG\n3RcuifXjj1RhgB8TxiEVs1m45a6wbxJwXod+eoUmhQckj6yTF4MN0ETnbmBl\n2p3dgM7RUwmy6XGLyl6x9aITT8PZZDyKT2xvzcvmAgUeDhn/ug5j+oqOkkps\n7Wxs6JrOS0/wHA6xz9QbwzpysJ/rXReVB8k+kFw+2kRiXcnzYSE4be3ImPX2\nxhMGRuD/+GBxDcdbSUNNK7DPqvhHyd3eAuzljViyp3ZjD8dUgrNiDAd/mUTE\nkGbHVXt8A1Ae0MOmQt1kwcMC0bLiYl9S0lVFNY6MqVwBz0KQUrcnVljiPbHo\nSDQeXJDAHgO7vRUiyt9MrQWiMAVGzgLrCBrHw1KU0vSqYtpBz+kbjycjVJDi\nmVPDAh9iKzIMuxV329ayyzk5rMUuc8iUJ6WhRz1cOnZvlmY4NA9RrJcCHzB4\n7YMWghhJ/mZmEojzwPQhAGS9W2FF8PVFiVl0eYEK8NFii3yvDx+d9hgzXuL3\nUjN2\r\n=NIAN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE1ric5wku7VZSYUXwiJeDOhbIBdWCNmt0gb7MEgxamwAiBmOPKAkni4YuEneJQ1pol7V4RlSXWX+A9JnRQW8Ar44A=="}]}},"1.0.30000888":{"name":"caniuse-lite","version":"1.0.30000888","dist":{"integrity":"sha512-vftg+5p/lPsQGpnhSo/yBuYL36ai/cyjLvU3dOPJY1kkKrekLWIy8SLm+wzjX0hpCUdFTasC4/ZT7uqw4rKOnQ==","shasum":"22edb50d91dd70612b5898e3b36f460600c6492f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000888.tgz","fileCount":756,"unpackedSize":1227572,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrZLECRA9TVsSAnZWagAAbfYP/iZBYj2Y5E28nhO7sbPh\ndy/d7xN7RAmm227fs/nz46vlSUJT/jOWfvLFWk1lRSW6sIaQpGyrYMQgWmGX\nlNEGikQaIOALry1F5U5wHiEbXPbmJX6vcBDqjFJ5X62jMW0MhexZkwlACgTi\nBGnsql+gpHeaTgwEyb8OBlevcnKLx3Egt4Qlw36mfRJ0FLqWlhom02NTvU/T\nXWRf/6YTo9335jb1aSyLUphAIrI4eWxwlC6TugDQeSGTDFCrdBwMBbbDt1Wg\n+F3Alj26xDuuYW5iHWK4P4403B0PXn9SHVISjP6XlrhUs6INX4N3q9G6z1w7\nHdN8sh5480MBwOlMa5DjPz2RpTgVwosBpnSnAkDsslVX0GjaH/QSMnxVZl+l\nIP/+552kE5lcV72B28D41MXYKZbN87zTWpjaOcZMyYFKaV0NQltkBUxQjwQd\no80hE5D6g7Uz/aIzBf/O+E9TjpBp87Sk7dQggksnx1rxGv0dgn+x9+nV4RYS\n84/BItNk+YR3ObEkMdFWjZzonVqo3+MwkoTDJFV9QAbnjdWtpu8zxLZaRxj5\n0X8coiIYAM6hpseaLiFfpBabUNELSmXdbYWod7lepQuyaQ5F8Auzg3dkgh0Q\njzp1C7V7wdc9JZ2mTKVMd8TwmND0l/4goDNYwnB+9JHaACbiffG2EecaowrL\n1O6P\r\n=F0CF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCWhHhZfye0p4pfOEIlx/LoZwz0oBiU5gSLDESwjlPlQQIhAP/s14aclJl0N2aE8VSC502WplFKUZL5aaRZ4j83zjyd"}]}},"1.0.30000889":{"name":"caniuse-lite","version":"1.0.30000889","dist":{"integrity":"sha512-MFxcQ6x/LEEoaIhO7Zdb7Eg8YyNONN+WBnS5ERJ0li2yRw51+i4xXUNxnLaveTb/4ZoJqsWKEmlomhG2pYzlQA==","shasum":"53e266c83e725ad3bd2e4a3ea76d5031a8aa4c3e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000889.tgz","fileCount":756,"unpackedSize":1227641,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbtEZkCRA9TVsSAnZWagAA0X4P/1TIB2GsXvYI9LXrFXSj\n8y60/SzCZlxMq20Fa8IQ9SCgqPJAEHusEMws6fsRuFJlSBnVx+2oPJsONrCL\nzKFCGeejwCme1uYVc4lJIDLeHx+JLUWnavuKSL+vwEw1U4t2teeq06zqn7fE\ngOtgCRhek42/VWdaTQOMk2VrTTUJ6lwjlcoOqH+Ttgcns+2M9bSeqS+hcHRu\nFR1Y5sv3b+4a4retdXs0N6n9E8zy1kkkTxzcUO2HoBaeOuV7f++7UoiHGNWc\nw3xw+oOZ1ynle/1wEMIkKUDaUmrzQebdlP1pSlq1N64snB/41Yf36hdDLIo7\nVe1dieHOHqfGk2UWrteJ+h1sp2pN14W+QZCBbkJy1EhLegnKunwG2/sx34wW\nGmTAYoNW5asYRJSATUUbwelIeV9upYjeubDfGy/kRzcM3xqO9dJk4GnrB/Ws\n12i6tmUZvw62tbK3ecr+3Al9wASS+f51qxbnMZ0YGTlyE1Iu4omj7ujODN+O\nxdDVdZWcsQoSnR0hWRLq8WiP9zobZea8DVwOEfrWNEMk4l9aBProfdQQjEM2\np4HjS+mDsbkl4L6tph4bm4z+eD/IASKfqMv/zc6rVliiXc62EKutbhXtCLwY\nb+S309rN2nH6wTtNHW7gTpOrKhEDeAw31g9WO3TvSa3mbNU7ILBlDEfU7QJs\nA7JV\r\n=q7jB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQ0VeJvYVau3uDxi+GNXcLirFgPV4IT1qOdLuxi5Jz6wIhAKWbE/SLnhwS8ZiuOKqTo3r8YWCu1FtNJhbVOo3zij9w"}]}},"1.0.30000890":{"name":"caniuse-lite","version":"1.0.30000890","dist":{"integrity":"sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg==","shasum":"86a18ffcc65d79ec6a437e985761b8bf1c4efeaf","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000890.tgz","fileCount":756,"unpackedSize":1227706,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbus/SCRA9TVsSAnZWagAAkwEP/3S5Gn03hdD3/nXpAtJk\nVD8gZGisDYionz241bB59YiKnH3rZrjHagLXFSJ7zkL36umiFiGgrb7MFfhZ\n9cq6PacnW16e5JjmuCCeBNYyiqu5FZ/K+hCb2qoxbmlWAf99shrTQBsYiIYr\nzTnE3mkj36JhepMsN/CAaBOBRTU8VwBq0E9tfU3wcoXrulNMivm+gI96dueO\npNy/HPLxgGLPtR0YSDBmt88iy1dRGrEoQop7DK2JdAIRAwJQQGFPi/1IvPEi\nVTFdhSwndmN9OqoT1jo9oRpXdovyhqZE0WgTSVNQCrWExBptKlKnL9f3EeMH\nQw5RXAnK/4RvWie86zQxCxrTAWtqfyvWlq2qpx+jrVTtxKtyvhpxRZw6cVZU\nZnzoB6sBuaLj168TVPmx82Gn7PRl/7A0fPV/FsS3IFl1fk2JCWiy3sYiDKB9\n0tOOIS4mDOLHjIlgdjh2Ap8/0rA7ALE3gbMMns4tsjh1MksLMqIq5OHDWjlP\nyQhcCTdUdvZzKst6y4awGAdhrSTEp4jTmTkyrJTwwM2JGq+o8mkkf25R0ZTJ\ntCvXi5BNPmVn430w0VxXTtcad6CiO/P8xZRDivcp9VGFzJe/cNeRExmmnjwb\nUGZSyzz+b+BEkRsVoqL0ucB7iKnIXpbtBAQHJ13DAnW4Y3Q4oT5r0kC6hx4s\nP4zD\r\n=tf2N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKO96m1C6kV2NjtNnoKbzj1wE+jC11NjmPpPooXVm0dQIgCUd3lQxKo47W6UyVkf9lYv3GFpeZDA9HwemFvh8ksDE="}]}},"1.0.30000892":{"name":"caniuse-lite","version":"1.0.30000892","dist":{"integrity":"sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==","shasum":"344d2b51ee3ff5977537da4aa449c90eec40b759","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000892.tgz","fileCount":756,"unpackedSize":1242846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxDSJCRA9TVsSAnZWagAAXsUQAIhiz93okhgJVoPmz8sI\nuiSt8603fYBaGoUs3hMk1cj0FrnyjrfLqyGh/CzeLoR90jjcynMHmjhV9JeM\nUsNRqgms7w19/XJ+a7iIDmWRiVzQV955GJLPvy3or5ST9Rhp0YFo4ysYKtGS\nfujjnNMNv9LMosDROehBNmWCCP8JqaWGa1+t+k2d2eZrHVM1cn4rZqbQwRRW\nDsXtCkleGnH2H1oBS2PlkgImtlJ1wifg6Z2l/+oD9n8KhiAHe0VjZA8V2MqL\ninem12Vorkzv1sWu5vacZV4ooqiMLYVGnUTfabrTzHnFHqRQq1zyl6y4z+Ec\ncfB7qOC/GGg+NkG9tiNTTipTas/bjS1eKjDOSvfW4J8og2o2zCwFgau44AHZ\nPcFMHvA0BuSkICI/szpELndpyxHuwqFrlKIsOEtL7exzHy0+/VikHj+vgwXZ\n0wpJz5OedRCnMv6vy9+q+d2XBp3zl+RKkM5j/pv89NaNfow52sfsJhk8YIrX\nMuGrnDW4bNOzFCfNoC3FvdCEuU8RWVwIvbVaRxLIrxyySafHDKdWeSalPjC9\nHOo2eCTnXvonU3VLS0ucoVXh1Eradyk3eV42Eb6SAXWP6T6js3NSBq7GgbeG\nMLg6WmIwmIcIXyGtwhfBiwd22KI8ZKdx1D95ah4ieP50HySY3gz9DiTZyQC3\nrlSE\r\n=KtJQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqjtm8wLHps5EysLfeIHqToU9P1spZRQIr//V/GFZyXgIhALvQGJTHF80CS32BqJH2bNJuL8Gdgs1zYXaK3sPTX2hu"}]}},"1.0.30000893":{"name":"caniuse-lite","version":"1.0.30000893","dist":{"integrity":"sha512-kOddHcTEef+NgN/fs0zmX2brHTNATVOWMEIhlZHCuwQRtXobjSw9pAECc44Op4bTBcavRjkLaPrGomknH7+Jvg==","shasum":"284b20932bd41b93e21626975f2050cb01561986","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000893.tgz","fileCount":757,"unpackedSize":1243858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyBr1CRA9TVsSAnZWagAA4mEP/R/TUJ33Eh4zsyTSrwGX\ntshSGkT0TTemCcysBCHbbBBGB9BFJPOl/zReceAT7GM9X/yTaPgXDyf5gdaY\nchRq9rvztaTQ1j/O7apYK46QH2cuIh8ImsxR2dpdTE3V23XlHbBu23ibE0CP\nqj3z+stKCqzWNztSH0M7rdkruNPT2TkIroNJsLu4a2Fxo9bFkbogtfDdDN8k\nuZKiT4+NtJqaFmAJRPYavrRO25/rmKGjiKBiTtdk3k6SV8rJVKHnaa9r/XI+\ngSaDIZ0Pnh+G9DJBvkyJcBoWEOmyr3cHOajdTqzsTvoQC1AN15tMEvuQl1TP\nDRxp7Qgb8rUfppDbzNgfKZqxqciInjz5tet4b5r9dX4YiFokBpGevyQeYsyT\nw9VA3P/1XED11qL9pVX3HDEw2Bb0sxucwrG8HGcnsqhxBBLhgrvO0zmz8PGV\n6zTffyUORNKnrtrHscuX9gvEBEGIJyS4I3xwqFd3EnR31fSyQ1tyYDwy3KzM\nXM3QxfiKsLOqG40OFwtT813Q/f4ao75pgzZyTaVRNPGp36jkev0Wd+91jXV7\nbLrs0XtQFGd5Jx/rVMVI+2R0ay4TPXmB37sQgU5wSeH0O0KSceNUk6q477uR\nJYp/cGJveVSozR7dJ1m74pL4jk04MrnN4uFxqs8PLvPhJNvzXRH9wf9fKE0F\nFJIp\r\n=MpE5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCU0YPhGbn6aoVPXBGD8DwQL/vO76SjEjxgXtS4/eGGiAIgJWLeb4cTFAWgUvvF05K9dV7R4AtpguwXsy38Xkie4FI="}]}},"1.0.30000898":{"name":"caniuse-lite","version":"1.0.30000898","dist":{"integrity":"sha512-ytlTZqO4hYe4rNAJhMynUAIUI33jsP2Bb1two/9OVC39wZjPZ8exIO0eCLw5mqAtegOGiGF0kkTWTn3B02L+mw==","shasum":"651306e690ca83caca5814da5afa3eb4de0f86c2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000898.tgz","fileCount":757,"unpackedSize":1243949,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzrJ3CRA9TVsSAnZWagAAD7IP/iLsggKYRy9ebrMWFSu+\nvH/u7or5GNVX6fTiCJV1af369riW/LZq7CCWKWgJqTGDdC3HD1tbhO+5TTap\ntNal4tzBgnoxMW5lZGBsJechBvNFmO9+thuXj0dRHjWDX8HkOsq/i/SfoC21\nC6G3XJEAOWdaq+/xkMt3nnp1grpHLy0Eg70Tve+Clrl3iHIyjFszaPGjB/qf\nKO0LZ9X7tGUIMs21O3MuBK3tms5BNsiGYiGt3OQ0yLOxztNEh4tzEPDN2eML\n7wHrK7tPXLJ0c86haOUWLG3QHdiO91mtBsA23/Ua4PwvgSLZ+InYviSyH5j7\n3VuNigGK6Eo+023g2FEG+lsEl9A2Y75VbZ/YH7rh5EmzWUVNz0s+F1/HCg1A\nmELAMTFZT05txNBZ7oAg+rjpSmmhphqKRgossvF+HnTSQRLfZzQUgilYpxpW\nA2DB7sQazQRhXgp7HdBZHjLUqQgW8qFvbIJcBXqktQ3H2q6jmJsgz2rLVRoy\nlKNURBqjqHARxgKU3LAsVNt2L87sAQHK6qMz7062OWv5wxEEj2kap6bQUmXk\nNVHB4qVYVml5Rinz+CtjT+dTyY2pZujKhZy1bSMI32TLzI2rYLIYz1tAw/gC\n8w+iEuSrwvMlVw3c1Ucq5VxKhEuSzvmnWxiLQ9vMudHKCemwomLB0OxeOhwL\n37Ld\r\n=2+fE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChG4DeO+cxQDnhwW+8wPXX2qjhnukPgM1iOvP88cRdXQIgLWX78GDB5mPUf2fCxsboCHXPwUGdUgGKZr5W6bUFTQo="}]}},"1.0.30000899":{"name":"caniuse-lite","version":"1.0.30000899","dist":{"integrity":"sha512-enC3zKfUCJxxwvUIsBkbHd54CtJw1KtIWvrK0JZxWD/fEN2knHaai45lndJ4xXAkyRAPyk60J3yagkKDWhfeMA==","shasum":"6febdbbc388a7982f620ee0e3d09aab0c061389e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000899.tgz","fileCount":759,"unpackedSize":1245865,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0UdkCRA9TVsSAnZWagAAUmMP/ipmLnD4mIFxb3HHGEDy\nkdjxxRgJzwNSm2lWNwwJakG64CSrjMVtUb+uM4dEe02S/Hfu19HJ2Y6LPDLj\n2LBBIePwQJkFZZxpNmEwxnUWVMRck4mGWXiIJDwyJvtILkjY/Q++E2N6QSM5\nl7cRxINm3mK++j4ry93O7pYrj27T8nyN0SfirDKdQxpKO9ImbKxwxfiaYjDd\newmB0SAv6CnNCizKHVmchF/+gwiqh+72YFMVoTfbeN/E1V9YQjUXw7Yu348i\n/jZ/TQEBooOW9YNp/y0vaJZn1RLdPFnhIhPkfuAdEb+O05W5qNQVQpr/+T29\nu4bQTN6LANF6vE2DTYa+S9vtAsfjKhNaaX3EIhhSJhR1K8P6tZ2L2VVcf+BV\nreYN6ZXqWnNUGtOsOlRQbT1cgB8cGyo2L4o8ugjOWt1TReuwDw+swnMM9/Ca\npPWRJfi9eOxo6qqoy9TTP5eIgHoG3NgWELpWA186MD2iERrv+CFzNZb8CQBp\nhQK2IYwxWhVIl7IwoHEzWJRVnuUEkzQu+8BTTYzOEMKFTO0OZUgd54T3nfpr\nkDmlA9eW/L5PUPp/EPmCeB4tDLg9Qa2osTrRGHSKNkctsZY07XFoU/0TEYW5\nQHOG8WxXsk1crjqZdcEngMK0T0vXpJ5/gJ73qyIWCeUZJkLRgHULM+xxr8Ay\n5p6g\r\n=uQ1G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICpgtZTGT2z6T154/WBHkcNfpUFs4ZJt4DGejhCGABKgAiAYMklONk//7XV3JWCXYZ/b+hMG45LvgTPqRdHk25VLWw=="}]}},"1.0.30000900":{"name":"caniuse-lite","version":"1.0.30000900","dist":{"integrity":"sha512-xDVs8pBFr6bzq9pXUkLKpGQQnzsF/l6/yX38UnCkTcUcwC0rDl1NGZGildcJVTU+uGBxfsyniK/ZWagPNn1Oqw==","shasum":"015cfe37897a3386a3075a914498800c29afe77e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000900.tgz","fileCount":760,"unpackedSize":1249446,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb1mM0CRA9TVsSAnZWagAAnsUP/j5L+TSJgHEq+PxTJM2Q\n5+ZNkKTPOOeWXJ5wojJEsZKk+86TFdo4bPpki8gMBPHRNLjE8WNfnmeKfJ/V\nVb19gBgNNzGpB3kuSvZZ323yPcmg87HdbXvM+Bm5UN7YdxlTzt5+yHcJviXH\nDyDSfF0KbN/hx2RGrFcD+4BlSOzIeCxXq0x5uaof1zrUZv1WGVs2YZj56wPM\nF2/bstf31Rc+nDKO2K3Ykzs1bedGpEd9lmOJRVEICc7w2b0caFxnoxoue2+P\nun8WfRt5Fon13ox53lvVgUBbg1n642lcJM2zSa6Yx1RAe9BAof6nM1I7fT0/\nsso3uEDbG3h2Lw5VRiZL4B0sZwNxAT2ceGOLDcl9K4pqntcwnX0nOn6OYbS0\nNJZ8ZyeixnJfA0Vfr9dltlFcVuwbSmvcBd04MLRohRPWFEQBMih3LgrjvcsX\n054VjkKqtES8VyrbY/0Zocy7xb0j0Eonkt3JVTCigM+ZkCAfNvXuTzdSeKm2\nV+Qm0vlWd684By6UZ6hfHGugR9CjQFqLBl1iD7uKIKklo9G4O5yj/tPMdRXf\noLJj3TWIY3MYeTgZWKXt5dFHOQc/t7u1wRPQxlprihjcZPCRP647t3spvTYv\nDVoL6se2YWwCD63xm3ng32NedAGVeTCZd3hmi5oAf33XLJKVbb718vLSPRaj\nL2rD\r\n=3JgY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIALEBJF8avfulZ+II9sWU+p7IxWOjv1XcH0sxis9Nx5jAiBfgkXd0ZIer0vZTUPKeEleG5B5LF7rJMlV00p6zubv/A=="}]}},"1.0.30000901":{"name":"caniuse-lite","version":"1.0.30000901","dist":{"integrity":"sha512-vQ9EuQBPXdVEgKbTk2zyKsNV9lYRW93caszgldxGCIzbMWMjHJ9qhQjF7TxkS2Va8BZpP4vG0GM87kcYgRXVzw==","shasum":"1f55288738537708ba3289007b6b61a400d5c5d9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000901.tgz","fileCount":761,"unpackedSize":1250387,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb19DRCRA9TVsSAnZWagAAd0cP/2TRD9GfvwX7E2S30de4\nUMEK3WngUHECE+tdRfU0Yb2+e3ONGBjCabBioHC8b0pWgAAVN+6/QOOwFPBd\n/NMxnOLfPvBMHZ4gGOOYWJpNlPJWNMHZ1ZmkF55cWW4m+2XGElIJRqyUB4wN\nEZCyZzJzsnvzFW3YXmXadtcP7s1KHo3yzr6xLU5MUBns5IIK5Ip+1jO+WJQX\nSYYigxoiY8B/meK5LimjaJxdvdtne346P4ZEwmvPUBXh2SrRg3FWZAwWVB+o\nsjkSgouw9pngZoSYu+xaADMXD/fiuUyLFy8ubuoKQKN7vik3fXCITgfmQUgm\nN+0MjVzK0FquaTICNh4V2knLp/GZRQWjNw33YzN34U5p9QLeV67UkvWogjNH\nqqeOq6DR5dkdhDKbteVUEUGcllpH11pZjBPvmw9FKFuwjzBzWDQnhRP19TVa\nPQdjJkgoGFb6LsNzRPHi0iiDzKjFp9Z+qTDZ6EfJP28m5jFOZCQtOgyJOefk\nt3oR7utRixX61g0nLb1en+Xhy5sBLwc79D2UeNk5DmawEOCP6xOwxyYrYFTt\nn4jJasiDywMCtTePUGgspxmRWROncwEy6IE0XP366blJFHN6+D+pOBaObKw4\ni96qogv/5nf82NYceYgo1EqMvpFYj+zXnyN3Us/zBhMxcj2uwt5dCkVRUjxd\nhbR9\r\n=L+WP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE3zl/AZm9D4xF0+0AkKxaihM7yV0qRPyZDgA8GTk+i1AiBi5XdOvu0kAnW89Sy7g6Ts5HfCqehVLSQS0nwBnQH+aA=="}]}},"1.0.30000902":{"name":"caniuse-lite","version":"1.0.30000902","dist":{"integrity":"sha512-EZG6qrRHkW715hOFjOrshH2JygbLfhaC8NjjkE5EdGJZhCYbtnJMaRdicB+2AP8xKX3QzW9g3mkDUTHUoBG5rQ==","shasum":"74eaf6ed7f1d31e5148725081c9df60051c5e2b3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000902.tgz","fileCount":762,"unpackedSize":1251387,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb197gCRA9TVsSAnZWagAAN+gP+gJIejLYpGnBK0GlC+DJ\nw1XvjyE2EoFT+piiX8pz5Exn16SWfZ/SOPkiEKyKG8ZwOy5vxojRFYWyog5f\nk72ibMLXCyX8Z8/CDT/etreljlht+5HWKfRnMdnylkVOFSVflREwE6dh9sRw\nZL4i+7U9nyaCO7TXteJHSbU3NB13n/TCkC8aP2h4G5LZQrgIHpnhiQBfkZd9\nM1tqReqPrD5ugHMEOCcvrB3wVvRoaPK6MUZDCflokk7vU6Qhiqqz60zPcrRX\nNJG7DmV9CUu3gzREbvcaTsJQa+TsKqmIxEriAUbxh5vi0481pHwEDY+sc5Ln\npGeajIyoubd4T55RFBgyHyRW4vbSOPZ3Exy6oYrFTLIIuyGTyd1pMHgldCLO\nzBKnRXnTIKHdot6yC20pr1tDSEfPANwA2PZ+GXAFfQS54ZyEHHSWhL7rYB62\nYD2k1y7zYKf7YFWey2pXtAEot4VKL7pnwX/J3hRTXb//LEnBz1kxUsJw9VnC\nGJT5WQEfadL5mX31nD3a1rWeDfsL+fI3dTZQSgcZ4g/oefe10Gi0PirTXL99\nbU10XvwEoIwOnIUuSZZ05J0CXxAMWjCVzh16dJrUjXYfO0p3+Y6Cz1VF3eE8\nLRJZQ9/I0nKcS61Rr0Y54vHuJi/+DaQEgT+LdyGnWfM07HTvF4SuiqhzDp3W\nU7dn\r\n=JZyw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDHQMvxCUiIUb6DYjd13xnK71UFF8Ctmo7/JHATTOermAIhALXQ6eeyEEXO7haJR5YGm+WwHVAXgd9nbfMHqEg/t++1"}]}},"1.0.30000903":{"name":"caniuse-lite","version":"1.0.30000903","dist":{"integrity":"sha512-T1XVJEpGCoaq7MDw7/6hCdYUukmSaS+1l/OQJkLtw7Cr2+/+d67tNGKEbyiqf7Ck8x6EhNFUxjYFXXka0N/w5g==","shasum":"86d46227759279b3db345ddbe778335dbba9e858","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000903.tgz","fileCount":762,"unpackedSize":1251453,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2T5yCRA9TVsSAnZWagAAPuIP/iyCOA2XL1w+SUiAzAOS\n+aTFLFhZvj1jA/k37oev3YsDXrFX6tHMC5Xbz8dhwv7zTR2q4JypqmaIm/qP\nNqSQ03Hghef9b4ddE6Czdui48ATBf/L4OBz0DFM5gHAVpYhUXn7smHiGmB+C\nNqUq3h7C3owVnXZTG5R+i8iQvU3B5XA4kUKMcINJ4bd93B4ztAlVaaBdTgTL\nFHEJrQwWtvJJrit5d6WEYqvDlWuIJaBa0k4xQ2RVvjTDCJZTkGwqeRIUTCqo\nw2GzILgJLPqwQGeXabYbByyCWbS+W2+e+eZjrETF9ewkdWMpLwynpaWnDYjH\nlblmOOYdKCSH6mrdymhQh4TzpXLBRAUz3RqUDZyeMCZEAw3Zh7rXOI1cb6MU\nL81MYy1Ox1EAIcbsBUXw7H3OedFn5Qox/XphOpJZZkFeWIXR7NQU3ginkB44\ntWsAfXamaiCcPOesH+zcZcSaV+C2KGeXdkVTPP27bQrQ0elBzuzD3oI5dovl\n/l8e9jGPCgqIGA6fYvrPkH4tALbay5VYA3AUnlchlEn3MoJnOmoyWI0a9Myy\nkXrmuJtkA281wjbn+Vlj1iQIvXo8ovZMKGf/0oIwxRUjwoqma0MFX7V/XEbD\nZ8mqxYGSVMS7XsB8IMh+wzKZtP2VNeyiTKj2iBcWjc8UcIvPXItmaHIVoiFa\n3ANw\r\n=gTVG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDP+PK8PXeIBBUkZOxJLLrJs8VsLkbWkxWd9WL9ZWEYLgIhALOWvblwAey0bkVHupRwYdNojO4Hq0IacVqTHFpj0aRV"}]}},"1.0.30000904":{"name":"caniuse-lite","version":"1.0.30000904","dist":{"integrity":"sha512-M4sXvogCoY5Fp6fuXIaQG/MIexlEFQ3Lgwban+KlqiQUbUIkSmjAB8ZJIP79aj2cdqz2F1Lb+Z+5GwHvCrbLtg==","shasum":"4445d00da859a0e0ae6dbb2876c545f3324f6c74","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000904.tgz","fileCount":763,"unpackedSize":1252475,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3UEFCRA9TVsSAnZWagAAk3kP+QCD9dDwF8mw9FNV1lSy\nLhaJ692RfL8bjYv25e9bqMvAJ82bo9fIBAnGr/WxyY6O1gFQoi0ft3gMjb3F\nHhwL5rL9/0OYYOUyStnEsL1PfgO9/3tZHcym1qUtL/9PareiBFywC0iwQ0t4\nVnWyH6nxqKlwwdx5bmUBBzq/16NFTQaUzfjALJ/uF7o5bID+XL5IPVcUDsCx\n9VCX9fbhFQ0jgFbxkYoqJ+5e/S12SKYVFVWWfUUzcIJQiXXBehVIyGWSyQcS\nE4AABbMaXuhlhLd4DpuTtF/WdJWv5s4KYu4iRIgDM5D59keaSYQFHOThX5O+\n7elVyP8wiCQduRzlDPOnvjxmQOM7loPU3CdV0Q5Nu0lCvZ54sh7FkYFE07W9\nHUeqONGc+CG3abB1SV6bx0mpqJ7853x4SG/8rzhimjAfsYMjVN7qkmPDmX3G\nQlTH9HJwPcg2TFtis2wn3s1Azvo16ucrpHQEIkMuGMyvMPcnGjKQq4HBIbG3\nNattJ9JNmg1erl9Tp8/ouP/3kLds85p6Wgr2Xz3Px9/L3Sc0bT/R8iGmHHm/\nFa1X/b11zePzHcaj1NVlApp2BQ2fZ4KH+pjfccEEm/leZfjqCJD3INSbIrpn\n1g2Hja6gNSqVRUqDkXEPYDWWSc4CJOR8yrDolsJ+Zv4OrdEWWvNpQtJHjqtK\ngIAN\r\n=s9ph\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGlyxdQo1gZcbDl5AuAToJ5nX+4IvQciM98dhFO8DDstAiATSBn1EPvehMVM7BdWZUEcztsrhWo0F1ZCXeAdQpMHjQ=="}]}},"1.0.30000905":{"name":"caniuse-lite","version":"1.0.30000905","dist":{"integrity":"sha512-cR6ICguvhRrkAjFfBoe54vJQMVOEz7vFmqrV6oor1a7GRg6DdswI40lkiV/QQvAMb4txzTkjSaLaJaiAtSuQzA==","shasum":"8f731ecf5b8553c7154a691c3df3a635a1a3fda5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000905.tgz","fileCount":763,"unpackedSize":1254050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb39X0CRA9TVsSAnZWagAACewP/0vUvtZN6yo1tF6UZoE3\nURdtygBhT3Iu/I9HABWXxqu6dlwdt0laWEQBf9D2c7fvsjMuMoh4tt6TLD64\nhv4dWPdf875aqFg8RDEF6vNx+aknjg8ebEUCVeYGmVsyuTOQW24W46BMHUlB\n9xiPvswuCDy4ffRLj3PZmrDTj9KxfogZ6vA1W00sB7LIb+N0Oq6478fddqKF\nJoqMPeLtdmV5U3nftP+L8hbrUVdFoY0BcIXiJfjzRXQRjITg4V26OoEloD37\n0PR7dR0Buj0CFNqtW9OebPwnR6kL1rp3maHPjE+Ny7muqnxt/Kght4eCHJX9\n7UOidWt3TQUMA3sxY1tMBkbr/RTtOO2yhNvc7M2zhyB24M015scm0GeK8Y+R\nQjThFeTMOB2f2EPyZHn2/SH8RDfuZ+SvF0uRjeSSYwLFMUzHJCvKr5Y3BKrN\n1RK3V8XBMCG0QTD6/FHKY1MwKtnLPkNLjK3WaMeD0t7KOmEfTkjGw63lb5TY\nZ4Hlx1p4uQ2S+H7CufEBHcCkQqjCs07bYe4bnL6SuZoXYGm4ofKq4LS4nwwo\njNQ0ZsMoL5iu3HSq112iGn/IaS4SLx+Q62yqfxPGOk091X8ciSY/JswdfUIc\nAQaXNnsrqHNHnyzYWs2LhRGHKTK3pWzm5IVnivjV2yiEqI4tHeAOxf65c1IZ\nU0T5\r\n=hQ3p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGd6ZbRJlQWzCYQGRyjIL5Y5ATUOdzSpRafoaFg+aZe3AiAa5TyT38cB1ZDe5ID0E4qqUzyO4HVzBZkmr1d0Q2iiOw=="}]}},"1.0.30000906":{"name":"caniuse-lite","version":"1.0.30000906","dist":{"integrity":"sha512-ME7JFX6h0402om/nC/8Lw+q23QvPe2ust9U0ntLmkX9F2zaGwq47fZkjlyHKirFBuq1EM+T/LXBcDdW4bvkCTA==","shasum":"7c44e498a2504f7a5db3b4f91285bbc821157a77","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000906.tgz","fileCount":763,"unpackedSize":1254122,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4Sd2CRA9TVsSAnZWagAABtsP/A/Na0UePhK+RFwL28KR\nTC7Cb3kMySBrVcs74iTgPf109jFaoCdvmA/t6XYZMd9SAEpoZKLtzyzpSeal\nMSn9b8XchfMzQauMzFT132Tm7aCXMkj7Mmyc2i79pFBfJMW7lKv6OUIkF53d\nyBOHIQcAI0CV6vdRs560nF8q4fRKkf9Q2xNAvrkGNe+CT/s5+jt+zR5qnJ8q\nekg+bkA5bDPjYv8IT6m1QgA0cwoSCp2xzmHulFp/1hQfOKQQB8FGRTHStFzX\n1VQlvN7M+HvpzMrV36/1uzTEJH/ZAKleQb8hAeHdotkEueXlmwHGGqc9qxwg\nbp8+PJnFIcCweaPOTSWhePcs6MGE8ZQaZ26Iw9rdGE0r5dwI2LPZwy6tUAKN\n9WzmxlPgO9B4Fo1L6ZORuHLpeXeXvL0HTKhohBQPus/8u2yaI5H10jhcsF39\ncYI6eRPYuM96cWYyCW+LS8JNu4O4f2jTF85ipGUvjmd/dn/QXEe+i4s+nNeW\n1dtNU4jCv2fi5SQ55M4gKbdkhC71Qn48ppwKprJ73O4RjalUptPdV1ytM/Bk\n1JnfQBKsEcjSza8Hf4bh7WyxGMa2wKv13q+HCdVq3EM0VDufyYlHE3I0FFpU\nZJ45wMFB3yunSzQF+pq6DREMtHnW++3kSYWOjnn3ZSEjwpHOBuLlzDUVwneV\nhOmu\r\n=wa4L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD51EldX1zobKnS9t5wu2AGGW7/jJ/zlQ8Y8i7Yp9cH2QIgKPKs+Hodoc+laf0eozw3bPivqQjubb6VCAAwrGaXbH0="}]}},"1.0.30000907":{"name":"caniuse-lite","version":"1.0.30000907","dist":{"integrity":"sha512-No5sQ/OB2Nmka8MNOOM6nJx+Hxt6MQ6h7t7kgJFu9oTuwjykyKRSBP/+i/QAyFHxeHB+ddE0Da1CG5ihx9oehQ==","shasum":"0b9899bde53fb1c30e214fb12402361e02ff5c42","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000907.tgz","fileCount":763,"unpackedSize":1254216,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4+aUCRA9TVsSAnZWagAAFv8QAIGxazES5jXfwXbS2aW6\noBbtWSVFt03NbxgU5Fq+6n+F9jwKRnva7tsXt4TDu4XB+rNKwmZqvUwwrHa5\n5yYk9ijeeTe6Qy5dyYvWRXCRaandL8SE+MMDyAAePN8u3VCuRKNUkiwt+J/N\ngRkQc7fC3ntv4fuxh/+Tqd2rFFzJicrrBhtZBKmFOJibzPMC8PKEnBWO+Mhs\nZDYXWIBFnWWr7RUCKyXY4mhvOvJJhA8dzUo+B56VqQRbruJMa0OgyoTZS2iV\nZ9xqTW9c4ikH8SofXdKhHkTQXRhWF0uKFV0tSnB5Nk7BQE9yrpJj4+9VE8JL\n26CPs697FNtmeK7SnOEA/s/uDfJdTptcg/CqNMdbSrzyyMKwKpNxUTSpDtoZ\nct0TCY6+ZjhPgXdlxga6mgS/7WVxjNzmWmBYMwjBeicHi5HKboy5+xtI1hvD\nCYVaT/AQ40DdLbv8uzkgmvkisEKep7Xxkv5O5jxNi9Yl/FxI483FFb/mINh4\ntyOeTzJNZpG187bh4FBOtkMRrMzrULf4KFuOsejjy6lA5tagZ6YRF4tXaptf\n3/LJkiblll6/jfZPxbK6nLxCZw50ibMJ3dDBK7mBhzM8JFq6OICRnwvXAR3x\nLCWIkZjhk751eEVn9g9G3PfE03C6M5rss0UBp7Ow9VaApuOHXco6DHcAh0Tu\nBCqA\r\n=Fk47\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICW0TnGQfbyurDttSsZwkjah2HODcjMqGUiS1H+JlPDXAiEA/vL32abbtFwpxaUbOOeghakBYGo+lkpQLPImNBffqV8="}]}},"1.0.30000908":{"name":"caniuse-lite","version":"1.0.30000908","dist":{"integrity":"sha512-nwoacBOIvDxalaLVPSEQJK/iYh7J6ZV+Ouvbs2OLTQcIlcZyBf8rw14ah3FA1MQW/T30vsmZkcZClHteyo56UA==","shasum":"4de28d9353715cbc06b308b53f98a89a9a44e4d1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000908.tgz","fileCount":763,"unpackedSize":1267999,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb8Pl0CRA9TVsSAnZWagAAtBgQAJbGvhmpeEK8ndQRhlJl\nzPtgMAVj1tOfCB6Rt1bNg1zEMSIFRnH7AgVwKUglDGGn6+Nft6oTF3j3/PSD\n1O8fOlvUVvwI3fhXFlJXQih2p+aFLj/hBNj+frYX1Ss7qzxIotTq3cj2oUi5\nCIRiaTc2NlM5lKh6rx7GHhAgXcw4uBnrhNbNEGAFUX/OWGEuU1Pqq/g9uH+b\nrTSlvfDqLc36MUvEorD6yUBA6HLlWqyntTCWg+W/T+i0tHCBsekXs+59fBsj\nYn8eVocHsLcJ7KximKzdo0HtvFN2o1aJCIiVEPsyy91PsRuwBwXoY59kz6M/\nTTD1a1bVtXsoeLb4TW+2vtZICaNOuupgopCF+IFWaea8RYzduVTFFrUjP+Xn\n5/l7MGXVbeknh/XRSxRsfPojBQVREMlXIwIfRz+qjWVphfy1kTZNVT6FcgZY\nTsMVbjGtwX31ujon6hKfZf6yAk7L12cWdiAiJtiXECHfUXKEKnERacYrdz0r\n280cVsem9Y3ehpUIkHHNmgNrHISY0jXcwM3DIoJfi3pAhi0iwCV25bFlCopG\npHAYuoOIJYaFfWTIt8CA5Ic8xsS694IuYIgno9dsXjqRhpugovP38xTX1PHQ\npe6K0FcOAyJsnieAwJMkPEpCcONbKB5L84gRouMeVETz7IKPu+/4KB+Nrs4/\nsLCE\r\n=5cKE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHjw5+X/hrb7Oi6EIFPKNsfS3UseU7p9meB/YVyPEbN6AiEA72Tt4TlYiIjX1Ny1DOz5RdfIbE5DuSXa9ALWsP+e0fA="}]}},"1.0.30000909":{"name":"caniuse-lite","version":"1.0.30000909","dist":{"integrity":"sha512-4Ix9ArKpo3s/dLGVn/el9SAk6Vn2kGhg8XeE4eRTsGEsmm9RnTkwnBsVZs7p4wA8gB+nsgP36vZWYbG8a4nYrg==","shasum":"697e8f447ca5f758e7c6cef39ec429ce18b908d3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000909.tgz","fileCount":763,"unpackedSize":1268080,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb8QeDCRA9TVsSAnZWagAAIMIP/1LZqA4Pm1Wxb+Hh1cK4\nCtiK2AnqfhvgDd+0nva8snye9JvIGsBm/Wsj9K34VgroelcYDOjumDfyYlWF\nN8UL4HapfRbuPxO0aR0XCyYrtHhF5xURYhM2IBl4aYL7fY3Zlme2upERzB5n\ncA8aJVL73oHXGRPLRKLywxW4hw1qOTU9xo1NSwRaquvbZ6+LF/0uCM51WlQ4\nST+O5TJqV5MlAMGavNizSmchbNbvrReEsbKtt/6ddg8Rz+wqeE1pUOdOXP8O\nvC0QIsqchMitm/mTf/KyA2udtGCs4gwaKIKqrvKiCRJaQWgCEhgXRkupvW5e\nqGWVQurPSSMz/HHCBpqQS9t3EJqQ3MC7jakrcLb/Z87hhE+zdjommN4kLYnK\nRI9hohwtlIShyU+7gSQfUGnZybsewSdPdl5TI+lDrL/4J8HjwsHpJkaARa1K\nzX9w5Vz4gpAk4+nLv2hLxvvdWi8LV5Ow1sBEKlIIFWdNtslxI3nOWNl1DfIh\nLVfZD/2aF/4DYZDuRNT4zHha0mntCBZb2T/BO4tWGqC+uaFlzBJwV2gIgWhB\n7BRqMk+W6cV8//eM3ohxztVNVA8LJ76feiBXHc7QyPFoy9JDo9SvbCfu9l5+\nj+4BxALyqOB73QGq63QWbUnCumGdvy1KV3erudyInpRzRoniZLCUck/ESH83\nOTAT\r\n=A2mV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICCGETYwhBFlzJdk1TtfEGvAO8vcUdppTSW2nDfOiDnlAiBX6a/1A9Dijh3jPLyVYweY2TBP23tvRJCxF3TFaC7bOQ=="}]}},"1.0.30000910":{"name":"caniuse-lite","version":"1.0.30000910","dist":{"integrity":"sha512-u/nxtHGAzCGZzIxt3dA/tpSPOcirBZFWKwz1EPz4aaupnBI2XR0Rbr74g0zc6Hzy41OEM4uMoZ38k56TpYAWjQ==","shasum":"755d5181d4b006e5a2b59b1ffa05d0a0470039f5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000910.tgz","fileCount":763,"unpackedSize":1268171,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9PwJCRA9TVsSAnZWagAAFMkP/iytsVtV6c4v0WqCX1Ht\nJyKu6iyJmlkG0pCuuEjGFHBCdKdFRCgmL3j38jZdJ2guBR0Yu6rxlVQXWPGT\nHS10VUPRIwMIMtxs2vNbnDNkmiLy8TNTYwDT2U7LbkrZsmZjr7+9eRYKugCn\nB1M7dJDp+y2fXcUmCRWacPmoJlsQ5tFmJjMonYxFC5DqAmtJ9Aie5Hn7rGrc\n2v0ixQdRg0pVX/R64fu/jjWzqWrBMc4M31crlTbj6Rbd3pzYWGHexO9KlDR/\n7nofG5gwyCc80xNbw5+SAXGnAdZdCwR4Turx7Uc7aAnQazFhorBY0Zm/3RMi\nUp4btDbNbsK6QamuvnivVk0mcREgY18oU6aL42IWpIJJNfhqYk49PQemkywL\nE3Haiqo3sgJfmiUb4c+0g/DpprVk2N48KErXxCuLTX3kSFNRz2pBPpyPOGWu\nrk0zte8LJq89zt78MRLLg5HaFGHrQvOroZHVkNqJL6D/b4dACzDM8MnIHLa0\nMAWYnIqvUHa+JkoCAAF0pfQLLrve01ldcRv0OR6jGh2j5R4CpY87S+f/HTzC\n7JumgH5iZcf3PaH5zohwL8vfiX7O5t4LUysjchTQ4Mfi5HsYuHZAnSy12pVV\nh3M367wLnCn+Xapx21sdy+4ViI5lEPydtZzcj5jmcp8AGJn/QQiQmVLmAgX+\n/gWd\r\n=ezAl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3rvTY6hO4QR07835Woihu6E1iYDf0WH1xZXhcd/x+SwIgTYG0IFh6pLP+vXG2h+RulXytp+JVftMdXr0fllqY5Og="}]}},"1.0.30000911":{"name":"caniuse-lite","version":"1.0.30000911","dist":{"integrity":"sha512-x/E/SNwD80I0bT+fF9Y3Kbwo7Xd1xSafCAmFlpJmaVg3SQoJJOH4Ivb9fi9S0WjfqewQ6Ydt1zEVZpmMVYNeDA==","shasum":"5dfb8139ee479722da27000ca92dec47913b9605","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000911.tgz","fileCount":763,"unpackedSize":1268238,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/OUFCRA9TVsSAnZWagAADk0P/15SxP+1GyX8u7RWqnS1\ndJV2N1knGFQT7j+3G8uMwVha85RpsgRTO5r9cCKTPb0pPAuQ9btRhko0UwOz\nSZEe3/Jh0dbwzwhXY+ZUlbg3iWK+4f4zdES3mi31Y3hKgbjY6hagWGwEMnpe\nHgRd3yWR3IxOqOKfWJJzesbyN60kHNs2M7i9Q63lITKN/rWEr8lGs9qtf9Oa\nrod1g5DdX7vMbjbXnocPi8q4ABQf6rR2df3V5el6r9dcwnsCEVIeoxmpUIEq\n6IkwLMLePsiS3+vDaQHhfSZbc6eLxWzuRyRKN4Rw9bQS3Il43vupctLTGTeH\nN8CEP/vCPxq6Sq27Zvrx0xOCc+XndRmGcTohePE+pQ2spXggNgbeURdOQq8T\nhf5GjCoJd5EHPCVRCEGgtQ9w4ov4kPr0NVJy77PD7azJOLpaFpPIGktEuQrq\njJN0LNf2u3JDYD3h6tU9MqMMy9XOY97oGWUvQP9dwa+Y4iy1O+HSXcxE58aa\nr9pkeIlVtbuY5MX8CuN9spI2MXnuJIJaiQ1Jx6E3ndoM1dmG7iQ0Dappg6qa\n4YRT5Wc4YQkAhgmgQZls5+As1dRWsHaS4hTnDuMCAXKzEDGYCJM9wsP1pT12\nbp9FcjRuao0f+YCztxr+oxGIg8I7qE0isxqgABqhiRITEAxznWHLOXC/SNuP\nZ4QM\r\n=sZax\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGDWU7qdi0I7RRUSzb8SERKUsilJMKLO35SG9mrLr/z3AiAgdgBWzIfV53ndAQwKfTvlU83ste+y1fEESEZPa6wReQ=="}]}},"1.0.30000912":{"name":"caniuse-lite","version":"1.0.30000912","dist":{"integrity":"sha512-M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==","shasum":"08e650d4090a9c0ab06bfd2b46b7d3ad6dcaea28","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000912.tgz","fileCount":763,"unpackedSize":1268263,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/WOSCRA9TVsSAnZWagAAyN0P/ist2mQ1GWpwae0mzhjE\nHFeMlk+qkQACsbT+jtkPwyVqZdDoQS3OHbEqzDssm3lKDl0F2d3/Cez5o1o/\n/Jz35IJmNqWoaP36Tou3c6LqBzEz6ZVPP3it21WrMwMyOC0dSDI7kXtFrnPU\n9ToboTIaRdQho7RlqJbFRNCeoARhF0vpx/P6W/6TDPudmgT3B/vvCZ1Og8Jw\n0U8aqybXRX9uCwlwINTLs72lG+t6RqA+eGAtVxw6QF2624ezfxo72KRrIPgj\nHKuaRZkOw5vQlBM2gbPQGIySaY1wzvVU/b0aMFzkQH+xgMmePCxHAVa9XgJg\negrd94szgn2ReXOqglx1Y1uBlJ7qBTOoWwMOYAInc0yWlABty99N3f7nqlp5\nrj/e27d8AFHV56VgJ06kDq5lI5fqAUVTrPl/IL6ArELZBRZnFFMhmFOfuOIp\np5QIwhF2cqcFk3O/sm45umnbJb1nvS6Y+sgpXaTufk1U1ANjfkqngB4jc19i\nz45rZvsogsGZoUlhGVE5gDBBJIvFoVHOmPPNJukvfTfcmVM+Noh7nhuaTC0R\nz9WIu90GIXHmPcZd4d+XqkjIw6v6Jud+H2AtBiY+t5iFHiV1ddIEJPtI4JO6\ntrdcNhOV3eqNKrMd9UAeLXdJ2buzQ53ErA9pjlOF5Ow+E6xtAhRTCuted+e4\nJfDX\r\n=X3N1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQxM9U6IDsFSiRGGu+C3+G5S2PjCx+IIxxdYWw7vBnFAIgO+rRmY3kdUAvh2+W6W8owbR8eK0Yo/JzcI9GYQlRaEo="}]}},"1.0.30000913":{"name":"caniuse-lite","version":"1.0.30000913","dist":{"integrity":"sha512-PP7Ypc35XY1mNduHqweGNOp0qfNUCmaQauGOYDByvirlFjrzRyY72pBRx7jnBidOB8zclg00DAzsy2H475BouQ==","shasum":"560311ecf242eaf12159b720e64b11ebd759b5e4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000913.tgz","fileCount":763,"unpackedSize":1268403,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBNwVCRA9TVsSAnZWagAAPJIP/j7FUKkAYUJHD+NXYgtw\nlELr/NCx9OObL4NknTkn1ToVs1emhRx6pEQJFdC1G2wbJEhm+ziM0zd1X7J+\nT9WkUDfDAJcw0COHVqIwKg6+DyKFbVyuhQR6gzfc2XXZd+Jo0QaPqLUCpbQT\niqIKifDLLX4Bgxov9ULV9FFd0or4gMg79M9NWlpPICek4m1ajoQGIevP+Qr6\nf3uGVvBGBtAWb1x2gyZ8E1ELYQOqvoe7sMAO1v2Ax1xrQ4xcrQF0nVv/erPz\nftibFaBz90e/p7cfB6ceIZtsPbrqq0FCWyXKEa445rMm6W+c0UgqdbrdGdxV\ngMSpReQp1e7kftlyXBOnRAcvTFIWdrEaVxzjUbEdf9rib+IkN8UV6s9YT+Tn\nYfpfU54HxSVR3/VnHCKyaUIK2ZqZFTMCexffUGtDtJl7xOCQZPbAJRj+tnTi\n/HKPBkLOmKb3VgG06C97b0S+2UJsTPaiuQRrKIWi9UC4KfaDtePfXE5f9KMV\nLtbPpS2UEeNQfapkXsU4BMGueRqBGGSIXGcsUFGcRKVF+ZYaLW33Kv35/4uk\n/jayBqjwF8MuBOIDmPVBM3Iufwn6QIyFZcEzkKdMy4Il4UGwFS2b0r49EWC+\nQK7EuZjliBI3uk2yhaRwuq+7cYng2EqJqxfCmugymhKvNiZSQNdtbWCCuT37\nIwyu\r\n=cK/E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDghZ6KEq6nmAfkFUkOG/LZyT0BPlLI2mtDVZu13OqheAiBwKq4xmohjvAS/7Yfe6B+P/D5TUMd3CipdzdQ32nc0RQ=="}]}},"1.0.30000914":{"name":"caniuse-lite","version":"1.0.30000914","dist":{"integrity":"sha512-qqj0CL1xANgg6iDOybiPTIxtsmAnfIky9mBC35qgWrnK4WwmhqfpmkDYMYgwXJ8LRZ3/2jXlCntulO8mBaAgSg==","shasum":"f802b4667c24d0255f54a95818dcf8e1aa41f624","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000914.tgz","fileCount":763,"unpackedSize":1268469,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBh+HCRA9TVsSAnZWagAASRIP/RPvlzTsU8uJAEoxztwe\nRXfF/A3fOFNQcH4T/rqwt+fEEx+dYRSXds886Lip7Ad9AX/UK+az9eJooT0p\ndPyyC3V/p4L6plsfUeDDD99Me7CqKwxurXXAz611AWEi5d3vNu8+dpySqcKm\n9jhePbekdUrQImP1Rpgj5iybaLMn1yspbt9+T9s+g2nC/CaG3R4ZreBwECs4\nR9BXmmfNMaytO4sswWwUjW5bcZEcDzPZac6IUms1Sq9j43+loc5Ssny9oYxP\n2+UlPQhlpQK5Ka32rzDaMQhJqVx3R+I4W9sMDFsZkIIPXL97HxUo4+eHjIVi\nKpHVYy75PnMKVsanfjAlsd4ccPIdRfz7h+3RZdlfiq9wmZk3ZMi9uvl9uFgG\nOBHA9xqIWVuR3r0uAchqUM0J/aKJ/He3bbURM7D8SGTVVuj2VmJiANxAXjSU\nn3gQtsqK0+LD3U/8QLPbkxp/FE1agASjWsYN4JiOUzfjNQKsV6JiMf2NTflU\naOsLU/G/qrcQAbOFsJ0yIS0qfj6Xg5E3ggL2GaivXpgE/BIIdPWfuFsC97Ct\njFdLeejNnl3BhUF8CFDVSlFYsAEzCIrgf6F4yGRUXcplJaB0ofisIW9nXmwi\n/enTZL1Q23a8cAqfmi/PHWjidi8sH1ApdS1BlJHa3sIhgHfOw/LShuV8hTJD\nOo5L\r\n=TgZA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBSJNgwzzUx0w2Cnd4j4kUm94P9exXXBoW5d2Uidxer4AiEAhH7dtNhHqGSmqYsWcKpXrp0bIZdbOcfo2M6ivTyukXY="}]}},"1.0.30000915":{"name":"caniuse-lite","version":"1.0.30000915","dist":{"integrity":"sha512-6MmDHxeFfue8DYmcIKVosSK5ySNZxeZhsVEsGnOZREtqAe9EBYW5wKkjZou73KXMFlIcYsm1MdXSgRfraN79dw==","shasum":"62fc895e9517fbf871c81fb5fad109564c453be6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000915.tgz","fileCount":763,"unpackedSize":1268570,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCLR2CRA9TVsSAnZWagAAFkUP/jz/jor7aJV8juRYpUE5\n27h8ki5RhfbWuR7hCgVMUSRXRPL5fiWr4CSlVIxKJcG9VEq29PabvKMpE0vw\nS8XKaVRxdrOtjTr4o0H74gF4saI9jXwQg1UD0vh9Qr5Ohf9Lra9qWHNJz8/0\nKB7jlbrDv5mqViBUahuBIC215KbCNaNV8dBubeitO22AQDgJNe+dL+O0cQZo\n6ps8WsLZR1VLpL9mR0cwhbt/E6HiZt8uB+5aLnUhpXj1nc1+wdbzINkQZOET\nEL7I8eJrn2EH//g27j7hnntUY0D7T0QU/rZIO2e2jZ1I1AgtMcsJgBoUYTRd\n6gEmMDnqd9TTOGT8gYskjV4LooCG+qbIpqEYtN020bLuGZWmPpUBADWJYi8J\n6xqkTeMT7fHS3JSqBldGQj41kAtv0ZJJL1eer0e0K1NyxEUiVe9aTVQ9L7sT\nsb6Iu/X6IGx1gcxM7eTmEXUZ4ugZutNEE2wsBXZbaZSRz19bjKF0SMiLuubo\nANTIMYEb+dh98VA48hKU7F7ZtTZyCupJYtON+M92yr2119CccE7npbWc7daV\n/ZNjmlUaSdab7CKJOW15tgy2cTHgt4dh5LCAOLK8AN1uSB+OY+M/SzEPBKNO\nn0axZBe9s47sqoutXJFRT8QH/XiXw47wIEjAck4E+F3/sSH+9cM99aUZaafb\njnxD\r\n=xPS7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGdPn4dBp7VahDHEeGWBcj2/mRdJvDEATc4yGNezicoMAiBN15W+64CEbgkOGsS4zoOjq0f61qH0PpKTYDMzrgmlSQ=="}]}},"1.0.30000916":{"name":"caniuse-lite","version":"1.0.30000916","dist":{"integrity":"sha512-D6J9jloPm2MPkg0PXcODLMQAJKkeixKO9xhqTUMvtd44MtTYMyyDXPQ2Lk9IgBq5FH0frwiPa/N/w8ncQf7kIQ==","shasum":"3428d3f529f0a7b2bfaaec65e796037bdd433aab","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000916.tgz","fileCount":763,"unpackedSize":1274294,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCMKJCRA9TVsSAnZWagAAFC8QAKSrODk7DxvkSiH6pfxD\n5zmvJ/ierwxpW9+rsKb8wHSUvDQi8F1EEy/8+KNgVWLEna6DzxU7U/WCK8Wk\naehs9Q4DA1bj8IjkNt7vaSuDUGwQXrNZTZhKI4GPPYbD584TaDf121o6/OJs\nHaF0L2ZnQjbFUvl/UEuiwKz3aeAVNneXu8vOTkwMExfR9ubV2D98ZuGjiTal\n4vyI78TDtRnOT6RcOzA+NSb5i0QQ+l71DxiKm4w2L6rG8lzP0cdWA0bowSO3\n6GFW6OmdderKI2mVXIV6xe/wGSFqQVN2pxFOoSDtII7j0JoIMSuZht6Ktp7b\nY8LP2g5vNWyirRqx7ijoVMsRyz6Qnr3IpF0UXRK4ydFwMX8bdGG0rNgqjhdY\nUH1a8n29QiH4p1lKYsHch3wm0fPbVpyFNyQb/yxi/3/Y4u1n72SsEbHNsGYB\noPFEDbKoN9+W50Uhm/lKyjPcCp+wIHmY9is6bR22TYinHW0dYUGmLoJa/723\nU3Tn91jOShOvbPRqh0KQ8aeTCjzV6nOvCKbJNEQZrihBhs0YGDHHq5sXrUbF\nMtOvCqI76RW8Wv/ptlmOltapUm2HjmGAXCRHa6IMOvKdoeGx2Wr88hae9wcc\narTLUo+ZPIJHvaCgAOg6unSHhwshNUev5vuIqyPsSSnotWPqoXbm46Qf4wYl\nlj/+\r\n=hi/f\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGGXLbVxJ3eimoZ2fezuI1pJrvpbi6vh4xiJ8c3zi1zKAiBcZn/yI7HkrAg9xfOrOSgwt9neCauZNGst6x+EPnCKtA=="}]}},"1.0.30000917":{"name":"caniuse-lite","version":"1.0.30000917","dist":{"integrity":"sha512-j27ZOs81aF3yqPSSWcUT/0rk5ntnqyZdXYN5M0C7WX+8wSNHjioKPYrjDAJgL9ldL83RSSh+fIhyUa4np/5m6g==","shasum":"200bd1c3f518016e7fe900d3b261bff28704a112","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000917.tgz","fileCount":763,"unpackedSize":1275385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcDcI2CRA9TVsSAnZWagAAlK8P/j6lYTAgiK6b3B2NZryI\nObrN5UQ+prR3kpl0MvODTZkbVpZKXSFzlB8WzfHeB6/4Nv90pjR/tdg18ILv\nraYnqeBz+vjIAMtuXwfBX5yPJIGZTiMaIaxRFy+VYLTnQA9CvP6e/I1Rfiwo\nH1w3SGiN5qrkIcjnf9haX0ItTm587jpMLnV3rL/o+nHs4CWso0DP5dIqJsrN\nil8Ojln7O3MIYIRjGnrKYQEJf5QUfOspDaRJ0YJhz8T86aO9RdBK88pbz9Xa\nud2YIHfdSg3zELRnPslUN1VFQqnJmRgQtmPhPvi16g7yerH40L+7w1F6ypbz\nWcjW2qvOTxkYvg8dTAHhOs0KAlYSmRp9JZZpCz6GZxjdWxPbcuCFFGdxgXt+\nG0oj2MpDvsDGqhWNZHY4IqlsGy4pmOvdjCAusR2pL51wnzfB4HSo/aXam2Sz\n53K+qZ08Ol10ygSCjkfSHZXQ+FBUU/Lw1ekzp0Sqf3phb1Rmpy+K06UNLDkh\nqkipQqdYStd6ow5A2Ra1oL2UnrEgGdheTpDHcW+uLIW2gWQVsZpk7+TTlDGU\nq+HKRnq76S7/88zQLhAZ27H9KnF6jKsDI0VkZcXBd2G+tp6NDFMimrdakMFI\n44ikds5rn7qu+HBVfpohZ08Fuj0JnAkMqccFaleNJe+CJOUalPahxdaqmXyl\nt+GT\r\n=C571\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEajOdvNQBodDhG79J17/GYWh811HD99OIVRv7giDClkAiEA0SdDYFO2vxq9BRgcEqA/15crBuOUH/UdSV5jnmNed2s="}]}},"1.0.30000918":{"name":"caniuse-lite","version":"1.0.30000918","dist":{"integrity":"sha512-CAZ9QXGViBvhHnmIHhsTPSWFBujDaelKnUj7wwImbyQRxmXynYqKGi3UaZTSz9MoVh+1EVxOS/DFIkrJYgR3aw==","shasum":"6288f79da3c5c8b45e502f47ad8f3eb91f1379a9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000918.tgz","fileCount":763,"unpackedSize":1275466,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcDfpxCRA9TVsSAnZWagAAB2kP/3mdBH2b8OwERAc7b0PR\nMvEDNPiLP746WUNL1kS9S/62gtNZ41A0WejXS3DTIzXNJdv44R23mmNQvRgC\nfhKyz6obCQk0vaZqVF4uFvi54StBNThcWI5KvAa7DOVqB10CeuSqz6tmIgM8\n5ZUgBrzc8OwcV8B8oRtyr5AuSs/HTEaHTcLJX0Ib7amv/ELR57JCqulXBwlq\nvCeCtapuljI06lERJCNbNJz0hkl6Vf4Jdq5M2OPb5l1v6ujLpk8q8Sneu91L\nsLkfi4jwQz5kcTaHxljmoiZw+XcoWJ5n9YyjqaRcZmhY4wpIYqPvps0WVeWL\nb4HBoIK2lfScnvYKjF21B56KVavfpStfbcYvaHI/gdEjTEpPniEWu0Y73Cb6\ntuhdu307eSjJLeSmphvdsmveCh9bOsLNHQFe6soVdVsCNAMFrvLujzRvKama\nxLEcJgICbdhkL5GC1Rc4wvvF2wUnBSF+KsHwp1/BSPEntaLEfOu7GQHzoXhW\nMuCnjNwo3MuQFY7tifk3BsJItIM+NxdMCkCchAGIYRs0crGppl20QLts4rNH\ng8yjsLFUOAGV4opFIMDwBrIEhcIMNEdf9+ifvUOCbRHZJfrBq1F5iIENiV3f\nxV07V9CXNpReFiMU2AuAXhmUAf6KcVAqcc3c/f7Rdv1vamclNdhxh2nvcfkM\nGuFZ\r\n=+S8U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICrlyVD54P9LbNMfXbBgrMHhnoVT5feVXtUDXxiMhOBnAiB8fASkxMX8IIpR4wcwt4VaeDkd1nWFoeP/TREAxn4kyQ=="}]}},"1.0.30000919":{"name":"caniuse-lite","version":"1.0.30000919","dist":{"integrity":"sha512-1dBJnnYkBNWApXCSXLBXMuHqvDAOjza7nBrezhtQhqjFStC/E+MSOM207w1apOsfHiS70C38HipYD6SmEEt0+g==","shasum":"ddbb34d20103b210048ad725b47805700c4deb4b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000919.tgz","fileCount":763,"unpackedSize":1275533,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcEzJlCRA9TVsSAnZWagAA2mkP/0SJDsgnWZAF73cyVHTt\nX3EH4BI2ZC6xVXihtHKw0JZ8RvWV7bENeKNrtXf7KE7aREsjgxeYBfPB7zRX\nCs46Y8aXbnXqT3U7fgQ57VLKVGpPoWJxFL7CByc5mS3XkQYOAimYDn/j4eqA\nwyodlnLkF4bXB9raQZFVkD3ULWDtuMyIynFIYy5kjrUERvFIjFIU735pVDkm\nZBT9Rfd6AJ2gthAMJzNpMbr7kTDIMPA2H8LNRpNeV8uKA4BWdbZn3X+nt2ZP\nO7RSiIJsl9IjuS1nR9tPXBGm2m6bEdsMTOwReflXHgx+IFKLfhWOMBpOv8GF\n9cQvzQayRJ7zKrUw2bkukOVIj2cLQyUVNZ3iAay0nd3zLEodxdUJC89mtE3w\nO/gXR3DgqfoQU8BnhEeOqjC4QLTP+y54T5W6jJgOXjd9zuzfaT7zMkAYqqXv\nu4WeGuHpev6X37J1RHX9QDKv2ud0tVZkboW/1Tje+nhcAKwbJonaNhXs81RN\nmTV+C9ycg9fJPYGGT+GbShDR2UPo0y2OGOudnYbLgla7HvdNpA6i8CZVNtd0\nY+bukxhSdzVwOCeoUTP6tzsaCu8W8k53GEITJ0LsRMkBDEPK/CQfFcE68udP\nFVWDRY2Fec/B/hXsOIRK4DoWQcLGtxeanv66l8D6wh7pLMq1Ol2nuki036wc\nnl+u\r\n=Lot/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDPjH7AJksHsQ7/T15JrOKM9VEztr71GFouC0qsBdv36AiEAtN0wKVpVkPdCTPuilXQ43qskdA5QjXhQkBkBZhvm8ws="}]}},"1.0.30000921":{"name":"caniuse-lite","version":"1.0.30000921","dist":{"integrity":"sha512-Bu09ciy0lMWLgpYC77I0YGuI8eFRBPPzaSOYJK1jTI64txCphYCqnWbxJYjHABYVt/TYX/p3jNjLBR87u1Bfpw==","shasum":"7a607c1623444b22351d834e093aedda3c42fbe8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000921.tgz","fileCount":763,"unpackedSize":1275615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcE0B0CRA9TVsSAnZWagAAsd8P/3vuQn6fOYQQ6kFK0IcZ\nzKLnxqz5HOwXIzfZPlgQd0v15rF9eSzcOt27jYujf3LFxO+c1ucvG6t3PcSc\n8lB/0jih9HvECzG6zhEb5cvOPs9h2TLqYtZKcrTI4HPvqPnVlI80qD1C1tCH\n9Gclg6AVK3S/bbmYovzwCkKSTCNuELpUYmjNjyhDiNcAMo981A2JdneMAKHg\n8leGdZToOgjBk8daMkwoJEJRvYf3f2p0kjBAiWvPr6hX4Tndde1QHEFVXo0d\nMedREP7A4ukoxGiKMP9cGXe8qIz3Du0tddLZbiKk7j469nsNET81WXcIs2na\nvTCB0s3dG5+ZEST2msIN9eTYBEZzyYcR24JCMW4252ZRfx9fmaAMTms0geag\nBhiYIaf+HQ2R+9evPbQlFPrY6ztqoLOcrqt+YZTS5oe32RTvENQTSyrBglgn\nLGNBGJstqt2Gtvf0Kn8ZWi6TukAm+FZfx41aDQwVnV/as3+YT1ADNHGRjaly\nWo2S63VkPCkfUy/RQPDy7q9ePdJ0Cnlx30RCA2tsST5Zah4A5m+YpFrhv8+z\n0Je7rX0zvGAJdywd118t+yE4d9q3HXpalH6I1JxOtdJjlCgoCzg7aTGWuwy4\n1RIzbytQQwg4/V/k/kPwv1h1WvKdTJbBdo91tTyO8fmHOicgk09EOXbHGLdL\nwyIT\r\n=nFy3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5u0KLXdEFkv/cUEsxPkOIFVB1QURaxnBRaPBWk2BQ5AIhAPJgvhUOpCU8NwnGO2jdJ2rKl6IQDyUyMnct+qm9/zzq"}]}},"1.0.30000923":{"name":"caniuse-lite","version":"1.0.30000923","dist":{"integrity":"sha512-j5ur7eeluOFjjPUkydtXP4KFAsmH3XaQNch5tvWSO+dLHYt5PE+VgJZLWtbVOodfWij6m6zas28T4gB/cLYq1w==","shasum":"148f9bda508024b5ce957b463ae2e8302b451bb2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000923.tgz","fileCount":763,"unpackedSize":1278452,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGuMmCRA9TVsSAnZWagAA8ycP/jF9PtK9ksljx6WGsy22\nTlCTPiY3au23L2hDzNVHL3thTow3upE6qyIyd9PolqG+8dFWiBbyj0ZpeDrR\nEhrnQOocIrUSwcGeYvzjvGEBZRpTLID0M88eFuWInK9J+X9vseW736Cugnw7\nc96Jz8iFqLhL0pu7nOPsDA4K6dwpMLH7DJZh9PFsjImw/KCxuHX/2l5CKtju\nqVpBGrwntSFhwpxAmcbSjMft4IiCeiO6TTfeuwul/tyr1sAZkwNxJXDT8M4D\nnr1BywI5AXpTg8idekxqerE9LsytqNzyA9MCdbG8LeUn6RRwV9YWkiWk0fI8\ntdM1vVTo2fmAJOGQ0/+tjYo1+C/ZGqOyDiRSB24B8b4OFM3akKvMxnZ5zlPp\npRsUoO8vw50v67Fjg0KHY8dkv3m/zXj7MYGlfIvdsXilLZF6qIJf130H3lKn\nDXikasL6G9AQif+sYOv2Hwsk+aZrfTt79ydD6kjmykq2oa8QkR8cpGT94NFS\nKL6rOsIj34tEpEytON8vuITDbLzgS9UTG0oVlrg6R2LQxfSuV3fQdX6XTmX4\nBAzoKzx/tY6W+cWjzudVFpkw4NdZji92vF2lv+ckjenNpKzIjLkUqnwSPZ6c\nHSpR7njpuQ2s7mIPOe3E8qWTxQKg6g8yeGRZiXIQAU7Kml8yn4n0jujyAy/l\nwbUm\r\n=YXa1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBeL75zHhRNoZvJxgOH+b3aaL6nHn7bYC9Ahpwh5zyCbAiEAtoGKrtyFpM2YER7tfZLoty1NtUw59Q0pMUKbokHfNJQ="}]}},"1.0.30000925":{"name":"caniuse-lite","version":"1.0.30000925","dist":{"integrity":"sha512-zcYupoUxtW46rOikuDF7vfL9N1Qe9ZuUBTz3n3q8fFsoJIs/h9UN6Vg/0QpjsmvImXw9mVc3g+ZBfqvUz/iALA==","shasum":"f1a3b9aae2a83071b1eccfa39959d72440409b08","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000925.tgz","fileCount":764,"unpackedSize":1282586,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJZlWCRA9TVsSAnZWagAArAIQAI8dz/4jqAb7kGlMKF/u\njZp/fk6F/bD1J762W1pNi0MEnTdb9A2Mx/jwluo2ARJSwGsYTDg2CcUyi7Y/\nBGO+q/rnKT28kUvm7LcunQKmmPzlem17E3mchLy0drCCLIKfuA5sLcY/tSlN\nv8SQGtUMItmwuKfEUW5CT3DYDrAkmMO8xNAmoHdHy9fp78AXmm0ryuQYNzW8\naMxgQGisTAH0/y1oANjR50gtG6V5AXYzE8a3+gWaEG6tyQ3v1o2c5KMKtD+9\nho/36j05xfPD/J6ASDfuKQ1FrWnTkjNc3c5u145CCQv2QiOZQXuxRpwyr7J/\n55+dXGnqmMI9i/PF75TV9ZCcoLqHaSADufCLpqnffXO8YIkYQu6wIj3OalTH\nXAIXz/ji5INIx6U8Oz1xe6B19V/X1kjqQ/77+QDbjrD1ClpQc3IoIIdrKv3Z\nrFG9ljR8N+vgS/JG74oOEotiqjPIdeMxfIYB81jm2BpCBR/44OsqM484WSnf\nsiNyU24YIQhf3dnGqbdquf6ujMvvswjotPJuGpfLkGyHftekL0ScgpKh10VS\n9Ym9Yly+niB5EZu1ndzMfCGfLwD46F3JjBjwQ+VOWXUGMXQKsPQkQ6JegEWt\nDcZDxi+62pzDQsRvsvwOjxPGmtBtWvozdb+L8B/HRrO+U9KhqhdLO78Il61D\nD7y+\r\n=OFfz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFrHcOawdExaXPWrH+RyAc7tpjRlgGh1s6mxW/izgQMgAiEA7vh0SB/1JpSGkjnJSHrOGcDsYEGLGE9FRIThYYGKQ2I="}]}},"1.0.30000926":{"name":"caniuse-lite","version":"1.0.30000926","dist":{"integrity":"sha512-diMkEvxfFw09SkbErCLmw/1Fx1ZZe9xfWm4aeA2PUffB48x1tfZeMsK5j4BW7zN7Y4PdqmPVVdG2eYjE5IRTag==","shasum":"4361a99d818ca6e521dbe89a732de62a194a789c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000926.tgz","fileCount":764,"unpackedSize":1282679,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLCLFCRA9TVsSAnZWagAAEiYQAI35kKNFdVF4lzLDZs3C\nux5MM82TWrCfCbj3BxWcst0uBdI+lrrQjxEeLvlWgQlS7WE2ZUhrs5VFjqdD\nsWku9MkvwXbRNrQui2dBMrkM6kiuw/6WCjC5DKoKX9CrkoKzA9i7QYVXO5Wv\nkGMvqxtTg3Wi/l2NAZ4gXXw4tFnqMQuygRZsCmo2ZONuMgIrPy0cPbM4ACJr\nWGrQOq1JdzJy1H1uxQ6BrdXSA9EipOP/g24yyvbjwL1cZpcdpdKxnUfyNX4g\nNZgrtxHASfz2xbKlAKRsFjfreH5qKLvm9O2BLS3K6bzkPmvDW8Pmu7C3323e\n17tgE95BZFwkYyP9GLU01ZR7P/GZnLiMnJPFwve2moNQxfr/qp52hDFejufu\nuUZmhjM06RbtIghANHTEcOFS+GafEycrXtOBAjGkFiY/c3Z30LYMlwJUhhpb\nhtEFFyeV2BiWUkXpyNSZNWsZ5OTlWGjTMUCVLVsw3D7ks26wKSLkyuHLQrnH\nOl1GiyiUOm5e7V17iMiUKhVV/+od31QjrD3J1jR6HGp/EL9boSwhJ+6GFxJs\n6DXb8GV8/Ps3RuEg6NNv6oLnIdLnAbvAeHKKNHTWIQfv9mk+dlMkqbDAhwB+\n4jP6Xr0jUEBBasB45FCLEtFsJ1mcqIer0khC/ai7QA0ktL9R8i6VfemwS1/6\nEGzq\r\n=RWDC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0EqjdXxjL1NEEe5jHzsrFWO8Nu3HZB4fDc1UY4E/4BgIgG5wDe/8/5PRvgYlsa9AT0GCkF/joHKRf7F50ERR1IFI="}]}},"1.0.30000927":{"name":"caniuse-lite","version":"1.0.30000927","dist":{"integrity":"sha512-ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==","shasum":"114a9de4ff1e01f5790fe578ecd93421c7524665","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000927.tgz","fileCount":764,"unpackedSize":1282750,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLtPYCRA9TVsSAnZWagAAsLQP/jM5zIs/iE4qIb/IuWT0\n5VGDADPiRtoLeZSuXo0f827FLBuJITtV/5+gNwA7DlBQ1UFvgwW9E/GgZTZk\nL1T3OWyHeJMwyr+KNSgsqtt3/HQmqPnuH/Djc1pQNZCBSZPOcvotrx9jupTl\ngWxuddzqij4BnvVoBnIwPys+H3+gXQ93q7Jo7BV14Zar4veVlrTEpAlrrtfD\ndL/iNzVXmhO+Fr+3uiFYP17mE1c+uQ8MaszQZToiJnvS+PT5HDd1yqUA30cA\n2dXFhf6PW/jqsVuaSrfho8AIoHLBZqbnvsfF/y4AVhx1kw0WbSLrZw6+33lY\nH5DVdLviR7CYTCBbbOMF+CkeochF1+tYi5pDKH6O4Bro38/v7je16MKq7q5E\nZTgQKHRg/7WeEQnMglgq2Mho4o2ci2NdRTOo5jd0i4+grTE6vgGMreK1BWo+\nr5omsrUjLGPUKcgCauZ7wj5ZzGAAEU8peKv5c04cG7iiAKyt//Ztcwy7vmtI\nVahExt9aCARDA7ErxDpsDErZFVVt2/q0DHKjCB2xTtJH+CcUXxA3NcnBlZLg\nfAjkKzRapxMdlrfi16MWkKlhQ0qJoZBMujadl6xNIV/VTUjtNHPPpDZ7/iH8\ncy7adcans7rIBSrfP8lIxYm4zzTr9vCy/GQlFdSrsrNJN81rC+bON7O98xIe\nuTZR\r\n=U52y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZftYz3NZoxi2obemW1+l9bWPEDY9w+xfNgko0ZXviPQIgJgR/3j3iwNGKcgueCxiFa/fWrU55bq0hl6BM1NVNmNI="}]}},"1.0.30000928":{"name":"caniuse-lite","version":"1.0.30000928","dist":{"integrity":"sha512-aSpMWRXL6ZXNnzm8hgE4QDLibG5pVJ2Ujzsuj3icazlIkxXkPXtL+BWnMx6FBkWmkZgBHGUxPZQvrbRw2ZTxhg==","shasum":"805e828dc72b06498e3683a32e61c7507fd67b88","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000928.tgz","fileCount":764,"unpackedSize":1282838,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNucGCRA9TVsSAnZWagAAoQMP/23ztv4Y3aewh7xOS3Z6\n0xvrdb7vME5VZmHwTLi0hT10wWCXhlMlKVkLGwOn7h9QxR29PVz8wQL8RBdh\nZ2T3A+dWB7LoygQQvKi9ztUfgMHbJcb6+j/9c8TrmVDsMtA3YkYs4MbIFSXo\nXrMvohij7OG99Uzo2/LpAqLMTvqyMGOoiZ/7CMRHDnWP95u9xdNoqS+xbHJs\nPi3I0tbTnQmmz5zzYagBTjRBYgps+/PnNlaVJcwqCFZJl5GxWJ7ZtEaqAwx6\n1LiNXgnU7vsMGZ4vbU4bMVKkTC6ZfDiAjTWZnj4ZWjp1IJ+YXuIXY5FsrMmx\nogaMzbXr24FRKpLDz2TCQqo/bAj4v1z1Qa24x1BiZf3xQw789o2Y4hkbQUKA\nPR0iX0IMJ9TaAa9plq37nglYh73yfLZ7dEtsvWuMqoOfWlXADd2EBO8JdRa6\nix8Ai6ZhWtw4ZQr+GCIkx5OWKaW8NXpr5d7c+6lo8U2NfcOXKr2XR8iFY+vr\njvp3fI3+stRLX37nLsDve1tfqgS44RyK/dNMQ2Q/AK+6SQiBbCHAJjn+poeB\n+23s0ccORMLuCz0I42C57nZOaYK3zzCtKTsgipDULvoihk2tlAYcm5/9IMB1\nNHTodfcfFm/tg4foeZFMnxTbf64diP/BVCs6H3wrlOYYdIVs3rI5I8BiZOzX\ni0PE\r\n=22jc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKO0xq3euT4HARiQomK6rC+R3mQTXbwB6VCVwyfxKIfgIgIYpQVG4rgvtIyeLc7vt6SkQGG5anaEZJJi/dNyvfS7w="}]}},"1.0.30000929":{"name":"caniuse-lite","version":"1.0.30000929","dist":{"integrity":"sha512-n2w1gPQSsYyorSVYqPMqbSaz1w7o9ZC8VhOEGI9T5MfGDzp7sbopQxG6GaQmYsaq13Xfx/mkxJUWC1Dz3oZfzw==","shasum":"7b391b781a9c3097ecc39ea053301aea8ea16317","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000929.tgz","fileCount":764,"unpackedSize":1298157,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcPsH6CRA9TVsSAnZWagAAXmwP/jedbV3KI2QRQAoHW5Wt\niO8GafCxV0L8JCqnuq7HYT0t2mg13DdlGB3g3qIxBv4qCfIKHUYd0GI8+Qqs\nvuE3D/t++aL3PTfU3lBciD6G4XjqmJSwD6eXgEWgW9dv4sKg114tkj3R9EwJ\nQRAxI9p16sCsOsBGiiCevBMMkf54kyn5aQ+4aZS9M82QuaJW9dw2J859ppPY\nW5qKso1GRilvNhY/j1xCGEoSpuWvkWxQLJGX+kFWdztrjK5K5cQHTudVot4k\nG9ce5GB/35eo44JabMaLjz5kZxsXoJPsDxRWXu30mzkP3K0BJ0w4/MDWXIpl\nypU1EPuYcSGg8RFe0Fj144GV9JAchg4y1/OIcS6Yy2luLer50bYn9BGgEKRh\nIgFPg4DRxMSTVwJce5Vz7wUof+XkJE7sdfbm9fSwsHoHegbs23W799gX2p6S\n/MMEiTKMziBwA0QqWfAMb7goSWOrCooMA0Wv8t/yZp/W/lbqNCHQY/fSEAdD\nE1Wc9m2/B88CT9l/nQ8w9hnPYKWe/HOnQ1UG15wfCF1GFIV20OT4Py17/0G2\ny5hYf6u2oaPzCZq8yQF0l7dkqLIltcJ/2fJasI6AjbvvFPMplhLoDO4a9vw/\nK/wzbyksBalrOSrYW1D8uZ7ihKkCI/YgbfZVZfzWpegwOkVMkA+LyQHB4KkU\n9TBP\r\n=K9gb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAghsnQfQtaiTL+XyIJ95MDIX4dYbeFs9ACY/pu6uF8oAiEAjWFbtX2YjYG93tntsgK1x/4/YiWmDh9KK0+HhhB7Vwg="}]}},"1.0.30000930":{"name":"caniuse-lite","version":"1.0.30000930","dist":{"integrity":"sha512-KD+pw9DderBLB8CGqBzYyFWpnrPVOEjsjargU/CvkNyg60od3cxSPTcTeMPhxJhDbkQPWvOz5BAyBzNl/St9vg==","shasum":"c238bab82bedb462bcbdc61d0334932dcc084d8a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000930.tgz","fileCount":764,"unpackedSize":1298261,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcR/x2CRA9TVsSAnZWagAA9ogP/RKocNyHMMFJIU4pSyKp\noXkqWg3ZeSEH48m2NzfrhLqfrKwZINifWRiyyc2JHY0YwNs43GgqXB6uoGWG\nfJhZWUrdg+cdUPEz25YMixwLXoJlhxb9o2a5HH7F8MjCqRg355jt0mD9O2CL\nAq3v1j81zZPE2O7xcQkLSHC6SOLGiGMpcapjaCTIYyEumC+gG5zFncdHNdVy\nm93dHQfcQsWqLTWGK1QlAGZCMzSy+gkJt+YGGBZH8a5h+8hbCWpXDRFmColQ\nG8fy4CEZ1kHsXh2WG8ETfOmFLoOaOOTjJEg3+M1o91lrnzAHrFjzLOGgo0D9\ngUTUucxGj3cGqpz5pu7xAyr14aJ+BEc8PgPXrZLOmu8XcOCL9h+ZL65i7oCB\n/Lsa8zF21XeGN6+eG/CtJ3UYN0ct6PtrqvlrlQ3I8/0u41Ora21H+3yQp0q1\n/SeG+ygsXM90HikhKptpz9lYd9cNhSTVH0wSv2vBltJA65dJmX9md6DJI8KD\n1SqhdGgooDXOYMFsSWloF0tritsipJ8Ym+6/uwJCIUgJn3FpYmg/1iaQZXY/\n5LXoMX9jRBLd39fBv4+RhPsvL9jmDTdSBMIrb8gtwXi6jiP9jeHpI+tsHpTV\nerOgjBDD8dgn6xhzUa3fQaxT24YHsVzJGeqxcSFXDb3V/bbEXeOs1tufgri+\nP3+q\r\n=SP8c\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBTTS+7NTwr7JDUnedHY6wrClrByX8AUdLp4zGPh2diwIhALTpxpHhQTJmXQXwOW1wIywnk6TIICb+eXm8RhugtupK"}]}},"1.0.30000931":{"name":"caniuse-lite","version":"1.0.30000931","dist":{"integrity":"sha512-dhS8LJ2i1MPPbxO58PBkr2INxS0k01Pb5J809AUTbASqYC3Te1hbtP1bGuvOXhqNEysi/J2IWQLD7mtO25RBFg==","shasum":"b6a487784a3ef82c3e456fc2809485413bc5537d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000931.tgz","fileCount":764,"unpackedSize":1298335,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSq2JCRA9TVsSAnZWagAAR7kP/26D11y6glQlTctV9I5m\nW9TuA7hjArtxnrIGJLx3b52RVEeOchcz309EDlxT3hjs3VZdr9//iohWyfAo\nhiEO9tAb3cJ905BzrKFYk8fNQhWPbNDTj9qH3avsPNDBALmGJFpxQlu8CGNW\nxWNFAIUCGkTVR3deSCsmY4LUFVARjOirl1BgTSAWZMhW83Ii1Yne+po7BFEt\nMtLYZDBztvNCLzjfykUpUPnwSaQ7q/mzJKikn1J00NUsERcGNR7MORmOaApa\nxQJ0e+JvOz63j/cclJ9Nogjiq95Mx6uKdOu0oFDNZCo+a7qRcM3/vfNXGdB1\n4AfMoyu1SE47Cr3BpmkUaT+UftI9GS8d9wmYT6p50KPducND4v2yLnQJqa/3\n5zP0wRn1OnMrPES4YXSWrDWq0hhtR6rxS6xu1nhMdCM+H8NewyXjtwsq7Sop\n2TsMMuqD/XfH725Trf0Xe7XlSj1c6mi7AjKI1mXknffg4iDzo3dVl/M5CkOa\nAR14vHn4iRG5Gt7hqy11rlO9Rbr4WCnq0as7V2q63rrA5iolSihQUsVUCNdZ\nY5y612LRHcwlikoMcbH03th16tsv1bibfmXGP3xuVI91mYZJ9oeO8D1uTQ+n\nNKhKzUtUN42dQ0fwozhfnE1wB27t7RX85uxOHwMcNHx5InP/h9JUAeSZhXD2\nb1E9\r\n=GPgj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDjKVqWM/dstmVnBszTyXJVeiwjZaUheOkLuLrfMY+3pQIhAJ087oP65GoOEVF6ce+wV+7YLlBrG8Z2DJPV3GVWD7Ao"}]}},"1.0.30000932":{"name":"caniuse-lite","version":"1.0.30000932","dist":{"integrity":"sha512-4bghJFItvzz8m0T3lLZbacmEY9X1Z2AtIzTr7s7byqZIOumASfr4ynDx7rtm0J85nDmx8vsgR6vnaSoeU8Oh0A==","shasum":"d01763e9ce77810962ca7391ff827b5949ce4272","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000932.tgz","fileCount":764,"unpackedSize":1298400,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSruVCRA9TVsSAnZWagAAMa4P/2ftbFiDGpAqoE0zPAmU\ntA5VAHsMwo/1r1j0IxO0thiggq9C1usIQEgaRITVTXOL6gWvDMxFoQ8VNxWx\niJqAPqqTcskI53jkiTFbz0Pb9ZuJZtDriNpScQom/4hwnfF3pDtSv15NslDx\nI+2DD7xWbVBkoLsdfyOw1E8sOXDw5RHnwvrErVEeNMhQhLidRAwlwHfoqFJf\n4VWo81sEksZJX0QJ1gL2Ak8y7X6cL311xFz5X8DWUxrRpEynQLmR+7+1SYCa\nZve61U/nyGlgFfZGqYkOaFpd/DN36uOw8wakiEmULz42YwU01gTYl93LrSga\nomVEUvqQPZhTkX9Gb2UdHxv9nc4qruTr9OMMnJXPZrGeWRJoWlAtSLcag+9K\nWDUotIl8FsB9wU3YqL3M+ncaWVgnd9YefbtQLRkycEwztwBaw0E1vPVkV4Dl\ngrLFglJJsrGeoys6+vzARJvrVtVyWho8tpO6FqAjh6SLuLV7I1Z6ADSrl8Mx\n3X8WIFUtiqgs5bguGSAqgoMw2l0yATLHC0XmKMiTjGkTRyfsQiLn7ypdqCEl\nnGYROA5YZ1uDrZ5Uq/iaI18z+wdTSLyzhjGnRUHusESusOp7DXaLm1tKDTVw\nNlRsfRGh3AmKjT1VXOtVQerxkEeklG1xC+s3NOGnNfMDD7d8yKl+oRh0qI6r\nZoeF\r\n=6ZD2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICoa0eDFB+8xNKIfBDukRT6ROwvu5tQ6xgx34xkGwNtSAiEA/YMN+kU80DcWF57N5ZU3ieQE0D5Oir57W5hzWGbtN6Q="}]}},"1.0.30000933":{"name":"caniuse-lite","version":"1.0.30000933","dist":{"integrity":"sha512-d3QXv7eFTU40DSedSP81dV/ajcGSKpT+GW+uhtWmLvQm9bPk0KK++7i1e2NSW/CXGZhWFt2mFbFtCJ5I5bMuVA==","shasum":"5871ff54b3177675ae1c2a275b2aae7abf2b9222","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000933.tgz","fileCount":764,"unpackedSize":1298471,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcUoh5CRA9TVsSAnZWagAA0xUQAJ4MKuMk1laMkfDu24yD\nPhRoFep1Ue1GCmU3rF5MAfip4B724GFUhSyAXOcQ5TVcmnFgj2auEh+yhnF0\nTnaZqOooXHiFIAaxPQXj9MfHU0buYUiPNsunVTtnY12kNDQFt5e/zDw560+y\nAlJHaF1slgzgs/xRmP7DnCfM8AxpxzpLJ4330vaZ4sX7qg1jYnOr8ZsYiE8a\nbhr9q6h6MQKnG8XI7cMEn/wMvVYOCfHT4XXMVV7ZHKA7VBgTYlo78ih3m2mN\nH1pu05Ui0pim1Eoh4XE5kXfnC5HGig5tNbMRHwzrWMl/JOI2JHI8QoWt2/2s\n71FGwTVws7USvHafWNF2G2jURDl7Kze/f2Gphu1eoPISdK0oHKUsUAHbAgVA\nG+lbgm0iaAXZJL3RrI2ue7YEFpUdAZ41JXeh9T8QgB0LnnycRaYd/5pgU0ty\nragdgFp0BsxbqvuysTUELyCGGqhwW/W9tGL1TvBXRMEm4Ofw5Z29KYsl/Cdu\nupjB/pPO7M00VCNMbienHWTd1U7rtzfBhiWs4Kem/Y6bpGC9x7vdcusglF0g\nPNYuJIb8/LU2dXXzd/hG/mKZ/Gy49N6sINMUqmxeo8W0qvF4SYctKWjDIP48\nRCE/SA6YJmirzewksyuTXiCnCX8R+FXQ/HZhKxYGHr+23McUU/VzVIlkdzqC\nw50m\r\n=Rx32\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEVXbPWmKdfMpZdSzNoEf9JmyHGKoaE1t0PpsWlIdlzPAiAnu1IL62hdG2qC2dr9kahHi/mkRoLATwvoJtffi1Meag=="}]}},"1.0.30000934":{"name":"caniuse-lite","version":"1.0.30000934","dist":{"integrity":"sha512-o7yfZn0R9N+mWAuksDsdLsb1gu9o//XK0QSU0zSSReKNRsXsFc/n/psxi0YSPNiqlKxImp5h4DHnAPdwYJ8nNA==","shasum":"4f2d749f51e9e2d4e9b182f8f121d26ec4208e8d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000934.tgz","fileCount":764,"unpackedSize":1298537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVpkYCRA9TVsSAnZWagAACHQQAJdsvqpPYkx5rI7hLzWe\n7Coq7iM2uNBftjHSOvx1WH3qBsSjrvPpMyEOe+6XjHV5ATXR1P6vnk7Aysq3\nldwUc82ybZGWWxq9vMED71mFlAgSHhSN93EVrYCN0kzbzjxSzFWNrjp5Q89F\n+Fv2/UJcsia7ScDtpcjXRaSkpjTHNUKjd2sw6duVf8SFNvvuv1qVW/4S3U9a\nMB9bwGYxdaEwdbyp7ou0aEz3JNXsrtV3Tdq8/Z6t3HSsB4cEFAqOPs7r/9Df\nc/oRS55N6v9Ccu+vw3vfNjrP0cPhW04V1tn49LoRteyxBaVQfjzLMLirNhTv\nl4RMGRP++/HHRA7KsAquZx5z4BixrtR/7v2ih3xmOjprCp63TZnGZde9jJaq\nNa0tDDSGUkGUY9LwskL0J6flIbJvSLH49mt7IEddJfwLFwYUPNeQ1EwZTl16\nHHCvCELhZu5mzX+tOz57H6USRkxUJriqEvwwn5lJa2BkCC3fl/yz5bKzjsE+\nKtkGQHIDYsL2C5l1y1yub23ALfN37sr693b7+o8yP7kjnKP9xiFxSJoQ4oXk\ngDbgaq24w7sV909kHKX2r9xDRdwkldT3YhloH3+28i7adsWPUqFr6nJSRqHA\nL9B7eUwDtd5ujs1IneBY1fZCdcxdsGUXIb9ShsKmp7qeAFXQPYE86wydT6vH\nIn43\r\n=jnjL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRfD2XMbp2WOzcpmX2wzOjK4WPNq2P1ssyUQDSLmNrAAIhAONVB09lRU3NQ4nFseD/KQxOELzcpFxQrt2ooNCzmoEY"}]}},"1.0.30000935":{"name":"caniuse-lite","version":"1.0.30000935","dist":{"integrity":"sha512-1Y2uJ5y56qDt3jsDTdBHL1OqiImzjoQcBG6Yl3Qizq8mcc2SgCFpi+ZwLLqkztYnk9l87IYqRlNBnPSOTbFkXQ==","shasum":"d1b59df00b46f4921bb84a8a34c1d172b346df59","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000935.tgz","fileCount":765,"unpackedSize":1302120,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcWR/6CRA9TVsSAnZWagAA2xUP/0EvbBthDFqFb1RSRnR8\nF/T/wchfxjV9IA5GKxQjaFscFPFfI9rBaftrxLYdiJ75bUXpzMW455862YWS\ncTfwiqlNxI6FhRafC0sY1jrEOwBWt3Qd0lw/rMj1AhXIsGfG64SFpapzAGXL\nmjXPucoGFL/xRQbYm8ZGE4ZISEtD9hZKrKG2vhmRBA7Wt+vsCaw8WODE7U6R\nBqkNPLVIylwIUtQgTxiv5E4VnoE6LwJ2TjWjpMozlzYPLZ6DHv0V6i8kY3oh\n0BYgkBcXqg/fprI6w0ZN59gUeVkl3KmjovK2GPEynejwXYkKRS6ZkKkFAKAT\naeDJkWbjTlsA3wKCxOpqUrjSpRb58+d3p7dCXmXPOdWa8MZHAFYVHxmzcJoI\nW9zFduOA61nHQsTvsUaLKqFXaBr46lW8Nx/DxvLsq6SDpayZT3DU3t0iTZl/\n5bfZhMg53/V2V6dS7whyHZ0lVxt85UK9jSJHX9gC6Dzpgz90zsuFI4xkTtyh\njPYviRGzraN8FidohWCAN6FDs4DQgXTRVpyaaUhty2pOrxLliaC/t9h3n+vr\nQnZmQ8SKBrN5VKDrm4h41VG1VzdI44Uu0QmMYps4wWdi3mAQNx83bAOtOgxI\nrzozlyW7cmZAnwzgckKMLcFrC4fg+ldpZ4aZslDNdhnfAF4FqR7TARy7+vex\nEeE+\r\n=8pgE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAnPItP7L/MnT9h9uO2jT9mOrluy1Qt6zCpqZi95t41nAiEAgsC60Lb1ytR+CogsgHnj5zW4qqAU7SRATUmmh6/8+bw="}]}},"1.0.30000936":{"name":"caniuse-lite","version":"1.0.30000936","dist":{"integrity":"sha512-orX4IdpbFhdNO7bTBhSbahp1EBpqzBc+qrvTRVUFfZgA4zta7TdM6PN5ZxkEUgDnz36m+PfWGcdX7AVfFWItJw==","shasum":"5d33b118763988bf721b9b8ad436d0400e4a116b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000936.tgz","fileCount":765,"unpackedSize":1305627,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYPrqCRA9TVsSAnZWagAALnoP/izVCrI+I06qA8o8ozka\nOPrV60OAmsGnpgElGvAO16Xr8r7v9srAfq4EO+r9mLi9JXAA4XKSzS29U0Ws\nRnrImJ6uKT3ZjON3tqkloCCIVtSLH3GKae3C9tOMwuecfVNMIQvDU7BjweEv\nkB8KXJSdaLUKGOe5q4ddElCsi66IU7M7COgmVugry9fg0EpfnH3gUNLlrrFF\nJUrokYBUzt7hT4rQd+b9HyIBO4Kd5h2sh3atVlEJv1u+jj9/jfPnuSKBrRPf\n1coMbZdbOR2jTQO/0BWdTQ80YHoSjqpUAqHPFYZe7fERPuH+eKHpTEYwR7Xl\n/USZXVgw1DbMWz0AvUI7hgrbsLHD+JESyiYy5GSphbj9WxJjE7HxDr60zZit\nr27fiAM9+G/h6IYyfAajehWY5i5uvG4VX+n7sjbCwkStrmurpNHVsIlTGh7k\nZRbCPJCUypzJeJnFBg+GVeJnDGPOchBP0u3AvLU6XA8MCetDn6eyohiYMJWv\nLoR48NfRwBiSeiSmd9014U3dDg86s0XEi/jqoORd255UqoxSysG+BKf3nE0I\nLLG/OqYY9aag0REeGsxzV9MFomJBb59ST4jztHEFdnRdOUb+gA4fRRFQulWU\n/7J0IatcxbmEaNxW4pVPJqDMxYYpyeq4OyEIeg28jzn/v4NmOS2UKVprH56D\no7VS\r\n=kJDo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCVKquFcmSjX9KIEo1d4/+F+52Mq6gROD1cUrdPjXHCQAIhAMYG+AoyfV9cqfglFBYgKiWQ/qNYSPdMAanS2oOat2fH"}]}},"1.0.30000937":{"name":"caniuse-lite","version":"1.0.30000937","dist":{"integrity":"sha512-mVGcm9lGv8xldeDEPN4Y13XtdDWrEF7PVOpESVr/LqdK2g3LYt8z6dgOWUZrVazz35ngtM9Nh4kWBIm/2sQugw==","shasum":"474ed722a9704fb803bee29203d6de51ba188464","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000937.tgz","fileCount":765,"unpackedSize":1305736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZkDoCRA9TVsSAnZWagAA4qsP/03FtrEFC1gOgRn5MaS4\njQd48ewX34TMN3m8FXQF4awJmPRqGc7v2FitBnoun1smjxSSTEEIL6NI9j8B\n8b8lsIP33AHS+3Ww0lduB8g+1UY7i8OGpbOiPRXkb8HKpIIuxkLgmAeknX56\ndm3BRkXW8M4BRIsOR9t6JhRPIRaHEHkhX9IIeKJRtiDl2dQWwrlNLjhImGM9\n7E37RYfunubNcp7sgJ6FYqX05dI/1Uz6IjvUw9CgjVhcCBIsch1FVc7GTZzh\nXaaoJMdraHh82lp8TV9NfqQF1Npf5EA5aXjsRrmtBw7vApfMftHhQVp0zDw4\n6ek+x7ox7kgUOngBwrCL83wMXdoojKdmHq61n0yryRMx9WdPQ2D2cPsmY17q\nGGAp46sOeTUjtUHIXrBIAra2xLI7yrz+EOTn+931tDP5bS0Lu7G8MQLM885i\nRzaC/Xr3x/gAL9HuLZQJE7nNLkz9vcpfYaCUv1ybrvYC/Sh5z6cBcoveml+B\nbSPy/f0d3FfdeGHScRu74cplpN3GxdDnnOHckka++g8VpR9CnKGvJ9GZ2RmR\n5aEHNg7w0AYvOOlxQDeaJ92suxaS0a4tPKVaxlnf6znXoOrENsFjShDIC5+C\n39AJIORPexWrZk+CKJwWDsnEZ+SxjtVjj1yWQnXBwBV6fZRLp/5oVrcI6nYG\nPz6m\r\n=8uZb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEf2Tg3tnpb/COU+3X6Ua5hEFYxYGRDVcgl/LOdOBhz4AiEAnMt55TfRBBmtzkaoUOqn+BhVWsWOhg53FXDAHkh92KU="}]}},"1.0.30000938":{"name":"caniuse-lite","version":"1.0.30000938","dist":{"integrity":"sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==","shasum":"b64bf1427438df40183fce910fe24e34feda7a3f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000938.tgz","fileCount":765,"unpackedSize":1308434,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZk71CRA9TVsSAnZWagAA/rwP/AqX/xnq4WAhNIUUD7aG\nrMVFIp63NoNPUVcnTreUCueG8CrxwDy+F3jiwyxs+5O8Pl2yEkrsIkD5zNwJ\nvPxNOyyp0LTkcvfYTteinb2MwiPuGUF9CanLKJFf1Elpn+aqAfu6/uqC0UJJ\ngSbvGWVJkzzhmvisYwTfqqTDuZlQk6HtkqxirBb8jfYnOjOYTo+YI32axn4k\nZW+UCDemRYW1rURBkZgLRWPRXFHjcY/VuaaZ81FADHgEWk0EMiHOkVzhbAa7\n2ARKJ0xvlI+xPVwJJG3f7LNso8uw/PrWuy+3IlXkfYmR+VUmYEt9mx7S4m5L\n4zUQPXWMf7eR9jn9L9bf9VbYJHtKxmW37uTIkVPlIsn6aG1X1fPtcwb5bL6s\nZH2a3v1WEktzXNL3ZjrxUkyHw3Hz5OqUDBdNDlrOJe2kR3U/YMvHhNiRdLGy\nh6C0NIdNa6qj6DphRWFF626WJv4dvebaLLJFxsrF0lOw5E6iRQ2EwrO6RfEw\n9Ldn23khusn3lVJ9Nd3AkHpvMK8Cb6cA7vhHC1dQe8chOFbW1Ip5OCubXg0y\nFNXPH0jAtMyW3ZsyhX0LUieQYzyhu1g9hbkeOJD/ch5ewDLXbl0HuDcRAnHY\n6602zQ12g8BUquJ5y4meNR5he8TVSAOSGrSt469F9qy2kOPNQlFGz5GTL+Ny\n8BLj\r\n=kSYL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8lUZ49UdI9a2LuTXl8tFjcspPzZODvZ84C/k5BipGHgIgLpq4EYn5A+HwIiD2yrNmOvswaoZRlUJXt4BzNDHfhA8="}]}},"1.0.30000939":{"name":"caniuse-lite","version":"1.0.30000939","dist":{"integrity":"sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg==","shasum":"b9ab7ac9e861bf78840b80c5dfbc471a5cd7e679","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000939.tgz","fileCount":765,"unpackedSize":1308519,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJccMzqCRA9TVsSAnZWagAACb0P/R0zauRwqqef/CqYWag8\ntNrwAI1aRvcHaPCjMPlsXnvJQXn/AiA/bavjNIn9nZBOpJESEOzz4+s3YuPW\nAxBalVnUg+JAZfm7LyamoWybn8Tvdnj5VXCZzzwpj6E/eEJ5PUAD0Sqkycwn\nLRMSrQAkWj0IyyavckICZ4nV6dJ1nerEk1iy8+ZfnhgTY+lqOTY9TJxHxUM7\nDH71PoRuNIGjPYPGRBdtzb+r3TzCxsCWd1TganO4L8Ji2vVDbz2O1+l2Bf9B\nmYvS2y2P3Dpu9sSQcg8g5xEqM093kQeCRdnOCP5tqZbfT3wpE7vuS+9iy2y7\nXONkojPggE6UUgW1fIBETsrYhm3odt/5ZaoZMuet3OSCIyU6OPhM0pIduSOC\n93tY4miaEl6ycEXsXLZhIw1TMJCfS5STuthroFtQAuQeJmkzZNLz55C/ZTab\n0rEWLlG8Mp7Sf0l/gCsXN9wXKo7mpjdviiaTnSj2aFSIEHcux83U79YM5cHZ\nLt8DbxRZGILM3yIss0NlAbOG/Ll5chHdojScVbSf1ko5vzXcoX7gYgi4uK5I\nO6OhuL3+vLqCEMiGEJ5KeeQaZ6VTKHeclhkWO2K5DbOEsLaCBcrglIvuxEDn\nu16saxuErE2zxrhz1vcDCGsAwx9TWAQu0qm5pIs9twVyMobie1MsRfQMHrJX\nBni5\r\n=g5TN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHJ2gSYrijdu/TSNslmwOhsIEd801MjEeXihayIZ0MOBAiEAkJ4AL4itupzNYm+9TvW4g6cRw2nX9l2yRelikk5MSvg="}]}},"1.0.30000940":{"name":"caniuse-lite","version":"1.0.30000940","dist":{"integrity":"sha512-rp/086IBUfCsNgBpko6DGQv674jRjeXPesDatDB2kxrkmDfD+S5Gesw+uT8YjpRWvLKLMRBy72SLRZ8I0EgQFw==","shasum":"19f2b1497fbfa5b96b615963097c3757f27989ce","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000940.tgz","fileCount":765,"unpackedSize":1308618,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcfDnsCRA9TVsSAnZWagAAHagP/iw98sXsF7yxAE6ym8CA\n+Z+3+qgXUEA8O1v7TpJ99iFHQb/61zCKciO9o60scXYPgVEZ2ZXx6RWskKon\n6z0xMUUWeltaW+Be2WIfvVPGGHhTQUupaef5z2oY77GCBGCTM5AxRBpj/vnK\nFOOZJm23dc279V6GPMg19RQhQqPVBJxsZP/17pkwxx39ZRbt9U3xrDakI/CK\nwII3+lkIGBDUbwb8N9TGktO5Rcf9K4wlD65TnLdO04EnukxJzTsP+E/V5Gn9\n64lMRIsOpGUkNNNooeoBQK/vfkL3RC4aPXxfzf6XX6YB8zmMlBaR42YR0MzL\nT6B61E+HimVgopQRwj/uf+QWVyQbotSoQAZT/1eNCVGY3Bs04xbJI90Szz9J\nkWi6gQJ9NmgyfPKr/xCWd/JNqEHrByM6dp1wNAlISl/XeNpYnZCU69diMbwY\ndAZqswPzY9KbZAl2mWzU/S8wrNwbK+jSzPBUGMC47NrI0/O2ThTPnTDAZig7\n9XwLkiDnAy9LM6hdT18nnVI5+yZ7wFlyBGiVM8ayeTFxqWBvP27ySO10fFz4\nGT1gx2/YCrlVEaZIY2FConu5laQ68mpnEBIIeqGkbHH4c6BdruXhs7nYh+sK\na62TyIZ/wh612/M/asgHJLCiju/m4VndHfqeV4XCDusZexmYRdp3hNZodWxj\nZKtz\r\n=P4hv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFpcBU4Jf8FI9gcD5x0RnVDi8BChzcD0vGaxab7qWbyeAiEA5NW/MyIl3NHeADKfa9kJ/xtYcgwi6c2TsMGUJVInyls="}]}},"1.0.30000941":{"name":"caniuse-lite","version":"1.0.30000941","dist":{"integrity":"sha512-4vzGb2MfZcO20VMPj1j6nRAixhmtlhkypM4fL4zhgzEucQIYiRzSqPcWIu1OF8i0FETD93FMIPWfUJCAcFvrqA==","shasum":"f0810802b2ab8d27f4b625d4769a610e24d5a42c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000941.tgz","fileCount":766,"unpackedSize":1309626,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcffvuCRA9TVsSAnZWagAA+bcP/3nDsDtoBxcbMMWlwROj\niXvlxTsPnQwpJipuvFbqIlWObLaArQOZ6tDYUabZ1Z8KEcs1b6zT2kCe9PxL\nIkq2c8tQ0Y3xBm0kKBHHhbpCxKEEZMmXyOd0/Od5Tpg/e/4ayBy7ZzhlGjrz\nqO13QEMva1bsXW1jYY2fDatHHgdwNllMdNSdb/RVV5YVbtc//tbwhyXnrQhj\njznWWmrXh1zuP70/ImYzzySN0l9QpM47hMIOkX4mEbeAaDBnFW9kNErcV3T4\nCNjpf4FPuEqrmrYigVH0bXx6n1GZkp/NdUciWd4lcVyWNN4TkdnhX6SZ5k6Y\ng1UIrzMIhTMv79L3qhlEX7Ydyjf/CDzoVpG7LkldMtqHvbvp758Xw8gaS7gV\nOaacr/6XwoRwlIvL/tWEtMA1DRzbL9eEWoNm9RQI8GV3088lY4K8St8lDyyy\nCBiCghoOH1rhKlGlq4vP0oGtowbbZ0u9E7KSd9aTvi6QE9GjI/LJPJFAGp+8\nzsJMXx5iGPshnORE2eYQe+qIrLhrzJ8jatjJ65fwHIVJUA/sPmHlXlB4eLM6\n3x2zWZvAdDEQPUaM7QHtw1T6YNc6uoWx6uniRSybPbTjwq29E3a1dSZSAqsy\nTOpcrYrGSpuClBEae6Vhh5PG1QXPEzUp99um9ecluHHjoSl+yKbJwhP4m7E7\nLnIH\r\n=Cxpn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSoSmTRQKtRHZiZj+UUUEfD5T9sQbnk3DdPUnN8CiqNwIgUUSaoxMrPcnoqCXgMeNoxIvFM0zteRgjSQyhH4dEPO0="}]}},"1.0.30000942":{"name":"caniuse-lite","version":"1.0.30000942","dist":{"integrity":"sha512-wLf+IhZUy2rfz48tc40OH7jHjXjnvDFEYqBHluINs/6MgzoNLPf25zhE4NOVzqxLKndf+hau81sAW0RcGHIaBQ==","shasum":"454139b28274bce70bfe1d50c30970df7430c6e4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000942.tgz","fileCount":766,"unpackedSize":1308522,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcgJ7tCRA9TVsSAnZWagAAJhsP/ieHJUT/IkymrnJmMuqE\nWWKov21Vt5kKkUJKiLRiOZ3v0m0T0vC4jcUee08pznRUl3DuIPlb93EpvCRy\nXNlrvsy8I1P7EwrWcp8S1/EfUa6t4ZDUQi3mSDEHKY88PaeaJ61vcX+s1sWn\nt7aQHCYLeeY73WiB4+Plh6QltBPH6ued3yV2wDImn11vw3FEzf5g+C61eWJt\nKcRWnktZv8RZ/hQ018lnQVaNp6Liks97X8KjFVw/Jl0yo82jLTVtDU4OK+jT\nfJq1IWfqsaO2bDQmyYGT+Wbx980z8GdklBMDTFlg6bBXaVwUyr8lOORkSFTk\nA1mOCMYEADFiDBwHFtP5TPjg8JIq0n2XrpBkpzbPa7f37mp1Vc21SgRgqB1W\nbn+SIM1lWmzh5+zQeus/CkA457+I86j/wiBgZEuF8f9p4/Na3nfjJOiZYR1x\nhajZPLGAFBJjO83bR5zqldkibBdwiUeN2wpIP8S8LCVJrVbzp8+8yAU1s6Qa\nmuE5mx6ZldMf7i7Coyg3Zu1BUmZImCpNIuNdNth2UQ4Thsvd0xP32m6NYugt\nsu65JckQX0EVg7f6ny0HMTPKGrg4mSjiMrVrR9Ckzn3JYEs2KrDSIb/rOBgP\nPPFKM28tkX955nLuMHK91ApfkQh/Fs6819iKQz9aIeUaBLrlyIbNTex2pQXe\n9RgY\r\n=Np8v\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6ul0dDhVjEt/unvQ3iaV0hZEqWbYCf+wqPxkZrzOG/wIgeexRXhUExPEqTOU9BxhxeeF/73XmrqsHuwT8S0hbBUs="}]}},"1.0.30000943":{"name":"caniuse-lite","version":"1.0.30000943","dist":{"integrity":"sha512-nJMjU4UaesbOHTcmz6VS+qaog++Fdepg4KAya5DL/AZrL/aaAZDGOOQ0AECtsJa09r4cJBdHZMive5mw8lnQ5A==","shasum":"00b25bd5808edc2ed1cfb53533a6a6ff6ca014ee","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000943.tgz","fileCount":766,"unpackedSize":1308606,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJchIVZCRA9TVsSAnZWagAAo64P/28LC60TD5LCBCzGReql\nPTyh8Tq98YQw08Bc5ZPP+lasxkDyG8Xc9OeXX/7H7VhB3QRjX2DIxaSlMhup\nWx6naT4W2L65rpH7gT7H4l5smy4UhTvvx1BaEjB1qT8Wp4y982xngUbk6xO/\nsnDajW0Lv2aiqCJAYaRiox/KGiUb7UBTH0gv3LpRRDYClu0krzUT38+3/sLq\n4sCBqHsPL/emDey6xn0tJAMNLNngkzo5Lq21eDGkEAuq1Donq4IKy3Wq3Rqf\nJEqvA0MsEBEvC/IWsTDdsMUI3P9HB0yxcJgWwiKec7HN2vXHCeyvapQWk0zb\n41x5ebbi5AzGTHZ4n5pKAZLIUt/4lV/1s+LKW/tENZLJJTDFNvodpWjopgkZ\n78NnY/5tBPA9qqqQlwh0xv+PcY/ojDHdc+FUvbrx3j5+YA72cGMBhPEX0erP\nrBY3vFQcvLJ8aIYqbbLUQ9N89gRbnG+7DqH7UIpldXxzDlUW5hr9RnJT4upW\nwcCw1jNxaeya3UaKDnJnsn1XuG3tWhsj4hZIprUjnYpTvgPrLicKAwG0DkzL\nwtqwj+8NbAnBxs4flP+kZiM/nT6x193ZQHr4b+FT0Eg4TNdYBfohJQYVs5Rw\nN9o1rKz1cRTiovAwKGPbzVrFeWtn0AxZ1+9p7bu999aZ6BCxRjIIOEi4fkBa\ndtyM\r\n=yhOi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCefr1m5jk6g2chWClc5FY8z9Rc/lgkeprE1pbnKZmvqgIhAJawrFE3019iRUDccQX+pGTtD9vtojD+ZWRadOF7VZz8"}]}},"1.0.30000944":{"name":"caniuse-lite","version":"1.0.30000944","dist":{"integrity":"sha512-aOhlwlQtkOrHN/UM1n4rvc4xN4ud7O391wDEVBGff39Prhxcoww2rQvOYy8mxT5W8MiTz2AMbTvvSX//+xaMpQ==","shasum":"fe0684066d29389c9279eb1dfbb180c09851704d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000944.tgz","fileCount":767,"unpackedSize":1309678,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch0R7CRA9TVsSAnZWagAA3NoQAI7HBJGVxHxZld7MdKae\nxq1hN3+9ddvdgA79CXYeE2qI9Q1QGppgPyzCx2HaRLEtkBhdgjGi48XEqTz/\nNvOIo/ifuwvsgogmCp9cgdAkmtuUQBMIdp10Q+3TFq0mfXUJ82xXl4FhLfaW\n2ptHVl5FfuPf9v5UH5X9omiuylcTXb/8WkmJgBpA5Imt1O801xZN/yvMGAlE\noB7H5jEEMVkyRwNMQbPvtY+uTbznViCrub9SRHKWds7qSBQ850Ji3Ni6H1WH\nHA93mmalwzzOTrcsl0icDtafQc4RWfU8Ik97Oz7x3y8k92mQIpj8vNANemSj\nowrWIjnnBGS1Fa87tuV9lguzVl+Z8CbS50heDxxAgpkoKlRwLPu/9rpbX/c2\n5KaPbtSo+50uQqIatzpZBAwaWTpplU2XDUaqvujjSGOJN4c2Rxm4QSi6r8Vb\nerZMQ9SDnUx4B3JBSeseT0PtPMoE/1ejbQJp3m+3d4ArAblyRaM3UCDJAZzf\nMnuetVfZ9pPIcqvT0/LSMdQAFJ/8ljFgigW9OnqvniuHJbalP2vOIHh1d6m3\nHRDW3q6zC0/+WoYeGp8gmj/cdJJTOMcgpc8xUeGUsjp6NBzpJchIGU019eB2\nUPAbJ6mInVVt1rPWgnM/b7Xwhi7SGX/1zhXOvGbv/aPrT3iuiH48v3P/Iaww\ncrFw\r\n=14m+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF1YGU1tzYASbHQhEIPUX7JApZL0OwJC13rSeTBgtAP9AiBO54FEyp63IBM3fXqi5u0Mdz8QP2Ild2lIH6p9DhEtmA=="}]}},"1.0.30000945":{"name":"caniuse-lite","version":"1.0.30000945","dist":{"integrity":"sha512-PSGwYChNIXJ4FZr9Z9mrVzBCB1TF3yyiRmIDRIdKDHZ6u+1jYH6xeR28XaquxnMwcZVX3f48S9zi7eswO/G1nQ==","shasum":"d51e3750416dd05126d5ac94a9c57d1c26c6fd21","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000945.tgz","fileCount":767,"unpackedSize":1309742,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch1KMCRA9TVsSAnZWagAAZGYP/iv4RGtX0OLQE1Kuh8zS\nBFe81DyWcFI/ihrOcjDxVnMqUeRxROzPCt7uZ13gtjyXBCUlMenH9mhqlRPY\n+sJj3+UOOhhFPvRqoUfl1nxGm5tCNvtprPWQAA6S/jXDRZeGaFf2tcVxf5mr\nlYXDMHRFtpM/ftSN+tFnj0UidtN748Eaf77EJ5i3yb1sD05R1jxfR8H7upxG\nuGfFQzV8aLqbP6lqscYJ6kzeaARanC7SN91WeWJiT0xu6YnNllzLczoDFHTX\nTXJDzF+Mx5kYXgY03kyb3pVqd9uAQR/Yx280ZiUzWSvg2qsU9PdK6KJHpppa\nl2ZJzmlDrcDaplH2aFAXKR1yVO5nfkGTMOc8RdZBUTXONiPM/jLpK0xrLPwr\nPZ1614U+hN7j+hag3OCoTetR4OqSQs6Ur14MX4XhUnUOOai1H1Bta2lpPu0H\nOjnhDh6kKMSOTG21mY/bSMakzyKeoqEeRtq0UE1Q5KvIaNVEulfl4nNI28pY\nwo81h9ZUwwwI9ipb1uJpKc4x8ov26+LvJ9dozsmx6eXcESjBTWkcNJ+0idS1\n73nYuWu7Wpo0KNIDi+9zfk5/gcaFRPkUyA8pUH+pzWxn3kJlDl3FKh8kgdEj\nIpWvtI0+v/V1Jnmw3daJeNk9jlqPtOEBwUirRvQ4zX7mKtoZJRxQbNhXmSrj\nywBe\r\n=n7ma\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4xP60bF4hcvigiE3rnGr9gUIsr2ESH/uHwrdc2YAIsAIgDVLncoOpsqzDd0HNgp7kmaaofGP1j7vwVMVxGI+kepU="}]}},"1.0.30000946":{"name":"caniuse-lite","version":"1.0.30000946","dist":{"integrity":"sha512-ZVXtMoZ3Mfq69Ikv587Av+5lwGVJsG98QKUucVmtFBf0tl1kOCfLQ5o6Z2zBNis4Mx3iuH77WxEUpdP6t7f2CQ==","shasum":"ac50a3331bb805b483478bbc26a0ab71bb6d0509","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000946.tgz","fileCount":768,"unpackedSize":1310718,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciJX4CRA9TVsSAnZWagAA/6YQAJ9KqDB7q/SrbW5YM7QH\n8xpQIMYq1dDrb2JNmu941jABzRqneLKo2Cvnw4/e4xbFDylTZ55vWi4mceC/\ngeh3/JubOfzHcqs2S/P56UvnoNBbUIiOeffQ3+DsztUwuM+ibxtshM/ZWSM0\nOJCkIcRmTPA0F5zKyFlsvw/p/oZgfHWHDjR3Ib+1HgsOBdvzMIqokSzo8mdX\nY2T/LT6sgnu59LpPb/nQvy7p2fx2x+iDIlOapTr9NqGekhJoqd82qhbD4Xj+\nsVYVSp3Xec1wjwxwQyRe6g3M6Y2IbvMlLTOwFz77uaFKQEZIL3H8pMD7JmAn\n66vQfc34DgkHzESizmIB4AFO23xIDj8iBZv9GoQjQUq3f4V8V6xGXQPacltA\na83bk6IoCLzeRtyAtjVuDFWyCbY0afedTkK0jyEogZfhBQ0XEXEsl0hXevP3\n+Ylhaa+848zISDTknNAXfu9ihtFEZ+HbWHV5ztHQIUSUee0woShWRr1+qwyt\nUrTXL7fhEP1Qte3cSPS2/cZrbGyryfKQ4kQqhM+r/NGyE+lPpcMvhsqsf2u+\nQ/gSezaYzO5elrhcC7olySKQnvJmFJ2ocweZRLPTSERn+8gzmREPWvix9LDd\n4UPH+fQyyjrRUYUVm4cCEMhdvWyBze/K5Dlwk2Z8WFU/MUkQ2g11DCw49+5H\nhOG4\r\n=BIm7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJq5VqU0W3L/QuAdUMKcIwMzajhjq+fPA3IUSiFqbC1gIhAOn6I1Jmqn8K4JfoRNMMHCq2tcZyH03+QqW40mqe8sqP"}]}},"1.0.30000947":{"name":"caniuse-lite","version":"1.0.30000947","dist":{"integrity":"sha512-ubgBUfufe5Oi3W1+EHyh2C3lfBIEcZ6bTuvl5wNOpIuRB978GF/Z+pQ7pGGUpeYRB0P+8C7i/3lt6xkeu2hwnA==","shasum":"c30305e9701449c22e97f4e9837cea3d76aa3273","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000947.tgz","fileCount":768,"unpackedSize":1310782,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcied3CRA9TVsSAnZWagAAs/sQAI1zEDGotVXesLfco99d\nozNgKysvG500O8XSesmMiNVUSb5MsVqtOW5u95lqTPMVOYC1Bg8ut98X1q5o\n74/Bxm4zPrGvSdvEhpJp/Z++8vXUxvB1PAEH2rL+rTvjKRoaCtFpQGiOfVLH\n1siawtHbWRcGDwN//orWyDe8zTPFus5lxe8hD3G9zEiaoT55WYjs3qPxVZFx\n69zCJqMFX/rP9QH4rj6OuIaOh8lTniXhq4q2bqmV9+RQIfBftf/gW4upNTnE\niPDPZCnKcE3UGkRWKAZV0rl99LVPesL7Foz/P8UHxe7WiC2ciYuARaoitJaA\njM9teymUrjH0JRUWCXX9ufVkHoRDj9+d2Ov9YEC2XdTCSC0C15U0wJuAKH8h\nfmw9h+zHaDR6th8QOB1hYAg2NaBonEo1ogwmKpKunf6e8BFdidggMG+KYQrE\ndzIODBCRTA0qbG98GNstbMVdzRLDMK/7B1UM+pw1C5CKz+EVNLZHWQPQYxV7\nmS82dHYH+QJUHz8+LdOuK3ffWidaCWlNXaE+j0fy1q5eivGs/5fVwx3fqmBE\nHSFFM+dD8ttpqbX30HasPF/hKLnmhmcnQIBg4gFNsrDIJeeamBS9uYgZ2LDP\nIelBcp/+Jij0RvPDEw0WMib3CB+deJFy/kYxolZuVCH4awQ/Er/m3Lm8Gqbw\nmcBc\r\n=hJej\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC7K6F/cjhzuOPkt9SfGNhw54uLuHiMLpETKnniBzl86AiEA2qprXofmZ56/T5VJ77w3VUGQNY9P4kpefTz9ufgnmFY="}]}},"1.0.30000948":{"name":"caniuse-lite","version":"1.0.30000948","dist":{"integrity":"sha512-Lw4y7oz1X5MOMZm+2IFaSISqVVQvUuD+ZUSfeYK/SlYiMjkHN/eJ2PDfJehW5NA6JjrxYSSnIWfwjeObQMEjFQ==","shasum":"793ed7c28fe664856beb92b43fc013fc22b81633","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000948.tgz","fileCount":769,"unpackedSize":1311866,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJci0cOCRA9TVsSAnZWagAAInoQAJZsEZU3bAbHSdcgyROF\n1V1wBAEu975lurSG1zi7w7L5zXmNIsDfTrVMc+ek+hn6L+GNAwOw3TuovB8N\nokc7RBRcA1fS7ynMSJfES5TExOlS6C34VDyEIFSF3HlWfwmHQwHl+r6C/LAw\nkKOZCwPxNC3mFpzC+hvuHd6fSOmhhTmwae30yUkM/vqdURzGzbgD3fxwBENG\nWtcgc1YQgDw7c6kmEHb5pM5pSuQ29Hd0DmDCIXh4NeSH4c5weon/jdVzSzYK\nO5Lsbkk3qpIe033B1raeBqzRf5QjaNDJS2MkWTpSKCiFJ5Dj7xIm+qWVzUis\neI0P3z37NAasSdgrkMnh6WTTajG6BglXtgIe1icgy7su6TeRWnx/MUKMj+CA\nqXsY7wxHcRtSZNIE6a094qOKctCE/iLJhrxrAphd58lOdjSI1TfYHtNeoT7x\n5dgVy4gNxhahSuoQ7WqSYnUZBNZaAQUBIu/d05xXGBju6ss1bxIFT9tY93Ns\n0qMqRkqJGzKOpA2RRqjmjSDMyt8Uo4XR0nQX58CnPrswcJHPo4+b1fipkymb\nlPH1OuPnCxobLm4L/+7v6OL1ozxy7qK1nzjxaAp4BrRZHEfnDk+fIP7i+a0I\nPvYn3lugM5V8TjRvrx16102rIVcR36r+R0p7MDRQaABgfSqnrvs46w4DR1Ts\nkJLx\r\n=yb9i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDX6gN5LOYWf9j2PZ6qDYoDhrf3JNIviDkmsu3Wvk40BAiEA43jBOr8glLoRLsA/L+brgpJKbbmqR8r0kq3gGyK7Pkw="}]}},"1.0.30000949":{"name":"caniuse-lite","version":"1.0.30000949","dist":{"integrity":"sha512-jIF/jphmuJ7oAWmfYO0qAxRAvCa0zNquALO6Ykfe6qo8qwh882Cgcs+OWmm21L3x6nu4TVLFeEZ9/q6VuKCfSg==","shasum":"8cbc6d2f141bc32362f7467b45a2dcae8e64c84b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000949.tgz","fileCount":769,"unpackedSize":1311930,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcjG5YCRA9TVsSAnZWagAAEQIP/ixI0amMimSn5EuTp2WK\nDS4pfRJU6R7hJaukX/R5bwqQldz0+6KlRYFYHbXS2ZD2qmUD37O+NUDHuuPK\n7uHA0GMA2kB5AT2dPOAitWsc4JukHMgVo0s+LMjzXNwZnEwEWRsvjqP4VisF\nFOkKIaPHv4qXzec8G2IEYqPD/EPeta4jMmIHF3ZcnDpv8kBZ6eVRYeGNvG/s\nDZ847K0Q7+R2zUreuChzgAlXKAU3O2wUg1VMxN4h/1JrCOqXcv/FVxDqzivj\nhUXM7z6EA4XhCQbNwt1rLsSlBjFjZM4JIFdP99T94wepyegY0MAP66RoBZqz\nLmmA5CsCltKD5QDhNZUJrkp2BKFApnrOsvZSjE1ED8MeIX2qZ5z/EVXVWwg0\n5Lilrwu/QZo0afEYC+f/+42T7EyW+R/Ay3ZQkF1Eacc8xLuxd3tByGdpejjG\nsn0WAW2+Sonz+7cX5cQu9PfBV/2lBqEQJyJIhufEPJ4xxUoE9syfmYnA2yvb\nACuH4oM5xviweTOrSft3TG6YBPum5n9qmY6dB12x1jCuTLIZ67U+lEPrrknj\nAe2dAkQjR+S6dgLHUzjBGVtCyR44y3M40q6VELZ3XomWW2IgS/SpD69nqHyX\nm1TvrYYKnWiknOSTAcl+dF6MXVD9qszdaZhbHLbvxvtiJkcDxS/ZQhJd7bXd\nlvY2\r\n=hFZl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyJFKGhrQ0MeOAhdXM4kaeD8P2gDRQycYHy9h49BcDJQIgUuSv43kjHXBejMEBcDg97A7nKKxkTwZpKLyDFjFiXrc="}]}},"1.0.30000950":{"name":"caniuse-lite","version":"1.0.30000950","dist":{"integrity":"sha512-Cs+4U9T0okW2ftBsCIHuEYXXkki7mjXmjCh4c6PzYShk04qDEr76/iC7KwhLoWoY65wcra1XOsRD+S7BptEb5A==","shasum":"8c559d66e332b34e919d1086cc6d29c1948856ae","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000950.tgz","fileCount":770,"unpackedSize":1312976,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcjeoLCRA9TVsSAnZWagAAAEEP/1vrfNkP9RToKeCU7W8d\njFVZGxIh6KQ7bIOeujQvOq4kp71/15hdMH7Q+UHhsg8xwpJ3ocg2K4ASj6KE\nYCafAY+/K+jm/s4DIMiDorqRs/OLBoR0v0FXNejM22+J7FSQRqdCzrK9DHsX\nYRS+6tt8t+aURrSzG+wCYXxbm1xDrajjuiN04/QUEd0njdq1ircB7IOLSfIO\nl8WtQMCJ7yyDWKNdbLpilvozg1EaqA37L4ZP0oODMjFudpuqxuOVWbpmFDLf\n49WV0ayxEkLRujEFawD+E1Q1acEl8Ek116uMwpezbqhJ6Z5BhWN61QJPY9zQ\ninHSdP//AsogQg7+Ff7mUNtcXOJCa5Mec3HPxfHJJvHvITHiHMGXiLVD3OFp\n0elHWzAsGZZg0P+u91gTOQhr3xIcwQhwcWBuxcdjOsrAiN7+X09uwT5ZlXbW\ngJ8vaW1sMWfHbV0HbCXlrgfyf/XdJtta6cqjfkd6Mo7ZenkJsKWpedhcdtSH\nza/QfFVbycg7smgDvbEjwzbyL37Alg8aIREpzZMyFnmTLcm5KNA91kFunCN7\nmOAIOswQwOI+xjRBExxyUCeawiTfHzaP0z9w+4mtX0QeDs/obFjtjmsw9SDL\nJhjlkSdTNgEpqiJV90ru6mHsRVL/zllN9UQZKURqe/ayxVrJv/rp+dhigmuI\nqUWX\r\n=zll1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFy4DY5C3BvPINAcjRCk8gZl8ubkYbJzsRL5dB/TJnbCAiEAt9yAtoIbQ3HhWWV95tGD8A2kn3iA5ph+F2aVIkFO+7E="}]}},"1.0.30000951":{"name":"caniuse-lite","version":"1.0.30000951","dist":{"integrity":"sha512-eRhP+nQ6YUkIcNQ6hnvdhMkdc7n3zadog0KXNRxAZTT2kHjUb1yGn71OrPhSn8MOvlX97g5CR97kGVj8fMsXWg==","shasum":"c7c2fd4d71080284c8677dd410368df8d83688fe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000951.tgz","fileCount":770,"unpackedSize":1323189,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckcJtCRA9TVsSAnZWagAA6MQP/RZ4u83WIKKobQY+Ro6z\n3WCHyWSiOIBtKXfRWMBgreaEGWlUxWM9HxZa87IF6LHnswvp421b7ktD11lw\nj8GMrukTeCikvGHRogj4ngmv8TN2hlACoEtgtIj6RKjgZ1OlzPXtP5OW9/Tf\nqGOnRUz1e93HC1ShFO7EhXb0Wa6+QYtH45H1y27z1iuGeZVKIt2dmQnZ5IY7\nevob30NeWPgE4lY70GT+o+QYf24qGhRQ4jAiVjyX5sCtXvdba0o3hJi69zqF\nrBnP1nLlT551x722tB7GLORWG0Lc9RUHNokznh4RvsFGbVRp1sSH6J2nESZA\nsDZ31sO00/PsusPaKOA+HBMTfO7paUI/d7lJnGZoVGkpowDBq60Q4KNa2qrH\nn1iugRMqWQi7Q0j/GW8cfSaeTiyG6tr2iDemU1XwF5C1Vik9/y/88mCP7U0e\nDb8weP8OpC4KLMZNwRGjpy/D3pF8pv9RMtryk05RfgHbakU6jtN6XD4273W6\n+uz2fJJzeRiARVxMvHOEcg1s4vJZ82ZSIjTHd7fpzihOADdWhbSOlX1J4Fyi\nSYVONiOiLqikNQI+5IjGvVmS1QdvKOH3q3o8URE7/7lfXr/f4TamxMeDYIlb\nEpTtzC8gXBuHDHY8Dz846CvftY1xBaQuNiNzzjaDK/Q4LX4oNgbrVEVfPSlW\nzCC/\r\n=fjhD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfKCxXt92vhEebBJi6CpK0SNGyczytpzY7tfGSWmnGegIhALdlNHWFc4xdOZiEzaIgZzMCnmn0kNrYB0SGbjgWy0Cn"}]}},"1.0.30000952":{"name":"caniuse-lite","version":"1.0.30000952","dist":{"integrity":"sha512-gqTx8Nf+9elYHcG7c2B0Sr+npRqa7uM+ezWPHUXvDeXV/kC9eySNePkOdz6286QtndbqQbyqyk1bM5yz+stptQ==","shasum":"3774c139463676427771697519317ecf0645e23a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000952.tgz","fileCount":771,"unpackedSize":1324213,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmY9HCRA9TVsSAnZWagAA2xIP/1zrN2VC2F/IYULKWTll\nvwAvO0Tp4Xc70JFQnCPNwePsuVp8DFGm5CVLI6Pjpt7Ojs8vb7uKvwEp9HF4\nGuVuS/CpVjyipzJHetQELlxsditzLznCOUBlwT8t0PR4F3gtcOuHPgexcP/P\n2qwgWYz81fE5lZYM3K66Yy4AGNyR8TmibMgqB4kYcGq8GY+TTNQutW3UTShs\nZZeag2i576ks40WKXUvLjaQZdFe6QE04aklxx8wuO7q02JxdrZkBbrx4v+6w\ny7muUTn20FBF1u3uw467J+MvukmOtRAQjM3ZDTBwqAy+/xXSYpDz3Xb0rsg1\n2Yapi/7/XWFTe9vcr0tSU0aQ/J71gfZpxGJUkQ4Jh6HWKm6/e6jc5oAgjeMP\nnFMlC6joZSR/i9PBhpfl1dh8psjLqLdQzdhmDHAy1ZinKnJfncCCyYQVubvt\n9L0TuJR/o8MCT20Hb2rW+gDysdLJZXPbDHwDR+NHvKS8QOPhyTJC7845mtvR\n6ukPUASa8vG5GoACWkoAzMDzsbubi0cxw9OJly6TAG/iTUUhTHsxt2j31CRW\nI8VAivh6UXjjCE5xAAPFRhw2MIQ+mJOvdK3nc2kNeNjxhZ3dJGCdgcWKa1pN\nQD4RXFOaRSPaq0KMZB3fpT4ufB64os6B+NLOp3yHy8IbSCMUR0KE4lXGGR7n\nVJ64\r\n=3Keh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEI5eEcUzZfRYmxEGG0YGXFsVHiAiz0Gz/YVw+AErhzOAiB7jMnP/U27bP4o3MeIAdGoc2uc2ds2/3ZkOox9YKW25Q=="}]}},"1.0.30000953":{"name":"caniuse-lite","version":"1.0.30000953","dist":{"integrity":"sha512-2stdF/q5MZTDhQ6uC65HWbSgI9UMKbc7+HKvlwH5JBIslKoD/J9dvabP4J4Uiifu3NljbHj3iMpfYflLSNt09A==","shasum":"8054c4e5c4aa69dc3269353a4a5e102909759dbb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000953.tgz","fileCount":771,"unpackedSize":1327459,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmbl3CRA9TVsSAnZWagAAf1YQAJyFX+Y17QxlrczjoarC\nNZ+UD+4tL8JuGz4PhivmJ8Dus0uARFf0Sj3pTYPRs8Rpywg2O3Yv4ABAQY3B\nxVenk0SAiH1SrApmlPMBAJPzW1lH9i1tKd3bBl4OUg/jarcIn5W6oE05ca5A\nOsC4YenH0DQgcERVy1r1Lay6ybyN21yA0v5nMj0ZCXFUra6dp8AT3zofgw85\ndvGgO68VuSHUdGAfz1I+LA5L7j5y5EydFuIaoXesmqcxrtTCCqPnbNm5n7zX\nxvKkPPU03kGaVMtGVSsOpD0/dG3zKWeJM4xgxoXGMBtDVGwTsXtrmLwNWMUq\ncW/z7mjOUI6J6gSEj2r2Av78bUd3oxl0gJmYGnxOqRHuQDHqdjqMyvT7CL6v\nooVUpEUlpiX2PfdlUoQqAeCcAJBvhsI0aPubGHoo/61RyDLZdAbRvAAugiRu\nLf9ykjFR98Mj2sZhRG0pLNHksABEaeaYeFYm1IMkSTxlbzxBY6K0MHi+qYhI\n8gYNNvOUsysPxQA2Jhb0P3iwxPyh8dtmMeVGcVtYbgmyS/aVaBy5O4yAMx/j\n0BJM0O+bju9svrrt6I1zDVfdjs2KRYDHklDDNE92lxlba8zTtrFc/nzey7Zp\nhADoykT5+Vg6LTVBUdUEEl7uWfp7iZtIPSMVcXeuo3s6OxyEB9bVE2a8x4Pn\n5lCK\r\n=gaPb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuVVMvaFHWECD0W85RJp4bqRnTp/nVBEuiP1SeZmfP4wIhALksd2bjMGRAw+V1pB31j0rXO78EUJ59h1zvX5YNnvme"}]}},"1.0.30000954":{"name":"caniuse-lite","version":"1.0.30000954","dist":{"integrity":"sha512-Wopmc0eVSSG1d9/O4JTn0OmGhUfhEHNkHhoCjUrGSImvHI+2YQWkOI1RRNTUFNSHbSAD8J41jbdZrPP4r32cbQ==","shasum":"227c2743e40f07c71e6683b6ca9491bfd5755b8e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000954.tgz","fileCount":771,"unpackedSize":1327538,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmwr6CRA9TVsSAnZWagAAyn0QAJtf8HrdRIuGSruvNCFT\nmlON61P52vgwbnH2QI3F0s6tofZqANOKRLXsQjpKLNAlgAYnXL4oaJCu5L/B\nPxS86NRUaxLIealMPV49yNzQ/CWSHkwoBWoXaS2LpSFGJSJi9rGYN34twQQw\nrlJWDWdNGaWCKS/gOCXNQZFkbOCW2m47J74xiAjZpEzj+yUirCq512DPxUGI\nhj4sMZow1kV+aOLNYi6lLsNHj6G14yVXjlnDQutqpivdTZjv7MHzF1l+NSX6\n8LcAEdEOyt0VzzGVg/lFc93udRvmQQiiDhhCWNA3Yj1Rcnl2l0EYTCKNvT8W\nz3OJUAJPqy0niazzglOQmFRy/5jcdm1odRdktt7pf6zmySvSjAe7l/HN7SOI\nAGFCLYjxvf8T8XDuDhBhUbVYwxc42U5TRAKj8MJT8WrmtfRuCrlq8sajTA+P\nd+JVqS3wAzimOXJBY5YjrX3A8RR69CClBgbyH0J6RYgSs4enUsdFyMe9iBr5\niaLWc44xcwIk08zkoixvwQ8IvHdYXNn8c9vggjX+R5NDIm82Z2hR5ljerREJ\nYeQFLKYsxU+p8FuGKjcdZc2e8Qo3dteQDoGgbwNo8H6K6yPiUMJ0gHSxTb2u\nVNTTwRU4RT/Nv3aY8rfwRWsJvIt7vQCITD6QGrxZpGSojBi+2gUG7F6uxx3Z\nMScm\r\n=zBTt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFzEj6mydAEHBRGfpzAXq9kY03BtQM0ZaSBzxMdNs1hzAiEAguaDqxPEoGMOi6Yzwx8HOnE0PCx0+FbbJZ+v/E817LM="}]}},"1.0.30000955":{"name":"caniuse-lite","version":"1.0.30000955","dist":{"integrity":"sha512-6AwmIKgqCYfDWWadRkAuZSHMQP4Mmy96xAXEdRBlN/luQhlRYOKgwOlZ9plpCOsVbBuqbTmGqDK3JUM/nlr8CA==","shasum":"360fdb9a1e41d6dd996130411334e44a39e4446d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000955.tgz","fileCount":771,"unpackedSize":1327592,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcnGqJCRA9TVsSAnZWagAAN+0P/3tz67gJx490O8uduvoj\nKR+Tcw7FnEenTdiBgg6nESbwoKRH/FyvWWVFoaO1eArkKf6GCvkit9PCntre\nU/JGPLG15N9Rmo4eg8gg7R5v7DiKhc2gj3zsIZ48DVIgnIANxY3HEpK16H3v\nsx9nepid1ouykiA92QJQNLc0uds+NIEPbIBX8ljuTg9atFqJFlflQ+X2Vdcq\ntMEn5Y5nYLsguyiM2HAmxHkqgygdX50WLiSHf0qD6J+FtIGsGOmqny8jDVAv\nt0s2uJxNHjRYp39tuZbgsjT4nkjOgFoU76vtrsumeeksCqYQab6XNa96oXoz\nOOZvkWXU7ieSuTjfvcVHuezlEnkufOXSyhm+KH+angEJfZ9DmM2yASROe9A6\ngCFn4p/UMkT8jhy8HUWyvGiEOLgk0W11zcxmMwJVG8Mirhr0jlMz+q65qU6r\nJu5Mm859G9bqYFP2943N6/UjaqEZBr/wbGartrL9Jsh736/BH0s7PUex4Gvl\nSLL0YbgIBfDswJ4aLzdlBXIV1+vtRT7VvIP146nPU8ndtL/DbfNSws/Wsg+8\nU6enm1Kt1nrDTsMgheHEAFbORj9UI38Tt/+/Uw34EeAq6RceDyRZor7ScBYL\npI3fh1sRLHGP4AIZnguZp4BROsIWW3yKeqXkTGQxwZ2KVJ8j4aPpaRU0sL/M\n/CNJ\r\n=hOlv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGFhKx2w9hUpapkZKF3IFdZoUtVs/1Z4U0vKLSZY6SEoAiAF8JDwAv3ooDFyed569DwLgvtqdQhIBGR4eqZ/uFheGA=="}]}},"1.0.30000956":{"name":"caniuse-lite","version":"1.0.30000956","dist":{"integrity":"sha512-3o7L6XkQ01Oney+x2fS5UVbQXJ7QQkYxrSfaLmFlgQabcKfploI8bhS2nmQ8Unh5MpMONAMeDEdEXG9t9AK6uA==","shasum":"fe56d8727fab96e0304ffbde6c4e538c9ad2a741","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000956.tgz","fileCount":771,"unpackedSize":1327664,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpDdrCRA9TVsSAnZWagAA/tMP/Rp+sd/07NCnjOjXp+vj\nPNmvNrM7x4oHms0CL3rFpcSd8nQXcNcclL7xa5yYPe54NfeCihelXfafz4rb\nGlBgOrArcWzAq/hN2MvRLP7wPBSjaTaWP3skfa+tqzAKK1a/Qtw80dWwnRAw\nnK7e2Gvp3hkAHNENGvpfYNt8DG6phu5NIjm1nHZhJojoeodC/pdvRJjIFv+4\n2248Mf0jrX92QcQWCzqYIGJHPf5yjzfZxu32I6b339TOD9FtoORHEOmR3Qqp\no93eKd61sB/pBH3Dt0LTaOE8zFGA/44WxbgcOduONUUgelyxJZ5Y4p3Q3F0g\nYXwXwhR0ciSPIxrdow8p2dLSAXNepcyr/R8lWMPlHI5T20UojB7S06DY8qUg\n5O/LuEd/LuifeSBtcdeW+jikzBzPxHyKeXTLhfAOJtKp0Wo427OR16cKtmPx\n/uU2g8wpEekMTKlWxh9GCU1YRWS4pQT3VYjseH10SvJml2giykRLw9fCX5RR\n9jKh0rmR90FzMEkGEW1vahvZiGgRWOsR5cJqH2lHdkV+C2A+tOVPDq6yKf6Y\n+6hbyKsx4O76UtvuIBl6pCRzmqthYtXPEQTNeUugobgGOIngLhpVh3+dw3+s\ntfLs7UQ+kxAFRKdSOSY61QzSAF7XZNXeJE93zVNThdj1txmtPObYUD79nJty\nh32S\r\n=lTJM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHUVPXB5FbuZleCIki+ICFuKoKExZdvJZwQYvlzRVEoKAiEApzbnqNMcAgYo58K5G9ZcioeLjcuwIPcnjKrObVf5Aks="}]}},"1.0.30000957":{"name":"caniuse-lite","version":"1.0.30000957","dist":{"integrity":"sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ==","shasum":"fb1026bf184d7d62c685205358c3b24b9e29f7b3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000957.tgz","fileCount":771,"unpackedSize":1327743,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcpFONCRA9TVsSAnZWagAASygP/2vf55U2sarqzNttLn2+\nD+Tnw2wtsAg9V4YFF8PyFIbm5r7TZ+JWFx/Pp13q71eceFeIrPOIyi23vBmz\n6JD/GA216HPP1kGGeJT4PMeANJAtNIaw0ZD/zjonL/05Rem5uIQ2P+2MMvet\ntpQzVp2oHkvwa49KYTKX6asjgGaXrGJcKSBB33/kwdM+l0PmLFWVqNKoUVDT\nEp6wpfhER6hG602Imq7RunTqnXOjXSmgrXUjXVzsRf2tnzlgVmEeJ3BDMyhD\nH0hFXDoff/o5v6lq+y0CiTR4iaLjLrhHDKgM2le9FbJ+YRj/mdY0SuJ2GzNw\nqgUf1GJhJzTfsHpKT4ngheLSE2RfJ61nF7raGWVpru2ivLnVvWbycC9qAr/4\nlLCZMVBUHFcleqrUt8uuHmYDY/YYcUBwDDKrCy2Hb8rssqRdGkq3AqCrKXDq\nTWdIQcwyXm5v8/0cAHn6FdxJyANmu2rnNqH99KsgMLh7NrV6rOFmeb7xxxk2\nOSBdTcPF8PZp8drElDBrRdmyxjhyE9zoJA2J7Ml6p3fyQhUCg5WV6BWcpYFj\nrQBEbUTGRgHz/PxTk/ceR0ZmoIz33xPk+QSm2uYsSOu38oV4ufICJD77HLSJ\nTkyP5bb0vkytG1/TJiEF8Fp3Itnv/wGsMipDzb7OVNjp6qUD92d3jtktyj8t\nwG91\r\n=9Mwn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAXKhB4cgNo+B4cHiFdhbXaRFqcx4wXSo+Mr9rHENyEWAiAdrvSs69s6fAbybXPUrJOznNZlqpJri6tBhPxKCVlf/w=="}]}},"1.0.30000958":{"name":"caniuse-lite","version":"1.0.30000958","dist":{"integrity":"sha512-+KfdlJj6IOOrYmX723ZymUttwietVOGQfVKPAkjn+hxWg6FyPVaaIq+euUDu5mK1lblkRcF4Nlw949Lrac72sA==","shasum":"f6307b1512bccc64269e3ac4733072454ede1fd0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000958.tgz","fileCount":771,"unpackedSize":1346057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcs6cDCRA9TVsSAnZWagAAxMAP/itN4SdPlKCQ1uMBEvCR\nbi1a3z5MQxOC9els/3UsOYDwVRPLpQYbfLGwyk7kG7WkwuvTCoJZprh7Xwas\ntedeVYAEXs+SaF4RvbWzhkpGzXyOzO6uszRZGUQrhjsHN/BRnmRcBX9kztbI\nCQhKrKYbDIorG4gIhcbEk9P8JP/cCFEXmJQ3Xjzm7aHHNkaI1azxAz2I/Uf6\nkCdBf0B9zjxeT/0w8c3w1emKpnJq+uu7rxEGSU6NS9hntSegY3hU7lHIkzdK\nwZJn1O2DSUjr7klXKC9XOeb6Rz7p4EIi+xxrx9B/NQbHmm4nPEuuOO19xzDy\nvKR59mgw98RyPsWLo0gVzwxph1nxXUZImLI9E8XzxzD+byJOXGo2FDAXR5Ry\nQlHMgGBc524pHiY7gBb6pgwmWylSvUXMCy0YPsnzrabOYXtDvH4kHmYj0DOr\nf0/8/UURpSYy2mWO6HmGPqgwQQ4PJxFBeog4VK9mnO5RlsMzMe/4EUCnSL59\nhsTYxDnQ+ABA4HCpAXBgX7p7BageKTP1I0g05W+lmjhEfoJi09dYxR4GvdHh\nvY9BvtJ7T5X0/4hUpobXKKLy/EvP7X09DASlYZNb7d4reLleP3oKDz0Lx5E6\nU5NxqItf+8x90ikWE+cECa9828T6i/CsI5KA40HdpV9gvTM7N+A0qtXFX8q5\nwxPV\r\n=69h2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGT1fRbMnJZ2eda3NN7PWQX3NOGqu9nV7FLqTVl7YHU5AiB/OhROpMs8ZJ9e2E6IWkyyYUoeUHXCT79g3iTgJE7J8g=="}]}},"1.0.30000959":{"name":"caniuse-lite","version":"1.0.30000959","dist":{"integrity":"sha512-6BvqmS0VLmY4sJCz6AbIJRQfcns8McDxi424y+3kmtisJeA9/5qslP+K8sqremDau7UU4WSsqdRP032JrqZY8Q==","shasum":"215d3455866da874179c6170202f0cc64f961cfd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000959.tgz","fileCount":771,"unpackedSize":1346153,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcs/tVCRA9TVsSAnZWagAAESUP/jEV0MZB+OSZYZnmqkvV\nxycRRRpxSJLkLajaHneh0lsLTCMnWvOC9Spclh2Lz+h5ZTXKTGpmVibRHvtg\n+EKP1p1hMICEMbJDPDxZbRUIjOPxQ0VAy9ZFKSOVrXhkFuc7Ihzd3pAQJv8k\nd/ho+IjrdVZ7C0W6paZDLkmtmwOn103mpoQbBSdkHQ0EtO2xKhbWKepDulXn\n7sNk/P3oz9NgNZoBMuyVY2cP/Tp263J2qvwJQ1XLMjSNmFJA47s3/iD6UmKq\nVzfOPTU4LehjbyLxQzI9UPG5tvuAac0i8mGNjQuyW+SQqb+0DrLKw56VybPH\nyrAvNUVhzE8gHBrWwp4u9hy5xYyc4t4GYa5JnoZ+WnaT8rM2TkMcDlX3ntO6\n3Bpp/nuelDV9M1HX52/1JUn8d20gbBIQ0q5ZLpxck9VE91K7nq/6IHrGOof9\njKxoeWqkKRcIDdnPkPhQV9oTg59A4yGS3gJEmLcngBp+yM2WIKLqlYmJh6ev\nxlsG0e2Vb0oKxCbtJJe4lV1K97n/yP7vY6Hubwk3mtrW2n1GUcshwn4dsnPN\nx42hCkNww91SC8Vim1YKBONdID1Aw+Hizx0usE/dCl1gOu3ZsvFVbsVLhMSp\nKV3pBvzM5o/R0BK0U6ld4jqbpZ/rDgjIojBKn5N4KYHDlJjcwFYNjuAuOcHq\ngXdS\r\n=1zuO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGJogkDglng4S0+zldPeJVJqwNyuKY/PRL6/4+sVLMIAIhANRae1KrN1iTgXOlw+pTK+zI0xpecn9yDUyNWrB1VIB8"}]}},"1.0.30000960":{"name":"caniuse-lite","version":"1.0.30000960","dist":{"integrity":"sha512-7nK5qs17icQaX6V3/RYrJkOsZyRNnroA4+ZwxaKJzIKy+crIy0Mz5CBlLySd2SNV+4nbUZeqeNfiaEieUBu3aA==","shasum":"ec48297037e5607f582f246ae7b12bee66a78999","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000960.tgz","fileCount":771,"unpackedSize":1353040,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJctXcOCRA9TVsSAnZWagAAFzAQAIjKGoZuIeFv8zl++7bk\ni0UGZQ5xMHIx86Y4be4Th+x30gCQXzJue4bCoQXYaVlUW2YkvTufKpVEMWUD\nzgt55+Er6vSZSjHZIO72mhE4BYK6bp2IEjBIpvL8DbjB040jGXti9dnd/oio\n2LRygvrsz7hc7F2srMAtkeRc+Jnzr9U3D13eTNVkjAPX2FAhEEuXS4A6fO0F\nmeh01D5EAR37dnK+JsMbkP+qM8nP8sCBbrXflYll4JOklh6ANzNIhrly/CK2\nu6n/w/pTqk/RIcLZakuuWRLPQikRzfyv+twWzJqcor7XQyl0DK2xWGGHhioi\nMupjt8pB8AxlVzYWKK/yeV3LOzyqoBuL9om/wsTnQeLyBixkoNgxbTgb/45j\nnoIHalM8/hpYsM5kduu2i330UhEaP57QmNGOrRCuVn1ndfVjH5bPA/vhKVr2\n+lncsnCLe7OvfTadSijDrFQSeumwE5jsf/I2Drtup1u4gUMlNOGMIgHMDi/o\n4/zYOI1TNXWkmXa7DLYU1pjGuawLH2MlWacZfO9JK7zVNcyAuXQaAWQ3hpfA\ntqL2hlGksOPmqPVFwZtvRYWoRGNv5OttZFY5c7/OjLVmInqRXrcTOXT9q7Cf\n21tpQuCFLueS/nllq8lkAwF6QhIWExgxYYlanZkJF3vvjdNJZIkJa1PsTEAP\nFvPd\r\n=b7rI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICsTRzJocJvemWTFj3GT2DDwP/Ss3XqeP7/b8AsoiMgrAiBIgyqom1vC0Rly5RRnABdIRN0P/40UVyqJitceYkBgyQ=="}]}},"1.0.30000962":{"name":"caniuse-lite","version":"1.0.30000962","dist":{"integrity":"sha512-WXYsW38HK+6eaj5IZR16Rn91TGhU3OhbwjKZvJ4HN/XBIABLKfbij9Mnd3pM0VEwZSlltWjoWg3I8FQ0DGgNOA==","shasum":"6c10c3ab304b89bea905e66adf98c0905088ee44","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000962.tgz","fileCount":771,"unpackedSize":1353101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcuU9qCRA9TVsSAnZWagAAHRoP/iEqliQ+fK2tJjywGLJA\nezGFFUqU1ZiB/rQ680KIlCxelLcwDX18NivOsQ3p60q0B0kghpahfutpJv+T\ntbjJ0hNXimFWu/pkBXJsop+nfsJMsQNMwSTTKme0WlGfvA6wR9UPd1834Hqp\nZ4ioUOOcOxxmWUYT+77zCRO6nwNIK6GAguvMvWZf77yjGKfvrAx51Z17zV69\ncw2XpCJrMBvzSFuZjGkuWpCmWcHxVRdfrVqwfJAsaX76I/6dYX//2JF/moBK\nv+K1kGWt0gTkXAZwdCwUowt6hdcbdSM0jmLf0ITskED5WhsWAqgcSGj8EFu3\np+rL/k1ZdF/SJGwNNaCpbv6YuGeEvXaOr2KfgKz/VjiDFiHKV3852yBqD0+q\nql2hlpi2BU7/w6cTSveJDbhbjuZD2Ykdyjkq099weKVXjvUK4UNFNO5tm7yr\n9vQoC0icDjZ2eiNjdDWgOzbuJthoWrRTpCFWXo0fCVohvKuhcmRTIGFw6rrM\nJB6BCVnRQblMsGQnYDuxRwEcWlDbsF7XsjqoylCYM+r7JutfVxLAEwRuSuqF\nqBNhYExYm3KfyDWiTrJXtE6S1i5bOGlLH1xKnAaCLcecMLzxt25xs6I4IdC3\nVKsCOG26cCXuBv3GIc90AbCgT6KFHVn+VGM3FzHavvW2eHSP223X3bnFDJNO\nQJSf\r\n=sB63\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDv4UMCp/gAnRAyHA19EtfTQnMq33TF6H5fFEUv12QMUAiEA0YJE4i6b2zDeIO7oWHgznOgMz6T8uBHXHItBeSkI8rI="}]}},"1.0.30000963":{"name":"caniuse-lite","version":"1.0.30000963","dist":{"integrity":"sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==","shasum":"5be481d5292f22aff5ee0db4a6c049b65b5798b1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000963.tgz","fileCount":772,"unpackedSize":1354147,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcv+bkCRA9TVsSAnZWagAA5TEP/j3uGjWPbp7cuNrfqNMc\nnFlaeB39Nlz4fe19EUSGbRSdoDTNCaMNBW23h4Ovre2FCF6BdY0x1IIBA4Fe\nbJpKlAeo+HQAj7xqS1su+p76OFTGNqXIRvY+F8R9O9UYU89Ab/avsHk4iRWL\nDHx1LpmTznQMvqmX4XXNAy9rbuP5QTLxjodabUPPeIzXCPpA6grRd3NSbb2U\nvWVwXeTOMMAB5DtTT8pXkwLR8FfXHgEoV0Uu2S/uXsEqOpXKphPTLk9Zg1rr\nfhp8FBsKrQqdhd09nkNT4fLYBm8vTG8B8VUHGa6NAc5vLHeRbrtlooTG1mN3\nhGakMHOexx9YxNU39JINUXjH2kQlrzQzbtsYqueKpOL94KAUdlUXqNoe811x\nOQqn190pFcH3+MnGEoXlsoJ22gg/4eD/k4fU5tEyUY83A+g8w4CmI+7ZbLLS\n0Rvt+JWADCTCLOCMGh+DD7lcqR+Z+5XGH2YYsBoQQh/ACn89V+01L2hGN4U/\nTVlklh2MtFyOnMLQkVh1DZL9f5LjfNLn5ljmI3Y+Qb5yIpHSO+b8TmbzA5DF\nWIgLBqVXq1CO0bN2SggxommTA55N9wukQdj4ibQoPeDY29jJ8Vgzf46NijPh\nmFA8U2ohH2yhDqWHFXyaRcK6aXo7UWHHhevp7OqkHmpoKCL9EDTZn1aGrPxo\nLzOD\r\n=4ZP2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDH+a5ZmSmk7bS+b8iKudYs+SV50bJ5T/3w4p+u+5fF2AiEAu+OO2jPmZIzt1tsIYsGzsHPHA0CHiiKwt/xvSmuj13g="}]}},"1.0.30000965":{"name":"caniuse-lite","version":"1.0.30000965","dist":{"integrity":"sha512-BpMi+Aq8AgNjjrfornip07/BTUN65CTCe+fmZJxnmnL9CUZlPqtLIRdC6pgxMFOohg4yf/f775f/NE4AZeoIDA==","shasum":"b7cb85847433f0b535efcc468e2d5b70aa3dc428","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000965.tgz","fileCount":772,"unpackedSize":1354231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcy8RkCRA9TVsSAnZWagAA8D8QAJtegWQDvuOzl3bNZVDX\nTt1BEorVBEnas2W0uwuU37PHdz3CGTDMIG6bNM+R1T9vxHOJXbIUa5UIc922\n/oTk/5uxUPVi3GboosNDrZPc5z2vYDaapWGUzEnmTQwkn8DVuqcEcnONZdVr\nZjrFGa5JrHwBLGn0DBKFmIW85RdOoDE0nBu82m9D17DbUVD4kbLq/PCAPW+b\n//LZK/vpd4LbiMclFTov8QN7FPLDZcnxUVjA66/lwAeZVtPh+SKRqCtaDkwk\nAtUILDEZ2uHB5GmUN/0nNF0HSEqZcAyzzmCVyRdF7VQuG6Hdrr9qvBzmeiTW\nQm5D60ketRFijXP2ypAqALtFuo5UI+zivEvVNQMC6PzuA+vLj9YIIF9dMbXI\nSt6EVOdpsKDfFmlFlFrss1e7xpwxo4HNJmKFDnR7Ncqlvk8A1Nmy0eHEGhjP\nTG/tEdsQRkfrIMrL6s3+2StZrBzfoC3NbMImEe9zTssN9NIXkDXBkKM7bprH\nJ3IciWAJIj+n7oecpxOE4Z9tGCttKYaoewEEW+SjyU7KJKqK0Un9TZtgzmWM\n3NiKCtiYg27fX/ozbtibkcDoMnBmpAdQHr4Kjl1ET08mFSBHsW2M30tIbU0f\ncrIOb9B6Hp0IeTarPx31bN3iBbq98KMo5/WwjkjDmtfyP6s73OtgsEDdLBe4\n63vw\r\n=H0Eq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGdcrIVQrHg0enyCGoPwDKhzjLorQSb2+YZ/KTXsrXWaAiEAu9AVH//QY0F630Fwwb86BOMLf/HPShHFVsRZy9VmJi4="}]}},"1.0.30000966":{"name":"caniuse-lite","version":"1.0.30000966","dist":{"integrity":"sha512-qqLQ/uYrpZmFhPY96VuBkMEo8NhVFBZ9y/Bh+KnvGzGJ5I8hvpIaWlF2pw5gqe4PLAL+ZjsPgMOvoXSpX21Keg==","shasum":"f3c6fefacfbfbfb981df6dfa68f2aae7bff41b64","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000966.tgz","fileCount":772,"unpackedSize":1354312,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcy9J2CRA9TVsSAnZWagAAN4wQAI53ZRO0Cs2n83WkMRU7\nAP4YqPjHpJ0m9FQ65Y/7AJCCclJWKHLGkcplZ4T4isJNTYbn3Tn0uW0CL8hQ\n2MPlNEr5fep2hEh5cQiPo9P8nKCkDWnQP6jZpAKyyA9J3fUnbU1smYKLrxrG\n+1YRjsNb9y1uDtl7+zUFdaMg/03vqMZOZGEVnIaHYiSn1kZml9j8uF082Qv9\n5Ev7qDi8FjnYUPp73dLuc5+EVKyixkCqc/aaxXB0kV6IPWpVT9yolRFYzOnf\nia8m6hMeIuGcguHXzWqQOqPYKaiJK94hnRwk1ZPUhSiWzo0A0V6aJn+yKWCb\nTV+gxEO0qQn3W2CuRZYWkcNpD61REnSSGVM6+64cv3VVRbegVuLi+Az0vvc0\nTJ1Xmvv1A+CMIBCo5gVWvz11k3aqdhpCgKBbkENOMxDZNtcL92R2BdKAyX84\nJTJV0v+5tU3+rRscO/6ENjsR1li4Q/fFgFlbm4+uCPkGuRmkP4oi+7mHMvGG\ntaAKXcWbXzzj8p7AHu/1H8Bq9ZFEAj04d6fZmOjET7NPiOqsOM0hKNz6NuXN\nIwaUFIVN3s6t8rpxYUNleJPpkGszhhq2YVCRHLa4XZ09fsM3Tw0yL+r5JR3u\nsn8gy+GMyIbQpB1wuffNaPCBKM+VLgei8rBFUw5qB1BZcSnsNi0CiBG7JgDZ\nfiK3\r\n=AL0P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDltzNtfJIuGU9Lv4bbqeZxhLP30DjE8gLHsY/L3siKvAiBX7U+kQt/tSykFXnyWO1RMa/p3fP5yKNaQ8gGqCC0EAw=="}]}},"1.0.30000967":{"name":"caniuse-lite","version":"1.0.30000967","dist":{"integrity":"sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==","shasum":"a5039577806fccee80a04aaafb2c0890b1ee2f73","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000967.tgz","fileCount":772,"unpackedSize":1347797,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0Rh3CRA9TVsSAnZWagAAoakP/0bz3/yZ1EPh9jTju6wZ\nsF+FVkRSltzfFb5cWovm8Dv3F+nFu4BjD/5gk8nsv+LjaOuvvYzkPqaKNMYK\nLP4ofwgWSZyVE8NV7NMy/38lQgRSOYC/mjJQQS/H/WiiDhK1ymne6OgmoPql\nZQM9/R4T6iRw0z4woVzl6lBnjvCtduDMKJoFIcN3dyttjsQtyy8chtFUvFR8\nMvYkuz8DJDG1L1A5ou1ALeiQgWvy96qS8bU1vCINs+E5faOvuB7XhW+68y9w\neP1GHxeFIv+SXbUyn0stTKieBAFOazaBJ2OoA0n6qFzZ58l3qZ1nxLfAAN1g\nunlktI8QvP+EHbseJfxc+GMQPRIc1ATQWWeLXhYWpB6GMRKIx/LjNepko7Nd\ns47U1zeqllpz6S2cN558LqrhdfBne0NA6Q/27KbNckW3fA8+pWgG3AWbSbhE\n9amcdE5q8SVqYbPq6lWCeMANr9Ngl9nyavsl6D6cENPS5jMIg1Fsxt71pXiP\nLqbt/+lAmzEh3m+T9onVtL3yzQMHTmPOoTOqTmoBWaMKpk5FhvXh8u5fQpxu\nSp2ZuXM8Dtb4wrLE1KqrWejzBcTWu4my3q0ZRXvaCInHqLgRuTXccDo2wg18\ndBl7vUX7crulkrBLsDnslEIkO1HHTH76pjII6h3AgcUxFcDzuHP/q1mXRbLT\nx448\r\n=VOrd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBFQA8HekDfHZuwa7iIJApzQ7xbef0hGzhRpmQZ7/484AiEA9bHULJM8sDhTwFe5ZzJqJspZUnOvNikDQTHUt+4DuEw="}]}},"1.0.30000969":{"name":"caniuse-lite","version":"1.0.30000969","dist":{"integrity":"sha512-Kus0yxkoAJgVc0bax7S4gLSlFifCa7MnSZL9p9VuS/HIKEL4seaqh28KIQAAO50cD/rJ5CiJkJFapkdDAlhFxQ==","shasum":"7664f571f2072657bde70b00a1fc1ba41f1942a9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000969.tgz","fileCount":772,"unpackedSize":1349481,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc3NnTCRA9TVsSAnZWagAAnkwP/RqZLoK0SRlFDSOWXUia\nWX6rUr13z+A9hA/J170FBYTE2rTKE6viHB9iP6FMIlWU8bzEQfX1QZR+DpBs\nj4wGqNAtXth5cQ+/gW6m+gkbD3M6RbmT+RU+9dXOhczCN5AuoKxONVu7qLIM\nXcmSgYVxDTpZVBuclM6aZwCyQYjk2BLygXXYIwdLF5Y8yHflmbPovVOLrrM4\n2gMVzuu++J1KWM+LG7OKhb2p0r/oEMkBWeraByeDaAWzJJS7bet4d03ZJVt1\n8UcV5fC6e0tsOs6r4u3ymXKlHB4N7Qyo3v+lB9lbgIHGYCK7HYSYs9rHfofn\nQaIgd62szIdeJDj65aulRBxdzGntxPTShxvIF+tLfj702DUxjmCZQZ/3CQl+\nXIvcIUiLnRwX8qEy9uk6K+0go2TS2Q1f4/qFN5nb5FC7RBFXymlel/KLi4Zb\n1B2BJcLu3R8oAFbOgWuYNyhO3M5g7k7ny5AWQyli9YOYCqONf2m0aOJw2QrQ\nvaBJQmlKe/FLbnBLtmYQYvwcDfDenerUpsp8h03tdVAO6hA5XFm/PblMM0X3\neuyRyp2Ex/TJvYsQ/GwkdKmEtmT0b801tQuPHyu2vlCtxGSEDhdvSywL8ain\nskmRiYFLy3bz7Zo6KXmmvNug6QrjsM1p1HlRzyejjP+KgRq+hPGuNkpwacU4\nfe92\r\n=GFGC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDS+DonM3z9OoJ+KPFCsEnCtFwhx1WymHxm9t4JEMj7IQIgP2KovhP8TQALIy13IxaZwp8YFPa1uhX5Z72P7UgGobc="}]}},"1.0.30000971":{"name":"caniuse-lite","version":"1.0.30000971","dist":{"integrity":"sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g==","shasum":"d1000e4546486a6977756547352bc96a4cfd2b13","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000971.tgz","fileCount":773,"unpackedSize":1353737,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5NDjCRA9TVsSAnZWagAA8ZAP/17KeVD3mu8qnhjn0AHq\na73qsnBfM3R5Z4pcrlK3Jsstz7WRJgcGs/WPCQljpWJ73lFEtVnyskobVxiF\nZRjQvZS+JAaRFtClWA3E2Jux1leap2vJxK/s/clkOc3CflcnAALrP+Kwe8kj\nAML+tOdBo+fbm2zAKZuYy8nFHnuXwiXFCogqd5xwtvPZWBYNWXqFf13gBloW\nj6uTyNkMY0N5fAu51Siy+CpeD8jxKTA8fcCpFiWyGpvg4hBtzeac389uX8Tk\nCSAtNbdpwZG5sZsp5cTT0rd1bxPcmMw7GiurH8Nm+MyFIqZ3kwWxhSePwpGT\n1EJ24CHlAu1AvyLrZM8aFFWxQyLSXSKwJuO77uplNqHryQ7ZOPzDwZ9YY2uo\nHkbVlGBspGrieiEB496IO1AhgLJbbU6E2Zju46TWdrqNLRXu8SDtoWKMWWrq\nLA7Ek4yxrWj+i1TXUdeI9bK7Auf78k26povbbo4RPuw2eadD9H6UpwhQSP5l\nL+WZrTznKEFAj1Dr4+dQWaqtmPG2+Q4H2LJ3soewWTPdxqXjDjaG504S27l4\nS+Uz3wi5UgaTfRz2qhN7z9EfYhD/Sx5o64kwaV9BinVn+MDdLjN8TefINV2i\nBcd3jSEKk4HQb7rx2YSi1KiAznzx1d74tsVy9AVOqXVwEb0RJjM61Y9eNlJS\nLl+I\r\n=nzOQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYWMbAvnQeOEUmVqyw+79hZf41gZ0Ff/Dr6A4UO3X9agIgUTbTsFIhNVuTN3d/Y/Tz2QHlzalTcBWE7ERUXAasNA8="}]}},"1.0.30000973":{"name":"caniuse-lite","version":"1.0.30000973","dist":{"integrity":"sha512-/F3t/Yo8LEdRSEPCmI15fLu5vepVh9UCg/9inJXF5AAfW7xRRJkbaM2ut52iRMQMnGCLQouLbFdbOA+VEFOIsg==","shasum":"2f8e8e54f9e6c5b7a631c9e69bfa1093d8cfd360","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000973.tgz","fileCount":773,"unpackedSize":1353818,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9hCBCRA9TVsSAnZWagAAAiYQAJx05N1gwCXPU+ZvcpQa\nOI8fyC56AgDTsfygXC1EzFNFCvQj8WSgaxb16Wm3NK6JI6Ed4NlT3Dg2IyB1\nn//BrZIZUP8OE5383BUZbBhIA2Fg3jUHpyuPj6UHEL/NFfmyrVsfinPCwzcQ\nMZNptGvFq84GSxhxIwxsz+oEkED0AKXQg5+qxL1k2RmvkZUX+huW65EUw7Np\nTc8Z0S4nSW5acEJKUK+dhoRyMjsl9oJrasJsmfzo5c6IIteAAMc9XMNUQ6vE\ntTudQa8p4if+Ezs763GuPikanKia/vyvKeLzhUFLGAOIzbhvHLLOLlL73mYF\novGCN2Ndc+qAg21Qvo9by9Lvgw1/JZNR1txZez5gNYIhajP5H44+ce3fcwWJ\n7LCyArTSqaQDqXcFqCjOuy+96ICHopbnzpv93RQvzOc8zLF5m3CT5TMDiUSA\n34emu0nGv17b6tGEySRHiJ2/d6dzdMfNN4Trzegp+7WNhkpvsDGLErnSNOZ6\nzRmtKzhQBjuti6A1D7imv93p6WiQ6X/UYfyD3mhkeEoPnbDWapfbZcVKnXJ8\nVPHbNup9OgowU0e/4Qm6CQ6W49yZHbfPeV5pn+xkHBd4pa/XWkbyKkQvR+oY\n5Yb4uo9w36msbecCJB+mFbvk3cJaP8mPPl8SlLn+gIC5FYY6kQxqF2IzzJ+7\nIWsy\r\n=RRTz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEqokA+Rsf/IxTckLekcElbPRHz2CukI0PCA45CMrz/FAiEA/lJTTb6qmlKQJ43LAxADzYYSK2357/aYHcdjKiJPp/4="}]}},"1.0.30000974":{"name":"caniuse-lite","version":"1.0.30000974","dist":{"integrity":"sha512-xc3rkNS/Zc3CmpMKuczWEdY2sZgx09BkAxfvkxlAEBTqcMHeL8QnPqhKse+5sRTi3nrw2pJwToD2WvKn1Uhvww==","shasum":"b7afe14ee004e97ce6dc73e3f878290a12928ad8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000974.tgz","fileCount":774,"unpackedSize":1354863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+LN/CRA9TVsSAnZWagAAjK4P/1zz+k8tSVeRikWwYBro\noW1hDcLjYxK5zim6oqOAyrIm2oR8sNVAyD3FdamxGuoGC+0K0XQZpiKOi6vw\nY1OaoTWRgYTYDmJmjDi4UlGkheJbifg0kTVqFoz5pVgABa3OzE+WSlrYQcwq\nuC1xtTF1+FpOyPdnz3e68/P3ByXephx5kkUOjwYNSk+Ln6Cb3tKxF6y2oB9x\nUmtjYV0EmLwi6km7AlO0JWeE8pNzCW8P744ZtiEt1MbyoFqh3U3DZr1ySF/5\nnuYRMxnqEsbQTkstaIIptDsuAJkUEkemJJLtKsMtKcPTqw+/WAs/BTNU+tgc\n0CVCA9RBv9eR9l5wWsbDhXllNkdN9Y9yPwblICW7rbQq+v7yTpq/DmG5MA48\ngV41GZq/XefRg1lZcmjiTkw41nOV9XJ0JR4fomngu4CpB5M5VPcQ7EbdwfoD\nRNdOOd5At2nifh1RsOH6gDW+RU19BGcsz4dwbdG7VgeOqWpRe34fZV33wWgT\nAz1iusdK2l4Y1x6nKUpLc6RAewqgrGf/cSJa0eqmPAMSzLHF49Rm+Ts3F/Bf\nVNPkwH2ZBJm6Jd/jt5G4rpnh8lNONIAa/uRwtLZeyJrtPIBNQYte/8IrZujM\nUqj+8ETlx7gaj5mFDYv4wd+/rJdKAnGpRa6gTH1So2QxaqQjoGaD5jPZ82aN\nkOU1\r\n=har5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyXUlokdCWbyD4Mv/RS7AN/PWuTd4Wxvw3XrG/bGlThQIgAurA8Cf5sqpIBaThwMbbSJ+JJpN2ngxxxv++nIgOiqU="}]}},"1.0.30000975":{"name":"caniuse-lite","version":"1.0.30000975","dist":{"integrity":"sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==","shasum":"d4e7131391dddcf2838999d3ce75065f65f1cdfc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000975.tgz","fileCount":774,"unpackedSize":1361697,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCIWMCRA9TVsSAnZWagAAt8IP/j5BqgOKMMZEuEQnB2Ij\nl2tJZJU2TTMRAImtxNh3q88sniOd7n8+KqFDmdUTy36d5Vw6vc9oQCfD3bJA\n5wR+2rB2eEa3rIf3uQlN8yuHRcWCt4TiTM6QT74nH2yeoMueOZEIDzuZSfut\nxBOLbr30bHiu6KIOPAuMLj1ftMPg//hfSW9CIzjVGSTTMHGjdNdDKnYRaxxK\nUvHIgu49wsOOnOBpq0mD71GK08yYTt1IDe3/s9WyE25FZAW07MiBiLNLe3mU\nKI545uFqntjDTIUgowcshzlkuUC+djisJHkr+5CoJjNNQlAU+9DJ4wH1ZEp2\nz5WA5wp2ha8L2AMT+S8gdpjT/JAiotfqJzgWKXcfmor+pk2n/5CKI/IGeaj4\nwL6S/U+l/k1MuzpW4dP+lxUmNs2Wy1CXaPF3MwIkY1Wvq4nADzDSaF/qau+V\nawOYVLq/N5V2OIDscyw0hVA0bkCC1eR1u6eEmEjE+x1fNxmJ0Yji2vOZIexm\nyYnsC9Ue7L/eu+sBWnl0xWvTrjFvb+flXsp953+hhjwCG1v77xAvD8KUJSqa\nRqFobZJDZCP7ywTaLxue4dc8fnNv12kbj+Pr602PCGPDyox8EhoyOM0Awrpo\nxob1yFuJUruP0x5mrHCRUKDNzaraViO/stW22W45oukqMzo+q8GIXyY7sxhB\nJcXk\r\n=H5kH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxTqn9TjMSM4TpB4h8SnwjgNwhtYdGqB5l60+ZZvawFgIgZBYvIBndygl8D5j9FIYQqZCwzmACd2el8LJo6Ow7prk="}]}},"1.0.30000976":{"name":"caniuse-lite","version":"1.0.30000976","dist":{"integrity":"sha512-tleNB1IwPRqZiod6nUNum63xQCMN96BUO2JTeiwuRM7p9d616EHsMBjBWJMudX39qCaPuWY8KEWzMZq7A9XQMQ==","shasum":"d30fe12662cb2a21e130d307db9907513ca830a2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000976.tgz","fileCount":774,"unpackedSize":1363296,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdDHoGCRA9TVsSAnZWagAAj3AP+gOmYj04hiZFPpvr/A2I\nBk4C2ee/4CySigyRFa/VINFLMTCdkG1uQFvMFailBZAVEhWAMaMyFte89w0S\nqeWVBuW90LY1G2/J1XSlfz4MJk+1you9FsMY1q1HMGgrU6tT09ZthQ7hcFGR\nWBC8waCYVmW6/SZ4mN9R9pFYWX/+YxJoHzKMT0vAMn3sRtso889/7vDlpbAy\nzFFxU0VoZSvii8Cfojpdezm4a7rJSfQKtNzv7s47/8+Csr/lAly3A+SGeQyG\nRI3ZjFMLOogjq1X7KdC2vipBaJPD3xAfit3XslaFTIyCqeHyswyBEbDjrJlq\nGBNhipqDPbjvfLVQA3OMEfCN6Cl3x5NMScZ/ePzf+P4eP/9/ypqtytDSneHQ\nbKcNhX1wSnamkp1tGV8DXgAXhgvRGQZQWXgjkpoF0aAGQ7TlE6COke7EJraa\nLA1LrhdLcYBFwd3hVcKFMKC6V6cMSi/lXka4oMKTISWB+B2Fac4j1Lg24O0O\nwBUSGl+XktkQ4lQqXgYZfnMS1X1So5ccioVvNJm/75J6Pwx8fjM/QfNnooTe\nlxHP7Iv2TWnKqfb4xyYnAQpjQ2q72xYedqnIutt7hBhXppvrK60gnN4M5+Un\nBEkNtG13x8lGxJCEvqdSLa1P0rbjnAfQ/G1jnoKJA/UaTFaIOBBugHmE3YAl\nNXen\r\n=zxRg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD14+AdxKMNx6uENPmb6zgFPmVfxgMtGBOGNWkYpcjdQQIgaQ8m9C6zUSJQhrUHaqwx/EpPdc4Cl751KPSvOUQ2kjs="}]}},"1.0.30000977":{"name":"caniuse-lite","version":"1.0.30000977","dist":{"integrity":"sha512-RTXL32vdfAc2g9aoDL6vnBzbOO/3sM+T+YX4m7W9iFZnl3qIz7WYoZZpcZpALud8xq4+N56rnruX/NQy9HQu6A==","shasum":"7da2ca14cae2fddb368c05c57ab4a529afd658ff","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000977.tgz","fileCount":775,"unpackedSize":1364326,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdEcADCRA9TVsSAnZWagAAlpYP/RRoiTObLc+4om/ydxF3\nVFCxVKPscyofNhpPQ9OecYdvAaCMsjGHNK1yR9RZlJGnBxeQcWBZVQ/pOTzb\nLmAO9/XGbwRTw0FpPFr29+5XtU+mmd0L2o1uSnBQ+oCtRfMXZm9rKplLTech\nAobtyQOoItOP/LHzGFu8OCnz99LBVGoWzojDvBoRd2IN49mBlsmOA1z5WQwc\n9pjl/tYyrqMgrdGKZK3SOeea+d8Cw1QMs/0M7tPQ887CkIkk0LPRJLFMpDed\nErvCazXgrT3fTRg5GKk0fo2+nJNZCpd9+PaYrJdBuRtvDMyhF8804AdjIeGX\n0/ANVyxmrz9C5MlppgueImYzhkvIJQbrSVVPX2sNy4IQbQCiSSuTVNcKoS5P\nBewkTkedD6mR5TO80J/M+Z43iRhnqykj+V/UIMqDGnTCZbSgSHn+5bles/Si\nZynUF9hPuwjV553tfwlD5ZgN2jxetBOJMXbUtFGNlcnGLWxdAlenK/WMd9UZ\n6lRKxdm960A5w1w+T3tMTk7D3p4wrsVGpjGGqooFnEElZo1YOvPUSSPo8nla\nGcAqunaD/EnH698X9LDOFUYbWy7LuY0ucKobyf4GRYwV5fvMukm0+nPvOwRZ\nSC+3FaRVs0JEOBM9ED84e6UKIfZTn5RDnP5USl/fvnWIJPWuIKhsM5HSQpQs\nGP4j\r\n=w6yh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL74SmDy3EQ/2d4IHfGigLU8158KPu3dT5OlBShqgn2AIgEvvN5uNAKlJMWEzitZ+8VNj8BwQm7htTsevs6u+bqWM="}]}},"1.0.30000978":{"name":"caniuse-lite","version":"1.0.30000978","dist":{"integrity":"sha512-H6gK6kxUzG6oAwg/Jal279z8pHw0BzrpZfwo/CA9FFm/vA0l8IhDfkZtepyJNE2Y4V6Dp3P3ubz6czby1/Mgsw==","shasum":"1e3346c27fc46bce9ac1ccd77863153a263dde56","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000978.tgz","fileCount":775,"unpackedSize":1364399,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdExGECRA9TVsSAnZWagAAqK8P/ieVi4CmG5N6JRI8oIdl\nowAI4l2tCVNk+Cx6YMXaSPiacLViwGwPOvLmiv3HtRI5rIDQLv08cLmP1wn8\nDXtmafLL8SYzKFzQjMKjOKMfBgBRd3pVnNcnVpV5zFG7/aKtDFwbY+J+0gT+\n2cBX105BMn7LwEjp5JIDtyuXqVD0TAI1qL0OEccpOtbaJbGzk3ikh690EtZw\nTaOY5Z6bnqHoSVCQOVe4oeiQqCuQcg3m76ev3WSHm64GkgKdSvVwo/3lPkoa\nC7WNTowVan3hVCWbGfAUIPZgt6tmtVLzLQg7NVkng2OF90dI95/aZ8Qb2qYg\nbl4Ew+5JYL8mNFutOesh+oKS8Ld6XDPFa69yZ5RbzGqYSzy6q7GrBkn9IPyG\n5Nu30Zp2bHOxXObVteJ2mAIYrPVKKw2Ql4mFoWSR7ZyMkXqMvn1A+XlGgeKh\nScfo90CXMSIz84gsVaVCLWoO1SSewRNlaTdq5eHPGu9eVgPboSsZFqZX8WMk\ngBe5l8fwofXb+4DJi+kj/5HT8dfkLdEXfH/LjfyUMwfS640YS1oYa8Ao4TSE\nwAtQ/vzUtbsQKeV2p9xMID0m+TOBNa+fxa+85JKxawzcJXARIywdzwbKmDi2\nM4mCHTTJ1Co17JXf+VuA2tRAcGZpz7T+P/cT8FM+eNl/s0QTVu6XhNbHIbbI\no4zu\r\n=PMPR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPMzwGtytRhqnvDsqw33p0gZt1Ffh7IN37HPmKocQqjAIgQDbVd9YdkzrCIe9Hpjn5QsB37hbWDq6M7tnJJO39b5c="}]}},"1.0.30000979":{"name":"caniuse-lite","version":"1.0.30000979","dist":{"integrity":"sha512-gcu45yfq3B7Y+WB05fOMfr0EiSlq+1u+m6rPHyJli/Wy3PVQNGaU7VA4bZE5qw+AU2UVOBR/N5g1bzADUqdvFw==","shasum":"92f16d00186a6cf20d6c5711bb6e042a3d667029","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000979.tgz","fileCount":775,"unpackedSize":1364467,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdGakECRA9TVsSAnZWagAABmUQAJw9iggGG1XjRCv2RSGa\nTR0tEHR6pMBtHkU7ZvvFmnnj63NWc48GP3Mcv9B3d+XuZmRAuWYjCpNowX2U\no6P+zm00NI+E4Epz75zb2l3UNHKBFTW+O8GOeUgrlGgZYFrTq75pGk/AWJxP\nmHI7+PRgci+FvxwhxnGknF0m8ZE9CszQ9YTV3RUTgdWmB7CLkOhmqic20iAr\nUChh+z278jCeMg6JMHk85LlQyCm/UKf5pup6pTmH3ISwxk7mxch57+2E9OUN\n4TwujgBcfWtKJRxfNH9rqBQlFyZYVNG1RhT/1OxMkBkY7SEGaIfBlgtvluzM\nkMDzwj9g+4/ZiwLRX4jfR4RYApt9qDPw9VaH6KZWBgRHrcAInwvckD9JBons\n0u2vLGWFj8gF+pOUfJ+H1ZjJTJ+1E+FxO7BFRRaSzehh26RB02la5KflsCnt\n6SWObbPbTMzV4iDrzn9/SdvGgkYmnJ0kJqtB2HozrPnzED/oimW6EAOjsaR2\ne6CnftSDAYrd2Z+Yz2k2ZiFOtJ86rkhfqLv/6FG9j8ZaXV/d1r2U3BZ9DVb0\nyb9x4g0RYoGRwaf0420oqKIvqYeNwWPLJ4cxTENlizE2vw/8W+9EjirIgd5b\nTZPuN0Jb7GmvfUW2w8VVZTD0kwmuY/jE4hLoG/3xMC+eCQVVFO1oairclWcC\nWMvK\r\n=g43b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHquIrPRjTU8qOFGk9Nop/jBYEC7fHT2K/tq7YmcLWHmAiA/rzDfimXDFX7TcN2VCx0TrZ+afZbwKmhdAQusn9G/ZQ=="}]}},"1.0.30000980":{"name":"caniuse-lite","version":"1.0.30000980","dist":{"integrity":"sha512-as0PRtWHaX3gl2gpC7qA7bX88lr+qLacMMXm1QKLLQtBCwT/Ljbgrv5EXKMNBoeEX6yFZ4vIsBb4Nh+PEwW2Rw==","shasum":"0df53e4354b3111f83ac15b0bd4c71fe92994231","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000980.tgz","fileCount":778,"unpackedSize":1367426,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdH4mxCRA9TVsSAnZWagAA2/kP/1wghG4twTMd25A/6grX\nsaElhVT2W8LB9HOGY46bBFOszfZXcx500zZH4SqyD/7BhqoHLtyBMxItRxl2\nObN60oHndnYfeAS2BWMwRfqhEZnH28Oqksey1YF5QpY4WQ44x3io4wPDh0C7\nUQFzPpwPA2CRiFrqWM410q+A8z9i1y3TNbvsiEXGv/5a2uU52L+17u6gCil6\nQlf4YWiIDBCuULKP1zQzEz51ptVwAj7CVltWStvMoRIuioeUCKezKiGkglFq\nHicSNOpVYsur2r3hBZV6129BBR3xwmoge9xSDsL83Iymb5/I6rMYacMdaZix\nRkj5mU8xfvHnx+arwfJEo2GFdilVOhz4H83YuSB0JBMGPw+2gW2SyIuYotNs\nyZjROUDzZcApR/WQztqAKnqLsXf7lb7DjvZF5uxoLMSfLeYJ95+KKJvbsfKR\n1gaoJKZLYHIgKIHyfvS3vtQHeCzlAoAQCjVdLKI5XO7NjhoZ5ncTNvdFlXFH\nFiL3EM9C4+cqXYxrT5x+NJWm1UYm+dF1B1pF6AzLJ+1r97FGmWzVfActyzf+\n1BWGJeUrlEjNUw4gz32JBPa2mGO3U3gp/imIXluDxrUuo+SqfiWoinUDRZqC\n4dJgQMaxfPs29YoTEthvnMCau0eEJnnshhmw2TuhhbsBj2t34pZcEpZmux4i\nA9mg\r\n=qVrp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDSZm6V9vCLdR4KS6Qmsg0iDtwzqDRbex5ETGXhVQnkQgIhAMYuzrQadVWdc1jhgL8Dtk3YHcJXQY/vbJTJhChJVUUT"}]}},"1.0.30000981":{"name":"caniuse-lite","version":"1.0.30000981","dist":{"integrity":"sha512-JTByHj4DQgL2crHNMK6PibqAMrqqb/Vvh0JrsTJVSWG4VSUrT16EklkuRZofurlMjgA9e+zlCM4Y39F3kootMQ==","shasum":"5b6828803362363e5a1deba2eb550185cf6cec8f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000981.tgz","fileCount":778,"unpackedSize":1367494,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdIuOCCRA9TVsSAnZWagAAwnMQAJxNvyjtvSljlTZOtnMr\nM+ngt/3FOC0VEd/FWrSjMJlGYCEapAzk6gQjrQP58rr8383THv5apkiv7HsT\nIEd8REK9rhofPYwOuPCF+n3xo40m6oAjiLFbed2neIrBZYQ4WQTOFevnQSlN\npulnIx1D0kJWUCC7bx9Zlj9CFTqOgHDYqHaN8nV07YPoaYDvtysVs0mylesb\ngDrIegrP8+PEP9z9MhJKBDyNMdrj0UtTipDevS9CTZFALWU9NYVl5QT/WbME\nnHrfVfShqJ5LyauTla6zWGuOWE0QGe9gHz0slICUnVrPBcQtauDGDqXSNoiD\nUquGq65TaCCeNTFttcQWthW4AGD6xv5GWr8tCp2ZZwdj8otO4lHlaeawFReb\nfWBUZNxl/KpSY85dsCdwFN4hllZ1SEyUJR5bcpU6Od1mFm5hCxDmgE6KjflK\nrr6bl2V36mUCvADTEXZvwnMrupOUD+WDotMt0pNBqiVMHX+LKwILiYET7Sij\nrgUmvhYFOraYGapXSQ6LouGfzDc+Ml/X+6B9CfNl+5eugBvYZIz5qHfI1x3a\ntQs6zHLzaZ+QhifyKPpJ6bYqR8OGaJWcXA/ceavTDgHRecRguSw8P9Hxnxra\nNw+bc/cZ8Yf5wwNuoo2RXbjveJY/4ar2yCsYBR/MiSBHkafMuVD0LF/vdoKP\ng5E+\r\n=MRXb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGCWGF5n2Th39Jc6d3keorNVl8eAF6l6gnL1YW8UvGuBAiAPihr2US9IH0fEIA+zSsDoQK8kOhnOW4hhXDzYiRY5og=="}]}},"1.0.30000983":{"name":"caniuse-lite","version":"1.0.30000983","dist":{"integrity":"sha512-/llD1bZ6qwNkt41AsvjsmwNOoA4ZB+8iqmf5LVyeSXuBODT/hAMFNVOh84NdUzoiYiSKqo5vQ3ZzeYHSi/olDQ==","shasum":"ab3c70061ca2a3467182a10ac75109b199b647f8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000983.tgz","fileCount":778,"unpackedSize":1379243,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJYaQCRA9TVsSAnZWagAAZQoP/0MyAzudBYsBNh378Nga\nLq3DVOnpKF6wE2O23ddO+njtogcRgdSC1MwFE3h91czEfVMJXqJcTNcGFJJv\n5BNUNEgYlJjL1ck2S8orHdEU5MVzsZFNh9TgucW+y1vgwys2HwcEvp0xJVxj\njxkquBHy4Cj3RGuvNTxhlMe3c4ZRBAaEGArRghEl3GuBic0/xM9oK7c+jYJ7\npS5QQ0oHY9/nWlXmBHxR7cE/85UtomDaAuYAmN9sf5Cr1MVxUFDeCQnRYC0M\n6EP7U0rmD5j/f9wrUZoqlmQDF01w0zpH0lwwKZVTWIFsqwYdKQjnNBvfQcCW\nThXnHKbp2OWNNn5dnRfU9E1r83/MjmY9ZVyhdFtKDqSG4N5oblY3UTfWsYkJ\naJPVFEn/kmnckF/HPGUCwlazXOU9dtLNR5kEz+AlJJAMpeibndxddozWAWTA\nJ6caDX1vHNZly52i+jeF5Tc+iAXBN2+KxwtgxGwn06l78mQAtFrjvNNdek+t\niyuF+19OSdYfbQo2yPu4Rk87wZIrUcIw40A34U1XPihLqal0TyavG7zpN7Yh\nCmfr6mDWwxxWzY1ysSViaY5kcbZS2OdZn9Au3OaMvHqUD9fACOSMBDw7lBvH\ndR23oJRMe1BohA03MpRBRFAhy19V9aQ8jkscFGETzmUYwBBcK/sADSyw0/pl\n9nAO\r\n=oyWq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF/Rm3WR6uvhDFzZMwchoduqTj0FVl8TaZumk2vVfULUAiEAkR6DVyUYH2XpBcuqymucW4ehb7MsfxOfjrroS5BWvHY="}]}},"1.0.30000984":{"name":"caniuse-lite","version":"1.0.30000984","dist":{"integrity":"sha512-n5tKOjMaZ1fksIpQbjERuqCyfgec/m9pferkFQbLmWtqLUdmt12hNhjSwsmPdqeiG2NkITOQhr1VYIwWSAceiA==","shasum":"dc96c3c469e9bcfc6ad5bdd24c77ec918ea76fe0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000984.tgz","fileCount":778,"unpackedSize":1388394,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdKWz1CRA9TVsSAnZWagAASFYP/2hAgCJvXDaTvCmysuMx\ndw4A/a6iv9iMdqUqTUNkFOSFsEO65OLyqY6+whxSsbbZomcRT99O+or66B1s\nfzwS079mkhjGAUwvfB/f2Sjsf4psmOF0VQEG9alcHQhhkVt9cBFoGl46RMg+\nWRFxxA+LSTQX7BeDX7P9SOZUuLmfXl+Uii/F2KrHogbvvZvezWiVqpBxVs0s\nbWEftbSaDA7qb/kdbWAHVKwOk1sEHSIZvkgVztRpnBZhmm/NcN//2Y5Mg2RA\nKReyL/H0tN1L9Be+lq5yynioL04HY4ICza7wyMy3elLSY5OTFfRPesqd1Ba0\nboToZl9wi0SyqRTSuBm8y9l/TFl7tgLYbRkEm1IEzpAPdHcN/fG9SUvZe2yX\n+PDvRPNmYK1IoRbZXQcLPOWdXMjkQ3Bu+ulkFih1DFFaQswbs0fphBxvvlZj\n6n14L2+Gz0gniZsF+fot9Bc/Y0aFFncPqNZ7GsNZSOn8Ae6Fri7HMAbPcgcX\nzO3LQDJGhtF3HjVXzu6dPcpnXUfljW/k+S8zadLJdAXxSl3U7picB1OS/+E6\nhR0hTBorTyrZIWLWHAdN53A4fOF4jdhzOxXyzZm8giA22SdMr8xcLKdGanzz\ntnKz7m9MPnzS/ZGF6ARIe3dEYmbYJmyVGfQ62lPYOECo8SNzvohwzkkijpXE\nitUD\r\n=7sg4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDln7O1H1xsIYM+xbBgy6epFzioPhIPBfbGfUwfI6ynzwIgIXAURk7fDDQIeWoiQflMSoWv6pnMxP3hXInGm1ht6Fs="}]}},"1.0.30000985":{"name":"caniuse-lite","version":"1.0.30000985","dist":{"integrity":"sha512-1ngiwkgqAYPG0JSSUp3PUDGPKKY59EK7NrGGX+VOxaKCNzRbNc7uXMny+c3VJfZxtoK3wSImTvG9T9sXiTw2+w==","shasum":"0eb40f6c8a8c219155cbe43c4975c0efb4a0f77f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000985.tgz","fileCount":778,"unpackedSize":1390041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdM/jzCRA9TVsSAnZWagAAE9MP/jXaLmlHnYkK83AFsnf/\n7CegC5BnvyHfHFtCeNgGDB3Mn8P/yqY/7LsjLJjVrLVrQhq4OvuD5oPZgQo7\nK91zU3gIc3SPdGimZk9WODQurxSd7/u6JO5JZdpIIlx8M7z+UEai2RRYnSR8\nA2sbT/avHy3CMJLYROQdCIDSW6bK9ft7deIVPK5LbNGJ5h8cnnAVesqMwpnG\nf2AvQvcSW7XKS86R2sApRaumjr/1lP8HmGXIYuC18b+/fuvIx1reBkBWMA4l\nvC54D49T9jDJxaCcBareF6Jpjf7TzHMOQit7MGe0iEdRhD9b0n0C4yD2sWbl\noolPy3etS760IB2v4re/7lqsVtOYitQ5x8nxq92qYvjEldpCxYRLAyc14fLY\nrcLUMzuQ+Ojdn6vLRbymP26+SPGlVh05gHY6Mb5VvK+5Y165JjDc+aKY7bPb\nt8pU5hqnV901A1LKWnxiZyQpJs9JfiaJzotUmnYk4UgPHv6owZRHh0U0Oy98\nKy348cxHM/2AuASCTm8EA+7m2uI2hpp00/Dmhlwyz0hEBgmeHDfgTaJIh2pq\neYnVAYnSNtjIjVD3gKYROBq5N0Z58lqgfnUeiIG/S2Y+ruwxNi538buFJKGr\npCw8o8i7JFthW9QhBo0cN5a5OmbJ2twx0xrjvPkkQufsVBS2PIPioD3KqCQ/\nehfO\r\n=u2gf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCnF0Q+3sM7gra7SNnrfzqKgMVSXcO5LsmUvAPnYDs0DAIgQc6S146K6flXETaXVPScZAQtk2bLgKsnA1Ew0rBsuqY="}]}},"1.0.30000986":{"name":"caniuse-lite","version":"1.0.30000986","dist":{"integrity":"sha512-pM+LnkoAX0+QnIH3tpW5EnkmfpEoqOD8FAcoBvsl3Xh6DXkgctiCxeCbXphP/k3XJtJzm+zOAJbi6U6IVkpWZQ==","shasum":"f34350e367cc900509511574817ac092112bf7ab","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000986.tgz","fileCount":779,"unpackedSize":1391117,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdO+HxCRA9TVsSAnZWagAAXHoP+QBVxc+A6RFHY8g0GwYu\nNQBRVKpNPn8SiLOUOSaJOP+X9PA+KRA0XYs96aLcejcMei2pyk4MJC/COLYm\nRSe7WmDmgJ6FOnhOcqeUoeWg1V7yXHmVbR0bZcE6LVNRW5f1xEN42exddHBY\noPPLYEFg3/wlYN8jxwIZIu98RZrlLoUcGFe42d4a+JMG1Tu2WrZVgvtSt65q\npMjIh1tN4Jb4KhB/U1OUFP6F1ykxPQ7y93HIUXB7Uc6wSQFHnV4L6dN9wEvq\nkfdPcdASmGZn1fa3opMbgk9YC4csN8qtZkBYP0825wq8vtdLxiU1d8qRkCrg\n242xJzDyvyC6bhc5fW5QTpvJyFP3V0tkf8dIrc+B83Hj4+E99Hk8vdto1Fz8\n765ck45E9WCH8mxgERJnE8f1uyEgLl4X4zqu7Xc5t/uRN3TKPq3wmRBbCfRg\nW162sM97mZysd95gFxpx2h4LL06QEZTafOjV06AdEogCH4ZGUe2csjuNVSoJ\nIehq0yDJgIBZnCgr6l/SBGXc5mFccI8fSocMG/r9twBS7AJvZn3hsZGL+RF+\n6eTWst4taQQWhfizj80RSUTRodrdlX8g99i2u1x8lqUAIPANAkOSSH4+WJp3\nck7QR+vSa4Wf/VauU52qioDTFfWkkZyAqIVIMKFlLgIehJPw5cyVy+xMd0pI\nAJOo\r\n=RW3J\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEcLXX4ZflXxDbyUPrwkzCbup1gFAg6c/XlK2F1SdjXDAiBTsItjJPMcyLk4Biv9O0bYefAgn41mMLzkbQGzVZubAA=="}]}},"1.0.30000987":{"name":"caniuse-lite","version":"1.0.30000987","dist":{"integrity":"sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g==","shasum":"bc6b47217afd8226a2b1964635c6bff62cdf5738","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000987.tgz","fileCount":779,"unpackedSize":1391196,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdP9Z2CRA9TVsSAnZWagAAQ08P/izj4nAgmCXo+CRyaIRM\nZQRx6HaC7eU1A9G9rLIIGlFMLjgykGPSxa9sShqvYxpg7q3tzA8hFVpMHjdT\nMtmAWHTwvsSiXpDYT3XRqQ02XkTzFk4KYeY7SzlcGvqGNTi5sFdmNXWw/35y\n6g1GYcdkUIqpUtJ//CiF535cc9yGDQ6O+VTChC2gUERYuSI6VLCPTj5hziAh\nH8MPcF2MJraZRhmRF1y3Mm7sp+hmNZT0Wt4Qqj4v9qnRLWl/oDi3lQTLFpxK\nHmomr3kPPKr+AW17jc4Knl0uQYwZw7g/lEJ47nYQHmga/e6uXLCYL0VtR4y7\nxgiGCNrEBgP9SiZ/vhjxs3+aHUNcBStdvsGqosVaTPZar7fcY68Y+k59tKgA\nOilNeG07CgDUAb2livqwRhzAES/Cb04F6UHI1g1QAhxt9kSYAGFz5wguVN+D\nARiBvEwQAdAOl3WsUfmDU6b42sMCBtnnhXa368mxMvxolmZQd4bSS+oeaNss\njiyyNVGSj6tUZUF40R0w7Y57iu2dCJVtfPzCuNEsw854FFzVT9VECxosth1Y\nRzCtSQoeKLfls+eNbVrUYxxq/QfbpJcRqCKYWro6FK0MTsRQPDXj1i/li4P1\n9RLX1GRfYFiZq2Gnae/4BbiZeGibl2rCEg2mo3o4V5xBHjCS+7xJBMljgqhe\ngh9i\r\n=e2mH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHgn2lj9mgGOhbLRCkn8xPCj+HWHnDbq8AysUsb58VnpAiEA/709ueF7bXPhP61IWU8l9sxTtrqnniZFQYGqS2kuVZs="}]}},"1.0.30000988":{"name":"caniuse-lite","version":"1.0.30000988","dist":{"integrity":"sha512-lPj3T8poYrRc/bniW5SQPND3GRtSrQdUM/R4mCYTbZxyi3jQiggLvZH4+BYUuX0t4TXjU+vMM7KFDQg+rSzZUQ==","shasum":"742f35ec1b8b75b9628d705d7652eea1fef983db","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000988.tgz","fileCount":779,"unpackedSize":1391257,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQQvSCRA9TVsSAnZWagAAZpYP/i3WOkEZAHwa/R7xR0H+\nOtQVjJqCMiXNgNxabSMPUQHQPFHN9JjE6uSfdjknBttoc5dgsb0D2lR15Rg8\nF+9ko1ICH8j6GwsukXZnjfkUxgCJ8hY6e4cGG7+Ll+WFYDrAz1K/NgVwBVhY\ncsk4n1Jqp1GkrjrGLmo1Lm1bCZa9bq0xTWNHGM5XC7nfO9XskILU70Ikykij\nCTw2rPvRrSwdq2rhztSJ2ZrCVOzYGpT1KsxlLY7q9qRiKTSxkUhIOTO67ion\nzISA5H1bqRl13RRWWinc2tGaoqTgPBhQd8PeSLGZNEwg5kwXN8bXjEv39bbN\niQS9ROxi6XNQ6YVs0pvl5ZwgnwLqW1oyD12824pl9ht5N3DdFaNUOOZaImGX\nHVwLTEYTWHlwXjTp5BG4snGpGPK5M8pPbzaH/PwlTlAobzmNYfmlwS7BI0Rw\nb9++dKJwPJ4F0dRBwcUZUFRKVU01Fr8Q37Pg6NZMHCf6a6rTdo6NONxn2Hpc\nh2mWXB7TX6J7hh2pp5UQBclIlAmvHjTaQ45LA4dnxR5eIHQFv67RK5gwNHAS\ncBgyemUQmpki6P4eiPAYnFGflFwZ3t8dnPmGr0zE2P/hek7Rhe8QJXQ11yXu\nyhwI8Si9OyfvjvDgLMBHDdCmBJjdUuH0u2yhOI2D8uyRDenrqyPW4PjIUQlI\nA37z\r\n=LlVI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA89ktyNwC+TpI+44gNgjH21wYR7e1yINkzctyngH93UAiBmIG8oGocsIPraWoBzTMv0wJ3bQNUqDqrZpZgd6Q1QVA=="}]}},"1.0.30000989":{"name":"caniuse-lite","version":"1.0.30000989","dist":{"integrity":"sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==","shasum":"b9193e293ccf7e4426c5245134b8f2a56c0ac4b9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000989.tgz","fileCount":780,"unpackedSize":1392257,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdSQLkCRA9TVsSAnZWagAAx8MP/ROB6t2WBcxuFrn42gfO\nXiLq1QKAnIb9cmxIGa0+6C7vPlPWjKudh4ZgisXpZKqNwf8tD9p/1B8HWBYU\nEnn3UZRK2Wi95DFRWSNINj6tJZaCZVbKSrMo9pUbKGiCgNcakJOaikjBEPJn\n4aSal+P+c7FPjMxmHk8RBd0qoMEqdetT2KfH8e5EVtXaLbQkWO2ZgNVQpNxQ\nF6wkVH92bxKv/FoSWhx1AYRgKyCBxg/+1xp4sTehT9yAb/AH6e23ZVtAIs5s\nja62qebaTtn4/vvLYeZLXgeUwPltsCSmdmEDPk+hw/5X6AoZDy/xFq+v1X11\nRrlDNzkBGtBakQhtrxMq2bGHqs8q2Zbcw/FXaP9+VqsQfnwrl/hZXb5i5ERz\n+WnNgMASKZVvA1z1LQPxGavKl92e1XGt4dYqqrIrV8e4uu/PQqob+J1wFM7E\nn5rgdDsktEOvai7itvYAycSmswI788zyZ592yUOdxVNRsVzW8d2pQGjkumgl\nYL7ZFyzLslcLzWH5M4NGuot1bkVTGnLtjMt7ffh3SfYib4BsGPW7TmD9ftYh\nXr3U8opLFn4nKrd3ivsS3nu2MEMV87QX/Z86PqtVK5YyzO09VMutor+4G9PK\nsllE3uJ3RW8j8gi3hEl+1/kzmvKVTbnTuITusf/IRSSf+3AabX4pdA1FIreK\nkGiq\r\n=Dtaz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTl9o4eELCF8cYWWXTc1YtJMePIbtkWkQaVnb3OR5kigIhAOWH1V7EK0yLPOSrvZ82S1Jni1/4xtkPnGNKqZLdoG/h"}]}},"1.0.30000997":{"name":"caniuse-lite","version":"1.0.30000997","dist":{"integrity":"sha512-BQLFPIdj2ntgBNWp9Q64LGUIEmvhKkzzHhUHR3CD5A9Lb7ZKF20/+sgadhFap69lk5XmK1fTUleDclaRFvgVUA==","shasum":"ba44a606804f8680894b7042612c2c7f65685b7e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000997.tgz","fileCount":782,"unpackedSize":1400302,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdiZxhCRA9TVsSAnZWagAAA+AQAJ0NiR73p/pCwFkqiZOS\nPAhXybiMHUAG6oTTj6UETiOv5rzzUP7MBXXtPKyTmHDFk4xWXtuC5VHQmrPP\nyajgf+HObbejyVmrKX/R5/8aSDOMsWVbee9A06zlWPset3zi+THwheANN4bh\nymY5B3geJQ9mHpiXuSoVG1zXsZZD+72FwS+oRyqpPhmGz3cMR3Qg9iDCocSf\nOE+A7LTSv9jtApge82v7ndvcY1crbeFEvDFc7DIlbSJmadtgInbzrpu72OT+\nlI27VlrOMFTFc8H/3vh6+CNBSM3cwRj7op8fJoEkiLHKTj2/bImQLhnquUnO\nzqLXAetiH+IHn7kv0RzsiNmz9Z8EDwRd1tA1Zf4kG+AFxZy72K+M2peIORRT\neQxYc7NCLBZqeWSx/soa8Z3svMe3iA9QYPcPorh4FGSjzeR173zE4jgguICp\nrjH3wIiqiKlcqXjYqrpDX8oXUHPUcw/D8u5RlWxKcxyNAtcolbfM4lVlxTYt\nQnxMDgFXB996eir7aaSIdc3aWPuLtlSO8i9s/x2Dhc12AoV3qDulQ42N47WH\nU3ER2wKjwLUT+nNOAW5SntufkKkG3e9NRlm6G74FCzLLXm+slxAeKEhVcZuT\njM89G8nvbF/Gbn0QbitZH4r7yaokqNSqSmktve2Pj29H2O9WRfiCIBR/LH4V\nPHyr\r\n=hFKU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDS6CXH6hPBA7tmtuUFVMjW8gAMHGEMP8sMfWM5WJESKQIhAICxGFocdDIUsXXUFvYKiYSl6vdRKrE77GtC5i0BBdPZ"}]}},"1.0.30000998":{"name":"caniuse-lite","version":"1.0.30000998","dist":{"integrity":"sha512-8Tj5sPZR9kMHeDD9SZXIVr5m9ofufLLCG2Y4QwQrH18GIwG+kCc+zYdlR036ZRkuKjVVetyxeAgGA1xF7XdmzQ==","shasum":"7227a8046841e7d01e156ae7227a504d065f6744","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000998.tgz","fileCount":782,"unpackedSize":1400378,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdlESCCRA9TVsSAnZWagAAt8MQAJSjUpsTp9N3pkCGPggq\nNj2ty9ROu7Q4iu+U17BgsBAZ4l1OLTVZZskMb6KluM0jXxC7Hh8OqvMzPLT2\nzDqrFXz/PwObtDqtRrTmdXlFrmmvm7BZYOT1SZOYoglPcOn70FOrd1VFvE3J\nfAhMIhrTIxgEeOa6bCiUmUy7jl5/zO9B8MdZYVf8P8s0Qy8QSuED/0XK+baH\nNEk6viylEpYMEnk0t1uJwlbBh/genBar/cu5RXfwf0u8P8AfiNcN6FtnW6Ex\nl4JIF/UBjimEiZ2yp9ahWYChZuwUTGLvZlhl05jba3FdPlIfsUvApiAkOFuP\nR04UwzZIw++4fQW2kH+FwZQNtQPX5mK2pojhLZeJQv0FSB+UR4LV1P7Y8RTI\nUa869242fzVBT8ZvhvIIojItbSIiTKkCHj7GaTpeCiTwd8P/HVstuXYW8Bxl\naBVJZTO/5+HuEA592rxLgXY/dyg6PaCGnM98PdzKJQBC9hVYcX86ZesblYL9\nlwzcTzWp00pQC2rXS5uTS5+jBTgegpDp0J4AseCPwnPb8z+rJVhZQq1Jborv\nXs98Vz6EUlRno421qOnCrftZfud6PXcWvjS9qFbWGEwWke7HA+KBY2ZQSZH7\nayQM7YvgCWwR0MH2AYOHXd4cFWKn3cXbQTCgmwrNuKmyTC5XgHqLntl1LEUu\nw84l\r\n=4Z8a\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC05s0Gu8ERtfTCmHRMUm4lT0NnfJAfmBIrxb0V+L6nlgIgFDmTLZdh0Rk6XuEoaQiy22g7QUzDKHZaj9adrKuozf8="}]}},"1.0.30000999":{"name":"caniuse-lite","version":"1.0.30000999","dist":{"integrity":"sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg==","shasum":"427253a69ad7bea4aa8d8345687b8eec51ca0e43","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30000999.tgz","fileCount":782,"unpackedSize":1403597,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmTYjCRA9TVsSAnZWagAANRwP/R1C3XOXSvsCoVTUKeXI\nhl+2UzpUOFGU98moGv7pVF795Si352Hi1xq0wUmScLvnUwCqEU5EHJeuQ8j2\nuoRhALwb3rrr3APkxR7AuvM9yArK3PxGgtOG6ksODbPih7LbzCgo8wJhSPSV\nUWltUKfbjK+c3cS4hHidOrAtJqPUydfcN256YGJeZ0WIRIx5efqFR47df4/0\nWkBeIWqvO4THukyVzAHhGFGyPqCqWHmr0E50mgv7BTjgYOIHYEW7hAS8eM9+\nzxoXs+nxt9mLn+JuR0dsl2zTAVBykjGXzjQ+b3py9bUNT1UtDLAwo3VWdg06\n6iEytJ4vXU0x05Sl1Rd6wpLY0pEd4EOxQ9/D/sn2t3dkJ4DuCDzpq3eLXH0D\nfhrmCnWHrhe9D6UN8IhYsx2oogL/WWHEG08gqBoqccUezb3DQE9su1YgBwP7\nOClWCbdN1lnDfxFYJAWQnKuZXlrwzyMk++mo6yvKFxt3yl6r4MzLUrsVdJJA\n8txNXl4jiFJjG25ywq7TFoiY/Ji55oBaqQ+Jdy7PIo4GdQUn+4ovjeBVkwaA\ntGOPuhbsqfp93bMI4PJdxYfJwPmB95gscOw6hAhsT3JNcrFElDKfReiK++WP\n/vAkXlBMBe71aAJgY0uLRZDcCVajqhOev3IWOeyFVK2xrFyMjBwfWy08+378\n/NeY\r\n=OnMH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFfYP5A2PbtdiILCUyNMCeJSG0uMN4JMQk6Ld09uLK9uAiEAhWi7qUBrCsiv+OWPSrldiV7/jmaWIvTbwklag5Mi8VQ="}]}},"1.0.30001001":{"name":"caniuse-lite","version":"1.0.30001001","dist":{"integrity":"sha512-MsWRX5x8GsZJcvIh1zkTERAcX9cRlT+If1f4xk3B5EAJftiwjab2oBKPbned9IuBiKae5u9PMp7T2xJBDo+9Sw==","shasum":"19dff5b917890786537d684776099d81f019c2fc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001001.tgz","fileCount":782,"unpackedSize":1403663,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdrTTjCRA9TVsSAnZWagAAOUoP/39GOLzRzeyGEzoVW7UE\nDLq+s32VmOAMZXhPif1ltPndye9mFvChuvb162TLcPE6CvyXK83YQQ4sbm+k\ng3Zb65PMY/jwped6QaV4uBQNko8OI/O52wC5zE6kyzL03J6Gcb0I4+zLiOs9\nIInYvQI8ixF6jYCKFsi70RHZc39KR4+pf4cS54zQsskuVSsOa6r1lvKdFKd6\nxgHFVWzy4vlokgAZwhsRQU0rMQkM4PAlUiBD3Xg4BegOJKt+tnPypPLPHXXM\na3VWi2anan6qmSRipQXnb3HBQ5OURqQrH2Io63KYgC0w1e4phrqglZGWRJMe\nsBZVD33Z6g28QGxDTpJYoh+C0s0W8PKCcCXbbcQ2l5Hy1CgKiIaLe4DkCiiu\neNWOuLq/SOEF/9W/X2c31+VC07BWqW2aCv/foDr7r0n/oZBo7dWfx5bNblyF\nsHynPgbWQSrbK9Z41S3GrxVE392A9Mfhk2BVOqmI2nBtRL8/rFKK/PZuafSG\ndypN/EsXEaA27YiasChkNY/IyVHx2I9fz5Evi0s84Oz1M07o2La8Hq1Z6mxw\njpt8GaqGHMftqtxCbE2nDZrU2zKLHQBL99iLWoHHz6Of86BJzRksfYd08NkX\nAh4IFXsyY5hx8aTn2qdUMrG+DHb2RJL1nh75zQdo0ex9y6K1gGB/c5o+hftp\n6yCx\r\n=zZ5C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHRiPaAAey2jAoy5jFEYScrPPsT6LWnGN+3u+kK9WMawIgTjctHN18EOQScOK7eyQEl6DXa0PZFYJxeFcnytQVwf4="}]}},"1.0.30001002":{"name":"caniuse-lite","version":"1.0.30001002","dist":{"integrity":"sha512-pRuxPE8wdrWmVPKcDmJJiGBxr6lFJq4ivdSeo9FTmGj5Rb8NX3Mby2pARG57MXF15hYAhZ0nHV5XxT2ig4bz3g==","shasum":"ba999a737b1abd5bf0fd47efe43a09b9cadbe9b0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001002.tgz","fileCount":782,"unpackedSize":1403890,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdrVECCRA9TVsSAnZWagAAs1gP/jfbO7TrGWi3s0XZiz3Y\nUG4TCwcdf/Gk9FD+85O33/fltZ49l8cZ+MMNV9qD/y2ryK2544hkllaRJi56\n0AInzVxUVmD3KNpeTo5G+sJbt7j6w+bNEB8xg5dD6Ezt4rfPpUXBV/Z4i+5h\nROA9OUSLh7SFoHfilKJ5LoJlcwVRRTM/Z7iNlpTadVV7j5x8AZ7ERn2c8isE\naFiNYlh447ugUJkUc2g1EfN2JIBLM/OJqS9dRdu1fqhPW9A+89bL3+EZnloA\nIpThi5MCIuHHs3cCMW0F1QHyd2i9PBwxBt23o7V6JlKzrgcWSo9XPuHtxmpI\n5v30jwwq28sFQMO8XpCL2HPchAbA3MmKclwPCvQSpkl+rQT0Jdg5sYSu2Fst\nrWXGFn+wZ/kq8cEBh5lrCJhyCnCIKGRvgce0eaC/I5MRV5QOgM5pHyIk2iKQ\nx0meeYyDIqSIYEyojChUCdZOMEPUKiTL4kDvJGHyDm0oUO3FQuQCI+6BsODK\nLmV6UfL6EFjnKEUD6bx2NBulelEc2Nnsmedbg5BaEr1sEucmsnFv1MdI6Ztr\nU6T1PjoK+wkjha6QCObj20rJwN81DnMIxWjG7AGU4ag6HW/hcw6EVs1I2RyO\nevLYiD5y/LMTWhYWchfpws0tMxXxVar8VWvXHCVJ4rkYEfnYzi6WNZaPouWc\ntBIb\r\n=3R5R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEch3bMJcSv/3iN5Go/+VYtSyERQV5QaTqLx/zNOy7wAIhAIoUCLrE8ovN9XnYy9hm3xHxdkxqPPb246ZaqnX/a5Yq"}]}},"1.0.30001004":{"name":"caniuse-lite","version":"1.0.30001004","dist":{"integrity":"sha512-3nfOR4O8Wa2RWoYfJkMtwRVOsK96TQ+eq57wd0iKaEWl8dwG4hKZ/g0MVBfCvysFvMLi9fQGR/DvozMdkEPl3g==","shasum":"d879b73981b255488316da946c39327d8c00a586","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001004.tgz","fileCount":784,"unpackedSize":1404387,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsUWBCRA9TVsSAnZWagAAWG8P/0Qd9VLEqMMFpijYN4ah\njg5yaHw6JemY3PY6YkRJTTRw8mm/jo9H5z71XHjELy5Wv3C2xDIRNDupk0iZ\nYso31l+b7T2hvx1KhtQFrQNOdNgrv1OaFgIKHvfoCfkYkh5erSjgripNeQOI\nvpAdZSww2ZUwG5E12cu0GuWuWpplv2EbzQFmKhGcJ2ZoOmmq54g5QOKROLqJ\n0a0niv+XUw5rKYU5j0TlSU/Et1UlRJkaZMb+a0IEA9wyx+Wf4Wrm8+Qw58+z\novJ15mtbh+8XKRO1XAvWJM74K3P9SnBCC4KSwR5PUJsmIwCZW3eDktSGTydQ\n4Ut4XI5cSqOv4LIvT7ZxH2UpajI3zqUpTt+TPabokCHyQ1sLZcNW1SOknIRy\n5/BFlkd2c3F9Vy23E/jKAs0WvS8t16UU0pWYZYFgT6+IvA40XTfGnAmqrNwG\nqAKsUJhAc6MvVN2CvwtUkUQNCREyy0u9iVFte4r0Lo77Sfso10wFHGU/zYOV\nDWClPTgyPrqfMQhg0hMYN851YUa3nXTIHHWYiuKPyiKnBZ4QYGQEkXOBu2yp\n9/3jz8sbVM6lsTrCKEW9nUy4CzwANV2OfDW3gbEk7KI+NGop8K4BXkVKo9/B\nAuIQTPQoPR6KeWOE5jlH74WzC2ExsAPWRnMrr56wR9YoBcpTSwfHICUGzJTX\nVW1m\r\n=qV9y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLbxIeo3xKKNctSgOGahgILRQ3MgplOleEGQ1sOImkzQIgbpe9IZjQdrTwr6j02NHp/rwiBaUgUMv07UEGzN5OjM4="}]}},"1.0.30001005":{"name":"caniuse-lite","version":"1.0.30001005","dist":{"integrity":"sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg==","shasum":"823054210be638c725521edcb869435dae46728d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001005.tgz","fileCount":784,"unpackedSize":1404453,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdtSvwCRA9TVsSAnZWagAAVfgP/1U9SlNPRJ2ssSC/vWfR\n/rdw5l+cET2BqIQ/1hT1nEbtn34wcgHlOI4IO7RwzH4a1LAoQoaZUGJ9S6sK\n1uhxiazCcy0CH7bspdXlximpQUuS9TiBh/kkaZb7nQrq2awzJq4J1Z6XjZRt\n1UE91NfTHYhMSGiip4r2gWBepiG9jW9UZ+5TUaeXi2Hud6Xnin3f1+aX7TZA\nD36/++sPlDs9EGbh2HxJWvE3Y4Rawtb5LLD+uHeGziL/3UGaDmDdCIWIITX0\n/hhdaRqRUN1mwfEqFItVjTUWU4fW24JCnO8oNsKtfsXA8B+y1dr+3jNhfDdH\nrboJ/D/kxdT1yWwOJP0odTWjvCOhyv+leziuhg+bWmGAoBiuPD1e1rzgzLRk\nNyt/i0+hmdobyo4nTmDVe1aY6qPjz5jpaxmCfFcLPcrCOr9dCZx3DUvDhQjg\nY6PDAWVbOQbm2kYj+Gp6lEQ5b65RpgcSFKD/jtldP1wYJr9faVLQweY4iU4Q\nIfQjlZeoZ4doAV+tD6aZB+ALw+YSEX4QYV4gRM20IvbRtLKEbC7gVHU9B9kN\n9P1cSnS2ZtfWjOEigXxI2ecQIWZXKgwtDuYvh0o6v6mAoS4L++k0h7tNdgZy\nu+qsHI5OoigU2+fl+pxwYn2zEMRrXPmT+bjSl86ZSMGBTrR51I63Od12q+78\nTiLk\r\n=C22g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFqPb2MSs/Dd2RFOW+xLT7KqKajhCPGHDb/mZiTSpscEAiEA3aAyviAcaS26+tj4NwttGxVGxTso7cecRU96nEWwqGo="}]}},"1.0.30001006":{"name":"caniuse-lite","version":"1.0.30001006","dist":{"integrity":"sha512-MXnUVX27aGs/QINz+QG1sWSLDr3P1A3Hq5EUWoIt0T7K24DuvMxZEnh3Y5aHlJW6Bz2aApJdSewdYLd8zQnUuw==","shasum":"5b6e8288792cfa275f007b2819a00ccad7112655","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001006.tgz","fileCount":784,"unpackedSize":1407746,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJduQRTCRA9TVsSAnZWagAAkgYP/jQQnpeGCmdGLnEeqZN1\nrQECdQPJGoKO6rX7b0NPBVbFfH12kNg5VU62CFmhx1cUQXJvsmx/doJdOin+\n+pUGD4Rg1FvRo4ua5gt/CGLULFLg2oSmxISQD4vrbHfIcqAD3KHW4O+oUZDp\nNLr3TkZmWsQNQq05aZGk4fI4/JnHwEevDacJM5MJXc8aNcMf4dln541MjBKF\nJn2TNklzX9sLx6SiXlZO7PjMNJOcGdglhGwM1pRXYIHTybTpMoNyJeEtOf2n\nwPK8DXAHq6h4vX5yrF0p7P4+FRhF35bygEmp0xRdksQ51x3PSihRmn6htOmD\nXPyDBSPwOsdvjw35N2KH/zg2jPTiZIl+lQAFOvKrkafusA4Ly3CeJ/ptA5SO\ntRmRfwChrnQXbSEJ+BQpMKIUYZorMphTVScuesBilugYXI1VYocsug4/Fp06\nR0/lzkwM+x5LTDaBwCXWDMqTLgCbXps/RzcrAzyHBVm0uoHpYqRW9AFGx9mJ\n+aBU4E8RNs0MoOn2alx5vnHowmcFpWQ654VHGATrC1JI899cePuzu3hJAVx1\nzAjcyBd6xse94gPwWZGIayuq8QpbB3cjly6/VWlgz0AYjrkqsUC/bcYIPRO/\n12Jk192Chr33o06rqXhcPnzLlCIhV9XAXgUNvPHyOFmG+9nV8kKyWYJdGB7B\n4B3q\r\n=//24\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDxtN2nrdPliPSUviU2nTySj9RMymviEeIGNhgSFXZUUAiEA5GMzSFUFgjLvYNyXEF/dPWAxGg6XFQB/cMI9FVKttqQ="}]}},"1.0.30001008":{"name":"caniuse-lite","version":"1.0.30001008","dist":{"integrity":"sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==","shasum":"b8841b1df78a9f5ed9702537ef592f1f8772c0d9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001008.tgz","fileCount":784,"unpackedSize":1407812,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdv8YBCRA9TVsSAnZWagAAo+QP+gOMHywt3t+CiQEy8c6b\nUQ4b2S/s7rA3D5HJH9mSco5t5Npl9kE1gVZ4Ic1ITDUe6MWETE4y+lnx+PLd\nVZVmjeEmsQtpiMnObmvAkDCC3NGAIN9aVs6ktJM3T/qidwd/EFsgQszaSd6r\nZ0y9mYO+PE6YrjgYNCGK7v0vbgD44Zj8VFUsMq4QN4tJzkmwp6YwJldxv6mh\nJL7NIw0RK+GCM9G3TeZbtwux3JnOuPMDvyERkWkKawnkPRnEC37t4scXxgcX\n/PfuScJFvEqZeKzKWVsYrIRsXOsAN1twyLouNTQp37u3+4e/EysXZ9sxsHOi\nlA8CcR0eRnvMXQKNXaC0Q5ZBRd3vI4dCJB+fjI4PxhLYfyrL50388VoimNK8\npUiK81W144ecV2TmoXNnnRaYt+Hh0ZXON0YCp3TylGzEn/tqtAjKfAIBHOGv\nDjLGZeYk/a7QKGIcLYC+gGHuyrejuxqxpSJWmjCZVdwYk/JBAox2XBea3nzx\n07KenP8WkjOYMkgq6k5hiPM/LX0ZFWTqe/s/MtRM5SDjraw4EFxDfmVYh8p8\nc4sd61vh3qI4SyjaO+hvKakQzMoq1WmT9xdg2bSjOutQgssds6m9OnXwJwcn\nA2SAcWL1kx44hKETGn9GTh3sXnx8Hm8ODn/T54jzA8CIg/DLeOxE27hU7G48\n9W8S\r\n=Wxuc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB5bCl1AsjGDL2+yTC+eeifvWCfJ96kQLSns3SSFOlGSAiEApT5h2DfGQbgcY4GJhIPwOZxj0E5CALqNYmNfLMWCQ9k="}]}},"1.0.30001009":{"name":"caniuse-lite","version":"1.0.30001009","dist":{"integrity":"sha512-M3rEqHN6SaVjgo4bIik7HsGcWXsi+lI9WA0p51RPMFx5gXfduyOXWJrc0R4xBkSK1pgNf4CNgy5M+6H+WiEP8g==","shasum":"69b77997b882a7aee6af24c8d7d2fa27ee41f348","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001009.tgz","fileCount":784,"unpackedSize":1411138,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdy5V1CRA9TVsSAnZWagAA/YoP/RprLfjGG+V3KcXhntaK\nC4l++wt6lGM4BGuXx7HDiVCrDTpP5Ut2SGaw5pj1ysgiljDdvOXy1iuZux23\nluJ40I0drSPunQLBDvtSQhBT7gFHkN3hzG7ciGH+6T3Et2ymEDGs+UlpL+Th\nnZCWvENkvwlahShms9asQ/MU9RFYoavUXKC2kxjxO7MY8Jpoag+eR9FGkfrP\njP8ZcWWnyMS6xXoNmnVBnVATORqfsnLHlqP1vtrshl+P8wpWGTbgS7hh3w22\noMU8ANH5GLe+LCMr/FwmAp4R7/oqObmaBvxiUGqLHGS8E4if4CW7zB/4eO2h\nkKYp+PFbEyVY977cyn1oUCzvJD2iTvGCU0PPp/s6csBWNrJ6Az7pT66qwC/Y\nhP9LP6lJvdUiJGjoSgj3yQw6V/y02Lp4Wjg/GbdBplLQLOcQbDEwnZ1vUaZM\n5AYTNYYredrcK88CysbYe0p8jWBMEVAm+DghWQqlSsyRsF7NJYJwrsNGCO/m\nzKs+vP6J6U7JwlSrinBFv7NovMp3wZT/5wZ7WO38CbqfQYaA5zLIEgIsgyKO\nPwQfiGv1vaYKctkII3bWk7ebj/9WMSBKi39TnXoxPip6k9eb/5O/3gUSCmtw\nnfzpA4u5iVEovbpDTKWNk5h8VN2cW88UR+dgXBxpgrETrKbNweErcz9xdN0s\n13ix\r\n=4VPI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCcRcsJW3TW6lSpNiIgMuLDf1LAxp1kByHMibv6e48xDAIgX8XC5n+qfTmNAnVcjfavFRQk/aGtXvkbJtxsVWAOQGE="}]}},"1.0.30001010":{"name":"caniuse-lite","version":"1.0.30001010","dist":{"integrity":"sha512-RA5GH9YjFNea4ZQszdWgh2SC+dpLiRAg4VDQS2b5JRI45OxmbGrYocYHTa9x0bKMQUE7uvHkNPNffUr+pCxSGw==","shasum":"397a14034d384260453cc81994f494626d34b938","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001010.tgz","fileCount":784,"unpackedSize":1408570,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdzQMTCRA9TVsSAnZWagAAlSEP/0JRybVAXFZvG0qcucwR\nz4q6BiQqwTUiqJ8+pczg6jqzu9peeB+/UPiJD5eiWQzvruVpVcHh+xXyBypE\nCsPhEH8mFfbwbLDCHvmb0HVsgg5g0gryiFKI/lwscBFrP4iNUOEX5yO9V1ER\nje0O1PdeTe+tQbHgBjxV5oYaNHYU3waWp91UC1Iv79sBEODqQSw+IXv9HrCg\nRIqAVatQ829GIn3BOp6AAEqh1kuvGOpWe1Udpk6iELxhlma7jW1aPSQYQOTu\nTbUB1/C2Ev4Mr19kiK/7n1JOLbG+4WjJ03kUC2sSiw4H49hHcrwkNv9DUmDv\niKq405d9+yEaeVG+fLqPo4BE1Kf9DqPL9J+0KQR0QPwkamt/dn4Q6Kqah1BF\n+6KcE4tjYaQTwpmkxb4fO+uovicmFTivcEYG9Ih567TfSD/ymyCpjpqljrtU\ndBYI+CwTP9IFip2bMrj1KS+Tgyr0VWmkswjvlbHZGNNu4319qIw6uBFuul3O\nFKgvPjK3r7KptAgHtcnLEaXEzYoMlAhvZbZjoOO0cTOdr+eiKeFxXOTbzf2s\n8TfTC7QTfa4rUXZIGtuLwKppenV3pT8iAfXZBe389vq0B2o09pBue2xz/hvX\n5bwZ7bku2Wo6hxWhFBsqw9it3Hr+6GdVUZJu+PsyDpWP5QnidmtDYh2xyijT\n+Q05\r\n=sXEx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuIj4RoYXGYAys/zmesXjCSAYLRaYyNDVOOJCPaQG2QAIgKagtgtTBVmjD+QIMy3z2TcElm6q+Taz1na/UicYBxnM="}]}},"1.0.30001011":{"name":"caniuse-lite","version":"1.0.30001011","dist":{"integrity":"sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg==","shasum":"0d6c4549c78c4a800bb043a83ca0cbe0aee6c6e1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001011.tgz","fileCount":785,"unpackedSize":1433195,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd1M/0CRA9TVsSAnZWagAAxpEP/RuweLka9rgqPw6I+69e\n1MM/UEOEDDj5mOqL21KWZU6YxlHEj7JwkvsecyyXw8jLj1HTjyz45odQ86pz\n6VOXZKVAvrBV4xDOlMyz4LuY6bL9Ux+mDUjOZtt/ynWa2OnMT/RhLb5V33vM\n/fL6L3ribYyQQ4TyxtuOlupYzz5huy6StIJAeLwvTHcihTLspaAZ9GPRM6/N\nD3O0cq+27Lyq8dC9m5fFI9onO5gClw85RtbDjoFL/fUeQ/coi9LDWhR+LM7C\nVf0lAPh5C/TpTsp4X3DGXPhOXZitLclZaZ/ooPkm97WlL/A0k4q905abFoc8\npOAh2tL66DbSYd+/9DcLmbMWthzMEsxIZ0q6I7E1ItpELPKUBLMOOnc0ZrbG\nfVngCeAsfryZQlKBGbQg5ABgwx5Qycdlp6j3iIrE0DqGVKPwlK+bSbZDS4Uq\nK7KH1dDDcBtUOPGTY8hbT9gEUNnOvP1tb+WNlIMMUdxoAyRn/UtdUixrq3Qv\nykTF/mZxryy0y6FL8ZmBGkrR/8y3cHXn0jrNQsMBZ9mIlafYxUkmGQqqA7Sa\nqk7lBqL3PHeOLvwxJh8UrzOsPEkYPKXpUB5sTTaBn5u3gKizT++TZg5Q1FFq\nCmVNITqsH/JaeHv373280pM/6ZTOqj4RpyJjpZ2tBk2NBD2Z3mNC5A5GfwyP\nLOcW\r\n=d+Qb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC0wzVgr5oQ+ipf85F1lkkt+xY4gGYorTWJEhoeBG7JYAIgc6iQDSfVma7COk/qKVNY2hjs72vsyk7FPejgSCk66SA="}]}},"1.0.30001012":{"name":"caniuse-lite","version":"1.0.30001012","dist":{"integrity":"sha512-7RR4Uh04t9K1uYRWzOJmzplgEOAXbfK72oVNokCdMzA67trrhPzy93ahKk1AWHiA0c58tD2P+NHqxrA8FZ+Trg==","shasum":"653ec635e815b9e0fb801890923b0c2079eb34ec","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001012.tgz","fileCount":785,"unpackedSize":1433274,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd23WCCRA9TVsSAnZWagAA5doP/igad7fvA3A6R1e2sQEt\nJDpm8BVwAmqqlBytvjG0XhOyFoT30lYRbFR+PxLMUTO45sSWbsECSfjM6YEI\n9dJ5qSrXeRu2+IVp2JpO5AdG7NMDilx7nXqLgoqCfhDa3Z2UWl83An0Ntci3\nSPCc2BINnA+8DrJ3vbPFlHaVAvVTe9a613EWibG+HQM+8G/Ut1wtoG126GSI\n03t7dqpZrV6zRj5j1+NEXGAlAspzl2atUQCFZYO1z0WIloANGuPx1kw667Sw\nlyfphp62bl/uANMgD3dgHz3NHI8I88Ng0L//u+zjQXCRkXMvRuz/ruNysyqu\n3jMAQlgyUMIhNl8XeHAs39Vu9dcmU/9wo3cvBt5ugSzN6ggyP1i1NfoXJGCn\nD1OyPK2/feXd3kT2nqm6wSRZb10ImBog9WG4o4+fFIQ1ytGxjKGq/+5hILtu\n0Ps2B1wvHf00Dtd8idij0WvdkqtkY6E9Aaz7VGst55EDisX6AuNt57TiNJrS\n6ldXDCVp9yihuhrJuat/2igY5QjUYCGT6vowDXA+MF8sQyKi/sirpWEwRI7U\nSwH2uG56jhzvbi0biEoBIjGQGtQX/BgAQ5RDerVLLgJg9JmnXGJ8q5jFzmSs\n7bfC8mL219p7UhTBE1/98/fPznz08VGJMHUkURfVz1Jmrz5dgT8lmy5Cv44q\n+Bau\r\n=haQw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfcKeGoPU3knbgvMEo7jWV3UukfnlD83v1SF4KAWvOXQIgeXL9LKgWdMY57Upnn9RnBYEp+Qdlcn1L92Wty58wX84="}]}},"1.0.30001013":{"name":"caniuse-lite","version":"1.0.30001013","dist":{"integrity":"sha512-hOAXaWKuq/UVFgYawxIOdPdyMQdYcwOCDOjnZcKn7wCgFUrhP7smuNZjGLuJlPSgE6aRA4cRJ+bGSrhtEt7ZAg==","shasum":"da2440d4d266a17d40eb79bd19c0c8cc1d029c72","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001013.tgz","fileCount":785,"unpackedSize":1433333,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5LAACRA9TVsSAnZWagAAGmsP/ixc1Nvha6Nejl9VRi6H\nGu9F9xoYQ37YxsucExCWnrp4OiJ8EzLitSp6k24tNnLuxSQ68tI81vJkWY7E\nVTEFTfDZAcobjA+spQU2mbIcTRUTw6LQV0fwaDghxvnpBVo8Jb8vLX1P0IpS\ndEwwWGQEIRjunAO1N/t0tCFCRaNickRaFhC/6m1MzOn3RNnvd5CL/2kZzYcd\nnwKls8gt7OWca6WuPjdY0+DCSRGsTIHU8edD21ky5S+DfifFQtA6RM5wu4bW\nDzSrdetwYPz7Qs6nR9durA+zgPSzcq3UACxUSAsE4gip4nY5Ayxn/QXON55p\nHchluuNY1v58tvSodMwyT6rAoIdRsEulGueTbbKKnWss44Bzf2z3iYwDTafO\n16uytYrtFv9HSXRVS8a3LofRC1z5tYUKDogvxhHMYZZ2FO0253xciQdD+nTH\nSsJr3FHfI4G25zhMRVQInU3nyhMUSeSLTGtUSlH0/Rp5vT15kzk2SyIY7Wf0\ngAwS4YTGxycZ5OqLvv4Pxfj2bs6RDocis4OFwtH9GRWUtk301G2uMyFeVAPi\naQbhpNgBYkSuV0x9xGHPKPE6PXJKBGn3E0bxApzuzreBeojOcjP99FOZ7+tL\nPgLFE5ywpiNxE/ohetRDtCrxt4V9TV9cKblcuMoRfq/9wUvMDZInG2VeiivC\nrFKh\r\n=pBA0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICtM/1sxbX5BMOvvDJWuZY+UEBfvuGEDKefDTgsLmDToAiEA3qrLIoVaCSwsbSQldyfCxJwqVeAGrquGiUKpletAjIY="}]}},"1.0.30001015":{"name":"caniuse-lite","version":"1.0.30001015","dist":{"integrity":"sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==","shasum":"15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001015.tgz","fileCount":785,"unpackedSize":1433399,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd52ERCRA9TVsSAnZWagAAw0MP/3SlQJXlRhHeGGufg25m\nM0RCQpWy2zySjymO7O9uJmw4C5hkEBXCmuGKsAJsyX9xMcH9zpH/k9XIyEGx\nWEOn+3EKDUclLmx9+jztyNHZ/sJDsFci5gq9B4zmlTrgPMk4BU9Bge4Z3p7j\nhKXVQYZsZiEf8BwoOXevUr4uxwZ68q5cl5wb17YnXwzWHLOzrJ45Av/DaTeT\nX66VtNs21x4jsFFii1OgzJrtirHuy6zyab6E8kv3aaFrTIQ4bW12ZwkCGIuq\nSJpCRR4iQFJTrRnK6vaf1m2QiZh9UB1Zopj1G3S54K2mrG4/OyF+sGrsG/Z5\nz6WP3USK3Ro/73InnvqTpKAL8ZCCCUbTZ1FTrIkqaEdSr1nRKCk71zXf3eMe\nmJLzEDJDY5DE7JrC+bk0/eHTS+dlDdpu62Qm+klhsvTfTWhalY5d1It5+1+b\n9L0/fndLz3XNW0nJB2Y4j/OHkuoZa99I6/q5UIwKymRuliqwHHumiOUUGxsH\nRTPQhQ2I/bMAw0BN9mFIPDtP7vV622QbaALN8YqD1ZPwdIJ/RcpEW+SWHQKf\nTsFXPpsL/RWoxnXZgpDP1SD8hFFBlfeZdRaoTAmX5XokrCIG15rNYH1lpo6l\nHSHqHAMUe8JZlZWcRjnMEkSwgzKIHxKTDA3M8seGlWPWLpwMYvoKjOzkMq/E\nSHqU\r\n=lITw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD61mHjBJQFdBPmPnyNweVasa8zl5V2CyZTIXzs4JqKCAIgAv+JpBXhGgPght1A4RZK8cxz4K7Q1VmWk8lS0I9TqHg="}]}},"1.0.30001016":{"name":"caniuse-lite","version":"1.0.30001016","dist":{"integrity":"sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA==","shasum":"16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001016.tgz","fileCount":785,"unpackedSize":1433465,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd9yUFCRA9TVsSAnZWagAA0mcP/1XaB+WFDqNaE2VthNxG\nBITxnmQ8IvBURTo/7spQzyYJbJzQZuazHZRuFx4FYmc+MBImQmgBd6GOMbtL\nr6NUWeCHEthNEZCw/PdwU0F3GEZtJOtB1dbqcoWvP0QOJH0c6ZG+nXiHVNve\nX0u+sb89rHhiiJ4IYgSVudV93sPJS+6jH9O1tBxemNzfGHOrFefFTZoNPxbt\n/iW8zpuzRFZTfda0bXIizmgP6xS0+mamxURGk5qSH06u7MS9K++54YJ0RkJv\nDrYc++mak/OiUSWA5+ExN7y27R2YAmTtVZ5Y2t/1ylcIu3fF3cezkIk69bW2\n8YY1Ul4zXnX3Al9V9WDmXYjz90nYIL9eT49/qPs4KD4joe8AhuqTn5YPtWqL\nXI6a+uvMXCH5KIle2mtghPxX+Auyh9H4RLK+XCO0gXCH6aur4db0pXKVkLXt\n0fmKY3kpijP/X2VNoSHmsiTnl8F3JryUXNO3Y5n2B4EilWadd/csxK016qQQ\nhR3DeS8qlDXd2KYwvCnrNeQYWECdQ1MXh0N6i3llkD/TT1WP8nq725bJ2uZ7\nklFketXaF5+p7O4LLbhfWW/pgK3ziL3xMBjp/S5H6lZYQ1zIqpsDFvROLVj3\nXe7PuteYE940kzEmx2F1GbcD9FrOCG36x3ZRXFbpcNO7Ofb2wBayZy7NL02j\n+TR9\r\n=ZORz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxei2IW1XIn0sUnk+arA93UCUfdqaAhe6e5neb1ltuQAIgPB9c4ZPpg9pHUuB8UrKstppOzMaeAuK2+QmHGoiV7AU="}]}},"1.0.30001017":{"name":"caniuse-lite","version":"1.0.30001017","dist":{"integrity":"sha512-EDnZyOJ6eYh6lHmCvCdHAFbfV4KJ9lSdfv4h/ppEhrU/Yudkl7jujwMZ1we6RX7DXqBfT04pVMQ4J+1wcTlsKA==","shasum":"d3ad6ec18148b9bd991829958d9d7e562bb78cd6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001017.tgz","fileCount":785,"unpackedSize":1417355,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeBk5CCRA9TVsSAnZWagAAgnIP/jUJDmgKsuTeddHZr4OP\nyODB2pz3EfAah/qWob60V85c8XdfoGRj6jPqYH/epFNMJ07Ex7WFjnfZwm0t\nKcruPkMfU5vOMA51sirlRoqiAcIPjdKoofa+jN1nv4ymW/w9GBniea4P91zW\ndPeLUvKxx89PMykx47euDxkN5FCUfTeOdbhJx5uJCfft6+7CpZJcSWpX5JOU\n177sZbLnTeUo+lNFTZFwUMEgeJlGDH7nrCMfr/wDvdDFTz+jftOMrU8PDQvM\ncL5f1IGg4lh1Qae9GDoTK6HJltDCO8UmvCGIyb6BYpb9pvCnicTPU6boZ2h7\nim+eE/ZOlF95e6/uP+NJF0IxsJxW0uy+C04EJFhW4cMmbXyQB3gZcddBAznN\nBUp6fpM56nvuyRRGFdDnjzJumScbo2ihoUqQGRs/nDOAfnrZduWERGeLElxo\nnzYZVu+2888gDCU6YATgQAq4jUA0m9AM0TbQ0gHGrxBQGDywHvOJ0GB8bwBW\nwIXkSW6oplHN4IQAY33mU4ATtBtTuTtVnmi9IRn4d2qK60+FEGGcBcZeEagd\n+cRVFaD6MCvEKNvNVOBZceq52BZNUK/JD4oOmVw6+MJQxve4K/ZSakjj37ei\n/8AkVtW8/MTUHZNVjyLuvjXEHrf+aCls2EkcuMlHBLWEm7s6SSV7MehR7FBw\nVBmE\r\n=CCD3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCG17NrvrHwQYylodgIiRAWBydCJKfGIEWYnWx1YFykGAIhAIpVqH0WtWczeqayHWHkPt+1fxf+ybzdB8NwaYkrSYjX"}]}},"1.0.30001018":{"name":"caniuse-lite","version":"1.0.30001018","dist":{"integrity":"sha512-GTHI7xdD2EX/U9UgNCEdekriT81N6ZwipsTGKAI1hrv3VEC96BvS5RVoc9Odlf9ftS92oxgflAGbYLi8UjIiVA==","shasum":"dd5cd57e77980db03e4fb7a4e9b4a96e32e1d733","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001018.tgz","fileCount":787,"unpackedSize":1419420,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeD88RCRA9TVsSAnZWagAASgMP/3Oyb5HscTWggxST1+Or\nyPePoQbqcR/EAe3BEQDtyJ87B6t+3xlx71kAwFME9Yk7phxP7eCoXBpgdjW2\nfg6bK33Drn5Y+TeC7rhn85Ki0fnS3SmCjfWqy71CHuorPOgqRqusYGwbdt4/\nj1dCQsCB/P35bhPwIzzH0/6Rs/ry4bAQJn14vdM54n9jJHx2hpQnutdjZbmm\n+RPGluH0GiDeIBfa54KNIccIq+9lr0Z7D9XtjwooC3pub3lWLsl101tBXt7z\niN3FnghCxQptRLba9zHSP/scB/ePcMIU8QV0ZhdVra5hlWmPHvE6AkJzlYN0\nWaKh8/F9Q7qpVxvJSauKvZKgBO54KsX0ky0GLgaUvDdn2g1hlZKVRatRy1IF\no1uL8sEvDv6lGWn57zPXgjaLvlFG1VNql4rGavUrFC7MChGdh6qAcXsqNxtu\n4vtf7lDL2Dn1z/vdb8JRH1jp0uImEtwiBbLFedTdkDi5K2z/SSTqEgRTAMTY\ncvUWODl8jGHdYvTLM1w2mzfnDNVVXjzJvYcaaHX/Ckyd4oKFGHu8x4OJHoTc\nxcZWsBPMy9OjKfG786qa/EVJdNRx6AVGxQD0v11x6cVctU3T6CbL9OrobIxI\n1eKvaO8u7Ug4mZZKYWq2CJNdU+gchAVqEz+3THqlCdsuYByb5pWNg+AKqrSW\nkh2J\r\n=FERD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGSHap1VJnRxdqEMYFFtF0Yk4uBkSM9Txfs9kamk3f4pAiEAoM3MCNnbSwR2HFh3Qn3jTVjB4PzQAQPp+jPZDWhCf4w="}]}},"1.0.30001019":{"name":"caniuse-lite","version":"1.0.30001019","dist":{"integrity":"sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g==","shasum":"857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001019.tgz","fileCount":787,"unpackedSize":1419503,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeETyxCRA9TVsSAnZWagAAt3gP/jjUSH6bws/VF2AeVXPB\nKNxYPlCMmgVxm1r8xK+7aixBs8uR6Qw8cdWMqLjYvyJjJBii2tu8NQpzwU0V\nIXZKb8Sh9lTeUZ2y0DeYfw/84IVRJ/x7BG1W2B5FqpU7soX1e2+J+Nb0mjXX\n8Kt0aGoiFkhXcmmrzWX6uhZvv9S0zlNJM1z9otkILsbGZxSL4fmZkj4XdL9g\naeu95RrP72eAqqNxC5rZ67TKjseWZi8zwP3Qti7gYrzxvH8j2ULaYaSxf0Wb\n3Hz0ORg/KMYCj0RMXULyqaqmq40WoiDLiIiUD1wK0d4nQN9LMIkHXwXv4YRP\n6hKq28Du+Q4E0ufSpelojlDp6uXUjXrbh/Y0SyQM/1dBhIwXMhw6fRkrXZoh\nmZwskpaV0rUxOEMobJbDI23hn5mvZXrMGjnjxgzLKbjEYaNrWmvr+OzzgtxB\nvwmf++VxFhW18v/73I24n/AOZHMpGWj+dG6AoDyceFBFkaduKHTU9zpYKdoM\nIJ4xt/GGy9f3PhRQjuuUwmF6X8mFEJjXQh4g8KB+mIzAiBxnnqecdOw5diFl\nWQ8KcU8gPK4vbFeMs/kHviFBnXpvJy05YVqK3piVQQpB9y3GKnUk4Ld8JMlS\nUo3p/sRtTfqSWYW6gvIEUgJVQE3446Fw+zTw8sO9wuvPV80QpSt9Bcu0J6O9\n52wB\r\n=yMCO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA7O4WpuPNR4cImDSNCmyAELEaqj0CCgvlw008YRXPeNAiAz1yR+gRS0+c+cX6PxiFoSB++OsrS+ip1DUTmjpSjnmg=="}]}},"1.0.30001020":{"name":"caniuse-lite","version":"1.0.30001020","dist":{"integrity":"sha512-yWIvwA68wRHKanAVS1GjN8vajAv7MBFshullKCeq/eKpK7pJBVDgFFEqvgWTkcP2+wIDeQGYFRXECjKZnLkUjA==","shasum":"3f04c1737500ffda78be9beb0b5c1e2070e15926","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001020.tgz","fileCount":787,"unpackedSize":1438654,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFrryCRA9TVsSAnZWagAAveoP/3xQZNs8AEB9bflrpSF3\nx+YXb+byXQcDraq+tolEabGNaF/Eqsp210QM7MCyP6+RD0zNk/hYvYk6jld7\nVd46TRmPvT2s7AIjfRR57X9ZAydWHiTfTxm/gsOPyS0jl60+VIysNqz0GOHV\nMBISeYgfYNFuqq1ZwW94M6nybmwMRAmetz2Q1JWgxg1dr0l0OqBqlmyFMQ5b\nSbJN+hhkjWoBJeRy/jPj36BkP0JMthNxfMnuSIMcac3M+Wqmw9rzgMl0yaQJ\nApzEKKM03NHAl90KRnjbeD5DBfy+83OkyxvgqqXBtt/kjXyeh6P6Agh1wvRi\nylWrwOI4auODxsIsjNAAq4SKnWFrV6Ss4sIVuhXlUcoSRgUfHBmZuy47QsHR\nfbLe2TFzp3ixEFCHhIPECH2YbluQTiFj/x2xiF7UmLlUSjUPzdjSSPX7XbiP\nWngRhQxAnttGz3BTGfRxFF/Yj76R6+sJ/AcS4r7sQd3m+ItTtKw3uCmjVI0/\nbNzP9pwdRL9UUKfmxK/XEMKF1hNR49ct+LSx2Op6Pl2OhLE1X5UT7mVxKRGH\nJVY1NLImvImt6q7jVySN7FZShGFGt+ZzezBhbvXxFXlUKSTol+wvfwOnccqo\n+5EoH0drTlAz1ympVEiUayh97dxpokcXsfBoSaBmBd1D9mgpQtKHExbvYAX+\nVLMz\r\n=PUNp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFmfPd9CJYCfUvQlyf6HRhGsYsfa6sPObL+f6wE2srozAiAMDypcmnpQvwTI5w/mbX2IpouTqnxDkBcjPhjjOEMz5w=="}]}},"1.0.30001021":{"name":"caniuse-lite","version":"1.0.30001021","dist":{"integrity":"sha512-wuMhT7/hwkgd8gldgp2jcrUjOU9RXJ4XxGumQeOsUr91l3WwmM68Cpa/ymCnWEDqakwFXhuDQbaKNHXBPgeE9g==","shasum":"e75ed1ef6dbadd580ac7e7720bb16f07b083f254","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001021.tgz","fileCount":787,"unpackedSize":1438720,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeHqPyCRA9TVsSAnZWagAAGOcP/1UKB5wTII6jCxOi2dJt\nvobdmfTPuSI4v0WNQxzeUUXl3ONWw4ZBx0S2oAzFinNYDRGSlnR3tiztY8sI\nhAkEmDMuKfpkREKmL9uxofGe9kJSN+Aq7C9Hp4a73PA8W/mjKVq3RbCK60ao\nal7esxAYX6Kyyzd9buZUTbapTNisKiCHgSWf3Hm5TZNhjNlBSnuHcbxqF14s\n7p9mtCZUipoyk6nxIBtq9h8t+fxf3sWjy4wyQiDv5upchKxtz6aPdSrvJ11n\nmXhB7LMozqiQnaw5q+63aGjjRJ/yq2+exHRfol7m2+/4Gyrd1IXb3qwvnvQ0\nlFIsx8cp5x/DzZ5vq7pFA7BcXltDYN+bE7IAawFk0X4UqhMRZg7jQd9Cvlv1\n5bM4u+zzHr7pQv8NcGOJnokvXtrYxOIYVgqpa09uvJ10Tw4odOBWFfW2siN4\ntGdtXgTH2STHtCA+83/ymkV5fISAYmyt0tkF77ZaPj6OhKSV3OK8GbTGkGTH\nhfOaCAoIfRe7t5wk+/jojskNOZdACh6VUfYix/b1iFZQ3hRxMJZZUmJ/afWv\n6rbU5xho/Qhkd0wRG4I1eq1v983r7RyadsCz1HHIzNx1u6dyCBISg2cW9AZy\nniLKEAjmr+N6K73cxJizuU8ZA0DxKzz83UAEjBEgQliLVMbLl3iio06KCArr\nzeUq\r\n=vvy3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHTVESW4nejATnb87fm105d1ZGuXM0EED/xxHIMwn/41AiAjMBqLucpLzXX0a15hwfKOJHMgGda+Kfw9vfjm+PRSFQ=="}]}},"1.0.30001022":{"name":"caniuse-lite","version":"1.0.30001022","dist":{"integrity":"sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==","shasum":"9eeffe580c3a8f110b7b1742dcf06a395885e4c6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001022.tgz","fileCount":787,"unpackedSize":1442045,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJmLCCRA9TVsSAnZWagAAPIYP/Rz5eI5ZBmMB1YU859au\nVrpETjhXNZnMBOc3HpXHIt8GMPqGZKyZelbLbdj2rPxNAgax8k4fMqw32Ps8\nq6txqNTYvxw2Z27nDRXZUDfJJvd7RbMXSd+rTjUkb81ChSGxqRxfs2GSIy8q\nqa+/dJl41lyVuto33q/9BAgUcv6rxKbYayJkdml5p5pgoFu3MkS8SkSWVyZL\n3dOGa92GEwivqUuCLqNVeow0/qWmfl1O4OhH/GxIZ3KSqv/J8RkWq/UBiQ+e\naH54dtZTdUtpLIF/RznDfMk6JSjVB0A/9c+2+OKrGGzFaT5JBy0/IixD36VN\neWmvVl+P8M+GWe00ufqzTfUESeRzjfJ/rQEOYUa96P+Ni2uwYMkRLq+JiKz5\nT0QtRFlpuMwbwXve/myPclAZPZOQFZU+rztYOa+UR9cvMhZm+3+vebDie/dI\nhosx/m6mksCWb8WsjDpS8m9vqRI9nu8tXWpP24sgqlEgHKlR+EsNaUdL9yNZ\n/kf+OrQP8Su8MWTjO/Y0FCwx02oGjLaqNUHNTfqqOCwlD/U+bIt4VT58ADKH\nJUb7pmQlAUl+U0F1cFQICK3npVX/e/EhMOjLo5/gXSbVpeicQ/8KdPkOjYzD\nYM9yWc4RodcRYs5JoQuWkW5jyBPiEgA6w+eZUqKs2vHQYSIEgNB7MDtL+S5S\nhC/G\r\n=TpMY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBn8nMSwegw7Wlb0r3dh3cMBTRELhL/tRvfyLroWBq7CAiBCelT18QSFVoUKR98MBiN7Z+9bFGAhoI4TG/4yCIlNPg=="}]}},"1.0.30001023":{"name":"caniuse-lite","version":"1.0.30001023","dist":{"integrity":"sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==","shasum":"b82155827f3f5009077bdd2df3d8968bcbcc6fc4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001023.tgz","fileCount":787,"unpackedSize":1442131,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeK+8SCRA9TVsSAnZWagAA84AQAJrxjUN/jj5wV4k+S9Bo\nZ1T+JPgkllnJLQa+GCGADbUakB/Lgh8+K6WT8mzfHazYoXs0Hou8Z2nnB6Ev\nlbMcBb91793AMxYidu2JuoDrdXa4F0sioCYrhL07UR7i8d4Y1FHRBn79ALTO\nh9VQlIVxivRIsQEHwR1oqrr4L3oL50j/K+1r1LJtTS4rp8+77iR2f/106wZo\nZr1KU7HJ0+vtSnZN9/EvT0xOa/1pMJ86Y8Olj3/OArV44zQ2JhbsNNXd0gCK\nOAY25jqQLvkkz5mZNKPFSmRYILmI/8TqfjWmxM8eBSV+Iy++k8vp59csugYW\nNYstM8ocuBl7PqB6iZCzruAEdhDmXMqJ7F8Zzi3Mgf8bOfwRS/jq8v7w0hki\nlc4E6MU0caNW2ktl7N2bH2Rq9RryEwemOcjJd7V90tscjpnsBZvcqeukbyis\nefuaSguidmTNjw6gdZQqlOuML2occ+V2mC1bfZde+sE2SO8qlGoafvwygqRo\nVursPRtvckJWMQ7jBMubGjTN29ueITo64DBW3pnRMLxYRmN3Aeu74zIgyVQQ\n5E3Z+8GUyyRI5X6ti9OFr+EGaKlN9ct26lGFcKsUd1xQGzKgb7QlAOGX/YnZ\nw6wnE0KdaaavI207zEiXvp61lPeAFeU4BFeegNf2v0G+9zJqgpna+O55g2/a\n1SE1\r\n=C1AV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHAH4ltDMVdhr/jIgQCfNtt7YpNtu/tFJyPyHsZgISJjAiEA9OPNaKoli3TxJKIbati0BKsVXfXMGH5cqz6yNGBYuIM="}]}},"1.0.30001024":{"name":"caniuse-lite","version":"1.0.30001024","dist":{"integrity":"sha512-LubRSEPpOlKlhZw9wGlLHo8ZVj6ugGU3xGUfLPneNBledSd9lIM5cCGZ9Mz/mMCJUhEt4jZpYteZNVRdJw5FRA==","shasum":"7feb6793fd5c9d7e0d4c01c80321855592a46b73","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001024.tgz","fileCount":788,"unpackedSize":1443283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOJp2CRA9TVsSAnZWagAArwgP/jsy3+6Zcr5F/EqxHA1G\nGqapCK0Hdh9b2KkUk/Hix367NS9KqnArLottykeW/lPwt3nQeLXULNzC2hlZ\nTpvT/0qd+iVo6HeHdOksiKtczqSJX4wrz8GwHI1TkFo1ZSrc1hzr9dyLMwhy\n6Nzues7aHch6p+C3fd4l9NbBAzF6MJ8TgEWe68YfFFwvi2sQM+2tG3bVTfvu\noebk6m9nCKm3Lozc0dV3rBRZDx1ps3hMQf/xWsV1myb94rIgjtOnePNtc0Oq\nwRJwkFxaQbG/UCGExoV6RLSJB8INY+zLr+en77EFRrv26/vIw3b3yKjX/guQ\nq7qo5nIoSKYvMKMRuddmcYixWN53jffmWBT9/mnY/BaSHxRFj2aUrNRDd+/z\nJ2OXwtIy9+IypXmjfPO1WeRK9iMHmP6kp1odyiH4KqVwrU7TwbggqlwV9ZKW\nudp6Vcs6FdzkXf5+Os031yUx0qpZ5+o4oblLg2LV7WhElYoDoZeM70zc+KcJ\nh9wiC87QInA0a1G1iVAuLo9AsSo4a7akUAfXN6V3kxsZpPylwBuMHwSMy6wW\n566YZIJv/VZAJ//EZE3qu4QUiLTBFmUSIjCnr5KUQ/P7HOWlVRP7oxhy8rc5\nz6b9AJeADQTlsj8v/ALvP259tIMecQV/Hyp6geaGJFWuVv9EDw1j342gpllL\nWiiN\r\n=7y5Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH4Ti1XiA0b5NOydBVSpC0gW7UNmrkf/NnYAuLQyhl0EAiBVtjpapm837vG064/UTnnbbdqn/9D9sf8qAjChgjk+aw=="}]}},"1.0.30001025":{"name":"caniuse-lite","version":"1.0.30001025","dist":{"integrity":"sha512-SKyFdHYfXUZf5V85+PJgLYyit27q4wgvZuf8QTOk1osbypcROihMBlx9GRar2/pIcKH2r4OehdlBr9x6PXetAQ==","shasum":"30336a8aca7f98618eb3cf38e35184e13d4e5fe6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001025.tgz","fileCount":788,"unpackedSize":1447849,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeORAeCRA9TVsSAnZWagAAxpkQAJLGYztb1gID82evSfSz\n2K952eIX0B1P9spjDhgYzptkNbqviZcwcmWKefh8Ab9q1qo2K16NAMWhhQGU\nBwq1+qwQSJndrIUXgk1paHWgwSm1ptyuIBB6AyBkjlmSj4E2LEsCj8OtdA5N\njy9Gp0u3IrmdqnZt0uBwyVSrjB0/dnahZw9Y9MXV1lgWqQCKSUB4OOw0zLOh\nAqowQrrpmcisXhgzwsGpBKMH9DATImOTnr7rltgMoeDuOTx6ppfZ711ejfvv\neZcpjvCuTDVMnf+gqXZqB2cHcgesU9v8uGAsNLKs+bUsNKFoezhQcltFbVhu\nxaOwA+cAN9dCilVoIsSLzVlvdyBzDGJwHKIaQpR5LDazKwoLKE7NRatfQmcj\n4siDuYDz9ImhKx1Kbs6tMBIOyDfW41VOWHw43u2q6pFJK4txCV6I4BXl6C25\nQu1o8VJWUXKU2SY825ILhF1VVGroTAw5b5db8X+FXCKDftguiQkwV9Q6dTaM\n59Uid+gdp7ZASO9iJ+BLi3nh9Vpds8g3TNEEUjre0xdUbm+moID949Mz9wSS\nHuv354OWiThayWw3q1DlumzW65SMQTR5g02XZzWUIIkirKiaxW/Dpy+T7SMt\n1Jn76Uu/ZfJiXjXUt3BoSFsQqAOIuYYvrsJyHlshwZaneB9RxiVDgm6r32tQ\nXbpW\r\n=M+h7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE32o1TtQW9DS0fbD3/FwWwI9Ty7NT56bLCg+fkOdkRVAiEAtm/F1ks7Bt63lp4QJwBZ668W6xYbyggTCO/SJO+eVmQ="}]}},"1.0.30001026":{"name":"caniuse-lite","version":"1.0.30001026","dist":{"integrity":"sha512-M7y+cJgKuDw+WIkRg580LhkjYiXifWjIDlvlDoCAaRM67ULZFHpWzoaF4/MfLDaZIJ3fuAmi/C/HSWZxtP++Xg==","shasum":"4a5ca93f8cedbd83a9a9ae93caba4e791c12246d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001026.tgz","fileCount":788,"unpackedSize":1447909,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeQNz5CRA9TVsSAnZWagAAH9IP/AqxkFVE0hY3Ezki7by/\nCQ+nz0SJuQkJo6JYlGD3yqrOeUbFIOLD9RulswcVzB/gtJRZRpOF9S/hjs2y\nqVt3IPPdt2SlEdUS3XDy4L6iDqmZaYr+62+iiB93sg8mCWCFAukgreSQQ3lB\nMX8iblbb0lRgIJVbqgqESfBpRg+44JzTRy/ytW9jGwtl71ro8+oKWstjDbG+\nJompciuT/2AIX+/pL08RekcOZi2rUSTAXRKRs12pZ9GXfRuV7mI9d9KcZP2M\n8CVq/65jWFXDt9AQVPd4+DTXESmlGypWS0CPn98v2+Yp2270/2IkRrtFttyv\nqcFyN0dGGVurj8qMSC0NpDfZy5JIAqSMz+BJa7vdVEZ+P9ozqWgXVfh2s6CU\nSO+ZJ/x/zPVWg3KDd9R+5AzEBBaMc/nHMO1sOd0FjVPAz8S5iwdPzBwpoYr1\nw0XjRTvK8312Ou4Qg0QG1X8ShpelrHvcbZd4l/6gSUGX+reyMNLnSMRQpbdL\nV9G2bEzsNXYossXnleWsZUq92EtWBiKWWEUQT5SAvkinzAu5uIbrg5GfTOLy\nqnoEPsQoHFl0+3aJRZqAWVNGJBkUUbXRzi0vuXhtM5u+xergjMkWjTzYwdkF\nfj1FnR1TPwLNtTawA/GEFruP0VuS+QbKPZIQ4KcWBGAWfstAxQUeKp+UG2RB\ng8SZ\r\n=jZAo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGlmyTJSDk7t0WxBy7mb31j/HMNGcS7mdaq3Zvpcj7coAiEAitkAdi2s1YX+ED1Hn/hHsxVxhjX3nivzrp3S4ABaBZM="}]}},"1.0.30001027":{"name":"caniuse-lite","version":"1.0.30001027","dist":{"integrity":"sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg==","shasum":"283e2ef17d94889cc216a22c6f85303d78ca852d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001027.tgz","fileCount":788,"unpackedSize":1454477,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeQOsNCRA9TVsSAnZWagAAzPgP/2+sEZvBcGn3aw8yniXD\nWxErf/bPrmWs3PYXlWMaRIfqw+7FuDQEBTLaZrhC8urEtPuw2GoZrnz13nZ2\n+qa8pjrd216/3Aes0hChkw79l2bZl6UrX8UUZWhRbYvzvk7X25NGYlTaoM9Y\nGeQaBlmlmFJwlKRlyEDhh+TcFigBk86R8tGvSPOqVXGmzmkA/KKdoXMF4BrF\nSBkfrCiK13CDsd+MCIIhEqu7T3n5hV0+9DT7OJeaIA5ywBj6T2vrOPFrTbyB\nWKK+gTSbHGFDE34ON3bblQg2ptW3B6G0SiU+2ZMGToqBrtNsGcTOXpoxAm2X\nnBpqGv2OE71gx1BbMjOvVRjXf44rWfzx+Z+W1I7z6NhmQW1uivcWqUsRwvcr\nV51qtJ49ANwKCdbh2j80jO+yLie5y5EHUzaxLLdHwss9psTbqCRgb1LGqP+m\nlod1bZ278Avm8ZWvt0J/xh+9hRGfMVAdDuD1IHbwRMuhhOqOXEiPXElxD6Q2\n7tr9IhF3+mumMLlzWQ0EA3v7Qkw33rOlbfbMLNeH2thGX0XETGjFy0jA2eTH\n+KKUkQdBgywSxIVEG4nY77WDiaxKvI3eDImz/F75dwLcvIpAd+xT9T/nxIWc\n++0E04c7vSNdiKFQHaU1h75ruPd4KgfA5lpZVanaB5Vs/NemIekaF++8cHtA\nN4gT\r\n=q2EZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzrYsyNaKg7jOdMV8QWsv5O1Ubn+7JSV9tAstKbAwYlgIgceo+RHTFx5gktcbK3uOnO5Yfv752qcfcidQBYxM9K3s="}]}},"1.0.30001028":{"name":"caniuse-lite","version":"1.0.30001028","dist":{"integrity":"sha512-Vnrq+XMSHpT7E+LWoIYhs3Sne8h9lx9YJV3acH3THNCwU/9zV93/ta4xVfzTtnqd3rvnuVpVjE3DFqf56tr3aQ==","shasum":"f2241242ac70e0fa9cda55c2776d32a0867971c2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001028.tgz","fileCount":788,"unpackedSize":1454558,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeS3cMCRA9TVsSAnZWagAA8X4P/0EHRN18SIa/VnOHnyHI\nsAPn40/rk9CC3xYyvkZnyyY0qJzvliNE5U1rvB0g16ucJ4OWmnKW7sa79qQd\nZLgyqs/Ima+Zk8f/lfBVi/NojIQwLAjzj0hBU+OysVcBSXVC1fineqWDXpg0\nBMjOZi/iXBHjrBsEtruQizDHsaS9pYpzveyHOUVqHc0VbJ4ghVZhIqP1ASOy\nCVghKeOUuDQypnYve1tD3JFB3fcIg33QEBycpjgWea3ZavaeF76oPFoDFPr8\nFKJFILoHEQ6IUtn9OIG9t+lKB5x640T7qnqX6pQwtyO0QXYCY4MzcUpdohln\nj/V33dr8ElZdtEX4L35MiH5ODSNp+ZIXtE0D/ohv/awQwrIAMt0YEY2Gdx2A\nYxE16/fd28UZueowFd9SV5pIy3GCwYiuX2u06ZCIflKrrVCy03ZIb3vOA9Bu\nMhzZ77hpRKpBX7M4LOB60SyVlWFA9GUerzc5CSQDl/ty02OsI65Y1glpiSvA\nx7//fcFpDnRA6bRE+uR8SA5FMV5IEjGvWHdYEhpVpqe5mjumqIpv3L0qjqzp\nc2t8nPMqqHBp1/RAfYkYRDuD/d0isIz3cRxxxFhQstrzgB3s04pQeuuyyJJH\naltpsatlstXl04K8X/CmtPvEzW1DbrVZGVjARcXmY5XM+u9YeSMU3kj7Idmc\nsXeF\r\n=V6Cj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD0alzs+jc2gZxHK2WIp62dG2x3IbC/rRPfuLOdkvb1ogIhALMBhZtM5yd/+JNP9uERVoVBNWzA23fGnbC+rIf9eTpd"}]}},"1.0.30001029":{"name":"caniuse-lite","version":"1.0.30001029","dist":{"integrity":"sha512-anyTt5lJAF0IyHfyjZGY23u29QeLkVElCe5rYefLc0n6YoYvDiwpGj3PATtRrkRDc6rQoe7qIZ7z9rJRCaTzGg==","shasum":"249fa16983413c0e9d77ae052e28a733fcb9f334","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001029.tgz","fileCount":789,"unpackedSize":1455693,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeU2AKCRA9TVsSAnZWagAAB18P/0bXXRVaqTpEq0RJAfE6\nV85Ox11pjCPT2MwtZiqnX3/7wn5wIt2kbMNtocu8oYPCPrC4ZUN4lEekAagx\nEJKhwryRmOLSanNTRVmlfnqeHHdaD810EPbHV7SsSLIxbtKYnl8Wu/SRVVud\nJcn9FLu8w1kQVocsQUoxYruHRdYNZM5GMm8eQrmqM45a77nPQ2iwzgCj+c93\nzjdTwMPJA9vn1bdpYyNbcERrUMjebTCyZyT7T5JTWjgGGlUQmuIELQrJtIfv\nmklzkTtiNdO2UnVvd4sk6c93denOSRgTxx8S4Eh1bAAp516gkVGpiUmetFmu\nqRmxMSd+UajAWTCfRyZaYDlZh4eR82GA8y7kuRnKjh4C9kC4phiwb7puonY5\ncviAAFN/mo8FO5Itl91eJaWhFyQqmd4wnSbQI+tftC8OWsDU51DFWQcNUeH8\n26DAKTAmdq6vbIBjXhXzfFkvBfBUL+Eqxa/6iwSrsYq96RyKd7maQE0nT98Q\n8ocEzDEePy1EfRcTpTM9keJRol3/Rdy7YvIQAFqH3meLgowDD3kBmkTw0/wz\nkTeIBFprzTQ75QwCGsY9NOVXnaBICQtqmSF2sbNaoW/CdIOQLkY4R+WpseY5\nC8mm2JNAYj7kh7bBtp9mKdIKbbnPxIrpfZuYYF4C2cGnGrvYKm3dleVsksw9\nUwX/\r\n=yvuW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmm0YBz6r63WfHa9hwnoKCcWcWN2uM7WTHqxXHwnnIeAIgfOrVF5LjHrcM3jYRx0USomeoLm4XQ52Xsr9/q3N2AAQ="}]}},"1.0.30001030":{"name":"caniuse-lite","version":"1.0.30001030","dist":{"integrity":"sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw==","shasum":"78076c4c6d67d3e41d6eb9399853fb27fe6e44ee","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001030.tgz","fileCount":789,"unpackedSize":1456844,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeU3wvCRA9TVsSAnZWagAAkzYP/26dUWiq/JHN3fSeD1Yd\nFFiIkHqisRuJ04S4dW2/42AdbDk3Izae24J0us0eYHxlndXaG3IbBCaPsWpo\nvQYidSybGsIYTFfNANxQqMG8cu7iNUSrKFQ0rJJUyzJBVVlGfptMTU3ZhiIH\nQywMhC2C52qaMvoIqJ9usU40y/UwvZYl0vLlDaSt1D2lp28DKye7ZpvYO4uR\n9NVNJ+z5T7ELD9eIpGtpjU3og2KQCikUWlQRGzgvm5x0X7XuBZTf3YnzJQuH\nZhcb/YHesaRcnJZYUOmDJIcxJzFFW33Vwb7lPdIV6ZlNaFpXCIiPItakE1MT\np5uoFxlWYlGEt79psB5T9sDGVaNVbFYCe0wWLdF27i03440WGfP3V++eDcKD\ntVUlgVtab+/xl5EunW6WToA5TI6OtFbVDLjgc5SULUJKM3wownRDVOx0odiO\nQORgoUdg9oQyn2SwnARIEZ7qqGS9sT+upSEykL/A2NW9kfD5oawVWa5YqD+0\n4foXYDHDwSKP12WM4HPyKdGtcdm1lvXbpRyXZlD3N5vVmW/nZ1/okGpxirBA\nrG7KM+1nqWnAD2pGocSEO6XucdZ/DzdRumtOy2tIhp5mQjEUFl42BDGlRuzD\nUaOT2Ur/EPUhlhO/Hx8diiVoeO0ef8J1tfpCMxYbCIKLLciCIStAf+cXUTaW\nhC4J\r\n=D7ha\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDaqA5qV7Sr6QsAtLdIkbltq2wQcfYL1KShK+QjUpLRGAIgHfkEdDLZssOXYtMBpBLDNXgkPcPDxQ0kd3p3tZTopW0="}]}},"1.0.30001031":{"name":"caniuse-lite","version":"1.0.30001031","dist":{"integrity":"sha512-DpAP5a1NGRLgYfaNCaXIRyGARi+3tJA2quZXNNA1Du26VyVkqvy2tznNu5ANyN1Y5aX44QDotZSVSUSi2uMGjg==","shasum":"76f1bdd39e19567b855302f65102d9a8aaad5930","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001031.tgz","fileCount":789,"unpackedSize":1456914,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeXJqJCRA9TVsSAnZWagAAzCQQAINQ+sN+zbOHnR541Q4X\nBF+bwhGCXTFMFO8VD3/OwF10aUuWa9NHkXLfQc2lzw/SUEMBNq65V0WW0czA\nyBK55+/p0CHk1fUpYPaddN6Yt7cqd/9XZW5H91IOZU17okMEiZOyjsr6hivE\nB7opkQnfw7vnbGYlqsXfcZ2ra0Jg9A2hfqHxaSwxb3sD3wdxGEuTmDm2YjGb\nLer2Jzl1YJp/icHaxsDZmXrDt/rdkwMcwEaml1lgY6NDD/I5U6NRWszm8WKW\nMR+gGnP14g58QKB3Kv4P6YVB+bqyGu8mo7fwv4ArKkqINVYH30uP5e4Iq+CI\nLKSNwx4IZvwhdp4uNPuHs9NkZ2P6LUDAPtll0UI2gPdsHtZxR+VWfKOoTtLV\n6ZEWHeclxUiB/ZOjeF007NPNp/Bcy9yKkoAZG9AGstu0xKxpGi6UhG646Cev\nA0+yP5uYGvL5dpmpLO4F5G1oU9cNGGb3ETxJcWyEjtAt5W46fceVk9ekpma+\nT8YrxSaok6Hu6s4dsCGdperj2FtWNeazoQKBhowr7H55k4GdcsTS9EytGCwA\nRi9N+xjPozmcTWUnnXf4zB7Zr2u5ShB0XuV4MURNUGP1QquFvUelXyLbAjTO\n5p5qp8d0bC1uoCimE8TbFMav1FWbSnCTMbZ9JExUZd6dwLS+LDuMrAEs+N03\nAYDW\r\n=OhYf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFR0wb7c1lSVDDARPcRurH9WGJkdYygvpI132ycduO4cAiEAqyqqxI97Km+VQyn4Van6Z4mZ5kqhOewssMoAeJryb+4="}]}},"1.0.30001032":{"name":"caniuse-lite","version":"1.0.30001032","dist":{"integrity":"sha512-8joOm7BwcpEN4BfVHtfh0hBXSAPVYk+eUIcNntGtMkUWy/6AKRCDZINCLe3kB1vHhT2vBxBF85Hh9VlPXi/qjA==","shasum":"b8d224914e2cd7f507085583d4e38144c652bce4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001032.tgz","fileCount":789,"unpackedSize":1474269,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeYI8WCRA9TVsSAnZWagAAV7MP/1eJi+I+oV3+SPQn0fPE\nXFq6SWYOXIPOvjjuxgwX74rBAxKQBjxbpC22WyBAXr8kdTl9kpS4Ky15axAK\nKQLgqPfVlVTkmGhiP9g/i4BfkzQ5tj8Lhwc4fPwha88dek8rYrlZIjSb/Uzx\n1h6iAwM5XtLWAJ/2j4+X1/mUwWeMqy2XUY/EqNWrkB6+WhBG9uhjf0AolGoG\n8h17XTylVD9OzWnUyL7azMvH46iAPmbJkv5qKh4AzoiAqRecpyQVngkmjCFx\nnoPNf8ZfdklvjFM6KTyw6+vIJG2bIob7PFNYSnOgqqfPdgoZlysFWZ4DflH5\n4jB8RIAH/MNX1NuBQKUxBohdfSx8ZHdHgndtRBvCX+gUJXsIgnG0ZJ6Ep2dP\nQPA6FqNj8U8KGy5qEyYcqHe72oJfrxBbDLAVyR2p8LcvHwpH0HhGm0yDSHgJ\n5UrE8EK46tCaRW0ra7Fxi9SfIVT+lfB+v22ByoXkT3n9eQiB/nxez8Jc01jS\nyDf2P0mQ9yLQxpGN8QBWWUZGrZDHj02y7LBTqQCNBKO/2pIzcd4t2m8FiesS\nEQL6takqgbwGZ9sS1AzBEGbsA9vRvuFE7s3uGPEADK4eNRLZyL35Sx1esgxC\nje7Z3UzQ3ajl1PHW28nLMV32UzllxFPjny2Q39T5G6r408Uy3TwxDbEXrqWe\nQdqT\r\n=Gd1H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB0XpPm8hKfl6YoXt5jtXzqB3BQZHrWX13G6GWiNGG+bAiBIZ+zt0zU1H+gVHemCtSDSOLqQekDadcFzFVO+oDZSkA=="}]}},"1.0.30001033":{"name":"caniuse-lite","version":"1.0.30001033","dist":{"integrity":"sha512-8Ibzxee6ibc5q88cM1usPsMpJOG5CTq0s/dKOmlekPbDGKt+UrnOOTPSjQz3kVo6yL7N4SB5xd+FGLHQmbzh6A==","shasum":"60c328fb56860de60f9a2cb419c31fb80587cba0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001033.tgz","fileCount":789,"unpackedSize":1474361,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZdUTCRA9TVsSAnZWagAABEEP/0oV2Z15z03wJAhDvVGa\nXoaFlXzq/WqkcpZy3/SytRaGZeZeDwFxFLs2I2+fgN5vq110xkiSPqj9Vk6Y\ntiJukXfp/xvveckUEKy5MIRMt3EMsstKUUGKSi77MhVubU6WbkpPi8oPXet8\nYarmC4oeEPDJ10i7AMZyDpDSVF2ofviEzR94ff9uvGC99viYEWd7VUu4rGA4\nCnPU1W6X5eCdKhY+a05/tr0ZXQhNgT0I7soZ/W/xG3BfZe6h3kT668SSmyay\nrLmzTasgZ5eSkGYL4M9MPmvjfrVTJbJqfBPvIzXlWte1hmE0m+7MWT+wH9/K\nLXbmomdw9HFEP7d2PF6Uigv9DqSGygF8SbhvTGM6VsOx2OWuXshjQx+xvBm5\nFtWI1uUz7rly+vH0d0ocuPFmXKEz1jbLnY552zLpeACCRxLYZXuaJAFju+bR\nziNBMUQk0MFdxvQKNn6h3yeHCmuu43guNpW4z6pIzxJ4gfKZfGqU1MKRXlhU\ny+ovVdY+JY+votmGcSrA01kFTr14x2a+2RLYeoXGr70n/IZ8oJUrVTc3wIit\n509eqiM1Ea3ge19FxqbftLkbt1hYo2nhdo14tKW8f4eW0vF2RVoxGO2J8svL\nKmm56NTozEdERVTjB2rkBJRu06j+HEHvGtgNi7aeghBmzkWwNCRSiBzeArWX\nD/Ls\r\n=qKvN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFRwWscotLWBQdkRIiqL9iwA4FbihKi3IVzSCu/AzGzWAiAtAEpwXZpmfPNOdHiz4Uerq/HC5PkV04Wt8rsaYF2jQw=="}]}},"1.0.30001034":{"name":"caniuse-lite","version":"1.0.30001034","dist":{"integrity":"sha512-MoARDV6F990onyNm6uC0F7nV1ZSkEmlVapmfxVmEB+my2FKtHPDJnp2qgo7qnnXqCT/NpS1FbgdyjJ8Knb427g==","shasum":"612d2bed8cdf49067a1bdab3f90da41f5104fb02","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001034.tgz","fileCount":789,"unpackedSize":1474433,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeacmKCRA9TVsSAnZWagAAGJEP/3e4cRQisV0tqN/NoEIn\nfTmOPfHxKfnHocMPX9JdAIPoF1As2ejCer9J2gwgpUzRNfz4tve2D/HKK6ag\naYho7MsrfeCQ3dy91pUz4TzEYhQVdMKlp4w1LbB+02IBhU5ZMdIrjwWW492k\naTPyDSYnQorqjeRF7y07SdFWTjSzDYxWniQ0XpvXLpdPx/JnPndGfhg/I3eS\nFxOekeQyRVhNj4dgQitj0CB8N8Nv6ZU7wJ4n9Ns8mevRKkR94M5mw+Gu9vXy\nleFAoZPr8sCaWVwiH+SGZ+0HiCL3puJW1Pb/KULTFYIjRPCDmHQ4PkLC1iJ5\nHCSZwTGGMKI6bmn2igk2Qlu3WKfZYIeR+yOwUPKK+TOst1NbUebKM2m1kN+B\nPLAvLpEl9+D+VHck9LWoFmdGc/tSO1dfGn01/bfJcJ/5Xb5M1yUtgAHI0Rm6\nNtM3w9AronhMl0T3pl3rCuDgEaR3jeZfuKFXgtJE9uP+6xjgu1WhYurMXYAR\nZBzZDw6jqjRX0/g4g/EBAf4apNe1NQu6qWjTJyKeXVc6lWKukwncZQ5CauGJ\nAQzIF2PJmDNvSpnfgcjQVFiTFso63K7fYh92gOvYfXqaF+oHS0HbAtjJn2pU\nrk83Ivyjux+LU326BZgYuNlit47piOXa0qnxar4mfLPKGCjhz5qOtHWHtXzU\nUybQ\r\n=HFva\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOEJsHziIraAYlL6dtkE/V7Ib2qKS/L1hwNTHXInwoiwIhANCQFHK6tSmCoCj6MQgBJeKE0O5V1l5Z4CyTqUb2/UL+"}]}},"1.0.30001035":{"name":"caniuse-lite","version":"1.0.30001035","dist":{"integrity":"sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ==","shasum":"2bb53b8aa4716b2ed08e088d4dc816a5fe089a1e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001035.tgz","fileCount":789,"unpackedSize":1476096,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeadeeCRA9TVsSAnZWagAARF4P/0rugNxZhp1oH3kpeKcF\ne+bQI99kvnxY/4vbMG5RRF7jVKYKfBPnQ8MSyab24duZZP/KVbTue0FUP4fU\nwcbxDLudrXran4J++ZQCEQlVH1TXdp3OfGGK/T3CXavs3SPQlJ0eNhC9drHJ\n+HpnHcDYzD1yVLxJ3QdkC1YPLnik3W9DymBQr53ORXnbQbXs73F2HuFocrJa\nCmCvNheC6o5mCfMGWelZKpUru7jN+7gCXoGPgFzNWXjoNUp8VWbTdb5rRRu4\nbYsBtEdBtSXXc2GApFnDJiGQIVS/cyBZ7FQ+uiQGrzKltG2Y5N9ibLCf9lOx\n4ylzUsEiV7TKadmRTF2bbqyY1KDtlU9VVeHmjAmeqGw5Sq1cIjm0V1wMCf9Y\n03hdDFp28tCNof3jU9KJbfw/AJup1sCPkWpzgVaK+Ll7SBG+UXmHpvXOR6K6\nf20CWL+wjVfd/W0sTclyr820aCKgRwYQoTzodw2iIrtt09AIRZTOLnvbziQd\ns+4n03k8VSVUbC0owcSNb9V3KDRv9c0eEtOYJuFuQ4LtI9izcB2j1Be3B83m\nG/a194dtdJqwTimaTYLbgcinewJ8nXNLKaqC5af9vhK4cCubxEvIqMfgFxXw\nVClPpL3CaSgmT1y+1ePiF467tFFBywVlLBGLqgp8sUvrzwEBg50JxSsL9hdT\nxqGR\r\n=jbqo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnQssyLzkqCb9PQ489ue7mq+rc0QnMYFZXZ6q4PiJUAAIhAIyasR9AOlNmQi0wUjZmqU1AmnfwITvbS2GwOs2S1Tww"}]}},"1.0.30001036":{"name":"caniuse-lite","version":"1.0.30001036","dist":{"integrity":"sha512-jU8CIFIj2oR7r4W+5AKcsvWNVIb6Q6OZE3UsrXrZBHFtreT4YgTeOJtTucp+zSedEpTi3L5wASSP0LYIE3if6w==","shasum":"930ea5272010d8bf190d859159d757c0b398caf0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001036.tgz","fileCount":790,"unpackedSize":1480426,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeFgjCRA9TVsSAnZWagAAUDoP/0AeEQqSryMeWoEGwo1w\nzgOUkzMsmQQ/1XLLEFhGUhD+eNVz0UK8Mf/64EaGymD6tiJcg4JkjhaGxWnF\nDEcwPfxbqPy6mb31Q8YdNAHzduJS4/txD+1oX6iI0057wB/SWGu2XJ8Jtg3r\nZpisJ81+zrDQQwSPBfMILsEBxjR89Em5ShsUjQuk9cU3yxIOQYGOQvJHqkWP\nQ2Gpf4Amyt5J5MqtySrrkK1TUsiNoHAhZUs/f6Et20jg7O1XuvSmh7Z5oCCn\nJmv/0hs44Tb4bSU0seJ4gLGaeGQHhNbw8K/+LtRuZTaZ1uIYdFvtNAZz4gsP\nuinYPkk2eGWqXruRMCwvx7YhaGAG8F0ok8PEaYLgZbcX/8mzDibLMGQRMpFC\n7cn2VpHnvKkPq7puAkpJP7RBw7LF10J44MtqyxxIhUxModleDOnaFOI1L2Qr\nIUTteRKk7YRjcZhkFkw3UyXW8G8ZlF86KRnli5FHdc31TeAOAIadXCSgiJZO\noOgliH7/lSpkQgIaUT5JJwZM7jpqsG5yHlX3BRBs6YmGXSXEWZN4qx2p8Wo9\nnS1Yw8nTd6EYxJOstXKWcN8MUuStb6r3OP0szJO5qn1JO9HG0Bz5656ltdvq\nHhqwFh2X0DU2uocJG+qKuFqglnfURfGEtF7pReb5d5GBAj5xN5/570jgX+jk\nKPDc\r\n=X45B\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBKfqc7LoUofKDRBGXUYvLlICKqO63amx6ETAxqczgYrAiEA+ccokF38RxSwxMJJo/8Pa/ALUFeOLyXRaaDOupBlQvo="}]}},"1.0.30001037":{"name":"caniuse-lite","version":"1.0.30001037","dist":{"integrity":"sha512-qQP40FzWQ1i9RTjxppOUnpM8OwTBFL5DQbjoR9Az32EtM7YUZOw9orFO6rj1C+xWAGzz+X3bUe09Jf5Ep+zpuA==","shasum":"cf666560b14f8dfa18abc235db1ef2699273af6e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001037.tgz","fileCount":791,"unpackedSize":1481481,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeeu0MCRA9TVsSAnZWagAAF7YP/3nPlE8NuQSLEEDWra53\njfk22AZh9kVoj+v4EouE9EPSp8Zkm81ZUHPe8ZkUdG9cpMHFUvECOFFpn3sd\nEfXngBsjxP3OpCW8apiu0mJDCq/a2ODgaxbOdVJ337EGl3HLVNzkhL4gEp7C\n48MAZwcDnM4pkiytjzDpf35odmdpwHY6m7puBRPeANnKyw6KyL/MUY4gPT5w\nNgNpmVtOdZOocuuHpjRFH6hSrPatK/NVmxLsCTko297QZbBFmqjgNpqd3dx5\nz8WJ1kQ20ZaaTk/M2l+XWueBr8F5+w0e7ZyS7BL/c3w8tDMBEiahwNvtiE6b\nX72aPUy/IOw+xOXS1FAF1IqOv1lg9wx4ShopsccNEV8wx39iPf2nM9u6bZ5v\npm43dCDQ7QuMnwmTPn4BUIPwePT/AKBebLJZ38dFel9Ck0Z/BK2sqWoHdMgb\nE+rfjRh/Fjel8OdFMdi8qTkYiL+kH50NkTx1md08uG8qqREhIqgUaCHTD+gh\nbXWfDaZT8THV75VukFQ2yfgitho3/S5RdtvWp9vIjypQC3Mu1pxAv5VIfmE+\n7wh1pgboGGUmC8wWIknh9xEIUh/q3ToJNT/fYmRE3av+PfhrjaRDb8PhAB+t\nez+5Yqxr2gfBqYdh71bYud6t/M3oivB06Qeh3XFbjekbV4SMkLpQj2CHc1JW\nQKEC\r\n=aItQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGLpaOpEL6OVcsHRtIQo1Ielr9zVr9rUHap+ETBwjwCWAiAEtdLhHUqM1JMro63cYjlwyYeTUSVKXhGUEgn5FCUQrQ=="}]}},"1.0.30001038":{"name":"caniuse-lite","version":"1.0.30001038","dist":{"integrity":"sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ==","shasum":"44da3cbca2ab6cb6aa83d1be5d324e17f141caff","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001038.tgz","fileCount":791,"unpackedSize":1481545,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJefD6KCRA9TVsSAnZWagAAJ7cP/2IRpBvvMIP4OV2Drjhl\nTsDX2YoTUXRjgFXIm7HrfMU1HO3oSkfWPdi+CHfgM9nDDFDVdw4IWffsKErI\nyym1qd8Y/lWwZAPjJ9GYnCBH+0jJHY03svSxPDzs7Ettwkqmwy+JAHUFmrPB\n1/8brq3tAn20YS1j6QO7OhRo5/H/irURJV3h3+lo64D6If2N9k4Uaj99i9GN\n/SBSdxYo7WXkVEWjb7Z10BrL9x277gPQj1SL/IuP3l3/l7hXBEQLM+eZZbV0\nCC3wZ+0Wk1tGYy9rGyREdZ9HnbvlqZFiSl+QxjZ5HY00nz6U6xTUmXlYC8g5\n15JsNyY6a6c+Fk8X27oMczOAN6JJ/DxTkM6QMT3cjjkx7t1xENahwO0voTx1\nQZxDCBj3WpQHO+RRzTfGKBmIzIEMPTYGKYnH1ZKoM4B/nD1y4xpgSmVM8DEJ\n3E4ShhfXrWvLQf9U2VSQ5KHUGa7f2CjEhPkCnC3O9scF+kbyYiDAD1iDVDeZ\n6SY5QekYTvXYBRw3cok9+TkSxPggZWSdbHcoADBGUu1KhqT0dpH2Jt/UukV6\n8vqAyPnWUC7DFs36y7Pv5V/BsQryVDuo6uHKG1OgXmC5GABPj8EH9LovexGt\niVrY3fqRz4L++LsFot9V03SRt/fnKE1QXcepyhCp2K1OAh1GyZSRohU2vJuB\n0y6y\r\n=VBbL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDR3h/V3giJYiWFshnTkGkDYvfiifDBhmg3LtCFf8O/+gIhANya9K0KPe4BBvHPwhoGZrjnwIS7S+8B1RYajKOKqRYv"}]}},"1.0.30001039":{"name":"caniuse-lite","version":"1.0.30001039","dist":{"integrity":"sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q==","shasum":"b3814a1c38ffeb23567f8323500c09526a577bbe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001039.tgz","fileCount":791,"unpackedSize":1481631,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeiA38CRA9TVsSAnZWagAAANUP/iQQzacru+XYicgSY2U+\nSwjo7PrNTTh3k03x61sSzw1wMKC9XvRayMQlebpGv40gG1Fp2sNR56HWIIFE\nz5vsqhrqZSWuCZiq0WXe08UA+jFQdqaOgVwjAsbRi46ByT/Msno+UmocyuuG\nGvS9qTpB4Wm98ZeySobuCh0uylELK9bdCXPzLEj3Z1GPGVlkplkkKnrBUC7T\nk2KmlPEJEicbiX23oKXQJBKSuTFypoQG7u7AKrxITYrdHecPDy9u0QbSq1sk\n8gcYEOtlbXWI+xK1kdWgEexPiuC0pAsURFBaB0EJoBHDmK7G5lzcYjE0HzU4\nh6PyXOpKuiky+2F85FD8v0+jHDvzg5V7QlQqQRxeRJxLzBXow68jrxKbOkQ7\nEY7HXj7USLCZ+SPp4iHNjs9jZb5cLTHO5Zv0FvR/5WQTNaNPv1f3iOK4rXYl\nlyL+kBtHy7cXEW9LVhubHS5HC7S8RLXc9FEXo2F70/i8tG6GwjRvzEgQ2omu\nMWi1/aqHQHQ6NSgKAQLblerbFlut7ngT3QuHPQ4A5P7S2sqKeDrmmGusZndt\ni24YxRazz3JieJkGTV3VcaCeNTxZESsat3utHIvUPlCBdAKKWbjk1LUCch3Y\np0vVGYMdLrrQ7ssY1rZWpQ9b9NEUaKBKMiNUBJLFuqYNl0Jz1de/NcA2DNJc\nsQNQ\r\n=LM8I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAqp9swLGizo9coTXAXnSNUbgtuJZ7H60C/Vwf268mc8AiBFhNfGWnFqKYmq9vsIrCisqYukWeZVHs9LXZY/TGsuFQ=="}]}},"1.0.30001040":{"name":"caniuse-lite","version":"1.0.30001040","dist":{"integrity":"sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==","shasum":"103fc8e6eb1d7397e95134cd0e996743353d58ea","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001040.tgz","fileCount":791,"unpackedSize":1484993,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejrORCRA9TVsSAnZWagAAS5kP/j2KG60tuanIM9WnkiAU\n1qkvC6NwbSifQXgjkebtvt0Fod3OJoY5m3OlF4CDAbnKvE+RCKntPHSlpYQF\nc7si3bVmtmXfDCHa5g/snY0iYPw7joewIGVQ3helDrN6t9t6mZgwU9hQeWXP\n0puSkfXleYiu3/6HeqnE0GUbhLitYEOLqQJv56SYF8QkIcXs2r/eq6RNLfRH\nn9WHOKvYEVGU0+4es8Vl2yrCMTtI6tuPotuXYjysjnr7rVUUuNynXHWfu2Rh\ncPdGP8XY8mzca0GdGbV2OWQ4iXhNYeww6z3OVwJ8iAKeiJ6rhvY9IVvEpu/8\nFUZ43UW+5tnN3rJ7vbWwGzFOyMVAxa/4Nx2waXttcGrMKXAzIz/Rqwl99CNo\nVFtqjc7Td65sQ/u+wHD2QoovVvRuwhQjyM6LhEcSi3EWjIRlMaRa+jnkzrbD\nK04QmoJT7bHXksJqEHSROItzSNlLVm+OIE99Il7wR85Votznx0C2+MxpF7dL\nDnKIuJU/Y81HZ/FQ3EGQiSC+YVDHGsbbGXrEA7Gsi/A7b3YRbNaw1d2GbyK/\nFzClLUnKLa3Vwwcz5IKnip8dJm/HQuLfqfg5GoOkBygCaakLWw+a3CeWvZpp\nyu7AuD2SoOanWaIDOBnRmWL8tflTBtd9agokEP0Ks2jh8Vl/1+m4RMJbzyNR\nmnfF\r\n=rytf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnTl9ItGrKKnFgsC/iRh+QzZ2s0p2Oi4NJRdDBhOcHjQIhAJ7T10V5AYGYVrVKn1YXJY+9zjxmU4dTd+okVUdUAO0m"}]}},"1.0.30001041":{"name":"caniuse-lite","version":"1.0.30001041","dist":{"integrity":"sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA==","shasum":"c2ea138dafc6fe03877921ddcddd4a02a14daf76","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001041.tgz","fileCount":791,"unpackedSize":1485057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJek91tCRA9TVsSAnZWagAA514P/3ngj3eDUBVyAlYcO1wn\n0Mbh3uf8/kPSSpZseqAmFW/AXefH3Yo5xO3Ek/iIEOmOxD3tihsRicpQNpDR\nfMqaNrdMGUq+r6Rb+0jli/0C+2zAbbM346+Gf7v4UBQZIT2fQn/2KObq4sR0\n5gI0A9XXAWgPPmZiklUlm8jkkldNoxpjM6D7znz3LUwhIcoiCW8LSDQ/ES2S\n9tF6TL89KTn8+8ZrqWo4WYGRBsSzzeK55uySM4GsQvD+Sl+keg6r4k3wEtsU\n1TFPAN0XikjtUAyN3XJXBNEPnlJbA+xsMtIOe+ZVsVAASVGO7V0NcbP918w3\nqSDL/huDqLdHV5Jy+uYK26AnwGYYiZJMsnngrG23bt6ObiVg/EGe4GNc5k43\ngR+UW3+4jqTSJGarNwz6ncrGpYmxn7QlOnRwN6X7/QOatqT9WSvP2ii63Tz7\nsooiRwmwYk/+y6+mlmu63jf5PXxn830TIJLifbe8y1rM54+we8rZi6DKbqBs\nOengUrGAEupINbCwUVINZziqWV1qg4lgjtTy9hJHa6fHil+U81QzFp4y+h7c\nwlu+6PyL/6XhZwOyTEcXx2d52z9m4oxIga5puqrnJ8rrGXnL4uLwceRjNAI7\nbriEu+gy76o+C/nnfDUl/QAL6hHSZgEAsgfWD06oAwDgseHUfMJsedlwCU/8\n2siQ\r\n=wbSp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFRIOfGKIw3I5rR8WAMPtCL6GOfKKZT113v4R1laVlrcAiAQ9l8AbPd9B8Gz+/Qt/hx1NAzc8VSc0l2Z/DlezoeDsw=="}]}},"1.0.30001042":{"name":"caniuse-lite","version":"1.0.30001042","dist":{"integrity":"sha512-igMQ4dlqnf4tWv0xjaaE02op9AJ2oQzXKjWf4EuAHFN694Uo9/EfPVIPJcmn2WkU9RqozCxx5e2KPcVClHDbDw==","shasum":"c91ec21ec2d270bd76dbc2ce261260c292b8c93c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001042.tgz","fileCount":791,"unpackedSize":1491264,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelo6DCRA9TVsSAnZWagAAqLkP/19LSF6UXiX5IU8zkk/X\nR5bUoaHrQMzMPqFJBeblS5psnoyarHgNpS9RqtlaS7HeGMOgTZ17BOyQ5oRZ\nEI1yDuSWCZ2xLM2bAR8xEgXCJAe8MiCM3Yj0Yu/9WyTXTO79yh2O2QEw5X31\nMF26eKGWYu6Pl5Fv+7q4dKCUY02l/Lk9C9oSZDA9xBLGZxZ4Q58dQZT0ONWS\ntRmrAySNfUDl5ZRQDgJp+MkDXK/xQtTFnrdxZ4SIAeK2w4MM9bXkiG2BrHH5\nJIHj0ovzHW3L7Qm2A7VOif0Tp0e7B9kltRrRnBeaGJI31Mu8YQ2ER7daFtDI\nrIMneu4XBzM7ELkUl83iSKTpu1lFcFu/ybq6SebikWGzAiII5eUavhrfGt54\nqUKqadC+4vJRIElzwI0mJihwKv6Ic3HBqa5F3HBl/TWF3RzZ0WbLBFEkhqak\nW/SHCva/7uh4UY9eBL45hmg7omO8RLSHWypUbsCff+UIj0cIuYKAbBY1Fy2D\nMkIoaGdqnIilA69QsYgConHc0xvAeONu/8w44YJJkmyfVB4zTEtVlnpIwm5+\nn1x4kChWhLYcZLyh6hypl38j8sNPLnyl2C7tS4XBIJbhdc0eFGINWZlocN6r\nvlO51ttObA+F/ZFHCursxo8j48yMOxFN/noqG1gzACPWv/SC55FXsKx7YEFe\nWEYT\r\n=8PNE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDh5gUyvX/y6kfYOZjJp6p56e3vsgtBeHRkoPiawz/VBAiBtp28P0fTzDpdptISYnyRYW1u2Lu0Qo8B8Up/v+zdeMA=="}]}},"1.0.30001043":{"name":"caniuse-lite","version":"1.0.30001043","dist":{"integrity":"sha512-MrBDRPJPDBYwACtSQvxg9+fkna5jPXhJlKmuxenl/ml9uf8LHKlDmLpElu+zTW/bEz7lC1m0wTDD7jiIB+hgFg==","shasum":"1b561de27aefbe6ff99e41866b8d7d87840c513b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001043.tgz","fileCount":791,"unpackedSize":1492971,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJem9SECRA9TVsSAnZWagAAMhYP/1+2795D5BhB0+cTtNk4\ndWrHaa2roeCvlVajpws1Knipd9Bi8KEf3yRe3RYN202AYJQlQDF7W7dsWGre\nkppWeuEA+9C4foDUuusCSyPsEP3WstMjhSgupRaHbDmK1e5IuMwXsIqQLBrP\nRE2RoB9K2YBqycDCyfPuQaWh6NfeqYuJgPjSTZuNbl+ARMcvUee2xUE32x8g\nnTGBREJgjI5CtMYJ2g3JXe33Ez5Lo2gMzVHZBf3SmqbIu+SccS2wKP6RnDAp\n9nYB3w7UeoESXVYLZVvkNJzXB/wfiw446aWSFaD63a0EsEIWU+lKIGH7K2CE\nllMo0/X/DRinloA9/3NE8vMujkgwpJgjqOKAjIzXjcBdLO6wQ9egmXqwHbFW\nZO290QOLnlHTxtF+r2lm5BLZC27r5nZFj4+uhL9yP9bTCDJx9FEYd9MsIyM4\nFWLOT9J77QHVElgbFoMtTc5CXspzVnuPWwBszLsbk4ApRjEypp2OXdaxalXJ\naA5GlRv4xrwBQEVvp6IAus19/SEjPrup4kEtzWtIM0KZcWuwk08jHYZGyY2E\nVisGT1jdi6emEUPV337N9c21ZyQO3XurjESyEhDwHvKSDniqvbxFQCVhZ54E\nFGnMnsKkL4g3LVJ3xlAY9YrQ0bz+mvfqcwHSHizZ+y5WKfl/f4Mqag8NhrW4\nX3y0\r\n=dCb2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCPwYRGI2fxK6Sy1FViqkm2m2+FjejJfe2MZI3I21JxtgIgH8vpYbQHrSXKbZcVNB7Zj8tvLBCsH+ddQqs6tbrJTAU="}]}},"1.0.30001045":{"name":"caniuse-lite","version":"1.0.30001045","dist":{"integrity":"sha512-Y8o2Iz1KPcD6FjySbk1sPpvJqchgxk/iow0DABpGyzA1UeQAuxh63Xh0Enj5/BrsYbXtCN32JmR4ZxQTCQ6E6A==","shasum":"a770df9de36ad6ca0c34f90eaa797a2dbbb1b619","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001045.tgz","fileCount":792,"unpackedSize":1494145,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenpObCRA9TVsSAnZWagAA7rsP/R1k/RgFe262ESWAjK+C\nfwcP5hwFXHjecgKbYGVd6Onwyv4BkZPZi8fF8RX3RJpG+v6lPGaaRm3JNoRq\ndMXzRptiGccScT595V+AHj2gk0Ce9bYn+nG8lmutFDImCUoN47oTTSxOcKdF\nin/OuTXMkuKyXbIUqvLaHytaFA7n+AlqBcjpySfRkuf5SFPzj72/aCdLyJt0\nI/VvNd5zsbRb86xF99psR8Kk4NF6P6MlETD4txj6Oknct/uG1drNdPE2goIP\nKqMFjq25prl28nLKhKspPWLojVUPPaERGmBSW3k6nyqGGKvkhz925gH3t4GX\nuXqEcvd7nA4RlGPCV+MttDfyLE0oBTG5RXTebbIf8yqNzMsA8cMYVCeBxyja\n0SQ68Sojk/PSvZv1Vqhh2aRt8DVVNu8xwQi9XgbwI7C3VBomergGwCIbOi4s\n1haN/4Z9Gtvh6pxQCsbRwthfWgzh7e7hAqu5Gzem59STh9qcf5gx9Ky3u8FU\nsJZYGTpqUF1ULb0OdIOq7RSr3glO9eGc/cE5nZmrL5eSYs2Y37UuKF3nweZB\nKXc3ny10nk0EON2FR6DtZ8neZ3FQmCxTC54Zl8eAynCZ/C6ff/bW05vGDtUu\nVovu7bwLWgc9Q0oFjMRG8GV5P2egKsaFQrj0R2ppttweLsJmma3cOXVMR0zt\nlc/M\r\n=8Ppb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAOxvam6GaVlzAWz8CChlrUb2zzqSLcnSAX+t3hAsVA8AiAtRr610UIi2g/2HYSPKq4tlrxLfq2qIPY9tb49729/8Q=="}]}},"1.0.30001046":{"name":"caniuse-lite","version":"1.0.30001046","dist":{"integrity":"sha512-CsGjBRYWG6FvgbyGy+hBbaezpwiqIOLkxQPY4A4Ea49g1eNsnQuESB+n4QM0BKii1j80MyJ26Ir5ywTQkbRE4g==","shasum":"7a06d3e8fd8aa7f4d21c9a2e313f35f2d06b013e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001046.tgz","fileCount":792,"unpackedSize":1494239,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeoTaaCRA9TVsSAnZWagAAGt8QAIgmqaV6c27IlkyfqOZU\ncBj8s3Go7/qUgCRcR7Ta21+ca0Vvhs5dmwa1ZC19qgEem08x5jCftBki7mm+\nHp/CWk6QxpAwm3jEcZhXD3miK5Ezt5EAoVE+/6czKu5kepCKFekTaUzPAPXw\nVo+dDBP/EMdsHY1sVjEn4mEAPiOhrCl7iBjSV8YMMyMhmxpDxELWY3Y10X1s\n3xH2ACJeGtZw3/g2nlakPS34AbgOPF90nXVdGAaui9F6Mk7QsnJujYdqOcB5\nhKQaJH1NRUnb/3hvrISj1AHYBNZNs7+bcOJ7Au4NbZG4caACBBkhg4epdGOM\n+ueRQhSmVt8fFUwWACOI4M3wGcAXlHoGdrxdfHrRuoHQlpqkq0BLOsBUJ50k\nCO3QlnsqL4Laavl80OwNV3qU9TKnVx742KjPmtZVqcHTVY0acvRiJcwmUUUF\nxJfiNtuEr9J37Wdkz9LgDdYQ1ggdKdAzWU+oKDWabF5w0iW4+mxUB5oMJdFQ\ntK9dchWoGaKcjQrHAwB8bbFw2VqrCJTQVmV1//ibOQuUwZeEKKer4V9Ogf9V\ntj3U1h1mW+Afj1bV8D24yvU6VG/UW+ghjod6RQUy7rlYlQS2jRg598+1AGBC\nHymUNbXy2PGkMrBHm2raQPb/pRXa+xhX6nuuWo1DJxLdIGoaolCFmbe72upx\nXfNk\r\n=7/Tp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEbhvzlzux6IVI/pmIKVA1wD1Bd91IGqtEx1rYeuBTMVAiA3ljRMjdclsNuW0denrUHWTiCOuI3ErWICg6xCh5nzRA=="}]}},"1.0.30001047":{"name":"caniuse-lite","version":"1.0.30001047","dist":{"integrity":"sha512-eaZFO+zPTGCCi5EBK0Ri8f2qXJ1lLH0Ic/UM2wrfc0bQkSiwGEk75tZEu2Gns7uvTMKcADLh0+QdTjzcRt3owA==","shasum":"db5d6649d5ef4a41ad3499bdd29edb22703c2a5e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001047.tgz","fileCount":793,"unpackedSize":1495358,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepGY7CRA9TVsSAnZWagAAIscP/iR/j6hP8QYYVXsavN8s\nNblRDQN/cRegYXocd6ax2yd2HtOjD+gnI4JXSjCIOV9ercgJM1jiQomz7cXk\nayAsFpDX/hJmyortgZc62a2Oag+tUNFzCtRxICx+LlhED30o4QwBIBtKANdi\n66hFNdWT6qhNaITP30ZyJu3SYCth/HGJWYBgdtA6F+Tp0WW0UnnuFZYUWhmc\nz5M3nprwhgEUBuSaUvzEy347vPrz4oDvvMX4LmZMxbrhEmWZvlZCexfup0Of\ncfHgqRibprJv4CeqV+jMeh+h7Q6ZQorz57eOhUZaXrk52ge6IGb3Izx0MaJ8\n46/niu7zwrt4xam0ixSFZbS1GaIBjb0R/EJ7coJRvjIN6fNyVZ7ZcprWa+F5\nL0TvCB/U0bnnrpL4sx6K76OqP1ntLZB9OIzcFoBIcZo3lCrp9RY6LA0Lpif8\n/O5p6ZghDEsSte7eKe8H6iqMqQmjh6PvKELcaj8plWFOUvCP+NxGDpStTB4L\nw8kbyKeoRlB8YDSK6pLeCr2Tw9zpsvvEhotjQAqAEEB/QBD+uMLk2gsyD8LZ\n7b4J6jEiUmhCxV9xnQxIo7fyZ7eacDTm0nlZtGfMrqRZSD/7mTaeKyCWt7x1\nwGRVL3hcGdbhYatPz6naQIpeBPSd9zn7Q6fzK34s07Flum1ttk8RPvodLqOB\n/dMr\r\n=cE5l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAEx2LIpL796m3rTxq8iiRWmrH5Cll7zLlbztve8WQ+6AiAcg7VAkFlaXFramXpPJ3XhkXXYhIRd5hMrS9P0NZlEEA=="}]}},"1.0.30001048":{"name":"caniuse-lite","version":"1.0.30001048","dist":{"integrity":"sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg==","shasum":"4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001048.tgz","fileCount":793,"unpackedSize":1498135,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepHRQCRA9TVsSAnZWagAANekQAJtdi5NO6lKP5m5/Yc84\nX86cZNT7HR6uaInWpVt8+ynoAguj8UChPrOOSwfQfNOhb4CsS7FWrpCOosR4\n75p2BPtcZ7CAaPXVqS5O8UdeUdNXYn67ElSGMjC7DT8PifGoWpKN55nNJKIS\nKJgK6d8fv9GfteZFuf+7+7g2IizyAD+GM10urZ5EBn6haobaTgfrb5QJEwsh\n7ufksUmJ+Yz5VjRDEV2tFeUTTQDYizYMpbWj7Hgv/BWsq5ofOlM4gSgCb1+J\npckVJhPDXSatJ2huJSBv1tuiOPXABVmtjVahFZSl1oHC9mhc7EvXSqw3N8Oo\nHZOJFoqmAQmZglrIgB7hk4j/ETQ67l8GNuJX5sxH+OFReA5u+rSfNenFpIbF\nwzWP2S/+uk6+WvVRYTxScVEP5cyaJFW6E2j5S9h4TsT3Hl2S4bge8o2QiFvk\nWVYW2c+b9YMQF/xTcG3yViDJdI9o4Hh2jzOFfh3kropg+TBPXkynvXKeb4Ot\n61voexfUP/4gUKS3Z+JAZoVoEbA7Mb2Jkw4uxamxj/eXPiE/zR8ILUJE3zAG\nDghdBWaB0qpQ2FaxnhGAVpuSiIBylfW3N088Eank57A9RzfnkRm6eJlg3zAH\n2tPvqK/1x5wmdL2YxQGghsMkqoj/eM/PcWGV3FRxhB3QNUNAP3x77ksV4z62\nVHKs\r\n=6BGG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHySqSIXel1LUjWUBRvU/zrHQqG7Qgtk3lk/xq0OYo51AiB03XElqVKfEz6+qmQ3dGqWbUQXm5N2AG6pU9UJGvWwHg=="}]}},"1.0.30001049":{"name":"caniuse-lite","version":"1.0.30001049","dist":{"integrity":"sha512-VBcWTkexrbyurOakYo1E7tmzB39jFLB1Tav7e9JQGIz5MCfv0FBj8qZz8XRJgJzo+xn5YGeOYb8Vt6JxR2xXQg==","shasum":"97d560015d2bdd7102b82ec807ec28d8aa7bd73e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001049.tgz","fileCount":793,"unpackedSize":1498227,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJer4zpCRA9TVsSAnZWagAAK38P/03UmL1sIhBRTbF1iXg6\nnh5EV5db5QjQmZohZnZU0DN29kt0k19n4Pl6GmNv31hzBqERsA/EjpzpF5YE\nyOE0TLYyZnffLFy7bCTq9kvJCU74YYSi5OcfDj0s5lCvR9Z0T8irrj72ebEh\nyLz0GkXHcbcRp5E1VKY2UuUtChQLlJkqMRGh59guwyKH6Y2MGcLA1+e+QdG9\nOZevfcn/6Lrh+DrBRQNGG/tqpQc4uBbY+7Kwxd5zzf5YZfv+9V5BltGU0KeD\nYooKZcNrSXwbp1WxyJ9YQEgYq9EO+rddfO9wCM82Nm1H+noG1trJHMJk/AiE\n3X5cr0di+7zsc1MAo+BqbcvUm4jAGUaL90JQqP5zG0K4iULqz5a9zyKg8TSC\n9smxlU9XO2hzC2VHagzP1U57U2rMSEmsGyIFf49ntv0wVjb43Pbgr+36Des2\nnc0H/gzsnadvlPti4VSkFIyW8TnpMeQ/dVlzmMpsi/mvYKYP+FxQamBjX8LH\nYyCa5GZI/nBwHI04u9HNvCw3pdERYe0hmwJbk1IY5b9PB4ZI+CDXuP80D+tJ\no7C6ftC4OgK36E72fND5YQ0P/BMkIE0f0w2JDOKC3Hw1Qr0NEbyD3ptFzGBE\nFkI3uwkgWmuXevzXh15chDx/2ie61OlRuJFx85KK54sOPM70AQKAE6Q59kPT\nClHj\r\n=xgFO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCssiG+Ae7poEvvT5WrpAPOZ2B+SF4r2mv4V0gscxgasgIgUStKDawzLrrMnUE/mTnChJWGfcnIiCI1GMtIY91NWV8="}]}},"1.0.30001050":{"name":"caniuse-lite","version":"1.0.30001050","dist":{"integrity":"sha512-OvGZqalCwmapci76ISq5q4kuAskb1ebqF3FEQBv1LE1kWht0pojlDDqzFlmk5jgYkuZN7MNZ1n+ULwe/7MaDNQ==","shasum":"11218af4b6b85dc1089536f31e10e3181e849e71","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001050.tgz","fileCount":793,"unpackedSize":1498288,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJer5r1CRA9TVsSAnZWagAA93QP/3pwEbBc2gKk7OmtCpUk\nCXj7fDyXGcDzV4rZi1tHDz5VrUcHz4GGbqzs6hNC/RcaI7WO1sHlCYyafiiZ\nmzhuxK5hghYsMAIA1Zc+ipoO3J7Cgd4zRAkwypIG7xuZfT2//L07R5Ad6weo\n70jUZZJTtAlnOH6RN8mWsqm7KFXfhWVEshGFh2BfzgPXiu2DudZaF7o/NNif\nfa3eb1CfLm8eDpfu2Oniwl6b5Ow/Si1KtXhxGR1P+SVHQRUGo4ufWC+vNBK/\nB2FEsQNsMdeKvdbuZO7a3R6N48p/fbhjrqlM1/kaxnnUHiMkK8ZouI/xeKdP\nnHfKiKO4uNE3TvciCRbn0R3L2upPq5udxWhE25HKmYU1PgZx5U8n0p6+bY4Z\nmXwBzRTXdhMExqjoHhpGST1f4uKHDYZ+QEjDJZveWJip7Hz+FO8nBx5DKTya\nUXIptyEMMQIyi3ut+yqq38xDzxqQjolitcYW5uSkzxmIbnQCkSTde36EdL3c\njcaQKVjQQhSqGlcrap4UJ3SWCDOSRyU7J8Cv88NlpkTgGpxRHJwvEGms3v28\nAlZ63weyA2cviW4UnFgX/Gp9WYgqzoUjc4dBb82H24sSeJG5+VxHY2KxCyWI\nGPeHFEDf453O/8bis4OaLF+IXQNnxGWjF260G9fyX4xUW/w2j/V8BbaHOKYk\nExVu\r\n=4EEc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuoo9yPN04Or6SK+5Ztq4bgH9ap92ujXXTUb78lHgavwIgXcQGzCGGK/kZsmhW63Oks8ae2lMNxvicj6VpmNGkJQs="}]}},"1.0.30001051":{"name":"caniuse-lite","version":"1.0.30001051","dist":{"integrity":"sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw==","shasum":"8e944abf9c796bc7ea0bec3c3688a250561fc9ac","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001051.tgz","fileCount":793,"unpackedSize":1498365,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesOx3CRA9TVsSAnZWagAAcZ4P/j5xpW7ZL0A++fA4aVHK\nIxy2fs3nGQG1Hbn8RrStleuoFygkbFzOdBaE5VPp5i/KYGUV69xDi1rYqJSF\nikOVdptIUIVzUkCnlLTGX7gSrujtwujzw2cLI9+TloWpOUDoawoTAdLBljWC\niJ1dlUMpiB2rnHJelPMJTbZC4RLDVf4I2NVu1pXJGa2HIm9jv6b16XFXXlgi\nYdvMiQ7w9YcSDTwTMnjWzPToj1LCDEO8/85/BS0j53rHqp4Q5qELEMUWOWMW\ncETsupcRmylD3nfFXDTy4SnCTQqKHeOM5O4tyD5ILy/Nb4dd6pKqK04+spnR\nsz49NhAiZYUHbo8GVRMJPwbwpp8Tixzbn5hdLiX+ew1IreuPowoFJwQbcs6U\njKaUaUGIts6v6iZ+rZmst/cLS9CW1V7f2NmqD/6kNFHg3qp57AFlmi6VascI\nGQzWiR/8ZMXoRZ2kEWqWTOH8zMFv/p8Ht6DtrKHh/ULxLgmLjxykG1ftlyWc\n8cQHx+4Vnn6C/mntelGr8suNsEHbr5KT3ptUXntPs1Xh3c2WliUJAm+u/zZr\n0KF7kFZZVQZ//3H7GmMCQSfoGRDAiII1VwWIplN10i/z2cG1f68JRh2we2Pc\nQN/tCE3sQOPaSLBew5Hs3fF9ty/bwgDgX6rjdKUbdd/4zSwbjmQ0w09LiftT\nYQX8\r\n=2MWh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDu2N6kLKP9qZOnveEfODQdnnJ7VgxGnV1u+0L8xlVC/AiEAzf5R5ifALJiUbtADEsM8X3U/hWr+3IYISDZD46j8LRU="}]}},"1.0.30001052":{"name":"caniuse-lite","version":"1.0.30001052","dist":{"integrity":"sha512-b2/oWZwkpWzEB1+Azr2Z4FcpdDkH+9R4dn+bkwk/6eH9mRSrnZjhA6v32+zsV+TSqC0pp2Rxush2yUVTJ0dJTQ==","shasum":"33a5ddd13783cfe2c8a6a846ab983387d4edff75","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001052.tgz","fileCount":793,"unpackedSize":1498441,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesgW3CRA9TVsSAnZWagAACTwP/RbfcNyrUHFhqnbhgqGZ\nEaku4rUe2I48QBimfBwcWphxMpSeG36EoreB9j49H9K1vb2iwz5o0Jtww3UR\nCN4a2epymRo1zlrrdwexw85qwfR/7D2EAOCwkm82LYGCmqMCTE30oBNOrLK+\neVv2ZNsvUB2mZRFwAWfKUZs7ViyFkqSdIdzJ1dXPy6gR5qJ+y1xlPLUZPZCx\ndIalzP7ITA2Hy3NoZn1he238C+P37ZMkr5jIy+F3KWF663S2HLCfzrEaq2kZ\n9uRr7Y86Sxwv+pQxkFNPxWxHp7zZ1RfF0FDZYecaW21njFryYeof0ORcpLZ2\nHU0k4subW8/mJswbMljOShEnHrxb1SOLPWl13nXQULgh9GQZ7WDWyfm9kUPG\nseg/zWGp/CcL3GNK36bRB9/WzBHcX0rzyh/orY3GrwwF81eAZjph42AhxSee\nocGI9OWGrPNwC+m1fO+Eefq51AexCtseL4nxJspHqmE4BH7JfbqTGizKpJMv\nE3e8kd+ATSvNLOYev+Hw6Xr2LWSNg3FT+55lbZec+z1tJ3ylGmSHGAUlo1TI\nV1ju4atEg2ew/0T7iD1ZAke3G+XVLli7O8yMo6annwQS8ChJa21Qbjxh8nl1\nmMNerpn7F+Ch7LO4u0zedNicOONXvqHEddRsLTtJVYABwYKy5AMQUIyBbVPN\npJUt\r\n=74zc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDd6U3RdoqOmkByIHLevx1egWfe7XdehLdI8SkWNV+lSAIhAK1K1MvZnaBJz0gQ9miCBq/2S73Xn0kc9EIimK3tjrMU"}]}},"1.0.30001053":{"name":"caniuse-lite","version":"1.0.30001053","dist":{"integrity":"sha512-HtV4wwIZl6GA4Oznse8aR274XUOYGZnQLcf/P8vHgmlfqSNelwD+id8CyHOceqLqt9yfKmo7DUZTh1EuS9pukg==","shasum":"b7ae027567ce2665b965b0437e4512b296ccd20d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001053.tgz","fileCount":793,"unpackedSize":1500120,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJes4+ACRA9TVsSAnZWagAAr5EP/0+v6TSKrqXQdR31jaE0\nfpljzw2yzwMK4+lrSW5NkWTGWEYAM24NMVT0+giIquE9aeM/eaTBJO5PoTXD\nrJj/Qhy/S5hwJDXWRL+eU0k4HkjI+4XchZxzlKcar0Ip0riDlAKnogMJYtHT\nE6pwyWf+t45ruEvrqtJuOozG1BVAjUbE9Zyv+Pxcf08eD71ZfJctPZjplW1b\nOr/5fNp+Ne7TQ9YX7y7uIElH403Y0ywJXPAfkKJc2bmjZvo/Q74Im089SgRm\ny2PhT07KG6odzu+TBItwaoygXSvM6viI+RiKxjttdX7LUSvU3bSmftebTgUF\naelwxovNjf1fX+gayg+LEW4wS+sriE9me0bcQVofX1ddHAoPmJY+TiWuv07I\nnjFDfRonu2inYNNCPbS26LdA9XT1pUsJ3Z7A//6w2JHrMmGqIsOyvy3ojjGe\nbWgroISselKTs0Kxv+seqbaEiZcN8RuUFO1+Dra11s2rqffW/sth0zyM5dEb\njSa2y3m9DTvTyXiLxxztvYLxQSBF1B5k4YxWcnfWsLmakFYKTSags8/4KlOr\nsK5w/k3kpFRI0NKx0CAxL6YIjyX6NzVpYcOY9L8f7eBfuQyiMxSDWR7d8Knj\nNW1UALUIteygFuzTJ6AMM+9egxVjaAn3GPZEh2v49NyeEpoLWuTdt8zf59vH\ndtP3\r\n=n7S5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBtetzVMYRUKW1BnW/wvay9wgi31bv5It6aBEQd6546wAiEA0uomNtGvz54Fe6Lux5ph5j38T+r4PSWI/1DvdUVhmco="}]}},"1.0.30001054":{"name":"caniuse-lite","version":"1.0.30001054","dist":{"integrity":"sha512-jiKlTI6Ur8Kjfj8z0muGrV6FscpRvefcQVPSuMuXnvRCfExU7zlVLNjmOz1TnurWgUrAY7MMmjyy+uTgIl1XHw==","shasum":"7e82fc42d927980b0ce1426c4813df12381e1a75","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001054.tgz","fileCount":793,"unpackedSize":1399746,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetNLvCRA9TVsSAnZWagAAWZUP/1lcmMjUYPPsMvIM0mFc\net0fly81IWR7IK/ruHw3OkYaWFjH0dPL9jZ3jvzsMEu1dmSFlRvZLXh4KtG1\n9qKDJOHES2VhKJiMbAuyeI1QxHZbZpX5FpOrjzV8+515/A+yUCbaQm28pkuE\newFjS15Sx856ifJIK50iJxDjo8qcXX++snteGbYH+tRlnx0MxaQNOiEhqNgq\nbTcxub/rJOIjsHDnKCzCfyDqvkSD8gJqGDYndcHYgCo/CwjcfbDCmz9CA7A3\nHCL8tuXedZLM7p6LCfEhzAy+deErQRkDblIODgJHz6KXj0obgqQKRZj+JNKw\nkKOYHbj4d8DbZFM6PL6NfRVQQJojWgVieSHl8USN1+9mZrmY4mdJht+HMsls\nNJRLXTdP7l75rOQywybIygxFFWnjxwCVBIynHOHRJZJOOF3JVZ8dw3JAMq48\nbb97FA7I06HpBOJKUi6nD+oqTzt0WIB51uY6I4IgjnJHUJdVHNIyW26KOa+5\nUanrgjpKDAkH/DiukiDBalT0pyM70n33IAv+XMXMDTfKaEzL2YQSp19KbUTu\nbr434ThG/nmBB6chIiOAW0YOlDjZBXeKUSyTfjYtxYQzh7S+EXdT3MAEgMAQ\n4OQLPp3hE+8Q23HBP58jApQbaSdQTZMIgNLONYAFBlZk28vF4zJ5ie2nOa6V\n8Qey\r\n=zRvH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEr96UhexAFPs1//sdEPWWZ56xEAxU+urXbR1dp9VYZ7AiEAvlbrfmdxZgaAU9iXQFhyBWVuwuRu9CL+cwf0WmPv8+M="}]}},"1.0.30001055":{"name":"caniuse-lite","version":"1.0.30001055","dist":{"integrity":"sha512-MbwsBmKrBSKIWldfdIagO5OJWZclpJtS4h0Jrk/4HFrXJxTdVdH23Fd+xCiHriVGvYcWyW8mR/CPsYajlH8Iuw==","shasum":"7b52c3537f7a8c0408aca867e83d2b04268b54cd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001055.tgz","fileCount":794,"unpackedSize":1400870,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeuJ05CRA9TVsSAnZWagAA3KMP/R/lV1G4ryw3t6UvU6ny\nI7UPvltAFMFllBfk1/Hn5YJlnEgt/9IY6diLXsNZcY0qDhEnY36jC503SeYb\nSqQW2pyY/JA6hD0QncHJZDt9N0ZWTrEKo/a+7jIo/Tm/bgCaaQ48ctLOinK5\nGMSUuJA7jdpBWlouhfBrR2w6kSWf2o11nDKsN52JY7attrWGnQIqnmYIT84M\nftbgD9IKvrNNAQWtf/nWtaENgZEEm+dD1Ysag41C7UiqI3Eaj5Q8kwEjcfk9\n4nZR3Vk8Bj+6NTCD3WTO5cmdS8533O6enmMY71iKHjBN9y+14Rk0WQTAUJd+\nB5jOSG1chqxBJu12IGrjpV0E8n1MCWt9sj/JyKstEBWPw5/CCUEtR8pOKQm7\n9q2eBl0jplUSIhNw1zHwjEw68Srw/iUl92anySsxjGxIe1Um23UmonMVAZdD\n5cpWcj/fIwJ2De7Dn14LQoeyNed7Qdl6FrSMOcNwp0Cl3FMFn8ISP3oiGl3H\n9GbD7pbwl+IuclAIbytAKKw9PcgmvsMuCjr7SHJV3m5RtNoGC1MnH5dB+JwP\nr+9+d6p/49szmAPPx9giuuvr1ytN+tqbXHXkUItCzZI/L1G8bt8TL9znYKsA\nSlZraLhVKo0yR0kYVrZ1WANjHRQl0xw1gSNEWeBkplJmhDI51fmmMH82MZ32\nKwSh\r\n=EEHY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE4q0nfj+S9qyqh9/Z8Swi4sQh2tOMSPZwhHLgdqcdBuAiAn9sPumDeXuRiCfkxvOUiRc1PzpdjfpUgCENm0YefuEw=="}]}},"1.0.30001057":{"name":"caniuse-lite","version":"1.0.30001057","dist":{"integrity":"sha512-bRXZJZrsIaaDjDYwOd3KGmDMT/MmqMhxDef7RVlfsJtSmF8eKZRvOZRY45M4O0Zi4+HXalYMY8W5miKBHXzlrg==","shasum":"d1052b77ef13304c85e610c23954c240f155b317","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001057.tgz","fileCount":794,"unpackedSize":1400942,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevJ/GCRA9TVsSAnZWagAA4rEP/3coz2fvu+GO+dzyAUKq\n7HIsDurCCy7ZX/x8AJidAxRnZinUupYCOzUP89C97YPhrXijR/qhbonRQTbt\n9/321RG/Oj08Kd7mlTYhFzBUtVLOreO/m/LRNcfq/oq2h7foYIaaEYuzQtJM\n8GiI2+q6qcAsBn8ofaGNjPqo7FMcC6ixrhT2VYdrKLTiO75ZE1+9UD+NW4LM\nvXzrmQC451AN3nO8RvRvUuf9F4CBmg6md1z/VMAJFi/mnyvi3g65OQ0j52oa\nziL/ZpO3IbAm8orqH93J7EGLOAuvfvwA6syVSYO1VE7MS5+IDShjwfuBPeSY\n+CWMmzGC0IXjxFWZ6AefPineJCNT6kz/emAeKVs+uBrDODyUUmw4u3ACLaAI\njFYW9pwS6kgF6m0a5dxTaaH33xdebbW0Zq8cLd+HUHtMxgmKClrJXAYZY3a3\nPWGqyUlVUjtfooJ+4n7N6S8VVwPhoTSUjhZFKJ13MSMtxj0alXgT8YjlErlq\nxbGKCcK6GeqUmUeQYZuzpUZXs0QdODvjEVyeOQIRkKSrEmFctKz1ip3EozPq\nfULk4duSaUQr+yDs/9xRl4/tRyrs96JKLzndF8MeCWUigP26vnvOkHaZiR1l\n4aSlaAToxo9WPIj3KHZzRWhi5s9WGLBKRUZUHt56++9BI2FFMAd0tBZz1F+C\ntydQ\r\n=HeM0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDj/3zKUvG5PtGRADYhEtqky6/qlx5mk94u5DZrApi65wIgOBHPWornOFD1Lu9qXPIgozjEuojJUSx+BXPKdc72rVc="}]}},"1.0.30001058":{"name":"caniuse-lite","version":"1.0.30001058","dist":{"integrity":"sha512-UiRZmBYd1HdVVdFKy7PuLVx9e2NS7SMyx7QpWvFjiklYrLJKpLd19cRnRNqlw4zYa7vVejS3c8JUVobX241zHQ==","shasum":"9f8a318389e28f060272274ac93a661d17f8bf0d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001058.tgz","fileCount":794,"unpackedSize":1401004,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevK3UCRA9TVsSAnZWagAADKMQAIkyLPNthzw5cYwoUnOj\ns6ZjNMHjfHK3VI/m/kP0XQxIEjNc7WJAikEp49/LkS2Pm8/+m5Xqdml06+S/\nOrzbtFQKLkZMNZeOWwSCf0fJOGtJOfsTnBMrqpYT6jqc7IQ3oYBK++CCctRe\nzpfrj0gFTvRbnzCyXdeFB2zlNQ2gn80ihzCvsnrWswvdhgrz8t/3XkNtzRvk\nUzIj6Vwnz7Eg/Ca5To00seqleKE7blaAdB1n1uePNA5XjtYUsOobAiAjZ9AK\nfY09FjTnQgkeNi1wiR2dZX/NlmSLyBoKpLC38cWYcbA/+Kdl16Xu8o51si2e\nzQIJzdmsuY2w8JUthetXs+P874Qcs8xW9NeLMmaqudlNrOklxvVIoaeO1Bdk\n8wxbNW0t1zF+3PmddWWre3TASQXqVEKq2//KuIjN+iBF7JyXl0YY57hOsFiL\ntAAuphfzXbKSnrPfHVPjrP2qVQmxJ35YnECZtjkRpPsLOKZatghfVJ+Vm4Mr\ns5xD5/zlnN3KYMEaboAb1IG1FwrSISj4j485IBbeA6O97AoCdK+bUkPG8/S0\nIBvjNRslq5BOqAbNM/fMu1ymXlNnot4G9gU1AC2mmgT5ofIJgZKyRDDq4QQa\nTqAZWrDNNUxSgcU/hadpBVl5USBHfLOJ8WylJZAe3IgRyyX9/7ukPehQEPXj\nMR0r\r\n=mGeY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkxWOViIeJZTJZzCrA9/iphp/TMvEcJZ8MUMfuk9L9mwIhAOnIhG4LVnE6tMWVCKSNrGX/D547zqDbKd1Xb1VfYftp"}]}},"1.0.30001059":{"name":"caniuse-lite","version":"1.0.30001059","dist":{"integrity":"sha512-oOrc+jPJWooKIA0IrNZ5sYlsXc7NP7KLhNWrSGEJhnfSzDvDJ0zd3i6HXsslExY9bbu+x0FQ5C61LcqmPt7bOQ==","shasum":"7bff0613d94b6ea41cb5c864c966d340f8ae6d34","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001059.tgz","fileCount":794,"unpackedSize":1401066,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevf9VCRA9TVsSAnZWagAAhWAQAJWsDOqJ9jJwNfAC0Op9\n8/9I3npT0q/kgP3JMjLDocFp2Gh/OFPKGCj1E9liqOw0ioqtBdBSuzyGEMy4\nb28otrmshxkjwBgF7DRMfnvPniLhqF9pPAz0UCFHcXguXUZef0SRbEzNVUD9\ne9BQl56Rvw1MHjUXbcWFcuTv81rsOfqniNtSgYAGypnPyQLJa15yGxGGEZ9i\nHmp7hOv8hKSrkNe30hmosIW+dSlKjsRKrEBjjX91vxxHjptdzBv8SruTFft1\npN8rvn+d644p8bph7jLUcx7bBrrdJxonksw4UXcFeGQ9OxO0SCc8UPm3cp57\n0aRhOm01Br0GaEuluMEyOJ5zC0pAEGtsF0EEZNh4H+WnK/46N2fKF3OYyBae\n9BT3P2CqNxWy2eVlBCYscNdYxoj0XnhzJCI4AC9IfrxctAD9hG25a/Aeq39/\nyTR4ddL3JypK3Q+ApaY54dT1uaaEchDz12NG5Na46Xjz7q+jugdV8UlEncMG\nZ5xNTMCATUh0xVU4ym/VCMOddlFTDHOOUH328K0j6S0pni8XNyS+8Yg6sTcu\nL7eUmLmX2jrL7lutFhB0SSIRb0yTArL4pzg0pwcyuCs/D5KBIqw17fNRQySa\nwnlIFekNlKk3pHpjoMIjCbzkqkcJ2B5yWqqa/MGfD9XkVw8PuAwkRkfUH20P\nv/Iw\r\n=i04u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbU93bMacKHvbho/ULdZk2V2NdThB9RSLPmCacF8PShAIhAKR6XaoQlKG2IkLAykfHqtOqpiov3nIcB+nRZ89Ukjrg"}]}},"1.0.30001061":{"name":"caniuse-lite","version":"1.0.30001061","dist":{"integrity":"sha512-SMICCeiNvMZnyXpuoO+ot7FHpMVPlrsR+HmfByj6nY4xYDHXLqMTbgH7ecEkDNXWkH1vaip+ZS0D7VTXwM1KYQ==","shasum":"80ca87ef14eb543a7458e7fd2b5e2face3458c9f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001061.tgz","fileCount":794,"unpackedSize":1401140,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJev2z4CRA9TVsSAnZWagAAUxUP+weIfD5nCOeu9cekIdpT\nH0TujHnBxFP6+6i1uKU1QeZgbzhjLyo1oALnuOq4bKDvHHvgyGebdLEsOqjX\njrZaf2vj9mnxOR4M2QeeMSTLo5hxG6hplwi6g5tkVIIE/VvXlvH3Qz6pn9mm\nC9/omo6nqU65vdkDLJ/2GfLyLJehm5C4UPlje/M539OWeUydOymhSte8ZzmC\nSQ25uTFhsBxPTqGux8J4it2NUHGo2nObTol1SR5rd8tnnJGOAcFapW4h5RnI\n6mmtl5+vezv6DDz45DuUO/Sv92bddtilf5k8W87ofW7slTg0FK7XDhMLyOb2\nNsi1UIRJVNZQI6kkrCxfkPPLzl0uPBvplOxARiIZ47cBGsD80X8tIv55mfx0\nCJJX8BiLwc1K/BZ5P46ZuqBKBNKJgYkgrYDkTKWuObl5xleF+kbBacsdbqR2\nsHmAG0OWx2+XQ4viTWiR2Gqzi9fDWnlMApz2K+FwmZW0TI/GlEgtXEDcVxav\nyRQr/dV+VNPdPtHtpy5HRX4646VkFcDek0+McGM1fucM/XBG+t6Ap7EVEPBH\nJIg4mTfmE8IjlNHi9Q4fR4wquNvyp+xklgnzCLwj7tXoARvRSJ9nQhSkt7CB\n4lsnj4xoDcFIbjDIM6WRE45OgTFTCYLjTJP007gB8SIgpBI8S22oKzhKDL9A\nj6qV\r\n=X3lc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnnvAlUObw/WVgFKAcL81RTVoEEKKoIy4i4FsbgUVefQIhAOelAo12CnKRLv3jtb5zMXKNukndYJlQEvqJg2E14Hb8"}]}},"1.0.30001062":{"name":"caniuse-lite","version":"1.0.30001062","dist":{"integrity":"sha512-ei9ZqeOnN7edDrb24QfJ0OZicpEbsWxv7WusOiQGz/f2SfvBgHHbOEwBJ8HKGVSyx8Z6ndPjxzR6m0NQq+0bfw==","shasum":"d814b648338504b315222ace6f1a533d9a55e390","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001062.tgz","fileCount":794,"unpackedSize":1401200,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJew32YCRA9TVsSAnZWagAArooP/2xEqc3ri/aiF4yND+9E\nnLz/XvbfmSXN1Oz1d95VFc0MDw3kv7Ee1MjXYsN0WUqYAg6+PChqhw9LH5+q\nVxufyu7Ojid7+p2WJSA2NRcv4xfxjze/1kWni7CZtQOPq/KkH2itzhk98zW1\n2sLmCmQgziXGcfj5cjvL0vdulzs7pdzNXDoK23PYkMretb+QycBiQ48JpOyf\nTA2n8ZyqMBPj9+BZOL19Upe4eznuSUkyYr86dxZ3yrfR5TLFUmOBbalYspmU\n921S5eHnTGzrb0WsHSyKJEeExvEecbT/N1vCSr4eTGD2Q0J3bkG9QrFWCe4U\nfw3fsjEJOayjO5YFH/7FBR6kXadxOQRZzdP+MvdaOoX4sIUsy62mu/TB4CRx\nDXPBGLSpHjwzRrB+Elwa3F7kQWNooM5wMibzls5vNr/sEOua0TA5SNCdXpxw\nBF8bKlYFWjHiYIryLZuvecYs5vwCQrb749s0GNSoSD8N8fKCjbYwfXRoR3iI\nmQEgQl8BvKybrWf6Za50XgGpCPOatsYwIskTqeiaphSiLMDPvEds1SQbnw4m\noQ82Ao0H78DjO8uaKwXewAf5PwamnmjQAId0+Al5mKoWOwgwl0UXJ6qb1rDS\nGncvL+PBiNLuNVKp7+JRQMYX0/mDX192Elp5XuzeH/ZM5hgBVJifwmH9ocbE\nkUCx\r\n=Ulhh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGrijivcPx9P4hykiiQlvRpavswNoFMzkxVvOWJbqYlOAiBL4odbf8MCSozyRXdC3OM/7UlNC+aRyr2Db5Dn3x8kJg=="}]}},"1.0.30001064":{"name":"caniuse-lite","version":"1.0.30001064","dist":{"integrity":"sha512-hdBcQMFvJIrOhkpAZiRXz04Cmetwc9NekeuNl0qZfHOugxOhJKxsjF1RmISMPFjIF4PPx1reliIzbfN42EiQ5A==","shasum":"a0f49689119ba08943b09968e118faf3f645add0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001064.tgz","fileCount":794,"unpackedSize":1401348,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeyLWLCRA9TVsSAnZWagAAAmYQAJMlGBcwQ8Ea2cKkTCXu\nBrz+RRWBUMzBgjHNtl41BNUWgDRX9RISL11ppLxDQWHzzPIsoAUeO/ZHRxsV\n+W7MUxRUuV3JaBAH30La3cP8ZJSyzBet213MNaqOCRA/ivsjkF6FuE0bPzZv\nO5ZVzmCpnNTMisi4eMbQ1t744POPbR+DhA0A7rhuFhndVijAH1ZoosgFUg1E\n5kIA4RTAiJHF1fydH4KBUbUJmhLSml/P8IbdwZAwfEHPite6TgVuzTuQqrk8\nqfChWQXmbcshKIHmx9/4hbY/RdzBBnEBDASe2s2JNEnBwMRAPD2zIkuEvI8w\nH0w2iCVX3iQpqggtLjfmVodMsR3i1dmOY1HLE3numYKx6QzCPqXp2D88fC1e\nde79Gq5uBRxgBRXs99+mwc0fhg7vgQEQz/xueh2EuH1LB4PSdNPqND/AidjK\nQGKxlDU98Q9kpSjf9Vaz02x9vu/AvQrcwCQHgwVwhUzPuQHuzcEC9BEZ6Djl\nHadghXfkjlbRGMF0owTbK9oDR35Su5dlm+M2YkY3su4hnS54wR4W2odOeRv+\nl9NEDFq1x2mA4EAWUIAbguIX/LLY7+3o/tB/Ushjk2jumapjD/iJSBuiYPjL\nfe/NpqrWOZnJnd6MTwiwiOw5VS6GW4df8CLkPQFBuzmqOAGEvCvuEDm/geV6\n55oJ\r\n=kJeX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFLG8jQGXzcrVzy1CAxRb/B4JNuuLxfU0jV3V7shBTIFAiBLK4NuUxpO9PsLpV1xEnp0a76qA4aLUSi4OnwzT50asw=="}]}},"1.0.30001065":{"name":"caniuse-lite","version":"1.0.30001065","dist":{"integrity":"sha512-DDxCLgJ266YnAHQv0jS1wdOaihRFF52Zgmlag39sQJVy2H46oROpJp4hITstqhdB8qnHSrKNoAEkQA9L/oYF9A==","shasum":"e8d7fef61cdfd8a7107493ad6bf551a4eb59c68f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001065.tgz","fileCount":794,"unpackedSize":1401408,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeywQpCRA9TVsSAnZWagAAfl8P/jUZXD3pj1I7oXXlZE8u\n5OzNpV06lCZbIOnXyO3KAku6QgguSseXIHEWBWyUA1kaD0ujTP2CFxTb1HVs\n3XDvO2x40d0jI3dvza58Wdger5MWw6ciTcZKrH8VMdrwT0OUendKbQZu2XPu\ngeI+E50Pi0hYTGXFg3+89fR1ECApLiTDzkfUpIobUJy/a60DD6nVtrIZRS4W\nB3r3GgS31kYM4vtAMeSpGORiEKX73AbdY1EUIKNj+xBNBz9Ea+aPntYE9E9C\n7/5gtItdkiwXpgFOVqb/Wj3PWU8BVbVgMdmpCuwsdR8UU+AqsZZ+8aOuagIf\nU1UPNQl6ON7PBvs0j2q4GOxIqaaakk59ewqqvzajB7YoTWay847wEqtQ/sHa\ntzaX/bySRLwXyGl19Gp77WXtl/MfpqDu2m8IKt98c+zILJgd+79jnheLx+Eq\nn0MNeFcHbT6Smm1eXq9c1XDUI7pHMh/+eCpyDAWj3hs+GaS5B3WV80PA72Lw\nQN9gJWpEgx3hUrcBQd/wyv1hDEF5R4Lyj1J5ZC3vMLV7TRRDsNCJLMTj4Cmx\neiniZUqYt8M/3vYF3dUWvujabwb1dMojNcHYCMx7zp0/8/ukhbPGEsVsPC6+\nRoLoORU90sABRsBFEKHGt67CAD4LcbdNJbylMBnEi1kANqtxyXGXCC1plzmY\nsegm\r\n=HeJ4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHF7hBFD3cwHykqA8OaydnGDbrIA9IyfO9t0eQe5V+ohAiEA398AXLYITZr6vv8WmyMX0WfTGwTrFLGbVpsAf6csuvo="}]}},"1.0.30001066":{"name":"caniuse-lite","version":"1.0.30001066","dist":{"integrity":"sha512-Gfj/WAastBtfxLws0RCh2sDbTK/8rJuSeZMecrSkNGYxPcv7EzblmDGfWQCFEQcSqYE2BRgQiJh8HOD07N5hIw==","shasum":"0a8a58a10108f2b9bf38e7b65c237b12fd9c5f04","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001066.tgz","fileCount":794,"unpackedSize":1401468,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezDmKCRA9TVsSAnZWagAAmeQP/jyluW6m4/yay+8z+i1k\nupO6+FkPQ79IOLi0oZyMBBhIVBml603t/+N8QvfiQSC7an+4Q2tgzM75Qjjo\nzzC8e7nQw3pBDk/JJQ7GkFlxWa85xGNCvcviNg1iE3mqlYBECtdArUc6jAVq\nxpbt90wIoj3Zhs+3wRIZ6SHeGwcaLrEMdDIA7wnOFK+0x901+v5+HSY2rCUq\ne5FoxY8EBBLQsgz7Af39DDcTJOo01rJguIR+ag/yQsYMUSMbcXhkskNvUHgV\nOmfNiCRSdcG9yisXn2NJfEzeZJQY07vCC3/6hK0aj6dRwYL1NF6Vzd+Nb147\n3WJAVDSQRAo1G9peJuP1U4pmvsr6iTCZZPf8WDYg5LjYDJ7oyBvKMc1Vf6dP\ny7jQ8CnvoDO//H63cpmFqJwpN/iIdWUS7YW2fe89iCUOOS1j/z2KG06lRfJp\neRcCYQa56FXEdXa7bFRXfk4nTaxDcrLrbFNSncrFO0T5XXe+2M2pA59lnjLs\nSj6KOyYmwjobE2rWQn80NYrDkz7BgHQ/yzcs0KIjPVimXq5gNkCOWFWfwQ9w\np5PaIt5GT9CTQrkP7dNgTYC53b704nuwE1CXdBgo5t0eG2yIzCR6jLmXub+L\nzytnXFiZeWf0dN8Ku0qDpxcotbRJ+dyfOKKylRffwKJuhzOg3GjEAEmFW3f4\nP1Ma\r\n=scCd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCW8JnX38EA/ScAYXNK5xpwBlFQCqhp2hQ9KsfmnjmHNgIgRJfHztfX0SDT1hjerL3lnoJ8rLekVz2ylWqUDs5qQ94="}]}},"1.0.30001077":{"name":"caniuse-lite","version":"1.0.30001077","dist":{"integrity":"sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==","shasum":"5d7da6a120b08d9f4fd94823786ecb454aaa5626","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001077.tgz","fileCount":795,"unpackedSize":1406391,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1yf3CRA9TVsSAnZWagAARCAP/jzS0FkaObuWA8OLttbL\nwu3ojlgq/96zIhwtw7d/MgNT82CEWvHucQvIsnGRY7puqLoVLa6kI8WqdO8k\n8r6fOiEiFSzK2PdPWcyJS0uN+H3jqmCG+SEZLYQmU66CIgQ4kn09V/CrDI9m\n7eGtFCSlj3f9LstAh4z2w0oFzoWOJ2UOp0EyQAfzH+KLa6XmQiW8fsa9J+AG\nRrqXa4WWKDW+zplZy2MeCA+JU6mm6ibuEYeMBqePhJ7kAPjVc2IAmPTMWYRS\nD+9TOa08Qp6nyzCl+4Uvb9MTaBbVRdqZ3w28qh8KFGnlj8DUIatEeE7XmLvd\nIIAVGFGm/iYILVjePoI8hZ8f/XNy8jAbzqCj3FbG3POSvLfWb48b1OMxeIhf\nB13eQGGNpx7wSa1ZCWObSlMz8snP3DyvFyFOJa5OiWotCBU7iieIthHDJg+l\nyyPT8bOeFY72NZhvFpPu3AqNYd6YgsL0pan7G0E0jpE6q80DuIZNBafV72NK\nSntDj/W2vliH79bU1VnhPbhPGOybnR+e9z8xQqPZOLZJW0Cn6YgDP/jfrJ31\nBKhA2CysLRUZudkoZTOf4aZSFUnf+u4spFaH8+HtRgWzK7RGhBNKo6TyswM3\nHplQYu6w5e26IvwtcJLQxftO57Ji+XZC5BH/8ZMBF91p0Tzy+kEfK7X2Oi7e\nA22y\r\n=ar/O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCo0VQqYJBTXhcwbdtd3W0sqCOcThu586eV3UppGqikAQIhALMXK10ztuRNv8j8c8NKtyk0fLjGxf8SmMobji87umOF"}]}},"1.0.30001078":{"name":"caniuse-lite","version":"1.0.30001078","dist":{"integrity":"sha512-sF12qXe9VMm32IEf/+NDvmTpwJaaU7N1igpiH2FdI4DyABJSsOqG3ZAcFvszLkoLoo1y6VJLMYivukUAxaMASw==","shasum":"e1b6e2ae327b6a1ec11f65ec7a0dde1e7093074c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001078.tgz","fileCount":795,"unpackedSize":1402869,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe2ecfCRA9TVsSAnZWagAATEYP/3aAxp5EW4B/YyCFT3QP\nfzerMj2r/5Pjop++q0ubVzdmZhi+7MPMqIfCjo9Zp6jBX8vDO0mnhwSO51Ye\nKV1y2QC8BP7kPEL5gQQ40mpgT1/awCVHpgHUqv8p9vokTVD8gn4wKok9SL3P\nu+q0eywR6OfzrC4Mo80yrcAOL8kgmG5zlQJD6cVrd/wkd82GFe+sg06EP1sW\ntfU2tEZar9sph/C/qkJlmbDTIbgJYXN/mA1xyxIZLYLT0qt6oux6ybKHzgnz\nukcNQGeXMTC5adnunOufAvx9S+21gJWYcKgMuut1FjDd+1NpYt4GIYbcJP1P\ne6dPYw0n58l4L8EVQ18eDGsk/BbaMvADy1bKGH6eTjCR12Zw4eWcqgsklz5W\nZqVRBE5abJGzg10FqMQotfUDe7ICG3NdFHNwOvVhFUUNW86AdsWjBaaQ588B\nL2IVLDR2yR7ucWRFmwxE03+O2rR053aLQ8tUdbbktqzXqBIhEEb+Zo6vgAu+\nDU+V4my1ZCXMTizxQBslUGPRXzfMTBFhbGi920SBlANaK7Oxt/RGnGfwrpqB\ncZDQcXI6vHdBc/knPnRkLq/B2/cp7VVPvrY8vabUb+PpzmUtwAmzlXl5gUPd\nmVEUdLoGL2c/kJrxNMI94B/mSOF/qOugNGY/7/4S9dXpovIvtyC8BGUwTjze\n5yzz\r\n=8A3+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBmrobJj7r0rhcPiEXDIpd/ZUl/bpoXeVXU+wG+kGLhDAiEA9usag4r630aXwM+vQVfKh5FhWjPaxKxc4Rl7BKsgFLc="}]}},"1.0.30001079":{"name":"caniuse-lite","version":"1.0.30001079","dist":{"integrity":"sha512-2KaYheg0iOY+CMmDuAB3DHehrXhhb4OZU4KBVGDr/YKyYAcpudaiUQ9PJ9rxrPlKEoJ3ATasQ5AN48MqpwS43Q==","shasum":"ed3e5225cd9a6850984fdd88bf24ce45d69b9c22","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001079.tgz","fileCount":795,"unpackedSize":1402939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3duaCRA9TVsSAnZWagAA3e8P/i4ek9/MW8xotznT4Br6\nu40lQcA8sczrDuDTDIScCYD51Idzq/+o4C1WVAXRHPtxZCBjeNIgevIY09+l\nGcmH3don5bPR2BAYyDzRlSdajPIS3Zr7BxMHWCuflPw8m1O6aS+r3GC7LhJT\nlUuwAUK1yTCtspqjfRVh4YWoc/Rsi7v/FmMQzoPq88ZgsvfGlOPksxVpxUvx\nrREP6GQT/q8cZVPjKX5zu2w0RTPuWt0iFBEBKJkCmqXRK36Nw5DLuRn0iEQO\ni54Hn0G4h4Y5Vtk7fHpcyBUfxUjQU5Jm4zGewqOiug0B+sN5BlKbY4V1PWZR\nPZql+bYe+JPCPk7DR6ej5K2lZpSs8gWiqOUpZLXz5zce3/8SGJNo8Ci+CXFj\nuT2UJJsKNUsQNE3cD9eTtf5vTORVFhM2vZXmZ3rwduUy9qFmPgYslPySnB8g\nEFcun0RmXxHmr87YS1JYRY7I6L+7MqyCPhqEgtE36dZo9+7A96ObcHSBDMbI\nef/YnE/WhtrKWl9w5bofuG1OuwQBLlJS/rYIKR7AHXt8lhiQoi2EEcwq27p1\n5X+4Ev/yFigRRpqhlnRXHsUwHffP+i2a1HXsEheiZmWZm+vkQj3WcfTfaWz/\nU6wc6h4VZ+TnAfYbjKtlzjm3SEvov/Y1hMHopIihX/oJRhm3VScvQAferiPn\nE8Uk\r\n=A1ml\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3C64FnvgY+BO2l+z1BgMyXnWRPujouGzUXQNaKBxs6wIhAN9WsUD/Ks8RmqzZzCkXiqTx7grVvbwkcJg4l1uqN1ed"}]}},"1.0.30001081":{"name":"caniuse-lite","version":"1.0.30001081","dist":{"integrity":"sha512-iZdh3lu09jsUtLE6Bp8NAbJskco4Y3UDtkR3GTCJGsbMowBU5IWDFF79sV2ws7lSqTzWyKazxam2thasHymENQ==","shasum":"40615a3c416a047c5a4d45673e5257bf128eb3b5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001081.tgz","fileCount":795,"unpackedSize":1403558,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe4FR4CRA9TVsSAnZWagAAEvkP/1qJslBTsTUmBYissSVo\nw2FCJJ7w+V1J9C8SdGE9dQm5DMRCoOIzQ6CAaGIEKaTZaOvi9uFmQ/YX7whH\nWA2YJlfd1291JYiE4CAdhfAL82kBI+5xc6NbLDoljfPKBllpHqu/8UprFYXa\n2IhJ5VZ7RPalFJhondUJINFPzyDiL3IyPJDh/7/u63ekaTzLuoLjRPB5EKFO\ncN35d2RmcvoMugqlnj2oJySaZDENANrgnoh2z5qpQK5fSO9d2AZ76RSsiXwX\nTWVh06gEs9U5vE0gLlAvicm/HSdK4jNM4cNHT02bd6wO4CinjkEPYBwHlsZb\n9FOVVUSWxIGZ7oTrDiWSXxyIudMo//UMGXRIWom3k9zOS4FbX2W+wfESCyc2\nRgGG8qbxqSj6R5vDm5a4foXfNuvOzQQF0aFoEasDYhUpCrOltIgNP5zew7Xb\nAgR302t2jSENmTDBeO1X9MZwO7H2m6rDDYurR4FzHPiPCTmS4jX6F0UVcWS+\nmgOPNLZk645U+7VOaKsYGmrTLuwCfrmbZrLJOBm8JwllFzT5ZPCED3qc/JuK\nsgc6aze/VDY14ZF0KBSFQ93xvw4Ht23CNzU/hR/5kosoYYkafKy94EXiZtl0\nHmF1DuDdcXuxrPugJlu0P8I1vPy+u60F9HlnPCIwrg8PC/0Kk8t6YE0DZjXG\nacAs\r\n=oJM6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDW4p+zpBARCDgpfPpT98Z0BkEAZ47+P3QYGhPhBHWqnwIhAI236utLytNFTBAxNhgPMlC632j9XzjBCjMnUMOk0u6k"}]}},"1.0.30001083":{"name":"caniuse-lite","version":"1.0.30001083","dist":{"integrity":"sha512-CnYJ27awX4h7yj5glfK7r1TOI13LBytpLzEgfj0s4mY75/F8pnQcYjL+oVpmS38FB59+vU0gscQ9D8tc+lIXvA==","shasum":"52410c20c6f029f604f0d45eca0439a82e712442","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001083.tgz","fileCount":795,"unpackedSize":1403636,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe5SnwCRA9TVsSAnZWagAAfZkP/3hQVgWqTWrBTvAL6XC9\nK+C//2VejqEwFRBcSIXuiL6yKDJ2++k8q/fbXTKPLeaAihehPjg8kayK1ajg\nvvCHfxmrHwog2udLPy12eoQp0NGto8+T0PIo7C4da9PazzRioEHcRrnoVsTg\nry9voIGs+MXOs+ZZnIS/WwMVs8RY0vYZyFsD24xOGSQNfTiSS+khAEJqaLwG\nZvBGfdr1Yme9/fkDrv7iSP8Hn4qT6kEhO2YthXzZ389wEW2ww1bSPTCJ2nfI\nywpDlbwX9hicaMRNyRhuygA8pbTLT2GjeWEpth9/qWgVTji6Dkx7IlhfP0kJ\nDmgmlHfGt3YopNC4YuhBtmtcTq0HUwY7/ndI2iEBlJqF3C3D+S8CRvGnUOze\n7VCtE5+gdKa2V66R/qqF3VhaGG8Jvj3N/KdmVSAOAvDbjVNNemH1lfVlhM1T\nV5C/tcgUwxdaX+42QCqgsvlDyQr5RaroItMkESaXm1HqxVY0TWbdOv1/H74Y\nPaN1ctEuxRZA39bAM8oJ1G0Hnxd6UPD6Ub+YCM1QU9QGeKmXLQTA8GE+r4oc\n7z20V8ixoK5cbl4Q75fFpsoXe8+dYZXOKTaLPhy4Gq1xBEtxgvIDBoqsOKYk\ntW6TKM/+70vP2V4o7/P16bxRctEYTxv3zxa2IaGAnQRC/Sp5Xsr+bRe/e+0q\nYOYx\r\n=srFk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFzzDXXGEZxnDybr2EZleDoon7Vu3KvLuAfAD6P5kuaqAiBMzijrLZpsBwoiVwOXCjRNcdHxIP7PMwOdXSIL29kYEg=="}]}},"1.0.30001084":{"name":"caniuse-lite","version":"1.0.30001084","dist":{"integrity":"sha512-ftdc5oGmhEbLUuMZ/Qp3mOpzfZLCxPYKcvGv6v2dJJ+8EdqcvZRbAGOiLmkM/PV1QGta/uwBs8/nCl6sokDW6w==","shasum":"00e471931eaefbeef54f46aa2203914d3c165669","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001084.tgz","fileCount":796,"unpackedSize":1406379,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6GexCRA9TVsSAnZWagAAYIkP/2txnewUQB9XqWYAJEiL\nb2yGEhFg8REWCcyzGGMixABZVOmY3zTmRoJc7GO3gCpoEE09FE2ld3NsgjLe\n3wxeVZvejp4uW932lr1Ft5Y/zpWPKij6DSO2rWpVXn6emVcqtDNlyKbiYlLh\nU5NaEZ91zkOqxnWWAfuUC18brRox1HunvzgbTUWeqPx/QjTnc9PckIIq0ZU0\n6+htAJdQnt6hLeB2VyW260296yX1pwsHRItEl8Y8UrqTeTpgd9IT0CgBjrBG\nABW3iYeYBg9sL0r/44WqqSyChV+e7juMGMqaFYL0uVkGWDmXflFjRk0IovHO\nVm04JnI1ODNJ/heJBz0v5VdD7KsI0VM8n2tQ+uHB2H5Cl0rB0yGuMsvj8nAQ\n7R/sZJrsOQdruPlVkM3AGugBff04ebOktoMgYHZlej78Uw+g7Q915vM0oGX8\nAcYJGSfTH1CvvYhJ//6N1TrK55VYt1ik+gR7XDl1PTHivUbwL8VHxkNbtWVR\nHSmiqhNFRbKrJhVy5WC5LCNufei8Rg+w++3UpYRyouFQ4eo6M+3+RzI10D7K\nd2pcd7LlMeMa/iWiJhpZ99g6NInt05ZXNzGS2TzhvqT6oWkpjRcU9R+2NUbU\nQjQElEvnZotrC3OvgKltj1pW2H2QRUOYO2tQ+1eICFAxiY1oAbuyNV8fL2vo\nm5Zj\r\n=JDbN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOn6LAwk1ZYSI7A/zpOJEpKZk25D717z0t8cs8W6wn6QIhAOEWUui0aHYvzp+0BwimcdiOWbeLBJQTt8RYMvz0wNEi"}]}},"1.0.30001085":{"name":"caniuse-lite","version":"1.0.30001085","dist":{"integrity":"sha512-x0YRFRE0pmOD90z+9Xk7jwO58p4feVNXP+U8kWV+Uo/HADyrgESlepzIkUqPgaXkpyceZU6siM1gsK7sHgplqA==","shasum":"bed28bd51ff7425d33ee23e730c7f3b703711db6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001085.tgz","fileCount":796,"unpackedSize":1406435,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe7vEPCRA9TVsSAnZWagAAe1kP/1E2PwAV1SCpqsyjQZmy\nynm4Hh8OG2E0nhd9f4lKF1UGEcph46L0z9NCnXU4l7UD6f8J/iyy4lIvYZg0\nFDmQPuLlwY7I/dleyzOiBlQ7v4yGKL5CgT/vVpeEnh4ITUYy/w1a+QFwtLs+\nhbRdJ+ggKP4TbQMUgpWSPxGpHl/YH7Nk3Be1V7eiZ86AbUt0KGBTUCw20mh4\nGh3ObC/jxuMFuzNuk2jTaqvifxgc2A63hh4T24ovSTbYzJa/TBEBFwFChwss\nK9Wz6u9QhuGZLfeld6VTkr/pKuKUrUqV/txVoGSSPtDnGfvx34mPrna10oh2\nYU2dqWNiZKN1DMSe1VeXrJR4lv+CLmTt8pnE6gvIKQdTNy0//q9PtfDxh4XN\nq3xautG5AmKU25NwXK69mMTarh2FJKBzO2YEzHQaZfCZkSC5dkk0zysT0gIG\nEUk4OtIvkHljmmmqqrOwXoPd7NHXK638DSmnwuZYZVCZ2BVJzOrsUCDu1tms\nUZofpFz5XsKV4gN3fTx9QJF2zTl38FN6mIVCfouhTLC6h8cC2bhWn9yf9kDB\nrAqG9ZDPt7Ms9rfseO9HDmI9lmbLPSP1b+b4wLKiktVzjQqYC0rc/lsFjidq\nQsWgYbKbUxoUR7ZdprupomoBQpE6KRTQcAZgvDIRHXs3TYRpvVSOD0tv1bqX\n7qgp\r\n=KToj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHioqlaeaQBIwg0SS1G7QRe/Zxzisj/OiK2ClK3xpkpQIgFKshsCQdh1BEipWDyOjTfvLsjN62XcVbp4JaiIzRS/8="}]}},"1.0.30001087":{"name":"caniuse-lite","version":"1.0.30001087","dist":{"integrity":"sha512-KAQRGtt+eGCQBSp2iZTQibdCf9oe6cNTi5lmpsW38NnxP4WMYzfU6HCRmh4kJyh6LrTM9/uyElK4xcO93kafpg==","shasum":"4a0bdc5998a114fcf8b7954e7ba6c2c29831c54a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001087.tgz","fileCount":796,"unpackedSize":1409248,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8ZQZCRA9TVsSAnZWagAAUQ8P/2xmsb4CgTf4zMnDhAjB\nlcXnmcqtuFnL4Cj57d4jsCyq1N+kqVHr0yILsUdpoqY7zBjWFwewEE/6B0oZ\nt55TduGyUTUaTik/djaLUUOO/rZqSbLnj3Z21fDydh8GS6xwtfnJrRtSWwh+\nN0Yb83BqH4HhdPkVP05K48JOGRKnSFYeT662EZpJJMfW7AaeoV0UlsqJfGgv\nRsnQ3/5j4agIZSFhXPakK1zqgKeoobhP96wRkwAL9Dw+oJMrSIW/aTvpvVZH\nHhqBi30GYNtR2TFNA/JX7hmwd2qW/20Q5D/td/65zVLBDha5mBGlCe6H8VA7\nczmWOPy9k3isbGD25AHALx1c4seAPLyQ+QLYWyKaig3y2wYVWGq/Ecoih1lx\nxKeS3QIbt+kWDC9ooCBNuD3Pi311O1m0QtY7myJLWSbOHX3l91nx2OmBURba\nWr5LtqCLEQDS/nWz/8JSgGE87Dmd0NIwCDhBub29Me+SBDcwdtQ908771sN/\nCnJPkQb/EV3GoMdpOSaXrSoNzp2vgId/4ML3Ug9gsilLAuaNtNtz6Jer/o8X\nwVEj8EgsNicntBFt0Gs5BIaQXIjpTEfgFD6T2XXGUVLUWKuS2xv3qygvLACi\nSFrCamfu41K8Vb7CJJcWubRrQKTvwcPNsbAr0teqrl/OVUtDQpzcYKogRGL0\n0l2c\r\n=+L2h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCjIg5a2r6HbMZGYOFdnVtklbKimglCsnZn8oJOelMu2gIgO2QjUKI/YmVBsd82Y5w3QQ8JpC0oX+ikMXtmex9kID4="}]}},"1.0.30001088":{"name":"caniuse-lite","version":"1.0.30001088","dist":{"integrity":"sha512-6eYUrlShRYveyqKG58HcyOfPgh3zb2xqs7NvT2VVtP3hEUeeWvc3lqhpeMTxYWBBeeaT9A4bKsrtjATm66BTHg==","shasum":"23a6b9e192106107458528858f2c0e0dba0d9073","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001088.tgz","fileCount":796,"unpackedSize":1409311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8uWLCRA9TVsSAnZWagAAjfoP/ifiDnFh8K1ChZ5VdVYv\niRuWeoLG94QbOD0iG2MtfbJkONGNDHvT8owxXIu6r0XVHwC7mksolzt5yPEo\nBKu/lH2xKY8i2KQhepCLH2WBshGrsTJZOAlwoGJ1hfpYbASo3ryPfB36ZZ79\nBrxkZbUywbgyI6pt7ZeU1lO+sEA/Uh8lwuMfZbLzvT7TKWaorZySQhSx1tZj\nRuc7CFjB6K2dc/bqztMZztE/9NDmHbM+LFPWl+8k9ccdS2oly90c7Zp7UM1X\ndgKe5hzIU5dp5OlZhM/EXxf6r+CR/l/0ZKpJaebwg+xf67LlVDkyMC6u+YEb\nJD63U312wtrIvOUHHh+Li90+SpdJuh7vWEGs0ZaMd1hrMkUHeeXAje4ZfEv0\nOp3t+vzJdGU9149PPiIUHFBhnrGnzDuJYQ0z0ntYTBrLXsRx8RGgJ1MOGABo\nEDWDjIJSN0s8eR2eTqKOhDIhzFa3Eyjboie7likbrt6WAqOnf/mFrbSfO/En\nswzY7M4gjX5Dyf5cYz9XR9RC81xkSsUaLzUlux6v/EYcg519J5RJkaz4ALGh\nAIemlq1S8UHh9FvbxfwHHtHHXD7J1eybv5WXU6eQzUAN2T34woiX4GkrKwYi\n/RtvRNusE0T0amFYvE5vyvMBsmxkzp1ph9JdSAD8CUnyf57kcomIJVLiNrqv\nNzyy\r\n=qFIi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICB3H8AvvbYvTaY3+PEXOjz2w5L3Har2xyW27SMpukbrAiEAv9+Xt9NTBZ3Wl0xc4+syupqgD169562AhsTvhKpVDWE="}]}},"1.0.30001089":{"name":"caniuse-lite","version":"1.0.30001089","dist":{"integrity":"sha512-RnL5dbdqAfQ5oxHjFUU8uiyJMvTKoXfRn0Asp2R5cpRsyiY5+kLl0fcocQijb0V9XAWFEG/2A/vSswRmpYarmA==","shasum":"0634653159f1179093a35fd7f36dbd7c4ed85101","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001089.tgz","fileCount":798,"unpackedSize":1411463,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9ugeCRA9TVsSAnZWagAAbA4P/3Ot2z1LLZv1k0R5Ecmm\nEDJ1hGTu657Eem8d7dJ5qBe/VWi1bIS4y96A9GnTr4mV7HadRGiGI8FYXUyK\n+OSgS/tCAoVIXU6/XWss7XGAht/+2m1hSsLfokPLLhrbpbpsOZ9U10sxTcxZ\ndCfDie6Yki1b7+Ce9nYLxTOw2aCWC7MKjaWGw8CRKeS7UJ2oy0YYh7Bt21rX\nsrLrvGSwRXa3YuuoGl6t0rnxTkdKzYhEPeqEkG9IDP3xGwMN4AP+bZiyUWmV\neqfni8RYDkKSHKQ3jezL5x2XBFPNWD9Sw/GA4i64vreaB9e6WN8g6cxqORam\nGp3QSUsOkQu5unvFbqCXbZLc/tamszi67AtaPBmciS6TV7z2RUcis2Haxw5P\nusS88Hhot6IV2qOaQYEX8hbWteNNS9xn+OGejWMKOcjmc89jVsincZoea2hc\nnuKmNF3SwkU8NSbtESiXBYbEVA0jr1EM041qH3zGUAdJ5UTqDxdiV0yaet8O\nBr+wx91MoG3z5sWh51RaxGikgSd8sPKxcEaWDWetnhRTWA7nZ800LAEpOhO2\nMjZ53hNIaxMq+QyDrYDSpYUFMeXyaEzMlMBnk0IEgT1VY3z3nqZ7jfWF1LmF\nRM60UT0qGlfKNC0rrh+WYsK2zOyTTNwnGh9Rb72H4rjzX9wvVEDE83Wsxd3a\nQj1p\r\n=4Ups\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCs793gpj39KAleLsGunrtibk4InrqpYBJZRXhk6CiMQwIhAOGNUHLVxm0tUv9gfMLs/YCg+OkUt3eWfQ+Ng9Z8lgNF"}]}},"1.0.30001090":{"name":"caniuse-lite","version":"1.0.30001090","dist":{"integrity":"sha512-QzPRKDCyp7RhjczTPZaqK3CjPA5Ht2UnXhZhCI4f7QiB5JK6KEuZBxIzyWnB3wO4hgAj4GMRxAhuiacfw0Psjg==","shasum":"ff7766332f60e80fea4903f30d360622e5551850","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001090.tgz","fileCount":798,"unpackedSize":1411533,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe957qCRA9TVsSAnZWagAAT2AQAJnf4hc4/ufOR9byeHc8\nBlB9tApI3rQhZs4Vw9C8lDWmrmGFdMHv9dMMwO3NLO69NufM6nWARqkcI6rs\nN9DoRNpluDDqNll+seH/pHsaXmjQwJzQf/BI22QA6DvGXXluWnfs0pXu09CE\nptpuvvR8OarGLeimchAXJ0O3QfBII9wpzvx/pQK8e3wMcB5m3zvxg/AxtMws\nKzR27zWMzTIdoZC2mDUisrOkzt4ynSvk7bX5mNYlczUVycNdB25pioSyYj9V\nGm/1v5pF0zFgvJs/5RZSROsoPjVIYYxCKad54dB6jjsxCARzPhzmKniRGLvX\n9/HFdhm06l5G9MqrMShkfCd/RMnsN8bC/ZYO+Q2aCSfKHsThv79G4JT9rsXu\ncUzJRufIMmX6mjuMUsYFFky48o9q+EA/47OWIUHvAwEoa3y+weum/f9dcVXt\nWdi0ZXb+mjXJ0Q5FGgy9yibQio39eUxRRUeE7lSA0G8dhUM4KXQHDVnPSnvQ\n0ocFRMl80LQVVyhFngdD18V2gtQcm7PPZLxa85OOOp/r5zswn357oDyK2B+x\nrlG3qP5zPQMlwD/f0tCRTYLCw9dxSJeyAm1c80rV7UD+ZELrt4e3rjwEjsZC\nNTFNnWpYkpz/Y4vY66CNxNFrBw1weNc5sByH2oYyxFteef7c27lWswWOkeMt\nqC5d\r\n=hKF9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCoopr/JVktz4CE+K3nnt8wx1PQLn4TKBGtSF88CrJ9lgIgR0iLzXYbnNEtn4KvyB2lKN0rD0dNMhopGQ96zIvpglY="}]}},"1.0.30001091":{"name":"caniuse-lite","version":"1.0.30001091","dist":{"integrity":"sha512-ECd8gfBBpv0GKsEYY5052+8PBjExiugDoi3dfkJcxujh2mf7kiuDvb1o27GXlOOGopKiIPYEX8XDPYj7eo3E9w==","shasum":"84908c67b98e02c2a56d4afa51e6458b53fb5321","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001091.tgz","fileCount":798,"unpackedSize":1411631,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+72cCRA9TVsSAnZWagAAgegP+QDm236EJt57ME/yQGMV\nGSHvUoKaUFraOCLUM5dMdzr7z/PfjCtDMg8lVTDhmv5joIQNvL25mroUFrmQ\nVNkuLZDobhgltFVwEXa4yFs8dNdTe7yFtM8l+dXoRml/B3WPuil70QHLro/S\nLBczW8Ug0I/sxSKL0NmUF7/hgWhyMU07EIXTmPIASKUVijN46XIyyWtnyvR8\n/DuXbKMpPjnMEpfkhQd2GqvwhJe6KD5qpZNshRjWizrZonGwn0AgaaPq0jOM\nYemzg/JW5rsoiGqD6TCjR413VeILgXqkCnsgbRujiQwj+PqMaH3UVS3IqbmS\ndYQvzA76x5PFhgDdbsW9/MVTipPVjrKFbbYaGZeWa5XIhrGYvVRg4dPCTIGr\ncO88nYMJNQ7iIzRuYLEhTpUtKLE/FOdc+nsxUu1jWyaNoxTC4NejMQsBxkTF\nYrt8oq2i4z+Zt1mE3bbUl4NL5i9HYuDF0xsPRrFiiELJQx/C64ZgRGJZZlsN\nsCwMUU7pzLgSAi+kR0H39MD+KpvtE6LKYWXTKD0wqXU1mJtiHtjyiY42AMXH\naYaL1rddRw/RQPCpzwUrDKovIvTMCKdNIC1lg7xmX8IO6dOydzMGHO98Rxmm\nhXuW88KNMlgCDzw2rAk0UCP/dhQsgaP5IXLQYOayoPPVUxD+6/HQYEJgUyTP\nxaBh\r\n=NOWB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCPSGttrjS9FPNnZuo1Bre03UavY+LCxssTlv6OQbzHyQIhAPI1vhnkZOhiheRqILK76339EKghuCvFb9KnK7j5dgvy"}]}},"1.0.30001092":{"name":"caniuse-lite","version":"1.0.30001092","dist":{"integrity":"sha512-DjzewcyYKjbfPQHF3gNe78JuezZy9a7szvLrUTomMZiaRHy2o998tGbInwhLnzlM7yI0sapt539P6AL/Wd93rQ==","shasum":"01291f9eda3a50c77f2083ba8855080f9d81eb69","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001092.tgz","fileCount":798,"unpackedSize":1413329,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/QEaCRA9TVsSAnZWagAAS9QP/2yGmsty5wGfvmFS7bXF\n7lEoV8ub7wiZFkN9wXTRH7YO9cx2BLM5GifHai+BugBfNhXcZQua04F/ZXpM\nJgp0bLScHFyMcF/oGA3L9L+AyYWm3/pIEP66VMR53q4ENos5aPpUpLKSjJC4\nznnTqiGXVMyMhFXKs3D8nnoCXPQJsaE9gOjQZ5cROziKOK4i9CyKRxztVyys\nD+gI/9o59Rk2NwLyqE9wAsooVBZ4bW3T1iXZrEc7KQmSFQKvxXuQFHBaqhYI\nXHhnsoWrrIb/frxrQfAaTHjzLiBcN87FSs6TdqCYaT1RZyio2QnfC5T0QWkr\nclfjN8byPzV7LnPl0SxQD31nBGhuCBb7uGsNM+qNltmKDuxUsceIu6dHzI9m\n10TO2/HlgKVfRyLwXWxZr/lfXt892KzNFvyWdbeIsXBG9i7twheHsa7qmSOh\nrnsFzTXv0iTOKNs6KoYIrKB6RSDvQTLod5Ce/Rld8kzFZECWbrcMtuzymxL7\njP/z7oR9fK5MRKMhphfxa88vkRziahqrGwXge455sAR5BN6tIMJx+X/crtT/\n/BOyYIbv4Os1CqPc/s68V+cSRjYR8sgzbJyPU9Bt7bFihisgagHOgo+a3cuF\ntYUoIhusRi2hw4ZDglG1omgP6u9letqcY5yra8DMstOyFALKCtpCulZm8KLw\nN+ve\r\n=Krw9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBVIsCBSGFq4CILH73mbpc7XE1PR64XN9yQtJlEMnQTrAiA0Noz4an5N+hyIhtFpaOH0mAI+gPVBnY7FfxyPHTNhWA=="}]}},"1.0.30001093":{"name":"caniuse-lite","version":"1.0.30001093","dist":{"integrity":"sha512-0+ODNoOjtWD5eS9aaIpf4K0gQqZfILNY4WSNuYzeT1sXni+lMrrVjc0odEobJt6wrODofDZUX8XYi/5y7+xl8g==","shasum":"833e80f64b1a0455cbceed2a4a3baf19e4abd312","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001093.tgz","fileCount":798,"unpackedSize":1415055,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/Q8lCRA9TVsSAnZWagAATSYP/2X0g+2dtdn6LQLKYtNA\nJhlV34zZQOg8da9/fPaqVBnIu/sanExVRwWQgzXNSa7xneEZ9TmvqQnN+4Ji\nvnB5xGQeBtEwWB43j3im7+M/XzFcdaeXTVfusI7xGXgSP8NO3V0mGtVw0VUH\nPvm//UxjiZoaiSYsXpKxL1UtLehx5Lp3wXsMH+rghypOXGSmlrPMd/p0u89e\nbJa0yId2ZMcpQmp0JUv56yOn+mNK2qYMDDYzD4/ke4UMwfzh5okRNgtFxJPI\nm2odMGC2OjxTYRn78rFxzxs3PqFQlSJHdITq7dujIMKDlUfYZjMiLAMBOUX2\nkA+U7fUgLO+WkpNQCq+o8LG7O9nV9xYWu/OcRjaisZmKX3kug9WAnWGePyxe\npNWES/aHFYGjwvRRrwvGFaMTmv/yRhXRSORLvgZqaTq74TS2MmMTBt+5Ah0D\nWjO3dgnmIc6sSjVO0ss/96vtXv9sRz0Sa7k/X9SHILTa1Mwk7sgXAo0XiFGl\nXTCIwdYV2EgopJ9PAMAIlxup0sIcZknvdYr0pzQBZXFKebLuAl6UhOh+wLI6\nUpwzRs3WtnmgCREAD0cIj8VlFeamsBTOZh1JUfU+MXgvEHfNG50AIRWXgQaM\n1LJrYR3kmQQu0er8gTEXeUHLzMY0f4cRaQdK/eCs3Ie9hwF327Lt97o3S1cs\n4KXB\r\n=Ce+W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDBqB5p+jifhkVGze8h/3zgix1f5/nohdcOWy/5T9AqBwIhAIy04uH+l15LVe+3zHV5AZNM70YBTk/XCTbmAGoxhIwU"}]}},"1.0.30001094":{"name":"caniuse-lite","version":"1.0.30001094","dist":{"integrity":"sha512-ufHZNtMaDEuRBpTbqD93tIQnngmJ+oBknjvr0IbFympSdtFpAUFmNv4mVKbb53qltxFx0nK3iy32S9AqkLzUNA==","shasum":"0b11d02e1cdc201348dbd8e3e57bd9b6ce82b175","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001094.tgz","fileCount":798,"unpackedSize":1431916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfAWYgCRA9TVsSAnZWagAAnBgP/3Wv43L/ITsSt1SWXSRe\nSRNUcPhJL5E9JkhbrX6KQoRhteQcU/ifiSS2TVQkCUS3+rGTat2sXihlqEra\nUJCa/jfcOLBndADdQwe84VvxX5RohqWPee12YozuwHpk3u21VwSDFpyx1QuF\n+5ciVw5/7OTzG2YJaIDVX4U5ErDcpghFdFKLR5Ntpwi0/Fy78LlLTvO1tXrv\n6A9EbwjQ9pfTaHBrhsYZ2zDaGKXpGN8/BpkMXRtA6dxYYrHx7aAHHYYVqa3e\nfvv0dZvGr3vqJCH1/M5Ds8x0B7H7vROjdmQycNnPBHEv1r6HGnCI4RjZzM2I\nglh50I6b5e8RT94fqL7cDXnw1ZafJV5zavQQ79VJWnY4qsonGr0FdRaie8dQ\nS+rv+zAdVcF+omH0grcEbJnJqKa/BS57W9u9V7NjQnv74EPh8Z1AURj2XHdR\nTGkbsOlTj5iQ1DNmzFkWhXFNx71QiqVGeUa4x0FBhonYdgw2eYP+TV6zDQbV\nM+pfwwa+gEB4TJAXBlF8nvJ+Sx9HR/qb5s54mHiyGqAg+9D3VLRJkGLIgZS6\nS+O4WDry9FW1NuSV86C/a0Ahnw3rDBz0WhWqs7eA7MK+uq5h9ENPdx3M9JdF\naQf4j1f+PrSXhR3tHzLE6dHwcij6a3sOtVjIEgPt4mdL6Nl6ByvCQqdq2aVn\nlAQk\r\n=YocG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIChuah21I3ELZ6mgARKmil3UeAWXs1yQkKf2l+ymWgkQAiBq26xS3UEKMZXHvud1c/uUzcENjNfw6xDn2VLitLQsoA=="}]}},"1.0.30001096":{"name":"caniuse-lite","version":"1.0.30001096","dist":{"integrity":"sha512-PFTw9UyVfbkcMEFs82q8XVlRayj7HKvnhu5BLcmjGpv+SNyiWasCcWXPGJuO0rK0dhLRDJmtZcJ+LHUfypbw1w==","shasum":"5a4541af5317dc21f91f5b24d453030a35f919c0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001096.tgz","fileCount":798,"unpackedSize":1431987,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfBVqOCRA9TVsSAnZWagAAo0wP/2aCBhtCJ6y5dutkn1T9\n6141ALeAJ0qaEa+tU9WIL9olZ90pIELojFJgnq7L6lWKczi6nMEaQmOiZTxt\n0Jy4Wlrwt9SKEmzjWTq99DPAXyPDKzSFnjazvoqaT1eUTGpNWiVnFRAPENEB\nXZwGrQYz6w0ufRXBlHwta7KCaaKwvYnfSk/lz9QMckf4Ykc/nsF6toPG1nqW\nlTr6tUGMTkByKlrO4dmVGLe+MFO7QaBj5O9hQWMPQVUSWLIu7Maby/hykoHD\ne3t1by4FhHRuTII+rpx92S3la5v+fLNgZfecVa6Bgem98w5Tv7pmetW06+T4\nOkxyDQfcdNf9rXL91CT90ocC+U4pjSDF2IJGV72EAochox6jD7tXBxdtomGY\nAdHWz+ckGMEZ4sUrgOnucs+fMHLPMwhtPbAUbFGmlLbwEg6dgvvsJlf9XefC\nq5c9Cr4ca1FXkMI7WnSV0bawvuJdx12sS8vbQe7N6zKi6R1k0kuiyKgPm1Ib\nKjyBYkPlBAruDVRB7uBxU4h8/oKFprJdZEMEDCg99d5+Efch8rEk3AoTDER/\n2oLF1NDrnPNfYZSvbv/iWPlYd7q0ahbehlvfR6cflJRLfm/7kuC8jxVGK6bn\n6Vw1bcSp398P0mrv68GnVA4/jDZHnOZsQkaV2r5I5LSEIb4C+Ffc4Xu5s3TF\nkdi8\r\n=CdSp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6z3rHAOzuccJ+waiJN/1NMVG8eG/peh5z0eFN4bihUgIgTUhlgHfwNB/h7at6uZfeRMJwxOZGbVyMe1c6qI3NTeo="}]}},"1.0.30001097":{"name":"caniuse-lite","version":"1.0.30001097","dist":{"integrity":"sha512-TeuSleKt/vWXaPkLVFqGDnbweYfq4IaZ6rUugFf3rWY6dlII8StUZ8Ddin0PkADfgYZ4wRqCdO2ORl4Rn5eZIA==","shasum":"1129c40c9f5ee3282158da08fd915d301f4a9bd8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001097.tgz","fileCount":798,"unpackedSize":1432065,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfB+FuCRA9TVsSAnZWagAA0wAQAJSdnfuqAYMn2wFwPz/o\nkFwFeBrP8rilPLkPLOKSkdEZ3JUJtRFuhe/uPDEr/0Zca5EgO3mz+Rgxho5g\nrQtI5v6CUDhDag7HI7pCRLD3EndNQepoFu7NyQlE403SWtamjrunAwxa93BK\nwluWpG4FjwrC2dgcMGkALFTxJ7zm5ntj1TWWMvyamDi2Hfwv+FqJ7+Upd0Ql\nHWsaEYF/ENsteJijiedYf8sbmBx9sgvDsSN7dRn0FKlABbtWTUDvWBuNXgaj\n7m9NlWLOasWJQ4UgKKIBqDtYbZmonBNzuIbwBJyZd5IRCkKKzku55NGSlE0B\neExyc+IJ6cTxBof9E0A+8jGnch1nF59w9TwqzkLNZwBKDYvlR1Ksd4KKiWHy\nFCRa6FP26hfyQi3EQmBvyevK0InmzG1jNtSRVr8G/2/vuRhEjpXazfKbh9Tt\n/SI/CzFOQ+wlYwKUxw8TQiI29jAkgTgZRatzsUv9bfkcYaQV3SAd0KIbv9yC\nIA+5wp4wZcKSgF2YxMOBpPY+jTWp6mKE/+tpVKK0dqVrRcgHIDpue8Fc4ZLL\njpSZ3KNysYDcDO7QDwFSkfVwhC+NE6EguMApDUWg4/RmyTfnQIoiNLK9KMBt\n5cESzP3hQ/y7P8y3y3CFhIL/6RrW2u9z8SPXq7NPvTmEM+xlPl1nAV+i5Xq3\nwj6U\r\n=xcws\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDscYkmv1zlXvR1SYVzzCdhW4s29k0IyBxhM1oQO+AKvAIgCy17d23arpHA8+ohkVoTylVGAZB+4w0fGK53ZhdS09Y="}]}},"1.0.30001099":{"name":"caniuse-lite","version":"1.0.30001099","dist":{"integrity":"sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA==","shasum":"540118fcc6842d1fde62f4ee5521d1ec6afdb40e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001099.tgz","fileCount":798,"unpackedSize":1432147,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfChPsCRA9TVsSAnZWagAAJfAP/RDbO6bn4YynZv1u7BEr\nTrQupgIDDK95yWy38P0FD3sY8x9Q93LSk2f92nxPsUkwp8zBIAVlJN6eRbFl\ng3MCBHlXhetEdc7GVqkroIIJaxWZDbCN/Xruz8mnHw2FKBnwrg3OQ8xBsRpM\n+vuWDjowuh1L9hpUgVrBs1H03DAxlVnFQvQvc6xHnqGUCvKtxeCWpOW3eJ6J\nIsB7MRoUl1Cz6j4FOaoqt2g8ituh0HUk33PWaPOsXgJcgd3PAa02dHIlkutY\n8AvxtkVUBusv8/P0agwI4NR9XI26ai3kCmHiZbIj6behovFsfOsrWCQ1S01x\n4WvofcI2+6akeS0zDw5bt0ZqEK6fsGqRGsyGFIdL5vUumsdDYOtlMzq4yK+r\nLGwKrJYmc0w5cF3fpjOSggqlSmrg+Q0BThC7lc24UQGkuGaIjNSXo2NDjVC+\nahdvVvTOH+a9xhcaJ0oRgCjK9ugnd4wEYISsErH2+9/RNapz11MQo0IKS7Bs\nLJ5o/J+rcNkjndD2UzJslp9UO6AsN0+IeRWssHZx0VJNPtctAbV9ISC8Y0PU\n5LLLtjSUgFPBXXhaESLPKuqKQWuSFQwYe61rLIDNdVG2AcZ6ZpJ1QVVTCo2p\nxcxsk4i9EbJGCDfowNZ/L+yzJUSGdUNgmIOADYUx0TF2XoLzBIL0TPWXnsyv\n1MxU\r\n=K/jC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL/BEJoLJ8zJtBjfc6RixZ50/oR1ak8xz78cdDrp7IHwIgPGtiKKpIPAStSge4JuABsjQ6UNeE7bs2sI85gc1nY3o="}]}},"1.0.30001100":{"name":"caniuse-lite","version":"1.0.30001100","dist":{"integrity":"sha512-0eYdp1+wFCnMlCj2oudciuQn2B9xAFq3WpgpcBIZTxk/1HNA/O2YA7rpeYhnOqsqAJq1AHUgx6i1jtafg7m2zA==","shasum":"2a58615e0c01cf716ab349b20ca4d86ef944aa4e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001100.tgz","fileCount":798,"unpackedSize":1432204,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfDmraCRA9TVsSAnZWagAA9QUP/jmDu77hiX+fH8gFF0qn\nPNK7AlEYj6LQa+AKTOXoIcRll/9/QSk7Rhqdo+bHvKPJKBqaLzDdSMa8isOS\nz1zdDLXwim2TFg/R/GlabyjNrEMlY/MYOGURKjRFk2ZKu/OLZIe1QwSAzE0C\ndKP2Nwlyj3Atgu+WRL53w/JaHHvN4iJ6dSLEFCjOyZtHtjB9RyGFGeLNkcFR\nD/Fz1cnHiLBTf6v2s5qPHofYFKEKuhQdb9efANfwLrPc1YPTfjht8OHZ6468\nh/CBTeAIYRCGcSESyGC80+dFQNi+uunES1Xt4QOOj2X2RP1F27U/eneDWk51\ndxyx/rUkr6vNre1GKTJ9SucF5RgCopSdfEktM8tmPBydqTkSm/RtCZl2jWDf\nKzIXBUf9XXTbyyDn9k3hQwtvtn+nC7DBmcAr1I1MIP2nH17PGREh66KuhEC/\n/XMqVihLzd9CTDQKUi99Ek8I7e4ct7Jold7OmdpphSJnA7fEC7IMeyUwi/kn\n8TvKmeFP84KbsRz8ox/RPJAl5QdQFOod6DRscBTQiVtku6BqYgeQK5x1vjAm\na0H6N/uJdeyzDANUeLa5Wo24eYJ5fd39Oyf22mri1lBU17d4UOSI19thw5Gr\no59nZg/d3TkiGcs3ntW5QRzjHrqIv7ewWy+/Qs78wsnnfJ0qJErqU0xcrwib\nh6YX\r\n=kmFA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID8INfaT9WFESDQWLoFloU8afdNanUQ9U4bHGHmPdw5iAiA6lUCnVDjOq3oiZirZLhtHhu1jU7L4TepfLIbtrcNK0w=="}]}},"1.0.30001101":{"name":"caniuse-lite","version":"1.0.30001101","dist":{"integrity":"sha512-RvPcMDBj6CBiDeZDxm6ZpesFbclohG3VL/fInMPcFe9QdCqMumjuyoMeYiGKCdg9c5uGKbB3EKLHyzdhP+WYWg==","shasum":"a65ca4693fc2902645d2358de9e2e50b99f48a53","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001101.tgz","fileCount":798,"unpackedSize":1432276,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfEQ3dCRA9TVsSAnZWagAAFI8QAIXRaOOp17w6Eq4rhZ3V\nN6c9t6+mvcBzSeF8ztjDRuI+K7vIBE0Bzmm1JTZ+cAfbJhnGpQPEpEv792kI\nJ6+Xy219la2Ry0tVd5TMtXK51lqItLO5A/j+40RKmD4s3lDzUDztnCWIuZO7\nml+CHnpvjU4QnYVSLomKMCnyK+8NBUTL9fQVUyUdtyQ41sG8jmhDvN9Lxq+C\nRCS19XFH3Xv6xdYj/WD/KwCW5A+tfA5N6HY+/gJksweRzZrzIcz0Cs6P2YLY\nBZa6LfJbnf7H4W4yEfUdgIAFSxjSADPXzKcjFv0bh2vuld5Hi6yicxPrru1I\n8O/ZYjgwvzHfjeBUsceZGrk5OnvDEeXRSwFdzJr6NvLBXfgZH0TV7NRlRgBC\nnGpIuUnu/zmVCwRvuS0xoWTXiLtDVo4MDJfoojwS1eoRBxMr2fadN/ZrXoJy\nVeYefTPSRAfbb50eEu4ThVbHCd8lWVZGFj5Zc2+xbPYmaJ8lNDk4iqyzuBMZ\nzX9qFpQbnKJ4sVlkmgzaSFzk57//Oz/EUo0bAoYcbXbEhQGzOE+AMrpIDpq/\nPih7RGjcUVzH+BF3EhX7QlfvZvcWQCF28V161AWKfJjKI9mL74zweCs8D7ww\nPowsWKW4hRYs0gHB1JTi0pXCzchA/3jpHxxO176jXVVzWc/NKmVJZF77lmDK\nIfE8\r\n=y/Li\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGzqsmMj66wJT9VoBSZ8/yLT74n10GnUjD+16OWTBPkHAiAsxCPyyVZBOE1kAXzvNl+YCjumAETKQsTR51XGhbiLIA=="}]}},"1.0.30001102":{"name":"caniuse-lite","version":"1.0.30001102","dist":{"integrity":"sha512-fOjqRmHjRXv1H1YD6QVLb96iKqnu17TjcLSaX64TwhGYed0P1E1CCWZ9OujbbK4Z/7zax7zAzvQidzdtjx8RcA==","shasum":"3275e7a8d09548f955f665e532df88de0b63741a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001102.tgz","fileCount":798,"unpackedSize":1438079,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfESoECRA9TVsSAnZWagAAMsMP/iaDrwtwdGhzKOW8H7cD\nICRsvOc/8guKig2hJ6+Q6ErnhTQN6ZF9rnPAMNY4ISd9uuou0kE6d8hZ4Y2s\nYDpUPBLdXIcYqFQxi2HlTIGywpjAgwtEAJnQYEz2u185yhfjXMdGE0aqQfxE\nvHIqvroxDzVgSJRZOfiwkAqgNqXLpRmlaqd5/mhABv54gHiSAnI6HxlDIwT3\nWLxi4kAnpZZeb8Y6IFKCdHoYlRARKK16k/kzVuQWRm4IVzZwa+2eQw9eVvzl\nppQuIrssY1D3bH3UqSjk1LVTXHKIDve+uygctQ+U0ddo+HBMRUemMHtGS+1H\nnbxqw6O6aXs7NAnCU0gT+TeZiEWS5tZEf4omefAF0DtRQG7qwrdAyiX/GlrV\nR1X/ZE5rHY2Q2rkHUfrXuFW9oQTpSVkTv2mxmyi6u9gPWq+Wa1ncqr2Oc3jJ\nSZMDImSG/tLr67Io9hL+CCpVQB6+jjLCZzQ/Rr/1diBW6ev+qx1zYMJVjeJX\nQjuHtulACX8mDhsRk8tfZTYCdvLA+uYRoYmX0DTKpbxMo8eCPiTBXpU6tI/C\nTYbOey3hNEXk9F13ZSJgnivz07uRpjWfY+ULUZe/2jz4/0GtNlQ9OnjFrvS2\nSz75zEKa0Z9CVkd/Azkd/50DXpaynQy+OBNfUobdLDG65ySOnLjMFVafnQPS\nfPFa\r\n=2L3Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCHkrdXGT865WVEpqS+Pnlc7Q8hi/UL/Q6mDwK0dOsFYQIhAOOGikO32Bpnay2/x9dNLT/yp3sxnCG63Wb06LoX+H/3"}]}},"1.0.30001103":{"name":"caniuse-lite","version":"1.0.30001103","dist":{"integrity":"sha512-EJkTPrZrgy712tjZ7GQDye5A67SQOyNS6X9b6GS/e5QFu5Renv5qfkx3GHq1S+vObxKzbWWYuPO/7nt4kYW/gA==","shasum":"fe81536d075b97cd013d4988c9212418faa289a8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001103.tgz","fileCount":798,"unpackedSize":1438183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfE9sPCRA9TVsSAnZWagAAsXoP/iryMA5pxVd26KtVxO8U\nkmu/lp4Z9YJ79yomgrXiqmv4iAMBcTfpBfEY8GpJguJ9yFu8KkDhRQ2fIpZZ\nqreKfdfF2cVMe2yL7A9PlJNz7c5kTE+Uyip7gNcVDlAvScdXM37480WkxoAJ\nWwSIGCBtsV3XF4q6CDSJ6gPdwQgVtdV7R5wEXpRZYZUERt+r9AyYTBwsWwyE\na2VtvQyg6/xa4p2dWAjmHaJOMViPU0F5VlU6ULFivkd0HYIU38nvivdEF5DM\n5k0UbmcUMpR9CR7N5X79Wp75EKNCs1tjG58WK4BdtuOGPbkw8Y+65GCow6mn\nXZ1bM+DL0xkZUchJKoYk4e0dj1C20TlJkD0e47xjc19okD05nPTS4guahkfp\nA2pTig5a/j94+qwYQkKJukaqTWpArQXAIIyeOOOc+5CkaYmidj4+7T9BjPzx\ncZNV3lHv/3tt4LZgmwGrxcBTezUjekA5efobFzW7g6cD43UqhffXoHkcEyjE\n29jIEhgspPrEaxHOLvujK3/+KOcthPyI8Gb8SUZN3UIejOlb2pKSfdPpgrSe\nAOrlsHrOPut9Xg0mMgKUqExRREOHs6kk+R8Yg9YSZBNqpK0AXKF6XvfvUewq\nhI+BQ9LAzkkiMbB4Ii+Eb7dDY1/SWDbwGOvgYURkENHJSabPK0gGmRoNmght\nstKU\r\n=/LtJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQxfvu9YCiKMBKsyYVQS6w4leSMtTfit58U9s8c02WEAIgCNm6uJzEkJpwMd2uvO4KEc3388myn0AV1ERY/aXfN2U="}]}},"1.0.30001104":{"name":"caniuse-lite","version":"1.0.30001104","dist":{"integrity":"sha512-pkpCg7dmI/a7WcqM2yfdOiT4Xx5tzyoHAXWsX5/HxZ3TemwDZs0QXdqbE0UPLPVy/7BeK7693YfzfRYfu1YVpg==","shasum":"4e3d5b3b1dd3c3529f10cb7f519c62ba3e579f5d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001104.tgz","fileCount":799,"unpackedSize":1439335,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFTqeCRA9TVsSAnZWagAAw2AQAIhLr/dHdLj7mXwhD70Q\nmgN4uO2H7hYE8aDQyX+/ExmTxCAFfEitrMTzvU7Hszjm2t/k6R0WyktfYQXv\nWjtWOknJJKvNa8emVn9J/my8CpV6iGGC6FjK6cUrfZZxRvw9+XlBFRsKSshD\nPl00JTvRFZD9Z9yn6YfMPUl6ZT8Ozz2xi3rWlE9/v2FPFHlHO8nKv3XvSxvb\nokWeTTxK8PgJK2n+PFmjhfmNVpNB6tcOpPNRDnr6p62ecqfn017lB/iXOJfF\nrC8kjIv3BQN9rOp69mHo8Xk9zeKNireVCzYA2X9X7rXpQP2+PaYPwq9FPI5J\nXeqWWimT3DOzjKw11nchDRXEidkoPSjvn+Pwgn+qq+eAzMZpxY+aWah34D1r\ngHT5m1LZo038l5/ts7G8sOTHFzyNV02zD61jWRR33w7IyzZEQdhwUyWYn4lH\nkVY2WgMcMTKaQILlRP293I5PavXxH8DkOGFJL53T7BN7UJ78MGF/fOwDHju6\nH8U5LY98IjXTaHNOF8WQuMZXu/krHXTGzvDCV9GbkZzyp0AK9wX3FRTDTQNw\nmldiFeKgT+iHzcM3VmbgbGVfpTyDPWRsA5E/IAKFEiV8l/gyyZ6oJfQxgzGb\n/gaARV2b5j/hGH0527wKhSwdp2+nMv1eGZI+fUWaC2kGVg+MWvS9npvG64K/\nc9Bc\r\n=9CD/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICQU+wN/kLGjn3s6Yl2XB7epWDPaTVtS3Eg+8wFcg4+zAiBrFwDbLLjPpwB2McHqfrN2QTR2Ck2LFRtGDd6pQdbRDQ=="}]}},"1.0.30001105":{"name":"caniuse-lite","version":"1.0.30001105","dist":{"integrity":"sha512-JupOe6+dGMr7E20siZHIZQwYqrllxotAhiaej96y6x00b/48rPt42o+SzOSCPbrpsDWvRja40Hwrj0g0q6LZJg==","shasum":"d2cb0b31e5cf2f3ce845033b61c5c01566549abf","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001105.tgz","fileCount":801,"unpackedSize":1445518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfF8+WCRA9TVsSAnZWagAAEx8P/RAbvjI5/duhUnhS8sxG\nCdYoW4OHlES/BkIq2fvQpMRued3yi+VgZS9g+YXACfzdUtim1lymrL82EgId\neiMxRqgeInNcjbIW7Vj47floKioljhe5gZkqSEnv4Pxn3mn74QRF7R1H+29y\nqK1IpThZsKiBnft+4zHcjP8F32OaPItzbHPNZQ/vDEv8Z7OWS7mnszMwg1KQ\nG1Zl+kkhORLr6z5P0liaeE3QpZTmyJ1iWaYHHL/38Eg9p0JokzNSJnCNNpiX\nHK0BQa21VDIvs0QpUjkB1Zbm5hH0roCsUAt96lA04lonqK/kDyWgq+TZZjXY\nSuvTOnz6w5uaVnDyvJ1Pewd7vKb8PP4d5pR60NxVRIavqQOT0tysOqYpxlbZ\nkWXqylOAp1aVkPa2Hh0wIhlLlELEN/F7DaACS5TVPdxC0AEpgqQNQwVbm1Iy\naSRKOQU5ahf8eg1gDJLLsYNf+2J7FbFPG1+jKZicjUwV2ST8gYA6nVR9i5Dm\nX+4hcWRYVIcAVowsvX33tKNF51iToJLchQtQ1HYhws1GFOmA28Ui7z2p/5PB\n+U7pwpSHFMpuQ5dZAGyglwhv0in3W4MSlF6vWBG+HAQBAnE+wyRLkhwnuASb\nGyq5jF0slSV4eYGRhs1rXrlJtrHmhPYN9joZvuR2yWmt4X2g5TSHj8I51S+P\nmMJB\r\n=LD5m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCarCJIryRkF9hZZp4MgIzCGyV/PpcTpseD0SHmhh3D6QIhAKRSl3e5lkG1R5Pbp9TtOjBA63WaFJN7iPN5dm5cllIV"}]}},"1.0.30001106":{"name":"caniuse-lite","version":"1.0.30001106","dist":{"integrity":"sha512-XqSQKt9Fd3Z9BoN0cpSaITcTInKhMNGkaWtQ4rDnyQU1BJzzWDWCUi3cJflaPWk2kbrkYkfMrMrjIFzb3kd6NQ==","shasum":"7e2132711295ef30ffe5ee45b71936354d105d8c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001106.tgz","fileCount":801,"unpackedSize":1445583,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHLMlCRA9TVsSAnZWagAAL+MP+wW+arax8Qb8d6SyQiLt\nSXaTT/nSucwdOjEF9syo82R6SxORsB5FpO707DRMZ1NE1dMm/Y8U5r/+VEXg\nVvvqOxgy7U/aGYE0TBPvtiWYUxLArxY1J4ikVH2U5FQMLSBABdoWGQ8KFy0U\nnlOyfRSBVjkRKyYk7zmI9RCEOT+7H9CMejhrvKq0lt5QERXWAuUDQPoaJuxv\nlUZ0BfxILohoE2s93AyEOWFNnAffO51Q+TVC+WSrWeo8smLF0JicFR+cIDGE\n+4VrfvPFQfbzochk0JzyKc162v7yysbmrVQXZlK/ynYBlIgQ6Ktxf23daYz4\nBIn9mfZi9qW3gmm0Bot0cE9t+ND7Bp4mccry6Vpv+YCTqtBh6cy3rgMM+zmf\nPK7VwL3vJQbh5slNLhTVuIYMiI346wO787NHpegkGovcf4zkUlsHaVv8V5gn\n9upnM+4EkYjGzTxSvEElIZR3YSpsHRUJV72cUFHW5v0XMhX46QAyWJbBtgus\nJEjwL7tDi82WsSDb+LCIjYNK2SkLGDFHWQZvCHYVo+jx011D6dC2bHSDWiRs\nGA4uBVFOSqYEIPqGVGamDrxrzgl6psO3Ja93fok5yeSIpL+kq0cwOdI1bLiT\n5Hh1ncBEU31rHwLwAwwcszPuE+BMYYDgc9DZaSHkRmWHE9UlIMbjY/8YjkdK\n+Usq\r\n=JGfd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEMCH1QMj1iFud4BsRidTkZnExF7AJwqFIrPJGKm1A9w3PwCIBblq7F6FD/LGsFB3B88aoXC1CDIb70BSEUGWXQGBokh"}]}},"1.0.30001107":{"name":"caniuse-lite","version":"1.0.30001107","dist":{"integrity":"sha512-86rCH+G8onCmdN4VZzJet5uPELII59cUzDphko3thQFgAQG1RNa+sVLDoALIhRYmflo5iSIzWY3vu1XTWtNMQQ==","shasum":"809360df7a5b3458f627aa46b0f6ed6d5239da9a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001107.tgz","fileCount":801,"unpackedSize":1445646,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHhKwCRA9TVsSAnZWagAAtPMQAJzW2Yf2PFlEgovIS9HV\nTvWJWd7OGRH092Ne3XEsLLQB5/8qCzk/0brT1A7IX9iD2PLfapVRKfOMQY9/\nTj+pRetIEWGqK63ggUFLA939dChAVhho3u+Bm9xuFlBr7O06w0ALGh/E0BZh\nQU41T+7FR7KZZcPwJonbGz58RGzQfk2lG17gSsSd6zfYPbLgSIQOzCPcahZI\nNONmVnAngpoJ9P4s66eer4g0kU4tq/daO/TLm4r3pwHp6Wvl+MF+y9yOKUB9\nR7M9DFHZ1/y8YzBzcLHWtRYt6//wkPJqYoLVx/oSxVCKY7IEhM6EXsKVnOUT\n/95Z1EJl5mwOgMeozvJT0AfMPUIMydSxb+89Y8+RzZ5KWRuQG6zMQ8+K0HiI\nEUycEg66BHOshMNpI1KE6At387oWLUaiX5C0dbcR7uM/S6nCGa4CYuH4VkWH\nFohOYwuuxqx40zbx5CdL+hMlRU7jyVWk6rV/uCaymkZE7kZ3hL6JpqRv8Ez4\nwOliGxHDPkCt/so0rBwALcIw6/8AsqPHkxVtGmbTSGuCEDgA8zbHycuh6zDF\n7rCj+5cNfVSCbzdxi8GrPzmXOn5dldUnnKVDQonIkN7y46YmkIoKPRLjRixD\nbUyRp1LwNhtm1LG6ZOBpdYPyO8D2fIait2WvW/ct9SYB2N6qJTryiT0aIx+A\n8Z5w\r\n=Kdtn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH69PEv1ihrQwjr+MkLxRNN2czuWjwp1lAMokwByz7pwAiAGl6c8RcqUgEa0WJl3/Ec5L0g2ztV6/Z2/U4HenbD39g=="}]}},"1.0.30001109":{"name":"caniuse-lite","version":"1.0.30001109","dist":{"integrity":"sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==","shasum":"a9f3f26a0c3753b063d7acbb48dfb9c0e46f2b19","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001109.tgz","fileCount":801,"unpackedSize":1446822,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIlubCRA9TVsSAnZWagAAj4MP/1QrPzg9D+arEwjfXj0b\nlEVfjOXfrBL6TprAViO5s0pKS4UimS5LrsHA/Z3gICUeTepgvUtGGxE19JD8\nyX/7GVKfrool6sbBjFUdR0mMEpT57DnNqdn1Nt6NWXZXtxuQpQSTpnJ1KzXy\n4b/hxsHGo7+qfk72pmQrYwkKF1+0K8GTZetKbs/HieCCHnWxPktG1NV9gPYg\nuh6tDjuIco6TVYEpesgQINdEVvfOH5PbuQ4vQ51Um9zELh2FfEMzAfrIc26I\nZagcORgm3qelrbAlvWa9PvP1ST183sVpLI+WRSoiyhtp6e/fZoJpo66P9zi8\nkht+W7S/WHgJs5T1fPqwMhwdYKsCwYBBaNb4/HM/8Hq0T0WlycHCz8DkaVrS\nbCRWUn3a94q8ETGJN/H1JcuC4fSAzCgT72T7BsQ1Z4mNe939ZmPwwwr/8oZm\nZ8hKE7kxxUnQym25jLsspfDIiTPg7SuFPciJTk9azyZIWs1mtWGRZWQUphDs\n7OftRIoCse9lKfiCOZT50TNQeSZUI/C02WNRCqS+a80cWhi633DNkfZw0mFl\nu61AXZmqNexFRmrVJCLcG25X6Ku09TmXklY/2E9cu+RBnEk8apM5I3BwqRK+\nje31CiUxq76kX//P4joQufjfw7rHl4rmKAiFYBa3Vy35t5yyYg2mYUtkPhQx\n2YXH\r\n=0VbU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGLHK1+lMEEpQhotDNEf7jRYwbccrR8QkeoqUPU/pn9PAiAraZEsbnFlV+E9MiLviUXn2euCiunRnVP+8vVjg4VB6w=="}]}},"1.0.30001110":{"name":"caniuse-lite","version":"1.0.30001110","dist":{"integrity":"sha512-KqJWeat4rhSHF0ito4yz9q/JuZHkvn71SsBnxge4azjPDbowIjOUnS8i1xpKGxZxU6BFiPqO2hSV2eiCpFQVRw==","shasum":"9003e3c7f5a43ea6f1193d4d5acba0bfb152c71a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001110.tgz","fileCount":801,"unpackedSize":1454614,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfKQEqCRA9TVsSAnZWagAAv2UP/2+aBfQ+6pM71Rlx81mh\ngVFnf/ojhdWNz4LaHXSSmf1F08jhwBpHaxSmbMGnb37U93wF/1mrQLy6tq3X\ne2J+YApEenxOF98vuOgUqvuyq2Kc+/zjfZulKRLPakmcQ1AfqljCyGP5Fhyc\ndKB7GRijK5iVr1mllC21bWt7UwY8DfK8hB2DNQ+FlsIIrIPcthBCxjiKecRG\nRtnTQwFoLuKETzQC/9+lxWhWgRMUTQxNwiOran3AjTkryga3OlUtpmeZLIsV\nQLExMn6bGYyCubXpdXXtdlFDFaXM1grCnmXIhD/acBaVLHQMjK7hoC8zgUFa\nVKzRcI+xQf6wxZCK65RP4Z1RV2Hii5wDqbT10Xx2yHfgSTCt0s4qDqJeaOB+\nOeWRfEnSsSnucnaRbDAcsr7dflFrjox7pVkeCwas0/XczPcJ0w3hPmwKUo8j\nFbpDxC9tQv0hiM+byGbROgznvUXPN3O8I4W14yg6szhUcOGVzYOupxwhDmkT\nz/OvoFJA4wISUc3wJ3EzPqDwqF3CEWvVXOfwqnJkdf05AKGgS2DsTx6MefvK\nwXHqBedogvJpgsVXB0ODGI8Juvq9fBX95rjYIh4BiJTMw3Q9WPcozJBk6kyo\nBm4wJINDup0F076kUqgyzz1Jzqs2qSn2tLW//b5Pjah8QH/H1bMakfdywrDz\nZoOH\r\n=L84r\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFGEfthE3+Lbb0+lf2x5ZK2K0yR8WhfmBBIFbNRAL58qAiEAiEp/x0FkbuLkCklCTf4ym3sqcZfn4n9W7PryZSLM93E="}]}},"1.0.30001111":{"name":"caniuse-lite","version":"1.0.30001111","dist":{"integrity":"sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg==","shasum":"dd0ce822c70eb6c7c068e4a55c22e19ec1501298","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001111.tgz","fileCount":801,"unpackedSize":1454694,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfKihqCRA9TVsSAnZWagAAYiAQAIirdx7AwuZA1KA4fl9j\nrq/QXwa0A1VlahAHGNB9LmQadL/OWspb+vC+PXYQ6rSr3U9ofvbzPW1M+G90\nw2kaWQoc1BrIjSMrI0HSUWkGSAHC1m/MEkUn248bT6yNvrr86ytxKcz2DwNR\nR4oxDcamrJahGcvZccZytOauU4b79WvxAQQjt9gnOGRRON5vcn5sc97Pv6zP\nnwWfp3E5Cc+LTM/5REyBGt4z+j2dXDSR40hPmiqC/ONozH0odG8SutlDy5+j\npmQL/CBuHK3NnaWQY4ZHrgUB5Eb65OexbelFm0TVwe1fnLVSblyWxfthwCv2\nk5u4/NASv7me6gGgdLIDBEoTZlR7S62hAGL+wpvUbWBposVN9l3o+JNDccCU\nklcgUd1p4oRjG/F/WkH6+ahfXyvbCeeCRIITZxZT6godP/Wqu5fP12Zp9sW/\neQ/mnLk/axLOSYDDBIvcs7oXB1yBCc2LkarHeB1qJ8UHkUsFt960h8ideNPu\neQaPwB+BhsBaqTXsMXBKa5xt6gsAdxxWQG/e7/8EIbdprTHUMuc6IQDnaUg0\njoiPjuKNpbULPCEcPvPzyX93PE9s1rSQT3G3dLklefKxGUHQL1AEI+JzJJwE\nfbcb1aFZNtp0PBiqFHWSqyafz3MExLaMRhqVD9RNWog5+BaAhTdqWWXLp2b6\nzMiW\r\n=7SYz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCif62oULj304tn/JGhcZ6dByMlewUvhAx4etPmWLTUfAIgUXDiGrHZgf0Ys7QVReSUmvP9BVjFXL/8SWV8a7wiTTc="}]}},"1.0.30001112":{"name":"caniuse-lite","version":"1.0.30001112","dist":{"integrity":"sha512-J05RTQlqsatidif/38aN3PGULCLrg8OYQOlJUKbeYVzC2mGZkZLIztwRlB3MtrfLmawUmjFlNJvy/uhwniIe1Q==","shasum":"0fffc3b934ff56ff0548c37bc9dad7d882bcf672","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001112.tgz","fileCount":801,"unpackedSize":1454758,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLNl/CRA9TVsSAnZWagAA5QUP/Re5oO8p6/gRXp41AMPH\np2thUlBXkUgSu+7MWbeIuPN6bMPjatzKKsfoPyZolqn5jQnqaIkKXhh2zLnC\nvTLWBfzxCLIsfoWeFLXLd4yojUuL2ocTm7uYxHw6B7i8BbFak3s307kAP23b\nLKXzkguVMSeCpQtT3MAcYMn+EVUjakNrYoRouX/HLPxdNrjWj3Pj3otoxxxn\neujZJkCMNFY7KknmTj2Icikc9F6PtGWh9AsJnPU6VEsQvnUXpw88pWa1DLsT\n8X82Uvhafoc1hA43FCVlMxMiMZ6N6OWuo96WRj1KC+owgLncELaMbqHOn/mI\nvq/YiIKs27/Vrb7xXMkSAQYMeuMEnFAKnuk3nAnR/7kIYw8svv3i7h5b6bYX\nSdb+7yminRSZ8Vg7Qyq2SS4/KMhbK5dGjr+eIZ2/zCCCR4mRQDKw+eB9njov\nmjsLatb8JyCzOpYxmWKEXNsmdTenFlLXRlg/PR/NusVW98RQfZopbszdzE3D\nIAiAUdnL07jHalNDlgjdaAPzIft8jh2+ZUrF7JmCMR+/F9blnfkQOHiNBaD+\ns8ZHd+kVDEsZ2CPqejg0IQmZYxHL6Siq06vu0xNp8GANTvjgKaj3bBf+c7QA\nVIuEuvVp0b/GtPNpt9kDxhETVJweCKu6ZkKE3wWnlzHThyz4zw7a5FGl5MeY\nLlBo\r\n=x0t2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYHdrya+MtnwWDEl7IhyizvTcG1cOAQ7b0dHMtZg0O8wIhAM7TAUo2hocZpRE+qo/5KlsUE9v0TkRukSlCyYGw09Q6"}]}},"1.0.30001113":{"name":"caniuse-lite","version":"1.0.30001113","dist":{"integrity":"sha512-qMvjHiKH21zzM/VDZr6oosO6Ri3U0V2tC015jRXjOecwQCJtsU5zklTNTk31jQbIOP8gha0h1ccM/g0ECP+4BA==","shasum":"22016ab55b5a8b04fa00ca342d9ee1b98df48065","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001113.tgz","fileCount":801,"unpackedSize":1456311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfMi2VCRA9TVsSAnZWagAAAgEQAILNZ9WY838Z4s7ZJXgN\niea/9B27QjDOjIQ246/2NzT6+dGLFDu8W7rjRJ+dJZn8yIl+zaIRPbbxMhxb\nq+f1y8jocsByJaz4/HSAlfl01AAyOGMZZ7uqibFNtiwTabafu/HR2weiarO7\nVGu4MpGZYRnCWJ6oBavmfDF1nQTVOc+Hb4uNTFkVzQRq1mslgIssoe7MSKAl\n7GVuroYySDrBuZB8hikWblXeSjlLZv+jqwpQCTlCCsiMSqxWN6Ahvps1fjjk\nCe0PEHqCdfKV8Va6jUAaOpo8sNTKr3PgWUbaWFlgAqW0MMH/3L9MmEEz9knm\nTEAn6kvsphnCY6k5CbgORLUsgjkNJkP/xXBqTU992TB6lZSOkk6zo24Kz97c\nQj6/AMZjpoovT8RYgu0Zn0DuT8inPFr95Ge7Unvf7y4/ono9OmQvwdlCUciP\ntVK9tbOAd8e/4AjTZXCDFEr4O92nfhPzCSf5sfrUCLizsNmkpDRwEFgwlbDl\n2Nw9Vkmg0pskQmoTnqBazc2aHT9NSy6QgXSA8HfeGWrwC6l22VeQ8Ot3GBFL\ntYV01GBdcExbmFb032Guq0H6dV0I73Q13INSadkxWQ0wJxO93i0pTPWkFfwp\nJ1qfqV3cBHjjrhvLq7YNyeH0hD0Qxz3Z7dQpI2a6p7bGDTWL9aQTgyx0nb66\n+297\r\n=Yiz2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEO1jz90nkS1iDzbqj5A/2/LxF8qjW/PaGf5hGqYH+cSAiAbJQ4XNCML0GKZ9PVZHzOTdb4VftAY8JM8/7xxD3E4jg=="}]}},"1.0.30001114":{"name":"caniuse-lite","version":"1.0.30001114","dist":{"integrity":"sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ==","shasum":"2e88119afb332ead5eaa330e332e951b1c4bfea9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001114.tgz","fileCount":801,"unpackedSize":1456376,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfNiIOCRA9TVsSAnZWagAAHykP/32COuJhfvQnzXSRsZZX\n66122wrOa+MAXOg04AH1lvdSxUaZrszPgM8BoELYtwscaNA3Gq4GIt4TG7Rp\nIWYu6dcBU73SkmnW0tFsHSVd7/hf0DazfNaCLXptf89ejP5g2SZBNc/zv7Hn\nNZ0utelDmsepZB4NyYNNdFMJV+2hSpXcxhaDVKeiRrTK0Sjn9EH2GmkVqKj4\nsXD81LxLILVNBon+ahItd7uRPd6ZxEwoBYrCNB+jQSk5sl4slwPNsKI9egHU\nC2cye3J1CVwIzBnHWTMJuH1bAC0MOlTJ8E+WNpv8iZbH/q37jSRKox1sRPQu\nq/jz38CtnB4Qjjd+OLQLv4FkEXxygHZMzT+MolRCV6OnL+GHQGpS2hHThaC9\nFIeSzji0aYm+Fqkmn4vy4AMC2JGzHvBzTvAKROYEQ3blSkStfHA4yGNrMlwN\nvWvlsiuYfSg2xuSxSz0OXvpndYmDlFzVBclX/ytnnWlabGCyNkWUKC/9npsW\n22dqCNUNGpVV8X40kqM/KciMX9TjL02kD/EXe1gzW9+e4yhMxDrhhkiZEzGp\n+zu1/XIV3XOflLS0UaPSpV5liZ4YDpNa7r+gSOYDfSfbDuMJ+imrh9D/jYUb\n5XRqn0KIwdCU2et9HiMW4Ft+KB+FvMbfUMja/dS5KHCxKQeQ4EPNweSl+EDF\nxv2m\r\n=iE5l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDG+9AR5zcLxtMGoTfNwYoxnO8Q6IbdVYWqhVWnHOOfPQIgGDKVqZYzIinptEZPP2H/QjjSMsYATVedvM7/H+ymCk4="}]}},"1.0.30001115":{"name":"caniuse-lite","version":"1.0.30001115","dist":{"integrity":"sha512-NZrG0439ePYna44lJX8evHX2L7Z3/z3qjVLnHgbBb/duNEnGo348u+BQS5o4HTWcrb++100dHFrU36IesIrC1Q==","shasum":"c04cd828883ba47f6f776312e0817bcc9040cfa4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001115.tgz","fileCount":801,"unpackedSize":1456450,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfOz3mCRA9TVsSAnZWagAA5zAP/0ALL34dm9VrE2sFxLRf\nP4XMdAHIGHNhP7Bq1w0gShxlpQG/o1d5j0tJX4W1GxOUxmhB3g2nUpgGMnUU\nKLQdp1i0mQv4VVT8oZrfOWiMPitDKtD5iadBrVkP2Ijff5t6Bc9FOdA8TyqJ\nngs4BtnvOJmLBqFa5WTEE3NPaS3qXHSQwEtYUWghI+SGe57ctMVehFtWZ0Cm\nztWS3H7hsxazvAYauSftsmyqeE8k77NsI87wiTFc8yV/lsSqkeOwJJ9311/c\nqHRjxN26T1XFakMvZ9gxMxj01RY9I5u8ojfrPRaD3usJZqMjnvVBu3l3Uc8U\nIkmYFw3QxypR4JuVQxXG+7/58ZuIa8FRqQxWcmC6Q9jT89bn8iFk4HvXRAq9\nBq8UI5kZzffNLoVNbsoNQLjoPtt4CAdukFAGQHf7xxHFciMOecyeIrnF5R2a\n19PwXCq+DAVmAamijqrcMlI3iVxfWZ6zGpFxEoYHdeAbtZ0lf5XWld05lwTJ\nMrjn0o4Ac2AEjh3ayMVPVcNuX7F8GlmEa3NvCLQxaMyDhTLV0o/Ifu3w9uoA\nJ2gUawLMXl0IzQZHFF3xRdmk+rjOS7SUKh4ZJicFpnx8jaOa1JUJpOpAnoih\nqT+8xj7nNefuBUOoG7w8V42WJQ+ovJYq1h++dIA0Ia0La+J5kLjQehpWUar5\nZbe6\r\n=hMnC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCxMEdL3jxlTffmVEtSBJbWXdRk3tfUI5ONJEgtwQ7WAIgUbc0SvvuwMsAiuuvq7cmw0Mya94ro7Hevrrz8svXRkI="}]}},"1.0.30001116":{"name":"caniuse-lite","version":"1.0.30001116","dist":{"integrity":"sha512-f2lcYnmAI5Mst9+g0nkMIznFGsArRmZ0qU+dnq8l91hymdc2J3SFbiPhOJEeDqC1vtE8nc1qNQyklzB8veJefQ==","shasum":"f3a3dea347f9294a3bdc4292309039cc84117fb8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001116.tgz","fileCount":801,"unpackedSize":1456515,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfPDsACRA9TVsSAnZWagAA9tMP+wdlkIlsPWWuQ3RPfXcS\n9rD8gPe0aS4eSKnTUkdl5GPXsLs7luhX0JEn6yjaxc/CVhJMwgU1NJGx7EMc\nnmoQ+rOTZmJUUY3e0yYDADgfIiOQ6LdrNBolAljFekRUHVgTX05QO8KGKN0g\ncl3IyquEchL7Z3mzeY26UkV9f7j+INUrSgRznWeATOVYmkD/DI32KLQwQhOV\ndHiH/t35mXecD/2rVqDhAPzSRB46thRn3XythrFG5/i6Jre/MBjayUlg30Ay\nU8Hrmo5Tbrhd2xyV8p/7FEQ/hcOg1AShy5XxUCBMfZ3gxRp/h+ZO6BEdl7bI\nbEsYNeTx69ztrWoeoAw8lkovCoC6ql7RUGS4TnkfrZnTyuuUyVOYMeNSh4F7\n3fgpzy0aH/rhIXhJscqnPUOtTLTvtpwvw1rVwUGIHZwnl0ufffgxqDO4ukiv\nzzIUkSuRQMWMFkoChZKNOgKAGAfFfsiXpFIEspX7N6XRdwy4M3EeabnpLEQE\nZvVsbNEJQWfhQ9qk5wvVuzUfUHjSz8fsXS+qX/rmVgvz3k95JmdJ4EpKxtuJ\nG4ULsL8JLH0DN2lq1cRSIdt0yNc6jpZt9j+7geJPOVSyFAXiSq+Q9TqdBZ1m\np0SSO4pO0AQGZeyHKfmPbr4lIFOF3DOs6eZe7DdmkSgrHt7mtYcyyrmP7oYk\nGpYq\r\n=LPAS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCa1nDFdL1+0FySwx/rDv4HR5yEUStysDWK5blRcbxNFQIhAMbqHzsk5EqDHAW4OmTeOnwNjTpmV53OUFevjr68iK9i"}]}},"1.0.30001117":{"name":"caniuse-lite","version":"1.0.30001117","dist":{"integrity":"sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==","shasum":"69a9fae5d480eaa9589f7641a83842ad396d17c4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001117.tgz","fileCount":801,"unpackedSize":1456597,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfP05/CRA9TVsSAnZWagAANGUP/0hAGnk0MMYX+wOiKyUo\nZzHsNWvPlqZVtIvJ0QWw3531wpSpM5GU6+wvbL82Es5rPBfE+RJvrqP0GY7E\ngQVPV7qX7vsvzboH1jVG8e71n/ZzrlJSpsJIv46R9wUSe9pbryJNZ+OlHYR4\nkFCe/3to9S64/mfP3PMiJ3D1TKShzF2OPZi2vr9ws1N0SGSWsK1CsPGZmwFD\n/4DZOkLQnGWAw8js2YgREoYKAM6YbWx9bO/x5wShgyJNmpSmlyLJae+0iHk4\nH6z/3m4eTMM29DA6bz+3kvT+JbudtRbVY9HXRvWWMMlLflFQ1yX2wTu+pLrO\ntTiaRN1STTNr3wNsEYi/qdiVN9ZOgppbXflGsyCfZrTy5tXSE96wLL9p4xQZ\nyPtAcEWrJtbmwrhpLcXkmUIzz3935zpqUoV89F4ZvtTa5qytqynG0HTg1ETt\nLKzkrUAgzV8bh+WDMRv+JmuO8eKkgKX+5avidbszewT7xOIdL2INE84elGCJ\nOHsKp7ecspZH2YlgbEUjYyoOMi24UY/X9zBH+IPMPq8I6rc8hcsx+47adu3X\n+gQ+9LBg1leDBnScpKgAMf7NjL5w0nfRJxwxeigTYCOqKhRhImSZeY0eT2jC\nnhxdYN/ktlUZnb5A49HS+cbXnqzqsOiYFOvjKQdTbeWm/PFlyPt2rQc8fCho\n0h5U\r\n=0dlF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCX5dmOiAxI48QzT+2MbcASk8urkxtsK7qSBHx3cdGKtgIhAJS69TJUipe9vNi3MfG4sSN28QuFgXIGTJK5kMrkOp+F"}]}},"1.0.30001118":{"name":"caniuse-lite","version":"1.0.30001118","dist":{"integrity":"sha512-RNKPLojZo74a0cP7jFMidQI7nvLER40HgNfgKQEJ2PFm225L0ectUungNQoK3Xk3StQcFbpBPNEvoWD59436Hg==","shasum":"116a9a670e5264aec895207f5e918129174c6f62","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001118.tgz","fileCount":801,"unpackedSize":1460005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRfQRCRA9TVsSAnZWagAA39QP/jNgOS83+qW5awNXrfSs\nBPMDq/STpJ9tGjSyhDVybTx41tJ9qPobVe8GuSYK16ZzUkifRL+uPBQS8Hfo\nvuXdTDRvrwFhTAZZF/Sh+nf1uR9Akz3Xt+dpThT75bE+UafUIoCJzlhnr5Rh\nfY52s8SxXxzq7Pzi2oh9ipKNPFVi9gw+tI6coDlqm3BK6PS+7vlXpT0Kea8z\nUCJiEt9iYmopRr2TsAQHZaMdNqPDYoavvRBLT2Od1APjjUcKp/BznOC59INz\nRNAIUq53hRypaBBlG0eHKuGvHkzbHD8M4Pguptubsbtaev6ofrXVmh6wud/8\nEctyKa+m9XHzo4skRTiZHUn02erWI+Hfu3+fTVXr84YYVwQsqY5dUxCiSfEc\n/8WmMfqKE8HEWpfTJ2zcAi1nm1BU8osege8EFiTDKkWurfiTO4WVcavWIMiu\n7/kOTWpnTyONikaJqwlp1gEUVxEIUMwDeubIdIuy4NFx9eJnH5MRB6aHK2xd\n7nzxMoYOxp6RiF1vR2O785zJqegV/uwdr+VMVi+uo8UgOvnV5h42ZZO5DvUh\nPTXuazuqT5U1HHM7nXWV36BvoykMQ2VZXxdDKCREZkbHmK6mDOuEPPUJUW6L\nN/JlAmSVuRUsonszJsAWYDQPkyafd8TL16DSEyQnoIeAF2nqs458TPSC/g1c\nOCyf\r\n=kQjG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6yFxhLbVgNXi0rq818FM9S2mkc/eiyZDkQA10PRaMLAIgNp07oLN/hZdLQUlBQuFoPlSLYVJyT2Iq26e8uASO77g="}]}},"1.0.30001119":{"name":"caniuse-lite","version":"1.0.30001119","dist":{"integrity":"sha512-Hpwa4obv7EGP+TjkCh/wVvbtNJewxmtg4yVJBLFnxo35vbPapBr138bUWENkb5j5L9JZJ9RXLn4OrXRG/cecPQ==","shasum":"99185d04bc00e76a86c9ff731dc5ec8e53aefca1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001119.tgz","fileCount":801,"unpackedSize":1460084,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSIj/CRA9TVsSAnZWagAAwaAP/17tO3PIqRqI24VPrz+M\nTmiAWYbb5sLkV+FDlThMk+eW95QLFwIQxl0Vs+vpxHdUMoKSCsDlZ5iCIFC6\nikNLJ61IOdGyLqowdDFmB5JEFsw1TvC6RMDNmgnCVbHetcLje95ft76U6UEh\nHyAgvZDXj9SHeO9SayJ+ahwKeg3p906om4qHjiD+sbopxU9vwtZkYLe/S164\nwBRC9EiK8Fu1vzoYdd47ywjL50NLAGUelyTBKwOOnti/V+4QwHE+0eoxnfkz\noTfw9zjcGDVOGWdYT5uaOFbZEx7gqwjmxo7aPSpKggzh9JYQ5e0jAs8wZj6d\njrmVBva78jw98NQfnZDyOqaEKgxoiPLnC30gaM8rGBnuzV/ve/r4f5VKqDtC\nO+DGAwBCvFYIXOflIH1jOeLP+1HceTnxYJBDXXiJCuCjBlaAvc993CE4AdAs\nNnxN+yGwYYlbj+zGJ4V3vXg7W3jzN63vyAsk6OzPOmbR94V8Z/A264i4wAw9\nVsOQ76jBDgwi/iZ/LRgPDzdl1+WOdugd6vRc/v0MZE9H6CCw/2so1HJxRq80\nomFIYBGxakI4zv6n0vp1APBHb2DzQTYFEvfhq+6m8t56B7soyCWnNTn7m0sr\nXPNN2A5Qyfb9/xuNSrOueiNbNoW0R1vFnwUBsCsTnXx8dabwtZJLCSB5fi8M\n70LW\r\n=Bphm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAmWFrkwe7DmHYQDUoqPY64umrpeUriRv/VzpMYmHrIVAiARvKO1Aue1TRXihC7VGFDjdYrQmQ45f8ytXOHbSSSP+w=="}]}},"1.0.30001120":{"name":"caniuse-lite","version":"1.0.30001120","dist":{"integrity":"sha512-JBP68okZs1X8D7MQTY602jxMYBmXEKOFkzTBaNSkubooMPFOAv2TXWaKle7qgHpjLDhUzA/TMT0qsNleVyXGUQ==","shasum":"cd21d35e537214e19f7b9f4f161f7b0f2710d46c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001120.tgz","fileCount":801,"unpackedSize":1460140,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSywECRA9TVsSAnZWagAAa24P/Rbu3hMFN307X+JVaDif\nt4nFHkQNHMjJM7vcQAf4rBpBW7RA7IlLIZOJjf1ukDkJN8Uvw3HhBRp+fE8a\nUedKpO9kKU9SfFzN4LUcknzME98H1H/GKWpj2TCz4R6dTPNDg+dRR1GKkXY9\noNKKtMLtoQClCPzlADo2kdRh2Ov4yicZU5wEpgJZdCmMadx7WMWoWDWgAOIL\neK5RFrbPZ9uL9wsScbMQgVdAZ4Y7Sp3kd/vZDmIi4BUiTuRvP27PpDJMYSVl\nv1JAyMImwpQDv4sABRT9/5BezsS3mvbWYfeeIyQgdm39ZkXQc0FCGRcMnWoH\n2Mg2uXr3IB0gqHq0yNNSeM2C0iqEL7pZZHsshM8RTLRcjn+Psg+0YP8r8yV9\nujwEJ9Ndmj35T8nFnBt1le0+mYZzuG0SE8GAuCsDCQ0J8ML0B1cC6ksaWJVc\nGc6AAZOuS0o0h1uasV88GsTJI6tOS6sCgj6RaPkDcNf4tJRHUPz0AXA98d1w\nu/1bPb2ijGh2t2hGRZHm4X+i/AdrxKlU9Pe1wBRaNV8YXsHoONSgma/JzqXu\nVfwR0Wg9eVbe/h1P0VfHUUPICGOHNNYt6htHtIUYe2ijalC1O+7FXyCVotqt\nALGy4r8d9Jw5ofNZeBfBuzCpOXD63und7FMWkC5Ot9H8+XF7adOPf8m6y5w+\nkdX2\r\n=bs49\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICt7eDcKKwWRY7QfBh+AMBlGTvViSC3Bc+g28OBiQpahAiB4/F6q3j3Ue248bFmhvevxEkY5uq6E1YYkt09MqNcO+w=="}]}},"1.0.30001121":{"name":"caniuse-lite","version":"1.0.30001121","dist":{"integrity":"sha512-s7C2DjrEbm4Z7Gk0iSG6q0tF+dqn51G3IILCWoIrF59EQomHpcJHCNo4ky1W6c/+dsEPAdqjErSmnw1YCY7ndA==","shasum":"2fb1d256fe07df8ca3f84a6bcc2f5febe53f4a84","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001121.tgz","fileCount":801,"unpackedSize":1460206,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTd0NCRA9TVsSAnZWagAAEDQP/2Iqju3qluu2dWGqfP9O\nydaxPhHdJIEdaSaXTQA+YESv+X3JiWzjPaEDz/4MkvuwQ3+iVNbRRspw1Hhg\nPd/xQ7IsjnwIWvKOmGC5FOwDRYD9le84iUyR1RDmicpLrGBtLhqIWsEY+IJf\n6+0oWKtfZk9hgrIpFyM96h50eCHwebVWwhcOZRC5ZYLRepIxvfgiPMRK8taF\nkNUJiQvTatk5XWa29fP7P0cLx9yiAUGiQ7tEY+WKiOBVpnM33/LeqHQFowfG\nqDtgsMwdKN+hjQ8NnOf/1PrU9AdyNQU62ueMs62yVEUxfNVbIXy7KQptplRj\ncXnoILwlyygasQNDNpUlrA30sE3OrWbQMimHmljJAcyb6hhn1NomK9Uf9SrB\nvKUiCjErJpSGhsNbq2fxa1S/nRz6C5g6iBsJNFOV+uXEwh14qncqkzcBg84U\nYCemjRww1BAJNPdD694bI/Q7nJ1My2Y4d16vwF9Kj9uWskvjZVQ+Wdc79ZST\n2y80+/1/mszl8KhG7wGoB+qvIUM2WM3bD2X1EqgtRx6lzecQW0ebusxCwqbI\nZL+uDU2VwJfdpQ1vgGImf3os+aOPfvS2xBS/DVdSwyVqvD5xdO/TuMjhUiiR\nkk5yH4TOMBzei2vrHpmSrxS5kcmIS2wpPNuckZ/a7SOTl5mQLRMyn3TtC5yT\nnVFD\r\n=A+J8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEl2KIh19E6m7Ivmp3XUHDZEtv8bv7hk+6ZSxZpzd4yaAiBhBzux+u1J2DQ5yiRDV7eLaERDktabJPSSlcnnus0YXw=="}]}},"1.0.30001122":{"name":"caniuse-lite","version":"1.0.30001122","dist":{"integrity":"sha512-pxjw28CThdrqfz06nJkpAc5SXM404TXB/h5f4UJX+rrXJKE/1bu/KAILc2AY+O6cQIFtRjV9qOR2vaEp9LDGUA==","shasum":"2c8ff631330d986a07a7ba7125cce77a1373b475","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001122.tgz","fileCount":801,"unpackedSize":1460273,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTesbCRA9TVsSAnZWagAAQWMP/iF9dRFIe60UI5NAo1uk\n9FK4N8PPNmc3qDrIVYoge3kLZO++jAFZaXBMlzEG1JQwZkfw8rkqDWGCOduJ\nh9l3zGJAsvdQgRrlu7UVyT6Qc+tOiXZDA0XpGnP74ytiGScCCbJ5kPbXWp+Z\nnkcxMfb+3+HKZ3riH6Xb2PR7FBMWy5NAg6ktBxiwkCN7irrP0xfieORmABTw\ne7nxv83aJAK1V2TWxmIHGyMfswfAmkqkthsJqdAYg8A0RCtNVJPwlZ4zy5oA\nYm6DONUAsGXbxoqZ/0vz8WHa8Y9o8XGpmkK4R23h5CinFbxd1qEKuYIgw2zb\n6R4GICT+J7HIj5T2Lt1jTBwoX3lxI/j5a3PffsKqWe2tQnfB3PUxM87xd4bZ\nWetQc0vImnSzrL0D+7237t2rlq6z5e3I9XuaWUqU3ymXxsZenQ0Mk1lOs1K1\nSjhciocvW8oz9UqBuOtPOXKo5tAXtIuEk3pcWlTM/6kSAEsSi4DOloQYE3Xf\nTuopaNXFuye9223Bs8lTU4Pc0Rm/QH6PDxN4MZP93kQnH2IXrjzvYd0bIYLC\n9EgxO/tjBKbd7bRlZaqfvyZrBBQh7keuahDXREBU+nmPHaLW42VtowIdXW14\ng1hLZ06iWFsfwxnnBZTeV6WFUYYe8qC5AGV2luKTObDNQoXnK8HMbdb/L7ls\n2lMV\r\n=Guji\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDAx7i6Mfy/voHotkoV+5qHaySgsZCI4cLOSNbo9lq7KgIhAJfpZM00/OpOjU0qVOT9WDB52/Fq46UznFgQ17ySlge9"}]}},"1.0.30001123":{"name":"caniuse-lite","version":"1.0.30001123","dist":{"integrity":"sha512-03dJDoa4YC4332jq0rqwiM+Hw6tA5RJtrnZKvOQy7ASoIUv8CinkcmGhYpCvCjedvkBQrrKnkcELxrUSW/XwNQ==","shasum":"7b981d81382ab2c8fd062f3e6439215e8c503c22","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001123.tgz","fileCount":801,"unpackedSize":1460340,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfUI4fCRA9TVsSAnZWagAAKYEP/R7tkGxvmwBMU1NGsfwP\niz1TrgWbt9NfAVsHog6NQvLZ+KBf8ezx4zTGVSIKKpKRoIw1U+QmwCYqOGh1\npE5c2NBsh90603bzXYeH2AhDto/quNF2/cVrBstrKSdCNH17tYltdq32AKZt\nEHTbZtHmPR/IuJOn/wlpgmN9IOzbyJUOFnnimoo1FtDkvENw2HcoX4+wFzxM\nAVEnhPWe0iR6BTYo0MNv0sM2my3iss8HIlE1YfxNYxcHfwOj4FJzKxuxZvXi\nu8aV3innMioanv+WNf6qbeeg7Hu6+ivhcw4zYMP4WCGNyKcCrhDw4ERwsvwd\nZoXUpOnv8slzlZVmtrKuj9x6OiraU1mHfI6ia7MVpYAwbnldz2W06pD8n/Jh\noqyDpqybMHYUNR+QxVPtkAwvw4ware+AaURHLihvpNeI1KEk0g96rpnK4drL\nl9qK9Z8yTsrFhYXJM6LjsG3qxoJvkkdLhnd37QzF93gytyxYo9CfSsIG4paz\nbJlaDOjSvpBHU/lsSWnpRFr7llp1oPUwIs7AthbZjQ/m+YMbEYUFnf8MIPHT\n3lJUyftOC2IlBLPTBM/k3CgoRDIzC36bDl4L1siuhsH5JHBqS01tJvLUonY4\nN97RppdQbHlJCanHEBJbKlc7K6KnohSRoKRS6Bj1O0+9U9b3I1eMedXxSaEK\najCe\r\n=0k3e\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHgMMLh/o0Rk2VTAM3Ac02FOs6Tw14/RSVdtw3N+2wBDAiBQQY+WIMtf5MkmOfEmRqMChH+8TbAH5ZJSVYEue4vDXQ=="}]}},"1.0.30001124":{"name":"caniuse-lite","version":"1.0.30001124","dist":{"integrity":"sha512-zQW8V3CdND7GHRH6rxm6s59Ww4g/qGWTheoboW9nfeMg7sUoopIfKCcNZUjwYRCOrvereh3kwDpZj4VLQ7zGtA==","shasum":"5d9998190258e11630d674fc50ea8e579ae0ced2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001124.tgz","fileCount":801,"unpackedSize":1462044,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfUdGUCRA9TVsSAnZWagAANHUP/3LSf+8U2zWhkPQlcxPX\ntWkKowiaDXV3Vx2QvkhX7l2janGMVg50BolNB5m4Td6OuB2C625owl9zKwl4\nOM9YjdnapjsQUy02n+BqZR6FTse8DhlSSzS4jpDUA0LseAbuMTSDYhwH10Dg\n4zAk8FEgaHGA4QEyt4DzaXJvYWmQhXs/ca3QdUZH2DGo6wy00xDoWH2qgk71\no1yUTiIYSyGXpdN+wY6tXD4kB+pzx15dQyQPxf4pKyfgjsMhDOLk6fsNCcqt\n9p3nVMcEqkpb8drRO4IYRo3Z2LT5MaV+hBBzEGCkH2VWyWfQ5kLay2WyF9ir\nWXwktI4BoFwJGJc8Fl88y5vm3mhdqIn83RdCKJW72hLCT2BvJ7raxwlnzE3s\nfO419C151dnWKvfPDMTKVwTlUjekacQqqzIg94vGAK5CyB4Gp6LfW1r/ymFn\ngjzYLNam9PfayUIhMtttGTIYBaUdgQFtFBk0OnVkBujcM7s8hhbUwTO8KjNf\nN/NxfCFYQKx6kGMrcVFEWRoV5FXLRR7Fxoa8J0V1gsfiEziYbxS8qPDhLF1C\nG62GAOLlqkldV0i9k1kjxKgKWMiPScfDo0VsaRRafYyIYOI3PzlrX9wb7y4h\nB1g+SG79LSOx8oNbpVzWY6NL1U/2eh2FfxapYSkZrc8tGIBMFSF8AYSWNNTl\nepsq\r\n=+Hdq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBktnqvAhnjpkb1UWLtjBrUq7hwUVXI6La7byMF+ioOcAiEAhT0+uvulGBWhiGq/bclZ/rG9Lfj/HP2Nt01yE16xWxU="}]}},"1.0.30001125":{"name":"caniuse-lite","version":"1.0.30001125","dist":{"integrity":"sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==","shasum":"2a1a51ee045a0a2207474b086f628c34725e997b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001125.tgz","fileCount":801,"unpackedSize":1462084,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWHcjCRA9TVsSAnZWagAAz6wQAIdlnIhsS+6oMQ7FIAAy\nYq86hNndadaQk4xqsLrEVE9/+wpVAyjXmvxeFpX3KKY2+66Pv6hrCqAtgeia\nNwrD220O39hYuCdWpZjnJgtmP4PHk2WfZ+lPIUy0UL9qinZt1WrNMENfIhn5\n19OPdKBoisYusVcfZwbcWViCP8pZCdG8IRL90x7UhWraSowB5l+ECg79ZA3v\nlcyfCuhiuz1hN1dCyZheULzIeTLhdryn0rccod3wM79365gVl4FnOSb0cBD/\na3W8PnsOAIMq+xNz/p5IPWU+xdtCozlP/OLFxJv1TSu+FiJvgISxYDWfEyqO\nt8yq8dHOK+7cpO1TdtoSleSZumakZ69hpM7e/Y58OKXyfj5tGd7lvsUCCwPZ\nq+CFivqEzAWpV9Ty/m/H+DqVDObIXAC13jfCVBl7UNMOy9AiFinU8ZHDnkEM\nQJF+bVLptgk+X4JV911p+5ENxUIryOnDPmVEacyzIStjfHrdMj6ymPIJZ2aT\n40wjsXf9ehtSC6jXbXXqy8rU9XHxOmB8j7Y3rATlAGQkNda4p3KaDcA21w8X\n4EezWZl7hLLRc1yCtxWOe3bSDrFk9vv+wxg4fATcfJfIp+qQfZ6WWtu9DcIH\nKx+ZF2F6+7jTpeX5qYkbz0+VMXvJjhjaWE87u9c+bmv7YMPyhrKkuDxi+KON\nyLv6\r\n=8dMI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGTrzxW78hx1uNOP15Znzw62B0uz+yoxIbpuNAazV9HAIgO7Dr8piVMW/bNzTPqls0U/N+AZgq6WYWrFrm9Sn4uK4="}]}},"1.0.30001126":{"name":"caniuse-lite","version":"1.0.30001126","dist":{"integrity":"sha512-l2odlsr1zB8PLR/rMyX+pi6/bWsDyCT1MrKyIgIUtJxkDkNY5bxq+hu1yOA7EwZ2O5PiLsJUopqLP/2d5xqXhA==","shasum":"d28fd23f3c7a41a4e6a108d536bda58ba52c9cb1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001126.tgz","fileCount":801,"unpackedSize":1462168,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXVq9CRA9TVsSAnZWagAAqYUQAKFVHEqNi/3shToqa/Fr\nMIZgF6U0mM9I70Co7zjV8UljVTM9FCZNpWyfW6OnWnHd4iw1pFigA+T1Gh0n\nLzN/X2CBadETKN9WM4t9MMNOdTRtZ9KITMSS1MBAlVqk6elj7q9WxRAVAGrr\n4JrEp0YjzW3Vd1P4uUrNAkiEbdc6xpWRhdjNVEHQdtIExuxBLtGxJgaOKqsA\ntdswPRtKAwK2ETXMGHG4tCJa0e+DfQKjv6AnM1Aqskye39KCxpNUe7OdBM44\nFR7dYTzv0EY2abw8wiuuc7TjZnZkCSQ81d703pIN6K+ze12Q9UmDQUjCr3nO\nX6z0+5eVXG+EKJlWnr4tmRTxyRokpb/UuzgpwVh9Pa4r7ed0aTpBwCBYXiDk\nV3zJOQPe62oP5+2zOelEntACPtG1S4s+ZeiB1nDYlJpk2Xiv3s08DnuwRYcx\nmy05aJERAFc2GI7tcAkzoi5KvleLirp116LmjJMpWdxTaXBZRePBTXfn0hTA\nw9wl68nOd7AXxGSWP7u11qr/A6RqegNCa9LnF/CHrVUEZgkZoWngMd67G4e2\nMA3n2t1j3c5FG+bo2e2I95JcTN4H5oBnQcRuj3/kIDmuGPoVKYY8eCIrjNLz\ngZAObp6+GBQfen3+jNtnkqxBV7uY2F6SaWPMIkkt0Cbh5areGy6F+gHWYZL0\n3rDS\r\n=MG+F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCb7ScFNC4NsncmWBEoxRjD8XTTJPZUL0FYNBoSZXKmrQIhAPnks1MHDUXF77jEsCJTV+hdmr9GUHad999NowYmoPlV"}]}},"1.0.30001127":{"name":"caniuse-lite","version":"1.0.30001127","dist":{"integrity":"sha512-S9jZJfOcB0Li0TBCBPyOyVmRmxXnW6eIjvxNoDPHpsHxQXESlpeS8L3GIFMn4b9qRte6NLqmVNLgILKGnyJIkA==","shasum":"fdbb5b2dc0ed2fac91afa11f3c8a2ddf88dabfda","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001127.tgz","fileCount":801,"unpackedSize":1462256,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXa8aCRA9TVsSAnZWagAAyywP/3evVNxDtTg8Y//WkUH0\nE6hxF1reUEhdFHdV4kx3cqXgFjqYcwD3MooW+5O0sSq9GKSczBnSVzz2N5Ka\nZhUjg2ZVROBZqKjCUDFY4kUGYxnFTJC9F99GIpLHlt6/hDe2O2Wo4myP1oT+\n+EWPDJG7Ch+OTyVAG66ZzFE5+4PRV8lwJIpNIkhUfi3yjJdvLOGwC5j5vU4e\nmW/Kj/DuMOhAWtfrXMruOKjY8X9TBPYSPlUGUhOASl/9t1HDNhF8F32zqY6o\ndxyyyGpYD2h4etvY40UX09PaMemBOiiE3bFNkMf7dog0pOqDKMhgIP3SiLen\ntABtO32FxxXU3lc7pnjqF1q677uLVNe2D1J1Yk3+GVQQGV9ky/pwtaWieRXL\nhV/1TQ6tF8+f8supZ3wJAVBc1JZBjX8sE5BVbqDPNthVyfgp2WW8yj2R79NQ\nzMdL0n6xQUuyqhW4zTEScoMOt0ikNOJjg+p10IviGq9h55bf2C1i8UF1sIqy\n9HjFCZSwO9/NsImcHbEbuAhaMD3eO0zNAuW3b8Uy0CJv0V2i3a84dkvTxTYC\ng4pq9cndL3rzSjg6pxlM2/PZ3Cfyya+CUHZQmjwomq8plpmGmWg5ENmSUIMS\nF8P+5pQDas+5HDycTpgLSOBId62vAr2igHkPPzC5VPRuYwkrhoUZPrYmS+HL\n8rUs\r\n=274Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIEbVXMfuhhIMg0igRd+wZjqoqB7EZrp4UkZWBv03qPgIgVICK/LlFmt/kly+fMVO10Jh4MVNp8u7aNBrs8EM9c3A="}]}},"1.0.30001128":{"name":"caniuse-lite","version":"1.0.30001128","dist":{"integrity":"sha512-ocjGtRj+4wP6XTEIn2AGn3ebd8nkFN3991GlZ3ubLrjUC/w/YGgBFb5iy7CHr5NaBZ/pfo0SrctGRDVUbGgpzg==","shasum":"00ea73610bc991a92250e958837c197734be7029","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001128.tgz","fileCount":801,"unpackedSize":1462324,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXb0fCRA9TVsSAnZWagAAvf0QAKFCKEs4uD5NOK/owM50\nCRPlQ2s9raK4i4TNtPEPW5ukMoOXbB8ZQp695JwSrl8UHblBgwWlmVmOIPFF\noAhYNSl48Bpqb9W1CesDNnoIxF6+NQ1YuDHRdQNQ1dYC9ES4qISxEMtu2O1V\n2mm039XqUpQbSlZ0TJsj4908I7BHPEGSS3WShBAfBHNkVRKmfiUTjE2dOYGQ\npqwZwNZoncOiIOHT2XZ2j8gCScU6IXDvpS8rfVNO2Kgqbdfq19GxryJOiRl+\nfJfUqdb8eXDFVKXqp/xM28GgwhrAOrtdftlu7t1wui3ug5/azsAacvA5c5+b\naTdYHqUKtvO2fqckvSKwGDvYO12hwfX1Aqr9vzg34wQZUY3g5TvBFAAddOGa\n3ctUlbKlYpHElpRCLh7n/6zEYtm6tcr+06r+MWKiqUsg6vKVmvKqnfk0rE4Z\n95IyJXzQhkNR7DxHFJTNhAcyJQStZdCp5Q+ehmKZPVS/VFZRqH01TB1QlLDy\nbd2kYXf5FUd/HaHa85Iwe+tITi1w/d501I+VcTwO9gnBfU+hdd854bs/80kH\ntvmiwbft7Jn8XZG47/XZrL1xFL3NMrSOaHSVwnjyfh4YES4U6WSuzClTkqlk\nRMqpxY2qrN8GndHxjIPZDYkalmIxAecC4Oy1Tg1FpmwUFzDyFrmi9vUgT/QF\n5tsS\r\n=eZSu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6TMeL0xeWez8sVdDi7xKhNF7WAJdxvgYUENHkYBCQ1gIgfv77OPelL8zdrEQPhm3vQ1m1GoiQ5qwH9+0/Dc3UgJQ="}]}},"1.0.30001129":{"name":"caniuse-lite","version":"1.0.30001129","dist":{"integrity":"sha512-9945fTVKS810DZITpsAbuhQG7Lam0tEfVbZlsBaCFZaszepbryrArS05PWmJSBQ6mta+v9iz0pUIAbW1eBILIg==","shasum":"e6514b94c0ef50f98cf7476daa91228ddd2ef7bc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001129.tgz","fileCount":801,"unpackedSize":1462402,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXnP2CRA9TVsSAnZWagAAmlIP/RqJV69oaybY84bcFZYN\nr2CmCIhrwhrM5xxvlIVsu9u7zqxRVS3FAtFq+4cIGSVREhSIYbNpzYbNoHgC\nIVk6ajfgZcbMs1QDmh5OdtUwOH3iw80rMUkVB6N0tF+2pJXAFysZwUYxq9IS\nvpKoQHQXgawS74iVq4Oa+OTmCa59OFP2a3lViCxRYu0P+yn5pUCZKYkeqkSj\neegTpNMkdSaPa1IqhJVYzpFFQjacLU+mkHGtoJnsWvJvDXKOaIES4pUp+uya\nDt13Xol5apCgy9EvX1t/yoAABs9drqAM70uW+GcDTYP70+OMslzdNJVmx6wT\nLt7yHnTB+7tkMta1zg7HiSNMYKeGsZbz4XeaB0Z035ZG7wvbRC/kM9b+dUT5\nN5egUQ9T6vo/hd9eYmzRN+rAkKkRX6AxvrPSHErnpjW3vhzlw6jKa2A9302v\n+g1gjveQPk80Za/aPmpmHSV15tjeSqoaOqAXZjZk7sYjl0sC52dTNfImtT2w\nQ1sgX/my+FC63GlqqoWWq2/GwYqgTW0Df3V3sJaLFCab4srotDOD2kJM2qVm\nBIpcBpzYr73No1fQEEPsS/K4KDHX/BhxWSRmI92p5pFiLP/xad4Xq8zfUhbB\nutqJ0oG2M32OHeq4E4h+Ay08FR8xgUV/bq3ZJJP3KFnTM1ElvNOhfo3ypMI2\n7RRK\r\n=kMhP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtbJCjK+szk/P8XibMeaoF8EMcENhtydmZ4797kx/1MgIhAJmdW5J6HaCAcsV6F7mEk2hT198cB8ybFPoJ28R6cD5F"}]}},"1.0.30001131":{"name":"caniuse-lite","version":"1.0.30001131","dist":{"integrity":"sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==","shasum":"afad8a28fc2b7a0d3ae9407e71085a0ead905d54","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001131.tgz","fileCount":801,"unpackedSize":1467966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYGA6CRA9TVsSAnZWagAAUHwP/insTnYQHIbj2c0swjTt\ngjG/wLHWkGxQ8Fts5EBFJ4dS/hg0LmmNIh0Yw0GdtUMgTRDtEMYT14IUI2Mo\noC5+qtLmdpfJ9LDKYBh+Sz5fUqx4WMRvoML9psBIb2sA4tIiuldEKDE5wWn3\nGtED22qnU5O4PbmGggySxbpoqmz8QEOJaYMv+cPf/W9bCBDo0yqXPhQlpcOe\nFBjSlNFq2s2OOfThAC2Djr9/OlUARKIOWRjw4OwYIzmgNAiPF91OY0vrt5Sp\n2ysdeBV2l6Ze84b0kOHeLYixxAejZBk+Y9LsWEd8ao3nTaIAc1vRmWReNnuC\no56VDqDsQI2pMzw1eMJX8oAJ3yChVsNmmHSk6oiD4VC34G2kvqMqgpqbkay+\nH/Qb99PaA4iIhWUSmzRWo2OXB9QWsbEALN1szdjzLI6lHfwFds4T4E2wdBTO\nd6GRFlgJqYedTJg9RDNJ1wKSG7XIaoX69Dr6MCNkw9GzxOvFtD+xHd6MCZ3N\nSHM9TKrcg2anrcUMmA1L9Vka6+WmjCjAohShm9NUhT8HHMcUqB5/6Ni1NVA7\nnAhB0x8t/+V4CAt521SBYvUM78DLRWZBGurEQ/G17VkAuN7Urf0bYUM63OGd\nB7i2hgicsu8ArRGPCi1dpJK6jr0MwneRcHvzUaLOdxeyMpPszqjpon1ZupGG\nL7JA\r\n=EmOg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPgzJ+dDmdPBMaGT+J5PKBz51+AsEmDaabPeLsuTLSLAIhAMI4gw++2UJOITo+ju2vI9aMpEFG8IBYqrkVHedxfWd/"}]}},"1.0.30001132":{"name":"caniuse-lite","version":"1.0.30001132","dist":{"integrity":"sha512-zk5FXbnsmHa0Ktc/NOZJRr+ilXva+2KFJuRiQfnjkxJfV/7DYP5C27lSQF++/veCUzVWE5xecZnSBJjf6fSwJA==","shasum":"309279274f10d3aa736aa91fa269fcc8d0cd7ef9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001132.tgz","fileCount":801,"unpackedSize":1468657,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfZZiRCRA9TVsSAnZWagAAvrMP/1w19V3o0n+NNQDTU5Se\niPh1wkOCeBLpLzjEy6AQtlu7faIUJPb+hbTdMh6mVaaGhbdclKf/d/UcP2Eu\nViycNjslUsfizfyXs37iiLYuGVxdaId43m1qsuWRyuyM4g+0Ef8gV7D1ECrw\njsE6l2bTWYQLDawaNrKtCDEpJJzwa5EMkZibplTdq0O7/S/m/xIN8Di+EQgd\nAcViN29JGV0KWq2bvTYVYUMqYZJjmxhP/kRZl38CyNJmWBnwV4EG3V9jjbpn\nn/91bokG1rMFfNHMoNKwSBgCLu7FYZU1EUbw2tJH9506PEmF/DchTOS9TlZl\nhEuBbRDJTk1MdZtXhjxG+1Jht85xzmbhfYK5InoyvlZ54KvZQIKUJnHZk2RE\n/o++Z9tYAZK74SMm403mYXCkqjYTx4osKGcz4rhj7HsJLehg6HqYnPvDAOOV\nEuucyt1s0Bk9zivzHzIcJ5owycejhfbrsNN06E+LS2y1a6MGJcQ5BoE5eS6A\nlD+TQ1uNAZuqd5LnVYvxD4H6gIKNpO+GcrcLncg5mwbVAHfrMUezGqthKDvo\nhkC8oY9J7cqgBmqTMXuzTu0dFfK4YkF4q7jDkOqL6EJ53qz8NTWjhZlAn33o\nnQer3k1LtCgvk2M3aZ0sMT/nysxJ5J+ILRthwG7fLIroWEO3wdkXLFmCSNic\nCv9t\r\n=m6Sa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICyYqMahzEy5l9RN6DPw1J6+sOogmuiiUIWLBvNmemeWAiBXfXZu84vnjVOx+waJb9Jy5wZldtswYBkbfc7fP6orUw=="}]}},"1.0.30001133":{"name":"caniuse-lite","version":"1.0.30001133","dist":{"integrity":"sha512-s3XAUFaC/ntDb1O3lcw9K8MPeOW7KO3z9+GzAoBxfz1B0VdacXPMKgFUtG4KIsgmnbexmi013s9miVu4h+qMHw==","shasum":"ec564c5495311299eb05245e252d589a84acd95e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001133.tgz","fileCount":801,"unpackedSize":1468733,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfZl1TCRA9TVsSAnZWagAAHvMP/RjD43L6ywMIamUbNiur\nzVyRF6LfrClb5Lo1m/Lkl0nTWjnfZuawNHanzep6UBGyZvWoMTpNMje4+BxR\neHLD6Bw4PtcsvmLLZ8MGHKiLt/Cp1dVymsyDNkLl4wAaFR+XtYlgphD0hB3p\nAtZDNcfjS/1sLayWuIWfJsEUTcP9/Hc8ptWVkDQz9Gzs4QiBMfDn5gkJqGW5\nCNS82OJ1tEe/QqBlUbpW9vhcmhP5UyVD08R9Y6kuJlc+BxdflnOLqsRsyGns\ns4XOOilMYu4wn9Cnywgv75y7YB3ax9SvbRdsW8cl1sHxykLIMCW8/SRqegwC\nIYcTtP1krZD1g3Q8XGk/FGaC/YAk4yoa06TEpOlH4GRU/vHpyiXsXal0janz\nJUQCJpX6xLsHcY+Vj1Ap/tlgwplhntdF6flJwBot0x8k2b7y6aM+VH8Gxd82\nKE7uhIA4BEqoYg8WYGfgDplBqtUMDBPsteY5iTUeSYyt4Ps4PBK3QVAJ6pwb\nGM6bAmFFOlUKxXDhfSE3DOQvFGLv8igoIaGz9gofentI/z6ehTCxg/SANeFR\nWyqeQXMabPZNYJ8rFntGHfoPXaCWBwUaY4VlJcMZ2VqfCgHZD6AWEsHov6tp\nSUskmkNYWPhSeLoHGNtj3B9uUCFYQpgnw1u4zHcYLJcZt0/hvZdY2YhBE7FA\nfus4\r\n=5Xl6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCreGAdfmO6sW37RM+Nl1aRQNWV8jE0kQjTRjSNpepX/AIhAPiF0cWUCudhAqcZW6weyqJVeMBV8VLQFberuW87Ut+p"}]}},"1.0.30001135":{"name":"caniuse-lite","version":"1.0.30001135","dist":{"integrity":"sha512-ziNcheTGTHlu9g34EVoHQdIu5g4foc8EsxMGC7Xkokmvw0dqNtX8BS8RgCgFBaAiSp2IdjvBxNdh0ssib28eVQ==","shasum":"995b1eb94404a3c9a0d7600c113c9bb27f2cd8aa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001135.tgz","fileCount":802,"unpackedSize":1469910,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfaZrECRA9TVsSAnZWagAArSAP/RhT5ocIydbap0DYJDbQ\nCCyoAQ/GgvD+ZiaoS33/p7mPLFxJCgIPXrSoYUZj3HwyurzmwtgtJOLMTD2x\nNNehR1evhMgc8ZX89YwcvEHSUQl+01zHDBfBBUN5D83QLv9u7OwngDhg+vXS\n/HDktbCf8AYNF0Nf27R5P5BPEcM/LhzOuSuJIUwCddzkKqVSQfc7oSEdB1G1\nNkQF3CI86VZTL0gIlVSpxG2v4emXGcHvk3urRC5iBmzgZU/rBSQ5FGXdqzaq\nmdp8XhOS8+zonZ0amrQqDGxjQKw1Pde5yVdYsqkTgHGAPGVmN9GfdUwYRflc\nmSPwlmrtpX1UlMeVwV9bGpEIf3YFUVGKVWO0t+UdvN9f9L7fBFwKozympqUq\nx+urzJ1NCgPeLBGs7wrJ8/MFBj38eZgY0um8Hsq3o2qVKYHq4U8Eml47dC/E\nHkHndV9A52XtnXJgWal0rTgDPrKne+iL5l20dcclaHHoITljd4I/gjMJEj37\noL1VIDoc0ghwQqugNLMoPMZU/oDJaCPE04fOYwI/Swxraw0BWOXOvV7RPvFb\n/nPsv7RMqF+Q/GONY2BQ/7qGbuQKqCYUhi9mRBW/H6R/tFlJmyVlA8LphCRW\nAONi9NqkVR2IDIC5tg4v3Ai4q2tpLSvFrHOi8TtZvq06IgPkg6bVMse6eIsq\nGFeE\r\n=UlzV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFBuUbGEf6o7H19Ce1LcCDJBRqP7FRoHn4vC2fahrI6LAiEAoUvg6ErSLBCTqEKjLJ3RCagdHaON/axqLyrMbhHvosA="}]}},"1.0.30001136":{"name":"caniuse-lite","version":"1.0.30001136","dist":{"integrity":"sha512-VRpgi7sxGbLKiok0v1ld5GK82wxCj/icLMMr6S0Akg83TYVfGWdPXoGILyefudS6chd8EX6RbW/Q26giELwaDA==","shasum":"6cc76c55b2dcd29a3a998cd5e21b68d5e12a5870","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001136.tgz","fileCount":802,"unpackedSize":1471673,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbXMmCRA9TVsSAnZWagAA8hMQAJaQJQGXcQXfXCcAVLIt\nOg4RoH9nrI8OSngcezAr9aVABX/x9rmPdcdUbbZhDKQuq4V7d4NxQbGRqJKJ\nt6X9kV0ZDHFdspo8pDHDGFhYWsWkthtAES9UcVFclPpxcxWMR5KRJ6XqbafB\nfXoX1ZwtPTLrCP0ldMxZlGK9PCcpuCBxqMLfO4VaOPJ9GnYeLSnos87t3xse\nEHp2E+wccs4TRHUOCTbUtwEBuZnKWq0WId8+BS8LU0SkCSQXSm4T+fokqfm+\nyozNWUR6LblAmQ7cWGmtq0Ikg1jZ6s3dogPP3CQ+fpJEN1th2g6dWjK1b52B\nG61JpUhoXxQ4yza9o8/y2JJUXWLw9uCx0DPkZksoyvETSFaHpzo8dmd77dhk\n2A9tvoB3JcztoQTQ0jcbVaDb/Yut9YZoMKF14YtpqrQ0NAukVhaighi4zSdd\n3tG/Z29BnUx4UpNDn4n3cdeggM4J0J85elxw6nrd2nD+qAjeBy//Iw5UEv7I\nGfvPIZbXSetrSTq+8LSGAhWef879LTo2PBdYdjJkAQPfI1/F8SIhxHkufv/O\nKB1l6/YJZSj3EJI5MlZ7w6pFdNsHx0RgVTGHY3VytB6Oa1MOvHdTji1qPRiw\n1ogUl7rsxN2h26bPKdPet7XwsiVV0GYevGbZU7hT/fAOJ/ayMmtpW9z8gf7I\nVpi6\r\n=WY5v\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYl0hzdR6TXbp1YUvroBmwpX+bisIS6bBB8I36NgGmpAIhAJ4EVrynfr90ZYix7rFvBuEbdR7BVvrJdVIgMR8uDsmh"}]}},"1.0.30001137":{"name":"caniuse-lite","version":"1.0.30001137","dist":{"integrity":"sha512-54xKQZTqZrKVHmVz0+UvdZR6kQc7pJDgfhsMYDG19ID1BWoNnDMFm5Q3uSBSU401pBvKYMsHAt9qhEDcxmk8aw==","shasum":"6f0127b1d3788742561a25af3607a17fc778b803","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001137.tgz","fileCount":803,"unpackedSize":1474504,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbYEsCRA9TVsSAnZWagAAdAoQAJUK3DizIVAr3Hwh8Ng9\nUdnbCjLEiVbiTZKpTcuDI/3TQEWdcFPSXj15VsLnqj4jw+C22yoUj7y5BC6I\nYU2T4+qA1/Aw8vPrJBbTXCscfnuVJdZCcWre5rf4BTtcZYhoWA9CSfSUriEb\npVSL+g47Xdh2ohqj1VeAFAa+9R24w1rTlOrtAQ9tf3XonsTTYLnMxIN7uzNt\nlarez2vUTRM18Rp/k75xwAci/mukYaoymfMKv/NoBkihhxKBsFudx3S9KWn2\n5SBGfhFZS4UWMMGQvI2m9nMs8HwXTF2ohT+OrniOGsj8g88OAUovxEynaHmi\nJPbhJWf/jKtoKmf+P9p94RR9skybXOSvTN6IxbwDvq9ffcqGw5TIbrOO023u\nUFOTgdT/wD31sBjIW9WPzlgkF5RUuBfk6xRwYFGBhYv8h15rTt89fKgnPcuk\n06dcA3KfHc1r5Si/jasnUWRDyYJYfaiLht5A8ljQmJkIoe+nGe3ZIDO1jVLc\nt4mlpTl6kCGxcwwkUWclSzQHKrGtuQXdgyKMWrQFsCfuEaAybn/xPBaW33n7\njnrG53pIoOezMzX9nXTx5iRe2BIjnOfxQnId813ersAA8kQiphpyaFX1+k8b\n81QculZu3SNMeKL7SoOQ22rsk4cYp3GboK2kYQAEUPo5KpjOQCRvqGni3qc+\njw97\r\n=/Ny4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD82j++IwAarePNTEaawbUU92QD6Ly6grlRhWsixlJv7wIgGZ2Iza2BC2i+x9QArV6bEAHld126wz1J9Dpl1KYNzCc="}]}},"1.0.30001138":{"name":"caniuse-lite","version":"1.0.30001138","dist":{"integrity":"sha512-NKu/48s0YuVowzsAxoVW1ti5dn+Fm8cZf4DGG7BRoNyBEhdKAxDh42yveEovTQBYiQ043gfZuo1PVax5t0qIfg==","shasum":"4f4da47266584712f4abca3f0ffe4d22135b4d39","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001138.tgz","fileCount":803,"unpackedSize":1474579,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdBioCRA9TVsSAnZWagAAehgP/AqJDrc0MlQYjW6vrt8e\nmCk7yU87MWdkJSktor+LgGqvyJviAS19Zc4F8pHQ33odPUDhXkpSTq1Rf6nP\nM2v5mVE82uXQb74IO6XoZC6xbrBqpC4iSs2hhzV7TINSP+LSfKm3AJpE607D\nbG0tzCgN1rUXzXhzwrnGyEX2W1oODKj3JDulWaP8cmZ32XsXmlrBZ/AXmTFb\n8t5o2AsTx6i6iWWAY73+8nKYpXRB45ULmsiNPoV6wjNI6t0Gt5uHfzaII/rx\ns2kKHsBEP4PkwqfDGN7KqQ0PpsAvncuOpc7zYxNDILylfBQ9Z3laVbHNVser\nPaXY4PG4cAjASMfwHSxjj51EHG/+JAo208gGPT9JeAVfzFhaR/PrX0Kon9yS\no6WY7NAFPuo9IRqMPgfvTc9kyTu8PMZYPbR48zPJXwE+K53po5BLWvwJv5BA\ndXrQD3oDdFaVs19EMSuy3q1IbdwrhMrOgzaAv603H4LZIbenE8bn1YpNvu8X\ntbylO89W2i5b1/u2SFCnlAa5m927tif3KVhNAlMGacBnOTTSEySjCoVlfUDy\nPj/2pB4zjNGW48wv2Le1HJlmWbyXKln8z407+XQWw01WFoBT1+5EMzszJD4T\nppvkZjFQZ1RzHZ9C2+4RSmhXowspeWUzCIPnaWueNDud+NiOfFS8n9j8dEEv\nJIGe\r\n=Zgvk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDDvpyVjqVwMWIAo7fXEvC5Z6pci5AWsylL9Fyn4RQGOgIhAJLDmzjhAAPqh09B56cmCwv25xs/Ya+GXRY62vjYS+8Y"}]}},"1.0.30001140":{"name":"caniuse-lite","version":"1.0.30001140","dist":{"integrity":"sha512-xFtvBtfGrpjTOxTpjP5F2LmN04/ZGfYV8EQzUIC/RmKpdrmzJrjqlJ4ho7sGuAMPko2/Jl08h7x9uObCfBFaAA==","shasum":"30dae27599f6ede2603a0962c82e468bca894232","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001140.tgz","fileCount":803,"unpackedSize":1474687,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdCazCRA9TVsSAnZWagAA3CEP/ArwNY/dgXR/sQM0MMv3\niu88oGPu6O0Elswp7jVWNmYvJHTauujSrU3LSqfWcwWX5JbFF8E1A/wKDQvH\nSTVJO+1UzdssZ0gfvTWdEStd5Di1NiuUgRmw/YtLFZT/l/yoE4dTGJI2PVWk\nZ6IXZwycMWBeD2C0cAmxi7u9eyxZnqpMkjwnVupLJ4c8WPSY5bHE4gteGSUC\nOxaakrAtgZYLw54ih4uv80iOUWEWBlatVP5ytHk4Ned7OVk5sWQqGQxVdm2f\nTuPD1gPTuakatz5Drfes0tJCXH0pQaYTo8h2FgLoiYqle+ku9GI0NrLNIljA\nb7BEuFDuhizdnYlZZfO5AH8AWvLSo/JoC6vMILc85fqH6uG/oX1v73+6tY/P\n2ltR4CbFKVudHH9DvNEXcE7MW3Q6oKxs5dQyg0tKunrr8W06ifgu5h+y7mmM\nqsZqreGjqqfn6E6c9nQ04QcnaWgDv4KgxYgeKbN2sMuEFx7llNfuSZs0K1tf\nAm6TIoK7Kp90C/+pJWr7Voi8jcWbiZK2HDj7VcOSfDrp+YmQmEXXpI6M+/PZ\nBOQrcxo3L+Yen7f5DfVYeCfuW5hdtSkdFVVzPPoBubXJsMx8ZUZECl8ZuGqa\n6gerKS+JklDnEv+v1+OxwWkT0LkldKet8XI38PstfKy8OdJM88Ax285GV3J4\nEeym\r\n=CqfL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCA/wwtXOtJ1/+X0WO7JX+BJ8qquNVXPUHBQx4RvZpnoQIhAJGA8dbSxiJaPBhTX+kKnSeDTo9vSMXi5hLGotCpN+KP"}]}},"1.0.30001141":{"name":"caniuse-lite","version":"1.0.30001141","dist":{"integrity":"sha512-EHfInJHoQTmlMdVZrEc5gmwPc0zyN/hVufmGHPbVNQwlk7tJfCmQ2ysRZMY2MeleBivALUTyyxXnQjK18XrVpA==","shasum":"214a196d81aa938b268fb0cb6d8fab23fdf14378","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001141.tgz","fileCount":803,"unpackedSize":1474758,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdTHqCRA9TVsSAnZWagAA2tAP/RxWW7Lz8w+NQD7/rxVt\ntcuHtSROo082jdRdfV1BeW1Ws1McxxVhoObkYWoL+HC2qgLYHkSmjuIvyCF0\n2xFxBmvAaIyRkd7BlAm3SGQwGLDDsicl+CuZB3mf5uk8WzYXRMsvmWusPJ5l\nfJuFCOeJdmFly4Zd7FKNiTFeaB3ZN4dxOaUFbFm2nbR7iFLblYBC8i9YVIA+\nyqOJjbHtxr6pxY5LVFcP6XKq3KBlPhnUbhbU4hrS8PebQbZNwGfUQFg5MYwJ\nm9FEDUxbs64td7mQt48nXEN1MqxdEjp5Nge62LgC8lAauTzttq2W7bmBzPC2\njmC5cSERUQ5yxmD2nvID3D8hRnbrusvCj4G+YMTfLEpY2dva0lHDUbHVi7+h\nG6AUZA3xx2QHWcsjBBaOqNDfsBOL0xdCGL1lvLxvR3qXtC0iMgKSniAE5uNq\n7WiIiWrHxpRKyGm7aO+SQ8wdZp33kKEhIscf7/PGKO03kbibNSvr+Krh2yJx\nHmnjD9bb4U4ifmZVDsK8e9si669ZLo/AoilZIru//Hodk52mvB2j2fAYk7zv\nXh+pzQZIFM7zUBha3R+PvJ/SHtlR3DxfgLQaIttas8CwJU0Y7vUs29UWQ7AI\npplsbdK0K/QHNpMWpfwFgYvFIa7wUO6J7RRkTapGCPPbYwN+CKzPGAMQhLe8\nzb3j\r\n=VaeJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVgD63WkRNJ/54tEBn1Nm18VANLVxVsdybmQVkWWlVoAIhAN/K7+cDqFJVgKxeua8sUJc9S5/R3XpygmTglNAjklW4"}]}},"1.0.30001142":{"name":"caniuse-lite","version":"1.0.30001142","dist":{"integrity":"sha512-pDPpn9ankEpBFZXyCv2I4lh1v/ju+bqb78QfKf+w9XgDAFWBwSYPswXqprRdrgQWK0wQnpIbfwRjNHO1HWqvoQ==","shasum":"a8518fdb5fee03ad95ac9f32a9a1e5999469c250","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001142.tgz","fileCount":803,"unpackedSize":1474824,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdq2QCRA9TVsSAnZWagAACNEQAIwoAKyQBLe7lWRnMHjl\n+plcIuOIXmAiJWoIGiwsDfp5iGJrsx7Sw69quH9BhPT7dqWa4Tks4RLhB5Th\nL235ndmaKsbNaBCHyLpdK3heEMTbsXDQB1zhaC+L3UI8fmDq265zaDPn7VXM\nv6fxOTfoE1L9YBQGVX57XB+v7P8rSpzfYo7qvi2y8LK/rKIBJL9a4QcSYlZM\ntQPdyu9qJueSH7ny5lzEfwRecaLzj3T1vyHLTQrpE6T9fJf/KBsSz264P0Ky\na1F7l26XMY5b7DDyeXqzisqxNs3nSEx2XvOnXCd0rSVQ2ydcOh+ADIEa63y0\nhrI8ZcUgA95Vf1RR7lBna4DHczX3jIQsowGSPjFtszU72Jl1wEKTulFLhi0L\nW60fW0gtRQEr1aU2G30EaupDYL+nVXQm18r3wXM0wl8w8Vd1ETTCkK7d02FU\nA3Ox9B/KdUxYbvBTdbabaiG5zLUbnCuBlgucdNpjQbt7cG8cOsRaw3sWYoQY\nTgUEehjOm8YB+m0EtmVZuRvNIt/3kUuS2viBCdMGPXX3MVgoA30XSu+r0zv4\nUWGQEh2tMcRO+44ViwRiHeOAKVsDUVRM+6RCvbAGZkB0FsPlh7ql62DqVSK3\nAJecWSJysjAQk8bk3QhCL+WhplzQPNqPPGt63/NFc1qk/RiEld6sffletWOO\nfaY2\r\n=n05y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDSRLpZDrUhfclfVWbkvmm/C2wJxDyh3MbBCs+HzVKCHAIhAI+fUQ8NUrcE2nQsCu7faHyqud2SXBdVT+utzV/aYE/7"}]}},"1.0.30001143":{"name":"caniuse-lite","version":"1.0.30001143","dist":{"integrity":"sha512-p/PO5YbwmCpBJPxjOiKBvAlUPgF8dExhfEpnsH+ys4N/791WHrYrGg0cyHiAURl5hSbx5vIcjKmQAP6sHDYH3w==","shasum":"560f2cfb9f313d1d7e52eb8dac0e4e36c8821c0d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001143.tgz","fileCount":803,"unpackedSize":1480105,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfeNIXCRA9TVsSAnZWagAA61kQAJNS/pnJPU3WMFokwqtP\nTFTkFKakgAJ4Eg+5xCbW46pwxRPitQT6z3YXDjzArKHraCUWLWxR5KA2KPV8\nNZ4rUaKTwp4pxu4NWkEKmFw10j3C2G5lc9Yd81KjEvgFJMPJNCHt+2CBOy/z\nmpsYp3EML5pcFP7sTbsrWJrOJDwphx3NCdyQvM0opmZmR4TpYS9/4dzR+3bo\n6qPZy2xGoqPkJzmQqe/vbrVy2i/lk57Z7+R7/dOFYff1NYegRPmmT7nGm4HE\n7ms9nLGfwXp/Sc/0xnxtPnJitMS05j5HnBZhAKp9tjKkLcjkqbmuUVDq0m4V\nXaoj8H7pO5+hIVIYFKJDbdCga1H/jg08YA1oHXMuNsh099M1a8XRJwXo9VyD\nDCNGiIEVOZvuo2AYygRKyXWYEvKeEgzmzuoHoeAZCQnil0ngHWWXAYBWUXKv\nmhp8k8UWKSbnYhhQ0zFTlExMGPAy76fP+5VxDS7TzCm8tOvKUPcxJrlE41+c\n+elIJemFnKkhYr2RARRJJpTOwVfstyKV0NDWdUWpETsk/EKcMfgZCulwzkIn\nfUdEmvqaPkarYEr6iZ8ekWeM9Y0g1s5moq/1ZEDpzTK0zVDjl7VG/ir4kYPd\nEeuMZPb9y3elenL6aWywrCLwQjnbi2JQyb06INWqRyrGjC7Jy1JHWjL4CNQo\nhwFh\r\n=u5oO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID5HDNET5uveygiN+8Y5XrDYvVGO9l4U1t6sBPYlFTRDAiB2DHEEZWvNuC084279VInyKAOXk9ngln9eznSkC7ougg=="}]}},"1.0.30001144":{"name":"caniuse-lite","version":"1.0.30001144","dist":{"integrity":"sha512-4GQTEWNMnVZVOFG3BK0xvGeaDAtiPAbG2N8yuMXuXzx/c2Vd4XoMPO8+E918zeXn5IF0FRVtGShBfkfQea2wHQ==","shasum":"bca0fffde12f97e1127a351fec3bfc1971aa3b3d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001144.tgz","fileCount":803,"unpackedSize":1480200,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJffA+uCRA9TVsSAnZWagAAFOIP/A+wyag2zdm5gzqGBZX2\nMBC+sj+i0gJwNyiawuwX2H1GtHEJubiYRXmB1sAYDnljig1jPJqe1IdLXkBo\nWrC8Qf7fxyOWsP1B6zfNxDVhW0pnWAk0zMMo2Mk69Uz9JvaGFF/ehE0f1rzz\nDmu2rzdzGtsxnvH5U4bEP60PcBtc8l+taq4iAdSUn8vj6twwl/Di8vWBADFg\nlAhwJajnfjSqsi5u4bXt6P7473K+Iw+zPLUdxMICoK+B0HIze//wJwLt43EV\n1idBzPKNkTswue9fqOzcyqcQaVHAt1WpbZz/Hj0DpvCumg+0JiSAbRe43+qt\nhxPLcyxmI81aCuWrRmxBLXHon+wWpKF8lhWhOGdUngh0Rh9gKznVmqfYIdLL\nVzX8v/gBolp0OPyX5ePHfdXQLhGmIFgGo6J2PPG/RePCw/jZmzJCrjhM9rrQ\nmVzceeuAYCRDVRTGh8W094DxBSCkzrDO9BJ/n0MPMfKSpCdxirP7enWGgPDO\ndrOP7E1KEY2CA217O6dvFE+XvquErk6ZPWWoDm3w4hL6VxhLHpSsPgTWLweI\nKPGBuPLS+hnoHfSdvkJ9qgBhtMO1iZ4Gco92g7VNTdgOs1KBj70mNdl6yNSe\ng3EAZ1MqfB1cg6PIgghphafv8wg1vC6Rdszh0iMrndAkuwOX8rY1UhE3aINZ\nUZIc\r\n=QAoz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC/lVD/uDpbVASEuA8tWn8fh9/Ya3zVQjZiolWEWJr2PAiEAyNLtb5O67M3F8MEAEgPGoG/ks6wiDO/IvZbtC+JBIDM="}]}},"1.0.30001146":{"name":"caniuse-lite","version":"1.0.30001146","dist":{"integrity":"sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==","shasum":"c61fcb1474520c1462913689201fb292ba6f447c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001146.tgz","fileCount":803,"unpackedSize":1480266,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJffqSXCRA9TVsSAnZWagAAL/MP/RTEf6Z8Lu1xI1IIFplP\nZr1WxvJIqnlM9Y73y+S8hIE2oDXwL4jVZ9kSbnFIgyVj3W5FMuNdisOjLulb\ndCaI1yvXNyJp+upU78yvTUInqlqov+yrSncOqDeinIBPmMEy+L4plN0MKR7y\nCFcPWfMINlYZl0DxNp3oG9SNHvq4856dR2/zSD0f4V2y3EiHmSC/cq9WbCNn\nq/xKRNpWvjZZsznHdiYJHaKQWt/bCbCFwuzlruo70RPT4Yglg15H5X6cXHEE\nLJPLmYEHwOwkqy3snwtP8xKvMOaJ76RtxVNZ3FZUh8z157ugBp4R95QhBez/\naLdKzyUJblhvOdZZPueS+sca1H/or8HbLW+acGOA8iSS5tiXC/1kgYG97Tzu\nISXwnZlVecXowJdM0Xse/8G2LqpkH/J1QqfsnfPUkmgUN29Bu39V7nbkXdWG\nTCxir0IIRQadmGS0J9oMn6sFm72LaOM0CNFhgE464o4nrlX/8T02oE2UeHVa\nkm6hodtGv9fFZ6JyuFSFXYq0yMOUG2GDeHDBSDI7VMsGVehZLffZNIvBO5fB\nAbbFZezqV65yrMHpp1jzLl+s3OxuNRYVQS4l2iGVGWkt6t1BsrtELbpe+pSx\nbYRpczlqin2H7tPBAzG7djvj90l3IeWy1i7uzErLI1Ymi6fuz2uCPbCrz6mQ\nT4q0\r\n=4ZBh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDsp9Df4+VD2HgQjncNA04c3rbJUrWSxlQLshMtHfo2hgIgV6uxWTKQpym3S9voBaREzMCbKAsIE+nob+YFBshB1EU="}]}},"1.0.30001147":{"name":"caniuse-lite","version":"1.0.30001147","dist":{"integrity":"sha512-CPyN875geYk46eIqPl5jlmotCr5YZC2KxIVfb4z0FrNfLxPM+MyodWD2irJGDG8vUUE1fmg3De9vt8uaC6Nf6w==","shasum":"84d27e5b691a8da66e16887b34c78dacf3935f00","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001147.tgz","fileCount":803,"unpackedSize":1483646,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgqdACRA9TVsSAnZWagAAArkQAIlXyuv0DW6DgLYyCNpy\n8bYaytfNHoT9Mje/PqWojw5eXAtypZe4c47UlVqs1nQLZstIo+ZFaoH+iZHL\nb5dFg2EWcrj0u073/zXw/Ts7dG0CX5ZhGajAfZkiGGAZWTt4Cz10EKtNREh3\n12HDAymnlpRdCCVr3miAe+/z4nKPVLRMDrgF844RnvvZ6fzFrYW3b0N4ip3B\nbW1ZPK52q0kUZtgG3Cpt5XE53xOMgq2H/uWW+EeM5JErXUP9B+turnrq5C7Y\nKq3Gg0+DlghP70ZKmIln7jZBFitejaATvLW4P3Im3X55qtpwGjTgqCu5Dx9D\nbuJ+ms7qZC2e6HjfDHfR/LPZ0I48F2qLroR/eqRkgiO4ApkA2spgkwy17FQu\n7DE151Z+wRhFFHtCbhon7RS7BX3qvKQp0eMU7MtjPZcZ5rcPCRDXMTT1DH+C\n0uIbH6KnMe6M8Lmj+xnEv4jK5s+N/ZEAYAlPoREb4Toc8u8QxDEoIes0N6YK\n4+6M1FCH0lfzsBtn81MGuGX/TfX8HXLE7EzUBSfAAh8IRhHtsJ0mCVLe3KjR\nF+M3BgtoSaayKzNRorENolxB7t0UREKTUh6hEiDyowdQjmWM4T5+7XPXkIi9\nAh6WZiZRAhwYUQ3b5TaQ+pX+o8xwqz/dC5I3R+8j7xA/L0hy6gMKKyXEhsUS\nSlCw\r\n=G1we\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHgvXFv/s6t/NKb1n6t3+rNZS9GFuUa7z49CYJ2Z6bOZAiEAk5UJl41/Z5rJhQbvbq8wUqV5hy2akoPy/6zojUEjNqk="}]}},"1.0.30001148":{"name":"caniuse-lite","version":"1.0.30001148","dist":{"integrity":"sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw==","shasum":"dc97c7ed918ab33bf8706ddd5e387287e015d637","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001148.tgz","fileCount":803,"unpackedSize":1483718,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfg/jWCRA9TVsSAnZWagAAwuYP/RyC6UypkVGZpRuyWfZD\nqS2/wS46sRJWFE5Vc7jPre3j6r8E1HNilJ76tqPbac8HzeIJKLFNwCszIeaE\nrnPOSHMDAS/iEiVYawu/6DoN80CF6DBDkXiHN4jok//urAzg9pLnRYIqH0RT\nK+w/doAM7YHDFJ6kS+QoDQ57umO3gAd8Gaq32RPBBtD3nDZGxraqfr+Jp2Y6\nhHwuZGHXy8HNTwJMdbEmjOpdX2aRf12RD1YimuKIpkwejc/BgEulWFkbkZBm\n4eQ/mavcc59IBIlOZXOs6X8b2ATGDowWZLX/OjwdoLVFcD0WQv0EdCEGLyJL\nFyEhUWUSsTMdV6mIrnvHgb2nq81LIGwFtSZf6J+3xLWGF9Gcf+hKDiUOk7o8\nG3VjdYOJOmdznUy5uhv9eiCMTt6wbgiynW96nXVWJ33GkMOrJWfz+D//68KF\n6jw3aITKXjgN+a5zyAR/oRZOqARJUwNUN6XBJa5ayklx7lHcC2ad9aoO4ys/\nUj0WQjGt/1ODKPnf3YYknbId7sgqMoHT1cE6M/1virfpB3PHb04+9biVf1ew\ntfVtG2fH9sKFE+Vu/0qHaFp1QAPuvnHQas3FdIFLIKAO/UCjsGl5uHkDUz/w\nvN4IQlNNJs3Ejl1aWdjJoLQtUS2vDLiYhiqbV/79HoVs+OgQo92iFkSpvUlb\ns86+\r\n=ZmDu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDtJzOeWvsoXL5c4tt6zKQ10ZaTI/iRaVoGolj7D8Hc8QIgKC/abmUbs91WSFQkrgWlZPEU2i/jW6O2XA05npvyQGc="}]}},"1.0.30001150":{"name":"caniuse-lite","version":"1.0.30001150","dist":{"integrity":"sha512-kiNKvihW0m36UhAFnl7bOAv0i1K1f6wpfVtTF5O5O82XzgtBnb05V0XeV3oZ968vfg2sRNChsHw8ASH2hDfoYQ==","shasum":"6d0d829da654b0b233576de00335586bc2004df1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001150.tgz","fileCount":803,"unpackedSize":1483812,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfj9ZnCRA9TVsSAnZWagAA7pMP/R/U7dSsjJc/23Bjqo9k\nHTQeRcF/SOOw03v1+A3Z4Yyfe8bbEurAZA1Or3k34Uol5UgpFOeJ7it+4/mB\nbLiZRW7ynOYkyGQaYj1FJ3ydiqTRfwYaMVbyrAE7CVPk38dxsqCpZGRpVIvo\nhjUQluIfOmrbAO6VM2qKp1EUqUhyf9t8Xax4md2nZNAvstGgbjb9OT1ufflx\n2UUvE90SlTCm+YoeeuiFpOMCAkLTPRdJ0Fn+sgkjpVFuJOvJDM6GA2NFF7KP\nwGJmY4BcVu3ip4XaZhvxsZ1+FDBoX10yeYi/z5BD+Ehzx7sZQBbk92RlTsNm\nD2U8g0EgBkHmrloyLOBSayMU3bqP0VNlAYoAlINxUF/Tya+3dq9x8whYY5eV\n/v5WO30fi91CY76ZXbLEPEMgMu04uhiH2b+6zpF9xb9ZaaOtDKjlv+PMBy8G\nTupf72xjz804Fay2EejOCvyEgIq1IgzsX3ymhea7ZCJeRkdJVPIvq8ukX4nH\nSilnmK9b66CjieW+lrMOpChEN0IOccX9cWt5tbKFTDPWOkFIt0/p7JcjolUD\n90cFtQgEsddWILp4I4HRKNwCokyqpc9MHkjjv1r7Ntpq7gGGe1A9iP3J0Q2G\nG9FYc2VJjT+aL+51+bzif0oyJjORs/oa+NOdh/0kQScY5Ziytj2Icim7vOkX\najmB\r\n=pknS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEY5jFT+eSFQpQELmgo3Lhe0NMTmXfbUALfUvqqhhWjtAiB5KYzUVwW1DnRvAvF+x19zW0CKeZvuWCaCHJeUCKoUzg=="}]}},"1.0.30001151":{"name":"caniuse-lite","version":"1.0.30001151","dist":{"integrity":"sha512-Zh3sHqskX6mHNrqUerh+fkf0N72cMxrmflzje/JyVImfpknscMnkeJrlFGJcqTmaa0iszdYptGpWMJCRQDkBVw==","shasum":"1ddfde5e6fff02aad7940b4edb7d3ac76b0cb00b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001151.tgz","fileCount":803,"unpackedSize":1483907,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfk7zGCRA9TVsSAnZWagAA6PQP/R3dkN9OgNU+iUwEPQl9\nsxV5zy3yxIcDvHFyQTVbVL6pkjAL1QZvS9WI+R2dTe6Pwx9ylReQzHk+wWf2\n3bb7dTRSo/RGNqc+NxMlDy+1ipnbzn2wnsMqF2+lwCIgjimpBQP3VOh+qOcE\nfnIjkxNvNflOsVoi2nuDje76KsEk0OWDR9d7MvrsKTwVQiCkgEH7/En6kOJO\naGTIycsKMw6zlGk2WB/UKblPsUCMclOBwiO/AofE10sEiwHLBUn0ReWAYAqZ\ntd1Mdm9FyNLx0sxZ4zLGpyfRrOtKIqGdWJ2XCnMU94Q4AaonjRTkqPi1TP1g\n13NNoZOImFI8xtGW6xCxoQZv4eChJbe2zHVPR0Ai5LKllDdAWwjsuxdSRP+B\n/Xux0mg14GLYbSx4EDVNn5TplA3FqKH1eDlCiz9LrTDohDL5kFZPZoZTL4rv\nQseKooDpU6e0fExbeIU3A8q/97D7avSwHjzyVJ6ynUCQqd9rpRrTeiNNJjAW\nmnl3VNy6HIgaUhlj2TeYDexrezVLa7A8Sj+BRxDQe76S2QCwisOEcomrV1nc\n3GFuNy3VUKMAWs6EO7Agin08Tn4nR5RIYkSFxk1RqCZdJo4K+ud+s5qyEQvl\neqiqjasnHtKAGDFMMEPgK/Kxz5HQ//V1cDvEOEKTHSmqdt1sxfija8ieRWhq\ndwFY\r\n=3NKC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBL9WVtcTnAZbrBcfFGkKO9kie549B54AeR8jwjhJt4CAiBQfz6APYXE0IPOkTOyspEglo6kFQbgxTgw0JX/Tnh0hw=="}]}},"1.0.30001153":{"name":"caniuse-lite","version":"1.0.30001153","dist":{"integrity":"sha512-qv14w7kWwm2IW7DBvAKWlCqGTmV2XxNtSejJBVplwRjhkohHuhRUpeSlPjtu9erru0+A12zCDUiSmvx/AcqVRA==","shasum":"9a0942fe777cd7178fb084693b79415ff747ecd9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001153.tgz","fileCount":803,"unpackedSize":1485668,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmmJeCRA9TVsSAnZWagAAJdkP/1noKxsc0G7w2xT8/Y9J\n8EqQlr5tKqKMmcwgrGW3XJMZoTjAHveC0VPOUVwuWweLfnyBAKk0cHUofeZL\nwRFZ62JaogCPCH5OMpFTvLOHenpPhrzHLvwwu9+3o1iW6ov5ONmPi4b6E01n\nWTRw6nw5foJsv3lbGuCg2YoRkem0sPAElgCBqtlI0D6Kph60aiDy9Qoo7ThV\n0MJRkDYOxjBFACQu7y+bwPnVmGAWKIvPNmB70ae998RHlwjP5NW6kfTPpIIV\nTiD++doGjn6PHcmKV0NKaPe3/z2at/WIDWkILfA1oJR6mplQ3wAS6q8T2JKP\ncmOZbjG22NWAmTRXT3nO84H5rWQ6cr5l2NHzQEUSlAeI00fMb/YXxexko9VS\nSzKWsCNC5kLqyTM3DrzwfezChJWwXAkji9zRG8WdP6Q+Y8STDoqfoOna0B0U\ngrfs/56ct9mn7lBObjM7kk/r0NO94eivjnEp2Mw1F5DnwkGvQrWJNwA+AH6N\n30vIsKybt3hFozTxx4HRjScVrM69GCKIKcSBD7JBi1YqRkUu18SY3HKJYlf6\ntWtbddO9bmAZodKOoTO1/BwAY+UILkQh968slBK99WlkfU2nLSIOYaaeD1Dp\nAQ7vMkbCa1Df0CfnbPv9yE3odEohTSDqDNucJpvyNlfuJ7/nf86043MEPnr9\nyhon\r\n=zoel\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBwwEqX1q2biSf8bHbG30C+UiLzlKlX38eLENZCrd1QAAiA65sadQSCunf3r16/ySJRmhyA2Mj09yKzOW8wIp9Go8Q=="}]}},"1.0.30001154":{"name":"caniuse-lite","version":"1.0.30001154","dist":{"integrity":"sha512-y9DvdSti8NnYB9Be92ddMZQrcOe04kcQtcxtBx4NkB04+qZ+JUWotnXBJTmxlKudhxNTQ3RRknMwNU2YQl/Org==","shasum":"f3bbc245ce55e4c1cd20fa731b097880181a7f17","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001154.tgz","fileCount":803,"unpackedSize":1485752,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmyctCRA9TVsSAnZWagAAv/UP/R2ivoQ3sZYZBfEcBrvc\n7SqTHyA6MZ600sk4FezrZWamzU+Jc+CerrGOfV0J15aL9+FY8Ch88WsBqws4\nUqSi1uzY/WhVgio1YwePhZQNBIeyKSjmOQbeBIBM0+96ucuoleSvHaqcd802\nRZ+PEfnTsq4IIBhV2w18EewVevWuihsbhMwyEKphOGo9n0ZWYJXpUX3VxQxb\n6uPY59esE3qOP+1FT1xauVxfQnVQgpbDHevorDrY1xGf6fLFxtr0LLptFZ/a\nmMc8yreBkmvD/4LNGABfUf+289PN628HKkdjo2jJxTts1W0+6Jc0vE37vant\n/rPrVBq30UfuzEWS+Zx97GQMJn6lTiYYAxNP+x8JiVEFGIb/NEcabzOUKRYV\nVc5niJvH1msUkdIhB00MKl8tEPxpUQ2mD2007DYEc0AjHu8+i0faCM2J6PJV\nEuk7rdV0JPQZZsHrvlMQEAuFaR+IUenBnebyqpyIn+fm2bp9kl9q+o6mwP+j\nhzWYWdaRlRpilH40q2ASt09tqaz8mUzliGX9MsqfsSaaIXDSmvmuTpXVO0Jb\n9nXdiyjUTqvLJ44rbeotqsvyoU53MCht7fC6y+gv/APvpvVzHnDLCyZ8RRwU\ncKAGT7CyjrK72fWeH28MGNtBDuDAb1fnYRHdFLrRu8pr7C+h1HrLaV3BK2Oa\nabAY\r\n=Tbn1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAaKIBIgb+gDLbs8Jvy5/Txp4NUt28EoLX7r3NpfLD+DAiEA7xzNh5cZWUq7YE1dOsCDvC9yHskRQJ04IWpRMaoG6Ts="}]}},"1.0.30001155":{"name":"caniuse-lite","version":"1.0.30001155","dist":{"integrity":"sha512-ndIFE2tHg17go7RRoGxTaFGILKV+07k/qVKvRlFdf6l0ewybIbQX65wMFwQpNDE4u8aXJrD7IXc5QYMKtrTiqw==","shasum":"087f063d7de063fd26516b66689a69075c75431b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001155.tgz","fileCount":803,"unpackedSize":1494398,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfo47XCRA9TVsSAnZWagAArs8P/218aSCw7HWzOeJD2Iqb\nq/h8NyTXt9241n8n0Vb82C9q2449S8+Tp2hbBSzFslPVfr/7tPTsz5fswZqZ\nURYBdVze1p9APScMaElu51pzFfJkaIpMNCL9yqY4J/tEIpUiJKfrP8Z+Mris\nzfpTAWrMxVvQXOF2mngt72eXQdzmGh/ei8z691RzZ9PLYnHdDHAyo92HE1CT\nbjTS4VxFBr5UiNJqDFz4HVkINBL06xF2siSzwXGAt+7kPck8AR87K7ae+Jp+\nrww22DO8y02nnrmbaypYYfUP/jyxxFTfXp40P2QvuPHaZeWjbLzx4rycnHPn\nk2CBebwuGv/YE25/hFrFwD7tDMc+BO27InE+xCdi6Gq8htG9iZ9Kze2sCJeV\nY9Ts2iDcV4lYCHpXU1PZD2PHC4ODbtVoYQWgp7n0uK/T7Lw1sHb7jR3t223z\nodIRLsmYzoc0rQ/yEImh9uH7xBKhrjUVEcoRTHdLUb/Jvrew/uwdUUcAgWKq\n14K5UClj9FZKluysGEBCLkwZI4D4Dgw31ePjb0hlWD63J6q10rA5+AzQNzDx\nnL6CL674jcR1uHhdIHEmB1NY6AfB7ZzWBHDb/cWhlDnwq3Klyhkrf4jMHgY7\nnuqCkPoNdHefKP3zPWaTUCq+945DwLqwohMUCm8tX1YBIq7tJ8tA+arpEkER\nzw81\r\n=5l1y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL1kllN9cUJbetZ7uDzToAOXtfrvTLkd86dut6EKEwNgIgfTK6utuSsydC/wPGhs+l7UMaTA8RiBtDFmzd11Oy03Q="}]}},"1.0.30001156":{"name":"caniuse-lite","version":"1.0.30001156","dist":{"integrity":"sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw==","shasum":"75c20937b6012fe2b02ab58b30d475bf0718de97","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001156.tgz","fileCount":803,"unpackedSize":1494464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfo5zMCRA9TVsSAnZWagAACMgP/23PReI+XPWxTD917J+X\n8/yBeUvtzrXpcX/NHWPgriWjfFXbUdsKGhZgUc5G214VEyL/Wb4rW/H6Ln7/\n5VGFGz+aHnHHcxn2FRrqtnQy6lBaKvSoIhs0weqvMZkv8iQ5Uz/53MadItqF\nsa6HRcNuHqLmqTXXGg1Au8856GFDxkaF0OvkNV/kwr7LNoSrQKy9Mc2VQaME\nu7vz7wmTiEytuvgqucFItpGHrF2EOBYeFRNvq5AEOj/L65NEHiPTnHCOkiaM\n6YAB6Le/cYz95xkzebb9JgKsAS256MirlaqQsd8TRbBX9GpXtoIZtRxRCHTD\nqfuwSZOwXmfRc+xw0FdBk6e7xjexO6up2ME0H3SboC4reeydLH4xHWk6TEq1\nbgIFsgyslz99s37LpBT7Qrpb7DRhcpKktr+o9SjC1i+ZLPPsTRFiOIHZ7t9K\nTjFdRescyiux6vYNEBUy0NAGWeKsO976aaCdUC85hytpX7ksItHbdwYr8lL/\nPB/9HpZBiSguOhrWaSen4cYVvBpgCU5koMOf0RYfcb3PgnHTvY/ROQYwCAvL\n8xTPBGxg7HxkjPA9hj7iFKhzzaQqn6nALZVDsyIFe78qrnYDe5B933XS4B28\nHrFDuLQDdLQQ16/dFkbSf/sxlJ9O7/R7wHudxwTUnuzGc9PN/y2TCtilAyGb\nEu96\r\n=S6/b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDy+IjDwauxLvyCd0+Pcwjd6uefT+kv11fM9T7MyU6CbwIhALZLjy6kdDTa0LJXf8p3XOIH7yPdhMeSK3cd+s9jzUy2"}]}},"1.0.30001157":{"name":"caniuse-lite","version":"1.0.30001157","dist":{"integrity":"sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==","shasum":"2d11aaeb239b340bc1aa730eca18a37fdb07a9ab","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001157.tgz","fileCount":803,"unpackedSize":1495109,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqNTNCRA9TVsSAnZWagAAFbkP/1wdHurT9KnZXvp6quri\nm7L36LRfG8z4lJr8Mj2w2TQtNGXtjro35hK+g79y0OoMZU/FoceASBNb0Elq\nV8rj1sdNidh7EPEQJgM0bIxT0gQvxmeORRqBvjeARXpfxtFzgitnL5cayUpa\n9qzm91wIcBP8qDPhXQDmHtBcFEioqOszTUyymSglfhpANmHL8NjzFWOOAcnn\nYmwKZa4NFspduYIrVI1bH9daJBpdjPy3O6SEKWM/cVIrZzVtwuoNlt+AJHhP\nFhpJyMXuHe8cAVzLrgNjrW1ZBWfR/fBa0+HXDAuNrIMu/UX2tzxSsar2IOnP\nfGVWbyMyH09hsYlZvALdHeYtLvRZKLH+EJQjrGOgVzWVidgqQOwvmmYVIs1n\nG5bxbNp+x1Sr7wVvoILHZs3NuI4TlGO94jtznsL990SSMjmotIsrrbCZBJfA\nfqArSO9allcZSgwP5/FWIDsHQu1QyCN74JSxm1XbSKHIB8TbqRg8OabqEBnN\n4cKGOi5a9V6sbbJKFzJwTlUTGRoneSOEt1eh7fyzeSYhvBtoj3OIBqxgQGgT\nIx0BVoGpXS/OfCi6TmM1QMSFjTQzj4+DtGq14NilzQUyiVUVqIRUin3vmIJ6\npLnYgLkOEFQ43zRsvjXbmHx3FWt3FLy7IeQMr2oZyok8VF8HHnGPm9c/K8h7\n3kBu\r\n=nMlL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCxlswJ/t6qc4S4ukRirqJ1ozyhSmJUhRVeXECn5fLG5gIhAK/RG2TIlKiZlmLEWB9OMvcu/z9m/3y1Sm/lOSQ3dSVk"}]}},"1.0.30001158":{"name":"caniuse-lite","version":"1.0.30001158","dist":{"integrity":"sha512-s5loVYY+yKpuVA3HyW8BarzrtJvwHReuzugQXlv1iR3LKSReoFXRm86mT6hT7PEF5RxW+XQZg+6nYjlywYzQ+g==","shasum":"fce86d321369603c2bc855ee0e901a7f49f8310b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001158.tgz","fileCount":803,"unpackedSize":1495175,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfsMvMCRA9TVsSAnZWagAAzWgP/2L6G3GCievLybLUxXwR\nXkyzn305Ki4u4MHrp2if+2NeT/g5Ndl+J2M5h1ozP5qdKdYDdyM+Ld5GtzT2\n0CU0BDTn41XdZohyIL1DD+9PU6g8tbMNkLX60mHSc6o83Sc3ysJsCLj80aAK\nWPsEo83dPqhmCI1fzrj//kGydVZI+s1jvdbhdw7APlSv4f65eEQH2+IM23E/\nFDHZhOev89j1R9SoOuZOrXV6FNA2xGl/cTYhIfr84c88OYpZdntfxYA3yTTP\ngn72JovvomzAzcCFhg6hstKYYPuE9HARvffIBN+wEpnqTzutdDY0ovZei5Al\nuyIyfTafMMqKmK//g5lQErgDXBtd80aPE6L4cLf0l+eGbF71hgnbQqFqBJwb\nJQaxWIWbIp4zCySwp4BwJoPNHs6lEbFPtkGurEeljySt0cmehulXDckZG22K\nlaZTxhS9TWl6PX65Hqzx+gzDPD0xLc1BXKNPTeJcXD0++MX3LGfvbyrYo02Y\nAQhzmUS/OcepRZSamhBZJNOnz655OQK/+ci51Z4QZgTnXoAmJUnTHN1A69HO\nODlM3Ysk6rXLEihA9WyDBfwkLj23B6tDjPxUdJyeglkaM0aWxwvHq8DgWBBV\nG7TxLvGwaNHugA/rN36Pwnqkv6ZbBUo/KgGW2xlCyHPp72a2P1CjPwyNHR6l\nYmBh\r\n=9WUk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxua43B2WwnpEirWHGStiiQjcbnkFiaPNjl7LBSnILvwIgKp/rH0SneNob2o8kazhxujUIllA+38u+eb7rTETs6Xw="}]}},"1.0.30001159":{"name":"caniuse-lite","version":"1.0.30001159","dist":{"integrity":"sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA==","shasum":"bebde28f893fa9594dadcaa7d6b8e2aa0299df20","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001159.tgz","fileCount":803,"unpackedSize":1495201,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJftM46CRA9TVsSAnZWagAAuWkP/iNTMZ0LQL7LYjxYGqnW\nW2Zg3LfVFZOEzew7594NV7YJP7kRD5rytk+8gfyq1/EubO2dJxlje9bpQ7f7\n3hIQzTEcUc3Go7jCDho1i4dqowhZ6g14OzFkZJSb6bc4QyrSgmbVypA4HnKe\n+Y9EbwKt5cl1fznYsyuLMU27Fq/Wq9aFxjhmHXeofS7k9Fe9XYkKei1pQeEO\nIjLaBlTUrZMQWshV1/Ud2U0/7omdg8jS70wnatB3m3PzFKpIl2+pW/g1TPhJ\nLr5idNB+FohEg8uqk9Y/D6xPnmwZ+jPVf7/c93oUxHtg+/hy6fhj4EmSON0m\nBlwuayZ+vCZPlcWF29y9SDxSCQpusUyDZEodQ1yk74CpyGyqJY7r4JJ1lVr0\njKfeLBbqzr7jYqFrb3zGsH/qb8jLLmdgNaNhgBQxXRTpUj7pkn9GHmab56XQ\ny+pKid5ymtWWafggUQGL/UcaGlYB39K5uyPMNh7zKqsrWQ5UjXGgzG3hWNWE\nBD5xbgtrWFQV1BapUeYKkoKfxIrwshjKOyKbZ62jzikxKeUoPHCGBqnUCoqm\nhMwCNQWFN//gd3RY4lccjciQiyL++P90A4CxYOp2l4NTui0hzH0tt8ZVe8j7\ncUJyntycSFfWeSjVmPWl5EOICOFEhCeb3QVbSHFknPN+bU//ozbMWQc0DL4l\n2peH\r\n=iWBn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEe98pTPxkHhaAu835QivBH2uHMxbGjFUNIwFUB/ZHH2AiAlOb7gzKnt6fH9VL8jHKqUK5SZFfq4WYCUQ5Hh3LncKg=="}]}},"1.0.30001160":{"name":"caniuse-lite","version":"1.0.30001160","dist":{"integrity":"sha512-AtJ0gWgRgahP/8GLCtlqD1Z9Dc6I1MJj2nCuI1MADQ7xKpMhAAxxevjjyWYAG4KfSO8vkAsCZUhRve0i4luJfg==","shasum":"8c30155b11a20acb1017fa8bf656ddad977f5b8f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001160.tgz","fileCount":803,"unpackedSize":1495292,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvKktCRA9TVsSAnZWagAA5D8QAKEkQBwCB+jGBcjc76WC\n4URQ5BgMh1cYOBI4yAQpj9tEkAp4xuCtTtjczy/oCFe4jmYMXvG9BPfxXcPi\nIu/YlgsBs1zwRKsOhMCay4uFYZ+1RBHnJl8UVIhagD2B3sbp4mgCy6SBBEX9\nIQhVTyzSphzyO+WIYDBqgX1Pm1Rk5oCADTI5Mg3CIDgCXXGQcjtUeX/5yVdW\n+AotXaPr0GK9k8JtP9s1RQbJngknLzM4ugTOVAkaDmEV7M8B/JIKgTUvLYGA\nqhHLPyxQ+Ma14CUDM3FNO+ehllHESNV2/HfiUfY+rOzcA4t7hKOAkUW6l0KY\nZm0LZ5czn0cl10MMiEv4i/mmPKrqPkXPorme5aqr1VoIWPW3sZTkRCcloGSN\n94aBB7ORtY/j29YI6BOAC53SEcT9+grTdcGYCp+LcEV3UVRezTBiqzkHYw5B\nvub3c3kARONaoa5h5fg/xSbucWT3yJ0ZoSsa4il7UTVsdO3vUor9OYt9Ltra\nD5FZzoyYkXIHtN+r8LenNRdrz8+C+Tcq3NSb9+Tck5uc6XVC7hjSmPo9Zlyk\nDXy0PQyT+7EUjw1T5M3RzAADEMTeaTlEXcPqMlYewkhBTDZmCzkXJQ1/8vkE\nd8fRuaw53XQvnFJTa50XJW0+RqOdI2ICo8sYe2+EzO39naD1QlreFjgRt2Fw\ns2eq\r\n=BU5t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDf/txToP5dBsB5coBSH3b0tt8LefLuerala+f+gSuF7wIgVgcSOH81zuUg5n4xVQpeZ8hg0rXjPD7GygZ3IxN8xoM="}]}},"1.0.30001161":{"name":"caniuse-lite","version":"1.0.30001161","dist":{"integrity":"sha512-JharrCDxOqPLBULF9/SPa6yMcBRTjZARJ6sc3cuKrPfyIk64JN6kuMINWqA99Xc8uElMFcROliwtz0n9pYej+g==","shasum":"64f7ffe79ee780b8c92843ff34feb36cea4651e0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001161.tgz","fileCount":803,"unpackedSize":1500347,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvLc/CRA9TVsSAnZWagAA0qwP/3Fn/fuK2k1lkUfyHj2K\nbs2Yxe8Bs3f0noQjm+Eq64WAviKWtHVfNW98ChWqUDC7d8eZ61EzFC1HLA2g\nKWu/7FYJKIFQygDJDWoBKIXTLUP7ZJvISbvaS38oLFuvxaZlwwm6/mRh/KWh\nPEbb+kB3rwTxmZ1QgeSwfXRW2necW+5HDZw3zVj17mHz62kJzAGg5n9U0eUr\n/OUrDLiPv1oFdbCwakPmYBE2j7FQSjCvYWMTE0C2VZ7n7TFTTQBPyxaTSnSw\n04Roi8PPHp/cSeQ0uHTdytadkV9b7uQXBdDf+2QZzqD0oRyW5fOlBhmxSSfi\nXt6h3ptdIWA9U8+Ev3E4MEVUzAvVsnyePBkUC7Ppf4i2ggATTpq6UxILomMw\nV0I9oFrLpFbRKwh9z+5NeCB7xqZ2n979Cuf4DDCKAi9c2UTlsLaYGJROhf61\nV1LmAldUX9w4uncK0zXTvCXIYZpY/cZ88Jo+9Tng+Re7wmGCLktI1U99ww2N\n4IsOCtvxmJPWNZDgWdBpV/JRu/GhI7kZjDFJzri3djEFL+BW+y09kuSZjqJs\nD7Ai78I6BXc+fKhHKYEilFSOXo65MqXLJTtLB0xzlr1JedSmS+A1P3rWaRdW\nWy07vHjXELFqACH1DtXbo/frXJc7RSXKoJtxo0kDV/Yql5lXCn8Jz7maAzxq\n00Mq\r\n=OfHQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFy75XdI8VD/y9WluV4T5tDjKto5JAaFuuABqrhYrRLXAiEAxwMxLzjwGddUsmmkCPGvntA/bi49T8sUqlEhR+/+AyA="}]}},"1.0.30001162":{"name":"caniuse-lite","version":"1.0.30001162","dist":{"integrity":"sha512-E9FktFxaNnp4ky3ucIGzEXLM+Knzlpuq1oN1sFAU0KeayygabGTmOsndpo8QrL4D9pcThlf4D2pUKaDxPCUmVw==","shasum":"9f83aad1f42539ce9aab58bb177598f2f8e22ec6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001162.tgz","fileCount":803,"unpackedSize":1499904,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxKA9CRA9TVsSAnZWagAATwYQAJNoNrx3sKZCENqnyg8Q\n8b83YmRvGivTWWKXaqg5Jm1CRCn+viSMXK+b3EMIbQG2AccQX64tuDmSYzrG\n+/f5Oms24pI7Sujsqa8GlCU9UdX6iAC3CddIUjtzDodosTIPmPunnzmqRegk\nYDrmpw2hCgtTyqUJNCyk5m27z3dHAkj0c+crhneG/LHEkQxH36GY5pFpOndq\neurxYqIOWV2T4Wt9ZafQYikVbvfs5nkl0EuOsvws3cVnOOeYAknDyhoxMLpT\nZVCrT8IXZLaG2i/q7tdlt73Zdi7p8RyKqkGstxMmTSJMB3CIG0jyDIzJkMze\nu8KOtFFj1WV/3Ugff42Zk7g9cVkZ3OIBWylgYgR6z6d9XiGxuF88QfmGDX3o\nFWTY0Yd/RoewK3SII36vhTlkolPw0buicHtWSn3Yb+8DXkzHqImsKYp8j51g\n+s41AR5QOuemqH89UkgVT3nBDcA+ALRVqxLS93S67FzQT0e5YHhbvr5WwcQX\n7uZ6YvZdngYYeUyviA+I0IdEfymI/EN8wcVSt4tspZ/XEjZ98lwOj2PqRmMJ\nTX1hWhvf6aRytBQuje/5v6+MFmc7dOMRdjzFyM0ErWIoVkB2PnK2QWfeksxR\nPo4cyzDiqhZlIflspwADrvbG73qRSeCXFNvG6QGN7Mu199P7fCbxbvxhp6pB\nnDZr\r\n=XC3e\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKJ6m12gqj2lvMLlAlulO+AnPGd28EiDVz3wINjcB6xgIgKAtKNmxhqQXbls6mkxFHJKnpdOSR0fWfM4dzA99JDCI="}]}},"1.0.30001163":{"name":"caniuse-lite","version":"1.0.30001163","dist":{"integrity":"sha512-QQbOGkHWnvhn3Dlf4scPlXTZVhGOK+2qCOP5gPxqzXHhtn3tZHwNdH9qNcQRWN0f3tDYrsyXFJCFiP/GLzI5Vg==","shasum":"7595ae1b430fb4ad6adcd4f0a3d705efad9dc379","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001163.tgz","fileCount":804,"unpackedSize":1501085,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxVcCCRA9TVsSAnZWagAAY6IP/j7iSoNEq67avdJ4xwg7\nwYC27CxNNxei/AOw8Q7ujyqNl3bu/uHNNx/iPtpA7Eswj0aVeyL+aZwALmkY\nozWmJJC8sdUg1aCrAjn8eeqyZvCCqxhLwb3bI/BO114e19Q+yXFzQKaOsqvW\ncfzFHPu8QLQn5XRva3ly4cGlX7kAZDcMO7bp7fyhf3FiNtqqGeRp0DxoSOg4\no/YIr5iLann8et/woRVu787ESxNLbjgJYBFAYHOidryotSx37mbCodMzhd84\nbdiTIeAZDP7ut32YfOuIKNEfC0CkNNR9KD6iD6rYF8d9qsw4iro9j9qiCBpL\nTkCYZYuNhkskhDUURZ/hKZAc8yeUDSszSn+TfLKaUYPjL2MN0whEj1/3V+du\nkLLshzrNPW3AkPGi+oRPSSNV/icCkwoYRNclibCoYxxdL6Z/D50x59ECUE2v\nK59wvyMvLdSFV0BNYBZ+8nav+uWMwEyPg1FJgopd4UDm0Ty2KAxgR1U6Zcen\nrr9Sd99IBOCdvwJ6WM3LFR8FYptkpo+FP/XmrnEACcOp3w1XPIF7MeZpZTEk\nF1hTbfuUTZdRf4kVJtqJ8UmY4GVlLdUa1EL3JmGPhWQWJPgnM6k4IdRH/Oev\nbmKw0M/tFONYB9o8vQIUiuFtO9iLohJ6jMNwzfT4rzJ7WVOsysEwerydNU9q\nlVLS\r\n=MGuG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFZde8z5TGltdjDj7smbibZqcjfysrITQnt7hHQ+0YfhAiAzVfM0WzT/MSi9sFNIID6xaBtiplmu2QGkWiLZbNuO7Q=="}]}},"1.0.30001164":{"name":"caniuse-lite","version":"1.0.30001164","dist":{"integrity":"sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==","shasum":"5bbfd64ca605d43132f13cc7fdabb17c3036bfdc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001164.tgz","fileCount":804,"unpackedSize":1501151,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxfGxCRA9TVsSAnZWagAA4OYQAKM9iDgrgoZTL4tGeXIl\neF/xvrILdSrZXyKqhhjVzc9z7NBnyZFwQAoDl9LGWK5oJchP8sQsKF/ORbK9\n3nV7MSAPhlPS+YbC7GwehQR/8A34pgwbiNSFZmzm1Y7w/zoFpFaUgF/xuwqQ\n1MP3PLwRRW16fJQrQQabYYohLXo6QW2VSt81gKi4U9XNOmwtlTNHMU5QqpLq\nGx+f1n4q5n5KtRqetKuhzixCL1WGjTMgVpysq4H2kEj7C6jEJHuJmWqhZbJa\nmqVidhOqNnbTIstX9H0/7bqBV5SqkYP4FCxJDXzXFkIsnPpIQ8bRf3NgjWAF\nb7j+g64wCFB03sZmf+hxXz44+Vzr6JVvuCmBHk++PrxQf1+Bht+NNv6do1SQ\nuU/aJDwEwpZpuX9fpPChgJCSgbawnJz01BLP8hnwcVfVC6ct+Js0t16JeQML\nTsXecZRkz93NCl7VwrjFSDgCHWnUgjLm+WXBZhDzA8rDCpjuJii2QflKs2x2\nhHZQoLlQDb2umsI8wfi/45LCo5irO3SQCi4pTi3FctXwjN0ljcPeQC0/EDdY\nKuKMcV30+W3Ww3xnyHsmrFTeMVJyHwmUa2JM9axzJybu+EfObnRugOjGWlYT\n+PZhvanmVqvH1q+m8jJ+ElROm2JlCUq3eQ4dOo7vjdGFSDQKyanX8RgTfRbL\nTDub\r\n=U+c6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGCrq3jOv1BIpdR0blcPZi5jnfVTEHG40a9DgcVDKIyAIgK1o7RyIh78RRLVQj+Kw9aervUDN1H2tcrcyO0ILfoZg="}]}},"1.0.30001165":{"name":"caniuse-lite","version":"1.0.30001165","dist":{"integrity":"sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==","shasum":"32955490d2f60290bb186bb754f2981917fa744f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001165.tgz","fileCount":804,"unpackedSize":1510437,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfyeZMCRA9TVsSAnZWagAAiXMP/RCwaakqwDZpcOXSc4cl\nEat225aYKQrcXFXJMUajP+4uBUf73UBtKqNxVoLM0ke8U/8Udv3IzGail2C6\neKpxTh2tLEgjXBU8Isx6jnqRZZ9roAiTn5nKh2TReGkLzUy1lO9gVhSAWm9j\ntKQxa5huob1dmbN+VD6Ggr2MyJqIO1vb2axrQz++T3pkRr2roIiRigOMK4LS\n3V+KmJTvscStZcAG/s9+nFyYBjbi2ZTKED4WyWhossQEQABHq/qcsKanUIdz\nIqWsGlgsXj9HEQ5/VZQbzExu5V918dBAY1NqJvJPkfd1Zsqe2g3MMXLC7Cz2\n50kpfLeoxeU61Ef1NQtTEURJbrqDnmdx0To0k7i3lqVXNna8Vah9EawY+uAL\n7gO3CQX99y2gc8s4ybkLLqCY2+dOJxr3E1/GvnReXlb5y06RpBkYnNK6p4BZ\nxvPsf6IR3fTeW094FHs46sJ613+ls4wYaH5ab5QuQdYoa8j3XpqW8kgKW3Sb\nAu8nnSsc8rB/eNjaCZho+c1wwLr4zvkAITkT+TAJGP4VOOWHvhdHds4+u+6I\nm5dozZId2zYD2LaTZZBo14+70fxZn2xV9X0W6m3QRHZP4Ov4puHJBub1qyvz\nBBdJiY/b1aFb1ELfpOeKB/5bK6xHDtg1J1XS6E11KJr4O/PyD9qtb6K35pVc\n9LWM\r\n=uDRE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCIA6GZZNNfqrgI66oDtVouTTCuMo5me8ZZyaiJqapwyAIhAJ8udLmkXWDjwA7VthuASkp0iYf5kwMXj3gZT9oK5dCw"}]}},"1.0.30001166":{"name":"caniuse-lite","version":"1.0.30001166","dist":{"integrity":"sha512-nCL4LzYK7F4mL0TjEMeYavafOGnBa98vTudH5c8lW9izUjnB99InG6pmC1ElAI1p0GlyZajv4ltUdFXvOHIl1A==","shasum":"ca73e8747acfd16a4fd6c4b784f1b995f9698cf8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001166.tgz","fileCount":804,"unpackedSize":1510529,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf1xU7CRA9TVsSAnZWagAA3usP/j4b6H+oZUH55lA9KhsW\nKeaIPwDAaAmPWh7zTl/KDYmGmjEh08+/0tv43fUWaJkVUw3CJaKYCUhB5qDU\nC56TCF7eF+LUBpk1XoBgKHz/7nUnhjZsOW08A/VkkTieWtGa0x5Ij8H6e8Ty\nVQu68pvWrUDHwnqbS+WHVJ2dsH+ddkRXYpJSfIodi8DOKlbvYFfsGOtCaLsB\nLo92dU6lH9JQtaVaIpzW8I/dmSc1W3Orxgl/0yFvShFrx3qJx6lX8e/zS1UY\nALDyYXt7g085ORDiEQ07dV1YjRHU9n9okOTz82lhyp2jjr83R+uYWPiW9x9+\ngtt8DuljjhZQwtbat+/PMKibyfymbkujf4zp88mUFZZjAIk5cKiiZfWN/ui4\nQTJ0PsyDMA6nLKqHnyGfFxmfS00k6Y9nDEr1yPAFaKc09ZVpzEoUPuFzXmSK\nUT4ZDBss0emlmTZfC5aVw50M685smgo7hz089udV2vbfUmIOJeHKQ2e4Mppo\nOvVERbc3W8OvHZvsA1fhJOQk3L5ighslwi+FtOfWxomT4Bv8PlH2LaYfnvRl\n+ifRp9nUv4v++zh9XMVWgV7uhr/bJH362CZZSM0v4R++POq7KojX8NJ0K/fl\nIJQ+e3GStNmeJHG+Bkd5/PyYgu7UVxGvPoSQNyDz9ukC5jLWDF8nTxC55aZ1\n921P\r\n=AIM2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB0B95u/hidJdhIscJhjoLTn/RPQaKHRviVAi2fxDFT4AiAIfZPWa4wcxKeAqqD12OlWmHOmtFILYYsazzVpHkdFSg=="}]}},"1.0.30001168":{"name":"caniuse-lite","version":"1.0.30001168","dist":{"integrity":"sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==","shasum":"6fcd098c139d003b9bd484cbb9ca26cb89907f9a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001168.tgz","fileCount":804,"unpackedSize":1512303,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf2ZwfCRA9TVsSAnZWagAAeIUQAKNH85x2xRYtUw4JKn1c\n4e2eTKisMdEJX2m9JIGmrFt1VRoXyPnrxBTPoaBrK57zJJy5He2nEftKPaWV\n19Ev16/3/hV770RlJ36kK7j49CHlJoTbzaNmJUeN4Dtw8j12KoRcPtD9b3fU\nvaMEndwZWuK7OAIEJBDdg/tYzb2Xu+aZqg2o4zj4nQlXilDMwBQTS1IwQHGn\nFMK6Vq+YgS3uTCwPtVBzWO1s1WepCPIdNYeYo+zk0s2d4RwH9S3qOcZJ03sk\ng/GQxCZ15IxzO3cJyVGWptWtcnwZ0GK63SdlTiX+TkOt239SqHgxaGTiCntI\nlrE2TeAbrTRtEIyEkrNHCHVb5PgJSGzLD9NSEajRQE78sSCU642B4VWEIpbj\nUopZDTapzZ72UVEoDwmOL307sqyx0RpIMFpcXC/f1Je0mulGGtgvg381Fj43\njBFAfJsijLB+W/J2EjJVz68BjHjL48/iyzkwKYVXCXNdb37wgPtoRwhFZ96j\nE2dAhjR/c5SOnyqJazT/fJB5ganDAXTj4uBoFWgsnDNs2LxTOm2/4ZiM8PLV\ndiGjDWve24bzyn99N2sDYpALp+Gq//8PAUEC+Ow4ryxoYzmvJp9s8e+yVa9C\nEKn209/SWCfgM1Dc3rU3T9/9kKPXTpt5xpT4VT+gx80YL+pqpCNi1BZ9lAIV\njS0g\r\n=AFoD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7K7nA1Npm07i81pywOZPcOsTmIgG9SHpItOliWw0zJAIhAJBXHwbj+KIU1PYeaRgr4n0aBbVEacPFirZx53lAKtU6"}]}},"1.0.30001170":{"name":"caniuse-lite","version":"1.0.30001170","dist":{"integrity":"sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==","shasum":"0088bfecc6a14694969e391cc29d7eb6362ca6a7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001170.tgz","fileCount":804,"unpackedSize":1512378,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf3vA6CRA9TVsSAnZWagAAmpwP/iD3Xaqv2RO8kyQlWJQ1\nhZOJS8LRZfyfvel7dXPmvHqgh6Rlb3j9LA9O31mo5gshLun8pP+O0QFxqSf+\n4eMDpU6IYfOHQ+VY/wJK65U01tygkI27Kq2GDcGrXXp5rE4jc4q4a7s6t7fp\nT4WOi+Plls6AO7miEfC1G64wtGlGkYXdkD2aeUrdg2UkpGIxGIaAiTMQzS5M\nkAKlb/Rj+LQesaPArs2JFgltIZ923WH4Sn79dUa1bcBtTtfUTf2ohsjBRsss\n076GiU/X7pUuFQ5x8ssmCbly3pyPKwybKahK22/vXgnpeDRyrx1JY8xIOJrb\nKUTE5pTBQPNVRkLvmo46Qmb85kgtwGMkaZAedQJFY7eqiA4ZeXAFhzt4pTYP\nqN0vKK8PY223KmzmXhbARi3DPFlMQwRkJ2ow/iNu09zuFrWCOkO1kVFDKvFx\nsl2OR9rNlCBz9vvbgIYamC2MnUNFyC1CpivwxGyQPE5gMBxP/ra+uMQnaxgS\nnQLmSm8RfMHXj14Mwq2AndEDsVn0c9mcIQ8mh+/Aqy9YbcKbc/9BXchDtXLo\ncBc7FDIxWVbvRfvAldmMfmL+OBedvgLlQzqcI2f+X/HYGkEuRDEM7seJDq/o\nTlAbvJnH/w21braraRlqKZ7tYIKHu2hMB77OeLn50AOeJR2ZSYoO+AsNoZ+Z\nw6hj\r\n=3ud4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAN5wO/SvtDn6MHvJhMCrQezDGWX6Xc79S73eZsGWu/uAiBa0qeCI0jSF78YuteM+79wrC61Ds8XSLuQfwQ9/0FOUA=="}]}},"1.0.30001171":{"name":"caniuse-lite","version":"1.0.30001171","dist":{"integrity":"sha512-5Alrh8TTYPG9IH4UkRqEBZoEToWRLvPbSQokvzSz0lii8/FOWKG4keO1HoYfPWs8IF/NH/dyNPg1cmJGvV3Zlg==","shasum":"3291e11e02699ad0a29e69b8d407666fc843eba7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001171.tgz","fileCount":804,"unpackedSize":1512454,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf6nlFCRA9TVsSAnZWagAA/SgP/R3TJf6Vy59ue8X4qoNR\nQYLzWoLoZMxCgAlfSxrrb8KPzIqgjtc34hwL81LI7vymO2tIecsNfE17Jvql\nmPWpAblPHjnd4eneFxXOIHrypV5S/wvrrlcVAx7lZRNpKZTJax/dXmJucbPC\nR+cjL0jDHZZ27LeFetrE99GWp1BXYQsMEA9dVgFz++uvBZB2P8rENYOrajyX\nMgXOH/D0B80Fr7Mkz4s9Ll2NioQg7RJb8io8YjjQeq4ZobcYktTdPOlUdWk+\nw/fJTY8/tjiXzJDfTtQOQcmf3ALBLvihCFk+DJW/zwaGlxQCxF75TnZ25pvq\n4GFPiwdGdGw3nUzwizE/83u/9CNvnsQjF4L9mSGQzBD4p97iiCJNObL3RB/k\nLg7gCWzXhkb7l4KVxgnwzJcsPVR4uB2s8C+ER5Emm0o0e/3xxPrwxkliNGuB\nRTMGw8S25wpJquGR8+rsS5Xdc3WXO/TIoh1yRUzyoo1v26DeLke1mxp6raUC\nY9cMCgkfPPqEeYYqSaY5l5Tkb0CrWLR2qPfh++1ObZmGzfw8JLUpz+sNFZNa\nz2ddFjxu55ve2d5M83hMEXOu+5QekUpXrn7LoCNDilBfBuRERHZn22+wJ45M\nL0XxwTYDwFih3PtcqovmHFOaFc3UXQL/1v3K9aGOwEeMvleGTZWb1QMzfN84\npLur\r\n=RdjD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCPRMWGE5/YZ+AEgZNom72Wn4fg5VpNir4dFQDHXwx9DwIhAOKL6YXQ/XQriCpki9xBA0UTjsxB/2axz+Nva962meYt"}]}},"1.0.30001173":{"name":"caniuse-lite","version":"1.0.30001173","dist":{"integrity":"sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw==","shasum":"3c47bbe3cd6d7a9eda7f50ac016d158005569f56","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001173.tgz","fileCount":804,"unpackedSize":1503770,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf8qiaCRA9TVsSAnZWagAAGGIP/iNC+kplrMcwtcq9Nkle\nz8iGpPQolP/95zdp7deNfiBpeDR2hJL0K9phdPzwHGFwv8+FJIpQte7QOjxG\n4RWXGjn9yQWPaA687VU8rycHS9bdjSbRvNhMm2+FiHwenKi95fNrRd0LFYXL\ncS+eJuvyBYiKHV+ebvLmNskQj3ciW0pTnZXU3DjpuzfUWs2iH6l8YuFxBUNn\nwxO2wlLYkzyjRtwuqU/4Djlp71jWgi9qKeg0TROQkr2c1kORhMZMutk9k0kt\n+AFgMf7sBkXf7ZfhTsWOCads9SVFt69GVcA0BimuKwQ7qG2b48KvRNkg462x\n1b3jX7L58r0VfiOkt8/ZmkMzqUiQ4YLduldrOgBGh6+Tn8nKludF0QauLX3X\nF3NmEWFmmDdApiryQ5W6TU7m8ias3Wp5vkU/phHJ0s/8enAp2Hr+zf5/A8Yl\n0Is0ZMpLYtorPzOBs96BRS7w86UlkI4QGESzZd6EEZaW3n9Musm+HTjL8jtE\nkXK5F0x4KDvfLA1T92+KuqPHJKwN+viUaM6FUnaBZu77EEspeSIXl+LJ8a7c\nJDq5SSi1+sMec6gkzqKKOC8+i8BlpyzvkAGSSZCTZOp40mR5KBTHY75xEbDW\neqIXIdmHVI9louBwgoOlgtUlDIOjOkGRhY6ogGLJIV5RfV9TP0p1PjhOO9f7\nkpVK\r\n=SuhJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/dNbXA9fE50tyhoqn0fdqqCFWAXTQ1IGExJetkjjipgIhAKsmPXogE3j5WCkVoCBS4+IWGwxIIvi4AYWUMST1Sw8A"}]}},"1.0.30001174":{"name":"caniuse-lite","version":"1.0.30001174","dist":{"integrity":"sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==","shasum":"0f2aca2153fd88ceb07a2bb982fc2acb787623c4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001174.tgz","fileCount":804,"unpackedSize":1503836,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf+3KdCRA9TVsSAnZWagAAP9MP/jCAnjBa2/qMHFtT+x7p\n8oAi/5Vp/aluIvbYLEJcQarv5JkTc8kc7XfdGq+UGY2EYYxMIn51AhbR3OZI\nqriQ6FlTlslZRqD0A1Z2M3t/fh4JKykbaF+QXFTXyZkOw8r8FLYAQMqpnjQ7\n9Ia/O3DAjmUeU48ef0EHspGAXTWrqFh8y4xnT2Ngh3QcG/CAmAfdURWSX0Ke\nwCZ5aKOp3zDk9BwpV72SbqsUn2G2y8xj4XQB8xn87TGXsubcr3rl8SV1nawe\nWnr88LpEm0kRfaswcylP5J6IVvQ01C17zLBpaUC1GqPOBBjaU+CActUFSkkR\nAe18C9UFR1ufLOTGbfmIkYqRnC4cw5F460jQ0zBFhJEnChctVbtPKMSFRHRm\nvg8qz6aKl6aV+i3O88oLGwP3Fu8k1rjWRLN1OeUmSwFXo2tIWVvp0RkzHzSS\nKPdp66cQyGnOQIGPjCOa5xtPHFo0sHd0aOFOGQPve4BFgXSgPq8hGOcJLKQV\nG9lqKWHY6KU2Xy+QENo2nIHZxpmMYlvsray+A3W4BFaTB3Nkelo3bUqrSFqv\ny7Zlf0u+Pp43cGj+M4mh9X4q96MyEvE/k7d/NBejgGoj99NTaWaaEUCttB0M\nJXlPjeNj4+xG6hy2qgmA6alghdbXAfQCe90zmVePHYkqi50fZIq4V8kz80NS\nKtYB\r\n=n6W5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID6RI8qE+ZiEcvwoxd9h0X/pP9GBesWNosmR6sSIw+4uAiEAtXNXp8Kdp+hZQ33f2G9cI/zha6qGVILWI5cU3Biqp5A="}]}},"1.0.30001176":{"name":"caniuse-lite","version":"1.0.30001176","dist":{"integrity":"sha512-VWdkYmqdkDLRe0lvfJlZQ43rnjKqIGKHWhWWRbkqMsJIUaYDNf/K/sdZZcVO6YKQklubokdkJY+ujArsuJ5cag==","shasum":"e44bac506d4656bae4944a1417f41597bd307335","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001176.tgz","fileCount":804,"unpackedSize":1503900,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf/oYUCRA9TVsSAnZWagAACG8P/jDmcdjXZRW/gkZkrgBV\nIigJqQlaHGzngj60ByXqHzeHneMEUqYK404dFMkQ/IuD+01hEXV121hRXVrQ\ndN7aDnC67n9g0RXK1XfZRG7mO7XgdrnhmxWIYAh/Ingc9rkBasrDmxXtqV6S\nx+PnEWNClu7dQUgTz3YZhp9z0xXhBM8hz3l7h0+hNSQ9JMhyXryolYMiMW7v\ndQ/vslGX3xu0VXulxelUU2FNrZ32gYu6hzgndsMsl3zug4gGoFZsrN/ULbKc\nuISJ7YRw+SnWElTfnK/9WGUhfQknQoemAswX/fsZIOBf0nc2ZcX5vaBfhrUM\ncDiIPDrIxmZHqusgv25gJ+MHE/jO1VLcSm080q+gYUCBXrEgS/5hQZPriSYl\nBWLoTfH41pC//m28rqTxt6c6WnO2RuiDo6WsnurmjjIV1ifOp0AKK7WGauMU\ndsFyUuaRapAdMbbBMG5dJf6VcS3e0kS/hkqmQicNNJRj3D4Qmj1doMlAra5h\npxPvyXSrJ6NqRGCFXvgxvQB9KcG8TqvGvvJhfg8imidR9sgZSRpqHwbYUC2m\nqxDGe1RnEQpSQ6fb/WgF5opilOjkP35Rvz7sPIWbY+UM8GaVVeQ69EngvwRI\nPfECuUgD51MQ0Kv3TlSVTCwTm6HjqSkl8b4joKmdfHY2d0JXvKrYWQLsJA8x\nLG9F\r\n=3b0E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDRphO52ZWZPUWajSFKGXKdUzznaLfLPFONLDuIqTXo6QIgIQ76m4j9wLccUOcRigP7S63I+8YOJOD80+JXj7aduQc="}]}},"1.0.30001177":{"name":"caniuse-lite","version":"1.0.30001177","dist":{"integrity":"sha512-6Ld7t3ifCL02jTj3MxPMM5wAYjbo4h/TAQGFTgv1inihP1tWnWp8mxxT4ut4JBEHLbpFXEXJJQ119JCJTBkYDw==","shasum":"2c3b384933aafda03e29ccca7bb3d8c3389e1ece","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001177.tgz","fileCount":805,"unpackedSize":1505102,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf/+WpCRA9TVsSAnZWagAA4VIP/2vTZclj1aLEE7b2kCqY\nZI58bAu8NJQiaBhG+YY2pTY7kz4G59R/9WN8HHqljd9XoLjzn9FTEqLDxDka\nNh1NQdrmVmwg1gOwoZmMwMP1EazqWtDG/Nt3Ai5aHQS9pKsQIytJlQWRVYZ9\n4huf8pyRsS6vsVvO+ox/uvbW7Tqi0vYt/y9QS2ecfi8/PwgYEIuwMSwL6PEq\na1YdSmWFLKtDk4NUEMdV2dMXJneekhu+/QPP+/xMz87L+mv0mHVF3SVgI4HU\nM6ZnWa8UgDP1eFLUFsP/mhZL8W2/cn6kquTpi16Wj2m5bANiDtwCtUmpq7lZ\nI4R2bOcJOp2IuoUORztzZ2tBzit63YhAjO2wD++pjQEa1X55Msr3m9aH89fB\nmI78Uih9MlxzzZxAOJfbeA1zzmVdU3xNodjHplYubvda+nq+eTXwrm0Po1cb\nuvS2t2gkrVC+hf3mqxqGukpgLfmIjHGyYI0ehdeBYGqXxcISHugGiyViwXnw\nKDrY6dFk5Bu0pXL2Odo+aBQmqyAdWUC+Zq2eW3AjmpgcLwoMHzxuqigh+His\nxXjosaSmRuFCgsVka7mk5BaVU28RJN0YD0d5Q+/UU/xKYZ2RY6tdIRicAHFP\nDv89BtcRxwfTBycgQMDVDOKcoe+6Ogur+yRQkYBpBDS/JJbYOO62wup3z4hv\n5CaQ\r\n=aYa8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCdtoxQwwFy41mWfuPxqiwfTR0s8k+cQFnCW7SJ4jb/lgIgZgcsUfzOGkGd2EJAKKjnYDfn9caq+x6PdYSN9COV/L8="}]}},"1.0.30001178":{"name":"caniuse-lite","version":"1.0.30001178","dist":{"integrity":"sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==","shasum":"3ad813b2b2c7d585b0be0a2440e1e233c6eabdbc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001178.tgz","fileCount":805,"unpackedSize":1505168,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgA9owCRA9TVsSAnZWagAACDsP/ik+CDg6fjCsDy2n++6u\nx3lZClPJBxbazJ26OJSMVpec095m7GGcYTvXuSplmIrAJu0POFZyQHZAyNcx\nXWrPGAPL68F3nJSPJuzXZXw1qvPQYDBbbaIE2G4Ar8lF6mnUFevUtZtVJbBW\n3or/AK6tC4cc7SWNScF2jtRnnGiyuIs4bwygq763VwOKh74z41v7XsgpzvCP\n5CWpj4Y8NRLfEqrISp/06PeC4wtLCMLEK4U+Advp/QN9JE+S2pR4I+dzWxmM\nAqya0Mqbvdln9brbDYkC6kOyylB2cMW/73VzB+b0Ekh5/e+5jfQRZD8Pf/fj\nGHcW1J/rvvIuN7695zg0mOYE/NT8YWVEjt5BUaih4fDVkBct/92Vlot5pS/v\nBq9o1rm3s0Du3LV+dZ1ZUmxXbSBGdr5YqjLVMM+DgR4IpxCQwN5qZN8jAkgj\n/8KXSKwgVelPHfTUo/Dx2MDiyFC2FSIW+p/y6IxlBWhU1L1c4pWJc7EU9eiB\n9IwTVoZgkZaFhC9RGk75LF97ytJAroOBW1aoYW3ENG9uWLUiHNM1OJhCT6n6\nweD7/jGjctHf0v7v/oDLGd2VMUbQ16EaCSz4YA04/1Fa5kkmy2woucljCcKs\nUfFkPr6YIUFaX+ZFQojumFRpXAr+2CdZ6x6npzilpF6boSPZDqBz4bFRYhyk\ng9vD\r\n=TzzL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCIMl7PlkW++1lha0pkUO1SGsvNDS+vhlxUaIAaJon/aQIhAIw/nKF70c6MIjLsCi6PA4VuO+t7tHmg3E2+EngtzIEk"}]}},"1.0.30001179":{"name":"caniuse-lite","version":"1.0.30001179","dist":{"integrity":"sha512-blMmO0QQujuUWZKyVrD1msR4WNDAqb/UPO1Sw2WWsQ7deoM5bJiicKnWJ1Y0NS/aGINSnKPIWBMw5luX+NDUCA==","shasum":"b0803883b4471a6c62066fb1752756f8afc699c8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001179.tgz","fileCount":805,"unpackedSize":1505244,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCS44CRA9TVsSAnZWagAAXHQP/24gaXopQyRhZCZu8rx2\nMSp7iPrjbze82xMM0fcnrxDHu6WjdzDUalVF1ulqlTfcPRT7YN2hsHF1zorx\n2UdDUwVu4dZOB0Xun5yiOZNLNOOIHazC/34neYH4QCeqSPcPMK7qqPK9Yqv3\nOPVTmSwqoUXUijdsX3ldx3si0usbIhrtoJhIXzQsF4XlI4o6g5zLsoS9msfW\n/tTheRR1mXjEJ3LOWHNJnVsY0XOC8+x+qQkat6Y9lwlI794nZH1aqPLBpL8K\nYo06+taGSfpyECPN7fWmeuAAeUIvmXaZmaRI+rfjLlbr/jdPtl91qi6wDXGm\nDQ8o2RXKXZ0VqXn6opX7tjGo1cCM5p/3E5IMhvQRug7XCZMJCI9Iomh4c5W7\nRvmDNO1COapJSYm5Miwhn7oYnwlHTtnF9P/K/vzsOwENWLW/+1bjZnlJra29\ndXo09Vg3KpAuxPBM9LNMeGBRltL1Gi4BxRV4SF3vxjvfI8+7DATiiZCXRmbZ\naUChYZsVnMzDK05NcX1FnS+inWw791g2RX0M5hSu4e+4OSyHuq4QNnfbvNzi\nZSABdsVYiFzMUOx3HVoxq62U6gc7E/yY+SL8EPXNXWtJTvIoaxTko0Li9oct\n7awHBW3l4AQ8Kum4XF6F4YtFJl2qJhT/Bgzscl/NV007ub8hcjwL3YeKihft\nGeEv\r\n=ybvu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDqHUvpfH7+n/lIG2LjbWLERkVvrAmS6PyXL88GeRRU0gIhAM8WlmTgNHfCzB3WoO3vySDW9W6hWja+WAAt0cufx6jM"}]}},"1.0.30001180":{"name":"caniuse-lite","version":"1.0.30001180","dist":{"integrity":"sha512-n8JVqXuZMVSPKiPiypjFtDTXc4jWIdjxull0f92WLo7e1MSi3uJ3NvveakSh/aCl1QKFAvIz3vIj0v+0K+FrXw==","shasum":"67abcd6d1edf48fa5e7d1e84091d1d65ab76e33b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001180.tgz","fileCount":805,"unpackedSize":1508619,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgERdFCRA9TVsSAnZWagAAkU0P/RgzM6AD9oI3HwHt8tbp\nSpglfG7jckVJn7iDjwdWe6wnHP6hh/8oYTV9l6r1IKKw9qOXohzphGZgvf9+\nXgH+MXH+t/g7Xq7oUgdP/wKsaX1vNoN87KIvKHATXE/FCNX2cKtyGyyfK5kp\npkat56y+cBSg8Ms0Z5oUYqKv/1z1SLJKMFNGTggaaaahKoDBsKwd3Yg/0xux\nmHf7sjxoeOHLnWZJBA7lpp3YsClNFNEQa+e9IA7cUZumzffLVFBG8iV4Mg5r\nLfwliSwteLHaViJDurJmTcdzX0lGeUs5qZZ+ooqHVUozQIpLrGF3+UKmKX0N\n+04RuYjtJd+7hqWeBh78gYF4ZZktywWT+RBdAg8N0lN7MJHXb1uEAzgqpQzm\n+RrINFQwNHwbGvE/ODBSXZOPRZht01Gfmo3strgSfdlzoCiQZDAQWTUDJ6v5\n2M3WjPzbdQLzFRVWvzFZJ9gRIcrFJhoidWiEZ6WFpsygkIGVZ5uK3PjgBE/6\n4zJCU7Bi5rJpeO+O2Twa9LSe+TlE7cLmt27eJNcmwIdIwLCDx1FJgFQdWep7\n3wswUv6w4ohL40gwZ8TWg30avxLqk+kGkYKcnzoe4MPnD9qYWJVAscXqdnRi\nhmxm1T0W2/vrLxGws9ec3SjVyF0WOf3/e09q0WQ1q2Q3u3zzz5SEnRTC2Fg5\nuV1k\r\n=8lse\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEZW0CedzQiSnSj45oD4JORawNCqn3DVLfNwZaL1TisMAiEArNbF6X2M1DPppIPAPfrds3CWVaQ2sS9Caw4/pxkugg4="}]}},"1.0.30001181":{"name":"caniuse-lite","version":"1.0.30001181","dist":{"integrity":"sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==","shasum":"4f0e5184e1ea7c3bf2727e735cbe7ca9a451d673","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001181.tgz","fileCount":805,"unpackedSize":1510388,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgE6xDCRA9TVsSAnZWagAAHxMQAJGNG+QAxzPN3MFqh6Xq\n+ghk+Ktl3u5YbxDRk0nty/eCj/4Ysa5oVIp9TZhZCbKx6X97gVlvmHHcwsa2\nKMz9YR1KhiVMKc6yavPu8rFwKGhQQhp5fOPc+sxTV2Cd2VdEgOCTtGhGR8+P\nVOD95g2k6qIgwKYE3xoIPM7ThiHJ62vLGA0nvdHYRSywywbjN8Mj0YlTgbwS\nAf5+oJnSZ/48yG/kCsGINNAk1y2MW1ky/rroSTBDhG0lMKlXfhnij3PxIpaa\nS+fPJqbLMb0pfrq+ghew6sfBj49am7y9ugYGlrsrGxhH6zP16x07AxAE6q7L\nHIXqKaJxDYnI2KlMsDXUpWXc3hVXMJAjW+jZYcKqGUcSl9xMFJ4LvQ0tKWQt\nHE7gv/zI/cpxL5rq35NZYzX29i56hfbh28LXCNAwbO2AaL7Ctk3+BUtQaqZh\nkgkBVSu9ch3GJloszsjcOgcvOKtAF7RCNCLeRPEJkrGd4Z4t6qr5GaDhEagt\nAmRNZCsA7fHpPIRaXjjqeeQjMQDWxdaRbhXu2VZn4DxmsRfONygjuHcZrSFx\nE/rAGEM429wb9IVbbuyBojbzOBrs8ASMt8JPuLtOI8auIRDn6uFHMKJTeRyH\n9UgkCoxCmmVcTV8aaCpBEH8p5mDZcSgTvCbv+YnimTRg23ArD3VUJWHtAsMp\niOEd\r\n=TCea\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFSqtJuqPpSfj4bjRr0RTgmMBBnNyyOZAGFi9DPa4ajhAiAWD3XhGQZuLgiPzts+9u/MX3VXa4DS0CkSUJssT/0uug=="}]}},"1.0.30001183":{"name":"caniuse-lite","version":"1.0.30001183","dist":{"integrity":"sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw==","shasum":"7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001183.tgz","fileCount":805,"unpackedSize":1510041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgGQA/CRA9TVsSAnZWagAA89UP/3EW0rmu+K+We/CzX7RO\n4pcK3kMMsH4hOpDaepvKG5yxFxjDQuzWfDNu8C7XPjH1Jb+LoplpMbA5WQr+\ny1aXN7srvf2smvDAsVaFym9D23QrARBG2EvnPETlcZ2WZsmnANNJos7ztnvB\nNm13UCF+9f8oeEzCAYYU9OKw2Af0ZJis5b2eCWErmleqGiu+fYhTPcTu47N8\nnOCd0f/yc986m3DB/uIz0aS05PrW0DzzT1slNW30j9psMmgHrFXixlFzv2WY\n9RKKDqvPG1Is4V4ZAmVc8xJ5mfpvwDyHEHK5Gn4ijwN5hqFclT99tWAQlJSv\n/w2QSGbrj48CJUQr5uH015J5y5rgM+kCXEyF3fmoD6P1xUnLs36caC74E41M\nq2TEhMNwT8xtvtGqr2mjjMNQHfDkKcpGvFxD9qQgvpu0PhhQCNmC7aZj6upO\nbik8HjQewMFppWlo0zn/3GkLxLkafipIK0JJsj+KZxTjNfWzBOO2nWKBD97v\noZSSS3KRPcKM1RuYnvRBw2dafk1U+0zP7bF4Lw1zbC+xMFyG9o8gtNGiNsVI\nfTf/k/XAWcqcP26hsPMw/hOFll0E/VyFP77hXdqYVwLl+tDuN9V3I0dbJ+n2\nAmHZgcnm9f0U8Ur276m1iGxSFMUFncuL9iE0xRzlFiQZ8fIHosvtz+FP9ZhU\nvIr3\r\n=c2bH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEsj61zQuO/gK0TZxss1ubG8rSWv7MVzRi060l+WUkHjAiAIwo6SXI5Aakex15DoWGDpDTNTIYX5DA/AQDAebTi3AA=="}]}},"1.0.30001185":{"name":"caniuse-lite","version":"1.0.30001185","dist":{"integrity":"sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg==","shasum":"3482a407d261da04393e2f0d61eefbc53be43b95","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001185.tgz","fileCount":805,"unpackedSize":1509914,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgHOa6CRA9TVsSAnZWagAAQq4P/31NOLzyQcQ7VCXeSNfV\n4TS8qv2a64PLQANZC758a1xEZ6wFWWOIHQNwRqSBSI736D/BQja/haJbK5ze\n+pfP2hJupIePKK2BUQ6dEv95rDfU4NAYaDRskks/J6TXM/WQmyKervPoVsYS\nwB07QDkHuGgnMbymbX8JcBcTRTNEVR3BKFN69owF1K9wZVZGZMC6OPcHVfgc\nyBi1aX8HtHdfqmh1hXCW9x4asSWI9/sbrN1bBJxSO8vCTXs3goYC0EnRGwIW\n7X+3t5Cj/rkvKvTdeH7ETO4R37Wu3Iwp80oCEY7jpNk3RQrqqtdgOEYcWfOf\nkX9ldPuIvBi/qrQSkFpQnb6NWtRKJPbPnb2kkWkMfFISJkRFPz7LFWzKLKNm\nbWqOT6LxYNWxAR2aeygrXx+5h9/1vgwXxk+7byhZpWgj0yEZPS9dRa4WF7YQ\nWjhcf6rowzSbF0o3xxlgMOmPycJPkMCiRYukBMDigMERMUm9aClIvo/nJVl8\nuaWpaYin32nKardxE4N0R1qxn6XUb5EHvFvIGiNbsmSFNPiMgxtp4RxJVsIS\nHIeAVudkjbv6831Z9B/u1F0e4cp3ng6HOuZeWSWrd27+strLKFWuGm8+wYVJ\nTpmsSMPO2Ukd/K/tgl4jS1RA1Cqa8XHKTh8iCgawR5pMAtdGkjHnx+3VzZ50\nzJNw\r\n=W/5j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAJWWN2IoiOkravxruxLyW/vq0H3rb9U+wqL8Ga66bL9AiA5riedX1EaD8vjZ3wPcdo1eROIUE1U9ID0yrpZeu6x6Q=="}]}},"1.0.30001187":{"name":"caniuse-lite","version":"1.0.30001187","dist":{"integrity":"sha512-w7/EP1JRZ9552CyrThUnay2RkZ1DXxKe/Q2swTC4+LElLh9RRYrL1Z+27LlakB8kzY0fSmHw9mc7XYDUKAKWMA==","shasum":"5706942631f83baa5a0218b7dfa6ced29f845438","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001187.tgz","fileCount":805,"unpackedSize":1510031,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgJtgBCRA9TVsSAnZWagAA94gP+gP1GOnMV3zyn5B5hnxr\nASCjIVRt+iW5r++mfMLPDdyHL8M7tLVLKecT3Y/W9wCRuMxFW4ptD3VwlQkt\nSBCZIW4JMegX0BIGT8hh4zomlWgHbpzDnwzNNgkRIMooZ3QoJHgVjWQYsbD9\n64aahvPNCr9tmdC0hoGZt7LRE8HBnmVLS4qJricCGxyVFgDvH8Cg04ML9cMi\nLTqrlIxW0sgB5dvdtTS42yJoBXYvc3bT34LQy6Z9/0ojlW1Uc6Qzrr0fwsPu\nnEM3c1Q4nGymt5G8D6GYHkWunNmi8jvaUpLskzxY8jvHoR+udOLnmi1yN8h+\nzCAXr53vBMW+r3c3Z+yHnmsb7FGWcTBac6GHfEFMKnQJHWEgXmayuPPLZ7Qg\npXydZ90mpypy+tubYJZxIdbMHX2A3uRr/JQZkti70zCp0OXGFQ/OJHwlRMyl\ns97YjNp7CYzSaOz4e+WYUnuJnuNOyMxGaxIiR1cUXdj3W5qNauz+OCEQaKCk\nA3qcwZBS+EFty5IicnfUU5XJ/vfqXtOgGRbhMAxOBs0YwbBPm9bk+n8VtSgM\nlA/iFwzNeMwY3i0wj1t2Sr1tONCnqI2serEMHvF0b1GhEvC93vU6G9NM8tzn\nngdI6vQfL08FOnM07eqgEUbiim03rGX0jrajW4vwoFWd5qWTFKUo/Bc18u8D\ntT9F\r\n=t1G8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA8LUjP5/8MBtXKiBKiR2+bTCf6iN39x3RzqxycIO7RjAiEAnGHuA6dmQbNmCqw6gMv772+tN+CrtHyNupfVG87xOzI="}]}},"1.0.30001189":{"name":"caniuse-lite","version":"1.0.30001189","dist":{"integrity":"sha512-BSfxClP/UWCD0RX1h1L+vLDexNSJY7SfOtbJtW10bcnatfj3BcoietUFYNwWreOCk+SNvGUaNapGqUNPiGAiSA==","shasum":"f8547299b9db78d3882b0dea1cae891fed1651e8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001189.tgz","fileCount":805,"unpackedSize":1511736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgL1u7CRA9TVsSAnZWagAAPfQP/0nTXLbEub9zSQ3+btct\nbXEokT3a3f0tOGFDeboqDP/AILoemgkTXuy9WVdPcO2xYSs6cWOdEAnPGdnd\nPHCRccHDFXbIRF1IaeS6jWWVIT6uFub8hZ3cj/YarhejZcuBTe5/ZKp+vJHo\nqAo9FUvVLmxj+965mj1Qx28kaxlzQ/LmLXX6YT7y0FsVrDnmggUHFZfag/AA\nowKTCSIZthriX6ffQTCBXzKcajaR/+nY8ow3K9pGRaBTJyOYS5KuAtjPLXZI\nekfebfktZwEmnDOg7Bdacb450LI/U7vww9EVjIb5D9ZptRltXvNjMxbl2CAU\nkJyKNKashLiVIMSBe+t1kSUXf1bAHOFFKSdoSJ08lPihPPRW6U7HKvQWTtJH\nNz2V6S21wky7O7/PSMWIT5c7QRekribc6O5NlvCM7Oq9Cc3wovkZnAIEBknL\nUZhm67D7Mka87WHMcGuoBF23xzB2VbrZ+qjBrxI00MDpD/hqVX7ohnV/eT74\nZoOGDQmjAxBdjztrI+zvpZBd5Dgt9ecS4BrlEMoCFa6zHqYBJsDrWuE9sp7Y\nehJYtCwf9dwOnyzYqFcG2/zYXGQ2AcTa48ac/xFvf01XYuKKw/k2azWpcJMJ\nZX1NNGfRvA969Z9lOoByGlSljOcxbFK8vMDRvh5Dil8hGaK0w0AavvleDNbL\n878L\r\n=Z8RJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6tB334xD00JZ+xvUkf7QW/nzl8ijM6cXMUXm6zlPHJAIhANb+yvvXg0Od2AmgzU4JKuiOUuQlmMi1f0nAGnwL5giI"}]}},"1.0.30001190":{"name":"caniuse-lite","version":"1.0.30001190","dist":{"integrity":"sha512-62KVw474IK8E+bACBYhRS0/L6o/1oeAVkpF2WetjV58S5vkzNh0/Rz3lD8D4YCbOTqi0/aD4X3LtoP7V5xnuAg==","shasum":"acc6d4a53c68be16cfc314d55c9cab637e558cba","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001190.tgz","fileCount":806,"unpackedSize":1512909,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgMJ8UCRA9TVsSAnZWagAAv10P+gOdFl3GUMkgzFbVgcJ4\ng1Mt4+hYEP+HE0A9B6D/Zb81F/YGeMMoyBhlp8dXAo2PCuu5IG47sZf46c2s\nZk4FfdOqtNCup/M1PzEQmJTSTiwLFs32Y8Mpe3aFKgio3CmBvLiOEubdFuEL\n2FIzdcQpsbxVW6S37DZiJF3FCq0hIPt9KsLOh1Ky3ROAoQ99d94YjLkQ/mEj\nSioDNhml03aG/bVPhH22NCjeXAENLF+wy3jGOA4zYL73bKHqXscoOUcH/t0F\ndK1ASUxtOSiTTe87MeoWPAqM0Ehso74uclCGoWapFJr2qdW+WbtgxveRwWol\nbNKOuZOJxBucT5BnwLGOqyhMoO1+fcCDhB08nmQJQ3ZG4CSppL6WAVBo+T2g\nWneIyq/LjMa/oQ3UWDqgLo3cDEPvzPDBb0YsKYIPIKYN07ZVKT7qYodhdBCK\nYKlRmCshmX8uWpj1oBS0a5TptNku83HDMdBZA5sdA0PHhVcnkEL8u7NDaEal\npFsIm2D4qXmvNmtpkBTndX5fbmLTEtfhpdCeGsY80qbNVbm9orPA4Jh9/M5l\nDqhtVforEdITcqAQ1W22OFCm2kJbKwNIbmrBz07ObP9Ei5ufKnfY3oa1w8Mk\n766Ko0BHBXKuKvygmMfBJTx1kInk2U4f3ocZIn8WPJGQlXt2nW67CpXEpi3i\nqKkC\r\n=xoKC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDlKAdpfZT0hV6bPNKnH25Ybby/UNqXKQRhHCO+oqgMOQIhAICARVuqB8AU6Wf+Rz1RHFMY7IgnPGCv+bSRp4JmaYlu"}]}},"1.0.30001191":{"name":"caniuse-lite","version":"1.0.30001191","dist":{"integrity":"sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw==","shasum":"bacb432b6701f690c8c5f7c680166b9a9f0843d9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001191.tgz","fileCount":806,"unpackedSize":1512984,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgM142CRA9TVsSAnZWagAARNwP/0+nE34YXDGk3UG2u2N1\nn/GCskbRH7Oz4uhcKQz4oFvCHl5bcN9aDvnz79uPlkINWNFOgjTOVJrcZzKQ\nIGTxblu/23Yled0JDANQIuzFjEoq0uDDD0FcKhTcwgk18pbYunKHtKm7C4P1\nJ40D8KMjlCtZE1desr3czHdHySLMRjKaM/zkLBOw3RC3Npj0T6Yj8dt361ud\n5V2q/9drfqV97sJZUEy2OJdV+hBbFY2LXbK8M2F/xKOBI2+p3Atr4brUKb0U\nWxrLzgz82EHnkjU+zOyEli5CwxO4KoBPDFlsmL3BC7FGaO3NSQXAdbuv4Nt7\ngBI4eZwpF2S3yLIsBoeSrtK7CD82z5f78JowD2sBkbp6ep47mN1O5tQC/wBA\n1G1GYmutXs5GDczE38jVnHTWeuf7Qy9MbnBDL1qka/tKu+LpQ7LqgUMUHXBK\njrYn0tHlbUGfG2RGhYL6XmZ+YIpywuzV1ld9P55JcP88TbNXOnnBSg30Dsfo\n8pwz/TaK9P+H1byBW21nbYTo+p1vHY42A2hh51Q6yTIRQam0oRtsT/a6KEVs\ngrRpu4TD6a9F4xeVo31wKHNHJIi5xYxQenTfCfTbf3iJ+7XccA3mjw35JR1+\n5sCh7LyURIhLGt31Y8W1SmwYRTyyFzktR2cIwB5o4UhUYbmAt4Mg100uh/DY\nCpPv\r\n=2A+z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCDKu7v8RU6GxTRf1oNzVR9HYOkgUIdEhYN2bmVMDfhKgIgAsxct9g6OAL+I8n9EqhCVWUojZyfTnfSG8C1siuiPEg="}]}},"1.0.30001192":{"name":"caniuse-lite","version":"1.0.30001192","dist":{"integrity":"sha512-63OrUnwJj5T1rUmoyqYTdRWBqFFxZFlyZnRRjDR8NSUQFB6A+j/uBORU/SyJ5WzDLg4SPiZH40hQCBNdZ/jmAw==","shasum":"b848ebc0ab230cf313d194a4775a30155d50ae40","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001192.tgz","fileCount":806,"unpackedSize":1513051,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgNzaTCRA9TVsSAnZWagAAbhcP/i4C5Ift/JB8VYMBT0Rc\nHMbWjf/Vk1TYHfSpXmDbaS9V+MU0d6vzV/Zd1ElEHw/eL9r82CylH0TiSU9q\nHW1+iX/ykSFqVQ6BPB7ZltGDzuKbH9P2wA3BvF5hlWbV1TnzGbioVx7Ie7UW\nptLeuurFhK3UaC9gFCi5Un4FFl8DRo9nGjw1UGLfnHlcVRYAETNSXqTGGXxH\nlFS0MHl9NSOBSQh+mLenxa3hZ7G7yLW0yh0QKUvdKPDMNaKC41/OeYr2qKBK\nd/bkC8DfPBrX1WM3ENRUES/6UbnaMAKeOsXb+jnADD7M/VKMXRHn2rxqSvve\n6Lmxd/l8H1K3+aOV/LWllmgNVejMmyYP9YGZv/OvFtGiNarnrinoSn+BN3bZ\ndS1ajHvsskzfO8p5G/0xn+NvsfkN7u0FGh7GqWoVWX/6ZOIGn6yxEILBLSZD\nXpy3aPvdNFV8Np//Hzp8Kbc+KvAc+MjCilx4GgWL2B2FoXASsrT7wyt6lqjO\niH9RbZ131cD23WlNh0iA3FXVML+vnzWIgtlAbGIuxcP0wUGY3XvLyLmwM9Zo\n6zxn1RoapT8xLOubMnCW3qGgDbeeN3RtYZ7YSZCdEzAtO24b2wrN1gep/5y9\n1sOuunUaSFJI86PmIbGPFem46e84ecWz7HNH/XouLbvRE2hojec9IxW7nk8l\nd1ah\r\n=RAGZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7GQEtHoJbX9wlyDfRlA4xbFUNhiJZOvHcpSnS+C8+zgIgE1F0zsPf6y8V06kVcM/aqKl5MGKYcUsR0wiQchH1E3E="}]}},"1.0.30001194":{"name":"caniuse-lite","version":"1.0.30001194","dist":{"integrity":"sha512-iDUOH+oFeBYk5XawYsPtsx/8fFpndAPUQJC7gBTfxHM8xw5nOZv7ceAD4frS1MKCLUac7QL5wdAJiFQlDRjXlA==","shasum":"3d16ff3d734a5a7d9818402c28b1f636c5be5bed","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001194.tgz","fileCount":807,"unpackedSize":1514385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPeoyCRA9TVsSAnZWagAAvbMP/RZR+lmMUOlfmAmcMgJR\n4dhuvy2KrIUVC6nT8/IGjkYwl+j7WYD1bku+nlOo723KmHxzLNlEXFzV9pNy\nsnelzk+8cteY/j32WqBptqnzTxHxoiSP8L95tnXEMPTiLaJRmi1iChnFrX2y\nty9E/uP+2U8ReNoAxJ6Nd9+BuCBkaWH0NU3ScqMvmGoYrL6RN50BpC5j5mdc\nsFqEaD71hEjeK5WEi2CJQ7eeCmKjTCJVUr5otTh2yl+IknksN6zrYAtkGGfj\nodipGpYjL4ReilSti79GkUwtRlBhFOO3eJCqDJwAUZIfMCsFznjCbaLNXDfV\nRO+AexoX51T1P3YNdsLgk79bVNgr0TyB8c/HwdYhDR+ZBMEQkovSNqYjja0O\nisHDkWooD66ZyqHa9yPl8Y3OHLDhBD5cYYLMhc38TvgEZgOcPnku4wiYav0y\nIHLQDUvYBdh/RxXj7bCzXHulCAG5uZvZQxgasMxDSpKsxCMnMpT16vJQbqO8\nGZM0ZmxiVt3VSdkWStr/2o+ZF/wmh8cR8b2GJ0PKI6blDT5AjM1ClLwC0M0q\nf6w2njW25tz58NHLPtc3pu/rzxyIezEhZ15P9Q3zRYbJ0RcNiHqDOMRhsRae\nwtsLAVy4har7xOT597NlCvDeU5m8Y3lHJFXlYIXBVNzTg9sY4UeNQBcP27U2\nXW5V\r\n=O7DE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICUwGKa7FfOcKVdWST4VmtX+sc7mE0pX39NDiGS/bdGSAiA6nAh7WeF1FgOsGcTZ1UFeOAAYqYZt7frhUSIEWwcLBA=="}]}},"1.0.30001195":{"name":"caniuse-lite","version":"1.0.30001195","dist":{"integrity":"sha512-JMviRgau9XQKsdEVEDd2ZmhBLv2yGFXjeriS2WAc88yqbYtjl4uFDZhVMxWE06qB2XTRnljB6PSosdazMeLyrg==","shasum":"c8c560430080e73b70b90b6b061634127cecc032","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001195.tgz","fileCount":807,"unpackedSize":1516094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgQI03CRA9TVsSAnZWagAAj6UP/2jhOlwYzQZ1L2Ea5phS\ngQWbNt08gAuwoKSErsDFltMr6DXQ2IfHue0PSwlAKbMa+NjVO0mjg3wtat1j\nAboQov3Gr8y8waT41L16V7BMOL8/lFl6B6W5DhLt/XBczPF3/boUXVXOsW2F\nQQShry6/1WNfRNeJ2L2A1ORxw9CIIrP467jF6G22ZkEMb+WI619eYWUoie9C\n1GfwedqA3dJb27nnUMf3F211J76lrPkfisu3S8zijl4Ksn6bhkBCokctF5cP\nwfcj1GQeo2eXVB08NIHgsyGHMUPYTrkytdYTKAzIqUU8MS/WuByXJHbx00zz\nKNvBSXqC7YGg1Vqi5j5KxexNNPh7InS/tgR66hDiEZx+EpBBTj5knlVhNcs5\n4Zgcc/3APQjWEU0kuwWWPJgqifte7+cTD+A3pPo6CKCkuXX5bbtdpN3LunR9\n21v2c4jbtAyUVUjzw/edvWG83MRj6fHcb+OD4p5fUvQ1VWL6QzXDRfobbrLW\nkV7oL7wIzeDpzu7dZkAQuAAWKmZ1nBq8Gj5n8VENUYj4wKvBpOj0AlX+mbXn\nIIO2g4t/Eb+rwsTq4s2/VMDgnF1JQAonQLGbUCL5289WXBJ3UAa5NFbRM/zI\nPP9IxNf1EP4UHwt+qZErMUaqDVPpOjA3qDOL0iWVtG2HEXCYLzTDbIodFLpd\nzmUM\r\n=6RKh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHSTYy9hMFkTFIXCasZ0JQ1kBRkf0asfEqZ+kwiLJI6KAiAoXL3RFHzyhdvA9GFBe7dWIprl4679tkuy9hQprVrXqg=="}]}},"1.0.30001196":{"name":"caniuse-lite","version":"1.0.30001196","dist":{"integrity":"sha512-CPvObjD3ovWrNBaXlAIGWmg2gQQuJ5YhuciUOjPRox6hIQttu8O+b51dx6VIpIY9ESd2d0Vac1RKpICdG4rGUg==","shasum":"00518a2044b1abf3e0df31fadbe5ed90b63f4e64","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001196.tgz","fileCount":807,"unpackedSize":1524784,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgQJtECRA9TVsSAnZWagAAG4MP/j7SmAh6E5/90fhxZ+3F\nBC9wE9xyNxjs3fhxYrKR7Dto1ErO8Mt9fNJoKqwAiGhzQvo25mnEXoTZRA/l\nQk1EzJEZiPp5RFWG9el3Dph1h+49SuAwV2C3sS5ApUNMHIA+DfLg4Rw8vZDE\nenr6KUsYnin+JJPnnngOWlwOTYSIteM4OqriLp/qBm1ip+WFR5SHrZvPaYY4\n5kD5J/DfAS+vnuuRH6P3oFaMQ3KiK/uolfxTkwV7mmdX+MKY3xcr04q7nFmd\nW5TDUvANuQf+F6LSmk0Kg21fkVF08kiEmw7RKVeLANpOfdk/TrArSq8DruMP\ncITmfvC2ydw7vc8NNAkWMxiMGPqWSeLaILxdQ2OIk1P/6l/NSMQE9iakynWD\nCG8l2zTf0gZmJt+s7mTNkTMO4Q0SVAgSFt6RaGkaDAwRZpH1HH1iG8z1cg5F\npoqsbR7e+jLOs1AyHvZzx6iy5C8b7g7MJZndcyQ2kYqLlNRqsBq+4L8mTUbu\nhbFU2Fi1FyzLa0Lq1mIqxHEOHSseH+Y2f1mUumuc6vAWgXpAnLPOmOpTt5X0\nisLHuJo/kZHInJEBxjsR88IqwhytuM+I53LezdunI0N4bRK01MocnQwDgOgl\n5PyWPSfKYVHXmNzpDsZBGnpoA5YsMvJ3CMgplMdSlIoXI3i+p6yyjDbfskYv\njxCA\r\n=JF/+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0IjV8RDLnjFsD2w914jhvHduy7UJx7iy6Zh9iLvDijwIgPXxWcpKZBUuUaoVnzYPBXf5lCtnmoNaTo2DrZEEUt1A="}]}},"1.0.30001197":{"name":"caniuse-lite","version":"1.0.30001197","dist":{"integrity":"sha512-8aE+sqBqtXz4G8g35Eg/XEaFr2N7rd/VQ6eABGBmNtcB8cN6qNJhMi6oSFy4UWWZgqgL3filHT8Nha4meu3tsw==","shasum":"47ad15b977d2f32b3ec2fe2b087e0c50443771db","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001197.tgz","fileCount":807,"unpackedSize":1527134,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRXDICRA9TVsSAnZWagAAacoP/iNORSpXNGyfOqAscxFF\n4URklEID8E4KTRFgHZJjB0FF0hulEuy5DgxZiM9bkglJOkLJeOZLvG7vXg8e\nQ58jRWnYMbCkePm9G9VeKUH74LE8HfYfDzyYUWD4k+XG/WIfbqFgY5rJbOO0\nz/4sytR9m2Ds0pUFXKN8BnVApcsY22W01HWCHuDg93ltYyrVoarhNFAIKC4/\nwM0oX8K4w9nA8/XNHE/aX/S1vYFMXYu+kbDPUCYI8rp8Cvgf8tJAt86EuDxY\nBdAAot9B1XKWUT51ftHEM3Nx1PwovCdpUSCTEIFgYWsIqAxNyz9O8PBHKDfN\nAsr2g67P/ltxM0CBvNXJFxyNfScaL/qi6Kz1ozZ3Qm4FIQ/T4R9O3IwWbaOW\njut67woqjYJCOqyQ1+DVDDlJ/ywLIOd5QtShiONqsjYb5ATRIDoBhjfth4cQ\nINi9qJ8oI/HN+xNav8LNYsd0k/sA8VKpz/D63D30noA4QHgYlz4GmelPl7+k\n80rr8zNrW5XTagWsKnF5iCBgyTcVDgvZXOnpHY5RHv3/rVqUlKtvYF9W1G2k\nwoGFifk7GaOD7kF0J9HXJqMdGiOjtOhEPI/dD9db4EjMEYYC+kZWrZgjI1KG\nDMAKNju0w0HA9CTS+K30J/Pgbgj6R67eiMQy/GsOZKFDkM6JxRs3uciN9Dxt\nw9Di\r\n=QuY8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/NphUmi+gb2pLpF7jBlp9tRgg2BPc2NUJdOlzm5hGRQIgR7wNTLzWzQnbgs3E5q5BKW9wFVgXL7iEy+4/oPCMPqA="}]}},"1.0.30001198":{"name":"caniuse-lite","version":"1.0.30001198","dist":{"integrity":"sha512-r5GGgESqOPZzwvdLVER374FpQu2WluCF1Z2DSiFJ89KSmGjT0LVKjgv4NcAqHmGWF9ihNpqRI9KXO9Ex4sKsgA==","shasum":"ed2d9b5f060322ba2efa42afdc56dee3255473f4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001198.tgz","fileCount":808,"unpackedSize":1528385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgSGghCRA9TVsSAnZWagAAO1wP/2e1x6vQSkOrNaa4ljvl\ntow3WsgVqLCU0OP+QgD1Xd00r2nrtpMJloivpPJHI4BqPH2a3xfORAEUQPah\nmnhcEBDJI3KQD2oa/TXuyKwjO8aCYViUca5Qx9e7nizqqLv0eelIj/ypnZG0\nOrdwfBgujohwqXY4zVwOvWyJ3nIzKtyZB88u3wz3JucMDVh6p9fM3B35LjqI\nJbIH0P70VJbZiqdQ0bF++c+et05l2OHl1QXa82DXKtvEaM22Z4rQMrlR+gsh\ni0rYlDWGOjX3Es/kGSiLBBmtLWOIWd1gI78UdMKAk5w+PWEcycef78iQF3Wp\noFcDiC9fzFuJtxDWz83GT2s5Nxn+02Nz0KGOOwx+jI+KXQpOCEGo9wZ9UwBc\ngM6Me45pqRK1ZiLWj6f33p9PDmBcTgPxPmo2/rXCMUXWfbJGf5fDIgpffb1g\nbegolvpsDWaCQZOV9soyVMofvi0I0oh7hfieKxfegQAbNds1mq8WMBVjE4yj\nZsFbA/3hIHiVCOvzFAwrH6af2+awq+eo2n0xJic110y/nyJQ7pVC/ajKBgjE\nQ+gApdHO04L3qWavroKDQS3KUr9zVfqit87tuBZr+tdrELcKGz8HZviiIWiL\npH4ud2RE0LAivIFCJ/TRos2VdxrTlOgEf026+/yw8qc8aOGx/h3fce8h17EV\nXjnY\r\n=SCDr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkIqt6BcVgmKbxMljZqIDKeC2z962yOaAiyv1pzyvjiwIgdu8w7W3YTFX3lQj1kY7IM5G5NFJ/JaH3oDqfDP/1qqw="}]}},"1.0.30001199":{"name":"caniuse-lite","version":"1.0.30001199","dist":{"integrity":"sha512-ifbK2eChUCFUwGhlEzIoVwzFt1+iriSjyKKFYNfv6hN34483wyWpLLavYQXhnR036LhkdUYaSDpHg1El++VgHQ==","shasum":"062afccaad21023e2e647d767bac4274b8b8fd7f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001199.tgz","fileCount":808,"unpackedSize":1528993,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgSv0WCRA9TVsSAnZWagAAT/UP/2gX/WBPMciIAY74ZZ/8\nFR7WFKl2oIatawiHzRf9HkZpQEnlyTOjga0FrfStBaC7rjaT1jlANmR8b63L\nVVVOwfK8udNse5RYqILW4dXAlvoa4stpgOAkm8ix+XHHobX2crRDfgYNYzYK\n6fN6laNIekSknt2/8ffxtnSlQjHvQzLIFaF7M24NEAWpAZXpWlosRUHP/lZY\nYeLNtzqzo4bCkoIR05nEXt5TNHdoXue0mTnEIQfSSIQN+nQokZDefaUQi7MN\nLWWcHJzQ8bCBLbUO9RxauyDRDnC1Vo/sJikmkpWJ+ujMW/igWAF6wS4D1Dco\n6q8+dvqlm+mFbzff1HHalxCfOsVPBnpVcBNC7xQqV8JZoUAPBO60FjOYyW6w\nW5S30wNEt16w3NObXirzT43/2RJdBatOYFiwArlNoyY9OTjNQPFgT/9j7Hz5\n5JdbjnNeGlCKjr7n8GdJWCGFoIH2ebPqYa/+9Lk+pp53kJJRwN9ZOjECaFwo\nv5sr6Zc1SsuXgTFA3XnCRHAB1EL1r2DU5YI6wXJCdI8eHZmrwJEBp1VU0Lrn\njBs6c4Yvahj+JOYHft/XC3AsVOCxbuXXxqnFFELH42mXQYn3fJH2UkSN2CAq\n11B7A3is1vGERv5lP6k3kyDWu+SiY/r243ceDAEM4aCxKB/0rXNzlCan03Qo\njfNI\r\n=6vLt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICCRgSTrhAJVLfOnL6X0g9b/yUg+JwajEsBvpVDV3GnGAiAukkUpEKG73kR35ML/6Lkp96ZQNABReUycRkU1qzhSbg=="}]}},"1.0.30001200":{"name":"caniuse-lite","version":"1.0.30001200","dist":{"integrity":"sha512-ic/jXfa6tgiPBAISWk16jRI2q8YfjxHnSG7ddSL1ptrIP8Uy11SayFrjXRAk3NumHpDb21fdTkbTxb/hOrFrnQ==","shasum":"25435af6ba907c2a9c86d21ce84950d4824e6620","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001200.tgz","fileCount":808,"unpackedSize":1532303,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgTp06CRA9TVsSAnZWagAA3v4P/1edast8RM/IdgfAjR5O\nEyBiQL32EEte7wh42dvs3IA8o9tIAnIi+UwlWAG6wb/t3/kVW6wLq3JR5G71\n7mscl92C6lTaHNuC3lC9T3toel5O8zA6blKkX8KHGheUPhcikFvyhG2IdKeW\ntTaiLIdZHfS78oIiKSANeeCjifsYfAgcRl9sudkXI5/OqZ9A6Ivikobpug8+\ncH5Mf8lZsIOFaPRDN+B5W52PezSJ3m51vLbyTKIgft0K29HZtKOwRwUBoxM9\ndoF+l+spuz3hOIm+yos1d/lbE8jIeQi/DDwHjVhffcEwGDmXrvO7vJ7+gwHv\nYcDEbWMEC+xhCvqHgQE9YkM8r3e6wEnW42N6YYzDXA0ZCnqLXvNPbVV3Ksue\nJEeIsgKhAp+/o962MPoUlFZjDs8NMZgdBWcWIrACAv/CtV4N9E3mQkyetGRM\nro140/DamJ+M8mg+SDSg3YAWS/EhFWiDMtqpZBZixG7Hk6wqFvWuY23bvE/o\nulwrci8VgEpomV/CFYZ2MCgp0oVfUoR1Sf+SyOnpOK1sUxmvod3Ft8Z9qAhb\nCjfPpojjtrs2I3K1IzFjcsNbtw8tduZiP7Jyt1B7Vu9LlG//OYRrRBjydPk7\njaMw7drbI9Y87q8G5R3l1HuHm+qZniMJ+uGwWXpNjfkw/T+/126mg+OGdhl8\nkolY\r\n=eDns\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDgI9Czxiib0+4QSfpVfCOEw2aDefajNbWgLdF4VV3vlAiEAg0O9JSr4Ouk40u+AggvCZlPw0h6WKZBRv07dCnqN+f8="}]}},"1.0.30001202":{"name":"caniuse-lite","version":"1.0.30001202","dist":{"integrity":"sha512-ZcijQNqrcF8JNLjzvEiXqX4JUYxoZa7Pvcsd9UD8Kz4TvhTonOSNRsK+qtvpVL4l6+T1Rh4LFtLfnNWg6BGWCQ==","shasum":"4cb3bd5e8a808e8cd89e4e66c549989bc8137201","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001202.tgz","fileCount":809,"unpackedSize":1533573,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgUEMPCRA9TVsSAnZWagAAvdgP/1AXZvE0HNJXtwaF7bJh\nt/B0JqXq7ZhLK9JrcmX3z5llnEtlf8m13KQyC8KL0SK/YQ422zNxhEzcKtkE\nplJD1MONdYp0NGb6CRe9ye+lXgwSoKBXL1mzDZob2+4M3q+xOff1sGmrInC6\nA9DWhmdSmXaNIYpR+Gkl1f7q8TzJ2M7R7Sa1BwZgsVscuEa/XYrQoaXaF/He\nL/yWuQbLaqz6MkKkPDtzl0vyT17mOhihmQTSfQ0EGreEsnvo6Po3IFh/guI0\nog9hDoLq/rhQa1avnT9SGixC5QHYKmbOt4EKM73CyPp8i8td0j8wZR3BcCCX\nzNyq2r6bhSmdDUfztUi2tysG1WFWP3YiOfEMPqi+WXL8JWU8aa817tSfglsS\nPWYhTgDVGps+FQN5xC21K9hDWhrX2RSRov6ZbV5SQHoWHPMJ8iPqR+IQmmKU\n0F95MyQdhpQkezloq0b0C684r7cBD3qQR3fP0pKyo7mrp4iOXryfe34lvbuv\nS1SWuqvKvS/o+ElRrjtWi1HZbF7DKor3q2vKSxk+BojwhJCtaZG+cUAxqsih\ngxc3Rm4TeioWwPCtVB2g8A+9A4ZQoOu9avXOh7fGWZVMtzJpzxVwq+QNuuCI\n92E76u9M8DxelxdVLEO1dtclr6ULlS8fnP0IpShRllaAmOQFX8Va/W7rBBB0\nBpjc\r\n=456G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMvbrZHyvcUxCY2/IYSpKkUwlptuCK9pgpNgZg76AqUwIgbkysI3BbzyBfyF5Ylw7oZzsgnRDO4R03PbusQPIENFM="}]}},"1.0.30001203":{"name":"caniuse-lite","version":"1.0.30001203","dist":{"integrity":"sha512-/I9tvnzU/PHMH7wBPrfDMSuecDeUKerjCPX7D0xBbaJZPxoT9m+yYxt0zCTkcijCkjTdim3H56Zm0i5Adxch4w==","shasum":"a7a34df21a387d9deffcd56c000b8cf5ab540580","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001203.tgz","fileCount":809,"unpackedSize":1533645,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgVDeSCRA9TVsSAnZWagAAI08P+wf7qeMrxGru5Re97ZVZ\n94bVQu/AeXg4T99sQuPzELpKdrtlDtFb3aKG8oebTt2RxkGUX3T1VNk1JWRx\nHToRCN79lOnzBv2bFO4NXoInrRLWN0UEbhVT3oAmdM2Cn/DaW/l0Kw1oxl/1\n0jHbZ6b3Jx9nw1PutXtI2MM5DGJerj2LJ5mOOP8dEGcRm7WSVn/wsNYKcll4\nhLYsmxTZFJ4Lnno0csFhD5bu1IzBs0hv5rmsPm9MHh/2IX03hTJTmKICp4L4\nyCd06KyCirNQp8q8AIgWXHCGRFcQ7hMTAWwjyevrIQPBhfBKJThhTTfNS/Ld\nd7b9VNM5VFR//EiIBfC1Rpqu0+rDMWnvadk8j96Mux39ptmvVBuVIg6d7XiD\n5zFVEK52a7GIs2M0eX01FcN5mSWU5s1HTHn+wagMGwbni1xDM+5eBVPxUX/B\n96MI73MJjFsYS+g00yJXUljPTdEPhxTSWGVL4F6kYGyckG6zmckb3woCqFEM\nCJWlM4jzw2ilBFHtJ98onwuxGco7PXpRixAQFWVzwq4UpvUc3bcr3StUwFJT\n9dg+OwBSqII4LuYYa9772WOFmP2EmOIKAN7xRXnGFH6QeRkrdlIF6TNCmT0E\nKzovvVrvzd2vg847AXkZetinqwLs7nhN2DTiaGIY3nEGKFORIVJ/jck6z5So\nyIOG\r\n=S5Z2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIChtsV23T5xvse+G6tMyxVTdb51O0yrEQq8ye1BcZRZgAiA4mKDZ/xO6SNfi9aobmEf5/tEQXe4M5NCK8/c1UXlvKA=="}]}},"1.0.30001204":{"name":"caniuse-lite","version":"1.0.30001204","dist":{"integrity":"sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==","shasum":"256c85709a348ec4d175e847a3b515c66e79f2aa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001204.tgz","fileCount":809,"unpackedSize":1533693,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgV7uPCRA9TVsSAnZWagAAYKgQAJYcAKkfbSfVfKQf+MOd\nxSBJRPZeOaT/lsb99vlqcFhwTMWx3+PsTj0dTtKbHji4lSCnnz7EDpMzs/sV\nrKlRNpcrTW81Kiam0FmgRscDARlZATIipNn/OYDRjaAi/u6F2zGjyVGwkYD4\natmCX0rvUkmPUdE9DNROWVG9Tlf9R/NG3m2Dg2kVzxqGWW7nxWLIipuL6sIl\nUkSV6hWz9d+3bodZGvQ9EKt88OT8D5I7gej3A84+inlZ8Q1AcgyXNF0I1ESj\niLCyM/cFES2KqcdTko/3b6tKdm9F5WUEb8D+CdoZs2mJkCoOr0u6X8vkQStP\n2o7PWiu3I0NrumGff3KTAk4+pMlk0w8yXWs7MpsNjrUlOgZASaCXG4fzZTkX\ngEqmhdbWUIa0Njf0zcB43Xc3YzJhbKn4qQ1b2FF8u7M63mO0YwxVQv19+7Nn\n18YmkTuC70zeQj9RSVR93rep4NeuQ0znsxf0351Ru5YEKWg/I0ipRWG8jwor\niVcJDC/Zqf9EQu+GGz2XSkPIGYDIOb61wXG//kInPBF3mQcRyCk/Xswyguyw\ndAnVyC+jgkqIEvx/eunEO0cfk7kjwLkaZACD8uAKh46MSOI4dP4zIMyqVb3U\nuKoZGMwFg+FGiivc3Vpwll5mSgR28DVTzT2IhlYlpsvQ9dJ7SQ1LYeTwVIVM\nFaPa\r\n=i51K\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGiL7lI5X36EN30RVJSt3aH87NayyueZSL8WfvIL8tsgAiBbNx88oJV4v6fE2U3iTSDcQ5OkjzN1mT+DpX4n/AVnlQ=="}]}},"1.0.30001205":{"name":"caniuse-lite","version":"1.0.30001205","dist":{"integrity":"sha512-TL1GrS5V6LElbitPazidkBMD9sa448bQDDLrumDqaggmKFcuU2JW1wTOHJPukAcOMtEmLcmDJEzfRrf+GjM0Og==","shasum":"d79bf6a6fb13196b4bb46e5143a22ca0242e0ef8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001205.tgz","fileCount":809,"unpackedSize":1533775,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZAmPCRA9TVsSAnZWagAA95MP/jB+z7DezolKgpsB0bxW\nZB9Q0os4H8NtR36XeSMze+qbvOiOI8PaqOcHk3zulwxfcmx8Jz8cTUjp5IPg\n9ug8QPXXlrDxVvKolgyYJN8H2sRpVoneRfuOAZa11w/8NEW3v9W7TiK6fM+7\nsSC751CmX/ib98oAkD5P+cQsn3+Z2UiAzH88YUDRL+v/WFeBhsjy45b1P4a/\nxXmIwLnUGdG9wefEKPzuOrho0pifnyqeDnFITFlMY57BpQf0TeRQ1i6jNNff\nqpeBSmpM8S0jKbeWTIZy2cXQMJTLmsH6jHbOna/5G4XRRfa2vqO7Wlx9m5je\nnTAu/f9cCxyfNHjrIhGP4zF5RXzrTS8gGHHx6Eq0w9i6g7P9KMYMKFAZX3Xe\nv75TdOhCbIZGgmSJOFdiIKFbNbovM1iA/K0zcOZmCpprJ/iBsPOc2xOYD7WE\nWu/dRWzXZJ36y6Sn9dDnHI8dM5Kb7bMpEqFnrDAYXULS+SdwJeV4RRE1Y/KI\neFnTPjleP5Ia6CEk8kesZkaSGGndpoeGaZIWi1qMqBgC/oHDU1ZPDWAHhuig\nTu16FK7WO7lZol/HhoBNe5K7nP8uAwSwWYQ8PVJQm9i2/SL3CYy9VMl60x6P\nX9kFWtVWrCDgupwApBMyZZzymQ2Vc15oANl0eNGZgxNC2VuSmZsTTWPXK8/H\nghfU\r\n=3Z9s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF36IUwif18u6LKFlPq1luiA1Np2VOprBLF6ijbWVIzdAiAtw6wfZPXHq9gKLoR0HILKhPNdOIjwsLQoioNVIlkziA=="}]}},"1.0.30001207":{"name":"caniuse-lite","version":"1.0.30001207","dist":{"integrity":"sha512-UPQZdmAsyp2qfCTiMU/zqGSWOYaY9F9LL61V8f+8MrubsaDGpaHD9HRV/EWZGULZn0Hxu48SKzI5DgFwTvHuYw==","shasum":"364d47d35a3007e528f69adb6fecb07c2bb2cc50","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001207.tgz","fileCount":809,"unpackedSize":1534321,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgaU+dCRA9TVsSAnZWagAAmwMP/19ZDZNj0fv9i6x+gpAT\nQsxww6E6LK7/YnBIY9lxq8btHN0Pur9V4KXFJKxcPPTGjMlHLZzFHoxf9l4G\ncbaaDmwRv7ER0mAQb3aoUAHwKV41w9Z0et8fg2trP1ddzDu8UsWtZCV8rhBc\nYCgWtAMoFddaw2BoFxz/CzI1Wogj5udQRCaDd4+6+Cy2a43d71c1LeJKqQ4a\nYc8BK5XqUUcSEX9eNXLmQf/xsc01qCcJ6/dgsl4jl24aj8eyz6WVqg1HB4PG\nRUWdAzhK/ahrpiwacvMQRjG19DJnOI8lLXhK824BQ4vbBaZExE1l97H3eMIg\nJrHYbKnItXm/C6Hg6o9gEc/PM4sLBtVIihVBMrnRgB9HP7V02dA9XMn+T8of\n5CkjF6ql5I35CPj9wtiU6Y5U33rkklbW0LFRtzozgSv1Uh5DGlo8+3bieUld\nmBxo5mQik5vUaBHrkXLaFg8uGeVmCC0FzxRLwUoq7VRuqLR9gEZn7cBtChqJ\niJnw4e8ZSB8BrBayrv2JMXQvhmbD7f0oTj7nZYenRwX1dmnuLYAaw/IKxMC0\nvFGoSanec7bJl9L463AgRB0UG1Cmx9nLJqNEfuyC2dOTlZEkrPEHyyU6sfh3\nIPPnVvm+zolFb2aQwBE7tG+V8ycCGq/PU3k66NRBE5QI9KtrDk4ThFe079kL\neltW\r\n=M7TQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD48LTJCPC0Naypnlj1oPzFJH2heuynS2xI8ls4aZJBQAIgGZgXyTj62fII/LmjL3vSBzNsRuS74WHhNtRJ5USct8E="}]}},"1.0.30001208":{"name":"caniuse-lite","version":"1.0.30001208","dist":{"integrity":"sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==","shasum":"a999014a35cebd4f98c405930a057a0d75352eb9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001208.tgz","fileCount":809,"unpackedSize":1534397,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbqOnCRA9TVsSAnZWagAA3l8P/RaO2Wyjc7rT3SnQFBsC\natrEQC0obvmPswgiwL6MQuRbDE9LD2TcAtg7eSgPfaXUPCssRwkAq8sECdNq\nLUP8/o3zGS9scLG0DDbri/G6LX8kEvBVmNwduOOjvUJ6XzqgiR7p9HC+1cJC\nb4nAvPCcPdBDFz73VnUjKZU88YFSItRvhg1kaY45EvLgyaeTVPEhs+MOdIGN\n/zjMiD5LsTR28MOkAGNqzITh9jBb5H/dSThnBdSW1sAEZEQLM+E8tAKSB3gW\nB3RHCTRZlJijpOkHGOFoFvV5wSIYbG+kUXubT34SV/epKUzINgZrtfaFOx8Q\n2F/D2OiDUjoTSWSijqpK/Lhps3SU7KobkKIlTJagNqxgfC+fENsOAjHwy7HO\nYAyW42OXyuuHpijuYu9NE6M4A8AywZy1PEoFHPvjDQQJgEdMGIcCAdNVDn6h\nkCgdsHRqn4DoVQbv/619T8O+84jMMGX9MxXP79skRmSq1qoPwvzCTx0Kxe+c\nX5kiU5x4m6CdGnjg6N6Bho8Fu5RUDMJLB7gz14IUghjG6VyNqp/9eSJ8+/bR\nrORma2exTf3rC7KfDgLMEfTRr3RCroNjiAv0gHgKRU3e+Yo9TINdksuaCcbA\nFUTxWpewC5Pw/4/GznjrK/CU0g6UOVajKE1WxHRyv8N1WmPcVpkaEhmzw4f5\n4gF9\r\n=Ii7b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAQmp+9Zwi6XmgdBjV1JXwHIIJ1VGRnkROeK6e6ey4ZrAiBRgNNbTwJHmG8PzAboMrZfK+7lkcXSuRbcvtAYabI2Yg=="}]}},"1.0.30001209":{"name":"caniuse-lite","version":"1.0.30001209","dist":{"integrity":"sha512-2Ktt4OeRM7EM/JaOZjuLzPYAIqmbwQMNnYbgooT+icoRGrKOyAxA1xhlnotBD1KArRSPsuJp3TdYcZYrL7qNxA==","shasum":"1bb4be0bd118e98e21cfb7ef617b1ef2164622f4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001209.tgz","fileCount":809,"unpackedSize":1537751,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgeS+pCRA9TVsSAnZWagAA134P/jykzNLtsCNrO9xChj31\nWW84wgHqQ6d94mbilaeRyTus7dsLgCwrdNuv/KfxarAD+Pq+MwaScMq8cZV1\n3N6mT/9vKJcXFgUgnrNA5g39FK2/z4nssxx1W9NA71UDiZEUzwfPp2P99YXs\nJZTbEBu25jvoPq1nxswvwZipSIupo73Xvhu8CeSszgmBAvCsqopclG9wn3YF\nYGqnKkHrEReHorouhZPWErfi3rsAa8rxAAcFrVgfUN7LYhcfhyA8BRA+y2wy\nIdLSz0shulWRRlESDByIEnVWLTogMRzdEhtljhRRdOSMoP7rrecWxMQE7eye\n/3FiDAXtiXW0cyTjs5+JYa/etpkQnxeu2Ey+TLciHBKI0qwmCRjBd7IQ/m6S\nSGexzq3DCPVJhuUjNb2Jz9lGN/nwmHCIpivngik050/WfSYgWgfFMY6w9HJU\nb+86WNAOY/TwqIM6VoBr4dbN/1f70LbPqKg0bjmfMLrLVF1dZMUQ6L93WQkF\nzLbzUC8FzwuMYVWRGTPqEnWxJd51Dbw5MSlyzAtrzrl61DnkXWfxKXGTMXQv\nOJSIcIC/2qBFvj+FKbLn4CiAjFzJSNXcKbb+JOlEJsE5dt3iD8geYbKZLAwm\n1uzrB0qhK4JL5K/YIgiedQr27FKxWT8tzw11k5+iFqhSVbxlgpi7hsX1RKWc\ng+d6\r\n=9wC0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCH10FgLxCIdYPW8O8RSPWUN/NY4BZj5gAkvEyiXOd9hYCIQCxSvsigFtWV+fjaG6kh6B9if3OVPFsipgpvTcJidhvmw=="}]}},"1.0.30001210":{"name":"caniuse-lite","version":"1.0.30001210","dist":{"integrity":"sha512-avmGf0Jo00I8vB0I89J4Pba48kddasErV7slu7wrkyM5uY9gE5P+B+V3hjABv8Hp4YNG2nBqIUFUXlnqNteXEA==","shasum":"7c12d029e93b725cc2fe44a5eaabd9b838250d33","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001210.tgz","fileCount":810,"unpackedSize":1538964,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfIlvCRA9TVsSAnZWagAAJ5kP/2Z3ZpgA176k03CBFoFb\n4mSux1UBG8SREPBKUyqGCz07X0H5a6yXyeOpetdlw6Xb/v2VWQxPChaOWgyZ\nPn/RnwHA15Zy3hN+3jbK91v3fR+jLOjwgAEUpGmDOhlykEoQpDy4bBYO0vf3\neyhXS8F0GLukz8lt+VF5IeXI5KnASxEaKH3by6JXpzaTPma/PawIWdqv8Df4\nnq78isLjPbN9Mh4A8zu8NG+s64Bdz8sNDwGWIx2t6DO3LUFf9XiKfYneI/Tv\nJ3DH20Z1AJ57d94gqzjfx11Go6vMvvkWxQ6+z7mjKZonj3nt41DXDjaxtsvZ\nbK89mpUBeqArcvd9pfVFljaIhXQYdVsmXALRulrDO8EfTq0xD0dZhf9vehy+\nQOkndUJOHJbEZIwawRFwA+ztAlCLW/6HYZjavGmuF4dakOSFzHX+4aYeXKl3\nsJBdBYn3NzNkfm2RVmvdkQSDR/OYfrfqA4aYPmbCK1FIn9QB012rw0VguIQ8\nRWJSNWWdJdCqBn4MZXrfk5hHrxTC0MKtBZUB4uHO0GUJPMABpD4ehuEDlBO1\nwKCa/qfppVvvBNH2+IWP9oUU4XixDqqI3FGnlsFwYZp6josjdCrkrpI9OEpp\n2+ZUdRxsZQfs6JixatYraQ7eSz07lKz7Dv/+5C+xTe5QZoTASQy+0jlQEMxH\nkdCV\r\n=nw5a\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDxM/NoWllvJtJzvtwqblJBbburGZGC8JPjT65rWGPjkAIhANRTEhwKHMyfRF9xOD2u399H3A9UwRP1OKEZxiTxHHUj"}]}},"1.0.30001211":{"name":"caniuse-lite","version":"1.0.30001211","dist":{"integrity":"sha512-v3GXWKofIkN3PkSidLI5d1oqeKNsam9nQkqieoMhP87nxOY0RPDC8X2+jcv8pjV4dRozPLSoMqNii9sDViOlIg==","shasum":"be40d528bb10272eba0037a88adc40054810f8e2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001211.tgz","fileCount":810,"unpackedSize":1543101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfSQlCRA9TVsSAnZWagAAnSEP/2h0DMqenFLFoPac1Nn3\nrL4V0VgvBrDnEBYdRJI2pcKEmsW9JE8a0nbEY5PLRgIfpdRuTXIG6fNBoNCG\nuWgR3jLp/BRhverrJnKket5NT7sZpHov8sBMFOMmy5PypKus5w7RVB6Z381T\nxKfBb4d6WKfBLZmNkHg7eZZXS2DBx7yntKthbrej2Fy8G1cXIAZQey3ILa14\nQ0RNf787I+heq7SLM9w+MJpoQhHyXuohaUTgZQyUi0pLCDUeQTM40jklywk2\nHsVy/dWlTQgsBMJWLExcdG/mb6LfyuSSxhVNCPmvp06o0vKue/fR5xR0dL45\nbLaYhH3JUfGzLxqFrU25Jlah6PRZJsJtwS2Bz2kaxHHtfTyPkoTmxvOkzdYy\n2Dksg9nXTmrhUKamcboTjvUicokOCIKsfkK/66k0haPWZT+52BjZW6RFuCoD\nT8qdjNGKkDri0wT87CR2EsBPP4k/WH0o3c2dIYVb/bFeEEN0yjmvhUnzRzDv\nJzsVSf9UBOqL7w7l29eEoM87ANEtLTpi9QoQFlT2eCbcCNWMmc/tgw96Wi2V\nSOq5ubV3jKlqidSctxFfEj2X5oG1naXimQTyiCXYruoUVSAC7ukMQS/90bg6\naqSaO91nRPxh/04JBTFt+lDmaqUDTWrZmXtcexFpdl8ad2CaYvYKB09BEBnL\nVQob\r\n=uFOY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQLnXgnI4QDCFFU9Buks00xfFDlDbd8lJyshHh9v9oLwIhAIxhKCOJH32MeMYCyI3uWAImCxZZpn8bQlKUkr1gMyQx"}]}},"1.0.30001212":{"name":"caniuse-lite","version":"1.0.30001212","dist":{"integrity":"sha512-f0GclV7Sya6QkQW2uNHe9kq4hLG5u/zXCGIyQgvk6MB+61g2enOUJjaY5p25VZDLaQXIk8vWUenMjxGEWg06SQ==","shasum":"e8e70186e2cf1cfd264b69c2831bd39c6819c788","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001212.tgz","fileCount":811,"unpackedSize":1544348,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfnWeCRA9TVsSAnZWagAA7V8P/i4wuGWFQxfRrSrzQl9l\neODQZ7Fz7qqlwkz751pR6y6zQfKiIxalGIxsdlAGatxdlWOOAIBLBIDKsdHc\nKK6Bba9SvKjXKbn9UGK2Dfe5L4awRaI2gFN8MXYAtPg+mUpk31IL7e6E3vBD\nqC/ocEzihuv/J9AkeiF5zDK2ASA5+/m29fuXiGF44Pjhe3n3RUsLJte8V82h\nTx+R4CoKcrubxELS7nJeSCJKr+9ZZZEErfoJQ4Hq/9zqK7t2XiImB6kzIszn\nErQtphKJFzfWKEoSXXj1A/WTD2K044IB4qX1EJRbSyOSHaymrhE9wHa3Hyim\nYpBlynrbCGZtEla9mCp+P3aUfO7sCdvdPOEgCAGMhwkEcYgnLYPd6WH3Y0FP\nX1fn/WAFREBla7AiI5fHLZLfjPLdHhPqLcV2U4edJfTV588/jQe6SG+utyx2\n0onpoTbEcI1HyCz1Gbw1PGYa6Ey+nMChiuI9zhk3ratNIczu5H956cDnKsQi\nm8KXhiRI7bKn6WD/adDZLyGGlpA4r7Z4pGIs6ej1MrLh1WVuXmiGzOWr3tRF\ndSO+QK3+vV2XZLSpkpN+d/PmHX1sOqjvGQENRcQY//wDNfR4FFOC7gR2BUKn\nWWWGu6qDY3HjVE1bmWg9xCdCPWb88d7WmQHQhMErbxL/vdfewjV1VJogXXI/\nyzCf\r\n=O2ti\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEOFpLbNUK6rmOWHm5bV11jRrczCYpH+/wVnVR6ePr1wIhAJ6u6YB3594zwHu5FbLAUXje/cch6EZp6+EIswhKScko"}]}},"1.0.30001214":{"name":"caniuse-lite","version":"1.0.30001214","dist":{"integrity":"sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg==","shasum":"70f153c78223515c6d37a9fde6cd69250da9d872","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001214.tgz","fileCount":811,"unpackedSize":1544413,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfoOpCRA9TVsSAnZWagAArtUP/13tqXIEOi8hdSTy3Yrk\nbAlZ0WLUUNmvU2AL7wKV1+FyS3E44XjM8a1Cb5TSc7UJp13hzeRWV6cg0Hk9\njIShCCQit+PslsaxiOdFC+2Mda78mZ6H4fST9ZR97cE1xRiMEKI4/bPYCF19\n8NAQosC5Oeh75/WMLSxfbFTjxBuhRwOBjAdYJ45v7kp6gkiVF8MX3zJJTWtL\nmsXO3vG09GExYbx//T6aOF5Nc7r6CaboAIrwZJr3ZZyjv6A2QYh3dmiuTm0+\niTKBWsWbxPa53LHfP2dRzwGfCcONq6E9KQQlSRU6tHelUkRCM51FnQ5eQ+qZ\nXK94PtNM2HW6FZMkpXBSXws7Ro0lzPgDOTBZdaxjSS+OfyrVMPojyzsZ/0jZ\nQguA8wSY9l7OjzLntw/9t/7Tqi7ulmDrXIYH3rMU+YHBZsm7z4C5xNYJEmEY\nm8qPUmCMKn+r6FvONSKtnXTPRi4Kix73sUZuNRhiD/36QZM6rPRn7kI1X37d\n0anmnzafhQsvJLlPk1YZXVUo5T74gXz95Z/Z7jl/19h9le0DYws+QAwXMNUj\nit+UfF0Hiu6WHOTx8TGSP4dtPT0GA3y+LF1C2Ou4phjEAMHYY4v2Vzjsn3zf\nKZ71h8ApDOHgN/uTtNQ+/0bQ8YZldIsB2bJSbLYHsr6ZeQqR/oRpe2S03lbg\nlema\r\n=BNXH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/UpQjah47VnKE4fpJTajvzQo2dZTKiege8x/8pis3zwIhANU2Bks0PP3Eg5EuNlPbb/ErmNa2rkQxeaqWQ/e3RyeZ"}]}},"1.0.30001215":{"name":"caniuse-lite","version":"1.0.30001215","dist":{"integrity":"sha512-48WKhSpgduUNyY7cHO3lVy7v5Nx2FrvYJrmZjOoQP7w+5dMejWUhjAAszUXioV5UwT2ZWHDEbPgv4sBkd20jDA==","shasum":"4e7b45ecb88ea9d0c57aa0ee7acd18ae6515b645","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001215.tgz","fileCount":811,"unpackedSize":1544485,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJghlCQCRA9TVsSAnZWagAAY8IP/jDlnidg6JG2BXL/8MGf\nH+pgu4rMszpSAnJa+k3qUSU3+abggpHmfHhHykNBMf77x+6Bcn4WZcki5DRN\nOIWdQd2pL9NXufXC0DGVAkqGcXzTMDHa+y3ua7ltpSXJVJ+/X6yhPQBWSbUi\nkKh3QMfkMv8mPxsNk52Y8pd6SXWZ6BFmTIgjEao6iPjLpaPpqiecjy2KTttb\nXp5HE7weLkPKOvU6L4BPzUJVHs49htyZde6MF/+AYbSAt5dTjUKFCgaJLwes\nji8qCFbEwiR69XYEoHD15rv2f9YwkG5IXeb+0MLYPCzDzGspl05TzR/vZKGC\n96fIPiddNYgLijH5Uf10e7d0olpX+lhQ8S+jT2L/iWDntHLGXiUS3JGFsPhe\nRQEnrhgVhmDjNGb+pF/EW0hdpPrZQPxyGi37LKy7DEn/72x5jd8XgL4Ux9Ac\nBj5M/GaIdTYdRgVBvONSOrvsUtM7f+WRDXXDDTc1rY5bEqVdfhjnyh4GuBme\nGVc47q8VVGWngaH6gqdNcxJsVF86ruIyj/5qsSGZWxKY791N9nF8nqyIaou5\nTczVKpXU/ZiRbFxiDKGAmztFdDclx+Sr79sSpa0+jQ+yxu7XUsghEZ7XOzf8\nowwtjBKWGwzpvgiQ2ua71N50a0REXirqi4p6SNavyCdSl0wvE4EafC3Jr8+f\nQb8k\r\n=Nvzu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICa9Dqckv2HWQ5HKqkoyIMiA+W7/n6M5ZQheFyJfr3oYAiAkXL6UrQGfUl93VpGmBtfuuvoUxWmuY5Sr85hYRQ8ILQ=="}]}},"1.0.30001216":{"name":"caniuse-lite","version":"1.0.30001216","dist":{"integrity":"sha512-1uU+ww/n5WCJRwUcc9UH/W6925Se5aNnem/G5QaSDga2HzvjYMs8vRbekGUN/PnTZ7ezTHcxxTEb9fgiMYwH6Q==","shasum":"47418a082a4f952d14d8964ae739e25efb2060a9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001216.tgz","fileCount":812,"unpackedSize":1545761,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJghl6cCRA9TVsSAnZWagAA8UAP/1sPeboQRiofhN36Ii2g\nYD/HLHOK9afC6y1zbvIlyoxh5eDqSyxt7LefkVefW1Iq9j70w8rOAMn2IK4Z\nniAioGtW4eVJAgGu2sUEl393E2fCWajEzl64JxvF4bHD3JxU4MCWLyInsZMP\nzrvEUnpts2443gC6aZOR+HEcyXS7mn7kwMqUWH1Ya88J3PVVbXWprbWvbxnX\ndsR7bafRqh/LX3wub5bQIE2w2R0x9q1HGE8H845gR/ktQpjJo0AhpSzkoMO7\nezXHcS7ZeFjiNlLwsLSFUk81CGMehuu3ryMJDaGyCkz3HNgjMR9lW4EHjO/2\nH018O8xYVInVfxdzR8CdUhi8aKSMrJ9A9IVEcQwn/hPzs+kDQkhJolj2rfNS\nzzQObT1Q68rNDT1NgKXcTOKDgofpFcZBTXUSShTpZj70Tx82myMRV3QiqRw7\nof0nBmoNxOVuWQ8i4sACXFrKQ1CFWEbh5PLju6oJ8XIAEPtbCqln2os6cVem\nb/Z6RmnGI3xaEZWPZaNCSZhZWpSDgkca7jCj5cjZU8xnRjwzZSCzsNBIevDR\n5+XicLUO6kFo7ujb7fjLp5x8tyehngQtLjqqM5YCRJpf7xxU88Hf1cjiKLDa\nOCT/tcqIYPVwWged1HhW9CLEzYO7KKWsI/Ly8udhUTHQoP/mmqj7DeVzOl/y\n1ohR\r\n=WlIO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICqNCFxhw4EbX2iRrv+6PRuPPtrP0pizhi7xejdlODH5AiAUh3Z4an8c8sV3bHe6S1aZ/OvgDnB9wEIi2s5GYSo0+g=="}]}},"1.0.30001218":{"name":"caniuse-lite","version":"1.0.30001218","dist":{"integrity":"sha512-0ASydOWSy3bB88FbDpJSTt+PfDwnMqrym3yRZfqG8EXSQ06OZhF+q5wgYP/EN+jJMERItNcDQUqMyNjzZ+r5+Q==","shasum":"9b44f6ed16f875db6373e2debd4d14a07359002f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001218.tgz","fileCount":812,"unpackedSize":1567269,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgh7ArCRA9TVsSAnZWagAAEhAP/3LcqU1s5h9UuAbVb9IW\nk5uhuj0KKDIB9aUwfSPdMGaAbd9tQ9U52LEDLXqoF1bEGSXoPgMSi1GSvd0/\nLcOBZhqzFSwvyY9QLaxfvHQa/i/HwdOeI/6qMoV1tWgOO2NAXbHlC+ARzqfT\n2BrSg7PnegKp6PSPysRSKUp633p1URgKKJ9UT5YounMWpFL2HjEWzk1N4Sui\nC1U0uGt9nj6fSuS4yXE0VMazdJJOiNOgiPJGmckaPTJ4Tcc3Ys3bh4chMxKr\nxJ4te3uA9zapMNsNnsuCB24tnhLaiMwE68UygfzpE9TeZiIpuEvQs++OfyEH\n9dMfpIPUzYNkTQreuChY7n02XFEkciUeqTJe5vKKFc3JtZ2tEG4jo3m5+UD6\nQXPk4k9+O3dkwbde15skK24m72/6XDg1HjD36MSuGXK6D6FRYjnfelDgXehR\ntJm5+dYGPwO+RtERhSFS1Pqen1ajbiKnE4Am19crWqKusY3ITsXISTF7fvgK\ni9kyVECUV95m2fukQOfI/tEw4AGPFvlJ+uGntfrsNKp0uDfH8XNfWEMpVjn2\nd2TAM03ddvVUyDKFU0G/ClVkNvao+5XptIS3M+mGy5HwsHnZS3nuQYhIqfam\n9l/H+6CwnN8XQYBhi873OyjjoMKKbETAk+nXx233TxAnRFpO6H4n2y6xkJ2e\n7dCQ\r\n=YnJ5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFzX5OxL76dLeg8zwgB3paw86Oung8SXn6iihmfiyftgIhAOr7TWs4pB4nY4uruHQBskkUOeJ0AUI7F0CLirWqVxTt"}]}},"1.0.30001219":{"name":"caniuse-lite","version":"1.0.30001219","dist":{"integrity":"sha512-c0yixVG4v9KBc/tQ2rlbB3A/bgBFRvl8h8M4IeUbqCca4gsiCfvtaheUssbnux/Mb66Vjz7x8yYjDgYcNQOhyQ==","shasum":"5bfa5d0519f41f993618bd318f606a4c4c16156b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001219.tgz","fileCount":812,"unpackedSize":1569017,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiQGlCRA9TVsSAnZWagAAIgMP/1LP0kDbqnl2iEQbWaf0\nO6XP3N2nqUH8gff5/s9YgGV9uSBgzmnFJqBFTanrhfqGJ4a60/Akc2wTjIVf\nV+SdaN9XEhlZyhV0YllMcqdrKp+tGvscU2wnLewqPp3LU0zG/9NG9gTwjc/v\ne1bgFbECGvEPIRed1L6TineBRIEUSfyhfDm7Bzf28boxsvxbsL1m5ii7EANv\n4g93Drmd9o+zShTYWwco5ULybCBi7R3efqTOB8HP7xSYBzfFlTPvV9z4QUEr\ngaYNKPqA4R7Dvqzj4qYtNq6NCPVWC1/fnDqYElLDE/XzWNV0nL5S8cQUxS49\nRu0znQ1YY20wfl7tEr9l3Xx7TR32q/LJBtRWMz8brx0akMhMR0clurBfaefa\nntyzHOFoXLyF2GEQCA3lZDBVjfXOs1Uhe5fEzOxDpnx3lVr6LOsSo2cra70X\nb+5zOTFegldskvK8RYt3PSzMJv8tk9n3VronAgDR2Drslp6cjSLEVEuhiHTA\nAzaWcxc5sjh3QXnP9B0uXhf524IticeLOnRZUyAyWYaz1iqkt4PM72oTRLbi\nL/QYD3cxf+3MJAot8rmr+KSdgxunc4hG2hGW1ojQSC2g3EcT6+AwSZlh54Op\nu+4JjEftlP1Ac/pWRhyv3aPyUCDkWsk0TDYSI5Lx8ncIdjIxnY1hJGUF1/Dn\nLGuf\r\n=BFgV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCRpZpqcE3hMQADP2QRkszaeCScih4tub7jVG2UC4rSFAIgH20VlyCVPccYws9Yy0fOi/qge3xBWFJKCv1A7zxVDtI="}]}},"1.0.30001220":{"name":"caniuse-lite","version":"1.0.30001220","dist":{"integrity":"sha512-pjC2T4DIDyGAKTL4dMvGUQaMUHRmhvPpAgNNTa14jaBWHu+bLQgvpFqElxh9L4829Fdx0PlKiMp3wnYldRtECA==","shasum":"c080e1c8eefb99f6cc9685da6313840bdbaf4c36","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001220.tgz","fileCount":812,"unpackedSize":1569091,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgjkeeCRA9TVsSAnZWagAANukP/1MquqbzO2PK4apdTT9k\nJ9Ah0pwtlsVTsToR6NKZs96y/REIAgO59aNIkIJcWuQI1hPk22f2LFbOPQ6N\nxq1K5Y+Kkv3+D6rW1E3t3HlkJFp71uFaeBeY88kuGbsnia+M+OTciadb7KC0\nyMGabdGXqt7vJ8ddr/2ftYVeZdEOtGxCbXOEejIqJYIh9Qf7cK1Dgr3SFUby\n+Nyn9wuQ8GhrMil8fSG8ONCBuKnkoX0WH3x1MfKRV7OUyoojQJr16u8c5IVF\nY8Ba8XK+iFKs3wQBo+66ltxzs51g8v+N6r/OFasuPCEUoobOe3eHe/2A0BCw\ngFaN69+z/eBMLlBiRkbP1WqNTZenvSDLxd8sKvJcqPEAtQvcdgRJomh0fWzW\nSSbz77MT5dsrpHVKmOxYPsd7jqBc9oSJp/mzLXRTD1eMGYz6e71b9FJf4W96\nYRnkHIGaA3I21W9odtuljX0kCiNEqU3VceNuAgbkX35tkpGGhukQM6UAFrML\niuMlu73/GzQ3YS3f0+VEzUfbuPBK3188kJk63EUmHBlBJBV/PhZEGp+h9WXR\nwfJCxxGeSutcTwJvjWxcmYQCwTCE4wLWPwHPGFIixCVlacDa5RvZYVC469wL\nE+p7M+pAGvrVcA+NPovE2I4SiXMcFHQ5yQlEJVkqNwa2rRURdtLHhGtB8MAi\nThqf\r\n=Db2s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBvNzwGLZ++cnerzIzv8NSzPndwrE4+2W+LwCfk2jcwXAiBNiHD8hsgsqX4YYCYsBRGsckLY8saZtDdqzK97WNlPlg=="}]}},"1.0.30001221":{"name":"caniuse-lite","version":"1.0.30001221","dist":{"integrity":"sha512-b9TOZfND3uGSLjMOrLh8XxSQ41x8mX+9MLJYDM4AAHLfaZHttrLNPrScWjVnBITRZbY5sPpCt7X85n7VSLZ+/g==","shasum":"b916721ddf59066cfbe96c5c9a77cf7ae5c52e65","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001221.tgz","fileCount":812,"unpackedSize":1572931,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkOqoCRA9TVsSAnZWagAAZK4QAIVT8J7rb4ExZ0oCLZYS\nJ7OJ1AIXQNT6+t9iKuaU/dt6K8BBPmoZds9lqE1H6wj7DpHXRp9dKmH32ATy\n++MvtMk4mmkmXPrsgc7ArfebYdidCvUwX1ubycJ8YZOoSBMY9jza7IpGOecd\nAYKN6f36b8CkYzWIOLJlnTnrEO8/ltoYtaQhtk0fqDkfvpzXvCY5+EwfIrfT\nTCVey2yibQVRUeHxXAuaQjRj6lPmBXbOsgWkKfMujm2pZ9f92NoH7RylxnyX\noxPVPuvwiQRhTJEzZsfwzCJSMsnAINAtLY+m5Mz4ibtDt2h13qj4AjF40BL8\nAMuM6DpbOwHB089dDMNS+qbDUnh59tEbl89UNLvxq4OUKGZlzPDk0iyJNMh+\noTcnHKtpCSBqXAD9xcC90lJ5tit2s+hPcGC22PAC7X9n3gdaw+gWH2wsBBra\nICoYG2wE9a99td3kXt86llfqfm+z2KzwwMkJg3hPRW90iuWvqABMuZMIUkKN\n1ylJqxqoGEdCIdh59xO0Go1swmFLXLGhNNh2ZDojAbeXoTKyoQMX4/NYZsMP\np/OWDTJmyZ4nIL6amamlHzMTkuf99hi0WD+vwBWoSjZdYyHAlN3qvZLaq/Fj\n8dSIVEJWA+BR9oNbm/UzrORJOLfRznX8zdaSU0EedWl2o97hyM73Vuoqcnh4\n/fe6\r\n=OD/b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqeE6Gk0JnEQAxr2s2jHczYJKjz1XXy9IYG6/OowVpzgIge17FnSWZIlUFe9QjePn051vBkUKQFPd6X9imKyGGeWE="}]}},"1.0.30001222":{"name":"caniuse-lite","version":"1.0.30001222","dist":{"integrity":"sha512-rPmwUK0YMjfMlZVmH6nVB5U3YJ5Wnx3vmT5lnRO3nIKO8bJ+TRWMbGuuiSugDJqESy/lz+1hSrlQEagCtoOAWQ==","shasum":"2789b8487282cbbe1700924f53951303d28086a9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001222.tgz","fileCount":812,"unpackedSize":1573028,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgki4NCRA9TVsSAnZWagAA524P/REycJMrqLx2DpPHCM+0\ngEDHbqjWwO0WvLYeQ6VQR9uDFpayMR2Uywf4aPAXbGYKp7vHsURNCvYWSVkb\nqoZYmL7Ma4F9yjQqL7ePsby7NSMhU10GrW1qR34KfXS5uaA2xaTYwngiYI3G\n8uzyd5knLnBS/2RqO3R/kE+1L4n66SLuGaK0Ug5BgHqB0c1JduJIrsSUN8b2\n2Xkk4U1BZ7dqrI1HWdpm1q8SBNJBAQwbwkT5VrNO+zHMq3Au31Nd7mAo7n2b\n4i0yJK+8vm07CByVt80W883ELhaRer19kA8X3K+6+yGD3w1O9PMe7qX4DRSH\nZD0txBKumQ7894G2AhnHSmtb7mpi1HIEz8UIdocoknokPrHGJZmBHs4RdSuo\nkToEXy449dxDlHhkqAR1BWLfAkvm20evu22oenoHieli5hM0qOlbaKOd+OeB\nt3uwQbm9sK/o5n9/7ZBVnIstGZNVQANK4ib6liiaIEKyQUX/uk07vF8NPV/6\nD2TMSDQKTgW7RtU5hGQXuxR0kGaEmnLLY6IsxHb+1yIuJQRPIREUUFMgjl19\ni4GN9autoGtFPqho1WV8T0qlQTMQE6eXncQvngGJjLQybnTdzJsyUdzxVMFQ\ntl9rtDdDDZQDNRKXxREHfg8BbfXN/LRKYduKj3/S8e13DbKqYGVlAxlZ4Iwv\nkh7W\r\n=2CYS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmQdG+ZuOCwn0xp3hc5uc5Gh6J7UkKiOubCHLOpQqbJQIhAKoZF0gN2dmmjsWj8y7U2P42fL8yl5M/O4JzlgpxABjs"}]}},"1.0.30001223":{"name":"caniuse-lite","version":"1.0.30001223","dist":{"integrity":"sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==","shasum":"39b49ff0bfb3ee3587000d2f66c47addc6e14443","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001223.tgz","fileCount":812,"unpackedSize":1573089,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgk3+MCRA9TVsSAnZWagAAaOYQAJj/0DYnJcWp18EFaqXN\nQcojoyi3yKQIbI1u1Tb+h+Mp/jYBgCnwqjTPyHDCTdawy1VKpgdxBFMJk+04\nIccc3SlyYUTbVAsdRJ0hb5W7DGAl6XStUimEY8btgCdny3ZFVOCfoSyTfMk6\nwNBM80K9h0Wn0PKqJz1fXmH9eLoIjjUZfaOiX7fYtud9Kq0Dd3A9vzSYfPoi\nko3ZiJq4sB8ReV7SwsrNnuXvEienBnUgt+VsqWQdwcCe9Za+V+49Cj3S8tEh\nq6hEYjSdpLvk2lzlUaAYpzmHL/kDA97ssCydsg9Ea9pI9B36CxWMoVF/pdbB\nyer3NVgCiWvWNtKyvUyx3yJZnfdjOmVZHOalapz34Zk7zBu4WcFzJID2FQpW\n8EPlmtvhA32bGCEqbpEMSaZ7p4lCAaItNqofgGln3d2H3ar8fRzfx5NXqqkS\nsbAv8Hp/G2bUcTqlOheThvQX5ZEYEmPdh18HPhUxyXjJXfSEWnHmxmRR2HFX\nbtUp8lwIrht8h6JefwkA2RhFfJd4KQZMYkCiAdm43eUSXpwmXyOY9MbMDyby\nbclLNfzVGsdz8/Dhi5e+MADeTXDBxHfxZFysoiuQ+TjGVzlBibWWHstCAl9N\neuo4i/b4saukoNZrjGH+6y2BdqKhz2W7D1iFwvJNOn7OwoXVDZ2PQynFvAtG\nRr8F\r\n=0HCN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG8JZIPyIKVDcTqp/oaBwd2uYIXxMTN1gjhczJGoJKwXAiEAivf7h8qmNjXPolXTSaaYsUeOoK3VnVm3X6XB0C/TuAI="}]}},"1.0.30001224":{"name":"caniuse-lite","version":"1.0.30001224","dist":{"integrity":"sha512-6VJtwopsO01lEEG3CzErD0unMj/JeE65uf2vat8qJ5fcXSks045mcJOwo9aAFNNIs9DP1SbL0SpOy8LjXZjabQ==","shasum":"6fa646222e9e946fd6f5253e254a9b173405a51b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001224.tgz","fileCount":811,"unpackedSize":1537788,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmMK2CRA9TVsSAnZWagAAmxUP/iSSApHGoRHG44SipOaM\nLMe/5ZCqbGAlDeuxWSvra/0VVl90VkKQgX0qYAvFHeR3HGgKRR8fwa74+pKt\ns12FEKNZtT8QhGeBuMezPsbNlu9Y91QCbaTlVe8ynNFAwnJFE4X5FgJIehMR\nAUGxL1/fMMCdfLn+2rTQBjnsne/Pum8tO9ya3KwA3W792lNBJfxJmJ1fDveY\nuvBVnqfDlSzdTTdelK8d2voPJlq7CZWyERWeY0SVgmwLjf4Myu4jAymqVsZk\nmIkhBZFh3VHNSMHDgzrQAwaJo8xRd6vwZWYIjxmeGACfc8iPfzsaTmMgeQts\nfooh4WKcGDwtKsvbZz1uylsEWdTGf68jfJ3+KlZoorNNbNRzcGKg71y+rJEM\nsIcy6MmcvuUebg9TsI0YolPQYfP7+QC9++KAWGXqCDr7v5Dh3vDd83b07Wpr\nrr/wEfYtUlZgJDQTYZrtczHxmnZsSZ0QJEPhhKB7gDDTk8NPGEUx/TbcU50L\nz1QsCsmuNE5ZFvMH4sHsRIQCKQel7xhcKxiWvQdF+z7+BljyEXdLObA1xdfd\nuOFP5RLlidoIRZ2ayBD42eMMsRfivyor5ab4NDBPMKJ3hE5mJ391O37GeeTG\nVq3F7Sy1FpexiOEJTICqJ2kzFE8CLVEAnevtFO9J6dLCiQdIliJdUm/cImaH\nlsCn\r\n=xvaW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDt4FS57pveb59dhOFbv581rcWZPlfVU4d1tO/DS/QrmQIgHl5t8RGjO2zPINNRgtey+c+611pDIQRDU6iFZDleP9s="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001225":{"name":"caniuse-lite","version":"1.0.30001225","dist":{"integrity":"sha512-oDbH3OluyOsP4NEBA8y3XUNZMaN5yp/Ra+WGs9IebgaclHSks70axdwFH82FBt/HmrwShBmltHkU3ti9mgxQgA==","shasum":"4a79952082ddbc2b0e707f05696372b07748eeea","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001225.tgz","fileCount":811,"unpackedSize":1537788,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmMQ+CRA9TVsSAnZWagAArtQP/R/l/eyRZJJql16OSZ3t\nrOvkScWuXBxDuuOlzgi2S39imw98HVX3TY9+9/ZTj2xlrVErKGjb2xUXDeuF\nqO8PtTOlgFuo8jV0IZMT48kZzv/dO2L7zb3oHbHeqO8ZQ3RSa0Cj1swOZ6mt\ndAycL2AG/r5DdqufS4jNLX28+Tl+qQX/0q+LqqpdLUWAoL/F4/+xEKMBI/YN\nNsRf7mpCHUGO2utp395Q0qLhAK7qYv1LPVgBg8u6pxrbkUfK6UWXsmdXBGzK\ny18++y0b14f8R4O0fbl/vWJKlrg9JGuPksXvo7Ltz2iSJEdYUJEKF35Ywl0X\nK2uolJU0D4+ktYe18M8eJ+Gw9qsPXglL1h0qnqNdcp53di2eM7vC/hDugiDS\nN5lEx89GPfXY30MJY0q55HKvS2U+BlrPy2QjIsLrfVCrWCQkgP/+bqvkSDB9\nfSxLyLQCs6GlKRsFoHbeFcmpnwaVl60kllLeLokgPrKqH3NL5Kk6QK6TfCVf\nhHFs0HkCxWYdhSdD9ItXMhPmewF+6W5VC5Bg42mwR4INdjPV7+Fh6zTVA47Q\n+MboTSx+HOhgXzKLpE5Iqu5qWSlia02jvNaLeHLneSzo4eu82HXEAzfR7TRd\nyxDel/B+0YubpIaGjVx8KLraQHI3m1QyjU3b9X2zDqi70jhZAFtXBhaBOdj7\nAnLp\r\n=B7Pl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLQ0ELP9iiG/AcsQdhJ4cOcm5UHE8WtUNH8fqQuv8vgwIgCAbW0its/UrpkLv93t0lib5StSb4mTVK26mScdAEnKw="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001226":{"name":"caniuse-lite","version":"1.0.30001226","dist":{"integrity":"sha512-sE0viwUM8SUO/X1j6DH7GREtEnttQhhIk1hO1aicn1Nw7hbMH6NZhnC0HrJRKyD0/wHc0bg4pMRfQ12/nNkozA==","shasum":"a28492c63b8e32dcbe1bfb8b4430de97a6a9785a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001226.tgz","fileCount":811,"unpackedSize":1537804,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmNLFCRA9TVsSAnZWagAAZfMP/itUrM2qFiiFLJfUz2xO\n1DYWLKJcBdAPuenL3S7C+crg+mXqfrBSzxcDFHM2UscCDawUM5EjFWxKYUyP\nfg1X9f8/By67iTl+NLu6HdAq49y7eK6648uRYEq7aKhl4RbN9PML1SO5paTv\n7e7aNPzzjTJ7bSatznBd5GJAyXWJONBvoFYAWoYe8k3KnV0EevIHtpLAu2g9\nkqwRuVPOvKVkIJYQM91lVRt558fIt2E0s+l+u99/mgnvfIAC9leSIMHymq5o\nvdnkrQyzu6uNrvY5CR69o8i9z/4huFCKvcmCW5hHuktT7zZSlyP9Lrt35fy4\nc/pnYM7FTS4vC8GkrAW6VpycdLqLHrRXFs5Db8RziGRXghwQmIIyeyEnonaU\nVhb2j1yhCS59wRPs48cwYo0vl2jTPiIq/isUZAM8d823POlA7nmNfmfznp+r\nrOE6RtRb9s1db0+STImCiQx8zxKbXiS2YffQX5GwXG1C1uaOxgiS30Q4E6KW\n1E4Z9kzUMhVBeltC65uxRgCxkjOWzDvZsSeB4SJdmUXYFLmzIClc4feQiC6v\nPYKlNiExodY9tPEJitYyh7NSVAxLkBGc4bON4d2+VT4rju1inWEV/bHQIONg\nPcJ5idhRbQHwjPWcReXAjXSkugoxofFS5qKD5ojO0kq8diJ6CxwzSGvN1UsF\nhkxA\r\n=tHxv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCtTMaV87Q766lTe3K51j7PyWftgZfAYiiyd3+KQ9vBFQIgCR2PuwcvrkCTQ3H4OjsKWXl7CCChAxjAijSm9zALONU="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001227":{"name":"caniuse-lite","version":"1.0.30001227","dist":{"integrity":"sha512-HHZT4QpUw4Pf45IE3xxKAPgAN3q2aRai/x5TSHP8lrrKzARoH0IeBviwStcRi5lsFlscTkBbXC7gXyms43151A==","shasum":"437fe8b514ac4512d9bdb4ea79f20c400bd0b4d1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001227.tgz","fileCount":811,"unpackedSize":1537676,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmNyPCRA9TVsSAnZWagAAKW0P/j/xmu3Qsgm1ElHUuIRA\npUeGDdfEwMkYArVvYPBT12bp2vRIzpKYz6kjGjluzHFE0JvMunFYNbcAHN1S\nz2ivrV+dCjK6r6gMhKAVuf0j0rTssmSXZNLbP3DiLmzSZDklFeSk47iNykqG\n2yVM1f4B102tKyZ4i69ImwOIUm0h5uN/fahMAuNxVg3hK6e5awGL4e0t5/5j\n2V6ZdwWGqKdgbTWDWPWHim/WvvtP75Zq9VhRCZRutGf5UYgyY40A01hYBekT\nKMJB+xJxY8bS8C9UHSpAQC5MRZWLzCQmx7OUFTfLCbIGNDXdLtZd4oiIHMoH\nkPJodvaPKAbfGIiGepef/cl/CoxzoyEZP43XMUBGgtChl6iEsYrlOrpZkC/J\nfhHj7Dms8ukU1z0618O+wjKpHdijMHCNZgxkzXf4RtK1Mpaw/WzJyTUURedq\n3iOcs3IL3ItQwazkqGkmhDDWf6dV57xdAqI2I9CB8G2g37Gzo3IwE6g1ijE7\nQtRcZZ9odfpR7LWKVcroPqKwKjMQA5XtUfYB15fdibZu2j53IlBLqn8rm8Lj\nXrS/o91cMeiEZVSyGR0aH+U7UVSXdvsnkocoSaa6PFcY8JmuUjtqqlDhlriL\nIKqG64DQV5uVJcgGKFc6RVd5t1//JYY4sfq6w02PznalX10PxDj5gGynj83H\nFUi2\r\n=51sP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIANOFKzbhib+kTMEPl4HlvTrhasJy2bpGzEEy6BFwcq5AiEAgCnJobV0zmTWitbkk7A9VAzxy/2CoH4G5xW9V5m9F6c="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001228":{"name":"caniuse-lite","version":"1.0.30001228","dist":{"integrity":"sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==","shasum":"bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001228.tgz","fileCount":799,"unpackedSize":1525184,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmUnCCRA9TVsSAnZWagAA/6YP/0IGV1zeg5sbxE/PX9Q3\nI1EG/ZFspEIf/k0qOcA4exYXUeK3DbVnWUhqYJ3N6VHP44l7bAEcuQjvwSAo\nU2xsE8seDDxYtsHcqnew8lGT2fOLtdl93UbN10Q7eUrmDKj2f5pEq4rAJHs8\n77Q0ZnN+7tAT2iH5WBd6yDrvDYEyeB57NZVZY+nxUDTEjPs/eOiXBV6qdvQx\nCDDUcp5LL/vHKyy4+0nIOcmQniJBSsez1k1LbIgnU0x0t/Q6z/dxUnAmV3OW\n5CaeimX0fR6cioYSpeBThWh1hVdQg2jB5t9ZgxF5M0V0LukUlqI+dQMX9Ujg\n8zjpZb/9OQFG3tGygnEkGBsMP+D6DD6NDJK9BUuTKOtmKAinzMBCFeRbmZZ8\nLkn1Z/27QLBdfmCVyxpRZfHf9RghDYE9KyCRWQhg4AZmzZaFnAO2phijSujH\nZeRwvr67IKVNWaZxQHPvcx5rqG09fJv+69yIXRFFa5iUmi0vbFM5er5+b4LM\nnoLe/4+tZE4m9I/KwZ3kudKu6gDowxmv/vak185CqfugkrA84hnJUyWiAiF8\nHp8BXxakQGjyiO0tSVmwfksgLIm3cFRS5+r3CMxgBlYGRdJmdCMXAIoE5T31\n9EeG9ROAGAcnuBu0zpPZq2kHLYd1trwg0cmOHC9iHfImiQUv+TGYt7onma3O\neYzk\r\n=KLqy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAqjFu+Y9bnuoSONl80vAvfwG/Uaz7QVlJOMQu3qy80ZAiEA+Rz6nLo/vNitbgfT/wuB2/lkc/Sifm16FFB8dI9UIms="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001230":{"name":"caniuse-lite","version":"1.0.30001230","dist":{"integrity":"sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==","shasum":"8135c57459854b2240b57a4a6786044bdc5a9f71","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001230.tgz","fileCount":800,"unpackedSize":1526396,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrU6TCRA9TVsSAnZWagAAXecP/20fJ02P59k2Bg3pH+ea\naZH4H2OgbOxA6ua5Mk2hvFgViIwJTflw481s7tAjENqsU/Rjl9VI9bRbPjmh\nJ7eZPChUmkR6mTY9yQGH1yOXehqfqG115QhItxsexcJPmtyPyvlJBbcTY6Be\nVIYTRv3nKwsrksNeLRCSk9P1/SAntsGPkxm3vN12xz3dfPShVLeRmpbi34oS\nP8YkJ8u6CIDjnG7MFISEZCRjQwEK/LoDSmtgOpzC4WJ1CT/9JG4vJtm4HBnF\nxQLLBTkDCZVFhYw75j/2EAfq50BsC7EwwTmOj1ac5Pq54T6BZDej+n/4h4Sp\npuELByvc8neOAvi2xTbpSHtESbpKPk/BlgcuIa3BqdYECftPMw5rH8PqSasY\nBYPDZVJsG4jrrE+P6cW4QZGz+SS3EeTyWdJGNaognkxEhzxZEgeGff2cucb5\nExS59MRWAwWA2jonqx4x61SJorBbIS9gNYzr7dtmk1MJ7DA+DksXGoxsE0y0\n0jcY8u1Pa+4SFs9srE11nU4EXL1fGg9FgFagMd5cysxwshbzeXogZPpk6V5/\n3aMwQBVQuN8Lxacu05FLu1m4sIFeru7xOlStZRxuYuHAI/B3kItYiqPa5VFX\nQdE5Ny1xp/TuF6f15yeMyVcBYekY0egsvF78JKA47jTC0+5SVDJlLe00PZx4\nUXEv\r\n=ly2i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCH0UiDSSFjYM6I3s0MKvXFYui2QABTAOhncZzTRf6a+0CIQDSDaulmVEaR6kPcxNbkdUu5ActNVGMX9AUFu1suK8MwA=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001231":{"name":"caniuse-lite","version":"1.0.30001231","dist":{"integrity":"sha512-WAFFv31GgU4DiwNAy77qMo3nNyycEhH3ikcCVHvkQpPe/fO8Tb2aRYzss8kgyLQBm8mJ7OryW4X6Y4vsBCIqag==","shasum":"6c1f9b49fc27cc368b894e64b9b28b39ef80603b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001231.tgz","fileCount":800,"unpackedSize":1526411,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtIIhCRA9TVsSAnZWagAAopYQAIIdnT42//m19YAoBoYG\n1Yxj2CYtXyIpeOdqPh9U24dMsH5dKAvQEnhewJ3FkFTkSOy83dJCi++bFkWM\nELAg+6wLHo216tyvzfkicBIyfyf/O2xPaxr06GZg4lfVcLuJNhqbdivGW8ms\nYj4/kR7J/CXYS08gyVjdQB5E3oFgs0d77MUKlvbm3rxgkwZD2vqb1uLyR5Sq\nKZ0z5F30j6WuCeNfLE5eFRJluwqoFp5tLsZMrt+bhDX3F+8OAa0RuxJOP4Jx\n56IGiBSe50IOGpYLAwV/5O4MpuHFnYlnmUwA2PySPd9M7/hI71pgS3NuExJ3\nwIBMI+AYO0DQkkq5EFJa7v2VciPIuqPEYxtoPeNkweuC0tJeRKYio1OuWZg1\n07s+0Rj+5O6PDIFT5jyrM++XmwE42/92oNI78pyJQhRtNgD0mJzHqz7BGsaX\n7yg1HLubjYgpz2IQ+78r5M35+2b0e2eplP/LAGfKKZtjOc4rTfJvJLxmOxjL\nHiS4TefWFgpni5I2AR6um5gklGSyxOy8b1ly7Z/6kGvXyAi6gXrkDm8mZRLy\nsp/fYWZeUIUspgMs4/RHfaiI6KiiM/bFiLp0ONKupxQwMvJl/o6rOdNacFni\nlyTQrvmE8b01PlaWXNuvuPwrA2ObkCxEynlz+9q9TqpYdoDK8L5Zic/4SbfS\nqkCG\r\n=ZecF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFhdI5IpbFst97ZhdfXnS6JVfu4KhDnAjOXFd4bTJiM8AiEAjJbJGOb+BaX4croFq2qST3Mpo/jvA9BKd1psfxxa/3E="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001232":{"name":"caniuse-lite","version":"1.0.30001232","dist":{"integrity":"sha512-e4Gyp7P8vqC2qV2iHA+cJNf/yqUKOShXQOJHQt81OHxlIZl/j/j3soEA0adAQi8CPUQgvOdDENyQ5kd6a6mNSg==","shasum":"2ebc8b6a77656fd772ab44a82a332a26a17e9527","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001232.tgz","fileCount":800,"unpackedSize":1529735,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtTApCRA9TVsSAnZWagAAU0gQAIRdw3Jkk2UBornLJrSU\nQaxTpKYBqkF38qcDHPtCg0cJR9bt/ZXcgVJ6vfFyxQl+LlnDxFKvitQ2jpWp\n0SXfi9w4u0O9rgaHKFANyWwL8a+5MMbeb+jIRt25qMpFYZmVC0tJv3csx3jn\nSRDqU6SmI4j/+doLo79ezY7GB8kBHpMRMIvYmoqdQlf9TsYnwLMi2zL37E0U\nOjMtIHZaxMpJslkip7fUv1QkRHZa2gTbLvKkGplvlJwBsUq5kmiBhvlkRcux\nQ3fzkK9O114bb4BebDihPwPQkUwONchbC661/XxK229LJVlCu0uVy4MedUrT\nwB9TlCvhijGmiQwb7EM90R/XtcpJxZhu+E25A0vnLAYM6QdS14SBg/56tpvx\naSuF02+NY/OSCjufHcCFXKmtg2rwrOhcQRuMARFcwLHUTsxNm3PXlPFM1VEo\nxlJopQn7kR4AIQve4feNoR2mR5X38NveSgzltT5eSxQHl24wonYS4ZDQs70Q\nErb07jH6iaCJ+fKQz03OxLcKkk12oC/2WSR8dZLKRr969qLAmnkfNzURF7ti\nTE+w1gYOU6Ey3HVBjuIu0jVwPo+2E1Xzk218WAxm6lMRURkbbYdHpoWkHkFB\nNoeAzDzm01fF0roHLVxk81ua2RaQ3eOCRxBciwmdhqg0UIib5+2YogvZTmcB\ndeYs\r\n=Rdrx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIALQ8yfg0zVKAPNg/llu0cBo3bWe7W4wnLkfHxQRXv7pAiEA7vfAfN8n9rJRD0lj8hfS+xglchz/Mak5+U1j0gUtw8o="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001233":{"name":"caniuse-lite","version":"1.0.30001233","dist":{"integrity":"sha512-BmkbxLfStqiPA7IEzQpIk0UFZFf3A4E6fzjPJ6OR+bFC2L8ES9J8zGA/asoi47p8XDVkev+WJo2I2Nc8c/34Yg==","shasum":"b7cb4a377a4b12ed240d2fa5c792951a06e5f2c4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001233.tgz","fileCount":800,"unpackedSize":1531442,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtxFWCRA9TVsSAnZWagAAJyoQAJPgjSdrp6//4giuhDLM\n28sEDD1kG4fgoapjjQVZ2IipEgwEc2eZwlyPc20mLKkN6IqESHzVksiGCKeD\n2PVjzEeo7nEBdGXSXUJ0MirzGv1902mBS8JfstcA40y0N68s91XAvyQB8WsI\npeXQLR1hfgxy2i04ppY7Xnu+oFHHnWq8RilCyFmfF0hcMQyseHAA6SFaEkUT\nzfVo6TX3uEagQ9UE8uNE+c11KxbVUVvvO+Uk46rTN1nJxALka4AtGjqJ4Ktn\nFyRhPyMuPBlYtG7ucgYNpHOrx9pCggc8FAfM2aptsitfEGS3bO3XhJnWihKc\nTmayyCla1dJItf1jjpRARmK8/zo+V8yJ6gk9l6OGiDZSqCpwALbGOqcknWEu\nvmsa2HV29RZE1chn1VoeiZgNP3yUYTSXwg1/d0a7DwRYwYNHx8c/nBbfxUl8\n9r/Ex6xNCfh5rd3pIlIb1bIMQ7LzW9n7zN3llhpHPZCxIfGNcKWSJ36NMYU3\niyG06LXICbu8KR20ZZZV2r60CGWRT7XQbNoE67ZuXnPb37uNrviL6iqzQUPT\n9KCLHv75G9R3vxHL8MZN8nsZPT/9Ak5wdnGPbeCpWAQOYekka7c9Sy+nXTSy\nodspJlEWzl9YJFkjQfDmrvJDjH6tjTAp4eR7JWHeY6T2/EaAivTL/FU72s/o\npy6f\r\n=5gY6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDjBUaVk08zezqD6s8fBOROAxniwCAqgsMIZMr4e+DXhgIhAKtmTdJgQQGXv0/N6OrXc2YCA679EphIFUD++26TQNZS"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001234":{"name":"caniuse-lite","version":"1.0.30001234","dist":{"integrity":"sha512-a3gjUVKkmwLdNysa1xkUAwN2VfJUJyVW47rsi3aCbkRCtbHAfo+rOsCqVw29G6coQ8gzAPb5XBXwiGHwme3isA==","shasum":"8fc2e709e3b0679d7af7f073a1c661155c39b975","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001234.tgz","fileCount":800,"unpackedSize":1351558,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgucgVCRA9TVsSAnZWagAA2aYP+wXJOR5XYz9zyVjdQjfT\nylo57mNYTsbPuMthRQDEuGP6lMXq7iWyhUf/+uWfAA4w58BOYqrJQHGkh2Uv\n9BGCYF2nDTtc/XW4GL7lCHF1YDMnJRIYFdLR2ACvEiwHMUuWSyMdR1jue0sb\ny1iOBMRxwJJfPZajcTmVul6/SM2svx6EmyPpXh2XkXgxCmaiWrK4hBDQxanh\nc92Q9JZnoX+4/dJ5W6kDwpjg0it4K2PfxYMLxeifFKuVu87o6hFv6BZ+L0xT\nNgPUoY2GxXTAioR8O1OM3E2irujWaXXtHkvNd2skYTtPGVapB0LKhOWH/0pj\nraixYM0VaROj0jMjU0prWwB0BGZgSpnySliawLBz0wBMaaacs4765jLM/Tq4\nvYae6irtyyp/s4nEHqdEXYIivzWsxC/chTdTRcgOL99v0dN5qi/kXLm43brC\nLeHaQV58pXV31nDOKy6WbTmI0BhHhiv0ZOIB4TV3g4jA0ifcjHDqYLd8sBcC\nMDkxYNMk6rQs/8THAxs1Dg3txCH1BNJ80EnMtR3WNQQAK9h0eZVmnJlVuT5Y\nbNT7pWklGxtRGKlwvRg+ME0GhehgZFS5FWW4L5rMfpmqO1AqDoH+LAPNiDe9\nyIOcVotsGt/8DBkEAcCKXyxrGiAMgEty695EicUTG6smOpMOUtmSVv3xaujj\ndwdh\r\n=Ok/y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcbOG2SsGBCo693HyId/uX/bYw03jLP5MbgDubDQbtoQIhAMzF+fD5h3+6UjwFDfA8kLZFanpw6xUiOMFm4SNzrDlH"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001235":{"name":"caniuse-lite","version":"1.0.30001235","dist":{"integrity":"sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==","shasum":"ad5ca75bc5a1f7b12df79ad806d715a43a5ac4ed","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001235.tgz","fileCount":800,"unpackedSize":1351560,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgvFSSCRA9TVsSAnZWagAAB4kQAJpzfCyS0KEALhQ6Ux2/\nPrkiR549vKn8OBN/spgXWkxTlSK2tbA8i+0QfxVZGUwbcfCUX+PBII4sFmKC\nLhd/vafw3tYVWuCMgST/LCAQgE5DovY/6FJiHq6KEN/4+ENCyjyGa/jlYTeL\nRRK/x2teSpdhUX8a8G7yI3D8YPadsFhHoO/3jrI5vlYT5G3TPhwjCZKGSbaL\nTMBytG2slYgfIu9ZslssPkM8ssnHZatOzkMm4ARDh/pWwiWaiTNGtjNcdCkY\nfN0qecwS1QIywECzHUNmt+LqDs8Dh2aXt5IzX7LxTRVd1QhAILbgH7NnQ603\nQ+VAl9mmTqWhjeKIcZaNwS+8GaD5We0VrDpPIbyeRIiIGON4wa4rHhkBRxA/\nvd8kiaUcyAh2BJgw/xFUgfyXuXbAUFMO/UgUrbTQS/e/5TCu5PblxGGqn+J0\nQPsZ8Xc8yWq1zDxI0OsRnEereiXsu+O1bIs+E2UtYZmqFK64pYilLetz02ce\nmOKt2A+ywKrkbab8FldmULz9D8U7ZDyh9spBc1X2NP6w9KKskZTmzQgLU3u0\n4/dKtPvlu045MbLXvw7KIXYn4RsmBLyCr+TmJ2yww5GPHU1yy+VzLTLK9PNd\nNZw6ubFtFxuFWdkGTNRStoxSqlD6SH3uc6Yl5/5AmGXZ99rjkiLEp7TKB3ZO\nWCqn\r\n=oBxb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZBJIFSH1q0f6NTGVnJJCr6vVsdXVxq1a/3o6s+e9d/AIhAPTp4AIDU7nvsm2bSpwjdtL13nzOGhPU5/DPJWoN0ZxP"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001236":{"name":"caniuse-lite","version":"1.0.30001236","dist":{"integrity":"sha512-o0PRQSrSCGJKCPZcgMzl5fUaj5xHe8qA2m4QRvnyY4e1lITqoNkr7q/Oh1NcpGSy0Th97UZ35yoKcINPoq7YOQ==","shasum":"0a80de4cdf62e1770bb46a30d884fc8d633e3958","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001236.tgz","fileCount":800,"unpackedSize":1351560,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgwFrECRA9TVsSAnZWagAAwYQQAJw3fj1/ymTUypau+xFt\n5Rh3QRd3nnXV+5DzlCr+3CUICmaR9/THGVGkbViTvBlwp3EX5Xcp8c70n3ND\nJra3IpRKodPVJ7pKJTPktRknNZNSZBoSh/pnOstPD3IeSvkYJNSQ4GEV66j3\n0DZAoA1WKTEBMgmkrWY71AjsFIgMrPDZTEZ6QG6IELUujLIvg+d/+sU+kIeN\nja44thM0/3qeNfl+SC4S9h3DJ8eeXjd0rlbc18vPzi/bPJ+OkvJ5TP2J4jC6\n3rTlKm8Od/mAukG6hYCDsqMdTAmgCXxlt9p5sCUr8xdHyYzXjFx8GLaZ46Jx\nXe07ysaBgvnZNvsqrYhyuAtD5sOt4NfKoafebiDEIvaQ/z3GzXPFTGbvwBC2\nh6XKP30yQMNN3ZQAwqzEGgE6mc/UAhqidiJ3faSkyyH41KQs5L3yQOXFuyv7\nNxB/oR6J8evPNc4dAjr8tdXuqJMoXuvpUinb8uMI7AgPNzlrF8lklFHyEvda\nuRTq8x2jFnTw/WIb6XA/5Eg7nA3kz1EfOflWPf6zEuHvVtwmwCkOXBggdu8y\nja4Yjdvg0X844sKG7VocozYhv3smoyBWvlhM6JdnbsLinEl64j8zb7+RcgFL\noFIheCVdIWNTLW31u613016h1f6rSdGNgbm3xhAT1KPJBg3uGwyiwZ3OUNjS\nbyNn\r\n=TH8k\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLW0NOmaRPw3XzGgJCfy5RMorfAdypU/Wzjsyt4Uic7wIgeUz+ueOZ+em9MYa+sFe5TKGhmpsjN1WtgfpNMNNpGUM="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001237":{"name":"caniuse-lite","version":"1.0.30001237","dist":{"integrity":"sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==","shasum":"4b7783661515b8e7151fc6376cfd97f0e427b9e5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001237.tgz","fileCount":800,"unpackedSize":1352672,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgxEqHCRA9TVsSAnZWagAAXD4P/2ux1Hg7LdsvViu9rbPV\nbJr+4ZGuJfdgZmpH2IuyktOnaQFS+kZRXgNZa6dVBTZFUvzAlJW3DPVFYssr\nizbP6Z3viAJgryaNeaix9UPoIBtjV3B6gZRGRHOgaUT/gFEeif9lN/rWaKKm\nVKdQqtgeaLioSleCepFZ3l13peba0HL1Tmj7rBJTsFUaPvMhv6Fre8UjQa4S\nDXHRoQ1Of39lgpDd8VnDPy+NNKdfB5vmKNU5F+Q1BAIKhxsQRJ+LlCJ2mhqg\nHJgE5tiKrrdk1CpAAxdiiuYPcsFoMQgbU5Y5GMBLfOu8mAt5K6RdKnU2Yxun\nbpJ6Cto3fTni4PTmtsOPGxZ27K7i2iBdo2pgmEnG01t/D78F0FmTcb+0Eg+T\nuIWZuyjPsTc3W1SgtxVwfe8gx47YzUml2rsbb210QROEGemAP1q0H/DwsaYL\nIRZjUalgFhVhPaCVR0fT/qxH747RlVvMBAdu64BmXzXNKlYTTEIH98JEaXkc\nzGtm67OBAdyqFUVtLQM4jkjOB1pmEuncY9vLC6ulvQvB15cZcRLicxmWBZyv\nnYDOVMUtSV+YSIxtNh4PB0BufhVtDjaS81Yq9XqJhFmKaDpIS6ZpSz2pO5EY\nXqz0Is21FoHH4P9G8VvVOatFimwyIftKqAZwThaSsbkKDpNGfJuFDejcZIMX\nWJcT\r\n=Cqvv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+FPOPcdIQ1EH4phs99vKB226Dk76P0dsrD0BsYuVoLQIhAPpsnir7GeEx6IrJZSm/uVGe9OjTnKfVJm9DxbKs4Avj"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001238":{"name":"caniuse-lite","version":"1.0.30001238","dist":{"integrity":"sha512-bZGam2MxEt7YNsa2VwshqWQMwrYs5tR5WZQRYSuFxsBQunWjBuXhN4cS9nV5FFb1Z9y+DoQcQ0COyQbv6A+CKw==","shasum":"e6a8b45455c5de601718736d0242feef0ecdda15","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001238.tgz","fileCount":800,"unpackedSize":1352694,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzET2CRA9TVsSAnZWagAAA7YQAKOGa73MsoO5mxOXUMfV\niXtg2ZaWEk9DCwicKE/iVq4W3TCrEO4ZJQPOqjmhn+q1EnyTb9MJzU0XrOMT\njo5dPDstzHjnfKaQTRZo6i8XBc9LJPtHX4OU9HKQdPQD5z+FXNR/ynf3A7mk\ndEs/hEhqL989hhYwEwgsN4mQbUwa0LFeHgkjgVRWuFdiiQ6AA4CIFwCpHrLN\nRHpbsE9YSnMHSpr1sm3pc6uP4Bgz8cAlw1ZfKkkemEXIwR7HOLvIcyePgwYJ\nPHhheBKaCHbUDBNHI0jDZPxvZXzBZ5rtbhf3kdyw6203vX1U+kCkxx5rEm9n\nzxazmzV2XMHWZHB4kc/3N2JQKDdwLSlTyej4Gzr1m9pNymymH6GkfkWGluLs\nf6rIKdGQW+ijTtsCAknOY5u2OGTGfb8j31Eq4AQ2P1Y7ziBAu3wbunzzUspP\nTQjM4iCkuAF3RtYqbuT4fCyK8WkJW2xIC4ZoD8rAKwvnts7EiMTvJzzqtKSt\nHXrftEwfiTXOS52E3NqLQJ17iG59SBV+kRBCu5WG+mpBjZOdgo3ZXCK5w+d/\nRlPMkGKKXar3VoO+6t3gpvTrtdJJ15AfTQQUMXJt+HBPU4qnLXicnPUB6deB\nnuMMHiQe4s1hcm9t7LjhIppGrXSUG8nKYJr5JYTPbrKC2q3O1RUo+bdRjc3E\ne07I\r\n=Yhm7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB3SOV+XWH59xEaoPodnmmi29QD7SUktU3v0kRFsBhxoAiEAi8FRHbNAPvKQ6TK2k+4NREYwCivRu5A+sWO6xEYqiko="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001239":{"name":"caniuse-lite","version":"1.0.30001239","dist":{"integrity":"sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==","shasum":"66e8669985bb2cb84ccb10f68c25ce6dd3e4d2b8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001239.tgz","fileCount":800,"unpackedSize":1352694,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzlfKCRA9TVsSAnZWagAA9ZsP/iKmhppPHWcirhiMQ8df\nU8RL08cLfx3kEGaGRi9w2ldhjjkk/GGb37IIBjua3IvM/KmjZ5bzgx+JlHBf\n4uCuI7rcpymvknb93r9x6/pl6OJFvzuXuTXp9G09mpkQ7T67p3GwuA2DUQqr\n+GT7HPMMbC14UbmUPDYzVWI69AeKNEu6dHUxEBa2YNP7sGh5ZMhmBRFTreu3\nszKXoBvVerJ5au3nBlhd0gdP87x1RAD6/Vwp1ennXODOtdxm0yKkzsRrjTyJ\nWxX+mN9rPkptdwJTp3j4rsSiT7dvgbwPKvVjTn7qRAVkyUCSWY7gqISz7YxW\nZKrOx39suhPwY+YT8JbyTzsLUrr+DbEgW9XDgqzcSoRUNaOYQdVGpcv82iqd\nA/l4X8U7ANKucmjhHVl4XaWv1pImC8AtedIitSKzJF7GgBefYnb7GEeUTLKE\nkSmpC//9u8Z0Qfg+E3OcfgADlhTrzeFknjctA4ID0S8xS0MxJTGA63aPfWxs\nM0qniQvpn/h1/VRUhVESUdadPCHsg7NEoPpKews1zve6XSBwJnJ86lx2MbcZ\n4+bafDPo5tmFFW/7uXE4QGmQZSGbyvytBB17tw2QB7urEZrSPBD5yFSSWcGV\ngAFWrw/KaLxAm7+YZg2ILol3eztkJWjSBYQw1zfsC2O7Oc/q5pZRVe2N4b9T\n8P1a\r\n=qNuJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFqM3TUwtEqWGeXcuJI0IDO4WhSTZdFb2rJ0sB8b0a0FAiEA8CgKVI13sBKVsSgEA+ChdY0PhyRjzfprQ+F+HSZLTcU="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001240":{"name":"caniuse-lite","version":"1.0.30001240","dist":{"integrity":"sha512-nb8mDzfMdxBDN7ZKx8chWafAdBp5DAAlpWvNyUGe5tcDWd838zpzDN3Rah9cjCqhfOKkrvx40G2SDtP0qiWX/w==","shasum":"ec15d125b590602c8731545c5351ff054ad2d52f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001240.tgz","fileCount":800,"unpackedSize":1352713,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg1r+dCRA9TVsSAnZWagAAFFQP/28veUsgeTvCW2rn/oUk\nniko2+dM+oaw/Dz0LylkuLz67bVUdOCYj0eNTyt9XMB40wO94JHtW+1rreKx\nGqHRzsugbWU3HWNdG4LulOek2V0ORqFVZkPjwSEZSIRgl75sJA7luOKN50Wg\nweoJ6Kw+YVVPxcvHkBIctESUacqI8iT+d8q7yHZ4C+ZT3LY80YzZ79dhnPcD\nHoJF5gR4of6DTknPGcIjR/3KAd0qMCwlY5oy74AAhHpaCEBICMqLenxlImEv\neR+dayglGIConbxh33mw4EGJ21R4pq3LCdVE4jCHZyqjPYTjzCIjaFOpNPHt\njEYkWHzfyVIlgAsSO5W7KQSnS9MG/EUa8RUqFOAF6mctjSbPY8dseaQ9b/MH\nZFZ5SExBT/Zq3KNuhll6S//elbOSLSHowgptaQTREN/RTjAj737RyPE7CB7H\nDz6KfzLEUFiwqqPXE3kSq52ZkcmGH5O0vUmZLw4LRTbFhXXFTdZiduwTUBZO\nNTftxHKXECi/RS5ARr8QmFuG6uWFIdQNwLS/6znO6vPigJJGiT37NIRE4ZVU\n0GNdDiTsPrxFjIIMHc+Mh++PKoCRtGXzLFlz1BTZ9Uu84KXlPq4K8GBAxgG3\nrp3Pf/msuhNMJQW3OoUzI1RIXmmOjtfWKJybyRv+eRXcg7yrTlVK/iOtKRXA\nTy2/\r\n=v2LP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAJRseTJIB7cowFRyPSLfjESz2Prs1jU3t98ACV912hAIhAK6Qzbpv6uXBYRfQb1sVaceQqP35NlGTR5QIQHe53/5f"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001241":{"name":"caniuse-lite","version":"1.0.30001241","dist":{"integrity":"sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ==","shasum":"cd3fae47eb3d7691692b406568d7a3e5b23c7598","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001241.tgz","fileCount":800,"unpackedSize":1354371,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg2qf2CRA9TVsSAnZWagAAe6UP/AjutTS09Zn5U8vMvT1q\nh+1698h8TFbEz3mNlhOBks1OeTCxmFD1cPnJjHuxlW1Gc1WYfdhDPSLLvJNQ\nCNFUE1ksPbwaYyriUn9ipBsEpjmdQyZKArhPUmIvDALXT0z7c6rLRy/YtzEr\nUn8Uu8DQeDVGetO3F28SMeTD2xt2jr5yRT+FzaDsO8XQQ5pyJCFirhqiRgrY\nSwQrTACR5U9Ggb5HWDrDaLW9PVj+LbEcegKU5Ry2rz4sF5d1Q1XZVYMaR+Bt\nnaMP0Venw7KkSx/60sszXJbsIjpeT49bxm0CgvjwvBcGf8kNbWxEGRKdrvuo\nW76BeizZ4QOuCgXAARF6DLfSM98mvfrvOj664w+bIqsMVWIuF52IUvfckLEa\nw1Ck6ojKDCY26sLTbKRCg3cGATMy0eTMrqMrF4YusBWRO9YyoWA4wxcl7Z1s\nUZc7TRGouhWWEm4kqM9cYnziFneS/4tSpThNKQNpV2JUWSMVaMqCTLiNcF0+\n3Uixe/3VRVNrBVXrd42kiV7zDCnCG2Idyo6AXYAXKakC4qLMPmZEG5HedxP6\nPk4sSQrc05urLgm/gIRqq2No37RBPcNhS539EguXJEPGFHxizbkgT1lfHuCd\na97aAUh0PqmYJ0s8Ing6cwfdtwFYVARkJEVrixTUMdMfl2ytok3dsRS5y0uN\nLIrk\r\n=OB3l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTDQ4Qsm9uILdV1xxETGfjZM4GKuNHv0yxIjButxQY9QIgWxw/saSPOpnj0Zv6dy1speJz/xIpGVOW+lnjTBkVuVE="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001242":{"name":"caniuse-lite","version":"1.0.30001242","dist":{"integrity":"sha512-KvNuZ/duufelMB3w2xtf9gEWCSxJwUgoxOx5b6ScLXC4kPc9xsczUVCPrQU26j5kOsHM4pSUL54tAZt5THQKug==","shasum":"04201627abcd60dc89211f22cbe2347306cda46b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001242.tgz","fileCount":800,"unpackedSize":1358566,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4VtyCRA9TVsSAnZWagAAmH8P/Rv/nzea5ooE95D3Aaue\n9RhHHAF66X3b3D7Ite98zGm2/RWVK9FaYyiMt1p8nrsz2tOynlERu8BSNekf\nqKoypUyzvmEdmdv1uUJcJ9zlRPdv00hIEirD7BmyGH9mRMbZc9RNku+q6tOW\nvfPl+/d37clFCi4VNBNDm6KKSciC5VEVip+/xajSQL0rtm13gIGSvQPD+hWC\n7YhHSZFQby5TAaIVI+KftbO24xxS6Kt/HreIK7prhG14/CEmNo3/3Zgdu3Vk\nPT9qhsb7mj7BZOgaKzDrWhkDR8heNdcVD2MhUAqZ4oSeUTNugydHsDDHpbMo\nZrpiMLI7GdMMte0uiMCl4EszrxxE0YgL40A8K6CXnwaB5Hw/05fzPgYkZebb\noE4R1iZaUZdEXaBWNXqIFA0YZLwWzFbNgtmCQNiPIkRsI9npyk4dH9r0PDWr\n+/2XbA0qKebKyTOw7HQHxsc3xPFVDnZaFKeShJRhncvYSzlHiKwd3gudpefG\nF+uf78Q+qcREwuMbcJsZCoEZBtAniy1enSDRb7Gn4rovBYhQtxm8LgsYzH2s\niq7IHCY9S19vQRm2XB8zAY5c3Jnv7ddVVS5nbroiAubfu3rb0yQuxOfaCZ8T\nJG7vuTMq7y0Dmmqui1ZbvtztYE7CqJaCR13LzLo6x8c9TQgRNXORFqlH6Y5d\nP2LV\r\n=OmZl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAV8RoGcQJj9ICEfALW6WiS9POBMsgXjeMJd3Lx1TiO7AiEAyNmeqZC6yi0ccNtIp+r/GNJ2IuG1wdE3LvlwURn0csQ="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001243":{"name":"caniuse-lite","version":"1.0.30001243","dist":{"integrity":"sha512-vNxw9mkTBtkmLFnJRv/2rhs1yufpDfCkBZexG3Y0xdOH2Z/eE/85E4Dl5j1YUN34nZVsSp6vVRFQRrez9wJMRA==","shasum":"d9250155c91e872186671c523f3ae50cfc94a3aa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001243.tgz","fileCount":801,"unpackedSize":1359715,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg5UAICRA9TVsSAnZWagAANY0QAKUCWnbA0GX7bes2k0GF\noMc+wg0Uwx6/Rih9uunX2M5Ij7mGk9R4JqbuCRe1pyLfLzlKrbT5B052Ihk0\nQc/owfhdUNqA7krHNt8P5l4qzMHHaOx0TYQ4De/eqABCevVMvAE0NL932EIf\nzxMM0dk62RRKyl3r4CYYqviWRWcbE7pgfiAQVxIqUHRHLYTohzIF/mhaR5Vm\nLKkhdvr49S1nBxINWMQqgtsIbbp+NjJdtffqjF1VTnrVsiJqZ78XpWlW+/hn\nK/OPcjcCokzNNB3bzxCJitume63bJkcu3jN+l6lTurNJTKe0fIAjXZ2JXsrS\nc3gdLIDm5mose9b72RnMI1cffBSe7rDHIiKKYulaZ63I5Wuz3NpgAHiqvr4e\ndLNFcJcIKcQjH3DJ5zaau63QMbbNxwweCAbhMb5PtXXekJe4IQ51ggetAnL5\nlXvDKNbV7+C8tbJOhrBTp3TNM/H3XkVn91I1L0+6Yb+0JvkMvHQpLDKK+BFG\nv+yZ9z/tYytRLnNGKKnuDSKLvB50LztFVGbRk5oEFwGyMZfv3Mn0eMUTUN5T\nlJnwa4W5ZWAqUWAe5yTBZdPAg1BLFr6z0MXOGxCa4E3Y4L4GhROPbmEjhF+1\ncJFio8CFisrMq7n48oOje1B4ybmQCYwzvMmtVYYBjEC+fstyh4jXYtuQX7D4\nWhBs\r\n=JZG7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDu/yjb8IUUEN1+IeTqODrCwRwBs0UwGJJ3UpoCMN3sNAIgWo71WsBKU2kC5zQkCs1v2XWu3j9fhAt6PR3uPSMtq+I="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001244":{"name":"caniuse-lite","version":"1.0.30001244","dist":{"integrity":"sha512-Wb4UFZPkPoJoKKVfELPWytRzpemjP/s0pe22NriANru1NoI+5bGNxzKtk7edYL8rmCWTfQO8eRiF0pn1Dqzx7Q==","shasum":"a6dc49ad5fa02d81d04373ec3f5ceabc3da06abf","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001244.tgz","fileCount":801,"unpackedSize":1359715,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg7SkbCRA9TVsSAnZWagAATA8P/ig420Rj8QphMhXXa4Ag\nX21Yqn8X2ONe+z9UBm/SOn3bG8TqpTcKazV7pBBCLRrxUCKOCMzmMlyzDjTB\nJbB+a5AV/wMpSyEv9TW1dH7omzoZf7z0nfeB44qSiO9sPGdX1ZP2Vmage4mN\nWk9VBcu0Xk/MGLfwE6XxEF/mYqEWFpSC8mxpkCXBayPuUnbav0RRVaXyWTgH\n+24WM5+gUv0Nf6Ex2EXSUC8bO0kmrSV0LSgPd7pEh+DUQLNUKAXy4tmURI5O\nFg9+NrmmWR95iWFIENZ/D8ddCF8vgzj7R8au9RgVRxGPtC7bdmJGd9XspjnD\nwtrvxqkOZaDYpLpTWxrnPPb2BrXK4kwNKmzuYgimOVfuVW0ZxUOv9ZV/9T4R\nQ+7j9aqMEG3pCEYx3WTEu+MEpuJY5nVRHdEtTCeZ1OrFcudW7Tm1O7Mv/JWP\nAWacSVIRP4x6T9HH32f49zIBjin0NW/z+9ZFHLFPIkiWny7hfQzJ8UpsOhZy\naJnNMFSgfw7au0zRzhgtDsL3Pipy9Rw57zadrjq8C0uHQ5NjkVfvTu9V9ZBS\nf1WqR+b3aatc/jVxLGcOQOX8HcSdBlaVsWG+7WJdNSIKKxDAQgRcabYFe6aV\nJt7a8kmeX7oEglBgIrOl4Na6PWfPxGgr/OPFb6INBAGZ1cWqXuJ7k5g3x2d7\nG7z2\r\n=qmHS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIElRdlnF40l7BEjyKkWImmjNqwQcCPi7lbydYLG2kDa5AiB/NN5a82tIB1UN+cP9us1UV5DFEiDG3s/kCa4HgOqfxQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001245":{"name":"caniuse-lite","version":"1.0.30001245","dist":{"integrity":"sha512-768fM9j1PKXpOCKws6eTo3RHmvTUsG9UrpT4WoREFeZgJBTi4/X9g565azS/rVUGtqb8nt7FjLeF5u4kukERnA==","shasum":"45b941bbd833cb0fa53861ff2bae746b3c6ca5d4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001245.tgz","fileCount":801,"unpackedSize":1361425,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg7m5zCRA9TVsSAnZWagAANUMP/j+vFYue4QfZu5k3Wip8\nbR6UQl6q5cYPlO9PqeoABz4+V8rXlgl2tCQQekzdsVFVNySqC34uCXyKFDz6\nWdEvRWhiKrRSsR2aCDto6c+mtfIItxej7bPHrOlKIxj0r3czyXMTMTyaoFXX\nc2BUV1sb8fpmnI+dWrdf7kGV0Tv4f97SnuUgkxeeIBAQiAZ1vQykoXFgOV+Y\nhF6cYX1EjVO3hvnRIMY8iOywlTMJ5mJh3kHW/7JP3mhcm3w4gD1cT3UGfCoV\nraC2DegCZjv936xv2jfEdbxTw9B4SPjTjyStFUANbzd+9/q7N2Er8zcw9Lcj\nVrFElXOk8G7HIAXkZ+U+FgpIwOh2pyjlQSzqulsxUZf5aiUdcW/f/XaNHaRu\nFA77jVmaO6DD8oEn6d+TF/qnLON4eaEZYvMR0d7D607DalpCvmIFnjbIaw0i\nX1LJtED1IVB2M4L6kORGrQcStTDrF/Qa8XzeQuQxvjIjBrtoqfd6gEgacymG\ndofl5IklNhIwE07QXb23PqWWKbzNfRqJiW/1FKAk50aqfvN2PqZPFvG+Wj9p\n1qqxHw13H8b7eviQkGoLlEyzKUcvMdqA8fZizUAH7PyCk6QMn/b6Moxj/F7a\nM/UHr+XOcA6WU2AVpUJh1j+Z/NoBByhMvAGFMVy7KzrzgmU/evi7drBsTzTa\nYD+1\r\n=nRTF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlXJx61IG7A0UpL8hY1+Jj4Mo90qR/HCX5LkfgGsk9HwIgRI6ORMJaFKJNR0EFBcnHvCT5XEoEOv7jgp4KzQhKOD8="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001246":{"name":"caniuse-lite","version":"1.0.30001246","dist":{"integrity":"sha512-Tc+ff0Co/nFNbLOrziBXmMVtpt9S2c2Y+Z9Nk9Khj09J+0zR9ejvIW5qkZAErCbOrVODCx/MN+GpB5FNBs5GFA==","shasum":"fe17d9919f87124d6bb416ef7b325356d69dc76c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001246.tgz","fileCount":801,"unpackedSize":1363088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg97UXCRA9TVsSAnZWagAAHucQAKSksdEXJdGkJcgmJ5c5\nL/OGUThSU1bQrlNfAL5e6pcdIiVj6ZNJO5IM2KzG465wwjh7QjwDR9pcNK3F\nX0KTw0dxcnEz3R58OBlyEdiH3BPRMYme5im1+Bs+05uG7Ws7vjgjm5IH0mBF\njl7EWW8Kz//k+bbhsyJ0GovxpXbXdxMMCPoqzFxK/exUCxLEbuIQ1bbQB65m\nuaUNg0aHFc8Qkx9IXoabm9P8SA4wZChYuBRc1DJF9gs+qHwIe6VRzCIw5s/h\nHjHGwVl/jtpL1ZMu0GEO+TmIAzQW3GBYbsZKPTGBJBODbbWriJTgyYJnyx+f\nauvaQAe5oqnD04oIZuo09wJWfYCsioSNVx6XUIuNNSEEz2Wx27Cc3VlWcTuC\nGZrgNnJNjpi6ybupPF262oH4/SmgELAA7CTPmNnVvtCK6mVxSz7K1vzbJ6e0\nD0XLIIR/Xv0uF5BVddDI6soM/nzAchlEOcVwGBNq3Op1ayrZ+BnfjwtV6mZO\nRJRNVJRe9cld+/gI1Xu3XyQssq8eC/Z4t/4w5C8s75Xec/cGB3xpDmvvAt+x\nbAcszw96QKBnMEJngThYUvcI4mRMc2TZ7hv7ujZiU25/fMyY2jvgGTXcX3Vj\n0NGDZd5nPyL9EtT2MvKf7PJjsVLt9+ItNeZdRptdOLk8rzRFYg6xfZ17nUso\nM2HG\r\n=+Tab\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAhzWjPrMde4lSEwUAlUEdSouZJdSK7QHSZVyaSfMFOlAiEAtopdDtAMWMc70zMVdE7yzMA/x7YOU6aXGCu8PYnclic="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001247":{"name":"caniuse-lite","version":"1.0.30001247","dist":{"integrity":"sha512-4rS7co+7+AoOSPRPOPUt5/GdaqZc0EsUpWk66ofE3HJTAajUK2Ss2VwoNzVN69ghg8lYYlh0an0Iy4LIHHo9UQ==","shasum":"105be7a8fb30cdd303275e769a9dfb87d4b3577a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001247.tgz","fileCount":801,"unpackedSize":1364798,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg+6mNCRA9TVsSAnZWagAA98UP/jrwKl7/FaAW/IWWR5M3\nJBzbAWxPElW2U6jGq5t/56gS8SbI1VsYEX20SSSidBof+Q+nA7PQRgQMsUPo\nfSJvpFT50HvXW5SEhOEpn5r4ahF/LrrHNi1dohIL4okBb/cwqEclMs7wZznR\nshbeJMGYdf8oxjgWpK2BBK3+hqJimMF/kjkyWIyiky3nvGkBg9s+Hhx8gh+B\nt7HRE3hocbpocmYkUNkgrrg/zgRvP/6rOT+Te1lbybvsBm/uwtwMJfJt6Zrr\naORvJANzl+OpUGI9M2tt8bjByk+ACJA6XtbTrdTeVjAlQO/jx7FQZpujgayj\nUfQlVLdviVB2gk5nAb98cDMBaaASN0AaSj8s3QthRQHM4GjVbNh9CxTa16Fb\nCBZMdtSQ6XYlg39mJ3JD8NUUj/iJmzlX3eWRCBmO8nxGhFa90SLndPcmfHF1\nzShO3OamdHTqQxGC3fssAfTlqs3meD0j/ppmtxDHcA+MxFXBiLqzu8jF2XL5\npKmjrErGvG8oCZdTYz2OKlCOoEGGwBqaV0s2DdCbcG10R4l7+Hv8+RBRv9tf\nVBaHw+6QkaV0gxazwJl/4JJ8vjREVXN4l+GOFdBn+46vScM8ywRUUpDP55YY\nXJOmWxwUf3qm8zFqmgbWrv/ywHnySWICxZi4bAqy3QGvi1+uuUyC92PiSckD\npupR\r\n=l66n\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBj0O+GtiC7qD5C2/F2/s2zdUU4Y1QpVVQ90GmHtswCpAiB5Rd/mfGp9san8zHguGPcX3OUrCtH2ZTLeaXpx2IOiWg=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001248":{"name":"caniuse-lite","version":"1.0.30001248","dist":{"integrity":"sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==","shasum":"26ab45e340f155ea5da2920dadb76a533cb8ebce","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001248.tgz","fileCount":801,"unpackedSize":1365014,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhAP/nCRA9TVsSAnZWagAAl6UP/2uSIeD0ppuOmUqtHHU4\nfrSqfm3hf5cxIBEabzTXvLqlbUrtcJ0P4W6dJhjz6PduPCNoXFUf/d2/EEwd\nfwHSjcjGSNr1TtK480WnuNKzOEMIC3+3UuYlfC4q1DRpojGFb4vGpIIBxgZN\n8CGNmJZVp8sN/SP5i2sarsdY5efD5PxlNGQEUhHB0jlx5AwGCYqRmDmsIsMt\n3tFkLyTXg++le2j1yEW0S1/pFynae1+iQsOoIIyNmfis8D+UZM0wZEF47bLT\nj6ms+x2DhAYcmM44k5JxRf2oxmliQwxcGahxp9UUSuGNc698tRBPEjVYHe4+\ntabAloLZ41PpF15LuIAgc/1RoZSbf5VMpz1Nz3Wf80dZnnfuty4ileSuBY+d\n9/9eeCM/hdsaP8ers33daACDG61fexsuSuPwKuBmTqJvHJBRctGOeyA2sf80\noJES9NaKat55EDMqdrBMPXbPzIDFBqSdCcJAUmRyNsE3zN9mK8dHt23eZuH7\nji8g2ijyltuoqPi+ZXb06qXhsEdJ2HOYa2cohxkIxcfLmRTPPRkd+iOBvr3Z\nLNEJqMceeWTL9+fOizti/Xjs06Av+E/wW+BhkSRgiz7R8Hgf0vruOgbmoZ9e\n5wNVRbX+4bIUnv0UWaIh0XdhGe68q4etcP0IlgoJNDSYzvX194G5LpkxzRMs\nqYLz\r\n=9yGk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBgZEgFSlloWR05O+fc6TC0RkDjoBGkmKusVfIA/VZs4AiEA9gt7xi8KieKuLNt6Yn/z+YZiRmEveMGgIWQOWQkLrSw="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001249":{"name":"caniuse-lite","version":"1.0.30001249","dist":{"integrity":"sha512-vcX4U8lwVXPdqzPWi6cAJ3FnQaqXbBqy/GZseKNQzRj37J7qZdGcBtxq/QLFNLLlfsoXLUdHw8Iwenri86Tagw==","shasum":"90a330057f8ff75bfe97a94d047d5e14fabb2ee8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001249.tgz","fileCount":801,"unpackedSize":1367865,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhC1HrCRA9TVsSAnZWagAAXvYP/2pIT8fPiXQbp9o6sTmh\nU331Io4LBj8ILNm2ul1py7ZX9k16KTDIe9TuG25uc6vzf7Mc0Neg7feLwfIM\n9bh9TWO3dRGgsrk24JsO+xVTJi0s+NSmsGDm4saxfrKT01iFEqhmX0gePrlD\nP9s0T6e1Rh7vSaYH+L2nfl6osrWIVE+COMsF34paeNIl4gYEKWeDfU328xcq\n03X4qWOqarmkRHwSfhA/uWJPAFBH4geOAXsPmP4ovzPBGnDxnaldfRaKnVat\nwnyNmipmDEM9mxj/0ikGyy9OCaOZB0fxVzBKWKsGB3lUTJv1Zg1DhubAyoZF\nxil1JRLAoQPKpyvGO38sRLgsZz9tLM43o96jAI3UW6gioqVykHid5HZT1sBJ\nRADGEUb6oLszH4/Sq3r18imfbT8UNTDjzU4EbhSU34yVxgNEJjKX9QuGzb2p\ng1ppXviyjpS8V3PfcVmjlpyhHclHRqSYzNT9uXVgQeemj688VXvbHhF/rSkj\nKI1FXoQ7DYgy9Q+QBXAbQ+Ww+EeJSzuxUHscGLLuYk5l+o6CNpp2p19RfDNv\nf5sFMxQxjECagw5lEfd5Pek3l7WkPxrWF+OnQJ5YN2/MGZLniim+AAG8K6XT\npAV2kNCLpER1f04DSvb1s9yZ/gslv71xGFCQ9A2JRXhsKRENvhtEcawMjxxs\nqZqI\r\n=5Nni\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC282boYCWh+nO4pM3EVuJwWw5Y8mbiLyeLDUEKW28fiwIhAP9S6anLl6Qho78I3iH0lesI2qPm9pUnpHLAf08JLIMk"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001250":{"name":"caniuse-lite","version":"1.0.30001250","dist":{"integrity":"sha512-98wdsAAUhKX0YquKnbpIcJScvv0dEgWZeflZ07ah2PnhwgMGvKi4yaxQ+CM0XUT9bqzMB9RrwoHWhmkOZSM/og==","shasum":"7719197e30f567bc9deb9988c358ed0ab68bf158","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001250.tgz","fileCount":801,"unpackedSize":1367816,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhFJosCRA9TVsSAnZWagAAv9UP/jvg0J/fzur/5sz/NCvK\n1sd26Of7BG3/+DSv14CHCWMnDZBFBjfVr/74CdODJG1DErYNoVMlQYYMdEVn\nUfKP6GYWl7ZMa7UERGZ30Xeq3ks73aRR2cTzD0JhPFnNs70PwyzdNitL0f3x\ntcJ00l1/B7yLIzguE0UMhVWspn01AtMjdRSZ2Odkp4BWr9dv91gOQZkPCa43\nCdzi4Zg+QKK+V4Rykobzyp/T7c27VoK1YKAzL+s6e2BqiKt2XiM+hT06IPQ9\nG5nyjhXuWDvQChT3RmG4fyO4Qz5g6JjZOc1oVlixILqzThsnEjsFxSxcYoZ1\ny8OAacsw7lN1UsXVhtgYoONDA6x+xEDV3cj/q+5yOjeu4vO6NuQfOFcx5vkT\nfWWodJJ/BjZvTAvY5+lpcekvePoFaxkTN753ifI7R5umvyZP44BHd7Q5EfDw\ns/hoPqxTm1LUZK08qb4XE2iFkVcfr4CVec73+b+UNILjWrNCaCnWK22dtUVI\ndNobh2+CuSEA3GKv+UWhkidakXItRIzahkjvWqMVwtwHhhMOJmksMWd08Tf4\nGzLcp+PX5nvHpUUyPs5Ck9+zuqqZdaC/kTywtdyB4YXnlB0lbGjAurGJNKyg\nRu4a83HNoa/88aaowzNTzOtiJaCJJvOPOCkrx/ycZuJjkQxfvGWzUQjzVun0\nodA/\r\n=y8L5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDnLtkW4n5f8/J/VKAsiQPXWn/3rtJtQMaeKkx0uF/YlAiEAuMYuM3871+5J6zIEA2e5F95UJMu+4aL4730pmCwzVqM="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001251":{"name":"caniuse-lite","version":"1.0.30001251","dist":{"integrity":"sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==","shasum":"6853a606ec50893115db660f82c094d18f096d85","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001251.tgz","fileCount":801,"unpackedSize":1371179,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhFKnlCRA9TVsSAnZWagAAY5gQAIHeGltny/i9XXvfzOnl\nuJHlKHR/CYiMjVNTNSVEvqnCOhbdMUDTrGM+kO9fhPTPuNP32WNzsV5lfbUV\nSm023U5ZzcmYqpXHkVxdVWIc1MBpHEWGsRspSY0eYW22xTHjxSB/nosb4bo6\nBtQcYM8lGZ5NiT+999iW74Nne2xYUPC8FOE2e7OXI+n6TTil5BdkKk+FkFvP\nvHxdAcsfkYyabTTN2m6Lffvy39WymVtvsm5xjTQW9z6JmdieJQtoeONzcM/8\n2ZV83ofWCWWm3dp3S7KQKPMSKMICZ/wSTuTWUoGQeyjoWHvncBKHq7KnP7fQ\n2g9xqb9j3Lfyb0H1yfOz2RJMNNu7T+pmB+dbmkRAePMeJ8t+sINw/Q3n7U5P\nmo3mtYa3caWzZf7XJhWX3pA0cD1YbVZjghDhAV1QIZW8wMWjrU+SiUlJY5Tv\nZv2QQkDduo0FjFA1UGnQBhVmGSkdNai9W2UTstGnGKlo8uuBJrZsBxYsTUvq\nSR/krKClDv7xG4Do48NwLhYuLQOuSztaKdpZpEgeB6jCZ657K6AUGor9vKd3\n9JBp1FdU6k9VBJIRS2EVaVbAEGcoiHwQOKvHcpzbVxJ0JbSMGyQr3P0ZFCdY\naEg25D5CVsU5sBCgNisTJ/U/jKtq1UvfB95ZCKauM1NqngD9RDxpi1kgBHo4\nKrct\r\n=2Dgs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZ95uvmVSZ0zPXqz0vYYDj1I4GVOUqQthQPszF2wB2WgIgWJSa4kSzyf26tMc2lbFG6Qxd37pstY6mIDDG91geTGM="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001252":{"name":"caniuse-lite","version":"1.0.30001252","dist":{"integrity":"sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==","shasum":"cb16e4e3dafe948fc4a9bb3307aea054b912019a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001252.tgz","fileCount":801,"unpackedSize":1371179,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJysuCRA9TVsSAnZWagAAnmwP/3UneSxj4jiGSI4ossY1\np7GNGixUI8unb/IJ0ppj47frd9l0UbN8bvECWSqGK6KDdVU7xt7gkXwi/n0i\nW2PKLAyiRM4uNa4DrxDHMWu0aQT1YYPv3brYMlg1Mt9DGvCgfK1EO7N4tV6D\naEegPjMQ32QgNYl4rPPw8Gj5IGYLed2pe3mDGrrRRbeWpx49Ern7j0fngOqT\nULEmU5XUvarjDnmLu4gIWhpA4aAwXCMhXYYElqnmL6/fqYKTrGvVdg+niVKQ\nVUi8Vv+HMPVHHwJZZdt3iZEc/aSvRe1CKcImaKaCDvqoT7SOCt7gshsKoyC3\nbtk+1qgSHrxkDPgkedJadeF65kPBI6RS9WJUTSvN7GPQ98PSkkddOm1cKOlA\nBcZpBRt2vqpRmOsIQGH4prBEym2QAThy/d/ZQk2bF+yd73bQSXmTlZu5q9kb\nld11B/SaZ3eLf+ZJrlIzZtEny9wFC9k9/sCYMWNp6RsDfrh0LvLo9gTYXpSI\nmu39XBoj3X4l8xigkCIx1Ng0nH7e235g0AAFJy8v6Hg7H1O/bVzq0Z9frPiH\nX+/KMhll+4E1F/1XVkGXM13UzydrWslnXIQeSyp598KevtqB3eyav0sa6YNP\ngTxzm4tVWaU+JukuZboaPkz7SpRFTG2XUxjtA31q64sKkgsEDRaqzR3Fr6bQ\niFEA\r\n=bz6v\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEwI4gH8jv/watyPaPeHoQn9wXLfSSyriNE1oL+zdHpwAiBZGxFPKLmwp4DWHTB4g9TObiRwON4Eql5MV1LYsCa50A=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001254":{"name":"caniuse-lite","version":"1.0.30001254","dist":{"integrity":"sha512-GxeHOvR0LFMYPmFGA+NiTOt9uwYDxB3h154tW2yBYwfz2EMX3i1IBgr6gmJGfU0K8KQsqPa5XqLD8zVdP5lUzA==","shasum":"974d45e8b7f6e3b63d4b1435e97752717612d4b9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001254.tgz","fileCount":801,"unpackedSize":1518447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhMyStCRA9TVsSAnZWagAAyZ8P/2ywaN5+SE5AAv+AHSgw\niEsoH9/0vYv2M0aqsTgMFfAKtzj+mD7HvHFGofvoa8BKAAoyKQOTJDed7tfF\nhe0lcbE5llvbp1P4ts0QmHg+4++A+8A7elmSy2osXWpp5oDXX3Orp7/G+w61\nQxGzdOybU+/QSFvVGuvOP9imtn2/hMx1KT7g6xWNZAhVYxuUuFytnEWd9M6i\noK2b/XpJsq/YSm36mpdjq63KNTbH2YpwMniXJrh9VIpApzG8hxz0+nlHeHUN\ncTw2fa/I8K0UpBelKtRojN5/lB/Xru3Eg7xLIeutGlKUwUZICJNS7xbXpSiH\n2tCD0D0NrSa0fvqA/QTPu2Sl3HmPbib6MBE7Wjt0dlIyszHooKd10Tk95Ncx\nrZKvKKgFZAqmY18oq42G9hHvJOXJi61/ABzA+UvgUMATd9arwOEYREoRAn8F\nyyqVLktzPFJRs4Kh1TS/18cStkviBRfVxtuAT7/pGNF0KBrxbeZJrr9Yu6N8\ndvY2CtM8eSQcEk2EZLO24YDyYH/OZD13G4E/bXW1hEO+Pnq84Qv49VZMcLql\nd/eYJ77Rp5+/GZxxxbK/V5Pc9hjb8QBbPqnv8/COW+e2LYzQYwhnaz8SL75f\nG2jE+0FVUtDcTwTWh/nzsgdnV0S+V+7l5aq9uB3nywjb20mPdIP+syxwcdui\niEb/\r\n=V0jj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFrOT55v6NWd+JJGRsi195CEnY+DyGr59FoQpwzobTgMAiEA/9zU39DKDI6URdjBfzgbAPZo/oGO+KX17XQ7TBb0NuY="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001255":{"name":"caniuse-lite","version":"1.0.30001255","dist":{"integrity":"sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==","shasum":"f3b09b59ab52e39e751a569523618f47c4298ca0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001255.tgz","fileCount":801,"unpackedSize":1518447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhNXMqCRA9TVsSAnZWagAAAU0QAJETb2NUPmrWEeY3k1c4\nJzNzn6/V3VFRjuZ8La5REJ+vQPbnl9vxWdQ0QwX6yI8Gtp5ZvbMKsjkT/fjF\nFX61eafNNE5aomxnes+zFSo+i4Im14b0yVK1DlzCrbFzlZcdwJThGmMh2/Ha\nLtj597hw0EWz2IfySzWPXOrdyuFidLpomvukjN36ATDHkDRAG62q3l/8MzSN\nPc3mgRBtwZCRx+z9ow9roNn3cymDEKZttW/Q4Hb4XzNv41QqUmXmgGECYF7J\nObc4yK+SWmSllBGTMcUMiw+LrFd0/POUvI+KOc3al53fpxrsX8iGZ/fNMjL9\n6usPHD7fAT3IOAvLBf0ol/L/D6NVc54I8Wqyy7NBnS97aq1XnFiHZi0QdEkI\nn8isLrpzJyyAo348tgoKIVt4tXCh0xn/dFzBrWpi39MT6nUFG2vbTyr9G5Xw\nMaFrSdBOwWk43ifqTpbtaI2MPaYB4W+lzcTHgyfvTOBtigobTguR1Krsk0v4\nKC7PIJQOnn+MmCJviUitmh0P/5EuMYrYnUCXLzv9ivUgFtl7jCj5laqHOW5n\nf62WFOKoLlB/m87acbOpR2FCIcz9i2LQKiUZFaQvqwggpOMfg5MM+rS5CHkI\npApp+EzlJHHfHDrECCu6DULzhUbowh4B31/9z7SKPXIxUWR2ETwhu6NhxHth\nW4Wz\r\n=BOY+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHkG9iGYqXCCRlHzMgpP9yfUIfZwOGn1WR7pCd14TCvEAiEAqKHDkH8PBRaGQBkVYrxYSBrneOKav8LF6FJRCkK3Jgc="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001256":{"name":"caniuse-lite","version":"1.0.30001256","dist":{"integrity":"sha512-QirrvMLmB4txNnxiaG/xbm6FSzv9LqOZ3Jp9VtCYb3oPIfCHpr/oGn38pFq0udwlkctvXQgPthaXqJ76DaYGnA==","shasum":"182410b5f024e0ab99c72ec648f234a9986bd548","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001256.tgz","fileCount":801,"unpackedSize":1520163,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhO2GuCRA9TVsSAnZWagAAOPsP/2Iq+T3jXsitr4npuVpS\nnD07apHSOQtW3ND+WXbXr2kYX7PEtnaBL8NoaOkj4zSNZmmGu17fa7O/cVXE\nlFpa80qjDLHKY7U8nTEo9Dm1adIXAKykov2WFWOkm7GH1Jjhdfmueg8SemRM\nW+gc5hvAaGS9VuBl5kSi6zAl5grwHeJnVMlMXlHtOLsgoaoQBDu0gSDRWIs3\nfGlxxH6pEM4IKPyBLaB8j2yc9zO6Jvn60zJwqwtajskv8lx+wqMa5AukrsWt\n75n98mFTGeH72MtRCLA2WYMb3Eoaf8XDa6p0nrgs7rts1KRqZWQtvcJyOUog\nz4u8hUJl32Ywcno4eg7eg25sL6HDZ+e6PQS6P+EQVDM47F+DwyrKuLnjaomZ\ns0ayuAr+8E8D9KPKQB1dX+N4a/8WhKM4WoKafwnYt3tXSqHMBDGU54f+CZwx\ngtTZJFqdip23elgAWp6CVYmHX6TIrUVhn2Cue5zezIAswQwuhveDZGlvCCEI\nYc2wVrqH4C2mfKFE1tBUodwDhy4/QsoFN7ZEW+Pj/GzF8IM7AVX7+UZkkcp4\nGYOIYK54jhm5F3D3VqdOGXLkNERQ81hmFnMjW4+QaOzwbicpPyUXI1bvApRP\nIVs0zINOobDIomzRjACtrDg+HQj+W69ONPMJiHCTT9kPrkYimQ+VoM3tEVSf\nAbXA\r\n=kCFQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFVMe1QQI4uzU0opRG0ic1gk89u2kuO6XVNyw73qEzVAAiBC8zFqXZVAEWZVt2XP7Jiel58Gib9K786YGJ/yOcKrDQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001257":{"name":"caniuse-lite","version":"1.0.30001257","dist":{"integrity":"sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==","shasum":"150aaf649a48bee531104cfeda57f92ce587f6e5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001257.tgz","fileCount":804,"unpackedSize":1523757,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhPuYjCRA9TVsSAnZWagAAXywP/RlBHACsCxWyJL/RWX9b\nigSA04Vkkmn11WsGbgxLOgHcsc0NumsAIaFDUPNdyfeljs5w16hqds7VA89x\np2171SPupUk3oOQnAJCYdaJUfiELBeDwrqaWEQZjzpJceL+Xdtn2z9cUpMiV\ncj3PitU+r+kIxedq6wXEul5Fl8hRiI3hjP7uiBiWBDk0bRakmkBeikIlCZ4M\nCBBDNclAYVNlsD2IMmgsSUWCvm7pSZDlbedinh2QQNuwoAlQSNAUQeGxOU+E\nBioBkACsT2SfBced3V135sxdGDAn6taaYxWPvSfON86d6Ad6NPoGhSoeTH+e\n54c7sjl3XlM3eC4ErNPaTvZ6nDCg4Oqhrkvdb/sJ6eoPaSuhVL8IKxEN9ArE\nrE7HUMDSbvrPKsa5cdC6PO9lx02jPWXHhf8VXcGLcMrg1sfMIarSm0LXjRY9\nwQnKpL9g2rwUH3idMwCKi7fFVlvY6ff+B3s7sktyelJ9GKW+jsRz9dz4b4kU\nSqtwVlD2srvX+kKSVUtBPvHhSHdG5016aaobZFt64dBaIZVSZT83YOme8A4z\nuSfuyontwUbxxPcL9UyE+dYkKuM51iX3RaqIK5/fl6euf5Dm6jfhKeohi1Co\nSmnaFy19Gl645B/MWtJW6EGBnGbkjT5pJlCwRHvS0WDLcdsuKSfKXyf1TPoa\nGlqp\r\n=HUEA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDn4awwsJL1uHIgAn0Oiryk877QxpgECX9pgV61/S1MrgIgOKV6sq5YhZlF0PSrV4XqeP/zX7ZWEd0j21p9vzt6gA4="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001258":{"name":"caniuse-lite","version":"1.0.30001258","dist":{"integrity":"sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA==","shasum":"b604eed80cc54a578e4bf5a02ae3ed49f869d252","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001258.tgz","fileCount":805,"unpackedSize":1524990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhRCwkCRA9TVsSAnZWagAAbuMP/0Cl+PnNcmQnCVtZVGWa\nhjkTC/qhPJ7uvubbT+1ApwWJGQMLwG3Jvjl9i7iD/yGA/z9k9paQO8P/Fznk\nFG3ji+p7XrVjCMky4kMBv0DfyA/y7JirZRybx8+gbD5zpoyjgk2+Ro94kdQl\nodRixRC42J36M7WiSl+ReKpjh7Al8R2789Eyx8F89Vvb3n/Vb+HwWu/uhyt0\naLchhZ7wwXmfiVY8EoBgCSipJhJgoDF9s2fPMZ4km0hwnmk+xCo6ZF/uP+pF\nmQKOTWwa7k1I0twtOdqGz5Ahwyh9ktdAcV6+SPb7vYkedXsYPqFZAAwAPzS2\n+bTS9uvF1ctUYPtutBKitDDk1pUXz83Ikq2W+fWtboL2MeUFDmk+wew6T6sG\nLU+qEYtwcRzpqxHX3FkEKunvftLmrRXMIpmkNrC9pgvs9hQWCA62A4kBT4fP\n8YfyEjbwzrqASkfpAD91Q73HmWijY1Hkuac/Q5vCXq2RwjivUJRCBjajlJUn\nHuI1F2zp/HSs6wzQYDGaVFuX+68+vl5ZtleiuJisoLhs9ltKzXwbqRXSSxY8\nAm28LAc/JaQo/CB2Fnf8ZP7sFC8PX0he/BqWYRoghpXqYQ9sqtmqD2ajOTcG\nkE3baUvvDoi/GUaPdwgCWcDs2/k/WYhaDziSnK743xIY1F0HPzT3uoXWcUwl\nMNlP\r\n=FBUc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG518+Z0lDq/Zdmmm51eQSUDtXxPs7j2MopWuXMEmUaHAiARzenPEgll+m6+yeLDwXPLAW618UrkQsZrhGR/cZiF9w=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001259":{"name":"caniuse-lite","version":"1.0.30001259","dist":{"integrity":"sha512-V7mQTFhjITxuk9zBpI6nYsiTXhcPe05l+364nZjK7MFK/E7ibvYBSAXr4YcA6oPR8j3ZLM/LN+lUqUVAQEUZFg==","shasum":"ae21691d3da9c4be6144403ac40f71d9f6efd790","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001259.tgz","fileCount":805,"unpackedSize":1527258,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICwMsPkgIMb67AIoaMnlLBkGa37t+CBW3K+wk1Gj/JabAiAPF5DS/UySuz95oW9Bwt2PrQk17/wtzGTvBjlRvkiHVw=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001260":{"name":"caniuse-lite","version":"1.0.30001260","dependencies":{"nanocolors":"^0.1.0"},"dist":{"integrity":"sha512-Fhjc/k8725ItmrvW5QomzxLeojewxvqiYCKeFcfFEhut28IVLdpHU19dneOmltZQIE5HNbawj1HYD+1f2bM1Dg==","shasum":"e3be3f34ddad735ca4a2736fa9e768ef34316270","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001260.tgz","fileCount":805,"unpackedSize":1528994,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCDWPUUUOCONxXsJ02iRohWU7bwrmruruQiA7YHdfZuzwIgIqMIOqQogRBbO2T1xrEM56KG3MHzbMGwVQd2PgEDe8I="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001261":{"name":"caniuse-lite","version":"1.0.30001261","dist":{"integrity":"sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA==","shasum":"96d89813c076ea061209a4e040d8dcf0c66a1d01","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001261.tgz","fileCount":805,"unpackedSize":1530617,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChDt+FOETSRAjwn3Pag6jqz2Zlm50yxgPLpxuo/ltI/gIgeIYuHb4z03Fmw7dZ6ygjctIccgfGrm4uSr+CtROhyEA="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001263":{"name":"caniuse-lite","version":"1.0.30001263","dist":{"integrity":"sha512-doiV5dft6yzWO1WwU19kt8Qz8R0/8DgEziz6/9n2FxUasteZNwNNYSmJO3GLBH8lCVE73AB1RPDPAeYbcO5Cvw==","shasum":"7ce7a6fb482a137585cbc908aaf38e90c53a16a4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001263.tgz","fileCount":805,"unpackedSize":1532351,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWSlS81DUC5IeeHtImG/Biagj7+yXogESDxYLWgDwDRgIgA5gnFph/b1C847gqQy3dkPd03X4vdRbB1kriKVdQ5k8="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001264":{"name":"caniuse-lite","version":"1.0.30001264","dist":{"integrity":"sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA==","shasum":"88f625a60efb6724c7c62ac698bc8dbd9757e55b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001264.tgz","fileCount":805,"unpackedSize":1411650,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3U59IVoWMjlj4/941pTN1t2p+nne/0c0V0jkOU1bz4wIhAMbHL5obMOOKSFeFMZ1ddtsT3m8HhjJL1WRQUuo/iHw3"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001265":{"name":"caniuse-lite","version":"1.0.30001265","dist":{"integrity":"sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==","shasum":"0613c9e6c922e422792e6fcefdf9a3afeee4f8c3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001265.tgz","fileCount":805,"unpackedSize":1414486,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwPrtkI6D/zpD/UtWDxkxrJtxcq5lKAlDNwYcvCavXLAIhANgA4PJ4z298E1PrswZyNonAxSgj85zxX0IIAox5ROHc"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001267":{"name":"caniuse-lite","version":"1.0.30001267","dist":{"integrity":"sha512-r1mjTzAuJ9W8cPBGbbus8E0SKcUP7gn03R14Wk8FlAlqhH9hroy9nLqmpuXlfKEw/oILW+FGz47ipXV2O7x8lg==","shasum":"b1cf2937175afc0570e4615fc2d2f9069fa0ed30","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001267.tgz","fileCount":805,"unpackedSize":1414494,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDK3ZkPe09MTrDgXKoje3ZWVDSC9lWnyiinzi2RLeTHLAiEA2eHlEoTSWgOr7zYmiQV2tffoOmz9f+5TD1RrhBCMBHY="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001269":{"name":"caniuse-lite","version":"1.0.30001269","dist":{"integrity":"sha512-UOy8okEVs48MyHYgV+RdW1Oiudl1H6KolybD6ZquD0VcrPSgj25omXO1S7rDydjpqaISCwA8Pyx+jUQKZwWO5w==","shasum":"3a71bee03df627364418f9fd31adfc7aa1cc2d56","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001269.tgz","fileCount":805,"unpackedSize":1414494,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRX13pskMk46OzQjMwYvrNVlfUXUkULlYuJqv/skZVdwIhAMqbR4vidN/OPhSvdhjZ0DOGqFNYcuyTnj/KS5sxe3G+"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001270":{"name":"caniuse-lite","version":"1.0.30001270","dist":{"integrity":"sha512-TcIC7AyNWXhcOmv2KftOl1ShFAaHQYcB/EPL/hEyMrcS7ZX0/DvV1aoy6BzV0+16wTpoAyTMGDNAJfSqS/rz7A==","shasum":"cc9c37a4ec5c1a8d616fc7bace902bb053b0cdea","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001270.tgz","fileCount":806,"unpackedSize":1417986,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCT7b/YvyJ9GkCSM7O2mvVcbBh8AuCjy9tH3shenEap1wIhAPX6D0KaSs7HOlMUwEqvNEHNrKBHlRCACWz8klGzgB/O"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001271":{"name":"caniuse-lite","version":"1.0.30001271","dist":{"integrity":"sha512-BBruZFWmt3HFdVPS8kceTBIguKxu4f99n5JNp06OlPD/luoAMIaIK5ieV5YjnBLH3Nysai9sxj9rpJj4ZisXOA==","shasum":"0dda0c9bcae2cf5407cd34cac304186616cc83e8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001271.tgz","fileCount":806,"unpackedSize":1419658,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAcqpx3XBWuVkv7iWjlsipVPoKGlx1QXQXy37KSlrg4eAiBGREhmIwLeqX/49bRu+9lMkmaSAhU+X3GFPWPbzLuMQQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001272":{"name":"caniuse-lite","version":"1.0.30001272","dist":{"integrity":"sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw==","shasum":"8e9790ff995e9eb6e1f4c45cd07ddaa87cddbb14","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001272.tgz","fileCount":806,"unpackedSize":1419719,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmrgZohEodnTYgWSEWemgirN9bMDatFhyOP9R55oHU7wIgULeubihwFB5qbySPlg51ubhQVSAi86dOvENG7GQU5y4="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001273":{"name":"caniuse-lite","version":"1.0.30001273","dist":{"integrity":"sha512-8oFW0P3LFmOJ6+jHPGN2cRyoXoRBFCSoe2x8vSGS8pQwNJjonKUwH370/GNR/TvheySHq0mnL+blvDZm0N7idQ==","shasum":"ee94d4ad66e88c1b67f064e87540d5785a26db59","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001273.tgz","fileCount":806,"unpackedSize":1419719,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGtyHPve9lMX33pTyv8PA6z6s/EcSL55Uw2SlDbuvqxYAiEA4K84gd7HDE7dJiHI/x0tM9XXkEvVO1QrXIjHpMjeqQE="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001274":{"name":"caniuse-lite","version":"1.0.30001274","dist":{"integrity":"sha512-+Nkvv0fHyhISkiMIjnyjmf5YJcQ1IQHZN6U9TLUMroWR38FNwpsC51Gb68yueafX1V6ifOisInSgP9WJFS13ew==","shasum":"26ca36204d15b17601ba6fc35dbdad950a647cc7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001274.tgz","fileCount":807,"unpackedSize":1420974,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHfUS484PLqTf83M+UJMei7b4t/1YBg79ZZxYMt3u5vSAiEAqi7uTRFBodlSXKGQY9H47TlV2VD4bc24D0JyaIQRSxA="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001275":{"name":"caniuse-lite","version":"1.0.30001275","dist":{"integrity":"sha512-ihJVvj8RX0kn9GgP43HKhb5q9s2XQn4nEQhdldEJvZhCsuiB2XOq6fAMYQZaN6FPWfsr2qU0cdL0CSbETwbJAg==","shasum":"26f5076629fe4e52bbd245f9046ad7b90aafdf57","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001275.tgz","fileCount":807,"unpackedSize":1420994,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHyq1fiQ/xW6MpHKh59JRt7kOXT0aTKtUEQLdLgdqjRuAiAob6Cqqge04/yhLnya84O3VCF57u+HgrKVstzzh/dHCg=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001276":{"name":"caniuse-lite","version":"1.0.30001276","dist":{"integrity":"sha512-psUNoaG1ilknZPxi8HuhQWobuhLqtYSRUxplfVkEJdgZNB9TETVYGSBtv4YyfAdGvE6gn2eb0ztiXqHoWJcGnw==","shasum":"7049685eb972eb09c0ecbb57227b489d76244fb1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001276.tgz","fileCount":807,"unpackedSize":1421003,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGmFgWCGRZm4njt8uBQu7C37473XpTKuGeb12759BLYgIgbSkaLMMK2Msyhru8L71oezNSjC90RUrd6iPhL7Yd5y8="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001277":{"name":"caniuse-lite","version":"1.0.30001277","dist":{"integrity":"sha512-J2WtYj2Pl6LBEG214XmbGw1gzZEsYuinQFPqYtpZDB3/vm49qNlrcbJrTMkHKmdRDdmXYwkG0tgOBJsuI+J12Q==","shasum":"9416dae5e075f47eacd8e0475ae1dcc5a20e9ca5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001277.tgz","fileCount":807,"unpackedSize":1422143,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC82smd4oeoL6YN7CuXpgOnUWWSQCpl0S+gF6tZhZMwBQIhAPMjj6hOiD6Xz+B33+XWc2vk6GMBhgy1Y3mMVB9dogpK"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001278":{"name":"caniuse-lite","version":"1.0.30001278","dist":{"integrity":"sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==","shasum":"51cafc858df77d966b17f59b5839250b24417fff","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001278.tgz","fileCount":807,"unpackedSize":1424984,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD73WNUEOzXfpSjUeg6FlzNU2Cud/Jm+aPYXWNzSlgFSAIhAI7mH8JhPYUb6C9bT57IKPqyb1zSJ49NZZa362OoQfSU"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001279":{"name":"caniuse-lite","version":"1.0.30001279","dist":{"integrity":"sha512-VfEHpzHEXj6/CxggTwSFoZBBYGQfQv9Cf42KPlO79sWXCD1QNKWKsKzFeWL7QpZHJQYAvocqV6Rty1yJMkqWLQ==","shasum":"eb06818da481ef5096a3b3760f43e5382ed6b0ce","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001279.tgz","fileCount":807,"unpackedSize":1424990,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHtzspb0Gwxo70ecC4IFNBM4FmJGTXevu4TqZiT5DdvUAiB7qwNCAf5M//eApXbFCcEXMCtCPFV14tYNyWgc8czgDg=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001280":{"name":"caniuse-lite","version":"1.0.30001280","dist":{"integrity":"sha512-kFXwYvHe5rix25uwueBxC569o53J6TpnGu0BEEn+6Lhl2vsnAumRFWEBhDft1fwyo6m1r4i+RqA4+163FpeFcA==","shasum":"066a506046ba4be34cde5f74a08db7a396718fb7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001280.tgz","fileCount":807,"unpackedSize":1425006,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICN4THRxxrSPNEETosY2dyB0vdaGB2WDZW1vbV2JLnChAiEA9jVjAcsJm/HKX5749PxneLJ5+8nACPO/UOC8QyFjUBQ="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001281":{"name":"caniuse-lite","version":"1.0.30001281","dist":{"integrity":"sha512-1ktfDV2+4LYxOGeAZygMyvhiPBJKV1gsqPmfGGwRbwYOzDWbsQHgBFo+2lpRTMO2gWjPWJrCMLWa2fnSVnxn0A==","shasum":"fe92459012197185263c1e5362e10df51ddad8c2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001281.tgz","fileCount":807,"unpackedSize":1426684,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlItRCRA9TVsSAnZWagAA7YAP/2fdb5dOis6bj4AfLu1V\n2pdQfuUKMh1WwjNcYzVsua8y4UjUefmESVciGcfJCbpCXJAYKz3FeEVE0LHw\nwwh3ka+AYo9DO6YlfFHdvuO4OorZObm3jfHlZ7a1uglUYNkVKq/xt0Hniu9m\nPlQmv7HMCSWYJXQupQjV4SzqE0mhQNwE2gJ4A8iVLiVwjTcRcH74LIQAYEG7\nRl5L+KNy+NGqBp+8qloPiLpjE+jKgXUZl5btoMmzWQVwC4/NtyiwF/P8g8AP\noWxllt6FkBkJPKKqAeOveDu2h6e9vvAhC/7AkHbSrW+qGNfYUNhg+uURpDJc\nGHei1pHw2v0SRRKT/yB8YGsIrtRmRTgJ9ioc3S+W9ZTiH/3cp27WbKcgWiBo\n/4FSFSwN+dHJ6q/vpd+XJyOgEweNqmMFQkpdeSHAswpdkx/InFerBKrJ9qv4\nsjDUjxiGraD+9880gBgW1aGsrRKaXXyzNQensdY28m5LdSEvzpiEPQK1j2zQ\n6qm3qAwb90vg34uKklmem2aIAL7KwesxlhnQ7y4iQU8IYpTyijK1ZvsJ+nOm\nu7mYCrqaWuaMUGyE+ZJKrvjQf8g2xvzNY9nU4kVQ35CbZNRNk45P0y7iFAW6\ny2Az+St/zUanXmr0dtzn8y6e89IfTNDTYfDiD91pwxuGbrWAdt6g5Ilnspfi\nK1FH\r\n=G4zB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCcXJ2sQtnVFEeYELRbZAk38FBUOxaNFUmiINImBQT/PAIgJtIsPAICVnzY0Ag4ICEYybuOJIAnRJatINFee5Sfoio="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001282":{"name":"caniuse-lite","version":"1.0.30001282","dist":{"integrity":"sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==","shasum":"38c781ee0a90ccfe1fe7fefd00e43f5ffdcb96fd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001282.tgz","fileCount":807,"unpackedSize":1428384,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlLONCRA9TVsSAnZWagAAOEYP/jK9k47SpT8/aktoJimi\nTSPXOnybJCkN6tAQyEz9k4KoRdpQTkQoCRfYhkZjB6TQ74wAz4/N5nsI8c3k\nN4eBFkkhKwCD8LvgjxEA0GVRNEiYGfhZE5/WRfrqKGT9HYVNJ52Ers3gUoHQ\nrLKv1/G3pOiyL8CyYkBURu8MOBGtxo4NxAq/8NsrL+O5P6VZLKZeSdThPDdK\njNtrWIKoEL4t2BDmziiknMW2SLM0pHfhsjfVVMVfLzpc6u4Tvl//XNRLrSWr\nPqcGiGvZbfepjCtBafSkuqMVD3ahJNlt556c949eyuaU+fa9ebAm1pu1fxGs\nm1BYndfIpCIR6ErFArwUeU/XmyNDJPMJdRilWcWS7ZwgNkeGn7igwQ+K83o7\nGkyz7O4aoBRf6i4NMi7bdMJjD12ex0fKI3/4fow6zPzyZ02sUZNz9hojLHF4\nRzUwxIRYsJX75iZhvmJ/mT91p8/72kIDejZpebi115uNjJIO9fxt9mCyOQyq\n1JjP3dqVuUdt9EXewV8yj2+mSj8mvFze4n1U+6eWcxrNEhYeAluJUMUG/YBi\nozsI/T5f13cfSybSH4Jh2yof/1pNAcl0B8xj3EtoJe53QOp05rrrluGfYZR4\nedWUG1UL1NO3u4H0Lc2xoRS7hhPr+WaM1KMw2RXovOskkzhhpUlliHUMC5s8\n4fvW\r\n=35wa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIoBOVYSu33j1FJXHkafiDXiKYbZvJPVwXAFJb1w1QSgIgU08sLANw9t248IdMBzd5rDTHmLzJWpXWMm629fFLUbg="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001283":{"name":"caniuse-lite","version":"1.0.30001283","dist":{"integrity":"sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==","shasum":"8573685bdae4d733ef18f78d44ba0ca5fe9e896b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001283.tgz","fileCount":807,"unpackedSize":1430073,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhnyN6CRA9TVsSAnZWagAA6m4P/RczZthuyCxTwiqb4jlU\naKzMendVhiTZKxE2mrbB10ZjWz+HhEykPFqUaOmjZJwZs5oxH19toEKe+6ZL\nebPHneTNzuANhp2e36Lc6xX4AwvlNicgtb8hcRsT3jsIqCS7ZZcjmcsgX8db\nq4m9Wh2ij0ANxe/aJibu1zNXXB9s9nfupytUNN8+KVwxZsDbcnLwtkK7naP/\ncP7mEtVjCedsKo8sE5EE8Ju/hbpiSFnxlE3k5cEMHwZlQNhFpkWV7Jb4yBsL\nPBZ4mr4GRRcGwU5Sn++9g4EOEkkuEBNQWY7dd57evAqarLQ8jJBiVWWR48jI\nzQV6J6lNgSaauHwV+LzSBBTJF6Bl/fuzqeYIw1u+1NvY6Y8hRltvHzqXXSQz\nwi2jlRA+eTfakGQ2hYXK1t+RthODVFPgeNU47W87FwRq8NHHXb6ehNy4f/7d\n5Cu40UCyaJx0GlamkNJBg4UKzbvij4/I+zE8L7lLNScWDLp3mIDZDWG3hd2a\nc9wN6qU3IjmUapagPek0nA4S8gxnQ4nOz29Gg+AaJer9RaFkYI2OXU9VotCw\ncxkcgy+AJ9C5qU0wJnLQlV+8ljStzu5zAoGv7EbHwWMf8hucUAyKSj9lAE9S\n1cMaBVzbURQ5x4N5cl9621ndBOWSCkYpdqnxL+M8XtbHyFI39HEQYf9DJnbQ\nnIZZ\r\n=MPe7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqPGwP/eh1zoVVh7iyMu8NJtEGgSFJjajb0GUONF+fNAIgf/CH5k3PqbRdVsH61yDM6ldqD0VP841+X3TrxvkJBJA="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001284":{"name":"caniuse-lite","version":"1.0.30001284","dist":{"integrity":"sha512-t28SKa7g6kiIQi6NHeOcKrOrGMzCRrXvlasPwWC26TH2QNdglgzQIRUuJ0cR3NeQPH+5jpuveeeSFDLm2zbkEw==","shasum":"d3653929ded898cd0c1f09a56fd8ca6952df4fca","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001284.tgz","fileCount":807,"unpackedSize":1434322,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhqb7zCRA9TVsSAnZWagAAWuQP/0/PTiKIKw4WviP0tpnG\nLy9oW0glcaKZE3ZvupXMi/s+Qb1ELYIWn6WIFVPaza2ppNVSjE9jT3oedGL6\niaS303c5fBTo5XvZnAmD/k/4Htg6HUujk05Sr1BjGKl89ChlT/ax4afxBnTR\nAZSnynaaCYnAFNRFlbNbSrWOnT4GEgUQIusDtc47sXGUI3HfKhykLVSXzPwR\nXFFIlQNwHdIK9omiCZfJDgvZyXoRcppN0bgMT5VHJH+e8vxzbM8cc4vI57hA\nM5CZJ6rwDsZJqEtdpkgEKNDI3MNsDSMLq9i8a+/5AC5kABSgaLTP2BiYOwY4\nbFg3d/86OeiezI/n1VIuCkPONd2c4nz1GQa+xFFH5P2Q/dQ/Fax6v3UT6Cqe\nZYorRy+uuEP765TvERkhSA73qJA7gsLyPB1yDs7Zb5Q4dTOOCATD8jnGkM2D\nYBGG5mFUvS+JfKDQtdfuVqgcYM4n3zkPKoVk9mRltE/iSlgpDG4nRmG3wa1s\nUr8g81BzjCDkk9zrH8Rn9JedvcZQQGVZsA2fiM5hE0vArcfx5jj577iZt4Q1\nEhbm+E8AxoknBVKtepRf4HWrxLBj/XBaotjebyos4iHE9wccSTXOrnrN4Hc0\nCMh2VcLIniYIF6ggMBLDWzmyt33TeglQXM4ApjktBxFdRtRwQMUizFJv2fyS\nd8Qf\r\n=Y50t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1QAIGPTw2JN46RNe+JJZYOL3yNbvL7lQi0cNQd4hqnAIgCW61E1ja1cu+RqPJFfP/rpLwUix4/sfcBjFiqt/LUZw="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001285":{"name":"caniuse-lite","version":"1.0.30001285","dist":{"integrity":"sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q==","shasum":"fe1e52229187e11d6670590790d669b9e03315b7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001285.tgz","fileCount":807,"unpackedSize":1435990,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhrbORCRA9TVsSAnZWagAAdNoP/2j+SmlQn2b5RSy1vowF\n9+/aj/nabJxOfYTJ1ZxttRJFVwxqDjHx3/Kzc3szaXinovN7Z0QpORCivObD\nL4XqpVlQNWxXB+t62EQSY6iNUgsWyOd6c7sQclbl4OSuexIAvu0M306ZSFY7\nNOOCiCq/Ze6lWYKdWu+sxpllwHC7mFSCr3XVhTAxdnZ32UDIqZvC3cQ/SLCo\nQFvuyQdG+kXRF/P+kfnQWWiZXkWlPkaK66nRxw7Y1iJYDFnwlkAYi149NL+M\n2nWFlKRbIvTCvWs/hpFF7nqiUn4VjW0bzbP/aY9HfoLfvEokeITqQPKN0rby\nPkMZ4HpajDgSlUW8OM3xKCaz5U3xPyBWSw6RZigLc2f4zfNeCqJJkShFn/p7\noqnRkiX9PqKBG1Esd2ZUlKGXDQ0Dks6qHLwT/vQhKj08hdOSSjfaBlhu+seA\nw+lcFULc1uleUmWse3o74ozYL81WCmjfP95IdDipk5IF1SWmKLJlehhsSe9Q\nHHYoQu0HE+wBHIHamG2wGP/TX3CMhLpsQMvUh6sTrPUA4vfrxZsCpHMIwFlA\nkIFa1Z5FPLm7NnOfl+S1dJcZrSYX1p4Aae0PbwyCXv8B+AF3V14xiYxOGdgZ\nQHI1IWIvVEsVOq9VojC77oSG6+TPJXABqjVcqCHGM64x0uRB+AkUT6j7RiPg\nVkFb\r\n=g4Nx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnc5RXak2iA9hb+K2rKvaolIwOk+vZNmz+izNc4N1xQQIhAMPrvFywEoVzfttLsYbbrlcm4eOVfE7o7tgyDqSJjcsp"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001286":{"name":"caniuse-lite","version":"1.0.30001286","dist":{"integrity":"sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==","shasum":"3e9debad420419618cfdf52dc9b6572b28a8fff6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001286.tgz","fileCount":807,"unpackedSize":1437709,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhsbSXCRA9TVsSAnZWagAAOnIP/3DpkCbhRcIhBv0m2Osu\nZh+ckJcqhoJRs507/Kj3eO+Xy/6OmH4gJ3A7ebNy7sEgdQJDKHAsNGlRHrXU\n+LJMhZW0Up6DSoAmYEWU2WZtgtEuz5AI/P2mb5Rva2f6o/kl0vDBNm8KLil6\nRtZgabeK84NK3zmmOovAJqsY4/v4rYnuD9TCr5uv941uwbFLQXC4haWUmlMC\nUDI3Uopxfg2t4wrOAPJr8OEtuiKxgeD8ONc+Be+/1/GIVJY5OKXJhpXrkMYN\nRgtJpqZMyx8lxnUugvCA9UnIP23iTRzXT982rvffESue9N6wYFfzojbcu9bL\niXQSNWqW6lG0uMHuLgLNykDfFYDzt7gAZqC1uAl6sZR29suHLUEAjiQWmOVB\nYuUU/jU+G+W+R39klaEL3MkwVOGL/WtHTRyV1cFayW6vYS5RY1qGbA5COmyw\ns3z2NphuQnJUi5hw+71iMMQ5ect7vOLDBY37XU9yZg/eFbGRW2R3Ujd3tPLs\niNsrcl8LtQNE2X/FMbTxXYDwNOR/kVxN/5/pSHrd22m+AtimrpuFq/42nAcP\n2pViG/yesya3Q16SwsW2fA+iAdLWnnq1XSzEvhekmaj8cND/A7viVNuYpfzZ\nFL8+9k7PctlvXdjLRDP07wF/PdkUp7hsvfsA8Hxs4sWwoMdZy6VI1g4eT9Sf\nfg5r\r\n=90SP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE7TYT0wVgpGrHjbeFwq3ZJsL4esnaJ/CMLxWlO+JRDrAiEA0aBc1JX2ftmcRBmYkLuz5qoe26nxR+vpqmhwnpmtpCA="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001287":{"name":"caniuse-lite","version":"1.0.30001287","dist":{"integrity":"sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA==","shasum":"5fab6a46ab9e47146d5dd35abfe47beaf8073c71","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001287.tgz","fileCount":807,"unpackedSize":1441057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhuuJ8CRA9TVsSAnZWagAA6Q4QAI8rLvNyK3B3RAwBKBrw\nIZt7X2cc4+8OTDq+e745KDLV7XRYtJDfIccdFhIUgMgUHfb1oYnFf6IpcII+\ntW3bqFVwgcNnzzJ9eQcCWqu+AFhcqeb1IUKJQ9liE6bOPOi5bTvyrR5WU6Fq\nCEmnbGUJ7X806AOTvvh/EtB/K5j39m2IMma0WlwkXNtW2kEBPlUBKUXGGBaJ\nkIhwTVj9My9c9TfCzFtL1TxovaDkGTA2kLor1Mo3JFPd0p9WkltrIencJ3R3\n+oy9yF3+iw1sz95RMLf0QBaOZQDKv2DfRSauWf3RueRk3au9yPxB9xWXd8To\ney7mrcFeHE24bz2WBrwj4CSflPBFCCDC9si3PFyMzl5ZJ2SCHnW22J/HwdfU\njT+knfVLBFKE0EJHT3bvdECaWhjG1ht1HOYJawUKIR2wY6x+PsPF71WgKrBL\nIUqv0Np/HVFnnyXzzY4G79PT2OfaO8xcoTfYM09TvUihJoFukQNJ1D256VNP\nLgrgNxoG0JUMV3wsU7Gu2oug0kRc1TxfFfFK2hZGAlCuHOIZvATzthIK0Mk6\n+M+0q9vYkTZv4gisZX/4YKOmrrav9VejZ17/HhEhwrrRlpg3zlFtoCdSaRqj\nkG/YeJuMHAGavUw0fNzwJCjDD5vJCFCdQk15umRjCsi2WmTsztB/mISs/odC\n6B9s\r\n=uP59\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHyCM8eWHOSAD8cIX/DlweSRuKHPU5FFfhLd5zBcdK/cAiAUqnUqXM54NCtNhB5lCoJPAx1tSHm9ok+w6YvPPuJMlQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001289":{"name":"caniuse-lite","version":"1.0.30001289","dist":{"integrity":"sha512-hV6x4IfrYViN8cJbGFVbjD7KCrhS/O7wfDgvevYRanJ/IN+hhxpTcXXqaxy3CzPNFe5rlqdimdEB/k7H0YzxHg==","shasum":"d62a20175c4d9e740feda12a78b7c8df7866329e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001289.tgz","fileCount":807,"unpackedSize":1441115,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhvU7bCRA9TVsSAnZWagAAHZsP+wWfC+7bi6oGKN/Uq5mF\neL+/0kONCN63XTV0Ot2rIUFWLEtCgi8YelAjZlyuhsLYK9wUegTCa77mcVmL\nMFvMaldgI3Z9NEpfXuguRctA1QAdWNYrO1206kwmYlYPvY8Llyxp/2aZqhgR\nZazNfgFShIuxLsvudDWCxKgxfmfsRMr0fPwnqO9MZBNuf63JkXz6+LbJ166d\nf/QFkUdoWVI5i7wa1wEROfmL3kl5/ax9s2mP47IB+bvASRa0pCVQhk2ne+Ql\nfu7ZvV1p4jUutNRmHeUnCmQn87cV5mWDRGFAGTHy9bJoIVyAQROYB3Bl/sE1\nbZ7Y2DFD15BOM1PYN4cqd3LVQni44ZZ40DtUL5J1qUjty0EWDwy3Ua5WAsrM\nRSBng32EEvseBajUz2T5dtdW4OTK4oY4lGFBbh+6kWTODQXy4qXM54iD4obd\nOj1dCaYvTe1bNO7SND4lmRMAOywQsju7zzs4Qtvp8zEdAO6dG6I8Fse5pGla\ngaXkVkE8gH5BkflT7Zwo2pfKuesotNmZWIDyYABuvCkPXVH+/YF0eYqWj1jF\nGZjLZyewo9IyGAPJr5NDpleiov4hB7hxrc7BfG70IRAQVsstwdTFLgL5xB0p\nw8zEuYDZ1ExInKGRD1o/wLfjV4JOl+eNbZfGBJ95J5jIpMQw+4KBBZHALfRo\nR2sh\r\n=qE4X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDgRDePqsLccbT/xJw4GP71PPo7tvoLiwXuIQ/yt7DJDQIgH5FMs6F9nm27vBiTFI/z7nQwz5jMRYUKfUy5+niTPM8="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001291":{"name":"caniuse-lite","version":"1.0.30001291","dist":{"integrity":"sha512-roMV5V0HNGgJ88s42eE70sstqGW/gwFndosYrikHthw98N5tLnOTxFqMLQjZVRxTWFlJ4rn+MsgXrR7MDPY4jA==","shasum":"08a8d2cfea0b2cf2e1d94dd795942d0daef6108c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001291.tgz","fileCount":807,"unpackedSize":1441129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhvhSbCRA9TVsSAnZWagAAEX4P/069cuIZcsPLfjpbuR+V\ntwzaWPbUF/qN6/X4BY9tVdzj9biQWZn/H3ChMEUewNUbaid1DFiG36yCj3wW\nIeAGeVDa9ln7XtK3jJKSIHMSM3jnx9UaDOdavEUiogBlCEdSGELjdMAgwnWN\nyaB0Ir133IJ1sKAW07kdVZUiwi0Kz86MXz2rlPW9fmZn87dkoiiFEqbZ7oOx\nu9kI4jLZYRoJDm18pH3ND7T8dadMNG4B8uL466UFlrUmHseztn1SYocj/6Tv\nVsbU6ia2seWegKRZ7OrfdxMiiV4in/Zg2J2ROO+T9ZEfy6XqDBOe6+jiiUfV\nmAr6ol2YUVKguJ3o1Fe/7ND9fuN44NvnuFXlunXyNu+u0tqmUrV2+rmlM6D2\n0DvKlUrHwDsj7LEra7jkz4aQFoekSR7xS+wrPiArjsTgJEa8mNA1wQUKnD2M\nBg+S2HPEsK0w9+CQBlZzFYVmcvO8F0K8Q5tHBsETd4H7cppvtaKEufNCgNgc\nMgLZbdllg4/h7rj2rff5DEPXFfak0KFKS6u24FygV2S5xs5ML+CrtjpqBNc6\nAsIABm6/WXRgU99qsjHi6kDtRlDYe+N2YkOhuCuceUdr84wq4hz9c6ppJ+0d\nxZKRVpgJoh1fQD1o/x2/IvlrgYEahikEi8VJtwzCTOpgDhzqlnAuCrPnf5Rv\nhv0m\r\n=ECAQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICy8q71lfFHC7YSCUmmtVIOJXqaH87VRGnA0nyRccl+kAiBEvz2mFxA2uvdUMJiJBbk8crd1LFF1T4an3RBTWxFS+A=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001292":{"name":"caniuse-lite","version":"1.0.30001292","dist":{"integrity":"sha512-jnT4Tq0Q4ma+6nncYQVe7d73kmDmE9C3OGTx3MvW7lBM/eY1S1DZTMBON7dqV481RhNiS5OxD7k9JQvmDOTirw==","shasum":"4a55f61c06abc9595965cfd77897dc7bc1cdc456","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001292.tgz","fileCount":807,"unpackedSize":1441129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwit6CRA9TVsSAnZWagAAzksP/1po8XvA8gDPDzdylo7A\nLUeR8zZYdl2SIUNwYlFd8+pAGw2H8RzUUkmi7Dxr7f9Kp5dUcyjx0zivNr35\nIeGR6VftYMrVh3d9qs+a+aw6r/kov460NWmfQq2aeWl+r6wCkFbyd2bRnTta\ntuHjcylMjocHSOr1lo34Nje3UhYoNbatbbMr6+gbcUKqVbUNjx7xSuppmc4S\nWfmuukWkXlh741YkP0Ve5mpjW56L2A+c/6PGSzmIch4un1xRQlrxTUL1MGQB\nh5SJZ4E8VpJke34Lm6uOUBjlzelnpS0/bemzwDzxmQLyEfC45/dGBuQ2yOdE\n1muCQ+cH4bdkm+cuMg6rH5HxjVVQIeOCKw+7JQOAI+/2rnuf1A/6qZ92Wx7v\negYN36kPMGVHKobIB0sDKVgUq6Yqm7eGAe+sn6Hp7CMCNTsI8zSpclgxkLvO\npLsMZMYph4vLN09pt+2OCRPbbhFnKE4Foml9xSMZ2ffAvMs9ulflwvdSZgtR\nPalzTfCBOKfv4X/GPOEysymrZY6GFoHYedCEyKgQ14bTWGMHeKfL2ZjDuvlN\nZrBpOP/B+G3vFkaoyt58SPNCsjObQqc0K+4o4MkRgr+CbB6qnN7lfjohRV8N\nwAZPuS5FNf45xWHTFYsBJyQ9eYHtzLiT1GbimEWfF5Gw0zvlqrJvEk2x14zB\nbT7J\r\n=wknF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAVGaqIG4Ms6U8hHAev16QspREReupjMT9DoiT6tXmE5AiBCI7aXb/t+8nPeUP6mfbNAAdqm1e8c7eCDyTuJla1noQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001293":{"name":"caniuse-lite","version":"1.0.30001293","dist":{"integrity":"sha512-A4I5fB8Kxo0p/H3aXlaOkBp9mD0GspKmXfWHXOzcl0iHLi07EEVJdJeQPT4Yv3/dffRnrwluYZyXvMjbr6WhIA==","shasum":"fb8b7f071a04e50fd1e759d23e3d65fbc9ae5ef3","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001293.tgz","fileCount":808,"unpackedSize":1443065,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhy056CRA9TVsSAnZWagAANhgP/0cS0/1UxI943DHA5Xwn\nPVFQKANBQJ2aL9yjXNAypQEItIlWx15TL8qhAoIaL3beQpHEF+bINAPUvFa9\nBTk9GLrijhGpjE5XHy3Cs9uk2pH+OjP5IlbVzmwSt3Sq/5ejnVKSZwQt93uk\nlYH5tZ2IOCDdfIRTLqpqJFkEdin9G83c+UgFtfVxJ3xFF9c2NEdOSvMJX22G\ndrbUowatGKHDDKgZ1hR0473DyOXwRnbI9fLPBnafkIyLvARYHY4NUnHLoKe2\nqA6EtCz1mS7kwj2Cl4pnLg3W6B6gSOeY9rUQS5tIl+72jwcYj2dAkv9+7ahy\nmNkdkRZRhIt8qemsNtHToCV3iEclChGAv1IvcD6UMMxBUyYQNAM0Uzfdu8EJ\n7PQmOIXvYl+FIe84YShmaoO05SOTXte0r4YCD7BXw7siOEJ8FQXrWlM7iTU2\nMeeAKQ+3vuNySss8gnjJ8SGXjtU6+9omyIj2xX75cvnfX0q5Re5cAIF4lWgL\nFrdtVj1oyYQ2xNNezD42way+Vh9ujRrFVUFfS9orwfTHHVIqP3fHfSbzZBEC\nhl2FnzjC77nt98nWvhVFEfoLItEv9ygjssxYNBbXE/i9vs10rGlHsGpVOqjB\nqLYkyF/QtDTMKj8Gl8nvSzIc7l5i6wuP0wOCeM28cZBa2xphNUIuCD+bKYxn\nbghW\r\n=z9DY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkIvhwyKY7kxBb8srpvwc+rtLuIawpVYhJx34I/WDGQQIhAPYspAvDRwPHvR/EFKTCKZjjegpojiWbCoyqDTbL/ILM"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001294":{"name":"caniuse-lite","version":"1.0.30001294","dist":{"integrity":"sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==","shasum":"4849f27b101fd59ddee3751598c663801032533d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001294.tgz","fileCount":808,"unpackedSize":1443077,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhy1z8CRA9TVsSAnZWagAAzOkP/37Dt8+lLnwoHWLfTu2G\nBBdvLmkVB9l8XrhQWeUfIKES0qmxbwQPF2m1gNsEqyLFYtKddUdvR4FrocA+\nQEYQ1J6zcG2EII5wvdQfvvVVp2XKNVXBpkViuJIM/TyRAMEWTLfHJV0boXdQ\ndc9txfixiKbxbeVo+i6E2TLVMcREvzJMqUJZDhAfk1YB/puZlybxNTEgJ/1l\ntAm+Lk61MOsRygboXbg8Uf/983SOr1l2XTyTtk7AOc7aFdRJRo4dC/ZX+C9r\n0q5wrRZq0gw2GrsAakyIL2E1kdxmW++6FkAZ+VYAg9W9CZLYrsNPFn+LLpTS\n6xpyDT/qcMhyLUBzhNi57eWXB8dKXd2iefn9VdDP4RLj6cA4ZWmqFmjcjin+\nPXzOYY+G9PwwDthvAzRcqPVlH/f6A0lT10J/DhO3IBs0BcGc5yfEWBPDN0Ck\n+O6188VcTpKYfFSAuvgmfrBTVe1gAAI9lzRZkjh6FrQwEf437KRtpl2rvvkb\nCn3OSAqhgK1YrX5p3K+Jqk/rHd1pML2aQho0lrMc9XFHgbhBU+vpNDCsW8tx\n+P0JXn73iXGrCsg+mP5qkohX8u0R0ed0heDWuJAOeCFCdn9OQsKGhAGDfs5x\nYo5OlwZ/fHoprDF6dBqL1+X6T8f62vWv9rbw8mjYYcPE9qW79CV169HB7oRX\nLDK5\r\n=qpkW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCntLdQ3Grs/rzBabtle9ReZ1wS0HjtC2m2OQJIcFNUCwIgeAjZxJOYIygA/u9kzyfWAXyQF+h59bJcvYNGQXNqZtk="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001295":{"name":"caniuse-lite","version":"1.0.30001295","dist":{"integrity":"sha512-lSP16vcyC0FEy0R4ECc9duSPoKoZy+YkpGkue9G4D81OfPnliopaZrU10+qtPdT8PbGXad/PNx43TIQrOmJZSQ==","shasum":"68a60f8f0664f342b2835c5d8898b4faea7b3d51","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001295.tgz","fileCount":808,"unpackedSize":1443072,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh0OgOCRA9TVsSAnZWagAAJ5oP/22tB09TaIBJ0iMB3f2C\nlToDOLaIjlFREyGT5SnUAIQ5ZspVXQB8G3t1q3ZBgtDjfjIKPMNfWFNgv/k9\nTalAAyLrQDPFQMm7fiPOSO6VipI73l6E5dAICSi7lMSqMQh0nIBFJhQDogeU\n9gCW/gHt+F9v5sCf/rjPu4gGUtK6YDk+PytCnkuZeHx2FWFyGHBEFdD8g+I/\ngATBzH68htYYxlrn4+M84kQecplgXiWf7CYa5KucwhUp8B1a4z21l0BnELWz\nDEVf+fTF8zgO3ItI6og8CDecuht0Hy1q0CySWhZ/j6whMGoTpgbZLqWyZN8p\nQHWCa8xQcdHdF8tgYOBPT3bixFRFo8LwUBZ2rQIDDQ6DutEiNIP6NvaQwzuw\nTAcZ0tJkJmfyguj14AyAtlqLf8APpHYnABl4CVnVIrspkpDf7sjN1vvwXhKc\npSVgqXBit7wg2ZIy6YdRru4tndBjqizUnc7NhJtsGy7Vt9OOoz5BvFSdx8B8\nOLbhbp78uh6E4PZODImue1t80PE45xC9536Teed23SqKcKY5WgEf/UXynPdb\nZE4D9ow2JuL7zXSCqQU6IA7zmVolXipiIWVXJFDHCxeU9P1GIA3AsYlj40ey\n2qgIkBg+MOcs6+0NMai9vQo0taNByMLZ93/cCqMfEZ02vOd8TbhKE3wBdSml\nmgnc\r\n=/YQZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDUI5uHhkH73hIi6Sm6y+A3DFvjcQKwIdepEvJHId5tLAiEAp9kRRzcF7F4UeqnzUMQKBTqtr+AsaXGa3RaFirwqAF0="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001296":{"name":"caniuse-lite","version":"1.0.30001296","dist":{"integrity":"sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q==","shasum":"d99f0f3bee66544800b93d261c4be55a35f1cec8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001296.tgz","fileCount":808,"unpackedSize":1445114,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh07f/CRA9TVsSAnZWagAAS+EP/i1IHUciRaBjFd9eUe9n\n0crvYKmGL1jOreLXE90yCaMsDryMBvy57HOFBS7o8eO/zYPqGj35rlPnr2zK\nMso+4k+97dCQamMvJomHDfxxbxGDVB9KaR6juVZ0ebM9VWYEcVdsjWMwnzpH\n/Y43HrQGLZ8eUkgBoQlokkw1SFCzZaJqTKiSipp+H1gkdRmsyYl0TqkqAwtD\n7jZKBENzO1Vxm/2wWKkOl0V94BtCMmWtcfrQe0ct5Fba5ryczardzAKW9UgS\nhX5WpcH+JQyXrVmADkw3DkXaQrVMDkbxCVOZ5o+QlJ8vBYKLXeWrBAee4KRm\nEbS24zG/oqcnJ1duQWR+d1y0lyykrQ5AQJuhKr/M4Ek5OoL6eUsMHGy11p/0\naDyVdUa85r47g2j6m5qOWZapjP79b8vCd1uxFphOtUPp2BwglwNY+pTmwrWl\nUcBcCmw5wBFmY0NmtcheaSK7bvsCGXDV0WZhy1wZdx/dNr1ywz7p0CY/ZW+7\ntt9+cilv8vkCLNvfVh+QrqYH6UePs2Gz4FCP5HXi1qV+H6S45CALq305NplV\nuRPO1cD1A8WBybBfkZkEJ4xY24ri1fJyukDVOhzQtYOkceBlXLBh5kRPiJnT\nVPobvt9PN5O6lvcrgA6DwjY6YjXlSCLzXtU5tD/ZNjoj+NWVeJMJNqFZwjWe\nSeN3\r\n=/iJF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1Xim3WAluA8B6vmwFNcvwRRXYWSP5Dz7QtxhEvi45IAIgWf0utKRVKBWq4tR+CIjBLPqP9TkCeHmynHCuNsanud4="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001297":{"name":"caniuse-lite","version":"1.0.30001297","dist":{"integrity":"sha512-6bbIbowYG8vFs/Lk4hU9jFt7NknGDleVAciK916tp6ft1j+D//ZwwL6LbF1wXMQ32DMSjeuUV8suhh6dlmFjcA==","shasum":"ea7776ccc4992956582cae5b8fea127fbebde430","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001297.tgz","fileCount":809,"unpackedSize":1450344,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh1+QKCRA9TVsSAnZWagAAs3UQAIGv0GLRvGj3RfTMFtSt\ne1CNhUy9PxJMhHUuyzXmJNyOZ97LUdLXJ1tfgnPqNDGNxMgQK9/YP+Um2SQl\nBBpgBIRlozb9e4Fokusifh6Pyuss370oStxXGMBybwsE+i4ljMZ+40h3axpo\nkfBPKrQDsMBJVt5tlm/Tv4tTKJ5lkuzvfDMe7uY9EfavI0RDW0Z1nmyrJ4tS\nusLS1WunM3ckyeS1DDONsxsShpRI7+EFMni3X4seOW6R071dyJ6dfVdylL/+\n1mX9zT6VHeB0Lp9rM/FWn+cv24uv9wAq4S3W7SCNAyVHA/hDV55nd4Wy1trj\nyufJjXshsQH4N5keBC0L+TxYl5x08YbUXveDjKsUnkVYW0LRAEKDe0fPlBKU\n3JzuOWstuea1tdFUFLHwtNBYLpTvBZhtOiBLZEUkpEJnfV2OCQT9/95M8W/c\nUeldmtPoeoIxdoPoxwGoVvhpLAVok77KszQW5CowMexWToQDKshf4pzKFHkq\nd0Dm8a4Co2Xv7R8K2JUup0ypr8hU/9N25V7xR+irsX7zg4P5FSZgqwUq9Ff1\nzhf8nb/l6cdWMpV2GsUdkcZhuZMYSILTBygHdAWfJD4XMHYyok7LP2N8jMwA\nk/YdnjI6peZYa69d0a6X1SqLpwbBHkVhKat0WPz25DsCypzyi6PDZtgk2T0O\nQJIr\r\n=Nwn/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/PCDFJ0SUyL6MQFy8Rw44DkKJMHoxdjNOkQRnf1lhCQIhAN64etWPEjMD6PYB5Ov11bXGlxuufbZ43HRCQ3NcMUD4"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001298":{"name":"caniuse-lite","version":"1.0.30001298","dist":{"integrity":"sha512-AcKqikjMLlvghZL/vfTHorlQsLDhGRalYf1+GmWCf5SCMziSGjRYQW/JEksj14NaYHIR6KIhrFAy0HV5C25UzQ==","shasum":"0e690039f62e91c3ea581673d716890512e7ec52","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001298.tgz","fileCount":810,"unpackedSize":1451611,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2TUlCRA9TVsSAnZWagAAM7MP/1pSbIOxGFTG/CVUErpB\n7MeFm11KRvyyDFbUX6wIlywLsjMM2DHnlaOvG4DmXCnjGWFtAq+DuYBY6NRQ\nwbkSLprmIK+BeTFfRrXuMj96cLGFNW8b4jPPpvM194ODg1rOKodv+O8TlMtn\nT8wwnZKQrgBwj6o5TpFzZdxqctHpMs0LgN1UzAThzSDbs9Kb/C+XBaECpIvN\nIlP57aNzX/sbbKcdZdWyrCYyOviX4cqS7SiAJDxv6B6ZK7skTQCKM9yWmSlK\nVB/DjOa0Y/Mk0FNLPPtd6mwH+L6p1CJYPP79TCskZyOCWZknOK9T73q+NOG6\nMOZO7StSotpHSSrPDc1fdZH2OlmLdRVqO4vqJ3WBOBxVPWVEIVXwHPHH22q1\nMfqT8TH/7iDPWoaxaiJxh6jsO8nap8iKVW9QfcbPkCXRMYbvWkedaqr7M7oN\nuz8JcIrEmbQoF2VkXtfgDojOgOqOFpDNap6p2WcVn3PHxd1HlIbv0HsZmqLq\neULQwAynZ6DdbRG5UslvK3gGJxKgtsD3W3/8sVb3hf+raynM3v8TsmpXSQu7\nc8yXFTU1YeUv72XGl5PhVV8io/z3sVoZ1h0A//PnMWTUCUnw2sg38kKXlmqC\nJkSSJul+IuEY1IdyW0GV9Y8A+vBMIds1tGjzCVeb3U1/TlX5QudqKcRAqLEO\nMKkJ\r\n=HxkK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfSSSa0bvV0bYJMk3phWpFFDZ/tvXvvg38eKnO8tAOBwIhAKHgGDakmAi9WzI49+UDRRoj9JZdplydU8n6x/fA41BN"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001299":{"name":"caniuse-lite","version":"1.0.30001299","dist":{"integrity":"sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==","shasum":"d753bf6444ed401eb503cbbe17aa3e1451b5a68c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001299.tgz","fileCount":810,"unpackedSize":1453375,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh3mt3CRA9TVsSAnZWagAA34cQAIYEOcNhDPSV3caMY4/G\nUAfWlcs7A03dUewy0GZJTCLMKq4Px6/I3mBNMddm2zK8hsSNeP6NBf4rwDND\n/TX5zlmYAbrT55nkDqiJNrR4VaHS/GkLiICxjHRDt76lsaQnUgujNDyLoC4/\ndV0FYnBNta32TZ6kJnRs+W/0dDAjywQi2BMMVY8lEpgMD69YjOR8Y8k0RRAq\njUUekD0cs72RRERS6HlKnHINVaqYvULVFvDz+ugM6CYXyD7MFkFHEkJsXzxh\nw+ZC11wSArf7vIsuom9Egqnygvt0QMZuX2/ktO/is/QxplMPOraFo2i4T3wR\nRVcyaSf8/h4mM6PjUlPDxQEl70CCDtxOSUXDjg3d7uPWSPA7bKluPI2MrmAM\nZjDjQJBRPIIqD6kKYcTFa9HOiG9ZEPdOc6X+qqinOWwT32EVxEVh8glckCMV\nOc4At7NvrZ8fvCdnm/OMX56t/QyzwniVaSv6bwjyoESy1yCKF9oHgtkag/IY\nl2F95Tmbr3lpwURGLQTpGanriN+7NuTxn8/hRE2T/OwTceLH/68cuQuu19vi\n0sU/Um7lSLDZtI44oCXzwRRXC/ckOJjjgBSvdtAJPbp5QagQ8mDfNow64Mtd\n9Uel0RcHUPcluaLVkqQKz4TZvuBit6mZMLvkWtZ3z8ALv2H6wPFzTDlsyvuX\n1aNG\r\n=fCTH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHWLJGs3NnTmpCqcrlAhA4NifhqeNN2xhdFyS5PKpbcEAiBnFar4x17+/a+wusQ2G9AJ2UIM12CY8Xj2vGXo8lryag=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001300":{"name":"caniuse-lite","version":"1.0.30001300","dist":{"integrity":"sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==","shasum":"11ab6c57d3eb6f964cba950401fd00a146786468","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001300.tgz","fileCount":810,"unpackedSize":1453381,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh5RMCCRA9TVsSAnZWagAAqS8P/R3W2eAaUP5DG6zvcill\nm2OigQ8pSYD+KjGirs7Gk9dzPEilNakTkclekNd3GZE46gq73xKE39B0n72O\nNXiV0QZ7pKEtk+yuoG55+hvg8HXicAYgtaEo441kFi55BND6j+9jxYpxSSDC\nUxMt1O5qul6v63wOtZvvBPl3of0y9JEVuOH/xHVJMgsYoBuzaYe5mgH+077n\nSAtdKwvnP0636oGijBVtss9c1lpTwRMwUakygSb3qqRPV257U87jgVJNJQ4x\nhxaXZAxTtZhT09wUMlT0b33tkoR6LtVZImnSJkx1Q9pQ42Dwns25f7CFHHA1\nKZFNl77a607ELPAjUVJEI+XSLRuXVmhuBPGBIIFRDiJbuWO9iIAnw1mCi/9T\nVrN+lF9HeM+47ELETuyGjBPRKuq+DXAFNVgf/dBoOLkquJ6vE9aYV2ShFwqw\ne6YFHjNs7fcNpF6G8No2PSWQh+jnoRkKd2GQzLE2H5Kv2jv3YxcEybCcEJsh\n7CHkK1f1eMfVM90h1jYwajpfvc13CuMt4q1nnZszuQSMQWsKURKq3cs2XfKN\nvOKqovNOJzfdEirQZEEJCfSAVXxr19kfxyWR4Be6nushuz2TOhKK9Cs1w3f3\nko4saeacF0rfBo6gwsN0OsZO0YduoOCtO4qAf0ZZ3fS2Gu7jUUIJ/y9OV1vU\nrXBN\r\n=VjRg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG0ax7WHz9DgygvXX16FAtoLJSwgbC0Js9mAD0sc6ydCAiEA51rYKeVcUiQwtL2QoKhF0n2zhxrXsKzZu5CBgUW0vvE="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001301":{"name":"caniuse-lite","version":"1.0.30001301","dist":{"integrity":"sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==","shasum":"ebc9086026534cab0dab99425d9c3b4425e5f450","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001301.tgz","fileCount":810,"unpackedSize":1453381,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh6kj8CRA9TVsSAnZWagAAfbEP/3QWzm1NME3vkoYxiIJt\nKC1z3PYzCu1k8Ihtx22PSBUZa3nx2e7gU6nHMpowNSEM/uFqMJPfU4yPgGiD\ny/l5yvs2TczTN3yD1rX292YCvuFWYQcjFzGu6aHdR60gGIsvRjM/AyG32PEG\nQTdcxQY6DfUn6laRsNmr3N3SBfmznlKvXT0AgnC7eCdtPkEhVknfgwyPBX7T\nEyr0BsFXXagQuJlM1qdsLxvpGhAXjbPKpsQ048tIfd9ZiLtKfJgNgcV6f9Oq\nb26ZBhSFWi5+3n+pxvMeo7lgSFKkQi47qJryyLFVAH3O7Pcw6BFRcwvgVuLv\nocUupxSXR0PMManTwjZIaQvLRX0ZL39IdN2NsovwdpbnUOOku5j4Zl875Nxu\nGuMi9yuVe5kLcg8UFqhidl49gbIps2O3on60IXaqbZaTWSO5Z28UoTqLC2qu\ndFqgSfp2rTQXHdVXy7nxSVwBU8IljiG6WlUH2eOh7pXOgiWG47tYQRqglN9i\nIQOAVDtfQd8i3wvNV9KubWzTBy351iOKIDXbtrVltgPuifyoeekuaBpIYYa8\nkNTHAa0D5MOW0Im+t+M5mS+iCG+SnEbikKhpaspFF3x1OTeMibf+6BQlYsqK\nIOOmhr17KCwwKC/vJaZztXZ1p2Zv8PysOBAKPP4dbY8hTi73ByW4H9tmW1mr\nvrPV\r\n=c8Uj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwjzrN1OAAeOJ6yQROtA39bmu8I881L4e9d5e29V+oOQIhAPkxr8Mgj4qNyuQFuv/uPZ2fXnsDuhuKon0mhkqVVYEm"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001302":{"name":"caniuse-lite","version":"1.0.30001302","dist":{"integrity":"sha512-YYTMO+tfwvgUN+1ZnRViE53Ma1S/oETg+J2lISsqi/ZTNThj3ZYBOKP2rHwJc37oCsPqAzJ3w2puZHn0xlLPPw==","shasum":"da57ce61c51177ef3661eeed7faef392d3790aaa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001302.tgz","fileCount":810,"unpackedSize":1453405,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8KjTCRA9TVsSAnZWagAAUxUQAIFir1vAxWvu2qagTstF\nAdhAMtuvfDoYyHiEj/febaiZZvCpj1oewFM1NKY14XhSlfo5tIrxsoLotZk1\n+nzGjfMIh8z0BOHgF5humq722/C3g1za23hCv1XbXH1DjcsAP3yGKUVAqkpW\nhbmfohfJXX/zpoaLCez1tmDajMuoq1Ct27zB7YqFCcZRmQYpL3g0w6MTRrB0\ncA5IobTSZc7Mk4UWOrtMTA7nXxynEwj3A30CVV9eQmCKI7To0Fw5lHn5YB5T\n3fAUaYSEWMOR3EdcjxDldRKFEl31XTYEV77iREKjKzN3fNg9o9lxcFeTIyc1\nANoxI28Ss9P9BAkoTR4czOGqBdmkTGIL+VkiF0nzUhQl04vPSf7PMk1YexJz\nUnMAd3EzTAVdO7nOpsmGLVAFHbxHZ+v9Aoi/CgRWkU2SoiOmblWfCtVi7Uwq\nXd09goKj1u38LecqTh2uwKEwIZuAgZSPkLUhhsgKXhWjfN8t5/fMaw+Wbtt4\n40+RBpV16bVpX4PktpXQgDkrXge7ckYZccmmnBzJSltU/ESBY9cfuzjuUyKA\n7OBR2t+6xnUHEwZe2L6o4IkoDRsjLB77xIIVmiAf+JesvHJKpoJE0k2RMGbl\noiOVubl5GV59ARj6B+3sayfpauRBKyaOnN+pQHfv3nR0iA4esGE8ctmNf4OE\nMnHG\r\n=HclN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDJse8r1/z2ktWOJnoCWwU3hIKxLx95+Bad9H6SMugJBAiEA75M5ZFJZwwcvAUlgrnP2AwrfRTx/RW1rQ+o+t9yMZcE="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001303":{"name":"caniuse-lite","version":"1.0.30001303","dist":{"integrity":"sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ==","shasum":"9b168e4f43ccfc372b86f4bc5a551d9b909c95c9","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001303.tgz","fileCount":810,"unpackedSize":1455100,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8kDNCRA9TVsSAnZWagAAVKcP/1Tdinc75uMgQ+09pXsR\nSWZSJZ8SAeUIy279KP+ug0PcP8Tq7TC39tOBx9wuC/tRWiwO4Q3QPUxum+6M\nVr9aoFOAkfuuwl5Xbc1pJQB16xCKVgliUgOUNj1Ebz6en1BkuneT7R6c9BDm\nXdi8iWJ2XNVB97wIu86kpkArq2I1hD8HDwt+PXwjiAcqLvtkEUfswtRZZP+f\nGN69/VP6BzOdmMGXlJjsL327xvL0jdDl2TrqvFXXNfyzFFxBwjfeTfrFKdNR\n/dWRPIG6ilu/9RdgIKOP2BBtKfQ3gOE3H1qKaArTNy49NZIFV6ACE4h7UmBy\n6JXLU1kdQ1eupnMSk6y4KpQY6nKPxR6zWG92cqe362oUie3CdBXnw8RqHWeS\ncnUiEEA37w3Q491SSarh211ti9s5etW0M1DLMobMxozO0+ivqQ4KiSgtYgwu\n1puTQHOiaepd083Rr3Z3s2Lh1S19MbTBXZwKraOXBoxR/Zpq/94CY3fWTkQl\nHlEJS9PiAkoyRNgJQM78wQxmPYm3HR4edfVJB9feS5qsyjptubTQC4UVeVSl\nc4rKUazh1k7tUe5hLO3NcAnGX1KAd8lSG3jA8faZ2CdiAUcVT11cVOwz9VpD\npDikz5qaYNj4Q0wAedi7CUUm/xntEG5AfxRyEqp6wxT39pJTb3Dl2aVaMMgB\njABi\r\n=RoXX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCqtrNKiF+cXIEk0Jd/FyiWCFxTga95C8TUazvSmGkYwIgKXNeBo2KcclRJJ8c07MpEX/4kUxQGI1kMfmLplOzwWc="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001304":{"name":"caniuse-lite","version":"1.0.30001304","dist":{"integrity":"sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==","shasum":"38af55ed3fc8220cb13e35e6e7309c8c65a05559","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001304.tgz","fileCount":810,"unpackedSize":1456503,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh9YTkCRA9TVsSAnZWagAAhbgP/3NpZ4HemOV5SUQ945N8\nftK0lN6dwuMrzLxtCj2VuU4NfNszyC7KI3yvpVVDaMqAbVURot7Zd4VZyc0c\nOOhlSIaPwNVDs247gAwEuethuCH2+JGk5Dq8LYbIZrrnMXkYz+eiDhIiDrUE\nxd6SSfLSC9lOUUJFx+W8xF5kYCN3H6XULx8NzdouM7K968fih6OVDGXIeQmL\nzwkQukegRld7h4z7MY8WNm2qVx9fgF9RjrgTsSVar0jMQrA9/rVliv+Uqtzz\n5p/2+8Te+PwYbgfnHz6uPensDeKTvku2CKVylqSyfsn0P1LDoPmuTVdTUVYG\n5SRCeBTHHW8fdjrC3UUhdQkrwmPoHcxs5NrtdQ8z4iwXGAc0GhOPR5M+ItzD\nHLNS2gTTdHhaPK6K0tyFd1Rvs9+dY3t7VCdP7ZwL1yGRjo7E6ivrEP8aHouw\n3lVUVY/D0GoXVQqkjV3l93uMYsJek5IETMWEIX9EPhaN5NPj4JBR4AMAnndm\nAS5bEjr6u7wK2rNO7rmiNFdY5+tkGkJ8FTdGRESAlkisFR+T+VH8uYrf550L\nmH65MBO4MzVDRMo/mkSrWhIVqbXBZimSa2p0VSuymcmP9K1BtW2UIz/mOORQ\nQeTu9448XnnGfD75MwjmZ1CnoCaYC+4it++VkkXuqLT49PbpqfRRAPqonEdO\nAavR\r\n=TYvP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNrZGUtQewZZDc7IoGGE3DxnyRKmqHapQ3Am71q1yTEgIgQB67ljO/8wuNc7kVnBsgSXdZNvj6LNNeYfpAAPO82Js="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001305":{"name":"caniuse-lite","version":"1.0.30001305","dist":{"integrity":"sha512-p7d9YQMji8haf0f+5rbcv9WlQ+N5jMPfRAnUmZRlNxsNeBO3Yr7RYG6M2uTY1h9tCVdlkJg6YNNc4kiAiBLdWA==","shasum":"02cd8031df07c4fcb117aa2ecc4899122681bd4c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001305.tgz","fileCount":811,"unpackedSize":1459005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh+f7cCRA9TVsSAnZWagAAoSUP/0eFkrFcG8qNxUAbeE1H\nGZuE/f5qkra6MKwHSbhdhz87itpB99TBOvMDmnlz77cral2rtR/x0Ho3W2W9\n7L7PM1bMplDceDwnFMbMsXPfTl6bMcvb4VB56esUrwRJ8R3EEQQxm60unKOg\no3ICltngXb0fJgAdbMHZ8eQXPkPvTUaPM0bPoSXNkEAcMF0VVZWIFc16ruKi\nPYFuMph6rT7FiU2/0Tiz/gQ81VljZ9gHIUu1s1B2MTjW1g8Z6Yjik/Bg76x7\nh7Hlp8x4gw+hSwJrEGcEhoDFe5Y/079riQ+WbUK3biBTVNCK9d5IOqgSJ4lU\ncZ+4nCYaKEP3wEBgyzH1afC1UveYoapqALwDUyG4DlRcScX4xJxxpVVQI80T\nBJWWo5jxLyV61a+cNjTOB6qv0AEoAQemc78aoCd9IwqGQp2Sis6Q3WhE3ixr\nsEF4f7WWR8kYJD3eKAxJfHqm9/GTwsW0Fwvpw7NOLmt+sb5rI6dxyJ82qBaH\neYwy+3B4lnQwURN2vtI/Z94tvy3MRe5pJwlsN9saagYJdgWQvhZ1QLh5ad5d\nrnHFX428DGd51hHrXf4ZTkgs8LWmV3dStr7Rq9dGk6fZ47TPQMpDsGXwuEZb\n2MESrsmqYgUFauCrr8oq9wmhXdLwR2tr44BS2d6gH8TxMWTQmfwtujy8PRmF\nXOO5\r\n=cH8U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHtfv/9CCmbs8mD+FfRxjQxSJu1Qtds6Bh3UyQwKuyIAIgIIm+sB7XEZIh96OeXO7zXkz8X/6AEyh+WJuP20E/9Ao="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001306":{"name":"caniuse-lite","version":"1.0.30001306","dist":{"integrity":"sha512-Wd1OuggRzg1rbnM5hv1wXs2VkxJH/AA+LuudlIqvZiCvivF+wJJe2mgBZC8gPMgI7D76PP5CTx8Luvaqc1V6OQ==","shasum":"582592afe243bad2223081b8abab07bf289cc699","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001306.tgz","fileCount":811,"unpackedSize":1477776,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh+4nMCRA9TVsSAnZWagAAfz8P/1nKFHqzryuaL072Fj6v\nPtm11DcOSbteQjFyvZ6WorHpEaJPYQy737GuZBtT3PHOK3U9nur9LQ8fxSoM\ndwF1bxzkPfYraF1JlV1qFq2xSeDl15HgdPyZGsQVt/j750zmgtUaiaIWoVdc\nTvqbuFHONrGeBKvFV1DzL2XPIP4nCpBIG5deKHSy4hll78uuQ9QpwvPy3e/W\nfhBWAUm9np2mR1J/3EiQUTH+EyvkfB0LHIoQKAVyXE+qlaPlHUvddbLKCfLK\n+TnHz+HuJm6426SJGWDvzPzY2/nGeRltMPlloyiWX/kisehBjy+mjZzW+fGU\nQm1rihQVME5kSjfDMJ3YOxv1oNLoYUGyM0eEYavLaHCJfSQhzokkyEs/n1xH\npvvlGNCt26nFruyFfqDDSPwj8s2/6U+0sLB62uRriFiZqcxC0HQ4o11pDNQs\nl017yrlakuGO3nT24VF1jSnOum3aKBkNOYBW1L/shdBpi29aOhgwqm04kQIt\nRveTFAerGUMjTfSxEPoD9Klxju0WAPz1n6MAk2IRmyvBI218k6XrHODdaHjo\nsLKP6xQDIlurNIVZbNnmfV9xagHliqj7blJTlREi314VhjDYWt/Q2YymfuZY\nOQvBAO29Dt5rAMq8Z4y17UWj0Dk05qsuUputgPpCa+5mHQ8xH71LqGiiHnHc\nZfmu\r\n=ST/d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEpgVtD7DUxtmvws8eAHGFiY1PDoMgDVf/fyp0qaU2wYAiAixxZTFP/AQRs0+Z/CxiX6XGL3kSpgeB6HCNLdMp5hyg=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001307":{"name":"caniuse-lite","version":"1.0.30001307","dist":{"integrity":"sha512-+MXEMczJ4FuxJAUp0jvAl6Df0NI/OfW1RWEE61eSmzS7hw6lz4IKutbhbXendwq8BljfFuHtu26VWsg4afQ7Ng==","shasum":"27a67f13ebc4aa9c977e6b8256a11d5eafb30f27","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001307.tgz","fileCount":810,"unpackedSize":1476537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh/K/hCRA9TVsSAnZWagAAZKUP/jBMz+2sWlnjzELXsZHo\nHukNCI85PIvzRJIz8L4SmR3cTMjzStN2YylrWdbXUaD5yHVX/oawqj2zVmw0\n7mZfx7BVesHBNHAHNcTbf5oBsECNhoDwl8s+IzfM7qn3Cw7Ac6QZpAnzhlyW\nhB3zPy9qPp2WGau6SZTDecJvuYbe/Y0zGgDl+OBEOOWeBmKalz642q54ZzVz\nCLcmzAKGDpEPspvXnBxZ/bQ6q+GFW1cWlzlJzmO0TU90WXI6Oo1bx5ZQZOU9\nVQjw1lnk4X9VOA7QkMYwgq4HR3exvK1khgzBmQodT8eDDXt0PEB3yOWTSLD8\nc32Vt8mNvlVD5mdM1qBBBXHKQqq7bIGP0kwDC7b35QGpYSV9vx9bmnsFddnp\nnP82n8f79ziHs1XzX1F0VemA7G7zDi6twgf5ZZ4D7//qbXYye+x+oR0ZfZv2\n0EzCtvMOP0OaGhsOnxEHIWBJKCluEsGDO/474S90zAVqhIiCpUZ2OrJBD+ad\n1H4Tt99vXJ1vEPcwkEeFa8u+wjUU9cKKHOCrW40UYgJaIgxwpt39WVmwJFmT\nyBwymFAJZufW5gkeUAKhQuCL7ibNXcEhQ1Ny1Pj4YEzHm5JmLjCRXOyZTYqh\nnZyripY7MX681/N+i+zn4vHNl8a1DsRj7R5mGDiyk568v+1D9R5KJ2LsgxrM\nkJul\r\n=X/cY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5FZa+A6DatKOP4Ro8ZiVjzvr8VpwI8ZkQ3dzl7z0x0wIhAL6xyBWBaxrrsumF42SYeGeCbaEWRvlVlpR0DBw/Dbc+"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001308":{"name":"caniuse-lite","version":"1.0.30001308","dist":{"integrity":"sha512-cUXbmSTlfG54vdGeA7guriSSAmzyxMWoHNN/DzQWbaLkDlcxrTu0Ox+dA4f8J8/SDXes00oC6iTx+watQYoVfA==","shasum":"8ee68bbf226ce429297d4328977dfe0c312dd0a4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001308.tgz","fileCount":810,"unpackedSize":1478217,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiAKWaCRA9TVsSAnZWagAAibUP/jr/nskFaXC5PKaLaEBp\nAkcXmj8bc9RkU3BEp1DKFVJrlGOnoo9jCuDBSzx0T5TqJYrnsZMCBcpSXoqw\nOiwP6KpiCji7WiWcmQJf6v23VXhLARoqkzB3wnXDEg6mHY8sol1w1lFPTYeD\n9GkBS7pzyZN8UKxLPbg4hA6PpwyRqAVfgks2jdQFjLwmyB+ZbZ+OiTWRWr3O\nDc6w0L5/l/uWKunlPQUPanSwKp42ojZ+9DGjm2kyvRRPWZa1wJvY95EltfeF\nkOav3tFXsC7ZaN9DmnjSyWRpfwx1Ij+HHb4RnD6jPeqNWeT9O5PSHD2TkN1h\nvYOkWuY6HB6Dh0z13+eUnUWgMGV2GcGWUDlMjLjcBreNHkFztF3r89U8Iv8m\nQcq34Bi6u89Pq/jj0+ki5u6a4NK/rh7t6S1cQpArH6B8a9tIQg3/6tTEid9R\nTfhzEeKrgO/ahYaTZOBUiZlNTb6uw4n7a9MK6xcEF+I9/HY9CX/wmeex8FwK\n5fb2snW9rmQG7fu0pKLIdUsmD3ZuF67c11Wt6cScm4T9cShK5+8lFNDjv4lx\n4iKLybL364lAiZpgsTDG09+buAVNfQVvZKyzIsiqI1ajTj6YEUbqEkZbQSyq\nEB36ktrLJ+4c6hkfekAqADv4TySPks8K6QVA3j2da1g4Z0fBCvS2MSA9qBJe\nuvrh\r\n=9AkI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE/gsuKfS28wKA4XRUtu3Yaq/JaRHGsja8IRQDN6VNcvAiBtTJ6p41kQQEcD0E9b7yeiePRLM/FUqtw+rMPLixsaxQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001309":{"name":"caniuse-lite","version":"1.0.30001309","dist":{"integrity":"sha512-Pl8vfigmBXXq+/yUz1jUwULeq9xhMJznzdc/xwl4WclDAuebcTHVefpz8lE/bMI+UN7TOkSSe7B7RnZd6+dzjA==","shasum":"e0ee78b9bec0704f67304b00ff3c5c0c768a9f62","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001309.tgz","fileCount":810,"unpackedSize":1478231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiALJ9CRA9TVsSAnZWagAA5SsP/iCAkBGj1308XtuhVCA7\nPWJgaSC4WkcZqyocyINOw6mJwHxIXhoS3jCvdBmfdwm579txjmSYDTBPoJ/E\nmlo2l4pfbdauygGgKxgCizUPun2+jSnuK6rdW0Vgl9qmBGbXcLLjM0zrk/11\nGJgaZ42RL3cM24nIABbY+0wOWX+4PWDbFJpFDrdSnb+uNFXh3G0RXh8haewe\nnWf5GRM/G0oWTVmlcUntSwR5vj/ApCrdagCKJc/pxQZmHPRnWwwk9BkQQTY0\ni9R07Fk8chKVeOWn3iGfhoM/Ht/CGnUZj8YxPfdK7xltUp5lb21BrkMg8sma\nPni3qxoVKNdPINSnDB0gy4vdBKNI7mZ8KVqmD+5HawO3Ve6UEDsDj+a29cgx\nJm+dpKIWd8OsObOG6kveWBfYcwviEzSEwfaGCXFHNH/b3jrBSeEksJ80npQb\nVif7Sen4ueHNW3ug7oZPuGN+tRAWSek6wH8coHbdp4DvUyZtpgHoEq2fPcs+\nzQCVtDYAFCbJaKYU7nQcJtaCvj8hhD500I9Rso887UrjWG7gi94ZxUNe7adZ\nipqLNcyt4Elqm7jaMJaEAkOkcqDdhxONUizToym4FKZpvyfEeemZ7Dj7U1x+\nutOb91S0DNvWnEEhu1if3FNdf1Jz3oLtQC3+cxZ9ZHkP2Usdo7Iz5bT020+b\nHNDc\r\n=m8Ae\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFglfSbaorEJ94mkJy7QLMjk+oKNs190apIgYKU+cbaqAiEAu6GLyREzuG8wAJwGP1fS6kmmjuNtHR7e3o+t5g4qOLQ="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001310":{"name":"caniuse-lite","version":"1.0.30001310","dist":{"integrity":"sha512-cb9xTV8k9HTIUA3GnPUJCk0meUnrHL5gy5QePfDjxHyNBcnzPzrHFv5GqfP7ue5b1ZyzZL0RJboD6hQlPXjhjg==","shasum":"da02cd07432c9eece6992689d1b84ca18139eea8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001310.tgz","fileCount":810,"unpackedSize":1478241,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiA1V2CRA9TVsSAnZWagAABLYP+QGc300l2Or0Uv9uhRjq\nadcph3c3xxdmyJ84+6hokOJw5INl98lPFKhcxNCMZc3oaE4hjuXIs61tfJAy\nlwVaeIu1WS3fCQ5n+laUj+J/8XcqM6dqEeQnrkJPny/W87BJsN9xS1I4bz3q\n4fO2DYMn7J/1cgPnRZV+m2ebaZRLJRX9P3y1Z1i/JuURCABBsaIr7kANfeBh\nILHAS0YPf/EjJqLl1muFCubXwM7MLOzKBKlACx3/VSEwNvu78+MvKaP13WBI\nOKm0Vq7Xv9ZnbSq4btTfnXmwZlyR5nDH3wECePsWOUF08toNT432113+suT/\nigZYT0W6f2yHm+9fJN0arFOAioNBgto4EAC5WesHmGbbWQSrd+kGuZS2/fPB\nH24mPZhcKYLM6iFVyHqVB/bkEk4K3u84eQwMPIVnhQSAh77u2bMSRQt70hIz\nJFnyDKoOQ+CRL9zojLzRwA7wuj15TNuN5gLuqDMWUZQ5nDzSP7KuPqcWrTOE\nosjyEc9mwCIoqbpwqgOvsh1N1qWUzuuQP2pYHnOMPzu+S/bfknr2geoiiyJi\nvgR7743lGp3rIVbLBPuozKhgpZtIDzCRQG4fL5KMqcfbbkIAGaTyA12daGvd\nWb+PVQkw7b1CBKneRtPwK1riq1gSnydfu8Mmsx6GwQAxy5+CuyVBDgtkCwlv\nsYjL\r\n=m5JE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCad9cuWV5UXb9MOnr1CB480oxY9oP5lRhbfhNqyRlXGAIhALSkcgVAl2vtrfmTFO77CwaoJQkQ1Z8u7ZOBXzN1egdW"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001311":{"name":"caniuse-lite","version":"1.0.30001311","dist":{"integrity":"sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A==","shasum":"682ef3f4e617f1a177ad943de59775ed3032e511","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001311.tgz","fileCount":810,"unpackedSize":1479984,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiBMM1CRA9TVsSAnZWagAALDAP/0HEIQjQ/CTR977ipSOv\nR7d643J5KHerHIU7RvFUA10vqj6UBPhdKHmevK9iwVtMGq6LeCtCaeHOS1IU\nmEbIg8AYskGBwQRx9BhO8BEPYzJKBVecOSKr9qX5BfoD8NJGRsiCMT4voYJz\nQ1JXEaDwwPGTpn3qW0gNeaQ5GDOSSITtPRpXnQJU0df2X4qDLjCgt/iTigt4\nV9FcPwDgHJ09OAhHIGD/VitN/kxxZBE+rav/GSV3yD90R/TRHiXqZky66TW2\nJACjEUaqkN2ciPvSkEfRYg5i/OylxxDZym4Ceob9QXZe53+wdsXkB7QWQ56H\nT32xra/Y3Wp/Q48/VzOuo3YOZ6FMNvhswwMDi+KG2ILGgObNSYpzVZOcF6sc\nSDXc6pzABzigYcUrJ2MkMYjK/iPhHSHfXUaE6hfWjYYIMfUgoT5EcTZRV4nd\nBfyO5lvM8bznWLXZPor7acV14m3xAMrJ5iFjEMcwCAirm4f4zZq0D4TWTXhB\nKtgNWUvvbAEceC+mhW24SPq20toyTHLiTjI5l8SKgqkBXVK/d8jG/gQtkWAH\nA7N81DrpFoDD9ngZcUG3uZK0dlxF7BtlxQ2YvCt/Ekff+l7pMFYtMRTAdzn8\nmQNufZ+4NSmPKxAB+X2FHDBYvKMAU3uUnkurQsAQKuYkK21qY89hakOSokP4\nuKKI\r\n=hdQQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgpzrMXitI99BQiqgE5sMvGq9Efad4BvrkzIMluhu4OwIhALqvQHA8bnd7ooQziik2tJ4lhkf4ZSk07OCvIpxrS6H6"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001312":{"name":"caniuse-lite","version":"1.0.30001312","dist":{"integrity":"sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==","shasum":"e11eba4b87e24d22697dae05455d5aea28550d5f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001312.tgz","fileCount":810,"unpackedSize":1480006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCKnYCRA9TVsSAnZWagAAFgAP/2cRlqwEIruh+h3KDwce\nnw4WSAC9tZW+CQy/Ua1x2l5B1+WO2mz0IbKPzvHjaTxhaNX9C9/JbaVyp0Qx\nqvAQCmegGvQa1JiHQq4rlCut4UO1DXPLLsn0J5BH0pu+P7lLX2ZF0vRYbsMJ\nBfFdSucCsD2kA4NmpZlNTxtwnaXJOyYJVqhL9IONvL1thPqmXQ9ZbDMGDUio\n2zsxcGCoU0UUf9vqA9K867kNbe6JuVI1EuW+xp2/eTqlPHLAoeov9q53GL4O\nn8TQJAVSs8I/AiGq8kpfzTY1S0glRkVgMAHcAPR/kntKd28zKokTtx6XVjUF\nFgYtD1Om++/4TCH2MlgCjBtxS+fahnUq28dvYVnv2Sbk/oscZEEMM3ByH5Sm\nAVgGVqxPF+vFgCfEdPSh3661iu3b8KEKAA1cVEnzYKasPa90UCT3+B2/fH6O\nxEUS/NbQxt7KARUqNSPvFPvjljABDAbu0azmP9Hbb8iYdsXiM1tq52E+Tf5J\nYLOiYvkpQ+1Dck7mZUR5alTbmPvZi6HAC2uu+LqRBu7NTeRpsGwT7cbLDBvI\n4sQP4clb1+mEOyS2Mvq7w5iLdWzO9UTQdJCPgrW3Kh1gPO+qTSfGffZWRcks\n9qiJE9vWxrlLvKU5lx1Lz3ebxE24VLnnqs/4aRzbONpv+rzObAUsON/wiOfg\nQ/Jy\r\n=1ZDY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAYeBF0tGuad7htvr49ofQqJeg9CeHI89vZ8E4c5YKIpAiEA9QkV82MMMUFY0KS4gbjFSo9wsfYuEU5GJPvd4fqLMH0="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001313":{"name":"caniuse-lite","version":"1.0.30001313","dist":{"integrity":"sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==","shasum":"a380b079db91621e1b7120895874e2fd62ed2e2f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001313.tgz","fileCount":810,"unpackedSize":1483103,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiIafsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmplBQ//bePNMWUmc10dFjPnSkacfOWeycTnCYI0iir8biHvohfKO5BS\r\nJ2hnUovXBNvGBE6HQ5coK4NbIjHL8F9G7IpgXm26c3qHyZuS2KoEJlpISngd\r\nowsF/3Elb3nRoMGXY09IZs1OMY9RB0kZaahiUEeaF+BJMHwNHCAXQ23KtmG9\r\nE+xGot04+1IbqSCMAusqldh6Yn/0rWbxV3ab3Z+47qJyvHSAMRWEBb96COfd\r\nmvjG1UZ3gifFjanJ9f+TbaJgwugjzAyeb6b/sqqRDg0OWIW78Ec2KDVB7gK9\r\nxBv5pzoozYGcPW9I4Mpf1SiPGXSgcmYtebQg9EYMCengLneeI+awMBrRRxAS\r\nvwo+U7P4kcDxRRBhVzPSiv/BzUFLmnHTggF2QJExDx1sjlPKvBYgXqjy/BaR\r\nqkuaUOZszZRyu1FlCBKvQeXm+w/4wObjIOw1cvLCi9BHmZySWrX+a8BE5RL+\r\nY+mhqCmM461jt4bd+8Vt7LFfeiggndgnhLyO9h6rvLXi3N2v/eLZQZJMaGxV\r\nThIAQXiYROp+L2JF+uoJpED4E9lBhBsp0q6N2CNZQxjkj8qvd9FZSj6+0DiE\r\nauSKypxqyL8SR5wQt5uf3n7vJftN358YKLnuJaA82qEupFCuP8XP6dwUs5jL\r\n+orosrjRHwwJLGP56r1MEhk3C4FwvbSoumA=\r\n=+rhH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbdLxpLFaqeCOQ2M+P+d4sVGvzceb/xYHZbeHEZKsttAIhANphb4/9az8qOA3ARS5XgyKGx1RYmF3wx284gBRIDFNz"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001314":{"name":"caniuse-lite","version":"1.0.30001314","dist":{"integrity":"sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw==","shasum":"65c7f9fb7e4594fca0a333bec1d8939662377596","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001314.tgz","fileCount":810,"unpackedSize":1484791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJvz/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo18xAAgVpy5q+6DPX6qPpAC9ZbmP5cs+E1/UqvT9SpKl06rMCHOS++\r\n7Rxt+KgsChZMdzvzjZ3mHaQc6vcqFcN8uuj984Y9FB3/qn+bwinN+kdRjnQh\r\np3aCA3phgvwJva69/lGbP9QbDOxpxVQRJ8fe2e2vXZyLBLTmkuwVqZMqmxLD\r\nUjtXOKQhueSfYbi1ZCYmznGiWTYsLoxy/GUokcNsrohowkDULgsGyogEx7Th\r\nIImG96oA+OqUsHPL5rLDliTmLhMuxo5Gl/U2FKG6jVzuFNmwnZigdeRx80Zb\r\nlvIuUMm41iH//HgFUtDGPynbRvucEiY1Y9xgLg6T8cZf0FMEHlPBgRTafmGe\r\n1iYNpPqELx4LOxN5zWbpPYBNIDnU0bE+CzfMSUlYfyl4gYH6kn+PVoQZz90j\r\ncGT0KiEGuhmoi8iVqF6Rg1e6utted23/Oln/g44CvVeU6+J4Bl8Y/ifGr14S\r\nr5YOA2IR/Hu2xr1OJc5u09TLyTLTC9Eh7dMNxpZc0S6DhO7l/jBvA4swxuw/\r\n7xSpFGfMvVoIfM+LAEmnunCJElEl0fn21k5MPjDem0Wb7wyTEmVsLFGbxyZF\r\natcNchb/gWoHRyEgOajMCVExvdzU1iGHIsVtpuw4NBiMhIl4x/OpoktsC7TG\r\n9/JppSy8dU7mYhcZekY9TYyg2KZj1aAKgRk=\r\n=H2wN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB8xCGRb9VEKaxovpt+DISbHHNm4nUqSrnvzImoX5hyuAiA9+5WZpgzvVruhRQykzVawwO53b/aEy7Xz905Mb0q2Rg=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001315":{"name":"caniuse-lite","version":"1.0.30001315","dist":{"integrity":"sha512-5v7LFQU4Sb/qvkz7JcZkvtSH1Ko+1x2kgo3ocdBeMGZSOFpuE1kkm0kpTwLtWeFrw5qw08ulLxJjVIXIS8MkiQ==","shasum":"f1b1efd1171ee1170d52709a7252632dacbd7c77","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001315.tgz","fileCount":810,"unpackedSize":1486528,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiLZTEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrgvg/7Byh4CZPXo4S3GYFuK7Xxnm0aaTEvOYrQCzxetRnXDXOZoARs\r\n40WJakyH0qQC6VeDLfnjBA9bTMqTbvMru5L8dl2tophYGPRz8WpxVAY9jb2l\r\nHMrhzZnjSC9YLWcwbPpe2+oCeWbgChPWmYrsBehTY6SUvFWvej6c6o6iEiNz\r\nB0zWXqTkZTW5zogo/4ra7LMMFpY3p4x5+xKfZji4VSaDJqW+AJtQm2OEwZMJ\r\nHYbS8mIO4EZ8sR64Hx7X6QnwTBtUSHo4RI5mJc0nQo8dOgV7UXgxwN4dSi1K\r\nhKDTFFfVSl1W9UhV2jbLfFwPdZ/M+vPEigHDO5e/bCM/eJiF4ROvXz7fWruc\r\n5vNKuVl+ST2OKMZzPTU07Bbv/FGQ2SBOPyv/Z762LPfnPmX1sRYqFio7jNYG\r\nHD9RA6EIrjlc7hHyO6oPChDPh9bvcGiXQ870teie5qqpu9BLGC1ln6Xq/L8L\r\nVBO526uwp17nLQ4yJEBzJd7qHsmBeOi56I+WQfmVRnGwgvlIrApe4S/H3NnZ\r\nOUkqLaLWRb6Wb4Gon6Guw4W1e0Kki/Pv/Z/Lk7re9P4XQnaPOZ7yW24oopEk\r\n2iwtpmnlMKWVhrPKPnIyobMaJRzbJUOos5YcjLscAKdJmmOApQkZxBDQ3eA4\r\nQUDUJ5nt+lrme2jP8LLdeaKB/y/J2RhkOag=\r\n=p5hV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKoNHkSUEObrbJBpLIAoGRfgJASyFE0q6OeBg5BnUWUQIhAI3NhCCHl5TjKlR4mLP6L8wulVL4//FICWMl7JNWeH5D"}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001316":{"name":"caniuse-lite","version":"1.0.30001316","dist":{"integrity":"sha512-JgUdNoZKxPZFzbzJwy4hDSyGuH/gXz2rN51QmoR8cBQsVo58llD3A0vlRKKRt8FGf5u69P9eQyIH8/z9vN/S0Q==","shasum":"b44a1f419f82d2e119aa0bbdab5ec15471796358","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001316.tgz","fileCount":810,"unpackedSize":1486558,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiLuYgACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrM2w//fH8FVGGM8Tzm1YCGENQiKjvDIgjNmEL+r0hOwmXnqG0WvDxw\r\naNAbgvr+gCqrIXApCQeIqevNq9ri1WH0gcDPl01Pjd3IDzWbHxRWA+orIT6b\r\neiHfnina6bRfXRk/Lm7WnxYf8h7Slm0Kyl/coEzcZ9wZwif63AM0Id98lSO0\r\nm9yQwIuBj/g5QAqvHfp9UIbLdI+j0CshDek5piCIpJS6KMyeDy99k7DNmpsu\r\nSvu47Y+MUZGMehfWt45zZqcStidHycGuuSwuu9n3unm8997yyDa1CPVRonT7\r\nYNCi/Mk5U9ap6w5PtpKgYG8Xced1EbMF1NL4f01PDRt4e2rGRaU5X1ArNoU+\r\njE8LbmygvfJ7AM5DWWt9G+vHnoyv8jv2a+Y0gLTgXHJK9A1m/sB7xvVM7YR5\r\nIpjQE2anAW4ZGVPxk0/0A8MIIK1crauR76gid/y++UcnxOMvr1qhfjx3+9+F\r\nvxVj8/98as8H1etNKBOFPjCXJ6e79W0D8EkTuhjWM3ZhlDnaH0HXmvfjtmM3\r\nV7ebbBOpLOWfDH4AQXBLRZ7Zsb1seNMKhbXWjsOCrThYEMnmcIfXOGErs5bc\r\nrL4BAnR9RyrXfj98YL/MiBTuuTRiwQS8FiYi+JUynQd1dBZLFyI3nQ+dyZ52\r\nHz56VImr9J0QDfMujZ37wIyXg8VM6kLkTkk=\r\n=gJjJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChBaoxqSLVsuSo5tNaov9UlZEJ5Qqg7/FUwrqpWYf6eQIgcMq5ml+fzLlknqi95BHMMTGPCfQTjnZWrNsskEh4AXY="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001317":{"name":"caniuse-lite","version":"1.0.30001317","dist":{"integrity":"sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==","shasum":"0548fb28fd5bc259a70b8c1ffdbe598037666a1b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001317.tgz","fileCount":810,"unpackedSize":1486564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiMBvYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq+yQ/+JhtvnmARBjzEFXE/ug9tQ0kQGQXnfsRgJGsmJI4sYoobaGgV\r\no/rgr3VeGMFPC13cXmHtwtB7dWg3PFLzQun7AANlCUDDnnh45tFqtaWLDnzH\r\nkEcbQ9RUCIDAfX1MmBFVV50JTVTudWpts6ZLnEtaXrK5NCk/8/Z4krGcM/hl\r\n/mlEDKWzhyhXa6zCWY5QgNj9fG10vGq77S4PdJ6Mmy4iV/KhS+0fUBvfSZ+K\r\nstG25x0WlFv9Uv9Gwm/G5/tpJ9zmrJWX5FRmXKhUEKm0F4mzi7BSTM5GxRRu\r\nEpgPLe3G+CBE8qatoELVqhbWQgXMyqaJI6rh9DSk1h7KX4q35hRnH0/GJr5m\r\nI7K91wndtyPQQMBd8iqzYqijTTADRCS4jlqsoT3/zSYE9Qe3iKALHQUk9tSN\r\ne+ZuW9ZsnhvV7pJ1d4GzOzizgo89TLljs+40HvOPTvLaf6GxnAenqOZ8ckgb\r\nQhwZzZvz5FEwduwSBHG8eJLNnidIBXv3zABERXm+RP54WWmOYekFqcpu+W+T\r\na1Bkq+SNB9VQv+GED864/xSvOZhd1nUTkNcZwIR3LJzIWhKh3pFjB4cpVatQ\r\n/O2TxxY84cp06l1FGHDfrlohQFOdzFsxUvA9JxgDICNRh1APJUZBBgmL9Qv4\r\n1e/d620e1ZaVy/IMln9DxufErKfrEqJvXxw=\r\n=OM7F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC1zikw7xYTf6NcJfBR8jmsiGbykOsG6pW015Bzer3cGAiARjJj3v6shvj2dSzR3IB7LL4C7B8OQnn6VC/OQxUc7pQ=="}]},"funding":{"type":"opencollective","url":"https://opencollective.com/browserslist"}},"1.0.30001318":{"name":"caniuse-lite","version":"1.0.30001318","dist":{"integrity":"sha512-G5hJuNhAPwOsmi8yplHn5k/HC/WTMGtWQtBx6HqaQFAv6iFU+ulBgMevh56eG0zDd277b4Yzkm6CmbbV1wVzxw==","shasum":"8c67d022d2f06e4ba8445af4063b5a421b0dbb8a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001318.tgz","fileCount":811,"unpackedSize":1487991,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiNWGbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoB+w/+M4c/8XaYYodCn3nTXWynb653ZZQmJnhdJKGqZXt5CjWgV7TR\r\nuyJtgEqpvZsyWCJhsbmY8Ll9bcqpeY0FmLAVOHk8IPlzTOyZbkmO6yuq41Z7\r\nmy0mFtvYjFgvWM4VHJkeQVZAYrCWGK9K6VO10vwEPLtRKnI9nwLNXTvKs5dX\r\nDj65TVMJY+jATTh7rWjWX6kreGxPiBhqrEO/WtfIOIQpK+ne2tuEHCeAtw2i\r\ngiswp+mk/3eWc6ESzkon3BxrSfO3oXVoYEuK55ueHBBeYixhZOE6iCKqqaID\r\n0NSAYSvZZSPCwyM1m81bhlpNbhAkwVvwwbIfiyuMlv00MJbTFrJVfTxPiU5J\r\nswyj7rfwzOKPlKcHohd4sikGx93ltwURyT3vlj0/zDyIQnizLitTaQBRC2RJ\r\niLfG4MwUSTtzEc1dAAYnknmUmi0J5xGOFL1EI/tA+BTwgTHM2012n+3jvg0P\r\nB8Pzk9xj8Gu7AS40K6UXmvof/pB6Pne2n0o/ROUBq1JJenmfRQO9XgcW556n\r\nzJgii0PeyM8B0rEzcCNwycsGSKnzPQyNB/SmRo/klXtsnNeg80/5prY7HKlX\r\natsFlUew7WZnSKFqhKqJN9dJYPHD0WO5GMHfcG2lPo+AvoKeX101LH11u59n\r\n6HUOj2LZNOdAAGCHpP1BUdZeFKSqStGe4sk=\r\n=8PFb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWlxHKnXalpUmFAsk9+31LZNBC25X/4B1r7mMx5vqdywIgfiIAElvjhXRY18YmmljEJuXVl9Vglla9/lTV7k46mcc="}]},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001319":{"name":"caniuse-lite","version":"1.0.30001319","dist":{"integrity":"sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==","shasum":"eb4da4eb3ecdd409f7ba1907820061d56096e88f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001319.tgz","fileCount":811,"unpackedSize":1488007,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiNW5vACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrgrg/7BJeEO4YOkpznsqRCQwKcUCCZ3MneBldd+en6D5Ru6X5oPR0I\r\nQLBw9zXlI1z9kNLd4FU02A+ib2pdh5Ta9wvNjHmplgc6zjPNW4B3DjgmNb7M\r\n+QCyyOz2dZhl4DLbO0ZliYJuMR5I1YwdEKuTKLeGUdPWS7ENdQ6pOAJICkWO\r\n40A/848PPwRkXcJEcodpc89midRc2p/wBQxe22pNke1jHAD5ecfSRvDzu6d1\r\nXxRbmzZpbJDD9HZE3tenVIb06QF5N0uqopz3G5upQ75dRSTjSlB3CFg23cfj\r\nhyKxbDm/ZiNk1HPv357TnLJn8own7+GAMOWZe5/1kd/aCt7VtPWoDiUtHCkl\r\n4cRILMlMjOc0UvzZh7pOQ1C09VS2Xno/u0XT8TNbNhJGJLyWbJ5PvMhXk1Vg\r\nUBJuZH5vUlAPP0/I2uJuR5/zp1WPBJmKxoRKs4iWqePNy7oHmUdZtg9lzdIF\r\nUM5n6FSne8Gr6YjYGBf3VD6J4MTa7Fm2OtQTAx6WnBtLcKaZWlUZ8RsArNge\r\ncfkWTHAe3WvHm029kIUR+4DMXe7Ji7W34LVFkyyGdZtv4jV7aytWzAAq0bkL\r\nk9yJ/br9olbIOEAUJkrbyHPOqcVUvOirlUZ4hionyUfUHM6RIkE0/peSJA61\r\n+rrl4rm+E8qi78ngy4K4cye1HYbv5ZO7b5I=\r\n=Rm/s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdE41QmUttq4sgC5FyiuWeAUVUPFGzCVwFPEfp7QXUJwIhAJP9d4shi6cBOhipEO9WxMxLVG26xxZ+Wg626p1y0MMK"}]},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001320":{"name":"caniuse-lite","version":"1.0.30001320","dist":{"integrity":"sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==","shasum":"8397391bec389b8ccce328636499b7284ee13285","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001320.tgz","fileCount":811,"unpackedSize":1488019,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiO/loACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbwhAApFwYHTRoAfoo859VWTGn/91T5NmOtkPYOCzYRDz9knWN4Fla\r\nkqU4s4r15mYM4B/N/3fPwCQwXJcqgrXiBwuzy5ntlRcva6JSzgOINvplbikK\r\nmMbheEgecTuNuZmqPFRHzBYLvzkDXVC7SZJtgHlwRFt7iFrChpfH6BgvaPJ6\r\nYV/QYczKdd+EuiUPyD20c2e+rcEsct8RpL4WlfydgIER9qTY6XpOdhiL+EN5\r\njOOAkqCfpymH3Xl13bI+ozS9dzBih8/t2LEUL6qDdp8ziRXrH78F4NQ9R5vq\r\nVmyga+EO/PsOyfXZTqMdYBd0h3X2XT9eRqm1oCH07JPsrY1kFHWdPZSqHOne\r\nES1h7Wq/D8FyDP2QC3PTG0EHU914QRqtllGGM5MJqoV2MOWnSi6MAmhe+JuZ\r\njXnw5EQPOwik3ULh4YNxdxvikWg3dkDv4CyG12vf7ArLOy0moEpxm/956EAH\r\nHQkc2yu4dWfirpIcp9nWKmUyjHGoNHmqLMEqXAO3m9k5WEVH5auJRIw7h+y3\r\nohIknPxnapNdZORoKCxUqYlFymRWjkss8LqJOY7MNDpQnz6arRXr3k7Btu7Z\r\n+3Ume3xgr90OUkk9gFQmKEI4atRD4YVDI41K3EueHbCMehXEo1L/0Za+/wHR\r\nE+MiksKz3Vrh7L1Vsi49BwiyoEHp57WdOEY=\r\n=/HP0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAEmhPjdEJLbTFTVBh39nJP/nSVHM3dYzlH+9bg5aABLAiABZvb8IYxKdQ+nagTL8Zud1yx7TgbNu8+xhzjZ/ridQw=="}]},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001322":{"name":"caniuse-lite","version":"1.0.30001322","dist":{"integrity":"sha512-neRmrmIrCGuMnxGSoh+x7zYtQFFgnSY2jaomjU56sCkTA6JINqQrxutF459JpWcWRajvoyn95sOXq4Pqrnyjew==","shasum":"2e4c09d11e1e8f852767dab287069a8d0c29d623","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001322.tgz","fileCount":811,"unpackedSize":1488025,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiQqzFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpKsw//U8NP0dZJ1/ZRM2kUcah2Jt7vMZDpVPehrQ+M7xPaynfveUkG\r\niYLbqw+nRO/+HsH9ROtNE6bhxJrjqSSSTFny3OqS+p/IAQXwDQSr5kRrpr3p\r\nNJ5QHWc9pvisuQiwyzLvI66B7CpkVXYZeum53zrPxQrAGegIGviA6Kq0P1Oa\r\n2XAoWLaV0zp8yfR+3tU6cqr7BtkYQj5/fuQHDx96pzvH1XYCdY37CEgtDgGz\r\nHRK9igMVwXOXO4A9yvS16pwVrvKNrBd7a+owOTf2yfIGJdtznAabDL1o5MFq\r\n8aEuYVwOQUi0qyke1MSD/o89ZdbAYqgmiN2MraqVATLcrSWhNzy+hFVKKBCN\r\nZChms+BtanwoNMs+aG6B7i6dQN9IJOPUXVRcvd3vRk61ytbWBK8AnXpymQC6\r\nYox30fH3XoR+UBLYJzN1x1jBzZGsTzeVRHkdFCVtmzOAX3UrNUpfRni9bTHc\r\n2mO80mVtQm6GBAZ+89dIsKOliDI7lpxkKz318WbWZr8ZzZuskANwRWtBFVKk\r\n7keNcKzKoAH9PQhI7C7xdIE5fjBxklwlS3uPAsdvNuiYx6SSrXt2ia0amDv6\r\n4EeBT1rMxpjiIIq650YEaCMyGTqdAxcFTtKqnSPRAzWAPQFhANRgbgW7zJvW\r\nqDGWYxwNwX3c3YXtuouMQPMoJ+t4kcfTFYQ=\r\n=Xgrk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCtt1D9IvK5Fsp1M699B3N6+M9tCqp9Kaqmoahv9dXL1QIgK0CqxAIqXzqS9yW+xg5IWxstJ+QOqPoCulRy3x5IvT8="}]},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001323":{"name":"caniuse-lite","version":"1.0.30001323","dist":{"integrity":"sha512-e4BF2RlCVELKx8+RmklSEIVub1TWrmdhvA5kEUueummz1XyySW0DVk+3x9HyhU9MuWTa2BhqLgEuEmUwASAdCA==","shasum":"a451ff80dec7033016843f532efda18f02eec011","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001323.tgz","fileCount":811,"unpackedSize":1489727,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRigXZV15qPETKCTlyKBg2edmHUCORN+KoIr038Sb/SwIhAMMHbI4sjqTPTUN00lzblelScuurPqNrgo2/XyymC0Mx"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiRUBwACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDSA/+OlETR4GfbE3tKPgLvaFid/r/jUUP1QUQJiHNDhJJCWD3gDu9\r\nlVmOZbTruTIYU1evhKeYvgJSwfWdVl8rYVv31UXYfQ3WTte7ailRkyIilX8s\r\n7kkQ5SDaMH3nbvfxGSnEgLlvXofio6xcb3SHrQET82W5VJqK9NTZupfOl1DM\r\nVqm7lAU2ID8JmlA4sIb30igHN4ko1UWvPSENny8G7IAagvWfGB/BEB34UyAX\r\nD2nDETmTZwnhzcShcOZFzKoIOGRHj0OfGCcHEjaqwg8SunVhRv9FVNpFNMmt\r\nuh46b1O1LPiD5eA0Xe3c/UEDGQQ0SJwmrvsqTBHbxkpqCXbRAEPHx/Xmp65O\r\nsabauvUPkWiTmPbdlfRlSArGWU/A/+KRJRwFdG7zPxTgqSjgmhRA/Vb/d1wJ\r\nP011wj84InseobeVz67mU3aBrVoxTT8m6p2GGcZQvp7T48RKAS+g7ovNZb09\r\nN3OCCTmufUsDPRjvKBeVp/s8FjXaCnXC2cW37eTDJuT55j/TGL/OZjoRGxoF\r\nchoRqItB68EX2jpkZ62bv7lR1qlXHt4DCLxgFCTpmaBo55CMy12uVP5f+Gaw\r\nqvdturIw8IXSXWEaiumDLeGxwGOoa+zjnh3z84wrvrTE4S7sg2+SbVFq2kBa\r\nQ1GaU2d8ERvgZfCJPqxzOxNTifhqVjQqtNU=\r\n=YEf2\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001324":{"name":"caniuse-lite","version":"1.0.30001324","dist":{"integrity":"sha512-/eYp1J6zYh1alySQB4uzYFkLmxxI8tk0kxldbNHXp8+v+rdMKdUBNjRLz7T7fz6Iox+1lIdYpc7rq6ZcXfTukg==","shasum":"e17c3a8b34822b02d5d15639d570057550074884","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001324.tgz","fileCount":811,"unpackedSize":1490275,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwbuCFjDZrGsX3JdynMe8jY9ALjocxabyl9F6wlMUVIAIga6TpkJ3xmtqgWeOsaT2i7bxtrJVCqtzUBDONShE6MHc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiR/KNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo2vQ/9Hm/OHZTqvtz8ZitlVF6XImYv1ZjMaqjSSgxDa+bkCsJyDGOu\r\nINtUnsoRAwIx75PrQJxb+/D2mosZ56/1ZhbK9FComQ7xhyvTwI58v6/fbjGw\r\nlJetT3DUmiw+zArW7tCJ++Ipr/nqY+Jjx3lacKgAoc7nn2dFCBryy2LK6AV5\r\n9LmH85Y8XLv1RFGdghT2iiHQVR3bdP5s3Osvf8FJOLNTxLwRE4LAY0iDuh7e\r\nTZtWGqFT75ufv5g1iZnuMzAseQb127cI0Rx+HgFvicUimYxn9RbSwj8cgmHi\r\n1ew7dI2Nh8BK7VACR2oVpBBNTNTNww+lClZJ7Lu+5k9lIh++cfQMaUBB6IIm\r\nuH7fyfPsnmkFsWoFOp1KSP4UNClVCQW2m9w28B3Fn2XAwVitCwiKxiPlp0OY\r\nSzkTboBigPq8c0zj/5/sFyBairb8JAOMjPk/aLezXXus1pDXphsM4BZfgd+D\r\nGRQmE5fnGfA/+8kAaMbBCP7CVUK9TvFS9vmYeUqEnM1tcdRUttXyGxz0Xb4r\r\nYFD6d3cpLyejGVPJRHyfXta3bH6AC9AO8sh9WP14WsvAKEfwLeVyp1caIX9p\r\nQFARWyVAi0zOpGrEd8xb0UJoWBPVRvaADDIn0+5pTLH12IGywhl7ERJf4AWh\r\n6EXyotYnL12fS8zPpp/uW7dCYhSCf2dpOaU=\r\n=Xxcc\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001325":{"name":"caniuse-lite","version":"1.0.30001325","dist":{"integrity":"sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==","shasum":"2b4ad19b77aa36f61f2eaf72e636d7481d55e606","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001325.tgz","fileCount":811,"unpackedSize":1490272,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEDNLbrM6gJIGPAtlrAWhUWD1z0AjB7iTfEp29lwK5pSAiBbHZENqY38HUWRiv1G4cyvaQKw7yK20xE/3jMDj++gsg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiSpYBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqHtQ/+Jfku3/79iurt+sK4lGbhrp2gNuS9Q6mp5egJjUpMOVD9EIoB\r\nZ+Gsrd4p0uDEClNsyNKwdKxlMxez3oQoup7k4UqSnxJRP+P4xWjFh3aS2Yja\r\nQ+UAUCkA4wSzCg9QIQ+Gm+ECWe1RmYRvPYwjx5iPQGEMNEPkN4W0oApe7TB5\r\nnkLUykR87OYq9zHQiXvgnU+s7VA/digXulBs4UB36zKw/o2Ee4vJ9EDzHfw/\r\nuf+NBUHF0NCs5Y0FMmgT39wFOn283YgJC8D8qOUbBcbW+g44BBy9FaMlxLo3\r\nbV08o0R5JJfKOE+UIfxkxERpW2qlGLri+P2wc5aYqVQdbQ1dQiE36GkTYZ8b\r\n3FiERSg4ke/Djl+/z6xech/whEZyogO3Y92wBy+JTE+/OW9bF6bzX/WWPC8t\r\noC6ruOr0qimb0/XA6ekXD0qpMbtYyMqiifiPEUo87LIVQTPcHPVmWXAAnvNc\r\nVIYz1lqS4l7vpLsGTS3pmS4qyjqFJ8tB3E0V1hNx6cB+zenGOAJj9rqgjbmO\r\nVkUV6vJir+VHZX6Qus+f1GXwQcn4ndGdaIpIDUfOhU4ULnBBT1HrvhlbyhWy\r\nV6cS9h7AeHfRjHbcGyO69VRUAeNXvsYA0hBuPRcDu1L15UykDzpOHFTjWzXi\r\ncA0ayBj0uO3G+2HRj4XgGKXLI7wAMUmjwVM=\r\n=4ABy\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001327":{"name":"caniuse-lite","version":"1.0.30001327","dist":{"integrity":"sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==","shasum":"c1546d7d7bb66506f0ccdad6a7d07fc6d668c858","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001327.tgz","fileCount":811,"unpackedSize":1498692,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICf32A0hOwsAGLoV/aRtxtvx2BU3HbcGiR1ksRrqYJpLAiAFw9PszSuTA5OKb/q8HHDp3miAcWg+rndt6XoOOhxaLA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiT8yUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp7uw//Ywu1yYCrDESFYSEnshzSyRNzopVmRvuM4ANzmJ7L5RpUtf7M\r\nC9OYR5rMcgfrXmlzWZJMACo/BU1dFATqMEFPqgvca4gt8P578Nawn/TXVbTN\r\n8ie73wSrFL65O1S0dS2fj/ufS+X2YspbvFTYmGqlNDC79Wz5Myg/yRxkTO9L\r\nu5BJjhSGicA80YCettJwUsm9x3jMR1EMr+0I18gZFZHGP1yFnW2NQAff6sTL\r\nFWUK6rnXf53zgINTiTCCSGD2a+N1RkpDVDSYq2AJFm++nu5WNkkYeDjVuLxk\r\nDkvo6Egmf17Lq6wu7lx0NS2UySyFiDaDKqyFjTW053d2+xGlJkgJYdZFDUqD\r\nkQ9bZku6tdRxh0jy6ZDoJD4s3UCIbH0pVeNvoHzFHKKJxhfpLzwqygBcf/h2\r\ndM1GANQd5Vha7Cnu9laMJQO2EEGzO/Dwb9rVvGJUMqpECqgkz49XJ2GUSUrZ\r\nrDpG4HzszdN+Gm6mCSFjEWdmitA9kpJqlG5m7b9nmCh3Y0HMLZzAVdQotTAh\r\nmC+CvBUAEWMmD0xpCzcfCh0ms1ge2hM1nl+CA+pROGWD9yqMNZAsN3bGN6ne\r\nH33ERsYz+ciMrL0eTyF3WpgUnm7iQ9QC0b8uODadzTso+oNyYTwwrvjkDgaS\r\ncOmbVXDJYJ59o5voD0S59PWzNkHFJdTbxqo=\r\n=Ycb0\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001328":{"name":"caniuse-lite","version":"1.0.30001328","dist":{"integrity":"sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==","shasum":"0ed7a2ca65ec45872c613630201644237ba1e329","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001328.tgz","fileCount":811,"unpackedSize":1498710,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE4LqaIX/aiLjQ7oKDveIykpgFcM1r6ujIAUerzHiDL8AiEA2KhLIet2KFObj+pU103EmPQj9jTVqix5Q6RCVl8pbXs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiVQYCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbSw//YIB17jKpB0dqdQc0Ud2pq2eSsmFu7Tr1ifrCHpTjrSso2BwE\r\nXNrvdhJlfGgAaHVRPC+aDi9QpsaxNi/BEnEw4DmoonKr9rjN77LnYeEltojH\r\nc+9d9hM8W3H+SGbJHjkRKX+8aS/FPoFPmpX3Of827v4KXSFhDnrWorz2ARTm\r\nP9ARSFRyw2eC3K997SogYS7Trl3/6QhDJqKSGZMjhFrdWvWH/2zppJxBPzyg\r\njYnMSz9e2mg9uTM2+POFXVPDwVqqnKFKwYpO1b761iB00cYjhwXzzlQ4v2BL\r\nVJVujXOW8XTw4MUCI7WPIhRks5mgxi+GOuBWprC8sLy2KKdcZowWPLBayxMj\r\n7FsJapRTqI+FFVrIWEC9ZSG8Ddy8JHePzB899iWneR2jiP6r8ThjfNOYa8Zp\r\nJBjFm2e7UYTs2Zq6rYCI4U1YGR2TP8vuHs/IgrT/DOpGmsf/gxYHmrYsGgRX\r\nBkXRgK526f+BdgSnp3SDsdUs6kP8UMJphWSxq/CqSrYlXFedRQEuN0aWHGlv\r\ntA6HfAcCZ3FiaKfHQXhjWjnY/o3iUHT69C8GyCKQ+O76QymniZQVMfpDgnwq\r\nyQ31G/ltxXtowp+0pK7VJSAXSSdku+B6cm3IWmE5C00na4yCf5HfxIrInJXm\r\n2Idm5mJxk0otU5oWRJ85Ukk6f9zNYceYIqY=\r\n=65s/\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001331":{"name":"caniuse-lite","version":"1.0.30001331","dist":{"integrity":"sha512-Y1xk6paHpUXKP/P6YjQv1xqyTbgAP05ycHBcRdQjTcyXlWol868sJJPlmk5ylOekw2BrucWes5jk+LvVd7WZ5Q==","shasum":"41048f2a5cf0c3c6198f40207cd323388b3d4399","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001331.tgz","fileCount":811,"unpackedSize":1501576,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCXgp7N0t3/NT5jLwfUwy1yDgEcvS7/8zxFHqdRzxRbFwIhAIc8krwV3uCnd2Yt9+EZECZYvW1KB3evZQeMqKsxtqoP"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiVmP2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoFQQ//SEAf8LmzVwhDj8JLjgLei8LYoV966aA0v5hGwqoinszDohPJ\r\nn87aD3R2XJWJ73CbnGv0zslrg1+oNWgmuMRIaqPKrCsOVlMA+cwc4Q3fBo/w\r\n+WkKNvqBM63KFlMWrrDyUJazLtJjO67QSoVie25G95g2lbp2HNpBm+ZmAkch\r\nkuwX/+tua/NwIFthMfa7U7GetRN0/rwvHdeXCJYopjztxlJLVkwn5bh5iN7Z\r\nxCUBuE4dshUuy9t9vcatvxZaAW6GIPjhnCzWJmVuTruxT8uyfALnh6PRxHtR\r\nHDthEN3gOXMYs2/0ZR9kr+cxbbQk3IXOLT04rsh+PoQ3FUSd6fEQ3uXMl68Z\r\n3cOH8BU08nmOVxemOD0ofs6L2TeZdkPaoaZ0Ql9Y5+kH1wyImvAZUnMJmxmL\r\n1oqnAAoiYHslc0QxkEWmG37B+2Zi+91cRM6+AiTFtTFQ1G2ehuW5HOtpAzQB\r\nKjR+kop0/MiAhgi9p5da+v7TsxYqH7h575puvbgUXvc4jAZ4FfW4pmvlwulh\r\nnQNlq7/JE4mcaHMnUhFk3gaCP00hutBYkCeXd8N9BXiZFXcfRVeEJrahqrme\r\ns1nT99TLStZMN3EkSR3MkxuJxx/h9bnCedyB+phTHUS6Cx+pE2eQHwjpt9GZ\r\nIaUyKtmPfBkzFuOBjaxkGSvQOoBTNQe4908=\r\n=/HWs\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001332":{"name":"caniuse-lite","version":"1.0.30001332","dist":{"integrity":"sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw==","shasum":"39476d3aa8d83ea76359c70302eafdd4a1d727dd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001332.tgz","fileCount":811,"unpackedSize":1501582,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGLqNRvpDtCE19+Stq8GZB39vSEj36dTSuk2gpRSTG6/AiEAnz4tyNS13pxC3tmbYl7NQbhT3E9NrkcISxzzWN507/k="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiV8UlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoEyQ/9EcRxZgmwKv4hhHDx5svyKxQ3cQ6X5g9bOXMkckO7cRfr1m61\r\nNgPFf6PvXzGp+fEqgxvKzsMrx3bjPvn1+M6EpiEWMhjAwL9YRWRx1HNXmzzs\r\nZj/lUvrJ5eqJqADyWHSUrakodSa17rFhXSjOSaOHjfiv6o/buCSNkgGaYCDb\r\nOCgsVMScQWui2EG6MTS0oprYmEQfTezfH+LT/cSr+mM2eEXtUcVWT3iENEww\r\nYqI132Cgrd9J+cOJg5PxvxezfEf6wCRAYRDi382NoGOFbT1zRX0hSB5WRUa3\r\nU164/w224uE7ZoVCFMkR2avuPJxHTWvYVmFY/4KQZmdziN1LHmUj0fmJUHeh\r\ndZRtBuJ0yhqGIWREs2pC7qdflUCPZdA1nTDJ5SsOCNV9qck3N9Y9NCnh9Z6/\r\n2JpyzTFpYU9wg3Vb4Qs8TlXBonjhK/7ruHqknqqovovgl00AjAkIl5+q0LA6\r\nOOD7qiRKCw/P4A1N501RtYmdTaD4VaXSndDYjzseN712MRrPSTXssxipuLAD\r\nK77LUHu36ASuVh/4JmtI7rqaG2HdPCuTEVrSlZ+iACmckO25JjcTe+Yqw1VG\r\n136Ms1AIsDZM/2vX5QicloCmCuy16yG2XN+MpzqOjpj8EXwUZQRBrHY37VEo\r\nV8GUJstjCsB64RPpCo0EDow9Bztft5VxT70=\r\n=igK8\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001334":{"name":"caniuse-lite","version":"1.0.30001334","dist":{"integrity":"sha512-kbaCEBRRVSoeNs74sCuq92MJyGrMtjWVfhltoHUCW4t4pXFvGjUBrfo47weBRViHkiV3eBYyIsfl956NtHGazw==","shasum":"892e9965b35285033fc2b8a8eff499fe02f13d8b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001334.tgz","fileCount":812,"unpackedSize":1509100,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKAD6CQq7VF6P5soOM/RdQXlQYG5ZwnZ5NBJGR0r9u+QIgUbTq3iAZVV23/wX9sEZ1x9faoXFkYzhG4TmWOpTVJlY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiai0fACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpOEw/+KiBAmEX65CXHz9Y3ldpJ46RJECoQogXacXN4moYfnEs8Q6BC\r\nim49K6f+gt3b63JfNZootQ6HH9gbq6GXjwZdEs+X2jnblsQK194mlkQdYg5e\r\n6+yYXltLS2AetRZLzyCE6tbkE5F26v8lEDsXoew9rQn6un1SRzwTgpoEmyXV\r\nvUkS3fmAzYma2PO33huyg8Yu0Wpp97vFohJBNWeQTuup52qNnK+eKVI6RtDj\r\nSmR/K/J3XgwmceCz35v4OgrPF4t15yUxQwMuh6nnXpPuB3xbty8Njj4Lijud\r\nb5gcACSV4g5pgrqVrI78lO3OFSLlsaRu8fG55rskFzUzAtXO5YMzfv39Z6h4\r\nFMo2yBhMOXFwrV7GGcb5On6d5HUBjU2JcANjLYUg5bXdPVwrMZAwUUlwny8j\r\nRTjWUZEQMDG3XOjqp7ynM8mDnbrqn3K9mKiJECpWlaeJ3d3KVkfryssPo5Zh\r\nvY9HsmEYQo5SjR2fHNiO3n+c+Ms5FWBjihaJnUrMGUyATPI6vuaRtMVaOQ2i\r\nUsAtpVr6r1Tk0uE/imdKwNL6NupbuMPMoVf9jbeqVagR9C/kOWCZCO7PyXCX\r\n7I0txAmWuplZqaE059f+bSHQ+gVYExnm5RNlTsZOu97qoIQU9edtKQ3J0qtL\r\nxBCHEcwrK3kaePbbs2yCDHfNwuW2NkTWJ2k=\r\n=TYFn\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001335":{"name":"caniuse-lite","version":"1.0.30001335","dist":{"integrity":"sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==","shasum":"899254a0b70579e5a957c32dced79f0727c61f2a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001335.tgz","fileCount":812,"unpackedSize":1510792,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKN9yR0MwY7iBxQpLVZsRk6CfhXoVT7or86ryaJ88TpQIgYHnL1Pq8nfnAHsv5ycJcsOl06uziY7ZO7rf4f9KLMwg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJib4BVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqQPw//bVIneF7/P9t4jlv005NGa1zt1ht1rhvcy8mpzWGyY5dJ262K\r\nrePSn6REcBSPqAYlaRYOCjyg1hiCTJ0xjEwevNWZ2GoYF92WzDBg2/5lkqN3\r\nh6XizbLe9uqS7yfYNyhu3iiJ8xugiG4ZTb5a600rgNlAR6uuwyPA+XQ6ZyLv\r\nP38o3l8/1zkaSbLgAjhaXWwjHbvgrbvvuoGa39dx6ZgvlUK08hMAFiBKOUKU\r\nLkPliDx4irNIyko3QnEBzEwp4nwctdzaP0DS06GG+3CwGmMs927L5bjFkVSA\r\ncrqa5gJprgD/OLsGeKijAifAaiXlKLwPVcNz3iaykPMyNecQSQ0x7lZWmhpe\r\nF1uII6n2JWG+KV58pS1EZZ2HkzWwtDtNHiTBuiahoHrPV76Pr4HR7X/kcwqP\r\n3pCHWcrgqv7NiKsIjmffuv2Th10Q9Fv1ltnG5Gx46VXMNmfOAU8nehkkALfm\r\nKsKHyk/jjIQrbXQLANPsMt3ZuiH9GDhibUukN5AV06kA/VHGfdBmuXqJda/w\r\nWiaODAjvSnRwyYFu09LN0CJAjGgvWxLHLz9G3/qzqnCo7YQYkQVvTfSQSpVG\r\nLDGh1nwxu88EN57/DMHtHysZuCFGPudDYFVMZrvVrutjlfOELZdg6SrswIay\r\nbYY1obzeZiCgM5FiKfq3FbZlgsjiDaSK5Ws=\r\n=wb8Y\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001336":{"name":"caniuse-lite","version":"1.0.30001336","dist":{"integrity":"sha512-/YxSlBmL7iKXTbIJ48IQTnAOBk7XmWsxhBF1PZLOko5Dt9qc4Pl+84lfqG3Tc4EuavurRn1QLoVJGxY2iSycfw==","shasum":"a9eb13edd2613f418ebc632c8d6c9ab9fde7ccc4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001336.tgz","fileCount":812,"unpackedSize":1531817,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbw8SGs2m9Cjq8UxKyP87kmV28wAsRFxEaX9oudv35AQIhAOZq/e8em8n5SCdgmvs291EUQcv/ngqhMLVkiosr2t/5"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJic1rVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrQtA//fTgL6jYiv1HmeP6VGa0iYklUlLial6cjlY/IMAqpH0vZW384\r\nopdojfocMsJgn4O4fhtPnmnR813H4d+zVyDux2N0sXIv/YOs22czhkJOUHL5\r\n/zMN8burQnsSlr6tJ0en4udGCCoc710gGmBniSH9UhCMbH9BpxGVmLQSQno4\r\nYWM89cn2POd02bxdf4qlN0VmkO6wkmtkvngfruDfglP1z4BxxXs9vDt9/LIZ\r\nPSH0hFuDAy/VYOxW+mlttyeGkvh7NB5dCmmeD0r+LG3rwRMWLiM72jnLCu27\r\nWB6THnd7Vfx54yiBgu1Xw0z+lFrcd0IlEV4abiuytK3flqsibCOLO6raz3xO\r\nYlk6vIxLv0Cb2KGaiIfB6u1QjkPKE+Y45t2gk3Hm++ULWBryPYcPJTZPHaHX\r\njO72A3/0KH3Z+LSy3C6NPRK2BqRFYVqJTr0/vF9ti9z+AqDNL9UrIFVGf3Pn\r\nvA91K8bNzFUVroM+SUMfErhOP+LZ+z6MgnltOe8BEI7J9+YlXBdDpwa7gwTk\r\nWQn5lyspXF+ILiaAKf7GRXgopqi2y64g6iH39OVXBsiGsYDLUtkZB8Ms4rsx\r\nk+RHFNbjkTccL/2NvfObeo30tSLJksXqVdp0KiYBezQ0mHaX0xpFhRg3qBh9\r\nDFZHSnA0qcNpncL1Rq6J5gP3RLo90tIYtE0=\r\n=tHyD\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001337":{"name":"caniuse-lite","version":"1.0.30001337","dist":{"integrity":"sha512-HZRbZ0QgO1wvrbbnzljfpQ05sQB1rUkr9LguxQGCk3sgbTgIw8BajHLUMFwLpPQogdqTIZcpn7i6Sf2HoOFEbA==","shasum":"171f308fd51ceaeadf78a7f4ad880a979193d9e4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001337.tgz","fileCount":812,"unpackedSize":1533560,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAqFrxxrNhtb4YtohqkZtz2B7Jp7mYq2OWIzXnv3vMdSAiEAtqo5IJBxR28u7lHGmHk5htzXrOD3tJQaxxUmV1eG6Q0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJidKp1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoUjA/+JJoqWXUWEo/BRIAq+Uf9M4m+wHBhR5LzI/w/dIhdnJE3kbyV\r\nFd9jtxE+wLUj7Y3PgqBjOrob81Xk5DYk6pSUM1Ct1gDT5G9VnfuzrSzqaf8Y\r\nLDBgsNTezimMnz1HixFTsoJYlABadUUHverUNm5b4nRHvVaCMEQrQugTv10G\r\nPSUQxc3X+4rh4+o/JbpXUIQGatrXSvWTK0xjQyuhT7EEL5N8YGt05OqXbo+R\r\nZ6ekZfnqmnmvbnhvcEf1WvOiBUtBk2QZoGJIT+DoJF2jlwt957hDOpAl5yx4\r\n1Tr6OXxKtvIcJJiuJlsPV+n1/1QdtXSfkpAmlCIxMUimVZ09LTS02rwJaD90\r\nL/rQ6eP2k/miiuhulGr9Ibi6+8v6+p52qYRZzzIJrGiSx4XVX/RXDFvkTYbe\r\ngMT5iy3pw6YDsIHKPP0lANGK7ls3cGvOx0+Ff73He5fCRAm3vFNa2Vz7PRCm\r\nUENlTjRviR+ntlHJuyT0ubNTQFRNR5LM6zoQqRFrWBpRVL2IDV27j/I1TrfM\r\n+YbRJUr1iNsOmK9JK2yCgpJejFrdF7TcqnB2AhiZD7wRyk0sKyurdAIion4V\r\n+QPZMxR7wRINtdfA3Dn2EtZHLGLuwnLuWdc5VW92SD4oTkSMpf7lBz5r+c4f\r\nuG1BVG94dNhuhTWedj/16PRvaRR+3CcRbe4=\r\n=2leI\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001338":{"name":"caniuse-lite","version":"1.0.30001338","dist":{"integrity":"sha512-1gLHWyfVoRDsHieO+CaeYe7jSo/MT7D7lhaXUiwwbuR5BwQxORs0f1tAwUSQr3YbxRXJvxHM/PA5FfPQRnsPeQ==","shasum":"b5dd7a7941a51a16480bdf6ff82bded1628eec0d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001338.tgz","fileCount":812,"unpackedSize":1533571,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA2FmX4YCkqt2RzksraAodeJPn2RBrmsVWbg9jqa13vkAiBpr+bwwqNQ1qrx+duM9FxxfGpKlYWmuFLTaH3WP9qETA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJidLZyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoQrxAAnDizbVeVo4/5/b2eT+aNjD8x3QMGvyElb8EHG1BZSHLIn7Lw\r\nlMqhHV/2GtjL0JpctMb5po+6F+sb4x8WfdTHqGuoaiLG8ne+wNpQCY1wNGpn\r\ngeqSLXOEzaPFVxRNIuQqx7ienQOXqnzWgxe64Z+SdiJ5zSyXKmM3L6QaHVMP\r\n8CTpIyXsQAiWpgJM1GXNhP81J73ETf0TFjMISkEIsks5xRY00rZ3vkp5cCuq\r\nOPgM6t5mVU9jhjykl4EDnAu0ChwAyKXKgd9A3GMjFurYKohAc068PFKrekLc\r\nV4F6YeoLTs7FpSFEuSU7J+VWCXDoHCyNo40qG68EqAxzcYM1d5rlhJc4E0+u\r\nVg3nJfTzhbobjSJ19rG9AeS0lNeL5Nu1r8K1tEbLE6p317lKcVekOBagyxah\r\nnRgo2wfjPTxyliVEftgY9w/uzIHr2i+jHdgdfaxgXConDgkdo/IUqgDsffo7\r\njJqZ7eMUMw95NMCeWwzUpioPh3D7pXASte07JZXcZ+ek9y8axqVbq7iPYydk\r\ntSB7cv7Fyq4G9oEoCyCQTTdQKzVvBf9JM6QMzBLxtfHTXtNLu7978mInk4Cr\r\neGDiGAPbhKORhjiMYBCW1C7ruQzON4ya3KLs8fuNUoDaPlyPbOgugsFZLDHG\r\nIAVfQ8y5cjiKBqAKKawfZZFKSRrmsI4/Ilw=\r\n=S1kl\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001339":{"name":"caniuse-lite","version":"1.0.30001339","dist":{"integrity":"sha512-Es8PiVqCe+uXdms0Gu5xP5PF2bxLR7OBp3wUzUnuO7OHzhOfCyg3hdiGWVPVxhiuniOzng+hTc1u3fEQ0TlkSQ==","shasum":"f9aece4ea8156071613b27791547ba0b33f176cf","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001339.tgz","fileCount":812,"unpackedSize":1533579,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBeaatNVBECUFHu0Bi1iuZDkgITx9Wedp3d7a93DdyM8AiBtQp6WFJ00nzt1gDamGOM91UCEzt80V6r7htjMSW0cuA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiefxyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr9Zg/7BlWi+heGx/8qc02UjJ6/aLSHGdkitQ43IyHwHCspC3XU2T+U\r\nuUYB/zLWNyZ4LPZ36l0kDiltuddoV+nfB++7XL7hTX5JzRxjyZKD7fwhVzMP\r\nFwcQd4q68QImr9GKZJ3+MV1wQ5SkO03zsdrmIrfgGAaFbN5iZnnHqENc9hn7\r\n3TvuXRz7Af+ARYpCnCgzg4xYMXDi9PRAfDfOWIA+5smwv21lS7spderco79e\r\nT7IY7QXCozC8wdpV4Fhxge17JohXAgo+CDWc8FK0GsnlM342KGxL8+q4AWC3\r\nL6rVNlYQNOhWfEpJiVE41cKuHXHfQ9Lt6FwPmubexg0Vxewi9upssv00GAAx\r\nSzQWZVk3cZngs+955gOt4qFG0ErNNJtV64JC4Ch+2PGMxtE1/DgxyMqGpfVJ\r\nqP39LcOXsrWCeGKHFJqMjlIBhy0MHSHn3auKLPmOpis/uljjdTQeOcu+AJXJ\r\nyPG3e7S1vFa3MgCFm2FUQt31rgomx4zHozChrHSx5WYpdDPbvpcWrQ3XNePX\r\n6wILXGdBD7b3m26Ql8Fmh0WKN9X4lj6QbR5YkNDfksQVV5GA7D/MPFTHMZAu\r\nqPmCzqKQ1OZkZB5t7dNgJGE75IEQ+tc27DOg11bmVPEAD3sLCGqk44GoaLTY\r\noGciZwkSJSD8En1q0uiBKRVqovUTgIZgGGA=\r\n=Nb5v\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001340":{"name":"caniuse-lite","version":"1.0.30001340","dist":{"integrity":"sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==","shasum":"029a2f8bfc025d4820fafbfaa6259fd7778340c7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001340.tgz","fileCount":812,"unpackedSize":1533579,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBRB9LtmUtD4Urr8Zk91WQuYsAdng0bwyHFnsj93K3VxAiEAlrN+ZGniKeh5yCpGdcIZtBZJa+VKEeg12m7OroP4D1k="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJifJVPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp8Dg/9EbzOd4FF4uG1yq6XsbIVwmCdhFw6LW4Un8jm9os4tAIjmVzg\r\nZTHiXoU648khi3YaPcj7mPbCWFMMoRe3NELUS4kEbqHGXhjJQ9EsxR1qbvkC\r\nZS1gZr54a/RcrH06zbweBSCb9DjqaRkW5/MbzTg5XWATwPJrRfWdJBfW9/YF\r\nrng7yZxKFcaCCKsg7RJrc+NFZkBlGv4jFHVouR/Q7enw1iWYBKWSfQCiZRS4\r\nBIKLKutMj/kGaXxby+hafBZPaeMTmCB5nodPRNm0VJymNuqhR6LYo7LzZnkk\r\nN0TkqIULXvgDIa6zPBshskgRZCQEQg01TY26g+rx/BsjS+5msaH5OQa/A2PF\r\ntEK/y+p2NGz3xHFTTBYJPKlBlFfP7N0O2qT4rCluB7VBB1mVmmiyd6w1JvfP\r\noL0Cqfx/lz+UluXUV9wjgeOdPcJb+khpJQcZdBQqfeCn0DGKJHmzHTcNtf6W\r\nW0B43bSmyhGwdL/aWleqtPev/y7ovxBbm1NK7PYQV7wQyHZatWUH2Nu9z+TF\r\nDtOpeiENcAUK38bdYXMXn8lkmIya8PtZqvQYEWFy2WZR4ksDGx8dT2SCJwk+\r\nWsu4euOOJjOhMIKk2AASlANnGPz0BVOdlMDYd0RjNLzp1qCSn2WSIzqiXv9+\r\n91A5qy7WwRrWIwr29oNC3sqMZCooCuK0pPo=\r\n=hC2C\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001341":{"name":"caniuse-lite","version":"1.0.30001341","dist":{"integrity":"sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA==","shasum":"59590c8ffa8b5939cf4161f00827b8873ad72498","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001341.tgz","fileCount":812,"unpackedSize":1533590,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDy3oWT+2R2JkbbIQq/IALrJyWkIgeUhrSJupfhTmP6pwIhAKh9xCC+R22MjP4JYCI+S+26RSyc8nvhl+nh8YoUoz6u"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJifzh4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrOaA/+JwAPVsiTZyCo7tjgg5qrlMZUEdU7WH8WLgj8g8vUXcL8BkKo\r\nZb5q1ut0vd/11szijMoK07RNrbZldoCycHSHKuyPzB88+uZf/GDyfkz3oRGf\r\nwbA+7oyPSTcdf6fmlIJGgM/vi0qoxYQgtHXD4D7RVcMD21FyT3CuZZeY2q1i\r\ni0Bx9U/JhWFUBfsaSoE39c9hFT97QaHnCm+2e3oXpAO+XlFsfXWiGAlMfBF9\r\n0hEpbLj/Y1MWMJZSzxwnR395CHIMwEH8PvKG6P+C2c5py6nX3X/6f2gesipU\r\nzjr3BdGI7PYeuugqOyNCXM+1c69RKjNUWjo+4AcAF+PTGvqSFRj7Ieoo5e6n\r\n/Xv2GThGn6v/eanK8VKTpkXxBbPd7Aqo/7+571Zc8vs2yE9ToJPNi/3dFA21\r\n4q3llm63s9FuNY2AbYbxkVVBs2L2PH2kumSrmtTORwTrWmV9seEcvkTmb0U6\r\nPOKZrefMyYcuAdLm3SNho0Si3AKqfxJbirmK8G/ECWTWfOFDzJ9Db4w3kRzC\r\nAdlVD3Oq9JSDsCUT7KXYHlA3oIUBbsccrIr16QESO2foZKuZ8x4EiNacgWoY\r\nk0P4zz0SHFvboCRcw27ItJ60vcRGhNy94tkTtfNDza3m9dPdJ4rVncOIJbaR\r\nxfAFj8RSxmy3VLw1nFlc/yEdLEsJxU0IwPE=\r\n=UEeA\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001342":{"name":"caniuse-lite","version":"1.0.30001342","dist":{"integrity":"sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==","shasum":"87152b1e3b950d1fbf0093e23f00b6c8e8f1da96","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001342.tgz","fileCount":813,"unpackedSize":1534966,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGH+H/dGntGX/zI0U5W6iSd9DiIbDW67JD9WYupmpkNvAiAXgzZaRtNzXBc1xmkFGbu2xx+6t5fji8ahlHwG6MHtYQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiic5tACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrKzQ/9HjloO+tNe99NqllwvXq89z3HH4sZ7vyqSB65XlukIGZZvRd3\r\ngnVt8F4s0cgAxDx+vqchES8bagKLN787pUXb9qbgebKNg9NaQhHNrNzl2y4C\r\nkshwB8QTkvqTtUwYyYNnDmAWe8mmk1k4FuNQ1tBz6fAa25R0cK4AziiijvGg\r\ndUbIvTnvVHoGziMCl473kEKfdx36ENKTl+479bVx10TayRmqn83tuG5PrgPF\r\nAZvXsojY2FmWKVTmFauThySQ/T9bWs7hjqPIAjDGcRS2qlwIX+2W9KwYCipG\r\nxQ1AT7JLl80Mg9iqNR78KI4xBOKLb/nEwEkjx8Z26zcpPSEti+L7JfZpNHIe\r\nN0x/PYICLWqgVslcbJlBQQmOljQTTEVAyFajG9fluh+iE5BsIysvmSD860gm\r\n9N3CxDD6tt7oX1x0njKR7bTQnB688gZZQ9d0SUqvZWwZ+k/kS5AHXLjbPwMi\r\nHErgl7ocj1QxuYrZvwD866vbBbWg3sD0MQrvIRcDNFbb+QlWi5kN1HhK8H3M\r\niFNUMnRcaQf6rE/sRjJs3VSIcn78KfggNfUhScM8LYZ/JUgFnqKNY+Bmmdjp\r\nv0CZCEZY6au2EkK5uLpUEPobEkOzUC5h9urDV/Kf/IQlcZvyvToZBdm6kSfe\r\nsUbAP4DSCHMtiT7tcOpqB4bD/r/jbLrU/aw=\r\n=LosK\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001343":{"name":"caniuse-lite","version":"1.0.30001343","dist":{"integrity":"sha512-8KeCrAtPMabo/XW14B+R9sZYoClx1n0b+WYgwDKZPtWR3TcdvWzdSy7mPyFEmR5WU1St9v1PW6sdO5dkFOEzfA==","shasum":"8e1107e30d9a4d2f63782b48ae0a3ce34e2f9c2a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001343.tgz","fileCount":813,"unpackedSize":1536663,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGygtGhwDWDqWqrN0pXUA9YCnF9YLndfX1l7pSufr2FuAiEAmqqL3qQpw9qsaB7a4U2iSWeaerHMw35fh09b+KwnDcE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijwnVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpCyRAAl0IgeDFsNU6Y909UCG4v5qNoM7M3SHHjx9S0bP2FuPvMRJvU\r\nr+J4FaLnJtJKMvzz66is/M/NWZLZkzd0A+1L6Rm+CLPjJ7fn7OFkpTlfbBR3\r\nWqZHExrkVk0BLwPeZDBdG1slYUGa1xg9hud3sWc5+x997UPUJYw+DmL+OOx2\r\nFjfhGKM8VsTJ9O13jkib0H05fq59ynBNLxsuyjJlQthbbPROk/0bCxPfnv2h\r\ngFJ+gNZ03mC279MK33n8kRN5afndtfkf1OMm4Dd4tUE+o5+bN9SSdA7gUa2E\r\n0By3jgkBGwu5V+SpS0hcdtzFSg9I7v5bx7fVL9MGt4/9VLu8sfsofXBaqdQz\r\ngD37cBFvbv26NDRWYo5vN4JfydaiSmZKlZWhWLWdbsJc0N7Jsvh1BR+EFdmd\r\nX8uvt59/ZmbI8V+fo1WZw8u0iIyJl03gbVse7+MRulYH57ArDWAK7Zo2np7x\r\ncDUhvPsCWM2LEa+K/OQ1TnPZ/G4i1bm98CvciwyVwVyR6qtucSQpOvQhD80F\r\n6IHSB+H9g0svAdzqxIuOgGmCpBOXnLiyxe9lvSlxtCPbA+1098mWDjgvS8tM\r\nXKyVGWUcaDFQqHlnAHusxbOVDfE8fnFsCY+WsPYM7rAIO0ua5gKlSfPKOxLB\r\nDS+rwW/6nHlEPeR6ODA6Z+P4sxkPYshn8P8=\r\n=lxPx\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001344":{"name":"caniuse-lite","version":"1.0.30001344","dist":{"integrity":"sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==","shasum":"8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001344.tgz","fileCount":813,"unpackedSize":1536693,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCzzFzAdXfpeQ7WTmBJa1w4XTLw0cg5HjVDshryVS+xaQIhAMKmlLhAmaZV8T9U9Y1hY81s2axxstMljZduGbEqfVAv"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJikGZKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpaiA/5AGg2msWOnrDB7rmutY2/hqEm39ZqPOpy76rHxuYWx98o0TQo\r\n0sJB94bExvo/I5R1H+GGCvP/5xo54DesVXiVvV2NrK06ofldf3ZoQgiW7lP2\r\nKdl/mDRGlEOHmLYhsm9VSCWG3dI02s1dOWJZD6PXBH+eT0Em5D4k1f4n04Cz\r\n4JJPjNWCnV1hwlsGFM2BK1bYfON0IcVjRoACDUOMVRsmfq3PxCmVAxox/lZU\r\nMQRVJkj7d46TypnUgWNkuLwpF9jS7Uqweb12wQO96s34wv7YnQsJIw1g+I3H\r\nyrKuM+TvNGOY/Pm7oRW/lyvbLEs67z/gbsVB21slhsgjDWvWaqcnvYT5yvba\r\n2kHfzCZbe6c4W/h4Rp+sJpbkYkSPqSi305jgnJw35AJMn+XcVWSPI5q8gJA4\r\n+7hg/y4g661iBIdVC5Tu5LJet1KB+dwRwzL1cEcnGOw3iQI9e+Ehd2GGIjh3\r\n9M1Njit4pQ66A/+IRcCbIYwJeyYzmU3fUE5V3QYB23wDB86t5FjTtXcFEF+/\r\nru+IGOhTbVjQ18ADi3DUfvCuVwXD3aing/YI9hQRHccljbaUV5vdAmcbWgRu\r\nHaSODiNuFO1I8eWnaM0bhUnskI8a1QfagD/tzM8lc0HI4M6XvOtlUtm/t02v\r\nHZVlaS1lsN9VATB5cwISWOZ0+qLgfYyxoSs=\r\n=NDuY\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001346":{"name":"caniuse-lite","version":"1.0.30001346","dist":{"integrity":"sha512-q6ibZUO2t88QCIPayP/euuDREq+aMAxFE5S70PkrLh0iTDj/zEhgvJRKC2+CvXY6EWc6oQwUR48lL5vCW6jiXQ==","shasum":"e895551b46b9cc9cc9de852facd42f04839a8fbe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001346.tgz","fileCount":813,"unpackedSize":1538439,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDv+RijRAl4GOwYjd+VobEMH25ENqZp6b6LvhKWp+wYHgIhANpb8Vm+IsogAN/Pgkl6tdxmENqqOjTekA0y0O320x/M"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJimElmACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoNSA//SG7ss3Vk1zfXClM9pfc544pZRFR9qdf53dO4os5fuF/txTfY\r\ngHCYCt90vLxN/chK0Sw5MW0rxLAbB7t8NpTcOLxwb++ZDfhSIh0/nL28BJLu\r\nY1NfPYfZjf6//MuCPiakDmPgc77/s490K1vjKVgBMccEUQwA42OFWkwIk5Np\r\nFE19peZmf2vevIDeupEX1F11MB1MO1ZlljtV/g1uSYZzvIX2diQQPtD5fZgP\r\ntAjgMHRE9RC39yfHBKSmziXyjYxqfEyzVWdvMXOKF3ipb903xtr9tsaZWXLy\r\ngYp9Z3tlHCFJjZYBOYODHpZlI2n4cs8h8xGaMgXDt5lNw6ezvDOP8sw1nuJ+\r\n7JKMfJ1+dbPIvdYaKnSl3QS+dNHXju/dPAZw1YF16oCSNzvJXFHtNOlF+oJl\r\nLxN+hDUFiMbHVWfjOm36jcDvNoH8MdIw0ZpwlnqaiHYIRx6bo/q6Ndn8Z13d\r\nT+ndO/SQWL64GhNJSxrQIUS5UzL+RFurqJOuBP1TePB4J4ea4BXW7S9d4bXA\r\nVASuSnf6h5YZcnpqj51RsOa9ZUQ2zikvXe6KwCaTFIrVOG+KVi5nEEFIS8Qh\r\nTmSC2MmC3zVuzVFk0R4kJLL3AG386m5QYwNEJ8ZvCKyIrQQCHWu4GNTYqFco\r\nUalaPSNlZp+Yo1OTZIutb0xPSh6jbcDOMeE=\r\n=1z1t\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001349":{"name":"caniuse-lite","version":"1.0.30001349","dist":{"integrity":"sha512-VFaWW3jeo6DLU5rwdiasosxhYSduJgSGil4cSyX3/85fbctlE58pXAkWyuRmVA0r2RxsOSVYUTZcySJ8WpbTxw==","shasum":"90740086a2eb2e825084944169d313c9793aeba4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001349.tgz","fileCount":813,"unpackedSize":1546594,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnFLuelE5GLqO9XK0K7Kg7bmxLb8ImDlEmqXiTlGshbwIhAKEJ1mpyHmWTWZ5kDZWca0EveXY0ar/JomteXr+hrjid"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJintpdACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpJSA//eZ4V/7p+ViLLeJHyKeE0CdAHu4gw+9KPNT5SBOxi8ThfwjQc\r\nY3zYjFOahqaT1dLaPJt3yfsdr/Y58IyBDqKounzmhLzdwh9ZuZUaQdwfVZ5K\r\n7333T4jxdc569Oc/0DUMXcTwCJKlYCE4RuCgpQHEK95plr97SfbfBYkmqvFo\r\nhH/+TcBI6EwDP74d6AKN1mDwrTGSCVblnd/Ffu5kRk6KysIR2Uo8iRGmoIYL\r\nguvh7QJITw0f4/2WT7YaKPk3KCDigP5O+8IfADAKG7aRWbWrq3oNdOKEBK+W\r\nBTdbvYKEnj2YEyrSVXQWGWGFynZIoasaUgP8Z3ztakCqXYEksNmIEwh6Evrw\r\nMTghnJt2YEZHVl4NDqIu1xLHShDoDfgMwZuipoV70JdmK01DJEDT2iONE1jl\r\nRH4c4F0r2BHG8gHqHwbvzPX7NedP/3I54fIBAsYA+JFHdTR6TEzR804Adwls\r\n1QVUSlo6vizSyKmlyqiALvClXjddvqrCUZJTvnZE9Fxi0LrD6lzNoKPLR2md\r\n/AcL00/DAhRqrDwbBuZJPlQUhZtuPYUYSLhcVPn3TP30bI7qwHVHLNm8Yskj\r\nhzZmCaJPwfY2mZ8j4AENaqOGNBM1k2pu117ATv5q7xSh4M5mY87lVwDJLlgb\r\nswYlkAiKXjgJVYU0pI/onsJj9yG0mj/QpPg=\r\n=qpc6\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001350":{"name":"caniuse-lite","version":"1.0.30001350","dist":{"integrity":"sha512-NZBql38Pzd+rAu5SPXv+qmTWGQuFsRiemHCJCAPvkoDxWV19/xqL2YHF32fDJ9SDLdLqfax8+S0CO3ncDCp9Iw==","shasum":"f0acc6472469d066a4357765eb73be5973eda918","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001350.tgz","fileCount":813,"unpackedSize":1546594,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDv2FtjO3mcPrwNBnfkphZuqIHh2YG+7sfUq2GA4X8aEgIgOJhVNShMQYPeUlQQ8fnapdrUXbPblTgBeUWKwbtl7K0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJioEcnACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo1FBAAg7yWqExpZuSBWGXRvpyCLCFtZn7It+9V8oWL4aCr3uchQlHr\r\nWZ6iGOLqz2ROM2ZkqPR84PdD3jrb4R4lzcAAXW9/aiZClHfIYsNuBodZH2FK\r\nq3J5cQQSWRKnBIYkFqzCCVPJ3J7lQsyL2VhNJZO0xVzcu6ltXjGxXZ6ujA/A\r\n/Gry453QU6f+RMoSnJEjUFKBtz4qRVi3tjGH+ci40F09kC0LtcPvcXCALXDv\r\nYGCOPKzYIz0wY+UFH5XGh9pSVIhDdWo4RCZ5fVXCUFm9i1/T/fV8t84BcjSM\r\n/WV8/hIPnI+FZULRJyTirJrXDBh4pQ/45TPYRW5UACrcylf6lHPidQcGLuXF\r\nIupvud6IxjWrohyMLoIEsVlbjRKlJGDxhZVe6uAph5fc4oXRGl5aKjr7cjGJ\r\nEXGPzfbG6VvPYv1XU6Kw78jN/dU1AFzhqqQe4jooQ1OBpZ7gdYlwgL/84fVj\r\n/M664yXfcBc7Emd6i4H6Nq8XRIaXsXJKlscy/wttKMfCPXV2q8B36JpnrHNH\r\nIKRO0yyB6xMsRMZrzT2dZST7I+RAgSEPg1z+mvk5Yv0opod6AN/ImRMyJf9W\r\n87kC4OnxgwXl5iLcXEkv6vluYpVKeYAuuIqafkhYDAeL8F+cflIvH1AOzlJM\r\njX2d/UKFev1G+U/YmcmW115sOEQCcN04P/Q=\r\n=eRpL\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001351":{"name":"caniuse-lite","version":"1.0.30001351","dist":{"integrity":"sha512-u+Ll+RDaiQEproTQjZLjZwyfNgNezA1fERMT7/54npcz+PkbVJUAHXMUz4bkXQYRPWrcFNO0Fbi1mwjfXg6N5g==","shasum":"fd38e07c0ab75921169bac5076b0e0c5f58f9b50","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001351.tgz","fileCount":813,"unpackedSize":1546608,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyUCFXdppIUofbCqAguGqj3SyInQ0Za9zdpDn4HNOPBgIgejohWAU7z0N0sUwsk9cfo5UyqB35I5wPIqQX769yAPQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJioRk9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoyTg/+PtjwQNfm123agKEPhokW2cJKWMGYX4mJ4P3tD3mhRSDNnC7u\r\ns6jcoEmzfLyS/7nxNEIM/nsNv0iqblLPJTJ7RXaiCzgPhhBNNlcEnWtqT+ic\r\ngor5swqxkvo3Y72fLbu3K1ekeMz2fZwLZ47AN8cGpbQ919LyfAZt6v8p/+3p\r\njPMK9nOAIgw2eOAt5kqGEM4QBztxmOsqTHB4r4VTCk3RgpS/Igq5BQIIODvJ\r\n+BOu+c8xgGmpH5HHba+Vs05jUmzeovKPJx5SG2NYyHai/3c76baQQck8qyT9\r\npk00aAady9Y89kUIegpM3NOiRpKpTDZxFuz6iVvr4xt9Y6uRW8VNTomN57Cz\r\nn2H/WFtXM1ORLtpyZiwOu0heL1fDhPrHpaQ+HQni9uDr+EmNywcrP0tKe8J5\r\nW4jdDGNrKvFwWIoe+lL8OynNqgSJp62Kw2UZOT+tAc6JD6vSDQMD7yMQK1ji\r\nisJEG+/9g4WYg2G0P4luT1l90xYsUbx0XErgosOE177RwruvG5yIKx7qVyBX\r\nKHfwlUVRhn/bWxYdURZeb4C6v1XxYBNyUPhywicyggL8NMYsTzfR/ImtC1Ob\r\nHcDth/OwPwrLuU21Kd2m0NzFqxu78dpQEi5VWz26ju9rPtH5AsH97Jvn8esx\r\nghKNdAbouPHXnkwAknokiLsj0f6KTvdsyvM=\r\n=IAk5\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001352":{"name":"caniuse-lite","version":"1.0.30001352","dist":{"integrity":"sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==","shasum":"cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001352.tgz","fileCount":813,"unpackedSize":1546602,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFuxPQdf7zCA2RF+zVVF0bnO8ndId8TFRlSfXZGBQe32AiEAhq8k13l5tptzSI+I2UlxH+NC69CQhzAJ6Z2Q2QE3U0M="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJioX28ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo3mw//W9YSHzlRQH+DlGoWGzAyH+nW2+wX0EgBYn9WqkGX2GkPAk8I\r\njMpno/bZTHY4RDdlEUuRqAk6ttT8c7fHU4YImM1+nF4uf7YI5eETeqorXDOZ\r\nHOYlfEbRfWaeTpSuN5uTatutL+oRbcF9dqNNSraUHMIdMDqfFJBUAuKEUoHl\r\nMa2mhjyd0U67oY2pJviwySp7BbPANQhWAFeVez2027drjjfuiU4wCcEy+d5Y\r\n0R8bX7t5MIQs0QdLSH9w+kAts6CO8jLEqCeGfoA8iaZfR/Xk4EoBf8Udhi2p\r\nqutEgfJmEBgIJufqRxGBnfh5pF7mCNWu9cWgXYsmQG8upYvKEnjudRkZREB2\r\nR6LTRiZho99teo6sK5WmYQEp8pFTmJYt8dNhbyZzgelBlhqeXaDre1d7Q5ZT\r\nsveTSsNeFcGumZs82USc5jmcF8/ktn4mGfL0W0dU3aNDvJjgkIqkql7AViob\r\n4ewZar27eDKjqO7apZwxFFc4LWD7p+2r0K30uWEo7kKN8fou4oeytapebm12\r\nlZEzK8liwuo/7PHY36V+XtZG+q38wCV+2WuXy/twaspPjTidbgmo21HSr0jo\r\nPPeLouuuPXXReXVL7pfHi+jsCDoyFpd5k6AHa/78o+pdvdHGL99+C+MIUUf7\r\nSBHlbKFKP1kewVZMgTOwsHLu0nlVTAlo48I=\r\n=8p/h\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001353":{"name":"caniuse-lite","version":"1.0.30001353","dist":{"integrity":"sha512-GqItFu1lCW4OGd4f47TVQXAGxca8K9Bz3cBb872ZskMo6FIQhiHCc7QjBL7Bb4XannbV+Gq0yHhFVxONW6C/XQ==","shasum":"c21014dea3bd0a15f34c5cc4cf94e9e8d6dea27d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001353.tgz","fileCount":814,"unpackedSize":1548029,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkkpTduGZk2iVmzCNETcOD5+94poZGlvPxnHJgL8v45AIgRtJT/Yw42bExunWdOKG0ao1PMULO153Px5zelJKLfik="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqUplACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoxNg/7B7ykXCbxxCG8lBeI/vQH/e0r3uHDLWL5xyjiJvSNIUlBy+0N\r\n4bd902tL1Jd0xXT5bDtXUhIZ0TzsUDOkFrPcSx4PmqUwIuBbz4485e65GLTf\r\n+bIsJEihKdgH4v5+Go2vEOZkVme8xZhFFcEvcKwG6VwMDONe2mve0ZR6psvC\r\nipXlFgRllJ3V3OdSceA0vFxQgYiVLzTBLWzKprLxXp3Jl1zf5+NLjoHq2Mj+\r\n0ABwgdlHgGTcnhs0txCmsHUsOCeQOkyq4Z06A+GzBH/hxgM368LSSjC62kc+\r\nroLD7aUWig1SKdk80DhXjwPZFVsIrlkg5mkLYlMmGj8Jq3/2QBnamtIK5Ej4\r\nIbNnBPc1zIRUM4swK6FQ93X5KZ7hf8FotMt1YCWsqmQ/VxhliAn9k0Db7IWO\r\nQC+kUvNF8cjPKHHRBZ7exdChg697SygLulsxAJD5Igl7nXVI+P6eRHagD31F\r\ng+NjP0AYufT/SesEfmH5TsPJRCAhFDyBxQ58sjVT8s3Gw7Ehejw8UREaDEFG\r\n0sNKhR4uLZJWcUPQ1opPBsH2cHLOBLXxKBGPiMLvwpNbGtE8RV5P9HGMWFIm\r\ncFJ4r4+/yTqflgrqIFeii1ffX5MKXfhoUeLTz0nOpQXS6Tqs73J5dRgYokxa\r\nS9jB0ms+FoCuepRFbsZ7BqPmFozlLvE/w4g=\r\n=gqUo\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001354":{"name":"caniuse-lite","version":"1.0.30001354","dist":{"integrity":"sha512-mImKeCkyGDAHNywYFA4bqnLAzTUvVkqPvhY4DV47X+Gl2c5Z8c3KNETnXp14GQt11LvxE8AwjzGxJ+rsikiOzg==","shasum":"95c5efdb64148bb4870771749b9a619304755ce5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001354.tgz","fileCount":814,"unpackedSize":1548029,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG5i6HuZkSqO2XpirfLjvZlRpzbBTSoWY5HjbE+vmm0+AiBg5+AOLJZ7CZ/yWuykROVdfXAn5H5DCihykciK988Ryw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqXJsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp26A//bG9SrAOnUom5HqxbTtierA5UIWYU621fKiELNtd02PhR2M9l\r\nrfYWVqcOaH6KUYpMQ+F1G/4IDY/ET4cQ/zmbpxGpy2wmD1jT/vkNsoYAwdAd\r\nhbhK4rLUDVCoCUWBvhRLEr/siIoUgFhcW1BpL9zAbPiIv8kOSt74OQzsfyEu\r\nai8cex6lnxmiuIl0oTeOLVjjtNja4Ok2swXHHQeFcI0n1PadrYXjpuJSzk50\r\nZdsP6yRDzY98py0DaYL8Ms6PFdx4diV20kB++Ex05HOBg1rcaJY+5/3vr0rA\r\nGpRepAEAvfT5MZ39UyZTCPjxOboEaeEWmpGCazwtsh8LaO7NLojQ5yaaK1e1\r\nw+br7HzhPV2NXwbatcovIkt8g4ZZDmWGSQeiCp6XjHjvL6GwoTXBvFUWcMPP\r\nKGS01fj9/d6BfM7VB6UJtEMYdn0EfnAjk5jscotRy9gQEWCPdGlA+ymyOTpj\r\ndfZgaooXG8eJ/wkhUFSjWHPQ/lsWI7toqpIL0XcsGqxi+71pZNs5ct79NQpN\r\nmy1ByRJMlk6LnB0ksFAewMATxCBDxi20UY0olvTt+cTA/seDdI8y+Xt9zwiu\r\niCmY4ufDv81O7DJ/sqEe+PFFZVLrtZlGE4wJGN6phv+Rr9KsdC+L/RBThs/v\r\noKEu+uyZbGsu2xrCFxI5pETVgE3G7fu3o2A=\r\n=uiVW\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001355":{"name":"caniuse-lite","version":"1.0.30001355","dist":{"integrity":"sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g==","shasum":"e240b7177443ed0198c737a7f609536976701c77","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001355.tgz","fileCount":814,"unpackedSize":1549737,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCObx3jls8vZKHJFJR2WUgcGh8qXBQRcMCoCqf627bTsAIhANAUFuK44fZUFYn81f0GrIbitfZpFztj1rm+DJdP2qth"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqsP2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqChBAAlluDBJTC7DE7dDSTjOsxE/31TX4MnLfwxe4oW/FJJRxcpP7x\r\nE1AxgM87cl8qc+GJf1GoLRVgs+7E7nL/cbnCcpZttQHDPPCAn5bHd1RB88ul\r\n8wPwF3tgum1KKKUCg7/sQwwMcYeP/+go/jv+nC2RWEkxsikJhrgenEaUth4y\r\nHy1O7xZlC3lMW80YQrHkIfODAD90ENZrQMxNICkQZJTAjWKdUucBMCs9lHra\r\ndc70jZsnQ/s5UUFfS2R9AL9e9p2CUavuFOq0+VJLopkO9auy5vk7++de3Wm3\r\nLdHayQnlEoLnMnpcZ2RYp+eoBkISuumRs69409YO7Sy8c48ntyqMH2SicOgK\r\nP2u6r232wt82+Z2FC+9g5JXaPuwI8cfmX0rw++1gN8oiNtnwJu8qVGOJ6tzp\r\n3IuEvtNrFtB8H0RthWRPu/ecTdeFVrIgeTjmRoBi+Nxgpf0G/cZBj9LZjFWS\r\n4hO0eKfiKwdXhDxOM/kFriRzV/5OwQ5CydDUVFCwDWN7h027GFy1WRUpOhy+\r\nl2Qk06bPur/ipcQy9ZYi4yJxH22yvS+loLsmPgGPBjuKbxgg/pTl1NgZ7aTz\r\npMof3A/joaaBAQtEwBNyZiPHmVJ3kuTYTSqLiD0fuWcnQPDQ3b9oZVYG3K45\r\nQ6aAKxefNRO3RWAhOZX4rFglYxVhhMSc3SA=\r\n=it2j\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001356":{"name":"caniuse-lite","version":"1.0.30001356","dist":{"integrity":"sha512-/30854bktMLhxtjieIxsrJBfs2gTM1pel6MXKF3K+RdIVJZcsn2A2QdhsuR4/p9+R204fZw0zCBBhktX8xWuyQ==","shasum":"cbf5fe7b33f90962bfbca532212ea478d4ec9de8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001356.tgz","fileCount":815,"unpackedSize":1551115,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE+9sTtKyox2lVEQGueRN18ICrt+wmYXKWyFKd4KwKXzAiBFR3rCIG15JxScrBRjsSX9Ry7m+wqGRcQtTFzBWxHR5g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJirNpfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoxKQ/8C5w704Scvj9Rksh7cZs1uwSaBLtCiLybQVNJbQYyy2jGIFY3\r\njxSUGQfxZ9srrYG4IO09EtrguorLe2wmKEq3r0ycTgEe/WMnBE/OLTeVfwKV\r\nnHsTqguQgcDfmjYlxnt/pzC0ngfgah+FBIYrbI3Biz4C025TG09c2O+s9BHF\r\nFAVrbwzDRzv41RXMevhUU+mOo1H1IoRP1Z3TWokjZPAIsbbAqtDdxBSWKwQ9\r\n6HO9Nwd6dXrJGrRNIy+tKZTbzf8S3so/g+2Fqv8HaaG/LRaL/LstY1vtCdUH\r\nYq4nhw0C4G+6pbzp19BEHWd2eJWtJCdN9hA10PkNDu2+t0hlP7KXu6Rs5bom\r\nJWxtS3X03OKkBZe1MNdXoAas3YDNx+jTrDbiJUGVc01uPkSBlBkiEZr53N/A\r\nMLyHR8+HMZMdwPaC6wH2arfiFYexw6ArvXpz8urzjNtniheecVmLgnEOlcbK\r\nwgB+QVHd0lPPRyIFBJI01RcGcuM44hspIK6/TI6qDb4uKnBzfA/arktmfZK4\r\nxUwj78ltGRb+xPASWQX+4IXlzaA9ADMwz21FXbBS//Z9XjxKAs93lFlLklZt\r\n7NZAluqsUeKvZmeEqli9bNQQTpbFIMmASiM5y7XBrq95E250Mwu3/P2nAH4T\r\nmQerwWERa+x6B3eySysqR+yJvvFAy41hflU=\r\n=De6V\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001357":{"name":"caniuse-lite","version":"1.0.30001357","dist":{"integrity":"sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg==","shasum":"dec7fc4158ef6ad24690d0eec7b91f32b8cb1b5d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001357.tgz","fileCount":815,"unpackedSize":1551115,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJ9l4yPR9ybm20yTgFnOGLWwcb1SvQk2bdIQGNOXfMlAIhAKWsf7RoWFUz+pUdPCDH95ZXV/CahQ3RV6+WbnuIKi5Y"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisAnuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpa7xAAoHGafICVOzut+CQDl74rbxcfEtmoakSRIj0CeAQQBHtqrHpl\r\nskzGWscGwJCeXZmFRtDfYkh9mQzzDyCZAYq/vP7zNocW4K2ZGW0h3n88oG2i\r\n/n7JGZvdwxI5CHY5Sr9mSLaVPE559upo2VnwnIfBSx9gL4kBQhd7bcOpZb3y\r\n1op4xML3SMCGTjhf5T1LBtMXeEfrE4nTHNIZdA6Bykz3WE1TSty0w+tGyA94\r\nR3sB/h2WV+xz/7zsQhCMg1PHn7u6df57O5KfK02+YmxY2y4myDonHA2k68DX\r\nbhLejs2zJvg+RuTF6ZyIJzgNZyX674MvjYF2Nd58ZQQt5Tk0xj13wZRw379+\r\nIsiTfpYvxmXeUhlleGvCQC0fugD7vNAOccoIU1xNj/hQl3zI3S3QcESm31tm\r\nqpazSvVEalIygbe4zLdF86dSbWH0B4V3YiCiEtjMD4rEn8UPxUnGmgFzi8Kf\r\nftR6WB+TfFIjigZABB9UUtBMAjKYGKi1mIuZW348bXNFa9T9t4J6E6t2GZ2n\r\noUUZ7Q5JOItEhQK7+NcCWQqeVnC4Z9z26KAKPI9CtG3WwrtoLU09LqZT5gMx\r\ngfYC+i2k4UxMKAZhPhxWpH5N5P8mWTiQWKcdTd+7XodQjU+6nU/VyHuKT5MW\r\nfBiHS8Q2Po85LeCysl4Yn7v1+D1V/QH82N4=\r\n=89KL\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001358":{"name":"caniuse-lite","version":"1.0.30001358","dist":{"integrity":"sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==","shasum":"473d35dabf5e448b463095cab7924e96ccfb8c00","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001358.tgz","fileCount":815,"unpackedSize":1551121,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZedgQwnhLVq5sLF1b/26RcYkNZOvHJthBYIGsNcO07gIhALIHiaYLUMmWf0PlGjlohwSQMPxBPhEXjFzUOPv2h0+Y"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisVtsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpVVQ/9Gml1xxsZAjEgWvHleVYNH9f1fFhH1uTA+KwZaQh98AIaGDCx\r\nxzRsshmOq/zVUb6qRwEm4bKbFLDCoruO7LSHyam06WTfdDYnZtjtOZhbjQCQ\r\nLJ3jj1cH0foQ5FD+3VRQmJGNA57QQuclDcqBsWiejH7OdqDf3IE1nIAgBHJG\r\nx70W2g5mhw1iEVk980ihD5pQ+V8w2MJ3CHWHBWnv/DZyiB1E+Dofj2SqzziK\r\nSk53tzth+Qo1A5hvx1nxUNlzmqJH9pUVDRnfI3RKnkHc2tHU1XmY46D2VAXO\r\nKLwczIZ3Lfv5co4jbJmh9ko+cTKU/02QLBSmvzpFU0/no59u9g/cskWSUFMc\r\nwBiVOYzfvYp0wv/xVD2XUVTYqyEh5VxFnjd03RFoKrkfMqRipcR/IlxK2PIl\r\n8n+JPSU37leknyGtvCG7DAbw9mEbDBVOk/KLB1mIRRs7+45VwLH7+Tp8xkqA\r\nS/JyTeY2aKUgVzWsQTEtWoFmdR94JbLGk3Rl9KZZz0Vg3NIJLFRyexKFMe30\r\nB4ibI/2OLyux1fjGO8OoktNM79h9qL2T6lQZitguAYlvC98Ah9TJFcGm9ZiC\r\n7P2GU0roIurqqplPxZktNRl9FnEetE+0L/PogvPQ3H4xGvKcUIm6mzPDDOps\r\nqV22ZDBgTHgWrfXKQ05NP9SJyjlYxBLv9/A=\r\n=bgp3\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001359":{"name":"caniuse-lite","version":"1.0.30001359","dist":{"integrity":"sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==","shasum":"a1c1cbe1c2da9e689638813618b4219acbd4925e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001359.tgz","fileCount":815,"unpackedSize":1554520,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHK5DbC/EcAs6My7eHALq0h6psIlaGMfW3U2/nZCxIPuAiAijmghDZpnsblfzwq0Yzs2GitqYUyaLHaPtjnYmGKaIQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitSb8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrEXw//Q0o8MWq2v0qfYCux0meheIWBlprRm7YvY4p0DXWHjOZK/eiF\r\nV5tjAVjpFZU2a109GPt+mUVC56uIvjSF6LXNexX+E7zBpSR45nMxtKS15/vI\r\nHU5pK0fX/eECc1ECI2++ymz1zmzIgYpJMePqUq63IjQp5/Uwg4h5LsWiG2H9\r\nuNtDeTD7SVNp1lYdN0XiKxPvDuQbErqsTjrEYIo7AQaIQ/A7QZEK8d4Xy0Ll\r\nGNcGXs8G/0foi5QWZGhwcQdeqtdVE2FVRYYKYx9i0DTQ5KVwsQDaRggMb+bW\r\nKo4ZLDE+aoaRE4vRq4G9vLOa87H4DdPPF+9p4ZhUqre2peT0izSTBgTMLVZ0\r\nxgD+xubqXWIYAuQUyT1SoU/UZI+SSWRufgxT5nRRcUwYm0rORJmUvnLSL+sm\r\nGYalpvfHMMFlJMdV1p9RyEdhqEj9ENk6vcLCaIER0q5Rbs55CCgjV1dDPPvO\r\nVf69LDmq+z/BOIvlU5o8odKg5HZeyGcQu2tJ1hMsf+plXW9ggjc3DU2Jz7FS\r\nfQ7ZCqh3la13uf4LI5T6h1Y+gH/rLQ71cbS+Ok7BEGzOMvEkP9515wHRe+ht\r\n+btnZK9tYDVPjb9+kLf8pvyqsgd6/UxUe3ruenKW033SLJPgmqurygMSmHi8\r\nl3Sa85YadaFOTUofZp9vbzJS5ODjav1WYgA=\r\n=Ssxp\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001361":{"name":"caniuse-lite","version":"1.0.30001361","dist":{"integrity":"sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==","shasum":"ba2adb2527566fb96f3ac7c67698ae7fc495a28d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001361.tgz","fileCount":815,"unpackedSize":1556281,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5GMtj6VFfYBR4a8HCYITY1sVEM55O+7XM7WFrZRoxywIhAIbH9fxUFpaR0d0ZAQvW9vqrY6xkFCv5FS+THQG2j8wX"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiu/cWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpGkg//Vq407LKEI1Avy9+ERUmgX0VyvbGD6WGkuZI7+lBaDI9GiwjP\r\nr0b/HzpatnXZyiyGgjd6ewK3d8rcXU3Et7UA5bZB0GLWLc4Kx1uhYypWudDf\r\n5unp3geNFiIhKuEx2MfUS1rtYCUmwgezxAVp3nB103WVmcepHl/VXo8E67hC\r\nJfZ7VAyxt9Bm8P3WerfEXmHrIHDLsNTRB4xu/wbL2w7w8ofMWg/YFpmIw1i7\r\nNiDhruiw0Cgw48G+omdorzlHtnHevf/7Uwvw8KyFCSIo3e2NC86nbNJkuBei\r\nvTgMTF86f1wUr75U5+fM0gkJ7oopCO0bfgB3Vb8AMDTB9KutzJFkLLHkLXW4\r\n6QDHArZEOxLTUimnwZOy4CjfzChNB+4fYjipqQoYN4BrhGosqZ/Wv/30asYy\r\nYdyOong3WjzJlFKSiOk9ktcpnhOwLvBDVgWK1wJOef5KvnXCRx+b12e/LG/l\r\nbNtmXwzmyXOpCxj+aLVIjwkzeuuJzCB6hBHJRnxXM0RSC7UugzpYd8IdSdvh\r\nGvUMAfPfcWq1EtVHh05qCXdUfW2WQKRzYA1BgYDu5I7flyiBDFnRViI9JJib\r\noAEe9f8MG2OlMG6ac/muwaMKDB8IavPE/dXIt9kez0/T/FQ8a7rGI/Qfa9Dc\r\nWjUhsYnfHd/LO0OUVofP3khuRSEfdq2+7ZU=\r\n=AuE7\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001362":{"name":"caniuse-lite","version":"1.0.30001362","dist":{"integrity":"sha512-PFykHuC7BQTzCGQFaV6wD8IDRM3HpI83BXr99nNJhoOyDufgSuKlt0QVlWYt5ZJtEYFeuNVF5QY3kJcu8hVFjQ==","shasum":"4a2a7136ca98313bee9b42f4f9a25bc2802e579d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001362.tgz","fileCount":815,"unpackedSize":1556298,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCq1O7EfxYwpQ4jdgn3BjakugJrrMdEu/E53fj4fH8+ZQIhAO1vEC80XYnPjrz/y/25JRD1rQUb47CnTNUC1WnoYEQy"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiwMsIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqSwhAAm5jykTCXbS/bRFYWuht6wTa1jPWmuThLCMG93bCGsgVmp7wt\r\nOmhzqWjx1JgE46DSh6juMfDruMJb8XIi3sUWydBLWhsmws7z9fWhaCjyaaPW\r\nZN0jv6rETdkT8PGqkrZD70q3KE9WRWu0cMG5X5WljjKA/OcW48hjT5Ai9uqd\r\n4BmsTs+GmH4ZwjaDq1oOMRrFLh77JfH3OjBMu8SO11ogQ/Ow5xpoIuvnysgH\r\nNvPjZ6eoTX5JFQTOX2NWD+FQYxcpmk6H1KrPYnmVHhHDsm1zZUXNgzSEURzM\r\nT31YOjFxSjpuQ+6HzdLax1BMHNX2WFR+uyXJz8YEM03vdlU28o8puni8eyTE\r\ng3V4Cfq1EIwhGNilwUswCY3muc6orIp29PXkGq0wFdHWJ3CNedpFRxKZS5J1\r\nzy8RENOyZjBnjf9DZ2UeUFI69yGY9U7Hta4T6z2pnlrnFSBo9mMP3pCBVzyc\r\nmgDUgxU0mGq7VUqa/ecIcTdis8hfapgE1SiaT0tNOghFtG/k3ue0TJ9lwxH8\r\nbgTYa94wfMU2ZiLNdLaIWaz4uDg3FyULSa+QUFiV50e5KNSSR3e8Ph2TB/bO\r\nlM2AgkMz+r4b57aGm09985f0JyEAY5g7Z0lJcfJXKpu2DlkN4AmPUv11dt9q\r\nsS31Azx2ZRMV5fJJYBYlIsGXo9md38+y9hs=\r\n=T29Q\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001363":{"name":"caniuse-lite","version":"1.0.30001363","dist":{"integrity":"sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==","shasum":"26bec2d606924ba318235944e1193304ea7c4f15","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001363.tgz","fileCount":815,"unpackedSize":1572234,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH3CRcn4x+5L88hN1zw0f2xonKBmQLERa6zbTrfUHaedAiAuFv26OkN+fNCdU7+vyX7KTFjmf95In+rdxApK7o7SdQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiwhx6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrknBAAl+g/Z4RQXIKkZq1QUe4jlsY2mZ5GJJqqe6Ib5iNBAqY0lHye\r\n5a5sgWMvZJvu+X4QoM5hECteBL1RaSJJOPBtoaz0lZ0aInQhQQ4OSBL2QU63\r\nRgGhU1lAy2x1jmpRA97hbUyA7knkbG//iSkach9RjQLMHxCsh8AWLCPPNCjj\r\np8c9eyOoJJTTtM/bJTGC1tmCoGweeVpNMQNr/hatXDdBcx/u43SokkNC0zck\r\nowHARQz4pd4a6J5TaQ47ctxF4ekR/w9qSxxs6+aXrRf6iw97boW7GCxo2KCa\r\nRQBZpH4YaOd3s0IjMu4vnXb3+tbxympFxTC7+oqO7kttsQ21SpTVJQy7sFT3\r\nlqFw2csdYW2pS1V3xffXG5JBQvuk6rVNIDbuhkjlhno5niKFuD0RIUvwIgQ9\r\nw4qoWdsLcdhwzWh/Qc6mZG4303FeqLtdVtWSb2r+WdRAYE4EYdMgPnlnB6hB\r\n9W4pOrm4vnfpE+p+4N203FpQxXWGKMzf9WnGwLGn+6EMjbNEJep49YQukPiY\r\nSDsieGVnwZve85dlAY2Rl54T8bT8Pa1si5y8ltdxosay3Mo6H2J8tv1rNAac\r\n300W5Zsf2fEkkyq7Sgv3nN4s1qhFdZ9pAkS3EJJNvAaW+zKJ4yo4Lw70YpZc\r\n+Pv/ibg9UqfMYTFQDuBHdIV/E7BfCK74fQ8=\r\n=WWuz\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001364":{"name":"caniuse-lite","version":"1.0.30001364","dist":{"integrity":"sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q==","shasum":"1e118f0e933ed2b79f8d461796b8ce45398014a0","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001364.tgz","fileCount":815,"unpackedSize":1572248,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJWDnmjslLHOpdKmHdFRnsx4zdNCjqL+0L0sW9XimEjQIhALichM6mwQPeFst3SptAQm+rm+kLe/oIXHQf8h52SlZ0"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiymfqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoWDA//RDaRyLyInpdqOaP+a5aHyp1sL2iFm/qgThf56+/841dfZHun\r\nz7Hsq73Awm1VKH+LIdN2i8vDENKkHOfFEBc2QsxUlB3Tf5QudWtjuo9iuUsw\r\ntxIo0Aa/V8bxNzWeKV8Hwd0v1ghIEnmVa5c20FIbqP1iyI/GLv+jy/yztmPP\r\nl0X9Cv1XUHhMZpUMp1MrMWoPceIQD7xuVtfay1fsMEu84SAm1v8oKrV1wcKB\r\n/yENtl94C3ujtCr3kgPfK6tfxxDVTbzW2fVZhqOzPG0McfGHVhX+mfAupK9O\r\nfKrFs4ondhtTI87SHxB+gxxEWtlIwSYhjMahY/PwjrSd/77q8cdFuwHmtVOh\r\n7vzpvF5NRfenmHrxJoit30pq/NwqsjAnm4LDbEBVU1h1R1slj1fNP4oci9ou\r\nw+wk5VHFxbhYVt1FiXgm9S23Egr5pE4XiL5Mf1F/zQf/gDft2wgF2XhXhGln\r\nwD94ByXzpyLLY11jPDJPNBEhaWcQjy0Jc0+8xoICcBR/1zzydtUlPyziS4ta\r\n9Ggm4ypFjebTMjy5bAuXr6SjDZfwVEbgJ16QckPuUUoQ/f6E8cQosnQYJ99u\r\nGpqwPCMrQ2Oaa681N6QcLXCu5qyMaxrlft/OzCKmdnuYUck7LbWY5zf1mIEg\r\ncziSpoC1JGRM19V0FjPUILy6iiwKqGyyTkU=\r\n=IiQ4\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001365":{"name":"caniuse-lite","version":"1.0.30001365","dist":{"integrity":"sha512-VDQZ8OtpuIPMBA4YYvZXECtXbddMCUFJk1qu8Mqxfm/SZJNSr1cy4IuLCOL7RJ/YASrvJcYg1Zh+UEUQ5m6z8Q==","shasum":"72c2c3863b1a545cfd3d9953535bd2ee17568158","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001365.tgz","fileCount":815,"unpackedSize":1572278,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRl0QGi6HOgzy1l4WniTYBMfpmLGJUabI6gqQ5i9isxwIhANJQr9JNLGzmYPoF913MlR1Xe+K32WFo6D3BIA7ybYC5"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJizOUsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpMSQ//c//tn37+TwT8xeWKsCUsRfDTxRWrBvO+Rhuuct/qr6wMEJHE\r\nNsA9ttMfeFv2+LG9Wru39+Ib8xWJvExMc0ZmngaZk2Op+hY7o8/tF2r9HDxp\r\ntr4zU40vJnj0UGdicU2DIONGWd1wGgIRaaizQQlu9bZGeHaekVy1HIcoE0J8\r\nF1PJCx9LwgLZm/YMHtSRTnWiZURJGzqR7dB5tAp24R2DffYseU6EVP7LgrTg\r\ngGcMOFUFdLzhJPRTk8gDf82h+k87j8bMUnY7qq/wgIcz0XAmEMYhi1iaU08w\r\nD32D/kghkFuF/dWkqYRfFTTfBqHj8oBpmd5w46wQU7t1djXB9uVgXTPsNMMr\r\nsTiUe8FGBr1bNtNfrLX/1Ngk9yilK4le+Oq0k1h3OngWgnCYn+Dh4dryI7xE\r\n5zU5sVZCzaIT4FnxyGqE5bNi51no3Hyz+JWVLq63Z3bmcQVOER/i4+nXS0pf\r\ncpsWX+URYKS05kGsVAABcnoPCIvj/BctlsZsr6RJYVNtzgKInVVWsO7gObrd\r\nDnADeG7/yZ3lKZwyqrxIH9uBNuO7BR47Dw6bd9zvvo1GCDJKRzxyD2ZqcB4e\r\ns5FVIAld+QnQxBUSxIDcvdYsoE1D2AxN1DtAObwygrn0/EhhrusllE6jM7k7\r\nEpWH8Hb2F8pzOmAKxJ3QRJgwa2YPlUOyMWE=\r\n=DoKx\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001366":{"name":"caniuse-lite","version":"1.0.30001366","dist":{"integrity":"sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==","shasum":"c73352c83830a9eaf2dea0ff71fb4b9a4bbaa89c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001366.tgz","fileCount":815,"unpackedSize":1572272,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBYtTqpjMf5qVrormr3UBffyaWQgoLV9l39AUyzfuPQ6AiEA9XTS8SLbg7I9OYqabSrY7BFI0W/HfhsJGJx00ypHu/k="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJizlIMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoSWg//dTJYX0xdIBnf/sAfGB/TVbOtzYPmR3e2LyQ8oSwC4fFe0Pkg\r\n2kH5BgYoYUeCkiwtl8t7BJWDWqUwg6BotuzgTRvndDfhc8fU09/qsBIYTtKv\r\nZDQsC4ShFlyachH0/wSoCnkyCr2wS7Yk9acqOapnKVAGYGhgW4JM6IQFKKGL\r\nDIy5kysbNrpI4Wn99DpO/or3URbChpQhe8BZsfCh9uATrGwxSY0qsyLb+2sO\r\nsi6NmCdzyWRoCf8nF01lTMaLO+EH9YLXKAkgpc/x5+wSIXzXQQIza5h/8gLQ\r\nh8mFH5981tpbg3Wc7/EV0+/iJTBCgGS9yR7klPAaqB3XrLini57lddKNDLNX\r\nZ9/fjz3c6Nzp1Kd6mhPeHUjbH///6i+TBGv/jH9NOaxDp7vg+CmE53GcNJ8s\r\nRDTxN2iQ9rex3H8m86RvfyWHv7xSveIcNxkypbwWK/+vSqebgb1Es16w/IGI\r\npmNqN5sEDNtYQ5bT37BKfZIYqVyzJK+mZO/MoxsMdPJIQt89iOZwOG/79Xv6\r\n2t1wFG+09XlxPj5yIMqL019nj5yb7MsWDIQ9+FWFoUv54PxMfIPxHKY3NhWs\r\n98pLLxZULKzgtsn+Mh2FnOIYYjzxNT6dlmAr9U/+cvU6VxNM75BT3jwwhhB/\r\nrQZC7STnjEExcmvmVzRIjMhSYLt09uTqZsk=\r\n=Ybfm\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001367":{"name":"caniuse-lite","version":"1.0.30001367","dist":{"integrity":"sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==","shasum":"2b97fe472e8fa29c78c5970615d7cd2ee414108a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001367.tgz","fileCount":814,"unpackedSize":1572556,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEFCJnIYOHLbLIkP/Mx9meLjypIltC0DriRoRCDVNJARAiEA24Dn3K7U4fW55OmCVwrXf8BStln8YsfrMDs6/6uyKJY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi0idPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqwoA//YauTszHam90RhLin0Kjl3SLsrQkMuPOPKQe4XHL8+StkPaQk\r\nw9vB8jHTmMG3BOWZX/mkiFMOFPpRhvF85Kin6OG9BmMrceDM7ZYvtVGDcImp\r\nDDHOG5v0QBHAPe3TtChWEjxWv1rCQ3PsPtDI1PJo2QGcQvKtMbE4HKBz/EBc\r\npcyorwuTtJqHMqWnGe4O9HbW3A7Wkqgr7MDEt2dwMbuLlhtVNwc7wDpJoJ1m\r\nel5ARfxCocMwxK0/W30zpJ7MipJZ6hmkh8rSMACMmKGiBqpsbImkxrExIC9u\r\nC/2yCPdwRfb+Abjt2Dz9FiDH4jU8V5Mz8kOlF3xlIp9MVYvMMiHh+ZjnIx3g\r\nEEU6GZPef40OlPqm72QQzc8HpmECKjMjqa3exyZFCYHeGoJZc7i72nzJYINx\r\noQPYUiHhqsa9ch2NQrps0KA/JLLiugEYEcYZ5zb5KsXjXxxZIS3hyYbaRb6W\r\ngzAZC2RTFAv3socmwylGhs+c+aIMrb84Z/3dDBi+jAI0oxXoadfX+Q4tET0D\r\nwg8tElAE9OygL5OtAI5R6EsON1r0BJQH8NiS0jpUgdVewv+CNSpjcbddazAI\r\nT5fIkY0t5fNO7JZNfACt70+oJUg6Jz47YfVi9RtGRCkT38G31GH/T+901Mvt\r\n0dj4NgaLrIM093rcz/byhQcF2q5B7KSrq44=\r\n=J4K7\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001368":{"name":"caniuse-lite","version":"1.0.30001368","dist":{"integrity":"sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ==","shasum":"c5c06381c6051cd863c45021475434e81936f713","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001368.tgz","fileCount":814,"unpackedSize":1572622,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIERmx71q97Lfw1Blvdgh4fpKDQ0XKhXZ9xilwxffHxIKAiAzHezJP80cl70boS/t1uW7S/XzbAn912rZhrrI00HtPA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi2PiRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoPLw/+JGsK/vDF6NaEy6bG1YeoKDzTMgl2I8enzGrUZeRScX09jVcZ\r\n9uUY6nZFrfjwNrBnqE5/mZx6hcprxvT/rq5jQC1OH+WZq/giLsF0/lCfiTrh\r\nRFhe/K32pcMv+xN6l5g0TFAJbPh+KumtX/jThJ5Sgl+t+z1h3pPo6zLZ70PL\r\npewbNvB1YWpqCtKnHkispFcEFeePJtqU6JZ2cfuaVOzUiQBdDPvJngiGJGg3\r\nEbTG9NXZsjA6ZkbnpRCKeMzrhOggIGVOut9c3U5qWds8PtJscgl4x7wC5AOm\r\nASdOL7SpN8VIiHwlP+2QwivnJJOZ2R3O5Cz1JNp4tvqAwj/3FvU+IFuhPdq6\r\noDQZEGhlnqIp0IxmYpO81rWI/geqXwqOFjEy0D5OIuEWJV6STahAQyo65WjB\r\nEg2nwaVxCX8QnFwWORpP097Ps1I6VyMgCe83I7xYwOwCTsEYwS62G8buCkyu\r\noPks7h4f/rOxWtZz3h8n0EYaD4BSlo+JdnI0WA26wHEnBqBCZD1RpncMFSON\r\ne1osRXN3xE/M7BIrxevZ5gKlAfI8OIPDl+iy/+7gn+okIaaawEj491zxB51F\r\nOPKQGsf8Mac3paJP0e6k8qTRPp0KSCiLkhtehN01yrhqTKbg4WpheezRb2iu\r\nCjH2+WtPknHeFc/NcmIWVeAzgr4QIkhBh8g=\r\n=E91f\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001369":{"name":"caniuse-lite","version":"1.0.30001369","dist":{"integrity":"sha512-OY1SBHaodJc4wflDIKnlkdqWzJZd1Ls/2zbVJHBSv3AT7vgOJ58yAhd2CN4d57l2kPJrgMb7P9+N1Mhy4tNSQA==","shasum":"58ca6974acf839a72a02003258a005cbb0cb340d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001369.tgz","fileCount":814,"unpackedSize":1572630,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF5nRcsvN/GZZNH++YxXwf1Ehe6v7gFypf6OnrJzqxfdAiEAxmAiSwFZjzjMiz03OY073yDKYquA163byYhY91IZDXs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi24uAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr0kw//RpDXOp4T6GwZh1xqzYzU7hTr88AvAELcLsTFaRTSUJAnfSfH\r\nfgtcUnXIjAHRoN3mtcnXSPnfX4g5gWCEjxdpKwUDjTnXpAYluEt1syfXScnK\r\nPumotVhUgbuBJDwvZUiCLi87PkX5wQ0QyYY1yONfySLPNRKkIfgdihr6cvtT\r\nkhXgU5c7QbHZyFZQ3uC2Y/9Ya0LcdDdvjdOFUlg837ZQxga6LGIP2KBEm/nQ\r\nDrI5KFAlLaS4O4U0vTnf2R5Yy2SasgeGuRZAEzsQzYETUyHsqUb8cPlxEO5c\r\n1s6uftrvU1mUxOLruIE0X3bBtRELm9g/CIdLKJepkYhAf8SKUhfu+H3lyHFb\r\n1fhtS4nyny5pbE9tAS8MIw5VASmUv9Gks6Q7rZBqb2Vsij3fjGDnWlYjovMF\r\ns9PAMew30DoR93iQU9HN3aOK9WgHIZYdlSHcEDw8B3awwH14mYVcakxy4ivo\r\np4UZfc4HnT2WlOZiSkW1bgmTxi0kjpjotizcdybhx59mTEwlu/UOjPL7fef2\r\nxYlk3rrxOm5Y0dVxFEYf7bT98tUlE/DOrBI5Oo30ngdgx46UFVVX3IU3bR6k\r\nuMV5CrAIcoa1ehskfJKg31tlQRPGBqt3fRc2G768e8R8eO926zHb6frBpRN8\r\nM9FRw2VH2Nr3Ri4f9dEqNj7kwkjjIXULKP8=\r\n=Hlh1\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001370":{"name":"caniuse-lite","version":"1.0.30001370","dist":{"integrity":"sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g==","shasum":"0a30d4f20d38b9e108cc5ae7cc62df9fe66cd5ba","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001370.tgz","fileCount":814,"unpackedSize":1576038,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFmPLWN/8KMTCcznqvdGmCfdpczl0VIPmJBA98OTLNWxAiEAiwaPwFMMFfAWRT2H1iJk0raGGvAQvdyl5mPScfxnRM8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi3ZUjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqxAxAAgkwlM1hdjRri2b9A12OqbuJ6XXFppdcQt7BjmLGmf9eod2RN\r\nvjV8hoKd2SaQCyMmWMbigOW4fSPfvhWf1E29noFCOt746XyKvjG91PcpmKq/\r\ncGJ7UJKrTS0wbaxCnl9thJ73EtIoAsHE6VzfvOVeD4se0+wU+dO6LlFuMxNE\r\npaIELIdLQaKt8DUPHRIPChn/jt/GlrXiyPEIp1YtTHKWgD1FXv7uiZtrJqEa\r\nsTztxIAEdfsn0gINEloAkZVZclocUsFp+Q8nh0B+HF9D8k6mB4wnTIaMnAhx\r\nipuTQ/Rg5UO07WZymOwXCgVj4fLBWJYBEyJaF15IDSNiKSeSZR5SoMq5GTuQ\r\ne5xiEiyFMkbOM3w0vuBFSrOPqZZ4jftfsBxlaGf+KEh2G654Up1bmPtDgDXN\r\nB0Z5ZA6f7oK/cOoXm95ES7ulX0IQoWnSAB+hY4RqBF5Dq3iP1OW2c8oF6P3l\r\nFmftmYM1zBtkb1FNtC6ePWflPRNBRCedK1IeEGdzeCOrSOfx6UdPThImbqs1\r\nF9VNDZIbWHBJ4I4S9ylxnhdYlmLFtEAVqv2zKipuKp0k7+oD4ex0w1HHmM86\r\n/MZc4I6SlRkDAcb90lVnM/JecHvVqKyUBjahBS5tSiSEvFpeKyDE3CbMDmBy\r\nvQYwF6shtOZm8DNupS6Ln1p0XHyZqhD/WJA=\r\n=/SXo\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001372":{"name":"caniuse-lite","version":"1.0.30001372","dist":{"integrity":"sha512-tBgBhIXBIqORB9ieUEYBKRfSlaF6YPq7WNNqcreF6Cl24UKNGIvE5/rP59dOGN6TRIS/5zOMHAMSRrVNmifWWw==","shasum":"133db3d1d259d8f97cc2d83ac7cb519daf36e07e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001372.tgz","fileCount":814,"unpackedSize":1576052,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMGX7hIBMW9e8fAj/cN9WPb2HdXj1y3uWHtk/Pn3+WYAIgR9cFOGa/Ovsu8ZtUslBo+96nSJ1A3NlbQa6+qZOXe6A="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi4iN0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqmig//Z3/qJQeiXQ1O3BAlqF6lvrN2NyxdM/MgPWgBVh/bLhJP7fdF\r\nY7/YcwGEKeoAmddNV0tKMR/aouzwdIGX/ivzAzzx5sMSKm3uFvjV1QOwCaDN\r\nM0+rrBVqNiZFMPgWFu/TJHARwMNT7yPY48Dbr0JJB2pa3JZBKVCwQMen2oL2\r\nA8QBvr89j1DUP6B/GK2SyLWsuqiLem1NJ00xfetdbtygTWDhOxtrnHpYOR1U\r\nwbakGKQgNI8Qirax+Uum9LwbNw5RuxyEF6cGF7pPt2Xzv7SIxTGjC/plOQcH\r\nK+gONC+o6TdB/tWmRk/Fkri3c5zs98ES9qDsWCUkzAXiUbzpIlTkpHuTl6zc\r\nR5UMW6XWdDm6u5jules5CTprKGV53M7tAesyASjKeF9UM/qci6M8CC1ryTmP\r\nPkOpKiWVKPVqxOb4D1c1rP3HsR980OI1inT67QuIEuFJUZ6PuQbM+zYYTtr+\r\nz87I2AMx2ILyf3hZ9gc1iTuVUnunDzxjSPK00MR0p3tMAyM1LsU1iQ9t+iX3\r\nPfx6Gp6ubfHNvU5wL2BaR6RLyKRJrWas8/VSSLRmcJcCYK40iTO26ZzgaZQV\r\nhJhyt/nj0OsXJlHMMCEtQn/cJB0fuV6/JXK06k3T7cQDoaCtXOgocfNeCQP2\r\n4LVKTODDOAfGKUkB1F/llyB+/JGHEFUnC1o=\r\n=dq64\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001373":{"name":"caniuse-lite","version":"1.0.30001373","dist":{"integrity":"sha512-pJYArGHrPp3TUqQzFYRmP/lwJlj8RCbVe3Gd3eJQkAV8SAC6b19XS9BjMvRdvaS8RMkaTN8ZhoHP6S1y8zzwEQ==","shasum":"2dc3bc3bfcb5d5a929bec11300883040d7b4b4be","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001373.tgz","fileCount":814,"unpackedSize":1577807,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAD4XrBZ6zamwvpdBxvM5rZD0RlnBzp4v6INlpRoaNRKAiAQGplzaVWg/M6EgQA8zQWSAeKkZlCuqegOTe5A3r5+TA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi4jK7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoUBQ//dZUgCp4mJ4R7qNagHvnx9eEKvnWWD5yEhw8Z895O3VPknZKb\r\nbS4iImaZYwQPuO33zqCmop6ZeWFnUzCYYmvRX98EKESiYKrIdM5/x1OQRdHx\r\n3eXkfvqFVkQTvj73B5ceN8JeG1hRtvckoLE4FKBRTNmZvtdYb8Y/e7sxEooF\r\n6ipi4BOkrt6lvNpHDtiJgIcmYzQ2/W9Vbo9KwR2Vdt/o5gBPnxIxcspxvMtB\r\nyqtZGbrXiIaPUYPZQTDYSctDayI5dUGdEjDQwO5GXPh+6xPdNRyvwiBfQnwL\r\nd7YrLlfDU6/KyLZxhOvM5vDla1oGAwGwdiLEmQOAJB6yzzgyvwQq7dCYbytI\r\nGb/RkrZ0akKBlAOlrNsuswfegiFdLDUGZxxCrrmvgLL6qF5z/uPWT9YcFqVU\r\nZnt97Rkb8vasJZL1DrAbGof1pjTEFViItWtz2bcpVl5no2Af2TOxkZPgWa+c\r\nt0wKj10wg+gmQ6eiHmBnm/E77A6JHNZ2k1Xd5H5hBkb9RpQGQ04eUcOiE+U7\r\nXRHB0OFoPo/Va0zhwUDu4ijZCZivr74szW/jdeO2z/PYdI7l85nH8MVX7kqw\r\ngX9IQD9Lc/lVvJvfiPlYh9VRsntS1HClwjhMQXXkXh4kRtp+2XkpUl8Zrq9h\r\nL7cnw/uJvyfv1/HJc0j0KF9nNs7fr4DH+lo=\r\n=+gJN\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001374":{"name":"caniuse-lite","version":"1.0.30001374","dist":{"integrity":"sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==","shasum":"3dab138e3f5485ba2e74bd13eca7fe1037ce6f57","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001374.tgz","fileCount":815,"unpackedSize":1586822,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC56iChJmmV2rbmaHFuFxrSmsLugv2iu2PxEIZNPVCuSAIgZXWSuoD6cyUtjUtO8Btmh9hNi3PhyDz+xVN8Qp7nEDA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi63mcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoqMg/+Jm3y1D1LUL3arvJBEFSFZ442xn6MIbqAQCKpX5/wvVTGXIMW\r\n3zj4KZX9yd/YW2wWg9ifQfNyCh9GnO5y3Zevblu592EC9CmzzZuu23XOxQKz\r\nK8GsDYoAJXsFfNlp22FMGoMG0X+QxySaz6kJ1teup9hBk/uWp3UL2qIoNKpk\r\nL728iN5s5UJwZ2mh/ZDem8ayl77tzDcbd6e9IktgJ4M6V2O6dxoJhIngOUfD\r\ncHd5oTed+YmVqLjldC1SKP3ATCyATs+91El81IGEqbydZhpY3QInMXe95JMd\r\nO2/0UfLLiS+BjrgBUgiBMs8JwCTcZmRyRWX8O/IMqrTbEs8KDPJTzs5Nb/wb\r\nhOQO3Tsl/vJc/L0WtAgCfwMOWCDRqYDkSD58QH3LQ3ExVUaFJ4aDbXQcJd7n\r\nbra5SmQ9+4WN5NDh8PMe7LkyyabeviXNpybU/E2cb0Y4n1rB+PH/WJSDYrhm\r\n1OVCmwqOHyIKChqtZEXyiAEmpZ81XJ7h0hA1tvkVe9Xfe4MxyniI2fhEudkb\r\nMMNxongUJhjEzV9QtxqTHR/xA0Tg7Ra4Mlhd+LDLSUYoCDSEQhL6clgNkiAP\r\n3rdnDHx4erUwJ/O19rawZfkyrZRNqh6krLJqvE7L6a6DpVPRWdzUAIJLg0AU\r\nPFzn1XszEPGG2BXqkbbsOQ3fLSx+PRb/FVk=\r\n=wq+k\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001375":{"name":"caniuse-lite","version":"1.0.30001375","dist":{"integrity":"sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==","shasum":"8e73bc3d1a4c800beb39f3163bf0190d7e5d7672","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001375.tgz","fileCount":815,"unpackedSize":1588538,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWQORJgLdXoT7z0CwFCaT7t2Cwm1mpLdSxz1nTi+fEFwIgezHM1LYSbZOD+bS/wf+KwIZYNY7p0b4sc20JI+DVIrU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi81ZbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrJSw/+K92zt3Y5xuN9D73ed/5LoJR9x1pjltMLd3qc3AIpldMK4AB5\r\n3W7PivaJv64W0C70n0OzBDjckE2teZlTmN8vhdlTbmI9LbkbnCfAkWYzXx9i\r\nyQhGfkjVXoLTov6YzD6G2FYrOwpqM13tQs/G+1OSp/NXB5i0Lga9rELxdo0I\r\nxs3QYn232cm4sTs9fa/s5q1etYg14XioLN9/ixrEutF7t+/yBlo83QanYnCH\r\nCjAGrzVh+P0d3k4nL/Fv44LJ2RaWmKJFi7ZecvQjv/ud+YBtM2CQ6sv70wG9\r\nT3od79tVE+0gxDwloYgi/33L1MiY/mQFp4B68xJsXvNUfuenigTfZ6ZaBgLw\r\nllHJ1twcJcNOdboa0tGjrSoKvuXyoQnY9SUbPKKoKd4z6SzIGSqhwbetKYCT\r\nXwoKZqxkNkyrFrrVbztBJtfeXm9v/eMFR8efCzr9H1hJuqjaQ3IysI4Qlubv\r\nYD/dDrX7s7Pm5f1B0187NK08SS4jLxRIBK58YkcHnal5mADv+2DUonhHPGo8\r\nnQIo96ufkGge5OIzozT+eoXpkkP3UsCL1YjNhayMOPIn0HC5/2DWv5EHVzMA\r\n3xMRMu7al3+oz4YeHwmaQE5Q7+I2PfRQuM7Fs4p8gk47bncG9t+tMC4PTBU5\r\nd2WYhUnpu1oGE1hbjrDd5GSYAKcQ7d/Fsk4=\r\n=/hrz\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001376":{"name":"caniuse-lite","version":"1.0.30001376","dist":{"integrity":"sha512-I27WhtOQ3X3v3it9gNs/oTpoE5KpwmqKR5oKPA8M0G7uMXh9Ty81Q904HpKUrM30ei7zfcL5jE7AXefgbOfMig==","shasum":"af2450833e5a06873fbb030a9556ca9461a2736d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001376.tgz","fileCount":816,"unpackedSize":1591675,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHI0/HErB1m/5Os62hzYXPi6oFTCvwaUVy/jxESelb0AIgU3mdLBWfFWqBY/rBVlUxqCUiAsV7RpDBmanvbrShMjs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi+V90ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmra/Q/+KRXemfEjYLRPgUadltg7OlUuCAyWAIgxsYcd/QHR34iah5Lt\r\n3/3OJNrx3vJ+tA+KH1Iupmrb0eB0MKCjSmXkLMHUHVGiJBqc1NOCtR74xGNr\r\nvvLFDBkg8L2bFN1+JHLJMzviFKRP2e5LJSrD9maAEYSeHD4N0m6XIavpvQ/+\r\n2aYXc4UgQ58T0BK+dtyUXbCpy3I2WxKhrPSu4+E/yVg6wp/36Fzknhz4FS9n\r\nj8E3BsfvpIL9VmnFv2FQRbZyrcPmTDkvttt4gFBd/qZeCk9kmBoSyfyaM3Rc\r\nszZo2TzGOPrH6v9s9R2WfwpVRAMyrfdKqyy40Cw1J8rRqVFXJLIFXbXaVIKQ\r\nj4217+UAueQ+AV/xNTtUe7JjQv3cbWUxA34BKiE1CpugFW6nC8DFzuCUNUd/\r\nFegpTOMVpKQotCERH9FI+rLB21XcPHAD2dRR4hc4ctftLnhoUAAucs7P7b+r\r\n4cwiOKQtct+UxeYzdNTi1JopCUi70eqp2FqOYAafPplyJ4u+nRsG3b7oR6Wk\r\n34ouId52z0GNcZ8Ioq/86fwG8uworbS7nh51Lnv2pIL89Hss3uEK3IgCZ/S2\r\nMpy0yT4s3ATFcD1llgDlUz81bsiSwPW5AX9tEezgHZh4nW2TQF7aTGWYLTZi\r\nW7kn+fK/HQILR1krx5FGd0GrNGgGS/mbLEc=\r\n=6wZT\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001377":{"name":"caniuse-lite","version":"1.0.30001377","dist":{"integrity":"sha512-I5XeHI1x/mRSGl96LFOaSk528LA/yZG3m3iQgImGujjO8gotd/DL8QaI1R1h1dg5ATeI2jqPblMpKq4Tr5iKfQ==","shasum":"fa446cef27f25decb0c7420759c9ea17a2221a70","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001377.tgz","fileCount":816,"unpackedSize":1591675,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwD+VSXp2F2TCX0TZimoqFct1fFG3Cf7A7tMKVhlAPrAIgDOI7e1gjehoZuv1wtN09iQgJzFAzQT+VkgPA9QVSSEg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi+yUBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqdTA//X2GWR22QPGDm6Wg6JlTeNVG1kwkItVTWMnp9IZoE4ITDkDwO\r\nsnfmsTomW9SZyQqAFcuzujiSXGf+hI3nlPOhfQoByp+Sqp976KHpqcbxfwTl\r\nD/RBIOzxdAh+Pjyjw7oF2Q/KDigtuFVtIw95IUD178xbDLOJtphINydqvZG5\r\n39jJ4a/96Thp/Sl4twaAsxNC1z0NLPIEDGhZAY3Ak9u9LdX05MXtdSNUXA7v\r\nsVeN3LWpw/Lnio5oBQwXF9a4FUp/jWZXvlyQeoIdTq7OBRCiU0rnco6eM/kn\r\nNHk4qGLkx7EHLB0YAxCEg+1TeCflDbMQC/q35abhgbG0JshowyEJhkeVlo9t\r\nSUuDVVbxsDSpQsFsc1EdrUQnftldsYPKpqOd3sSEEvRcvseTGcU0JPv5C2ea\r\nUfxXwCbCmcmU2T7Ykus8pW0wjDAoF/44pokt1GNf5cpxyigvDphaLq6L+LEC\r\n/LBEpNzSXnoBrU7nuPrXYlt23kNMjgZfYPF11MVd6eGf58rRiVOmYpBW+3T6\r\nLRKyAP4t5vVyPPfmdQuGr0EoMfbr1GSEtuzUgpw15AbS/0DOFtSdPJpQhxnY\r\nWSq/pw5Dz4EmTcnRElPpNismw66VudX74V/W/x8ceTE9yG/+PfUmFZ7Y49pD\r\nf3ROu/f19EfDcR2uqaFdvxl0sgtnen03MqQ=\r\n=3Obp\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001378":{"name":"caniuse-lite","version":"1.0.30001378","dist":{"integrity":"sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==","shasum":"3d2159bf5a8f9ca093275b0d3ecc717b00f27b67","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001378.tgz","fileCount":816,"unpackedSize":1591675,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCH29lh/S/kbz9sV0zkWDbDg8zyp475PkT/HhuIEbey6MCIQDp8YLk6fp2ZPVEKnNy4MvGbQs01U8QsI6mv+GZMbDkYg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi/IOIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmppIA/+JeFFiyCWwlC/Ku8/FDTeWZKB/6j8F4wsKwt02LA66fY8sY8t\r\nw1GbIK5Kcft6l4xwPzP6Nw+E/wjFCDtF62e29/RrHe65G+yiPyUSxwB2fZ+s\r\nwluJOSR7rtWSoba9Io+rsggdg42U5YXKoIQ5f5R7fBcGR3e3egvRAYsqB7yh\r\n6CRpezZ4sBIJhDpIBKPQi74BMlgZnUx7H6Tz6aCw7ZVkmrOE/1RYTH1Sha/L\r\nksPoQ+qNxGK8A4s1zKebd5KmnzXZXzA0UfnTiYNmcAFt+xEoNRzKF5N4z9xr\r\nmN5mj9MiK++K6c5kgki1q5OOP0acoVDeLhAtDPYAvg2FdHfuspcxga+5IvRp\r\nPHQV3RyJE4Lk21y1sT0l+GZQTYW7QaPut+n5QxRcrydmV8zPu0OWspqmUfKH\r\nksoEX6Jg3l/l7YCH9YZeKUAxsYiza6A/NOAyE26NtQeyLl8sdhXuzXCtMXpr\r\nwBdCR/mwcKH1aShKgLNAxGPdlCSy0YkyR/ZtmdpuHuv2bfsu16wLkRyluqP8\r\nQa3TWXkPj/U0bQmtayM4nfbl9YB7OrsTT9YZAOsOL7p1hYAue5QeEtESwC76\r\nT1adESK8NiJVQWofrpJy/ldJ306rJh9Ynx9JNJG+0rHmTzoCJT6zVvX5vpmR\r\nwXZuXpZAOu3LWuvs1jd56fdu9GeKb/ymDcY=\r\n=r7ss\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001379":{"name":"caniuse-lite","version":"1.0.30001379","dist":{"integrity":"sha512-zXf+qxuN8OJrK5Bl5HbJg8cc5/Zm01WNW4ooVWUh92YlKqQZW3fwN5lXLB+kI8wkP5vTWkIIN+rutZuJhf4ykw==","shasum":"c42f61d3ee45152ad0fa5005a6b5b34c27797a07","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001379.tgz","fileCount":816,"unpackedSize":1591675,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCFEuMDkg3tzoJ5FXucMqcawdjRucm7hI4Op9kYcJyLewIhALIPc5b3gV2tx8rpk6ATWOm+42Er8/l8GXHsvhcpTSpp"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjAGAoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmposA/7BuTe3HI/A7xM72LD2QO/NBDEOvnXfgIal48K/8yoNkL4FN5u\r\nVSTjGd3IE19YAvX71BmI3Ow6lbUrTL8+lEDs+sDA2LkOzws5KjeT25rNZfjK\r\nJqQCMMENITg4DnpBep5Ub/FwrTKBvzND1RJbfOwZIaXCYy5WshMReArnO57c\r\nzmNoZ2ZWY7y8TpDyMtjcv7sjf10WHtp8Xp6gXLUDunJdzpLEkMYzBBJEbIx5\r\ns6mSpY2w9qJk09KeqgToHd2hq0Ol8zGRU7rsMHJKwn5bdmQIWKWaxlExAPsV\r\naR/9P+g3LK/H7PULTojn/uwg7vWIfWqpPYPZJ72rhN8wSSlXErPIgIkzfTFn\r\nfejhM6qEHYasC0R++94/t9aQsyq2uJfWhUMV87o7ujAe/6tit4BihFbY+eNe\r\nU4G2Cf5SnkSHNWi2OWtugsrXfoLWsogjSi0W4x1zOxbdrt3KBhsRvS6Yv1Jy\r\nPOShstt1dFg/kHEzVo5SFO/9wYWNoul086gFwlZFmKgACuD/+gnNrtc7RIzU\r\nFpgz5/fPD9dAb3GZXMjg4yZI1zGomDM0XiATwnWQbX6qL+yXXM9sAHNPg5Y9\r\n1ERubw0E/NFrcgKHC7Ar5ZjeKVmzZlQc6x5lYAD+aPtFAxxqD9qL1snHv8DU\r\ncX65xuN8QqZMwPDAAUvM8BLHDbS9eJIlfUo=\r\n=oaBm\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001380":{"name":"caniuse-lite","version":"1.0.30001380","dist":{"integrity":"sha512-OO+pPubxx16lkI7TVrbFpde8XHz66SMwstl1YWpg6uMGw56XnhYVwtPIjvX4kYpzwMwQKr4DDce394E03dQPGg==","shasum":"6f2427ad8ebee1b400a38ca3560515756ba352bb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001380.tgz","fileCount":816,"unpackedSize":1825241,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDvDN8ppsoFZcEf5rqpwVinA9hOC/Eo8SgeUhMRl2FMXwIhAKVgC24M9SEbAmxC80OlGjI4fMKue9d2HJZoQ3sbkyI5"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjAWSMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqo1BAAmTNCDye8liZvuiwEoYD1YbXEmuF2bm/Iq3pP+LfII00DLY/+\r\n2117iuHdSOPAJNfgqUbqiF73D6Z1ADcfq+za13ayHSPnGm7xomSXycmzhjjj\r\n3GjeGMT/SncleXBtM04puxq08n3a6sEABA/pu5LfsJitfypPdqd3bzK2ej1g\r\nW2BqQ/2hUT4hjXSurw07f5PMV7/urJRsDxvvoZ7OEnQNkTuU76nv2TjeARH+\r\nGvUQD38rMWby/Ly2QTnrqHRK1Fry5zHvp+jkoUpWNbWAcCgsbRtFYBmCsxNW\r\n1IAruY0z1mF8yaTJO4H3WZ5JXgUaJabI08lP+00QyeMMF5+UzJ4u/nzqeEUm\r\nnoiW0Vwth8TphZRriS/QMsmGGwjMD5sR57Sk7y6nMukoRjKrozMBTJn/MkHE\r\nbYkAywygYIKcyJHd/nro1v8iNRyiD3YKHdEDTgDK7zGrgMkjMX7J/mngtpr8\r\nOuugTYULrOnGICyxZ/zWs4G5/rBGOh8B00Vj/3qsdt6cpDgXwFMgX7KxxeUi\r\naVEtKoqr7jtMJvo541IP/U9sW7yYxKkYHvXBW7G9R6ZTNFmuw1McZ4dhazoj\r\nCr+BO4Qygs82j4xWzqwk17kP9MOncJTyADF8A0gAg0ITx1z8V6fFZoNcSYnf\r\n7A2AxSqCfm+AkfikZCVCJP0J8eedXm44YgE=\r\n=8sTz\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001381":{"name":"caniuse-lite","version":"1.0.30001381","dist":{"integrity":"sha512-fEnkDOKpvp6qc+olg7+NzE1SqyfiyKf4uci7fAU38M3zxs0YOyKOxW/nMZ2l9sJbt7KZHcDIxUnbI0Iime7V4w==","shasum":"e62955310e6e69cdf4b40bc5bc0895aa24bc4b8b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001381.tgz","fileCount":816,"unpackedSize":1825249,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6AeYHdMoTqDsV1jBYgibWlwcr5FYEszGiwe9Qyp7ffAIgQY0TFKPCfoPszHl743ogAWY8ZZVLHU3hLyqhgGOBf6Y="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjAyjNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr89g/9FTTtVHuXM/HdHA6Vb+9LXgMgjDwdAqrtHe2oZ7ZYgkZQf74/\r\nVTrbbd+7llYfHOGFAZTO1SRLBa81Imr505sKCUYDN6moKZnjGcTLKZ50ZnrA\r\nrx5hGryYmhIqvnbBsYjwLsV1it+D6pnrtMf2LqW/h+x96dK/ZXAYqjZ86ZfS\r\nxZRqlK/FdgziyNzJ//+8zhOxJ6swEeVSHCIjrPIVX0w7Io2IjBmxn+pzAZhi\r\nEaTFEGXAJrzTd56bVJZE/9pvd1ZlkzfGoWF2BnCsGOT4LJ/43ocNaLkbngmi\r\nYwjC3cclluov3pAdf+20ORXRar2156JxlLo/FrvkOjl9E6zGCRk9l72NG7Nx\r\nmJBdPLFHRaANPH51yP8X3fgC5dkgmdGyptVfj72xp5joctgB9oHspfOy+uuU\r\n7nXQNGBJQ2KsOu5c8Vgf7C10M8VFYSxA0/qoDnFtBAWaJqQhEZ1Gq7s0grER\r\nox7Kf6nsu/nvpOTZ4u73cQfUn42Vp3gIkpk9w0TPDBRMd19Iguk6oAhxKJe6\r\nZ5+C6llWmVYaRqVAg91ua1YpxT7rWxveh44Zbs+ioPy8QeQyEthHc41c63E8\r\nwPYxW9Q3ttjFGgWM+AU3SIli2nDM6iA1zbSapJXkdOafdVtq/nxLBPciwKNF\r\npkYc1/1Wa0WRWSeQmUVx1bDl8gTvMnpPn8Q=\r\n=2Zgx\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001382":{"name":"caniuse-lite","version":"1.0.30001382","dist":{"integrity":"sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==","shasum":"4d37f0d0b6fffb826c8e5e1c0f4bf8ce592db949","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001382.tgz","fileCount":816,"unpackedSize":1826947,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEdtlKGKTb9oMvsYj0dliKVuC2vxhTQBgkregKZ3f3OqAiEAsJKFxtNTdpIXtPKRRnPt0YsQIg/f9eX6sIWEUWPY/hQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjBEboACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmootg/9Hq60eG+9y18YrBXrn7oTf+KAnFbqB/85MPv4d7QEdbkQSlBe\r\nNr2dbD2yS5+moyy7DD1eom3Xi+yQ4ooumIkOIx6IA598xfSNvcLGj4oSGCKd\r\nyS+jytxmyvD4RQDoxJq1s21YrMY4TkmfVDjN0QnmekxbJzQ3wx+MPINwY6LM\r\n6HzTdHDHV0nvTV7tSmCyuu/CnfJzoIaVhX73O3Er8saR10SiXMp9G5iCWIoA\r\n24f/kgrdybs7HjxJO+dpvhNqbnn2A0CwEIp6AOA1EJlPliEf6WN6L8BnOfF8\r\nEuSNfBjyNJnKAC53TEm2lcorG2T+6d/1Chnwum6NWsbudKoJbre9pyywy6RV\r\nMrqZWeOZv81/kSu0A5oFAeRDvQWnBZALZ3fvyax6F7EMqb5gNDKNGlZFVSZg\r\n13MszvZQyPdErQq3XRLvCNYEgdevkDWTvIWnuIG8VRdJqmCb4z9qYGaWRUc7\r\ne6DNQ3qHrjMDgdi/s9KS1QD1VG18Jct/PE6Hrv/zbKVZi0WtlyIC3kcJUIxL\r\njV2k2ZWUS1p2Y+5Stt0OQjbk1163iSOeBfesBgyZZswsNvxPW5gi51yafQs3\r\n6oUKW2CUXQf6Y4QPnFnlOW2PeVBlXM7RkhnDwi1YklvjMkFXhZXHBwLdeGQA\r\nQbYHMRUtNlCoIAUQmIwid/+4s7im92wozwM=\r\n=UdBW\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001383":{"name":"caniuse-lite","version":"1.0.30001383","dist":{"integrity":"sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==","shasum":"aecf317ccd940690725ae3ae4f28293c5fb8050e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001383.tgz","fileCount":816,"unpackedSize":1828712,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBeIXrkQ5y7M1QaAG1hqrWL6x47a56xXvpatsKFQMjK3AiAUEIBbNH/3c6WZ4T6A9sD10FqH1zCIrofvJ9y2hV0QbQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjBxPSACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrM0Q//TrlRSmKBl39ak1JNG0DDRj0w6Exfb9yt7CuA3LjuKMlB60yc\r\nRoepCkg1wQueVDW71lmY6SfIsLWdBQg/oRKdfLlH9rjf7BQbxMkkzlHz5v0w\r\nN38K2ppKrrhgYjrdbj27FVLv67pmcoACQaYBGhZ4R7THXeGt2XRtnM58ldrj\r\nxWqwZ1S1zopYqrnxBqdurICmOdyrItIkadm+pNxYNV8ToMvWLnH4l97v9MOa\r\nWHIE8VEeTUTPnx4WI8+bS7cVPh/Kiyu93ojwbA0cTavIOciW00oiFhPJqd94\r\n7M1R62SdZG3hV8Jus5O8qrdMyqDAlQQoWDsOBAeTR3zVDAgJLq+EdbgeG4m0\r\nygADT0YwDsqTtRxil7HhjgE0Pz5XR+YHD2eVwDtfAKj2wIZ3Sxf+jLb+hzLi\r\n8g5Z8QZjOzND+Een40EEx65r2f336i+Uza53TSL+xqI7PP+UquW6dIF6lhS6\r\ntLmt6/KO2APsbTeXWkDj0rbka/9Hem837fb439yFEF6/uYuzYjQ7hixoJAWo\r\nygQ3EAH9DSNj/Q3ApH2MKG1qec45NY/VgCAhgXH5smwthcNrlqvjIU6D/3Eh\r\nqoUUv/GH+56LVcHXpxZwFNR23yGoDONw9EBX0xLFRE//+ClQmbNM1ELplf4X\r\nIqkq7/AYq/O7pwnJbivGUeHLX9j5ST8jKgQ=\r\n=XoB/\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001384":{"name":"caniuse-lite","version":"1.0.30001384","dist":{"integrity":"sha512-BBWt57kqWbc0GYZXb47wTXpmAgqr5LSibPzNjk/AWMdmJMQhLqOl3c/Kd4OAU/tu4NLfYkMx8Tlq3RVBkOBolQ==","shasum":"029527c2d781a3cfef13fa63b3a78a6088e35973","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001384.tgz","fileCount":816,"unpackedSize":1828718,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKcZoPgBOTWA6blg8/yjYhX4KTEJinw20vMhkpmktyTgIhAJBDV/cfGyYWtJPzpRD+1D7sU/g5058ZI5aZAc/tvmeY"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjC7mWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqXUg/7BEJecA17Msa10a06TrusGzlkECoDKUscQ9T+6ni2wyrl9W2d\r\nlc2yxwlRp763P5B6pHbPm1hdYyfSU1iqgLShzUpRdCADppRGRZ4K7XlAM0sm\r\n91dTQw8ZC0cVjDOXcgFGy3RlgErnHsfi1EicksMZtDiFTMMjIyYnClm+7mm8\r\nmUFJqdsKSBidUN3qm4Wne2K4vdPl7TSjWR4wOOyqQ0bqH4YTsrXD/rC/Chrd\r\n8JWQ6u8kRRo1nl3vttMp+AVHeXuwa+FUL2ApM+B/0Lt43V6kczC0E7obITrM\r\nKEIhZnFmyKi5wtP8jYuTAvvXk+zkPXcdJHBIEsfCAzwXTbHzQ/1c0xr9iDdQ\r\nibaJmHPJCx89kPgzEWLaQOXN7kIM+4JI4vi0UAT3aCE2EKV7z62Q6QY4LwMd\r\ntLx3VDbZUy6IgjHl9wMzYxI4QuPPM0Xh0LMewoSgYmSgWbqo8BXUMvfF2Ejr\r\nL8pFL+cs+OlpEHmcOmtJ17bVm8jYYhr8dtH8/Gn3pX1BTsMx1B5k2dvJErTE\r\nmcQN+vtdE109s9bnHgdx1oQrnTjs+FKYq1g2Bf35DciFfeHcK2AMnCuM+YdC\r\nriTh+J3KEpMyMw81xAf+1FNvuNS4j0H7TOvHkBhfj1URzSr8ngVjBcA9RvUE\r\n45v3gQt6xSyMsy7cqcyrHM4VYJHVLvzAgSc=\r\n=qX75\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001385":{"name":"caniuse-lite","version":"1.0.30001385","dist":{"integrity":"sha512-MpiCqJGhBkHgpyimE9GWmZTnyHyEEM35u115bD3QBrXpjvL/JgcP8cUhKJshfmg4OtEHFenifcK5sZayEw5tvQ==","shasum":"51d5feeb60b831a5b4c7177f419732060418535c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001385.tgz","fileCount":816,"unpackedSize":1828709,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBQy3Ggap37XduFGvAcHMkCKqM4PmbVW1EWjCKq6Bbi7AiEAi/H/2Db3YItjz3qjgPKi3ScdckUos6nNdtQG+y/VDcA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjDZ0/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqQhw/+NPINE+iJ8lvKo4jnrgfOqBIsPwa0JiEKIA4VBgI+e7iudQP7\r\npKD+BTU+MXZYHygfdf/nge7xL71zsknYsRLwL1jN7HmfnlhWdTHON1f58J7w\r\nl8d1VRxft7qfHAKbNKIBr6uwK+05XaZkrfuNA04SuPhHC4nTuiUC6ck1bl83\r\n5S1AQkUR49YqzCVnu+Vu57NL2ydqOJxIXXpX/F0Wq2uu6Mci3rOAR+zUIW8Y\r\n92LhSFOUSRZaekLwFgYbwIG1JcYSZNY43QTX1W27O88UudBpAMJNX/NL51UG\r\n8wgIR7bNorZKqp7r89+Kw28V+EhAIyLGSY5PfzOoSbuxkAtAxdtkH1H1DtDW\r\nir1pyBLZCKtMM3PJyH0kRPsfHj0cSzblADwRGBjj5C8ssL+BsXaYkEd/eeXH\r\nPKqXN+DhIfncuc6jE/4VjsYqa2BbcZ5q7OVZDwj45pwApAV9Vy1MAAd2g7CY\r\nalxXyroZF8tJ3SuP9GNsGkQDhNFwtBQJ9xPYS/1TVoYENDAshA35IY9URLj8\r\n52QgHOiWYPYvFHhbitEHSDkW7DLWflDlWNlh6DMmV7bc3AWQCzLduq+oFHT1\r\nIqxR8OTnMiQpd8XfrMGcWPVbELPforMyzrF2Edv1q8T7hU11lZI3kmFZiHLk\r\nUDjtmcC6HmDnkLZNbFy9X1tgcnd/CJpYDP8=\r\n=FuEs\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001387":{"name":"caniuse-lite","version":"1.0.30001387","dist":{"integrity":"sha512-fKDH0F1KOJvR+mWSOvhj8lVRr/Q/mc5u5nabU2vi1/sgvlSqEsE8dOq0Hy/BqVbDkCYQPRRHB1WRjW6PGB/7PA==","shasum":"90d2b9bdfcc3ab9a5b9addee00a25ef86c9e2e1e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001387.tgz","fileCount":816,"unpackedSize":1830422,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDYdwlBGMTCTQiASsjiI/yHVrgFjtZEfQvfiJdVODLbfAiAzuBv7mwh0RQGpFa+ywcCp45MgizwoR0TltH/7sFQsJg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjDwM2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrjyA/+NhibaU95MBQ+wl4cdXtTGyY4vN/+G+eCjN1JPE5XrM1oAOXe\r\nZFJPEpU+0l4e+XQJ+0ezvOFy9/YvkpUlUwSTlU+7WYh6Lq+a9C0bKbUfw50k\r\n+KAgiru69VW3a2tXDvoBUTFJJ7rDfsFAdUcHvgGymdCrpr/LC0msLTnbTNS+\r\nrhmLmCWouepSWNSQnMFh/YK6lVxcuRP5ty6druv9c4nzCZ0KBXrel9Ip5gAL\r\nQXvX+QYwz+j5pEQgrlZ+rAKamOQwH5BnK9UTzuVhXMCSf/NgoNOmoLpvodUP\r\nXHfJHPf82OAcfe9wxpNf1ZQShfSyJxYepaxjV3IA1UjWe9EASwRanKaNEjNW\r\nj9NGXS0eKolGNXudNv7qaXpDIy+IIJIuuNKg05WnvYAUk5jz6yYU6ErWj6ON\r\n3MQs3Jc6hS1HF3iF4+3TSjJLMs+LrDedhXMCAB5FEmfp0Mo3raq13NKezGcD\r\nj+rWCenbdSTTEYudT3sDTmQhG1PxFPQmYE/LykDo8knf71F/RLqGlH6o0u4I\r\nYlld58sNM+mTN08RKuQfGKZLHN/FHxz3uUSJic/EARraIR6PiTz2h6rwynaw\r\nhJGxo7uIXO9g/1vAiWL3ECfxNi+r3GlCiW6JRwrBH2eZGES+2JJIDNscmJSb\r\npe6kIdh7hXCWNS8DgS+ne0yi2tVRtSR+2ys=\r\n=+CKC\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001388":{"name":"caniuse-lite","version":"1.0.30001388","dist":{"integrity":"sha512-znVbq4OUjqgLxMxoNX2ZeeLR0d7lcDiE5uJ4eUiWdml1J1EkxbnQq6opT9jb9SMfJxB0XA16/ziHwni4u1I3GQ==","shasum":"88e01f4591cbd81f9f665f3f078c66b509fbe55d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001388.tgz","fileCount":816,"unpackedSize":1843632,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHrOROfhtbhhca1UTrpbwUjGIOPKVMCV7SpljJ/mQ6FrAiEAllLKnN7w/H1pwyggaAQ2hKwEGM05oEyBV1k22oIIMto="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjEaHDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpi+w/6AuHzYkYQDMvtqkCmyEPx16aUR5/AgicePVnBfBq/80qBtbFg\r\nP40iahsmWrINnYUJjZeg3DVfW8IAPJfnGxgfTdTdYfZLpHV7hi1HXN4u0zX7\r\n+KHUQa8H5FgeTiZBgKig8SmrEIYdQTglF3v1oHHMlB01cW+WiofikbswSc4r\r\nJCONDIuzjSveyqLuMYovFVzVxHXVR35X4rygPZbon6tGj73ncO9UNJ1Y84gV\r\nSou3v2Jvn2aDIh27iBufvKUj/7/q/hVV0SIKscp03Jxm5ZI+6Ufid+dStOWN\r\n0FJo8VhpF7hXIU8TW4j9nvzA97aS9P2v9FDL3Nds9i0maRdovGwGvQYBA8t4\r\n+K5F27/0JzSgrAw3MbaBMSRyFLpKkl2cwPdX8FH5pybHCBnb/baca1bV8606\r\nNQyyf6/Y7AokXiXjcNy9u2tp/AD0DZzl730MZd7X6aiN1En0iJcoktiwurg0\r\nKAynzYZKkeXXoqhRucnjDVS0R7bLssCoyuOrujBCT6KovouD9xKgpTQf/VZK\r\nd9doP6DKDQwFiafHauLixqn0Ekga3oK1MS+0/uyD43lX96cYvDRnOvyu4ngO\r\nLKdcSHdncnsHh41ynRN+/uRuLioDyPeqbucrDjPTeQfJloVHSGVWlIRRrIwk\r\nB0zr6X+Jul7Q6TXf3TNdIHcuikYyNbaz6uA=\r\n=BfaR\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001389":{"name":"caniuse-lite","version":"1.0.30001389","dist":{"integrity":"sha512-dXCB1Ufi5VekkH5vygd46PGp0HMW4rxorX7Xl1R51FWLcB21DRPOIgrpxvuM1VHXIs4bu/QQQdQaBneMzq9C2g==","shasum":"e4138095d646420e1b6ccf80000bbc94176deabe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001389.tgz","fileCount":817,"unpackedSize":1845023,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCDXkd0dDNsVaB0bZeWkCIBggSguNhbG6+fzBSB7eByowIgb+ShM+WLBzJokZYxPpUNBhyZOorBLIngebbppygUQmk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjFQ9OACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqoBg//WrI4wrEDHTCnyvflYyc9WSJfDmc+znovzzjbb6PCPH97pdE/\r\nXwZfY3qbyDCnajVcG1dm6ZBTO6iRbL86a+OqWF9pyKSE8SZLT4oIi0LEjZpc\r\nWHIBtKtzDYIuaaKfklWSe0rNwhCZ/vXmsn9AQT+RTZvfWZxkVlFPI51zLlKt\r\nv2/3jfuYpI7CnNhA2VOYoD7FbL2lL8svyKpB7pqa6TMQ+kO39UIwZbTqB/F7\r\nCQZr/pTZUcbl2LkJS6Ylcd2+Jp9lJQ4sz6pdEJcmO4ZmB0s40rYKU+YVfsPq\r\n6sFHriUMU3HZ4KVVF3aHCxXqVCxfYkaGZZSdNpaWkXf9ZvCxoI7i5Np6SY2u\r\nbs35fm2cd0d+TdS5p4Sy2KEFaIAK51FWHV72/6mTeSVlsMOtRi2ZQ2mma2Cy\r\nS9mznt286zLKxLdq6pN42yPbm962I/PpYsiU4QxZWsDKGX1F7G/UOxSI/8/x\r\nCeJzVJ8MaUzhIh7bsYTtSTtgoXxFcx/RQfZfJDdkE5abK9IapZkCtvoRo7BL\r\nLnaXeluGM0BHKOu6mMvuqLlpZ/Rfk858Vo7QdSrQbgqU+yehLqamPsFKKfPy\r\nvy/mwnra23oYYBIp5x+O4gQZXRCfL7zY8HLkhYti/dDee101XeFp4VRbBZyD\r\nqZT0AUDXgkN5yIErY9KV0AFtk1NfZ8ONyPs=\r\n=h3gv\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001390":{"name":"caniuse-lite","version":"1.0.30001390","dist":{"integrity":"sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g==","shasum":"158a43011e7068ef7fc73590e9fd91a7cece5e7f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001390.tgz","fileCount":817,"unpackedSize":1845023,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICrNQMWZKjstTzgOT69CNIcZ3JJWJ2eqy1AUCG38DJQGAiBrXE1Dncox1Qmfs13n4rddaPwmTiiQN0SmxGb71u1KIg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjFTnuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr4QBAAj6ZF5bWCtq6RQi59DMmkdP5mDdTCJenSPS4T4Zb6pSHMu0wz\r\nPQsdl0nkcOmy2ilKg3lAvgIITSFIqXQsB+6DcscFBMqD8p5h4OivodZOKCJ5\r\nqtg0JR3om273TToWaJjd8KWlbnPy6MOxXKhYlBhLvnZSWOGc6k0HTZ3lqz+L\r\nteh5mXdp+Vd6rQMhODkQnAp0n264f+FAejkLNs1o0BV6eBilJOkGhyC36ban\r\nAbPX2XvQAp9Z2Z17tb7HWreUoinS3FjbBekBEeq+S/Ij0dcsYz6BgrNO/FEx\r\nbq/XHsjAmk/sajO3cx1mUUEAx+1Qajiu0Lkp4jZEh1bHkrddy6pI3m7UhwDk\r\nQUykU56pg0gQj59/QVCUBBLjEMZpjCa6/Kn+xcguSHqVfZiEmwTXZnrjquFp\r\nfKsT4TwN/XxPhnQEYgPYO5ALS8DLMxrtmIEnfQ7IgQr5Qv7/bcWbaMflkMWS\r\nTMkbUZeD1v27AVFRAOQhR6D+d9jsRYCX7ExsKg+PFfZLskEFx4EczQSfEFkB\r\nPjYWl5mlFefsf2yHWBrt0x7Z8lHLZLnOgut+RYrgl8gS+VM60aOXrn1avTo5\r\nmznaPnI9Twz3Sa88P+CxRMaexlUzyDWJuXl50nZnub1MAVLRdkD51dCalIQD\r\nKsl0SzdcD1b08gxM4p7lBOZ0fpPYCel6Seo=\r\n=Jey2\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001392":{"name":"caniuse-lite","version":"1.0.30001392","dist":{"integrity":"sha512-17kzHgeLmROc2n7Cev9XRrAe3Zx4qGwn3eHEhsYCxoYQIrVVa9tbGu0LEUflG2mUsBGtWcv8iNilmxhvRyv3hg==","shasum":"b1238a0f75ee72ca426d1b84b7799b89267267c2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001392.tgz","fileCount":817,"unpackedSize":1845057,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2/kiZhVrvBUBFQ55ohjX3OtgJLDGWhLOATMm1m6QjeQIgW3lYymjx3Vd6nuwZd8x1RGJS2n0tH6/5JxSIVIvF5wk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjGWDqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrNLQ//dolRtJJnH9Pmhs81KCyEhWZi3tMPM9YvStY2ynkeRAugNffj\r\nCUhbcJjOkLFqYr/odHpKKELZyKpmzoZD9V+YJG8tTffcqRkGjtKxgEm5vi7I\r\nTZWcHQTGTf3ClMw/HwATRXEZPPa9IVKHj5AchIzzIXqk4OSdEtLbvXvM9AIx\r\n/Dh41xrSasRAXwIBCIZCwLoy9sa50ujKJ6ttOqKY0pyKjIel8U9cUN6ppuR0\r\nTHc8b8tlmzNpLkfmpDT+6bcbzVYsAExknwWo9kpxvmQrfjMmU42YgDqSg+Pa\r\nRU1Hwt+MY5RLw9kj4nJ/A2A+3nQlQA/xx7Q93JL0aNA0d77L94Vw29IqrigL\r\nb0BxBEpDhWyQSNl0sEuGC/NKctCy/fy4cwAtdxPvJcZKy5cm+pfyKZrKBX/g\r\nG9LGme2NC4NTVeNj0twtTXcFRjoCt9LIJbihFgWCo6Sg9xSlnNZeeun+DVIo\r\nmg5IEVilQ5YM4K5JHTgHu1wncy109A0WrNEDXIbFme6YH/0mBtEUjbad1XDn\r\nC9NDfK6zNxUyGBhxEym8WKgLowkySY5ErsT3YmC00DCwJIzmD8rxTS34vodf\r\nWINassplTZmkMzHhtZ9j29QzwJxsmO/2/c15ObPc8i5sgZ2mCXHtqW7k3KT3\r\n0rTcTLI294f7lRBEjz6HMlnUQY/5GvajRas=\r\n=UGrc\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001393":{"name":"caniuse-lite","version":"1.0.30001393","dist":{"integrity":"sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==","shasum":"1aa161e24fe6af2e2ccda000fc2b94be0b0db356","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001393.tgz","fileCount":817,"unpackedSize":1845057,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIASvzgqLYQ48gOpG/uYGcIje+qPjB2Jam+abAUEiujp7AiBRcTILebdPqiTxtP7TK0RsQsd4ehM849t9fYgOPxGVYw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjGXeAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrTIA/9EjB8jCWSPe4QG4KiMEiUM/vd43AAQ5qxgd35bSfLi2vKmICX\r\nTZMb8Dq7hpCLEfWMZKtqqhudjBaqGLEgCM447tQSOKpAya9/pUcrD11o11I1\r\n0yoBmahKFua3wvWnhCdmNqi92vO7966gjWMT8MmrmVUSzGkYfnafDLfbk+Rz\r\nc4sENEMegpIB8K1I0vxLOgGXaxqlInlw2NvMg81aQbHQvUm7xmG4w/JZ/8Ai\r\nizkqtJJaJw+KpBLxjzPm0enM5rimemS+qEu4+lPHrEuZRmWrE/Ra7LeHPjCy\r\nxIiEl/A9cdC6KqpEFGUQGwubZIUtDOAWCirWc+5gELjaCwclTGfCDcbSBIuu\r\nFPe8OuRhR9WjuKXtPMrwx2lNqgyTmGa29ti0uIDMNQQrw1EPqvmAHqMA8TKh\r\nnF9RD48dD0FQ1e/mPIGAMDxw/2bNA3ba3trlS9njIDOKFJfUF+wT0HTqqwlI\r\nFFYAcYIFXhn76dWhmoaEkUNMOKcuKUh1Oz1zyPQJrpkoL93efaOJxv5GJK1M\r\n96wSr2qM4wIWGD+6K+feeSZRlK/0alcmVIMH8z0R6WechamaGeOIfBLirEfG\r\nU5rZbq5yYAIEx122albZSrsD8FJBhm6eVx0hRCzDv+kej5rAc6ej7hEyUR4U\r\n6ywfpdLDy9X55U997C2Kys37OMMrBMuq95s=\r\n=uSFb\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001394":{"name":"caniuse-lite","version":"1.0.30001394","dist":{"integrity":"sha512-TJ2GBCk9Oa6hw7Ta09E13PE0vHdwqL8mG9d1F2z42w87SpKykRksT4nt2IdGVI6n9TfeRHX60EM/WBxW/AdSfQ==","shasum":"8f53af95974476a774c4db4ed467a0efb1e24a1c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001394.tgz","fileCount":805,"unpackedSize":1827734,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDUJIPv3OSfFtIDzt2l3fqPtmOXjY9SdCWBtxUM3xMvhgIhAIbQzGc0t/45ICBRBeHQ37KZbkiymB88ZoQyACz4xCi0"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjHmZMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmokhxAAjd04I9gu75via3EGbCnETxkYuQoEB6cXfq3h/vwT30CNF8mM\r\n+70vW50cH2euA8zjjfxhXYCYy+/l0aR9IL9VPKiO9e/YrtUDH78xQo4OwzcK\r\nrbsjeUt8xCaDOUjjr9gH+hpQKccFWR+IfSRpCCfYRI5Sc4CcYhFDRKU1Bk0T\r\n7s2yfF0tEzaLtIfgz+GaIgSFCp+fjpAC8H1+W2feRp+G7aCyAyBUDHbbbmyQ\r\nI5amwdYsFmWY7n7Q3gwNwpDjwoAIwdSqWj5FNlA72KRjfly3gJfWDBbwJPBE\r\nJV+BO2+6MQ3Ix9DW2PrCDLFrMhKq2+52NlYKeRv6whLWacZGfuLY3A+7WP2a\r\nnnYcx5dFFh+kLkKPaQdjNUrEYPggGm7Ioivu4eaKZiWwPJlV1IfuC9PZnk9f\r\nuQtqhW7Qq85OEC92zhpkpenH9fOfxIoURBCzyL3ePELuTJqcTiPlLVSLU96N\r\nIKMnOZ1dEP1VCwYOPm3wxrwfGMHMS5grVeXHgB/EBPL5yciy5xQ64CbI+p4/\r\nddMGpxN+0zmwXfWsdnKxWn14bfGUlZpDYCBbaQm+o/KrZpbpVQrT113J6LsS\r\n4j0kA77v+kxnisaWd1FXh31WihJVaSOnlL6hbP85RnM2X7vnPBS3lTCPmbub\r\n3akAdc6ZNu01kD8uRAvIUrhVPZBV9U6AKqQ=\r\n=Zibt\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001396":{"name":"caniuse-lite","version":"1.0.30001396","dist":{"integrity":"sha512-Df93cp39XVZRoOl2EoiuNp2rc4Dnsb9mDQEs4qFa7/uTx3FnfEq+jyHLf/0Ik7GVJA6wvJuAI5ZKUtUEenAm9Q==","shasum":"1c3ee1b7ccd60f3efd7461201740c8de9fe1025d","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001396.tgz","fileCount":802,"unpackedSize":1823489,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGlk8ZdA+jf9FS+mWYJDK4YNJoH9ltQ6yLAELIaAhqcQIhAKAeSvfTvN3+7JQkpF747NuuQSw0JxjV4vfjpb83QJOU"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjHnVEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbqQ//SzN/BgumK6KUEO+3+FLYc+g3IJWk9UBMqVEzCM4qM7Q+qeCA\r\n/VpWqowBY9ZpuOA55e3wWWxnA9p4uNhjWj04Oc4Bpg+3NTxEQAdCSmOJhJJZ\r\nvg85jtZVkr5bEp6xzJnOK0favXSTwxIx/o+SRUVVY2KtbkOM/ae/b5N/VHGt\r\nhzedDbmgW1kgJu0kcFHpqhl58y0fSRd02lpZj/WnYu/PXDzJy8Ks9j+tI1PV\r\nobB7RMUqx4AUl5V63X0DTxiE/LEsTqmeRpzvbkHanI6UJks8QNkRKCACA/YJ\r\nOBGcKm6W/7zQbZQw0m4atZQ8lsRgfFBmMllrq93cJ6QMVblA89C79KuQzhIk\r\nhdPkU1aBvwTq+mNmE/mia/9SBuruHYz1M8PpyvIu0HClHkC7aZn6E4tCkKXc\r\nDLQsdLwQYG2zUUzWtIPgWE80T4M1wBpPyXRFXQDa/KPZwfilhPwVuFNDxsSp\r\nPlx5F6sDzhsFGW/qRaWEfde07KunKj99ZIuqu/iGAqPSCiYNli+psdQkI/H7\r\noWxEuVzoaxW+Q3uty8M3VNynJz440OzD+Ep8ket40EvOna2oAJrMMPBLL/ak\r\nexodA2h5PM3K0+tZ1sCOUavZ/yJnvZSyJVq5BLVTCv1GGma8Lwy5pZVgVqor\r\nMlE6e9b3SwjoTqCpyzEk9nd57/4EwNHgEwE=\r\n=oxqw\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001397":{"name":"caniuse-lite","version":"1.0.30001397","dist":{"integrity":"sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA==","shasum":"010d9d56e3b8abcd8df261d0a94b22426271a15f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001397.tgz","fileCount":803,"unpackedSize":1824976,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGddiQQcA0bPG7T0Y8v//r0jYdKJf2wX/MROz/RxGDR5AiEAjp4mTt8qWT3FTmnC52WjhZVdip1pQTWn8HMhCeEHNvM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjHqj6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDUA//SeR+Ap72aBAq76mFFnEPeYXjfTQgM3U6W634gnSzt6Qo8yJg\r\n+ixR8w3OlvJFqvzxrVYePc3iBuSWviy6qlePVMoL/SWw7RRjMYnYxy/+KDu5\r\n6GX4AC59exArYYtcvG9zoR2J6uPGXRV4GXDX3iRRraGe6tBA6a3yM1/4Ew5h\r\nP6MOTgmgeLofyb+f4aq1E9RLIZZnhSFkvT4bBafrR5hotlcdTLsyKJfUidWp\r\npeUr1Lt69IkmA94mro8rcxq+fSilmQdRx+91mRk/dBjOyg+F42UuQUBnEAR7\r\n0yLRtWhwaoKCR8FNj4ZQrRfFOCcl10UzRHV48uINDKnHs6/Tcwcpd6qv+U4g\r\nTDA2wY8MlR9yvzp4agZRyJXQlCARG97Cr1HY7U2HCEuoUkjUW6oqmdmB+EqU\r\nh+II0DISL9f0cgKu4F3dK/3sw2ZfKocfELu/6YA7pzO664PBobIFjltoicJ4\r\nFfRjwmWoh3I94hUV08jd6oi38X1f9BwRu8yDS1ZqpIVE0ktwDE6s4skQo9P8\r\nc7WsDpFXil7ZIByr0BLQ3NWJEFp9qHTbDq3YM8gRVa16HxaJhHbFFuobvwiI\r\nXQl+fwvd6BvOgRhS03smjClGe7tTn8vZZSIqHWpxZ8d8UAZ+68o2TqoFtIYI\r\nTf2LcgObuzPEs6kZQnbXKZ1B3l27x27Ux7k=\r\n=ed87\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001398":{"name":"caniuse-lite","version":"1.0.30001398","dist":{"integrity":"sha512-16XOsD5LWJcKSHZlHngsLMV6f6K7c/6KcufqAZsmlSMJTg1jryiCoVgP1+/2hOY8p5vvZAahBiK8wtkEMuanMA==","shasum":"532f03480f625078632f83f4e1c0f76227e181e2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001398.tgz","fileCount":810,"unpackedSize":1834772,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCy7ADXpBFxqPTKR5CZr9DmcgVz7QfJa7Y9t60Jk9J/awIhAL35oYQftansdBvuFIAuIjVG+/Kn+XaPGt3lvi8PIjD8"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjH/lFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoSGg/7BPwm0WMyd18f/m5KbcNpP+wFm91o7942xq3zVOCVObWT4UVM\r\np2bLKKZL0rDzHzrvTCECvq0Zd95WqpWWAB9fqf6TpPivT3YplsTKDSV8WrVi\r\nVibAWjp0IAEi5qoMgPHLdDUuqooMuCDRdA/8rdkHeBM/Tn1VRDvctLneXp+k\r\noz3cLevoxMav5U2nIBRxha94H9LN2Xm2RJRAy/38Re6Ho2FW5az+39vL2h6V\r\nADo8gjvCZQ7HmH6SgTQgjORmQ6Qc7RAs+qU3RJVukZEDyKMSzT2uFIxi55y7\r\n6xzcTKZBX1/9RBAlDHZ3+MfyGy8u2Ubfu8vHTsvzN4zyU9T/5u+uR54XxmH6\r\nmEjf6tZKhlk3kSQvG7tUnk7bjTeBBHzGeUa593PeXTwJ8MZAc50hobAVW/zn\r\nGjyz5/SsS6SnI3m0NXFOfknhw7xjnEa/nIfEwYA2WfMkz4h/kJGAvQWcJnGl\r\nyqoJ7mFzOYMrKCR4FiiCAjAAGko4XgFeKlsGLhW0uTOgpGdgkKRayKkitf/v\r\nUB7EW1jdMxlovbZhT8jAptrSijZoID1f9/LNXwdlJQYqYT6IrMm5OeGl8CJD\r\nb3n1O0hmWbbP72+qDFAYrA4Y7SGSroRVQVmwzLE5+ar8PRIvDtHboUFxXoCs\r\ni1qEgcDPBpUbEB92jiskUmuj6NIXOqlmQtg=\r\n=247F\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001399":{"name":"caniuse-lite","version":"1.0.30001399","dist":{"integrity":"sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==","shasum":"1bf994ca375d7f33f8d01ce03b7d5139e8587873","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001399.tgz","fileCount":811,"unpackedSize":1836196,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiGE4H+qS/bDYfMmI23unoWQzeAmZ89SaOpHgZluKpLQIgOrS6UbQmGweL5BObV7Vc+eVzBfMtdtwg3K5RIbU0lqI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjIBFgACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrwfA//QdEiZMFRVKeAX7iDmG9f6VEQR2Ze34C09VT6+wMN01WTU6dR\r\nMwXvba5H14pn/lvbyY8IWTnQ/EdA904N3XqhvEgfR5c6E5PNO4B8300U50sJ\r\nQunr1wR3i7faEk/Wb6Pi+8lE3Cd/rzyNyrCAQ4SlUvQO5qAC8Pz0EjTXyuvN\r\nKic/wNaTDITolPQHdgkbApDU+m+4/9/Fd9V/e5Tzi8B/kGjJd/deeqXswy+F\r\nAUI8d84iCH8rRoO4L+gi5x2cUtzX2NNoHeDXSPMRYbthISAoDXL++ppiIZCU\r\naQAp6EJ1U2tNOb5dl4ULybq18jlF7yf3gXT7XV3WnJYkoiSnWCCGerp2JIZH\r\nGNhpWCGFEu04/Q6f/QT8Wv/auEhqRagvKLuy5w2o1eVKnvejKFoGCHEf5XPb\r\neNAK4kA9itTVuc26GLnT4xQrHP74TOnUgooEh7WZcQLC+eEnWQcpg9wCqKo5\r\n5qN5S4OgJ1ABxhky5VtBUvs8RWDmBjXkDVoGDouEWMMmEuqC93LcbDGYK/Bx\r\nwsNlvGP190SLQo7FQGbKvkXKsSaVGetWCpvUcrkt0KAYADPN21vezTV8UCVy\r\naDrjc3VXEw8iIBAHDjzn35EMzSG9L6ZHJwAQE2YReiGp16z+tCAZ5JMdvR9g\r\nMAy2HxGE0t8PSflS2xgAUSXd0BOohW/MtY8=\r\n=HjY9\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001400":{"name":"caniuse-lite","version":"1.0.30001400","dist":{"integrity":"sha512-Mv659Hn65Z4LgZdJ7ge5JTVbE3rqbJaaXgW5LEI9/tOaXclfIZ8DW7D7FCWWWmWiiPS7AC48S8kf3DApSxQdgA==","shasum":"3038bee70d8b875604cd8833cb0e5e254ee0281a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001400.tgz","fileCount":811,"unpackedSize":1839572,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDr4EBBbKL+wYGCvwkOK4ZiXA2/X/rx9R/9uZuI5zIKeAIgHGcrhwIwTUEeCy0pnjdp3i63O5bWwXm1hhDlVLfsk4Y="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjIpzXACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpIBQ//Xn5j1oJvZ01Qxx+fTLgnR9X8NNBnN4sPWvM66UxRYXYe6csY\r\n2NWspyc0tsxduEjYgEgTXwI0Tt/NEcn05CzEWLKGxIQUGgzWxBGM5/ndPiQa\r\npIC1u0RVG4lsASaGf9QmFTE3cQCXZ5kPxuuG41/CmGfS8FpzSZxTWwLZW5Gx\r\nOJ15lsTlNgCV6CiqPxQ0+4FSb9QFRki+NY/F747SyKL6y8KAtButETW319E4\r\n5Kn1rTusC4UixCYsD5E4QDE0VXWwoI62pnG33ReKWKIo9ThUb14g5bZKJ4sP\r\nIUdnqt5a06zWFWpP5uP1xrFTpitfXGBY8vppkPexsids4FWZTrdj9z7ptrjP\r\nA0UHTXsquGjL3H0ozpYmVH748CUunEFg82JEKKm5l8AC7lgrpd1u2+74wKWp\r\nWgokc5ua9np48XM3g2/sgQJc33rDfM5mmAjgccTl/OmYzBNnjPxlS/eu+jfx\r\ngAZRmF9FrCYrDjj8TajZHkToevjCC5L/HgagLubmT3bZCd8543L5I3jyKyvn\r\n39qcUYSjvoAehYPVUO+3XfuXsrONtBRanDRBZFyHJkiAOEaoTkPdsYkwsp51\r\nN4cud440UHzTy0z6tGef+TM6zZWnIC8/RylDmbnNK4Pd4AGlTuqeQof8wAka\r\nhYDDmrjdn3wc+Fk+MHje2yxDlr8YbMT78/Y=\r\n=CUFu\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001401":{"name":"caniuse-lite","version":"1.0.30001401","dist":{"integrity":"sha512-fmC/D1YCOvs5uWFP3FNVJGTdE0QFQLs1dJ7W94wP0p46lXrDl3BNgZArKPm6+XdIVtczMN1dPNVOFsJd/HRnGQ==","shasum":"d8b2434b376266ce48274ff70d1094250636776c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001401.tgz","fileCount":811,"unpackedSize":1839607,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4bMGZeEqVEDbzMVTQU8NRzFuPtrh9iE8EPumWMAN1TAIgWPPDh66OWruqE1bfSdFoCJhuIy0I7iiUU9L4QofdSBM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjI+73ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpoRw//c1nO8+SQ5XLAOGV8XymEJLyPrRzBJvLkvbbrT0D1gFit2M+0\r\n//iOpe/YqPb24XmtFXJER7zri9yZwpyt/hJYJNzEwFneYAxAdFrCI9jdUZgd\r\njkznKcrHLsZcjrox85jcQera2YXiBSUYmrl/jH9AxRV0dCE80R1JXITY3Wfb\r\n6nbqu5kGeOtbjauLmMVLGqnvHL9R6TiVbgF/BQmc0aJxnCaBnJUpPgf4OpwP\r\nkbKiygykXDWoOhL10e+zjYkI8avN4d/HUjHfekXYNYTJbM/FiZDmVBdG+VcJ\r\nYRb9f4j3EpPc9EUyky70sOZe/gtDYN0sY3FcIftdqcVJIWaWVwis9ANsCdr7\r\nozfOgXwxayfKosASr+YPReUC6t+93XxV1c5uSKe0pD0KAIbSqS2+CSEqhxSd\r\nnRnUv/oY0D29NXYD+FAqNDkIIOqVhu4GkMiG4//73juvsfqp2mljeb61UzD0\r\n+FToD8WR378H06FlOPxkzSxlTpahJ8fKf7Lha8EHarqNff0tERMUl99DkVIn\r\nEmSxZJOLX19QtPAy6Ff5wjUagQt+DTYAbVWuj/WZo3JtPrZRLuFzsj3892se\r\ny68kvysjnGHiJWLf2G3n05UVJZ+QCbwfIKoWGo30qgX+TJEF5bhkvPyaRMfG\r\nVHKLebfA3z3dU/LzHzS1fIa1g7WlbeZovxY=\r\n=Olvr\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001402":{"name":"caniuse-lite","version":"1.0.30001402","dist":{"integrity":"sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==","shasum":"aa29e1f47f5055b0d0c07696a67b8b08023d14c8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001402.tgz","fileCount":811,"unpackedSize":1840825,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAdgH7lTOLh7tXZm7xvx8r+bvCGU8EhYHoX9xng2gEb7AiEAnGhOMqE+hAQHHVMvf+WJ0mu/rZKf3lzwzrWf5CrVMXk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjJAVQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpv3g/+KVHGADmNg1c+eVfc+BAiUs9Mrpp6o+PkdiI5e9g7Cigpg8Ye\r\nPziaLcK6sJW6wwtiOs6Jkg6uW/zZcPwpEzPxCIujTNuMgcHiP+6h/zzvZK5n\r\n6FBrW4poiMiKXLFmutW6U3FzQyVuEQwcNLh1Xd4JKSN6W0jRI2MmOx6zdE+A\r\nmplizKr/+HVVGYWaHSw9TkRCwfWufe/QXJTX8XEdUh5PmMtSlwmMVk1Z8uX7\r\npPoq552CvTZckq62ty8ioOJv1ej5ygpvPQzDn94xPWvy1qlg/jK5xLMUuLoI\r\n0DG4P4jZB4l683R28ocNiyZ2mtL3/iUS1C5bQ0YOuAen8pJ4wYX5jpa4pq9k\r\nrvW7WCtRGXT9egfozN/ymnfhvpLlRiUtFoXP+juVxbRWyWa0WNtTlZhQUgTF\r\n+vEoCRq6aFxgrNNeaZeL+XAVgbyAC/J6MCMMdKuUke3m8bVdt9is7RhuyxFm\r\nelwQaFUYMADzlB7qJrkPgA3zl2B8Kfh+QeZIyj5cIyE9kURwGKGrOCF6rDvW\r\nWMSMiD2ZfyMmBu1GF3M/yfXiowKVHryrzKHQhCpgFhPtIb6NvUnzH+4nkP0I\r\nhgJ9zyWRNsaKfnlYT1OAg5NINiRkdNCHRoYTZmUQhQvowsWBvLEYef45R9Vc\r\nV4r2dKng9UG+H4ca0Bd3rHQ9MV9Zbl2vNTk=\r\n=Q6aZ\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001405":{"name":"caniuse-lite","version":"1.0.30001405","dist":{"integrity":"sha512-lbm+F6HaYFGfjejrTlgB6IZQSZjpA1qcrjGsuvecatP93emI66a41hmQJIW+KNMhcuusgQW0R0E9qvP+Hq7eLg==","shasum":"c7b5ee5ce559ab110f3f98cdba346fd1729f36e1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001405.tgz","fileCount":811,"unpackedSize":1840825,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnZfTjYj7aSDyyIzianLAPDzjYiriH8uj8HBx+DL9ydAIhAPmK7ZfroTek0lIwRcoomiqlUKcFfpI5bF1v+ELp9UPh"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjJ+MoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqNQA//Y5cU3F3wuHnWVtKlA49JBBWKawoEiUFkqzxTUrsdqjXzC2MO\r\nb5N7XvFUcrC5rjCzg1ec0IVrKM0UMh5c1gnO/zwqvvJU8qD5YUJysVwO1cYt\r\nKx45HWKml4Zamc4GFvz0TjMxUU3NtKlnTP/nr1EYH5ggOJfKv4gS3QrvVWdx\r\nds7sUio3sqxayIqVXOcemkDaVFepXcRpSXHXeUVkgQCqzoDJfsR7VsJ1dX+A\r\n8vzPXX+B4truRUjp3G262t4Y0CnD2gQWphaC2F1N6gXcvv/M+Uz7GF5KK3m6\r\nZ8ANW4WEwCa2SBo68SYnQMutaBoiXiZuRxsJgeaROrP9V6g+MnUV/aqcQZZ4\r\nl8VVcEhR4oYp80Qj1T5gb173ct6WOxx1l/9MEDz9aeryOcpiuvJPn77Hh+yQ\r\nlr+ishJI1ZdRvjvpwfsJNCeIWo2XYKMzaYfM18E8MMlQQ4frXOy0zS27LcXU\r\ng5SGy7++DVGPRkUQ39n6g52YZ/EM/2iUznLJwyHDEXMhc0cI3SQR1GdspF8V\r\nsDWlZzVDWkExknIv6F7U8D6VNtcXh8NuJ4Slo+NMRGvRoTzXJev1F0LeVHH6\r\n/2yIUuQO5Lc2mtQg634Y0HLviuXc3abrG375XNiPEs/WKUJKKtjYfvtXpVvB\r\ncnsAYbWYW8JpO7+hoLtpA5cBFcwK5QForkM=\r\n=O0/A\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001406":{"name":"caniuse-lite","version":"1.0.30001406","dist":{"integrity":"sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==","shasum":"d0146e7919635479f873b4507517b627f66ab269","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001406.tgz","fileCount":811,"unpackedSize":1840820,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSjv7GH0DcD089cVSK+Z5bZnDMigNN6JA8cN2pfwhumQIge6azdtBYR4qP1/hVqbHLU8M+zLDuRY10GbvwZhL9eyg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjJ/r4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrruRAAhyLvvpRH+c+X6PjvshvcVzSGDjrnHypl+qsh7yKpPHWvJcX+\r\nzPF7AgWMaK19ocQ17/DmOipu5m7xHcYNHWi0jkvtAnAji4exiDgfw58f3wbC\r\nS3nkzDltt7vLSKH68EnpauqVadKzSYde/QG0jjyt/quAgcfCn1Vkqoqi8pNk\r\nuGNF00weJjtT68Fiqan/Nd9jswCBpeEV+HUnI+i0rNYs1iEBi/UUO/Av9BKP\r\nZj3ZFlliWmu7IifbgABhF3YCK4CBM1m8IzNGah4cgMDG05JukSeSnW1Ovn2m\r\nlfv5IwD7eywLLF915i/rkIlu6O00nnuOOPOPIxB1d+dbGM0CFi4YzKuLPa+r\r\nWDJgII0fm10SRsnCr9JiZDB1cNkh+yvEKdKF2tzCLEejg08wnOZqIjp9Mc4W\r\n/NRkhJFyxS2gkZ4Dh8tbXRWRRh6i8L+fBxLUnlgR+RKvs0B5P9XZlrKTWJ5i\r\n88OkxqRJJllKCqrkiNpuplZ0Ros57d/8RTD+fc/FtbPtXwFH2x4krE8tbvro\r\nXgFnfaykFKr3e4XvbhXS8H0h6/mmEmb8yj7Dol1ZPTllJdljFOeRFL2jMuZf\r\najzLT/k3TP6bDVMuF/UHPSdaQ4KSwiUo5XgTTQtvshs4aPnyEaCLORNo7oQp\r\nrGnPeaTxPuXubo22dqRASBK6hNCWQ/uEZOI=\r\n=WH5+\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001407":{"name":"caniuse-lite","version":"1.0.30001407","dist":{"integrity":"sha512-4ydV+t4P7X3zH83fQWNDX/mQEzYomossfpViCOx9zHBSMV+rIe3LFqglHHtVyvNl1FhTNxPxs3jei82iqOW04w==","shasum":"92281a6ee67cb90bfd8a6a1201fcc2dc19b60a15","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001407.tgz","fileCount":811,"unpackedSize":1840820,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsNIum9gJ8Zd7Vorvy59+g7V8IgzUVxJ5gkP8I6zw6BQIhAPBTaGGeQAFPFcU6ua8zIOkEi4UHpHZqBc7ez5h8L+64"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjKUtQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpL7A//aXBFIolbmoZBAM7SIrQClgKFqsv6t/nh2uhjrGU0CDJoY8I/\r\nNQ1TVXeR98fmNo78jjtWKLPQkSO9MnLbFBalAOWGeJrHPfHa9Lg3N3PR6pM1\r\nnc6BeGfouCymdiByiWdFxdzzhYcvDrkZvMgUPU5wAjH8dcHjVJOHtBGyCN1U\r\ndy1ix8rg0AtTo5XIxnKxYzQC+OTOsZnH0t0qIGEWXsTPrXaPAer2zK/Yf26q\r\n3fpiXv6mbY8JwQxsRWW1aTWpHOCleAM+sY6+Ydl5xRC+bH+ILE/B837fE/AT\r\n/ELs/t564OHmOBRhaXwhilsUrIe57tJtUIWC4kyLoqJg//jaBKsxgQwOvg+a\r\n2sFAq05dhOWqAc2kM0+uORKXun/DDuiReOl9MUNZopCpfXUdCWiPrRUvRU4A\r\nGUMXD5H2jHppiuK8kRUtGibs99kMnzZZV0gD+Bg1wT3QrqtVhW6X5EdHaJvo\r\nHFF2yZtTZN4MVAycL4j+Tlbe4STmmUjxaB+caxO+aCrfQhhi+tsm8i3sMJlU\r\n7+BhCj/di/EIVCW5GyI4CFo9RFaVGxf140J1CkJZYEyK4j/AXdlZCxNuO39P\r\ntV/UaLAeOZK8m+Oc95qmpPAnC5KZh7oEh/ayBIPnEqfARWZrnH6j3LtkXC5k\r\n7XofmqLAQGw9N7Cy7Db66Du3Wr0iChPNC9Q=\r\n=Foi5\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001408":{"name":"caniuse-lite","version":"1.0.30001408","dist":{"integrity":"sha512-DdUCktgMSM+1ndk9EFMZcavsGszV7zxV9O7MtOHniTa/iyAIwJCF0dFVBdU9SijJbfh29hC9bCs07wu8pjnGJQ==","shasum":"8f5e96bd9c5fd1a8c629e4415cdbaf556333a591","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001408.tgz","fileCount":811,"unpackedSize":1840800,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyR0yJ2SGOlm8AbhN0JoCIf3a4zApiWdbKdDrKE7KIuwIhAPQY1tN13nSBFmVGiD40jJHmmIulvq2iBr3FNSo7g7gz"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjKpzLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqg3Q//fuBldS+weuwDluOmAKFEz2IygOlDL8Z1hDhQalRM0S0TQR0q\r\nOgtXYMMMpAe/FVTCQzliz1rqx63zO4f2MT3lPIsf0mBobn7bNOIpstBn/Jqe\r\nXchQttdAm5POXaFFcVrH/gXgpvxrEfU+j3GMQ5tUdEN98h3VftnzGFAaLpqp\r\nCKPU/+Fx8Ja9uk0I/1GzhheNwh+xZSWjVX4LXIS/acu1FXhxbiJ49OT6QkNy\r\naSwSrTu3tQJQfvre9BXrX3OxzEBm2AUh6gjqEknWUg+QACAqlgPFsOnHtPP5\r\nmxg8zkORPU27RJDbYDZAVN18rXrz9AShIhuFF940PJMooj5Iox4RFJnSwg9g\r\nAc8QXhfKWQTaGch8eGje/yHXk8k77YqkcqscChb6mxdYguAR0MG6mG1snYwb\r\nJr44134XROlwOy8J+4jwJS+A4ltCF0SQy6uYSa7BLFo+uzlzHxOO1g1lhs06\r\nES3CPR2uKiFbMjffSzchcLb9wdx7IB6kOduyxwTPWQJQrxSo/roJNJ6hg7NZ\r\nhdK9sSRAuoTj90rW1ObOFSj+zHBsU8o8iVQJ0U/nKxO+NCqZKs1ZG6NL2d4k\r\ngALHQmLQuAipfZ2ZIejVxWL7USixmF4RPULh/hdoe8HOsQpnTY1aivfttUa4\r\n404rj988layB9b/vws/awCznxa2GXaaF9rU=\r\n=qz2v\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001409":{"name":"caniuse-lite","version":"1.0.30001409","dist":{"integrity":"sha512-V0mnJ5dwarmhYv8/MzhJ//aW68UpvnQBXv8lJ2QUsvn2pHcmAuNtu8hQEDz37XnA1iE+lRR9CIfGWWpgJ5QedQ==","shasum":"6135da9dcab34cd9761d9cdb12a68e6740c5e96e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001409.tgz","fileCount":811,"unpackedSize":1842544,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJmgiYPEyVz3rvrh0IRuJ6AWUgtgXpn3ukVQuZQAveRwIgQsa+L6Hm71xRayfnZsOXzLUnk1lRETswfgGiZGNkqFw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjKr1ZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr77g//TQVNkh7zMjSBgfNBwzhVSis13O35w6CQ4rr0YU/gJzNPJoph\r\n5avEL7qi9Td+XHXrMgbwA+rVDzzoCprHEtVnb7Kcb57EpmuaGO5uOWa2L00U\r\nB8fFcIBXzcPLkoCCX0e4cRbjH1aBLS5W9IHzmhx7yvT3YqhwJGbzEe/cMQls\r\npsfVgDNMCZz8bYN0uxN6YhMiMCa8PmxB3qMYiEfBZEfDzFQWqgVHw1FVtzWO\r\n2Wcte8E2VW2dhg0tptjjZ7aKx7yXqblk7c6wJxy8vSc8DM072HsomxHIv4D1\r\nqEG4o4ndaUKfCnHMxCODisRKql9Ljt4+2pt/fm5EV99NAT9jEXrX+CI7Ygxe\r\nKHWBEILWqT6C/ONowBRIA+DpUIyDvrEpuYJmv7VLJlIuMaymKtMQK6GTBtFr\r\nI4TAwBSPjFUEY5X6clbOZMV7ThCtwGO8b7lsFeWmEnJyGYD0frcBKOZI0QyI\r\nNs/LMn0LqbTioh7QpiVvG8w6Yu79oC8BXqJzEilK7eq8mlGj4S3aQYJjbA8i\r\ndXPL0dhALGq0xiTycQiuZe8gi1D9kTz/FoUn1R7KCsFrX19WlqD5FvsyyF88\r\nZ8OujnfXwRzZWdJf6gbn/eQLns6aDSkgErltikBf5AVfZzRDYV7IsJ1MlplK\r\nbqbOkr36HyVGC0L6Ujm0l4GNXZjf/wvMPrU=\r\n=AzzA\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001410":{"name":"caniuse-lite","version":"1.0.30001410","dist":{"integrity":"sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ==","shasum":"b5a86366fbbf439d75dd3db1d21137a73e829f44","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001410.tgz","fileCount":811,"unpackedSize":1842553,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDidfSLIVIQeoIzjQLv1Sq6OZwOsmHgzS2LhLhwrR+0ZAiEAy9wHKwgDHI0nMbs/8LY0FDlPxaXZOTlfi4rHBwm+FVY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjLT/LACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpk+BAAjYqzNO3jw5LBnXDfBvHpgwbeT1qDtLk2pqHlDzlwlXtd1yGW\r\nq/U1IajRO3Tc7uZv2Eg3wOMDSIeqnWM4RFe0M7DQu5VuJKbuW9CUa/7D7lJx\r\nEtU4zJRUmPOa5tNcuU2IwMWgsOw8nL1sF16rxtldGNVZR4Q+a8+x5LKV9ug3\r\na3f5aAghbg/KQDGjAF/1HzDGx0z7UDVnXlw3quXrTh1fih/2okJazyQcFZhu\r\nzYwmevGJx80mmWK8pTg2MxcTtk2WVEFzufO220YOgccmDus7asAbF/pbq5uE\r\n6YKo4KmJoKLNW/3vpB5XOx6NweCScLQ7xXutWY1V75ztZ7Ki+u2KQSRjqDJB\r\nLpf9qLvhyenwR0NuusJulTgiIk1C9sziNovRDVNf9d/YlUc20WlX788FaMNH\r\n7tNhVd7vTuTEVNSAiIdIl9JPva8mblovujp4CrthAKaCJFCgSU4nRZ2G+GTl\r\nUze+uGoIrVKzG91KMnI2P0ZLoM3COVE1uNlFKpFI1GfFneL/d1m8PMuGVFBB\r\nEqcbNsNeJIoO6JqyHg+B7fjgEnL87+Q5CZSE8qOhCQQ/Vjx6nTsaqVUbY0dy\r\ncaBI/bDnVopQgBt39WTo4Cj8DZMyFwqQZuSRRNVzY+0OIJ8g81ujdqZqWQuX\r\nGpljJVUa3lm4BApD4Nss6mg2zuDt/tnOwAg=\r\n=EoEf\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001411":{"name":"caniuse-lite","version":"1.0.30001411","dist":{"integrity":"sha512-HPnJKESKuhKpHvMY1/ux7J3nG7xG8jRuL4lbyCjDRm0doTNV91tcRk60xrP7Ym9DtJH/yuqntDWBJCqpXB4b7g==","shasum":"303c8594ca5903b193a6d875ac613548cb73379a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001411.tgz","fileCount":811,"unpackedSize":1842522,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFT2oisctYBgNOGvtRIubZAc6P+aQ8feZxxrNYq+nDhVAiEArL6jxV/9ioOddCGgsz7Rts6Oq1SVuR/Q9w/ZhsyGNk0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjL0OwACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrGEg//WeoL4UEbGkh0bpSZ5P8d6XyFx6gMqn/KT3C77ApLJ2+3NGKJ\r\n8AbXkNSuBri4ZYyJWKod2DdYiPgxg47DGrTeLMUSL4KJlMHQbRltI0nsKKP3\r\nQKytgTZCZaS2CjbwKkz/v0VDJvixTs1qYp+JYE2AHKuR7OoxWmFo96bv6Sf4\r\nEudrFQHKMD0CSydseXfXcu8G+YNkRMtW6QhsqfeQtpuh/cyPZYB0ohbbgMMp\r\nMNdM7ttfqFXZqLgYbUHkGBtgrA4jWeQRHionAz0Z+TDbTH/+kf0cTaeajMxM\r\n4RoFHUZFex38GznLGesdtYT6zqbRZMvAKlUwVST5/bp1CZPKNSY2loMTSNEj\r\nIG1EMxAHbUMu6QW68sB2YaHdGN8mY7FFT4hm2YWL2WSbX1y65ksAgEj6yGNj\r\nFyXNj5JR3+NvY0nkeV+jbo8lBlw/xUe4Nts1PL21oJQF+31w74rFAYNYfl8L\r\n5IQ2F4Yocrnn9rOu396OxQmW9Y7B98vligE99dhn8s+AskO/ChnEIoG+hP+a\r\nqt/aTToAO0nY535+i76Xk/vihF2bJkDhyXMpvdvk4PgMROtgcOIjl+9HDbMk\r\nutOd41AkdlK8UDdOTFkzYGBoMuiR1r/o2pPbzmkMGul+3YahtYlk2wVqipY/\r\ndiOhI8jRb7D1X4ffncXrBRHzgoK8j3PR2/Y=\r\n=l4g2\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001412":{"name":"caniuse-lite","version":"1.0.30001412","dist":{"integrity":"sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==","shasum":"30f67d55a865da43e0aeec003f073ea8764d5d7c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001412.tgz","fileCount":811,"unpackedSize":1842522,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzwv+9uTu6QNe8r3I86PWZeRKgej2LHI0j3EupTIlM7AIgI6bfWknbkjjWc4b0w/7T0CcNV1XRugEZqZ6T0JFjSLQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjL5kGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpcCw/+NUaZGLP1BUYRMSUAO3iQs78rcoNZcLon8qj321ZaxziS3/q9\r\nzDbCu2Z4ODfYF2B9VHEDOBZOfLpwvHd9H15vpnD8qSIOQ4N3hlhHG1/urx39\r\nc5KIXjehj5uW8R1ICLBY35VCawoQ4dvBXXdCWCRhETbBaVpeJbcP76SWm+6E\r\ngHvCZ+N2VqWL+2bDyAK+fiuUfag2IgqLL0ouJm0ac8WwmjF6B58ui3oTHnzu\r\nlcR138JrIK/GdYBZFYM/qaZpgaL2DjjIAnIDFVfbR0V4MhqDt6pLtTtt9JUC\r\nbZ5EgkKLR7iwpB0ckz5xevsmIr2LMzlVYqgYyXigDk+h5xOkexBnXkSSGVpn\r\nG+GS0aIUa1aKzCGuC+2XNdu68oqKLTfzD4/706l+54IBN3KZUMJlFG5AnD4g\r\n8HLMI/ExgzIh1UxcvWOYtqRPEWZUiuKWk8y9E3gx7l0GLs501y06coZwjV/p\r\nXi4MLOndiESHV7+WxjjBk0DBiaV3QJxQ+pxsiCUgEj/Uj6ogOQrtnRZ41f+z\r\nFEOh9co1Rh4CUNwHGR29zDMLeNbeMc/r3xVXyUPLUFtVer1PyxZgP2gpz34D\r\nE/XekxSPuDyGhLCvVetrHwT9ZIuqGxPrZZeDJQaOyDaBW2EUJcNvNrk9kIqP\r\nln0rGNjR0lr0pob9fUX4YNa20Mio+9XNgi0=\r\n=5QEC\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001413":{"name":"caniuse-lite","version":"1.0.30001413","dist":{"integrity":"sha512-7B38WLP02JY9Yp0pEO3ubK3wT6U+HYNZFOwYDh8Lue+sth541pyFdkORHlaCKNB+ZLt0lGuPCrzs+zvhAq0Sxw==","shasum":"7ebaf65ea40ffb2d6501567ec1e13fb48529ec8e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001413.tgz","fileCount":811,"unpackedSize":1844244,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD7YAOHGZlynI8mkH1YePPu0N4VVk7iR95shVq5bn+4fAIhAI2IU7I8NprQGAZQdBOCcjhWJh+oCzHMg1K6+fLYmEJU"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNSmcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqfuQ//YDWeIVY4skS1lYLhnmcIFKz9puQ4cco5Uzek31E6vfVzZcMZ\r\n323u3m2D6WIExcx5n2MYPcAJaEfQHgO0v4YGp/qVwZ5+m/Fbu1yj8twwKjky\r\nx1ZqVnEllNkySN1Ck9OoVA/AyEV9MAwt/7Ey2bqu8GX6BJS++ABdyNW86zWp\r\nnp42+J/wbYXFuB323/rT9R6CWNtD08BGueXZatED4Me9u/bH4/DX4d4/A9gV\r\nT+D1xyrVM2D84foc4VA/O49LFpgZ8dbsO3XwRVZbO7MfbXCNLyM5VKE/1mlg\r\n/E/J3Z9yIW9Bxw+LfK6wTASDpsknXaxEl5YvCdLFCkqwXUDwMdv4Q7lpwNkG\r\nCkMhjhctA2Q0HlQMCq13LT0Ad0g4uoTunXlOAfgsLa7erWt9s45o8fzDv6Dn\r\nmBFOGbd3R9VPMNZxD7ZtCZBxR9RwAbmTLlB2J2jERhIIK8VngQdga42sKeuT\r\nEjiA44E2FuJkWwQx91oF8PHdo8VM5VzhRWJiQ5/iS5ErYhfP0eE6IKsectAJ\r\nkTsb1eznJG/F/NVWJhSKBrCSIdLzwwYfCmzKfc2DbNFylZIf4UPJ/RaPhFab\r\nqiVTvFBjI84iTRMUiIJLUDJzWlOsBeErcgS6wDW40Ucq4y29HMdpn95X9dHV\r\nZK9HN+ggLhmYvcDwhfIIa5ZATaDKRPpLhvc=\r\n=8jju\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001414":{"name":"caniuse-lite","version":"1.0.30001414","dist":{"integrity":"sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==","shasum":"5f1715e506e71860b4b07c50060ea6462217611e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001414.tgz","fileCount":811,"unpackedSize":1844244,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDn4WMbbSitguh0EVH6VqewIAt+EBGSDd+6l/RRu3gjBQIhANsHT2Yy0SozUbV2FaYl/Fnjm/wEyQ5xiecfojoZfHt4"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNT5GACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpSug/7Bg7Ejs1mZQmb8BD3yQfoZcN0EvioXHqeTvP6mV0yJv3ap2w1\r\nQ26lsds/HhXKlx02Q+RGsr6jdr9ZXN0OGNZ0cOpOcWr1IyoFBm7TQUJxiyeE\r\nreOyifkvTWfxrk8YAVTcIRzl5qt3kbpm3n0eYWP5/iQgqTSdYrI0JVz1GPXH\r\nX+mPqeQCE5qdj/4edPG4IkrGmuikG/ZU90Wf8DsQ8eM7kRQwHCUK+flBvN4Z\r\nSlfEFNE5zjJjPf5Zctc3dDpA8Nj2/OUs6U5vnFjWc0XlmsB+aoMqf4VQJpEt\r\nLy6IzryguKrdk7QfW+7ugRrBopyDD/I9hq/WHcG7XSJTi7V6257TsC0upK7s\r\nC25nelLZUqaj9VZJTmW3N9rJ2yDWpEBmjMyvnfcdPOeeEsJ8GpQkBiz7Y+bY\r\ndvhT0rV+IClf2zysKIqNz5wu4AySKwrh8tngv6EG1sEfyGLiW3X01nOyybEU\r\nIt8TJrRmumH5h93diLbxcPz03XoR2GYg4FXKzCWHJr1fgDUs4x2mSi15Ggqz\r\n54OGHHeCg51ItZ/hTvK3Jqnq9LjWx1K8YVKA6lO1smmggwvbEuK5zhRCDKiM\r\n+t7hX+KdatpMQEnHzwVjIYuVrYWyZARBvkQcMZj4xF/GYFmB82cTf6gJN00j\r\nmw44WYTK7N8F+aVLY7V7doicngTMkI3mnhk=\r\n=zNsQ\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001415":{"name":"caniuse-lite","version":"1.0.30001415","dist":{"integrity":"sha512-ER+PfgCJUe8BqunLGWd/1EY4g8AzQcsDAVzdtMGKVtQEmKAwaFfU6vb7EAVIqTMYsqxBorYZi2+22Iouj/y7GQ==","shasum":"fd7ea96e9e94c181a7f56e7571efb43d92b860cc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001415.tgz","fileCount":811,"unpackedSize":1857547,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpTk+nIlGgL0n2F3mBT89Y+Po6RZQf9NzhFchGEjtqSQIhALL4eFjyeYqG9bWJGOE2ItmsLb/lo/qPQD340Zy/uV5p"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjO7n2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp8CQ//ZZ4zPT2EGc2r/9tZSB/5LpSZ30rCAcK3gH+sxFCDmkA7iGor\r\njmKaHY0QpCmsWZ5xFsWumVe6JnaAt2xP18uvT/HoL9nrwh1OyJL5czB2fnm1\r\nukdb8IO4/Ri0c+0u9MdCCrNTQzw3wY761VR3sJVE6msVTm6HomqIdMbNEs46\r\ng6fawID2AgIx6gLfHlMR/TMdApk1VKy4r/nGUpmgObBp7e5ZXyv0RGd3PagR\r\nJxeIJm/FqxGwXNu+IbDfTMv0/mtN9yr2Y1LuLjW885N/uPBAjQuYPETEUGdP\r\nkRGpPO5U1dybZKkkIDOJnxEwKeO2X3F8NEmJJ0Ho5/RVJmlORIEKGXbYR13g\r\nKUVVU2Xw+3SNedLmIobbRAPvHqg5qFmCx2yDACl4lXSdoZykOIkL2Un19RGZ\r\n/qSv4yW7rCMfxYBIggaYYYd0yg4dTXsB56aJjQIkzg8W1LM7INGfqib9ad86\r\nFSipAm9TKXJsVAv56OKIlBomNsawEuQ5W+nFTYWkoN/IIDl0dQBjAcSzvdGM\r\nKdI9H6+8O0S6EgZV2P1wkjJnABpJKMNuyX6XCbCiTBQJkPf9DWrgpMvWphwK\r\np9t30hT7LLrvalRJqGIq8EUwmV8+jLnksqSc8lZXRFunRJm9sE66Z+tCwybl\r\nw8jdKNLtehSuAwQX4gTPvwKGtU5hQ+aTFOQ=\r\n=xn5p\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001416":{"name":"caniuse-lite","version":"1.0.30001416","dist":{"integrity":"sha512-06wzzdAkCPZO+Qm4e/eNghZBDfVNDsCgw33T27OwBH9unE9S478OYw//Q2L7Npf/zBzs7rjZOszIFQkwQKAEqA==","shasum":"29692af8a6a11412f2d3cf9a59d588fcdd21ce4c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001416.tgz","fileCount":811,"unpackedSize":1859236,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXwgO5EmHIsLSEQ6fIP/PE38igrf/FN4Je1NveCS5cGQIgMiAFj49AJq2dST/ppejIp+o6oiA9g37oBvHyUzEG2vk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjPRcnACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo2wg/+JqBqKQz+MK5tX9+R2CTLBLA1Mh36WVZnRYg9IokPjFsnSlnz\r\nmA76ehX9xKG0WtyGumrL+IG3dd04fjaN4TWXirZEMHMZAFmhMmh6vVN+cv32\r\n2BUmHaJZu8uYTK1lF1C4QXFxmcCPE2GTeiqsj+TIcMc2rY+1JuHZxxatyulL\r\nDzmsJX4Q05BfaC1pGIHTSb7LnG6C16n/iW/7EdUz8EtfMtq60T87Y7KrFBad\r\npEpMvVk+tah8kRs8n2wfZMrzIt0e7hwc/sf/nkGfNrd23/ljoATi75VPMSds\r\nA2KfkgspCPrskSXfiIFj67CF0Sy6NbQo1U9DdWZlSqaxt9xNfoos9aaRO5y8\r\nULEYcUFQKCwD7QscjVwYuvwWRiFq3oDKbVdaCxBB4gAmMEJIMZ73FVcMV8f7\r\n3Cqpco/47dDpTT13+AHJlvq7rOh6Iu6CPBdB62cMb3EqpTlMjDxwtSxOe3jS\r\nPmgaIM9gzZUa78vGjIsYtamp5myU6YqmPFFdeebCJUBD5s7avkg3d+nc/5dw\r\nqY46d33z30l6xIYspGiNx2MnGLfiJwnWKIXHoCH6KYko1HXKdwGLjF0+Ivwy\r\nnYsFafc/fGhQD06Sy8hIglwcGIV0zzCwVGAIU3/Mk2Ra2aCPu3I9Xhvnjjab\r\nPzsnHyYnmo+Dl0nOqB4rFyq6/SEJWmG9/EE=\r\n=ot+2\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001418":{"name":"caniuse-lite","version":"1.0.30001418","dist":{"integrity":"sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==","shasum":"5f459215192a024c99e3e3a53aac310fc7cf24e6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001418.tgz","fileCount":811,"unpackedSize":1859245,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFk4afnYtUD+cIBCspwUW+lNstJ/wvNJ01yMmWyET4KAIhAIuml/ZgpVS7tk04PEd9PMbel8y1VDqWWjxnHHXuzJ1+"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjP7eTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo/bhAAmGh9RZwS0j08EEklfs9YBjQoOLEKUzoTRpMWPig0AAGDEe3j\r\ncb7UksLybp6FMMlF8N0ftDeslCwR93o5RIqeJKqYQdt9eDqPjSy3/XEHQ2G/\r\nGy7FxdnII2yuRUzS/K67as+klL3c2mjcwkTDii+o7k5P5SjG/KOyIjCdjWJm\r\nvy/Wn4wWuIwbmPnsi1GPtsTIMU6KoiyD2H/r2JbPf6aWVPqlb/01Rco2pjnd\r\n4PXzE6LCHIv76+4bWRvLe1XoFkDInVV0D1JQmGsunBMtjel+Hypwbsds41vD\r\nz4n1L6nU5uO37WzryeYkfpF+2f92g6j22sOnYG9V7LjSWd6Kv/LH5NShg3/7\r\nqOiJjqj9UG+eYq/BJIi4MQ8eWmYaMr4/slMcp9orOV8mB8L3aiUgOBIkNSsU\r\njViOWSOE27joMldWZ3FHtbG1NhO+54cW9s/OPxC4nCuF2GemJQimPC5wkHYa\r\nErv0a72IDKVFE+oH5tJTAxy+Hy4HaBCP2b8t+tmfB6uzb6TqMG6C0M0IVaAR\r\nMa1yAGv3xExgIFR2ZwF+rsKT4B7NR7cDBH8eGz27GR6eldMhYffjokiZ2fPw\r\nhfjbwl5eIr+O5cWKb7IIp9qWlxQS7G060lbKtW88q//5OsPWqGzJ1amf55ds\r\ntfhx7bDndw9dFBWieZulHq89zIpHFJb7fqo=\r\n=dD9a\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001419":{"name":"caniuse-lite","version":"1.0.30001419","dist":{"integrity":"sha512-aFO1r+g6R7TW+PNQxKzjITwLOyDhVRLjW0LcwS/HCZGUUKTGNp9+IwLC4xyDSZBygVL/mxaFR3HIV6wEKQuSzw==","shasum":"3542722d57d567c8210d5e4d0f9f17336b776457","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001419.tgz","fileCount":811,"unpackedSize":1859251,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBHSPeIrm7FQxXpmWnj/S5NrDGx4QkxtjaB1/84HYD7gAiEAtGqOK6sBY7ycB0mWYB2OfsjyT3+bQimn0EsQlnpY8XI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjR6/OACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmowTQ//VX6LXvXt9WSCAJNvFTDJwfKar7y/sdwk8VTBXZ2MIoTrA8gv\r\nwl1ZqhkMaXkqYmGlL05UZGWTm/c0V3ZnqnGyIpWyJ4YV5g92ZBtlssWx3fzP\r\nDnC+EOdf4Cs1tEzearCi66XKv+DOw1EEhyPeIl0QWRYp0c5vj67MsSe4Octe\r\nEKsMQ+h8L3q97yPU7NHEf++ETBKcdlmMzuPPBUf90haBeQT1bP9ATwqarp+Z\r\nQ3qptefhaxgyiVaY4JL68020VAUY07/HD3x9ZyN2h7bOkuGhxRfy/Z3Uv1tS\r\nbidyJmM3vuQsQt+WKQqPGcKruwuxEq4oEBoGWeeo50XwzGG+xOHfgbUTHZhQ\r\nsKxmAcCOYH3Z1Eg/ecZMPcVu5KZhGahMS01JYTjqutHdg5c8jnqqFHV7wG8y\r\nxX+bLFF74w2+ah0YoPUnY6JFbfc0Wy+oXAP86+9FRFtH6aqtTET+UyTpHpbQ\r\n5UHamU4ClCJRn46h0Li2bKVvPYvkAaNlw6Jc0npSpT5QonPCT+S3Ojho1aIM\r\n8MpoNdpHV90HN5pyrIBQN7R6TA1rj5WDPMu+pji2Fvlakjv+xpt+7BQK4Xk3\r\n3yTElmTjHQNYs8STqj9IayOYm190kLC2MomfWhE3535WgLAlgDPPp3c/izq0\r\nHe2NILNABYzMNTR1G2ki2djC2T/oKaiEuBE=\r\n=jvC9\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001420":{"name":"caniuse-lite","version":"1.0.30001420","dist":{"integrity":"sha512-OnyeJ9ascFA9roEj72ok2Ikp7PHJTKubtEJIQ/VK3fdsS50q4KWy+Z5X0A1/GswEItKX0ctAp8n4SYDE7wTu6A==","shasum":"f62f35f051e0b6d25532cf376776d41e45b47ef6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001420.tgz","fileCount":811,"unpackedSize":1859264,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCgK2zHq9MzXyfhzKFUpr81LSYldPEghyNGaEM74DErLwIgfI49IBLoktHK4LVe+VzlZXcdwMT7Eac1H1iOHUITHXY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSx4LACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqCZw/+JIJntChrOWad2jNroxLwN0Foehl8eX4ygFwBJ8ghtODkYp2K\r\naimf52QOeF27NWQT/MpBdNA2c5sRk7GT3bw/XzSLP6t1OFJAL5r4748+UmW0\r\nei9YCN2IbFWL+ChHCoGD4Wgijr5l1JGy6XFEuDDoPltuX8SiYmQAKxwskhz7\r\nyw9oU/Fm3OzP8L24nYbu+NUw9Km774lnSUZdA7c9GrS1P4mftHiOALe8AF6y\r\nPU0GOx1AJ+/L9jXlfhXNz6j7S6zBj5K4ZTG1/LPTCBmZW3TXAaJQnf3pXRhT\r\nRyHwm0SM7OvQQ+5FZNtm/bHvBHuXj0+DH5rebYeT+MfFO6t3ORJ5vRJqccu0\r\nxbiYZpkkIL3LaND0B/4G1nrP07CG+pOX9J1kraKjTZclPSIDTYC8KEagNgid\r\n9bHEnPLnk4HQOh2QEG7rWKu69QSZjWrSVOEG64ATi6NYZirb6YoWnYYjtbDT\r\nZAWe5nIxktklLGKmYhj9stkR8uQjVQcbcDBhN9BCuXDDWYdYde9p6TQzY29r\r\nIAdf5S3//LglDIqv6E7Kf6474vYBYiL2Lsb8GvonoUtZCfZ6a5bvxGg8oJA9\r\ncAiVcS6p7ZXSbWMRxU9WvSwEQ1uPvtFJxtndJ2hPQPYWu5VsCViZP6Ls0IuP\r\nxDY8zjILKeP9kp5C1d5atZ00p00tzSmYqEU=\r\n=uWSB\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001421":{"name":"caniuse-lite","version":"1.0.30001421","dist":{"integrity":"sha512-Sw4eLbgUJAEhjLs1Fa+mk45sidp1wRn5y6GtDpHGBaNJ9OCDJaVh2tIaWWUnGfuXfKf1JCBaIarak3FkVAvEeA==","shasum":"979993aaacff5ab72a8d0d58c28ddbcb7b4deba6","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001421.tgz","fileCount":811,"unpackedSize":1859303,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBMaQ7xIpgGCQGdKbnLF3tpkOhghx/MpHDU+XwlD15A5AiAz1uUuHAag9eW129OaekGA5MMN5V4TydPr/ICn7j98IQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjTksPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpuyxAAny44xgH2+rOe8v84F0clin36fhW8Y3WZg4YXxmCUbe5MCaaI\r\nl+y4Dxn6iJFikLJf1p7Hv5kAJXNwrgMcryrr1IK3VAYbObhxsgugFtm3r8ob\r\n+1MpT0gmhMIMfRdWNFHq5dnyuvPAdc2zgZuPDQv07R0JUyRDBwKvkfyu8gyy\r\niUTZHXDSDdFqZzkcBc+oQ7uM2r12FECd/vVxCM3kRaPmc3NCe4twVj+IXDcC\r\nEQA9XNjPZJuHSEKnuZRBDBDMQMy/rvhE0ymasgIjuVy2QXwv/bUrIubP7lvB\r\ny8Pfhoj55TSPLAhUrjPwUHp4gCwiLSHysIRoLqTOhoatyIET9OFLaqxsq1z0\r\nyDkll3w7LOYvU3abhPYViv2yVQmSgah+E5YlW3g8KfEt0dtFhNOcjix/am4P\r\nKh/bZAjQXNHpw0uA0th4uflcGqx/ovO5qGk9oT7Cae5XiaNMLqITBMMAKT/m\r\nBS4UgOxa+HcfdsJD+BeraGIQovdF7qxmm9Tq/SQUl3H1V5tjOlBC3UAqn7Cg\r\nFq9PekR2UfJr4HQmShU5r2iARDYP+DIauP7dmLYLH5j6MVjEAEqwhAJcR6UQ\r\nwAjzHNdqdzqkqJf0pXRDPxZzX/LZ6eK2JuXfOPj78dCoog1RYlAo1++FjJ63\r\nB2eVZt59EcnqyvKB420KIfLraoiFTw63quo=\r\n=GiUS\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001422":{"name":"caniuse-lite","version":"1.0.30001422","dist":{"integrity":"sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==","shasum":"f2d7c6202c49a8359e6e35add894d88ef93edba1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001422.tgz","fileCount":811,"unpackedSize":1861047,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA41W+VlKWQwGtH/MexqpZedibCsw1IJ/uT4k7FED66/AiEAgKFK+gWgEowUDpVveYjh7gjNoXNxSWnx9x3MZKegAM8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjT4g/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpv6w//S8MWJ/YkSuhTN9hqCRi9VkvfMLuw2fgHM87LNMYWQwrHQs07\r\n0og0bkm5QmERcGvh6Q2/DFM2n0XeZj6XrtyICgzmaRESy+yiIeAA4TIwKII3\r\nWnk6wYGpNr0eEAWWcKcLYGAMoki/b7J3iGejOOiKIopLFa4pYnXLbJcSKCVS\r\nxC2fE+yw15K5gt+iwMShJ+FQIeGp6YQhdnowAUTf4dSlaQ7wHwSt/B/ASBUx\r\nvVHb3RJ9StE18Ehwp3dipspZI+1H8kNZW/y/DbW1wBUDS8bX89V7mgbS9HtS\r\na4dtvNoXPAQ2PPTfsh2/aYDKMnEFIk+w7s7pqvPsvGFXAlFAdTS6f0/tLvxM\r\nFkxAUbefiXW1DKqbs7g1ufBoMDUjDNfu/CIflNm634C84psBc08/ucWXQfn/\r\nFMIuXA08SzJUFQdRyXjfNoh/Vldc85zlcVi/0lSdukP+SdFirHkmgzt3HpgB\r\nvLHly1Rl/F0tF3lDygIyPWGaLUP1FKWq0pPtTzp2V1uno4RDhZf9w06XGgmy\r\nor640s0ODd+0yZpEDK5QLWZSt8zJxHIQVlt5TnGh3Z4a7k5GnPm37ZNAd2wv\r\n+OJRfbTELpzEpVIHquJboX7/j3VOiZxZ8jqJB3l0LsgwK7XV2LUwRIgDCi+k\r\nSw7221TjLwXisUb/lIq3WxOuU4tVNkuNAS4=\r\n=HLwK\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001423":{"name":"caniuse-lite","version":"1.0.30001423","dist":{"integrity":"sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==","shasum":"57176d460aa8cd85ee1a72016b961eb9aca55d91","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001423.tgz","fileCount":811,"unpackedSize":1861075,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDiKSgduVjvUtVi3EhIpBe5JpNdmZyRMQXZBOIxbHe2qAiAtZM0xV8mS/Dv59To2ElWXX0qfcQtJcHdgogBWKABTvA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjUjlrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpcKBAAgWGjvjHQ0xo/hgI1PcfUVEOP0hAaTvb2dUD3/fu7lbUbYOOT\r\nx02n5/tQaH+69GPIcLZAl49k2YNC1bZ++yxCCzFC8EMqXg/3u828Drda1zK1\r\n5GhvxjjupIIjvnWfLaPCSiaCM/UtNloiSyzMO1uoYdmUp3tKDv+QDxK8GsGY\r\n+EXCqg+fr2rPau6ZpTf6HQbLqiLMOFPKn4dHzo8g3JjBSy+ICFI/J9smE3MB\r\njt1qb7Dg+Kt/OXeVMzKUx/oN5cvA4ct1jgIvbqIrVILbvxbxHSTViUCrZy7C\r\nowzcjyosKRZLkbos/LZwBRgew+NUqeu9IDgkSx6zERi9779LTOaAp/l8cW0W\r\nYZ99FeiZPyyPhKNf5hWy5Qph8yGjqh0XnaGepCnRLRX5mhs/7I4OLHuBEcUi\r\niiZQulIjsuoKO/V+4OWCgt2S6JI6hYHqdzPBTpV3KQkwb8cTuqVHJXMSbmLm\r\n5ZBjK1cJ7QXKUew3uSXk7RLDxhzuQTtJeUw0U371E5fDm0zKS42YH8FS2saC\r\nrDK45r7wDBV12Xmpjx5xF9EEYs5hNFBcWIyPrc6fW9+yG1Pm2CzDbsAwaQ/R\r\nack6SXZA3TEY2MCQLnNBCcZIbteCkHIIuEEqW3u/6KfEtWJ+iBwUkTSnYH6k\r\ndlTrXRqCKddKQnSJg+r0Cr4ou1kdmLzPn+0=\r\n=BzSf\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001425":{"name":"caniuse-lite","version":"1.0.30001425","dist":{"integrity":"sha512-/pzFv0OmNG6W0ym80P3NtapU0QEiDS3VuYAZMGoLLqiC7f6FJFe1MjpQDREGApeenD9wloeytmVDj+JLXPC6qw==","shasum":"52917791a453eb3265143d2cd08d80629e82c735","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001425.tgz","fileCount":811,"unpackedSize":1862780,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAkHb6CfHyMgLgVhF7crRv114gfqkyrHDVYl0j2fWmzWAiEAsUqn6RLTN4aMGuuDFJOafeKOzOM72oXqtENWjPnBwSc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjV4UuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq2Xg/8CT45e78Y/dA8qr8idehJCrCRqzrWpRkxewjR1Z1Cryllvl2J\r\noeMOUpUVDK9xqKZV8pwCP6pL6OCQ2sNnDtfxQtNadWLL9CSi01dSeNXX0mUx\r\ngAwkOGGmO7dwmXK138WoRZJXTofpryYvNMtKTiksWW/+U5iK/BQnxDQLhnyC\r\naLMwcek3hFW5vuOmIsJoLVPlctz/aoVqttCLc2iCSysYueX+nlDmZfZcSkeE\r\n/0tJl4bAYtd13S35pF/ZPOrcu4QwCqzapIEl6oaah6+T/kHwxA66F9Fs8m/n\r\n01bWJTjjl89wUGNGpExiS2v7Ho31j7pQjFgya0zQlI319a/sTDeb6NXevGWk\r\n51bTOD0S+qHvkXxYe+8IEV1fWLCWWcKe5CwRunLwRXfBXOCZgMCBWh1NXOax\r\n21C5VgAh2rd29HsJiCFsUdw8jiWPLpXxiYpg8Exm8ku7DiHSFaiPYY4mhFIb\r\nftvCUJzI4K3Vp2LT01u7Gh2xedhv7AW4RdanBTRka5oNIpwrMOjW58t9ZQuO\r\nT1BE5qADapG2MRiA0OgtI8fBC5/LRjPFffkRGbdRMVGOYLPu/lU++INf/HAL\r\npziSPG6eyocwCC6lGrm9r8wKug6tBV6j4NU9Z/gzfvTkNTBxyMTBMvCzTv05\r\nFty0M0I/65kg2U6L7ux3pSW5uB+54Yb/1hc=\r\n=S0ij\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001426":{"name":"caniuse-lite","version":"1.0.30001426","dist":{"integrity":"sha512-n7cosrHLl8AWt0wwZw/PJZgUg3lV0gk9LMI7ikGJwhyhgsd2Nb65vKvmSexCqq/J7rbH3mFG6yZZiPR5dLPW5A==","shasum":"58da20446ccd0cb1dfebd11d2350c907ee7c2eaa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001426.tgz","fileCount":811,"unpackedSize":1864478,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGWaikk/pTbb1vgvnllIrGkq5+Re+C9rPWR7N7phrJwzAiEAt3ww0ujdX4UpVUOEkLghzHNNk5Z/4PaD0mES7zfh8Vo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjWgowACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpBVg//RBwWErbqdwxGYaKQs2B3xzg/lugdTSOjVIH5/GD+q8kwMO2o\r\nIq70+rrW7aDMTYX3DVThzIVDsCD7Ma/gKs4l8mp4Rivh9Mv3Z7+4K+MQNLRt\r\nBJHZut2VQ5zXwEdXlV1DKRl+dKZYodxS7W2EgDWvgWm24x9Mg5CMglNlBSO4\r\n/4FSd4LDS1/cCOpsNCS2zRZHz7qUlewFrn5QwcP9ErSaGm/o/bldM9g00txk\r\nZPJBxFZjOtmO8DWeQALIwTEEtgObyIlX0sKKLv9QbEr8N6ufhBTQSR+0yB4T\r\nLd7jXWUAIzMxr+42c0PI76nB9kM6ozSERCdx7F35o9wm1z5aDoLF3Cw1vrVG\r\nIpjfBGAANpO7nyFJMvFxrKC2bbN4YXngLVTpByGtfxZKSM5dpYNYr1TLi2jW\r\nheeQpXLS0S/zEBrbfQjpknlr7tLjLMCIbPxCDejYIk7aLCcYv9n9WMHnmocm\r\nFEc5t2ZmvqZ+7gDSzv64E03xlSbC5o967CWmSW87BfXhBuPUCLBrrzJje6L7\r\n9KRt+bahDO67LLpBcNTPZ0yE22s+kAuyeAVwvU72ErxpzhQUR+dBxHPCseca\r\n+bM+z4vl7wDVxU+lV1ZorBtfxrPMW2BX72HElFGRAjt6aCUagR69cO/L3jpG\r\nPRkRb/zRGmHSUI3ArV14WHCbAoR0gnIsJ2U=\r\n=oEYP\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001427":{"name":"caniuse-lite","version":"1.0.30001427","dist":{"integrity":"sha512-lfXQ73oB9c8DP5Suxaszm+Ta2sr/4tf8+381GkIm1MLj/YdLf+rEDyDSRCzeltuyTVGm+/s18gdZ0q+Wmp8VsQ==","shasum":"d3a749f74be7ae0671fbec3a4eea18576e8ad646","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001427.tgz","fileCount":811,"unpackedSize":1864478,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG5forTWwLhDQqI0PnEwQvdH8caK+OgSwnNUTsQlqle4AiEA4Wg0n39fDzYBukxPPnakKTj9Kfy9hXbzQWIaDsA+r2o="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjXbyRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqB5g/+OgJSPzbsMkA0J6+7ortucmn2U4Z2d00jDBmWrqT17cf596Uy\r\nLHUjMy02Tw6nLjUjuzd3OZlOxm5RM1ukh7oG1+pKTXhfGe9e1/DwhTYKgqwb\r\njFv4TTpGRwW+3xG7OL/Cvl3p79iLBppELy8HzebFzqSL3hzp4bxyBWI+ZTSg\r\nqTBfFUE3Fdqpt8YFXzwLHzEB1/5P4xsPa8KZJDPa5mO4dlFW/gP7/3nAzCaa\r\nUoVHwaRtiW+zVz3nWkFDNE/keIy8lELbRKm1Y8ep3GkUGEuKRrrdDQA7D6G9\r\n5TRlZBs13J0usfkVNqSzXLaid8/pHIYhKd1VOz/HS0Ds3WrI3PPk/BQyJfUz\r\nVWSkLgCoTDh9daqzsJcmhJVI8dAEHH5Imf6ldR/GsKaFtW2CMdYPtRiIONAx\r\nHAHGfbeSXb+ZFygTSLyFn6vVQj/DGxPOpRikAg8Gg9WOpI3y+X6psi+Vbzlf\r\nMZYlwGOEe7KyEQZm2msfjqqP2lvlj/vjRSSSoFc6BPxyM4MxrZ0Dt2FDq1PR\r\nk2xASbwaRYYcbCpCOdwN4vaep+/2btM3ddtP294nOHtWm6XzdoTw4tm98/zf\r\nHq/wM9Ig6rNQND+40Tr+k0sqDHm6D6xLTwtmCcaTz0C1zhuOQ/9iIge+lcie\r\n850h3ZihhCqZcqZkgFO7IuApwq4aJWaFlkc=\r\n=FX8e\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001429":{"name":"caniuse-lite","version":"1.0.30001429","dist":{"integrity":"sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==","shasum":"70cdae959096756a85713b36dd9cb82e62325639","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001429.tgz","fileCount":811,"unpackedSize":1866161,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHtHs/3SlJn6EA63oXlWebxBAfnBZaX2/HI69okIKd2pAiEAxFkKs4sRMDvE6Y8qJibK62QdqSK5wr9JeOM17eaE8kI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjYLcLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqvxg/9HKPDr9PffqZKoujMg+fVmeOFz/ujk77F+QmBYmjm5dk8grSJ\r\nADvaeWgSYnWOire7yOWB6jo+dBizmzeaRi1RK/YNvnFggK4irTuQtctBe70y\r\nTGYm85yUVrGHAW16lMkx596zEb2/8qKEJXDyVEciqzJ0XyvARc8sEcl/PDSK\r\niTlzUOjEXFwyOLb44pf8B+AohIOxDL0exeYjy08IhAbLYPfF5HdpjdoETWQK\r\nRk27a4/BK/srTpl65/PU7nG7oAFEOOBu8V1rLlx3/RF4pmzPqqNiHCahmQAn\r\nn4Eu1seVKxbUCFVuOMVY5oHIo6a9XsnRyPhzi2V8s9ZP1TOGbuZKRtwQc2Aj\r\nxrH6u0YseiHYnPAee43T5bvviTYV5gY/jJ5ACvPOd09jxVE9ha1fB2OmYaSN\r\nWsf3KQKLI5QHqCuu9IQcnbNC725MwQEtfLcewgjpJVkPZUpO+cpOzZ8qKywt\r\nZMuYNkhzYC5eeTHfe9xhNwVtDFLpFDwh/kaJ27VavdrDrlpnN/Kk+jAqukXU\r\nz487B7mThek6s/tPIJLjOQhOIVelutm1bcPHLtNBt58lfBBPFE+x9lESmdTu\r\n1ztcW5xB5Tfd5RtFgcV/hQT56/MvaYy7xaq6ahLndQox+fSGDrgMcyUXoebg\r\noNgwneb9i9i0A9AcknCvWHCdx6MFqySuqlU=\r\n=2D6X\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001430":{"name":"caniuse-lite","version":"1.0.30001430","dist":{"integrity":"sha512-IB1BXTZKPDVPM7cnV4iaKaHxckvdr/3xtctB3f7Hmenx3qYBhGtTZ//7EllK66aKXW98Lx0+7Yr0kxBtIt3tzg==","shasum":"638a8ae00b5a8a97e66ff43733b2701f81b101fa","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001430.tgz","fileCount":811,"unpackedSize":1874950,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0neD0+3LLnWSaWZtElL+fUQ7Q0qdxgRa5J0Z5ireS+QIhANAo3vnmtbuaoo05CUIM82VjIXDGRlZyRzjZqY49anE2"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjZJ52ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqqBw//WrJ9uNakdtIen+teRhxL0vjVAECL5hPPChdnuYb87EAnfl6i\r\nCRu0xRphr2akdcU90sqDGvDgediZAA8C8nCbaxpb9X5/5U9fIgq4/Q4mHh3M\r\niDINZauFXDRCK75Nj4qy51HLB0DFXMmVICvqhDW5/WsD/GudFRpkLNn/zJ5P\r\n5xBh+spQzSRKBP8GK8ekgvauytVtoKXWt39gm0+ZnklF7gKGssNGoSTO1vEI\r\naCeYYXcbLPoXqZPTCXoxfvAi4W+iq0HssdHYwFyCk1tWXOMOPoA+0hwlTYMb\r\n5T4r1SN9XmLIFmDC1rHa3LK8PStorRR/l8ChOuIp1XYwGlORaR6Sqv+D4WW/\r\n5JvVs+DlbJ9n/F0qZibHsgUsLWogIJHgokBucWGbVgYp418ptvlz7cToq3gj\r\nysyP06v4wG3UnedEhfs1WeVyxxbGE/gHOkbUCh3Lsjw1zeAjU+oF6cTbGPtD\r\nhrzltCKkKB5Jk6RcnbAmPikcYSLvO3trIUeFbuAYj3263qpBz8kpilJObDX+\r\nRWsx/EkMRGxZ0nQoy7/Vnpc4sr0N+WBwict+XFwmlnnuJ6v+7fO/4Pf2VC4P\r\nuVVj1s1T1ROUbOuNOOnYzy5dK3vXoOnDrVU7hmrMFFCI2HOk0SBBQxXLAVrC\r\neu6dyw43IGhvUVQJYEuxQEtTJOXu0UVIcNw=\r\n=HNWR\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001431":{"name":"caniuse-lite","version":"1.0.30001431","dist":{"integrity":"sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==","shasum":"e7c59bd1bc518fae03a4656be442ce6c4887a795","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001431.tgz","fileCount":811,"unpackedSize":1874950,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCR9uCjnycOmu0I2CkJlaV/Q3TueTui+4lPh2EFz9gH7wIhAJuMieU3R6MThhzne3G+OPpCFIIpXLYP/j5MbSIkjB4Z"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjaKuoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmovPg/8CFQxQJXJrmqUTCHcQ+vXsih6Xpk9rliSjbV8yJQsZ48whWA0\r\nbDdhZgEU1SRlqhrco2OYw8TgEL5kXr9jFrJoNQuaI48+nW/majt0L0M4aOy4\r\nBjKBbuaC5njo3WEMT3qh2xoOFgavfRPgL4JpQmxCjVymq1zJrzOrtC64oAR5\r\nmiKpvJ9QNuFKHNwwA6TuUc5Ee7qEolpQwJp8zjmsd0MRJg3TbZyXtrJtWodI\r\nKo7vAD9p5cyqYmEIf3Q+Y0Lf9cQqGiQ04qQO2NLzzzcKJ6DqRNUUBonghEl7\r\nxVyTVs0pGJJ9hSY0oxGe7muZqSvcAHb04i6WLZqpetkmNyFWWVg8CZNmOarT\r\n0dVO9qlQnMvKejQQXRxUKLpHP8yG92MnY1HYSJ20AZ7db32Zmvp7qmfraYwW\r\nzA0QpPaihLzRCPLfjrEKwoVnaGfK/x9w2KY+Kkc8yluc4cm58JPWgReSjrxM\r\nubqsF8cGN3DFBlEbsJC4gZ6gEi5HqUJ8Mk9jxVV8XEC10W3NDX8UqVK8Vj8i\r\njiWmoEBSyYIyK8QaT8P4SLQx/wMhUsvIooK/Ezh687CHO8gyZzs0etv9/MqS\r\n0iPQkD7+3oKsYpTCnxbcDUlEj9iuXz30+NI3ufDvyU0OwSlX3ixmvZy0aj5A\r\nd8QGKKvKbJyttiLisYVhO77oHZiUJTyxofc=\r\n=DEZY\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001434":{"name":"caniuse-lite","version":"1.0.30001434","dist":{"integrity":"sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==","shasum":"ec1ec1cfb0a93a34a0600d37903853030520a4e5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001434.tgz","fileCount":811,"unpackedSize":1879736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGWMY0NAaIF5K7ijdVhKe2D+6Uhu+Hu8qkS5W/zjEjFZAiA6wnYYcMYJwpU3zjFHEoUXXEwaIzh0UwQfccWdjr1GiA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjey0gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrLSBAAkqYyD4j+Pimwk+A5KlbOAe2s80OsbsyqpXFVMnc6AWEn6L8W\r\ngN+dpJ6LgRI9no/fHc3Nk6svUYOekZjzU1HolWtqanl5MxDlOCewsrSbDRCg\r\nvAekykbHdODtHUA862L/TQUxopDhOETKRvWvFDBUZo+jUkyuComj6oji3ElO\r\nDUUf4dotCtPyEHQy1xY8w8YXqh19k17Pkl8wap8Ahdu0W7xXfFhMnn5o9V3s\r\nr499SU9bKid/MO74a2U7BKzYCWclxCO8rTkItXRIA0wVql1JXomaj7ygwl0+\r\nxp3Tw+Zi0gBY4jwQhrR1Eh3Rh3w69WdfqeGDDHRRcR3sSQB4OcUEapH7ylkP\r\nWmzmTe3hBGExE48vJYLwIowrkzRYLOld/H9oPkq3WTNuewFpd+o0xjjbBTeo\r\nYXsdO7rtppj0ojrVFNnBt0oSJLjLyLnKjW+8DmHHQTCFj2R+ms03sBrwAJBk\r\n230YUBlF3v/xwVtQJprPFJO/NQztj0zc/ozN9ZfStdcKRht+69BXk+gcC2Ie\r\nh3kwIFyeE6M65qNEzwioVPTO4sz9s8HxwnT40pJHisCr6NY7o+Z0vDGK+i1Z\r\nm5RumORXiEj8FNfoWiy2KV7lyCPDraEANSPuHFDeVVd7KvcdbkqdwlGqMabM\r\nI5G/9iNX4hOL7cw+mqx0pFSq7BN2r2Ix2gQ=\r\n=lCgI\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001435":{"name":"caniuse-lite","version":"1.0.30001435","dist":{"integrity":"sha512-kdCkUTjR+v4YAJelyiDTqiu82BDr4W4CP5sgTA0ZBmqn30XfS2ZghPLMowik9TPhS+psWJiUNxsqLyurDbmutA==","shasum":"502c93dbd2f493bee73a408fe98e98fb1dad10b2","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001435.tgz","fileCount":811,"unpackedSize":1881446,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIClTOoaukfk6bXsdovAF5It06zF5KjS5UMw3JaRzi/wTAiA9dkdLGZmTi3sJf5qTyWLAZgznJRHilfP3a7z55jm6Aw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjhu5rACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrvJA/9H7tWws578R0i41pxuLAJKiB1e3JVpiNRji3r5M9qG2TErNEO\r\n5XGV8NQ7DguD+e8Vays9z47PRtSwfdkxvQDZSUkAvr3b6sd67s76sc9qNHm0\r\nLLNXs1AxSh5bnr0eAO8Fx9YVU9A+gHVDCNLPNu1U3yPrFSA7s6TckK3ms9sf\r\nDBnk9MdezGG0LGvoXyfKFJBKavbVnW9JW4yZp5PsuTrLG7PQEU45LwXusFMi\r\nuOXStURVZDt56lANr32e6donVSJGSAdpKSNb3ZxHJvaCUBLW1yHMUYqqi5NC\r\nfVfQjh5oJ342SEZqHk9eVXG9AfTlTQNDSdAVIcKhkb3PjeWL84QxPvE+Jqp8\r\nXJ6TlOtvW2RCQPqCwa1OWRx54YwWBMhj4HxM78amCz9XQulWuT+0Mk+jLSKH\r\nl+0IlJlle2nPQeIawQSowaOf6WwS3cDtLRGFgwd41/dp5aWQTQ221ooKrG/6\r\nJBC0ovx9D69jQ/7nPPj4rjeq1AYZBaiLSRTj/grdfIqdbMM+1ABHVvPleahi\r\nOO5UtQ26D4VNre2mf/jLI3VTh8pVuURrtKFXfN98SrLMHUxnSzUE4L8dvMbK\r\no0Q+uPUA7Cb3d5lRxDEvLE2NW4d7NkjAuj5eX9xED0j8x5JpYAaCoQaJJiml\r\nFD+izxY6J8K1ezWkH0W7wR8sxhBhN8UpNKo=\r\n=p9yL\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001436":{"name":"caniuse-lite","version":"1.0.30001436","dist":{"integrity":"sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==","shasum":"22d7cbdbbbb60cdc4ca1030ccd6dea9f5de4848b","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001436.tgz","fileCount":811,"unpackedSize":1881454,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDysqYOKm6HDINZpNoALrwE5i9+oNVaEdHTbJWb6QLfVAIhAP5bKASVQCYitxr6701yzzGsctALm+++xBadpP0SR3jp"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjiv8XACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqeWA/+PsBJUDofAV2C6EzbxINydxRYCauu6+exqwIKL93FQUG7QChh\r\nchJlbhg0IUhx9lrpZN1iPkse5NaFXEPFofqpkzmteJ0lJkx32cOtQTI4W5lB\r\n/40D+66RNPcqEsVtyzG6di7jPrEx1fQMo5q0vE5FNe0lU6u0FkBuoETYewJh\r\nHAMx5IT8vECDGJUhdtJ8dSWpPSHx8a915U+l/lNHjG9uMYOm2vyCCT9jgzmK\r\nULvceaD8/qCysfSq/eA1Bdkyu7PKmzbomQ6AGsD6EDzzkcu7NHQfTJA9cKkb\r\nmBGPs8emU9lD+hByv1GZNDPu/PBRhVWN1LNK5Jt8nOZu2//T7Tt8oY6XfLMr\r\nMpIsd4OsGN2BfrBelNXFOLSN7LcNeQjZ0UVntCuwMizcoNApUuneoO6LEFno\r\n0knU6bA/goAzmfEEHEWJLQ+Ha7Xcbu4vZAfN/WYGZ9wFEgrz/N0tohHmLf8f\r\nS+hgJfcfptvSsusqupYS3CqNrcDkR4IraoSX1qM70U9XFOwt2HqKCBOm+pB1\r\n/xn1wEx637jYXs0Ph++DytceDWrLsNy+2UOLkMyAvQV4FsmDYAi6xuG9Y0ZG\r\nG6Imgw7tduSIPpn5xnVY9Va61bJcNmH5jFiL8SP7HC25hyppPqmmUkesujK3\r\n8ITJgzXW0U6pHLYaq+wNqPsAuFoWjPzoWb8=\r\n=M7RS\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001439":{"name":"caniuse-lite","version":"1.0.30001439","dist":{"integrity":"sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==","shasum":"ab7371faeb4adff4b74dad1718a6fd122e45d9cb","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001439.tgz","fileCount":811,"unpackedSize":1891521,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC9XwUtB3rWjr+qcrNSUtQevzXZsbWLDVhjxNkBUEQ91wIgYp3n+8N3gklHdwE4IXSxgom3LHAbX8ymkUrijQFPBHw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjksv/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpT/BAAnlIcfDogxPgbQ2SmTAu1R6kH9jIiRbQ5VeuNdF8NQsS0ZbNh\r\nmMrw5Yp9kY6PckeAQhK0kPoL5ZCALztU/Xby7h9Odb53wqTLG9LxOrg+uFyn\r\nI8Af99heg2wAaXSRoztKazvTZz3TMBUBoisohz8/MctLvhrx4uFZxZSUR/I3\r\nI+8RIuOsipEKrJclxZDgIwb73lpRmPbNJBH6p6hKtKxFNQsEgPH4QjATxE0q\r\no2dai40CyVOMLRQr9b9IioFS5PXeLi8tppNdg9wix02rRC9pQ0lhB7TGuQp/\r\nVhgDP5a57NCk8dGRs2xPYNCH4k1uwrEzxXqJPZ/W2WebDEu1/kQh4sVBBGuB\r\nTwE73JV4PgVqCdjQK8xbSw0sSw0EY5GNe2zAsC0GsvYnqLv5fuA0UAMb3i3A\r\nK03kqfw/+NRFDtnGmfu3vjzY0jdwjkJWQz4EYStELdkogLguxmHKc9tFEC9q\r\nar/F9Mh9K7cyz7QpDdzxPgK/Y8yEJCcD5USUF5P6oTGAB0oLWvLbjqtOb7LY\r\nGaoD4P2GKtWOVw0VBUsDUtGKVDhFBVapta+rMfvcRsWfT0Fh09sp6fGHSmfC\r\nKn1ehnFfGeYks4utAlCBFKvP62NK9AIPCVnwcS/Nf7M40auT9pCF1J6Kd4r4\r\nAcWxVwwS38F7QGWLXe+9QdhqJqdlYjbsapU=\r\n=f1a0\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001441":{"name":"caniuse-lite","version":"1.0.30001441","dist":{"integrity":"sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==","shasum":"987437b266260b640a23cd18fbddb509d7f69f3e","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001441.tgz","fileCount":811,"unpackedSize":1896594,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAl/j9jbc75SCyg0NEbENEb/5TbN4K18rOA5AdsKL0FzAiEA5e6sCCshufyrnzqk9cv3OrcnwfRs3Xr9PRSpKGzgEeI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjozmTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpG9g/+LMeMqNcckpcvyrRGRPbinfucnzgFVgHI84u3eajUoDD9S5Xf\r\nP1rYuNDFNMW9FAC68xkPFJeO5FfEYpV5viJG03LgkwNmp4XUKvlaZOwlmZFM\r\nWUtG3LA4uyBNokincb+6W4o5Dwi5MmFUPwcDaHSz/YwQQ57Gw/MmnVzfhxxs\r\nQjFI5K1wxsKTYvqMslPB9Q6VYsAU0WfhabtVmJesrySF6n9EUpYHPoAiJm1M\r\n2U3MJ2Qs3KNkTXgV3kdfoXJWTtBzvkclEZ8YGXMt7YB6UKss5EherZAYE5B6\r\npPJmvb+lE85MRCzMmH7HJ4DkHSw3/C6wXdbMuzHFRzSBzbO5jZoLDmZuUynX\r\nyzzin40NtuOwR3ZhtTmdACN1XmL7M6UDg2qPa3K4A16ENzBut4QFioCn2NuN\r\nWnIT7U80oeTjvbzy0f3JdGh+ZxbynP+b/m78pb13yv+sKqcROwDfBUQ5p4cU\r\nSkP04nOURZWNVXukZXseRnEEoie6kOxSu2qLxFJL5quODdAeOh0FwAYuhE9u\r\n5wVquK/i9axBU3ObigcWYfCSBOzYHeIz/NiAWVXee/rKwFeztbUbEttDfTjo\r\nLYrC3XQhBZMiTtI8rM/SCZPzJDrrL2bxACFpDKUEdfEhdwbaxy97+dRB+dRe\r\n6+/rIxNxWVZm4mk2bU4o8jtu4oHgyCChZOk=\r\n=DtQG\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001442":{"name":"caniuse-lite","version":"1.0.30001442","dist":{"integrity":"sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==","shasum":"40337f1cf3be7c637b061e2f78582dc1daec0614","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001442.tgz","fileCount":811,"unpackedSize":1904557,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC6k+VBZMsrwsFLQABs4A2fqVaWoNOmwHITWlgrR9ztdAiAdtdsrqXX+dDCnxTKJBxfOz5ILB7bssRS8i7DsOREu0w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjtkhhACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpthA/9HAo2pZTDT7Fmkj2pxT0BvL1MsSZP58eiRdTAnOwenWZJ+jcw\r\nIximyYFgPYofH/qkNiLuBLzlQyk4JMd5mp/InxEC+neQC5TX7ItE6vNbye1v\r\nhOm9zuizIcFOxX+DQGjUjCHuGRmOjhedXwUJamUq7Z/8ywGgQEEd0muqjwwx\r\nqDALYsstdHSKrhxRm9DwT54s5cV9cy/sEixMH5vKZ1Dv66aROza9Rrzjo42H\r\nbFvB5FHk7MCcXgWR13opkic4IDQso/zyYGluiELOCDGfu4+PLDSf5fti3eJS\r\nFHA7kSPSyTZg8gk4/OWO5RETg9VayK8tJ7HvvWDRhFH1jXLlJaiiqAZqYpnV\r\niL86G2vVMo3yM0qw4AWMgwlUm1K7+yKqBf+qART2pDjKKuW8htOQcTbJ7UVH\r\n8rJC0EtkpjHmM9H8x2Ekbmp/SGhMZfdJgz09nmesD+w0iYgvAS5Dlq9xMXoT\r\nNeAnRbA9gqsxKrwMtzHFpfvx6Rn2QYiAY6uFEhpyge3ybdZu0YPenBntjDYb\r\nEqkEDZ4QEXScAo+J8qhUvxHixKnrr8TlyXkP3x2H4vr6l81NGMOFzZSfnGnU\r\nt94xKcIMHP1GsNgC5wH5Vv2zY2QpxDIJX0CI8IgATGP2J/Mtxu2Z+oSp2LzJ\r\nkrR9CyshjrUjuU0m0LQgfArttK+PGDDnH78=\r\n=vrU6\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001443":{"name":"caniuse-lite","version":"1.0.30001443","dist":{"integrity":"sha512-jUo8svymO8+Mkj3qbUbVjR8zv8LUGpGkUM/jKvc9SO2BvjCI980dp9fQbf/dyLs6RascPzgR4nhAKFA4OHeSaA==","shasum":"8fc85f912d5471c9821acacf9e715c421ca0dd1f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001443.tgz","fileCount":811,"unpackedSize":1906264,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLUOa+yGaKXR964f5voK5HJ7mUQlpR0bCDDnVZ/DYQ2wIgcyPthNjZqqI7ohzp/qiRWn42+JTF1fi6DG5DBf7Umbs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjv60OACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqpwQ/7BZ7PGVCKmXYqjBpi8y2Z9rU/HkjK14ULJulbACh/YELBrOGG\r\nEbMdAA8uYiXN0qCwk1wtsi81Ksc/eIyewcAHiKSat4r7tqKJdc6JGOSYYtHC\r\nNOUX6PNA3HHEPGwAKgwtD80oGT8Yhg2EfiFsR1OBDLY90wR0AAmbpT7QrKtK\r\nHyvO6M0+JK9xfHOy3u2CrEcJ/TZgnef5/wR/VNl6fR1tDXXh6FK+mRxtB191\r\nW9tB/N5fQteBfubowo+PYkTV/Yi1N4Co8O4XCpeAqxQPQjpvJWYs5CuAx9vB\r\nYfnsSG/WcmtY8OBjCPSWI4TI9VsQDmzQWkA41K0+BP0hzzG9yOJZ/V15zyi8\r\nV+Uhg/FXAFljep6bBpX3jky7sWZWsz2DhITzMKHRj5TRjdOyHWySBesGBO38\r\nb8nb9k7LSfQlTNQOgYaIYWsdNn41hvfqbgcO+cRul3WVhdZX/Xu52L2tSLHy\r\nAmHFYS6JMr94l9eRbLq9RKDsUFWvVV9fBcEqeK6SBi9H55u15CfH4ySjOEE2\r\nSHQb0gvfkaQ01xhMUeLePioMlwlNm3k9Zibb1tZEq5UU5mikHYIu5ndvThjQ\r\nLnreo2JYbc5K+UKjqJkkAbjT7yQaHdkGBOchDHuQyNI+AHud0IESjiZJMzGE\r\nNIbifyqCQEZUd/j0PV7+Uy/HNdfrXWUuMaw=\r\n=6b0c\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001444":{"name":"caniuse-lite","version":"1.0.30001444","dist":{"integrity":"sha512-ecER9xgJQVMqcrxThKptsW0pPxSae8R2RB87LNa+ivW9ppNWRHEplXcDzkCOP4LYWGj8hunXLqaiC41iBATNyg==","shasum":"c0a530776eb44d933b493de1d05346f2527b30fc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001444.tgz","fileCount":811,"unpackedSize":1906270,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC4Tn+FsCxeZ9cugObYmzuA2PLljDjdw8n/3YrNAdBfuAiB/0vqYyfPKYrpi5YqX//woIzGc9yzlPdyRv+EBiZK3Qg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjwPB1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp9cA//SuWHF+AQpbIpcvzcO42hPa5Rys5f82rfO8j5xQcBp1QsORCQ\r\nD28yfn8XUDAnvJa89YCtEVgWmRnG+vJ3zla3n7gUALUDDAuM3a2cpboBM4iH\r\nxpfAQWzsiCRExtRusUbgrkD7CMR7y7h3gL0WpfMS1u9FcC4eChWxXQcKiY0e\r\ng5814f9anNmXRgU3e1Y+AcyMq7mHJK++HlnP97UPQGh0vWRAlGndkMNYwBSM\r\n/6jbezEd3RSJxvCLr8HjvXGCBpaHRTLrlNdECYEcOOOJxe5PgMZwm+jTv9SM\r\nfnAV7IRKBrQGAzWmTc1LMLFUjj6W+ve/IMPeQLz5MY/fsUk4O6kccMcNaSsT\r\nZnRN6EM78HICLB0KAM0XgoJ6P6+9xX/+RfsvX9jLpVe7jtim2FP3gjQCGrI7\r\ndZUoDmHBlAELcDUJ9gokWx+JCrYs8jyxGItA/EiDMO4I4KyB61taeNrWahRL\r\nuwyo94jeuXjeLPNnWyeKX1JSkwKt5CMUuGYFOjHtyHHqMWzVvuwKRAE6PKGB\r\nPYYyfU0RqLfkgqSai0/GPKVO+TFLdH42zAzpvqBG8pAhAVzM+nnSp4SM1JSd\r\n77tuxUequEusoRbfmrUeyZDwjcbKrg26ECJXl3knBPjbhndz7t+9l69AYKHx\r\n4chiXteMfbgWTVJP18yALYDFIQIQ2/ieYck=\r\n=Eduj\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001445":{"name":"caniuse-lite","version":"1.0.30001445","dist":{"integrity":"sha512-8sdQIdMztYmzfTMO6KfLny878Ln9c2M0fc7EH60IjlP4Dc4PiCy7K2Vl3ITmWgOyPgVQKa5x+UP/KqFsxj4mBg==","shasum":"cf2d4eb93f2bcdf0310de9dd6d18be271bc0b447","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001445.tgz","fileCount":811,"unpackedSize":1906288,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICbVYucXvgy8QrnqKHykFigGmuQmfuImcqyknUnEKcNhAiBT9zFGpc6hzzO151GC/wpGbTYu/LMwPewBt0zIZWN4xw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjw3dYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo1pA//SsRxXF6W/MdpWq/X7lAb+/IlsFI9dmafxf56EvxobrmwHEJE\r\n6+Ezx0T38vE4Jssk8sk2YwCV5t25sF46NxuOiFU1T3aRvwit4nF2i6PUhVz1\r\nCxTMAFp76h79rBxBoy2YTPav0hOutoz25H/HC2DK3pVmUbHURxcpTP+5qdDk\r\nzZRiwV57J8RjtumxT0zWDz6pR+cukQv2Cc5ECj2b5WvX67wb+XVHaj+oHjjy\r\ng/wHiYlldhB0o6r/turZ7HnXCouV8SgUSzl6UmbcqqZANzdizkbY6jzrmJBq\r\nDXAPIMdkNBGGyrZH6yUx/gliyr92ZwFbhZNuBIeqJ2UOQfiF8qyiiykaEzw2\r\nrpvZin8uSwLJwAkulvOvpvaCeFpXDzjxQHd8I4J4IPi6S5AnzZRCKeh6Uyh+\r\njv3TrhQE8Qhe51dAsDU2IxmbyzdFWzzrnbJhQjimxb/adLO+PAPtjV9MELKi\r\njvAaNkXXCx07jbP64GvzwFqcJ9MObg2Wg4xrK/CJ6g6BHTb4YWrAUUawARvo\r\n3ZaDs/KJXjuicqYDcvmpjHiwFT4Kjl6XZSr1WwcM+E64H4/NeQfr89xJH/fo\r\nDqwQlKNDm4DudyhaP5QvpoN0Vu5pM7mSG82x+mdJLhCfeW1NwsuHzr2XjLzK\r\ncsbf9+GxS/scUthcUFKB1XMq0luXsxNy9BQ=\r\n=wkXh\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001446":{"name":"caniuse-lite","version":"1.0.30001446","dist":{"integrity":"sha512-fEoga4PrImGcwUUGEol/PoFCSBnSkA9drgdkxXkJLsUBOnJ8rs3zDv6ApqYXGQFOyMPsjh79naWhF4DAxbF8rw==","shasum":"6d4ba828ab19f49f9bcd14a8430d30feebf1e0c5","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001446.tgz","fileCount":811,"unpackedSize":1909744,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE1TjUoGHzcQaJxlvhSs+1wztMvRT3ldI5jkr3LyZCjyAiEA8e528uCIjEoShXFneDVoZAKK5KQPnwT+nRpZwIpd/sc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjyLJqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpGbA//XOgHiO/0xYJaoMX0IdRBOlw1HmblwtccJcVZaOCm5v9KYCxO\r\noXyt6jvjP8w9XPRvweTKZRHVT/jL+rTF/qtiDCfiDnOV3uG3NtNM/XlondpZ\r\nho93R6yyJabwBEqLbkwnA2sWvbIyr2H7Pv4J2gfsI9ZGIU2T7qKZrE3HcAn+\r\nUUZV6cymyH/qefx/HRTHdgFxLaGG7oNINZrE7QV7YCDMo0wLyNnmxurkiosc\r\n3KkL9FLNyEe1tXctRo+nzRegm3Mwzvzx/J7YVyclAWuDlKVuu1f7pGjd4MP7\r\njyLSwOGCTpLhXAsJm96zXvdMLxplDt7Gimc4TBkkrbx6RjMSL740rDBWsjds\r\nTz2nI683aO3tmhmCUocG17mu0UKRu8cXGL98kXnOYekM4rwkMOwjiBAYKFOX\r\n5jsdRZheu6KVDC1upv5YROu8wQU8lr4KgRRw3UonIU7znEuR8gOCwKSLKZTD\r\nTqVMVU+eJNBYVfBZgMh1q2Jpmb1Qv/eVxXSGFUjlaVD4X4kde4iILe3UHHm+\r\nsqoRjdO0TlbwSmXIadw4PUicyOiEbN43orEZzW5WES+XXenm+KYLH6lgbSjc\r\nzgNRKcd6r04guMZ0yly5e0L+0ypm8efIYn0BDn+gRIBRLoy8dMa3/j4RLt4k\r\n6ZD6MQ2rxkTPORS821pOAqvyxkXJOf0jeh4=\r\n=3a0d\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001447":{"name":"caniuse-lite","version":"1.0.30001447","dist":{"integrity":"sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw==","shasum":"ef1f39ae38d839d7176713735a8e467a0a2523bd","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001447.tgz","fileCount":811,"unpackedSize":1909772,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQfE7rOpUtLZjGeKAHMQ4j0kDQ6jWVvozchp7I0Z7pzQIhAKExYpHI0FTL3zqLC+fj74tOcavivuGVKj82VPVjsJ9Z"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjzjubACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrJXw/8CFIuYbT91jGeRANNKFGaZ44ENlKHq9fb1a+XyyRG8pYX0cON\r\nK02gOh12CM7NI1hRCGDD3y5syqNVjvn4ejEGk5OPLeFfX92bPCO3eadRho8O\r\nP8Z/oylzrkYP9AEjAQWxKywZtb0jcInl6x7vUeOXgRKkAGnmCA8MYdxnYHYO\r\nUwX2gcXx68dnrnShK9rdGFxhfgMjmAP6qjOB+bDVqzjscWGQhTubZ4BpauRD\r\nl/LsdDUzlod0oo2jg7hSNmBXXrEbTLELq99AWvZqwtuLvXAwsQS4glONuhG2\r\nQk3CSROQnwUTQq3Q69hCEfDhPuTUdrDHP3kvOyU9M04tSXQjekk+M0G2pwDd\r\nIB687S28KS/cDgrGq0SRXcLbVrcMw/0NLNZpgH/A/vUtlaY/6ldWEqc1RTjU\r\npcei764It6+hvUctONTLVpxzQTdGNe3Mxe3/G7guGqdNtqwNvn8ICHWYgkaZ\r\nTj7C7Wmdx80NiyZKXbD8SUuFFd/z07DHbyvzCJh4novNGG/fm16tvjyx56J7\r\nZjdlV5cHXtgPZTRBuCWNwhhPFJiBl4yUAP98QWgkdjcCgMy7LT4UWSPF81Sb\r\neJShYD7hSyufeHSoM5W9O1prlVf20AdlWysNUYyLEoMffcFlhAjizN7nisoz\r\nXl3U2dN7PlxCPwBaxZ5T/Qjm1BKRDtu6jK4=\r\n=V3b8\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001448":{"name":"caniuse-lite","version":"1.0.30001448","dist":{"integrity":"sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==","shasum":"ca7550b1587c92a392a2b377cd9c508b3b4395bf","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001448.tgz","fileCount":811,"unpackedSize":1909784,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHdUYNxbc7fptK6xyCaCpQ/T7jD3atWqkl9sJDwXdo73AiBVaqdjCdDLIq+jB1B3NMs/0MfuiwM2NwzP3fnAH9HveA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj0NCPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqPehAAowtkUvvok28e0p8TwEzmOtAzA009F1UZ7qSTymr7RB1h7OF2\r\nG3MIRNxIL3L9E5ZQeDXp7fSVEOFIhH4VRq/t8WGFbH0tN6wSnnS3Ok0NybDu\r\n6ttg3+5s3ozyeCOu5o4VQDwPBT7rMpVFD4g14m8Vium5tuCAHEY55qKrGrj/\r\n5g87xmYLaY4+sy9gVOY0Q6syB4mY16nAeSP9tyGDiQm3yhD9tDQIBQhzxBi8\r\n53aa0Y0KYE4KBhYt5WtnOvG7FNGxGET2lQKZzsG9Le2sw27gMO00Wn/WPl5m\r\nEtygEkwKFSjbBscNICSaFvZTQvUZsVhga0oWI35UALtzuNlrDnm1arPPIkC+\r\nuzVTkc82sW8VcjQSdfXZt9EcKVDhSCLSaiprQHtzszNzRro51jg73G4VEgmi\r\n43ftKflpT90tOxqLsKFNpkH/5H5H3j4e2WOMNVjq8gcyt3eyaKeSBNK91mOO\r\nU95jgPLwsockvznPcbGz7GKLwixTbiGqJWm33Kqo1nfWyevesunoA1yrJKY5\r\nqGYSixkbm05PPUu5MtPikCuJ1pNXyxyQZiSdQvxLIeUR1lZ0nVR5JxrKUe1p\r\nUkBLkbYxBYteO53owLnoH8Vxt30wWLhDX03FjI8XpJ397EgPEXgSu7AcHvgd\r\nsR03+eCChYrF1OR60hs+jOqPeJId3vm5/go=\r\n=fIT5\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001449":{"name":"caniuse-lite","version":"1.0.30001449","dist":{"integrity":"sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==","shasum":"a8d11f6a814c75c9ce9d851dc53eb1d1dfbcd657","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001449.tgz","fileCount":811,"unpackedSize":1909808,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICLzGa0mWBSH0RMxh1Sg93tQAL5XO+dUS2mrErQTms/AAiEA3ytj8elAf/SjroVIXHzLhHZ5aI4VF4YJ7ey1MpAeWO0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj04GgACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrXnw//bn+qgaDkflhSrIxENi90AI+FTC0HlfWHaTGVztYYiopkdA+4\r\n/8QGXeSCChSV/Bi0EU5FcKO2ZHq2JijxiTqRSlwjpwChskDZB/ycNJGpLXa/\r\n8xZF+d3dPes0TptDluzNkzBOFIsuAw9uID8n3g3RrwrYlElIvU2yTJhBK/up\r\nLRC3PfKp5M1pAcBQbgmMpNxrdV153NS/nxAKAnb9r+co3Bzd/etOnr565oyk\r\noNw9y3YzaiScrPbGnR8ejNjQRz0ELLeuEtfrcoP2xeE0RwJ1C2u4mM8mtCW+\r\nibKsyOq+HfnvXpoNuEk/mBP8ZwjIR5hkp+M123pYdx8+cxOtNhv6mWRscTg1\r\nYY4gTaNTSWXThZzJrznCGGC1ywpnbei9G9E794K4dLn3b5O09UsRZGh78orf\r\nBQ0F6tfQy4h7jkBwSKeRqOKn0wUgcRsP5nKK8ZSzx5Fhn+BPueY1vb5om0pZ\r\nkm9iXqFdXV9vkCrwsOzXG8wnxXw2Ws+WzsKsr9p8Spm4uAPPsPbatcV8myoI\r\nCX+nhA7kt7U0KstP7QZfB2hesMqUONfsPhsdtuYL3pvCvFqQNeY2NyMV/1u/\r\nMvXPa7SPFd13pFVxGbSxr2gyW46FC41XgW7GfwYwUHhita11K0B1JFlgDv7y\r\nEoLqNr72fPXQWq8OT0BOlvQoQ8SXLZFFsnY=\r\n=nU3V\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001450":{"name":"caniuse-lite","version":"1.0.30001450","dist":{"integrity":"sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==","shasum":"022225b91200589196b814b51b1bbe45144cf74f","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001450.tgz","fileCount":811,"unpackedSize":1912085,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHPkqhCTNmj1hUMr3v3eCjb3OtnVSOZY1rjdcWCsrb1AAiBCEBU2adWGyMZh5OtCDRkha/FZgcOVbuo6fOLDSwFUaw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj2e7hACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqfOQ//bp1VDy4mr85Je4wt7mx1yXp4LU92qv9yJBhjGdiAmZJT6Ur4\r\nByPZy0FI1zPLLJSd1cPMXwKYukmj8x40fuODxq0nVc+0aTDD/Y1QzPwIFnar\r\nQINOSBEkThJ3/clCtVz8FnzIDOhnG5gw1SHcFdekF6Z68pvMxaLXYeNrKYzW\r\ne/GVgTQwWd2tTFTHb1/gymN0DXAr5vfYycwAtfB8t1pMSKnZ8nlG9mVAso3B\r\nVcdMmyBM8FXMusvM3DCKRxLZf3y3t/WiGQkNxQzHQDXd+1PmWqkPwHNdOmwY\r\nPqlnQtoqbni2M2wW1bGL9NMXJe+16JWarwi+fLRfJKgthdArDomQVjNuFOwB\r\nXSMOlntgrDcci1ZuE6dWCMQ4ZNlE/8EfE+JOx2MPtKbar+yKfm6ZlCTHBl/p\r\nUCGZtnImdjAx9DSgy/K24KKreRK4DzVzRIZhb8qfKThtFcB5JP5T7FDquK6l\r\nhNPj82bGSK8YSzABuWlD7BzGfKdYJ/sj/VofFkOWutllEDMHOvVt2UUBsect\r\nrYEMlteL2bWfsn0LCZDxnXxVF6yAv+bvS7FOXdjLzV1PcRb1lrW26vrMFrBv\r\n+DSgqPrhilw1ba+yhQq4lUkBEGYeqwUEj8QT3blx8qz/45Ta0WrZbY5wkwK/\r\nwgRqyHqKNa9kf20FKKUuyj/oXgrODTPMSvY=\r\n=wxaD\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001451":{"name":"caniuse-lite","version":"1.0.30001451","dist":{"integrity":"sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==","shasum":"2e197c698fc1373d63e1406d6607ea4617c613f1","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001451.tgz","fileCount":811,"unpackedSize":1919290,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJnt5JBGLDS/19IFUb5+iGrhNhCjEWPrnjLYfCuzoNBAIhANW+NVvZiDJM+Jon4FXKlI0M/MpJJoe2w7Oe45M9PY1f"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj4xCvACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoZjhAAn1tArucKMPGFoGXjcdJ6mJAJ53688CbGY6utwZV+tiovJ+cY\r\nsjeF73ziJIckWHex8VKh9iCDzrvi1fRgX5i95ypwGNVkG+q2dso+zP+95Fwc\r\ngyP0WDv5TO356Q8TPbHgd9Ok0b8wtajmlUID1VBJD9ksG3c0YYi7IKSyyL7m\r\nTo3vJMqhsPPTOQHsDNOrvFHQW8WN8hD5D4HPULYjdM2yT6ToMMQQRF/nYUZf\r\nSYLx21P4Zmo9sdn01iUk1NkiXI6gKnC9M2KK14b0Kvafale43daAS0EbodLh\r\nf4tbdmuMECVtaacumviLuFjjCzCTAC82g0YHQN26iILev2ZBZvtTcMi2lO69\r\nB8tkO51KLX4R2r528m091H4icpJ7Y6TyE9mk6G4DWrieZvR50CMzv138dPJV\r\n4jeaT7hvovEH5yFQf0ZDKJ64kaPeEx66fvmswJXcqRVImXqJ29G0tViIoPjO\r\nz5CmeeCDwtqkzXN80ncsbFkUS22scfk+5W2euOCFUUirsJP2hYaYFUoouAfu\r\nVjhj7vi/X/oVM5v7aK5busPj6wy5P94tm05ctH7NnhIJSldL4qJAQpTy/B0P\r\nicbWnY5de6nquRZZ3glf3iJRSC4clsAf9EMj5LnrvhMkqq9TGQmiDhF1Iar/\r\nm/KpJtlHzZJwqBH2VaIi4dPbHeuGmerX6P4=\r\n=k96r\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001452":{"name":"caniuse-lite","version":"1.0.30001452","dist":{"integrity":"sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w==","shasum":"dff7b8bb834b3a91808f0a9ff0453abb1fbba02a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001452.tgz","fileCount":811,"unpackedSize":1920991,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDaOPaxS/0vqdkZdlD1Dp93juR9Oda2p4AXQyVMqrOrhQIgcVxQ3GHMMli4MpdX6kmSOdRyzkXl4bHKBUWix27n/Hg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj6yB4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmph9g/6AhaDMyvxbOuTzBCJapKEdYUfJLtfz7i4MrlSglvRHb7RK97f\r\n8SaKH4NGnHBNlBX2KMJTl8SYGD1VCjZwc/yS4BIlko4zfxiwj3bh4EKBwa2q\r\nTkqL4G62K9pLvQoep1hfDVuERytLcirTeQbWib2JLRSsENV8EpYizKajZcdk\r\n+O3GQN8NmFkBmeAibztPX7N9Mw9r6ge/I4U688RPIaRGUTN97ZY90gha5FJa\r\nxBZrMIvdxP32CA5VH5LlY+BoNGdkDgPbdIEv5qCF4S01e28M7GL7KvJOpOD1\r\nWKBQs9Th3ITTp4ZXqNxHmeJBp7cOqKg2f9Cbga5luPCx/DAGOWBGgErTDOqT\r\nffSXJWHj+3LNCUrAQlxABqJZXHet+PFU8YEYf/2ovQF1pwloGel1O+zeVzWW\r\ntbsLeCyeWYckS26Vqr3S553uf182jzRNaSZ2+HX+cyR8O5gVBIm20CSOnbya\r\njueAUtMXPTARGOPKsg5eqxnBXj+itQ0adkCgoAg4JxU7XM/RXeuokFXKJvL2\r\neVESdoU2NPvAilNOg44Ul7pNlXL77KzeulJaF8EcvReJENdoQ7UXqGxmr2Z2\r\nozIFAoyGQaNiYOCh+S0qO8vzv4Eu94FMUCnyBdm2JPQHKtbiSdJZC5wKdtqS\r\nB7eDdTCf06iFDKrQ3bYPQRJuYkMiCJemumo=\r\n=LX5c\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001453":{"name":"caniuse-lite","version":"1.0.30001453","dist":{"integrity":"sha512-R9o/uySW38VViaTrOtwfbFEiBFUh7ST3uIG4OEymIG3/uKdHDO4xk/FaqfUw0d+irSUyFPy3dZszf9VvSTPnsA==","shasum":"6d3a1501622bf424a3cee5ad9550e640b0de3de8","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001453.tgz","fileCount":811,"unpackedSize":1924430,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDelWvPEL2wsohsq6zNaoHMwNnBmewiINIFrrbqI5wwagIhANn5I+bvQ/A2ICea1rcnI1wq1874ZRo/xBQ4M0iEOZBX"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7dGIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoE7g//Q7RerFgUiwTa5XYFp9PSqifjWYlm5kOg86tAVfFkp433r1N7\r\n6eheRih/6iUoXYixa/9AwCLNWHUiUSxcDU86uDWg54NVb4XtCUUBzZyD4siq\r\nIOuZf0AtoFFtfelmFgeSE5gREGo+sZz8zCegcn7ZSvENebCyGnBGfH5JT4Qz\r\nH+nAzF8ip1eKy81kK1FkK0NkHQgYEtoxenlcd53oLFbaV+iLLV2gyLdPWjBw\r\n8bAdMjgzK2PJEhxkTV58pfBRR+38UFKex5PuZ9QFFWHkDxQJau2YJLwT2Jcg\r\nEy4ShDRs8GL5dFz2oviYtCSSNp3YcQ3csEOqAht6MwhezIyF2OXAm7jK72RD\r\nDzH7CiiXw9vZBavcoZ/DVDWJ5yJxtllgFIU9ogRWI+zY2I4AGeTTrH9VNUR/\r\nsQvIHOO73tzzauSILHzXy5diiElbSW+eiWsKmo4MhBj4GwDNl4S6rhRjSLM4\r\nyCthsa63NTfEvuIkWUpiE59Ao7h9os150DrHm1l/Crc8q/C6Pd0Fem08G9tK\r\nbmRn65pTxuMshbyExyUnc6hI113g0g/bqsupaePeenNVUHR6nGRJ/4t+QMNP\r\nUOzRK/8HdG5LbunpwgnpWidjc+lLDELr85ZuK0DgG1rZspJn1+usdVoYxOFL\r\nFATw/H0Fu0FuCDxWDbZV/Lb4AyT5yfWEE24=\r\n=Px5K\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001454":{"name":"caniuse-lite","version":"1.0.30001454","dist":{"integrity":"sha512-4E63M5TBbgDoA9dQoFRdjL6iAmzTrz3rwYWoKDlvnvyvBxjCZ0rrUoX3THhEMie0/RYuTCeMbeTYLGAWgnLwEg==","shasum":"033f6df4452643a64173d02543902caa158dfd9a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001454.tgz","fileCount":811,"unpackedSize":1927792,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHUyzr8UxE5kH6a7sF/w4Wz0P72lChBOmSWa+xHKllGiAiAEFGgfdG+FNxFQVDUOxYheD/5+4wIU4VhN1Kzd7KcT9A=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7pZkACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqvlQ//eUJqqI6nq/dJBXbUKasqs+d9Ta41N1CURRGU1UfkDsubuxCK\r\nYs4YsH3zJTLx+QUqpEO1ArYZ5RMx7laaQpFhpOCQ4rihIiSmfOUWJC8yGXgq\r\npDVzcq0uclcfnXs9jDKSuMFfSdDj9f4PRYap2bSEZgcDewDFw/sReTPzCH4A\r\niqVSicHUUCdolRjxXT3fPgjrLaql6DtzVzb8UsoziOvBeqSkcj0z1uMwbRvL\r\nYh9wwG77GgybNW64nnk9pa/FOxKYpsBqAyoYOUJuRIfOTK4EtqXKYdbCvqtr\r\nkWSe9nZmlNCwuIdTsFqmLryA2NVaLzSwiynLj9YhSZY708Hcht3foAZ2thYq\r\n1gH7F5LpOVO9oz96bDWGf0oxhh5+sjCIee5s9UNxNhy4XEbSt9jEEcMY8c7m\r\nZnH0BNE6VaEgRBziAzMDyIE/XsR4TqXRDE6A9/5BSkofCU7g/9lo0OP6xtTZ\r\nkgtd7emoI9ZLOzhelRaonRJDCf7QWG0SSWBVH9AYAGJoqkQQaRo7BKVf6Zq9\r\nWE8qliMGn0GBAcW8rKlPbH5zTZ4/46QYoA7GupYtbST+ZH2SOxJ/hJwYYBHY\r\npm5evcBPQHXP4P0HLdpElGKBRC04le1+ENnyLF2B4MHiUI1oQtRTJAzhldtX\r\nsxjYIAPxd/mqq7HriiKioKwBDpM7rUuWAeA=\r\n=RLiR\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001455":{"name":"caniuse-lite","version":"1.0.30001455","dist":{"integrity":"sha512-h5n7WkDmyHlvHhVFDMC1OFUuWKoht7xuom/kL8b8uJzfMmB068adJgj3B0/n5PtnrK6rEqY8FE/D9m38aRdWhw==","shasum":"3a2c24bcbbb5ff73e3f347e11d71a22d023798cc","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001455.tgz","fileCount":811,"unpackedSize":1927886,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCi1t5ylHuSi7LvsWKQkwUchH0nIQjEXaLFVbcuLT/iDQIgNM5Jt2CzYU04Klv+INSNAlY3DjRplls/SFIZ5eYkFu8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7uL5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpnUg/9FS9t9JdgJUOzlCnIWqIltOkTonUDErYwx1ryBsgpYyL4oyEJ\r\nuHHWc9Tsev+W1V8rpOt4Dl/JPhHUFPx5U2nhAOs1bBRDzclAvbW1GkrS21Vl\r\ndEMQ1ZUBh8S6xi6CtJzTV2PWZvq9JWDiIbrq/JWYRJaOySsK+mr2gxRX7QbU\r\nSTFBM2tsLCYz0j6C5ZebwiY5Y5/LwXkoKElqFuZ/Ge/tgH6ZEJR6ICdIl7Ur\r\nuf/sf/jmzW7XIua7RdwnNUWIvScwxzenj0S5Q+TslvSJaOnXnQJnVwgdEx2C\r\nXWtWY2RL92Xnx0Y1fYZpJv1xnnSKusgGmlJBW0wjEIgP+Ssn/1tqzhwXqKYF\r\n0RNFTV3WRoz9oFt6I9HjX2Ek69u93z7iZeSfRT8IrdwiSY1vqTzgshPMQMfl\r\nd+PVKc4XLYmt/x1FN1o/YvLaEgV83UsVKL4P2y8m7zfV7CmUljWs3oLXDv98\r\np5ktjHPE9STgO/ptbMkP5/LO767McTp7tDc1iuhuUDu9eZRxP2MEUB2zxlu6\r\n/peeY3vh2tVTk60B1giZ2yKByeBCmWAOjtH8S01P/qmeJ5W2X2uerrA+DH0N\r\nu2efDtXacHgPRK7l4OIsoqKzVpblAQqU9M0bX+C2GPNbjonEw9YhbPc4ii+K\r\nHUOjFJVobkSrNpohxNca8zaxvXUWHYVhlsM=\r\n=Tlf7\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001456":{"name":"caniuse-lite","version":"1.0.30001456","dist":{"integrity":"sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA==","shasum":"734ec1dbfa4f3abe6e435b78ecf40d68e8c32ce4","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001456.tgz","fileCount":811,"unpackedSize":1929054,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICfsfpnmL1cMrfWerJ0mfkRg3gcCmV5M4zymRvAHKl2tAiBUxu4RFb8XkoLwSVbUVVVVCV/9tjfgv1VoFTOpgr+BMA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7xUAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpCERAAjdTuQRfk/0OO7cJbK6lskA8J99AtyivphNhPMR3MJgX++7Gn\r\noXDSeliJi0hRk9PS/0HXaGTtIk+9StOz8sNLgZc9vZkNTA1svaVHoSyU+CjE\r\nPfHfRSjlR77XYRwfJwnSDYi0VfOxeSP5SG/zQNaLo4M8ukq8ulaUh+eobUBz\r\nkVJOjN/AikhbPpeofq6FBZulWGhE9yDnfTsfUFIz/JqTcu33cVK6GBHcnCih\r\n2mWwZZ9n2ew8XD/4T+An0VF0AM+v8274U8rdoY9R/vHuA4p5M9VXp2CVZufv\r\nvKQODGunbwbS1ntjtzMbta8ou08HAYWFtsLakk+TfrnAyW2JpGCWz+gUTY9c\r\nVEVdbLHhXi+z5gVERvG+b+TOPZ7Qcglx6IUomAYDVWWxfB6H0iqf9EtXvjuV\r\n1tABZfqQoj8mSMh/L6VynksF+j6QqUB3JBtBk9naXvO4f6rgTfnOXUSAClAp\r\nU9FPVsk/f+r9ZZG9kpOBbRsezMyAMx1hP1QlV2qPdipwuHG1K9nZnOdOWaaZ\r\nt9MZBA/cu6UGyXkw6hnY7aLKEDdrO96KSCu5QqkcAdacqH/kDJPUDbEFDINt\r\npk42LRYZhIm1hT6McANXCcEJdkwN4tkFBqOX+cAoHe0nvfNcQTaGs/zSd7S8\r\n2wwO7y9QuoXf+7jfjagGLZPdVL41fZXtFhI=\r\n=3vTS\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001457":{"name":"caniuse-lite","version":"1.0.30001457","dist":{"integrity":"sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==","shasum":"6af34bb5d720074e2099432aa522c21555a18301","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001457.tgz","fileCount":811,"unpackedSize":1929054,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGCK/Go9Kt3TcP0cO/t9cpdAmgad2KzoV5vqIr+RF2bEAiA95jPf7zqPX8rVegpDKW7lUUjFHWI8zhXw1KS0NFlrFQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj8vtfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpLKg//XjT2dA9Nl3ijhocEbNmhn0fD+FtiPJXyXYVNS5qv/uQ40pJ9\r\nNHLEJacU4fkMNsde/DpCd2nw50riT2/7tqAG2fUeTNLZOWJjRHe9X5KxQDT/\r\nVAlQhM6M8db8Qq8/UPBt8nTTaWDng5BJhMWtpsb7FNt6jPy4+cmWCOzCS9/5\r\nIh2XMjfN+V72lNNDFb4/caXDqbMTYa6pd28JsUFx30ja5Eqys/NdH9Px4sw3\r\nPIhfcYRlihlAahs1MpwUFnH0x9+bFrzsL7RvqqavLefVo3JecGhNqTcqveS0\r\n7ur/d2EVBRI5gifvgwLanv10M27Tsxs7yovnx//vub130PrdC+MI+JyoKFaB\r\nSTSE4eANvOMWL0Lk1t9Wz1N8AaYGwRpsXPqJwmJ5fOTwilwomaJUfhT4aG28\r\nbYW5xEpNSm2BNSBrluuzy640WTNX62bC6hfKRJ2HfQ70Kjr7n1GgkaTkwofE\r\nLI7QMFTDXyEelKoqVS9rq3CqmEkXmUmpciciGqyF7q4vE5SC9karZgUuQTN8\r\n53iJZxJJ47xE13BiGiIC3tcFKQy34tkCUOiGvFmijJHWlHe7yKeFagXv11bn\r\nLyZkr7p1P2HCoB8sJ7brK4DkXGNKbSwxZUBwQdD9BABvRSDibPKPsNdi5X4e\r\noZ8G43BCZlZYjDDjY5jr6AgZcb8ItxbdInQ=\r\n=IMUX\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001458":{"name":"caniuse-lite","version":"1.0.30001458","dist":{"integrity":"sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==","shasum":"871e35866b4654a7d25eccca86864f411825540c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001458.tgz","fileCount":812,"unpackedSize":1930592,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLrnXO1ZVENw3AM5rCLQfhkM+B5hOIjm17VEsfjHxxAwIhAOf9nlveO6gMzcRVbckRauyUCCphKJSEtL2BHboSENcr"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj+mXUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrZCA/+Pw6vzGOTrdgKvX/QrVxovlmQRa2BrToPlB568kWIhpJjs3z8\r\nmZ7zqQmBJeyuT18rf0ulZQdO0RI1x5sNLX1/o4yiqB9FnFGdNP87PSp9JZx4\r\nUUmjaTkDvzwx9DxDzDgtF3Puje+xrAdUAQBRJpYJkjtm9GWg3AhDwV0pnM2T\r\nyjFhMqLYZMXfYIiLNh+U3KPNu8XT9XH1HSKRYeCGHyhCzQjpN0PtrB6n2Rx3\r\nrMOAoaheW0N5OfTjsdB34aDXgoHN84the+z4JDmO3rB8REOMY6LLGKZMb3/u\r\nPLvmcAHTHUmAcgF03PiHu7ltf/2/jq251/MNR45Fv4CLaCfAIV0cv8BLnniS\r\nFksAXENJtq65sRvd/bnHOytNqfRV8C90Ij6R/Pyu+FNnSJhDDAPrZsygmD2h\r\nZ+JD3str34TE5+1F3FFIvF1oz62M8x5gzg1qNIx1cnY7SD+qPszTFXXCVpn7\r\n4gMYriOmm/ytDkgNDzfbNQsgf25uIq3mToJVI3tLMGVSTgdk4MSzEwkkc1Xt\r\nvToq8JaRktya5jk+mnt6DBeF3ARwz3kqLD4vyUzyTelp4o8+VGpjPAhV4FdR\r\nP/XRhbx82MYORpL2YT2XqRP7Cz9GUP5467RiPveWRao3xJ8LpShUv6Dv1qGs\r\nj2aGGxH5iYLb6cEg2dCCo8s3kCKaURjqJQo=\r\n=k+b6\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001459":{"name":"caniuse-lite","version":"1.0.30001459","dist":{"integrity":"sha512-WmuS7UmOyuMxDquiA3BUKrKPBcpaIHrFnlEzlIYKecjmHMABYsqp6eeZLjcLCW5aFb/dRJNYCiuGNEssQgLfaA==","shasum":"a659c80b7be37861a699290a33fa05f628fcbd61","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001459.tgz","fileCount":812,"unpackedSize":1933082,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsSZEIsN/P5itcXO11GGG/oHT6WbztQ0CdI1VWnpzEPQIgEoHsepNvTySM3Z79AGiC1lzRmqd53FCbTsrR0nX+5tA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkAYnrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpvGw/9Ha6mKfYBzF/iRN3JRcW3vZ4pJGgsp1UOEbNn9snNEX0doSAF\r\n2VzUGjGZNfBmyenI4IJLkVGJoMY/iExrPh7XmmovRd2COqR8xQzX/ziKdL6G\r\n7kFnmiouTaK+nwnNeWdb1IERCDNeec62sfbPkYhal4/R7ms87XiVost6Z3T6\r\nKXLoLuSGfH+PPdMidI7DkTA0Dk/88pOUPCjMrVzD1CSYucPUJ8KHwDu/yLLh\r\nxPtp5kU6GvL98wpZNpo546OHeo/LLe2s70q9ZaYx3rzGto/b+cG3DUEh1oOH\r\n2m1gOumHz7e5SCrUMGifk9vd57ozoleYa7P39CxtEFcMgkWle5OHODxSrbTZ\r\nZxNZ6pi/q1KV8hfvfrWSxU2in4T1XCI8XFJNNhMgabU0qzNtJ3pkMPkxWHkx\r\nsNo/xaZzjNMFcjUwuLnn6KP814TwWjwsEEbbugXB2nJpMiZ8EQRypGZMqGfc\r\nFzpVQxB5B/z7ZRC3uC7NxcTd6wDelOEGTJvrh/PV686diMeKjf+gD+aLsP5t\r\nfmTSeZ9DlAnj7dah1cfwT7QqSYD8P/GNlYL1j/G5bMxhuziTK5v8m+s3Etoa\r\nGNtE067KLtmNMC7SU/GRILoz1RCvHGh0qUgwv52lSdMXwqI/OLieHjl914yf\r\nhknbpn8goL/TFiv8jaUXDgwCTh7KHmjFEIg=\r\n=rcgK\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001460":{"name":"caniuse-lite","version":"1.0.30001460","dist":{"integrity":"sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==","shasum":"31d2e26f0a2309860ed3eff154e03890d9d851a7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001460.tgz","fileCount":812,"unpackedSize":1928565,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfKLlqmO01tMRqE7s3BEe5bOG22/wRUUYWLAglbaprcgIgX+2oO1JVxi3JoRAlyKpWee+f9sOpF162qgipq9ya8jo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkAZgAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrGfw//XG9YEPesg4D2YcbvhBrHpHrT+lYYvpSdc7UrJEn/Uavr3mgi\r\nghNiFCcRCQU/nFUg7YXxl/T84qUAj62oaLgIWp0rsBMa4JWs6AxpCXylnMTj\r\ncBjWyUklaysxduyBtVuHxWS/zFCmi1WBLeFJNAUg8KDHrZCVxnQXXemrvaLb\r\nz5ENAPeAMzH5JzGsDNZ5WGPEunYHJWC0+Yi0UI6DD5M/yPHNVO5adZNr5GZk\r\nTsPqCABQl/l40O+CLseOdilUst+6UVnRd9lqzpJCJKaBoZuMHpUvK4AMKPPg\r\nE6RsHZNdn5j/POzlqoZPuH2JLaAigi39u4neQL/PnLur/9aor9XGUMN4AghL\r\n6213ftOr4J9DMPv2/gUm9tZLSfLy4OVd7q6tJ5VN4GnHmGhQIEnKklaUdI5d\r\n9YjAwsJ/bsAjagD+/qURB1lQL49IXE6Nnz9SgZHXK7HxGu0C9NmWIFzEfYNF\r\nquekIPwNeyllFo67I41OAIWavbgfhKVhFEKSxCH/x8IWkLW/lxYjolOmddQD\r\nojrBKKRxDuwJbiJWyrRE2XHEwp0vIPjdN5dbxIq8TrWP/e5SA/DsT6K6uOYB\r\n6LJouXiOVTFkTuXHlifitk0vLbhx8hOlrcAr9UuRBKHqGZiQ6e7dJPGTuY7D\r\nfl/2s+/Ceofft8fIEWMRRpYt4ojggLwmkdI=\r\n=fSsi\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001462":{"name":"caniuse-lite","version":"1.0.30001462","dist":{"integrity":"sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw==","shasum":"b2e801e37536d453731286857c8520d3dcee15fe","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001462.tgz","fileCount":812,"unpackedSize":1928570,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdeDvhi4MOwEAbltTlOVgolPjEcWJt9zMZM1dFEJbXzgIhAP5oWPQWUhBxc6UbdYLQZKGlDjvBtnIhjoPMWCV4K8e5"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkBtACACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp6mQ/+NRIGCYj91eBwF4KhGNeobkIDTwoIn+hJvFy3PN+la0fLsJAp\r\nFyQCBSGRD74j+0P6F3oDKPhq2Ea8FrwmeZBuQe4xCRexbJ2Eo3Egx64+UCeX\r\n2i7+7S/KTL/BSWtC/+Nuiid9f0NxAn4a42VIxvVavWEiYz/9H4hZwbvRuQ4t\r\nRe+V62/lJjMB7hJ3J+QiyEEJRoNi02LZmnvJDjakAv0bw9F3UBHYYSwNBnw2\r\nu/hewZBo6jhIGBKxPRZcxFQpCbnhLaP5KEoHRo6uUO3HIy6R9yxLQF3AcfPi\r\nPav4qQQdbjYCJddLpee7Qt1yD3wrtXd3TR4tORZ5x+UBxLBckLvZOW4ELcU2\r\n6J9TmRXEkmXhVM4RKGyhWUut7ZONmDFUUUbc0HYq/dSubcXpAtQxPMfBOK6c\r\n9DrQbX6/fkwspRDA7kK2uKSUjA+3lJa13/inaSVSWOzt9Jvg0pNMr0a4Azhf\r\n7sZHhhzvok5uZGADJfGm+r5/iDeeMSZASbEXlnjzpM7EZnUaD4BdPIWtusRp\r\nsWegh5Co2uTUY2GYaXH33/B0kFUjjj9a3KK+W9tnGlbo3Xfnr+PjV8lCE280\r\nW3yPdEhWT3Ufy+QaneXG96lCn320JJdt9NREZp3mKM7+5dYPsKYQFV3anFOe\r\nDsWBTh2RIbdk9yQ4wswu5+9s6cEaGDNE5H8=\r\n=NRNK\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001464":{"name":"caniuse-lite","version":"1.0.30001464","dist":{"integrity":"sha512-oww27MtUmusatpRpCGSOneQk2/l5czXANDSFvsc7VuOQ86s3ANhZetpwXNf1zY/zdfP63Xvjz325DAdAoES13g==","shasum":"888922718df48ce5e33dcfe1a2af7d42676c5eb7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001464.tgz","fileCount":813,"unpackedSize":1930087,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjhux6LxTobnxNZSUbX9Bafpj5JID5SK1q3RaYGGW+GwIgQmCO8EHAD8cmDkqRtirFwPZgPkZDmESkCzv9YbA2MHs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkCYFWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr8XhAAmT5E6gwUiJqU0ZNrhfSw/v2n93pBD3Dmcm8F4YxQLoOcjcmq\r\nZ5K7axT6Q2ZYBZ5/bRFIyqDadIRR0+dSjdNLmgOLOvOMC6c+CtSBmwcdFrEA\r\nGGdeT5wH5u8833btaF9cBS2LpQ2nvg+AheiibrY7FMkdvqxwcK0oBy9cZ7VI\r\nXElqVVfXRsZ8lfT4PAydxP5eAarohLNdr0pRfuTkvtEjitA9R4LAlz9vzHRn\r\nVaVM13YSaJkim2nkYeT8RGFM0kzH+sJ4GoaPKrc+t4t4Yat/kBEAgBLhQxxi\r\ncmq7kwch3kM1KbKu1/DOKauncmVDx4a1qidzFvCcQQztzqfd4Zqv485mdkDH\r\nKImYHL5g4jNF8jG7/Ra+p4ifaBahWsymnjd6YP1O4c6WCVXxriwe4NdNpcGv\r\nElN6wvaCPXrYicLYy8Brybw9gP+2XaNzPXcUjFvkOvfxTsfgAKyMNMXKyeD7\r\nKDY5GPmJ9O21KgaQhQfcJnUSw9ci4/LcT75+cR0lWjtZe/K1WPZLvmxF0bki\r\n6y7dWu+wGzXVrgC7LhQzoYA3/prQC9G5eBeO13FUZj51kwOSz7TCa5eIxhAC\r\nCoZ9UuMTCPQEPXUHOY+G5o2MZ4SQkF+1373vEwIdIgU0VsZPeu8YkwrVDZmu\r\nQYKtxYnK1tHrzH76ohdo5bgvFYxR+xir0rI=\r\n=IMOw\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001465":{"name":"caniuse-lite","version":"1.0.30001465","dist":{"integrity":"sha512-HvjgL3MYAJjceTDCcjRnQGjwUz/5qec9n7JPOzUursUoOTIsYCSDOb1l7RsnZE8mjbxG78zVRCKfrBXyvChBag==","shasum":"c1b715bbb4ff6fdc20a4827e0afe9f4374fca217","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001465.tgz","fileCount":813,"unpackedSize":1930096,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDidpc0LbShPnyz578aJFzWpFpZ7GFUj0kiVHk7GLIzfQIhAIPFE8+KbHr5X4lD6BSj8Wm7PnSPz0Vk88luLjPw7pe2"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkDsb+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr/QhAAkM9AnJgP3cu5tgcBuUNB7bukKmjzQSa7GkroKC5Y/FYWH47N\r\nHNqQlknsfgEJEtizzGp9bQmHCZ2zmQP1pTyXuP0yz3C7BXbqnPRyaIqsVUCW\r\nwXvsbzNmnIDvulodBku7iR4847Nnu79hwFFF+HmRivHnylY+Obp1HpI3MflF\r\njqxvmELa1a8WF5B85k3v3VFdHMxT8hysJhm3qbfnSNDsgmf2IgPD9LSg9car\r\n79ia8QBUon4QzcaV3uTA7jL8oQUlUsM6cBfFDuCXaBQAfLyFkuzyWxKkK7xl\r\nr9dW3vCq/Bc9nn0J39pWKXLhRPOjg3whhUiIB3+d3wRCXyo+6d6x4XyDbgEl\r\nAiiS8gMaNuaQUut1CEAXoCDfrU8PTLoUS+vXjy4uZuzVV0Bc1S41Lb5sEOK1\r\nPI4dtSWrmRDUxwxaI5rTTEo8YymdWtrt5eAMrZQ4Rq6tH2rcOFHiesgBODh8\r\neOr6vN7cX2fzaAJGAAJ4APwW7ogVSQnyxXbnULRG5OTT0l22ILcYziw+MJM0\r\niukpV2qetlNBqMsOFq6TaiTtluDFmleJuuP18RXc7XOF1g14u9p9eVNfhe7D\r\n+Fnqzv/dz9euk7zq2JAjHgQYJXMyv7BFic9K3najFTXWArK/6MSKf4WNnIas\r\nm/2ede2nK2rLsUJfhSZwytTzxzZypVtN5Rg=\r\n=Th5d\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001466":{"name":"caniuse-lite","version":"1.0.30001466","dist":{"integrity":"sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==","shasum":"c1e6197c540392e09709ecaa9e3e403428c53375","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001466.tgz","fileCount":813,"unpackedSize":1930099,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAinX/541It+bZRBmqbaD+n7VSJYleF0NhkRiS0gcg0gAiAtg64T+B/m8pFABORatu8GZJefH9dXskR/Rk83uJHi3A=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkD/xjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqQww/9EPGpSVU8hDCz/p2S/8bkHesdNyVVlhynVv6qwmBzYqjrv1oa\r\n3+O4lNt+Sfg+S4POl3Ywnlbp9YUS8x6CFQDGiK+8a+vhqd1crTAZw0ELEUjP\r\nXI7P3CSykTQqQbxrpy1hIy/m9z26158GFnJx90s7V9aU75xwAW38514y5oax\r\n0/YUP15ZYZiBLkQ5sv11ZhHbBQ4Yz7ca/voRJlM1ux5FSWSrzh7A6eWXUrBC\r\nY9VBIEZSlDSc7Krd1CbY417c08FvVTXwPuEEgtmtKj15iack96Tg/I5wiDl5\r\n86bsbbRIWtYwbdBGyLvk6WkuZUI/CcfdSUc/humm1IrYL0xthjtinpEiRBeX\r\ndJ6NmSzv8xvwZOje6gRBhWmfnXf4dhmlrHdR09xUsIuNSmhI0Y4eQk03Nn/z\r\nJtqZR13N++/kF3nGU7jwdmPFA56r0qx2AO/kZDk33/iyqJKL9L/eWJm8XBF0\r\ngovi8Z+WV38KLN0t8T+IuTxeD3Zj5UULAJ62P1HstEtEWDCN6SQiLlWmCcwd\r\nrixybYVeZl1UzsHkZjAEE1xAMHZ/M/u7rmGtFTY+7NgnFSgpN2qL3VZRL2hB\r\nilzA3bjoUpA0Z9CxnTeq7OjjJAYopsT9TovhbX1aAHt2dj/TKF3cgWHLG7ZD\r\n8VE7D7kp5ibx8yaTydZPdkkgX5/Y10rLV0M=\r\n=NuOt\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001467":{"name":"caniuse-lite","version":"1.0.30001467","dist":{"integrity":"sha512-cEdN/5e+RPikvl9AHm4uuLXxeCNq8rFsQ+lPHTfe/OtypP3WwnVVbjn+6uBV7PaFL6xUFzTh+sSCOz1rKhcO+Q==","shasum":"1afc9c16ed61f50dd87139da87ca43a3e0051c77","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001467.tgz","fileCount":813,"unpackedSize":1935294,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZlKzwvZzk19HatgA9RXDf7j3q7+rrUfV/LG3ECJ9d6gIhAIW86XcIcvIOtMfkLzSe4eGJt00RQTQYprvevqnRLuS3"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkE/73ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp8cQ//TaLrqlPbOflZW1M24EaPgx+Xyo1B0NYZODw6Ds3RcNTlsqMB\r\nbgZo0qh+aOb/pLO91Ed/tgBOa31F6UVJdRleNmY4xC9n6GTDNhr3SKH6oezu\r\nCLRy79dAuYGoo2ygKorSg5coDOiZ/hwyOHZfjRRs9hPC8SFyr3z19cstKj/T\r\nZ9aY9LCUtwBn2VRrABbIdVg/CDjLLTZqu14eneeGOXm+WTLpV/cQ5FcLpPQU\r\nug6IEKzpbiQNFakZOfvMjAaXcQlQANR5femR6Ba2osjXhbAQhJ7mB696Rhft\r\nSB8Fu2MemQE+Mc2iR0RK/vtjsqaHKp9pBKGMMg6S/wAfyuXQill/T4M3lbAq\r\njjwHfwEYmNytQVl/LWaoVc2feWV5I853VjZ0+d5899CpnAESxlhmGtnUBVR2\r\nHISj1iFewrkN3+RPxG+4hCKrN6RbW8c/8fMqG2TD07NB3kC8UM6U6jmwuNT7\r\nptsG+mQli7187j4W4EbxxzQXZOGHdW2C6JEd15FZiu3i7Ks92W2Y+xf06QD7\r\nqr1eSa6k5s3/bse6i7vPlp2CON0k+dSe1l6mzLd/awQnY11cb8jIRdEML9nE\r\n+W4kdDXXdR9hkpCj9xLD5H0rLwGtDaP6fKrdaSTiQLkzIBgOno+Z3occFxpj\r\nbAUbtJPLEEitu6QGxyQbmY7VK//nJulPgok=\r\n=i6bI\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001468":{"name":"caniuse-lite","version":"1.0.30001468","dist":{"integrity":"sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==","shasum":"0101837c6a4e38e6331104c33dcfb3bdf367a4b7","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001468.tgz","fileCount":813,"unpackedSize":1935312,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB8ml+iEi2BK2v8Fl7ObFI8y5rio/A+AnWn4DdgFRH2lAiEA9QyVXb10Mt3blOfus4et62xnzC8j2ozJCrzsGdBmZbQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkFpPjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoJhg//d5jz+AyY2XGTvKQ4Tnxr6LFFmTD02g78jGscMVUyP4ZNacrC\r\ns6bIXx1QifFI5Axc6CvuepKSPM+8W84BebZuSKSA6zVuU5lP9n59MNA4tBPd\r\nMP+7A/RAU5un41Xp2aUjdipc7hZE3dwqouyjqUTPmbv+96RgR+I7yLZEv2KL\r\nj1j9Pip9URl3koKZZoEa8zAf4gSCURI/nlekkFE+/4bnTw/ZdzqpMog8bfHi\r\neqfF0QHwbVB34v0B3V6nPnG7B3F4L8JkfUPSQ8CZXoBXC1AeSqLkG8CLX1XD\r\n9AP0rMbUBzZMKP4zusCmctU5hf1HTDtbQcQLOAjWLfiXfC6ofOWb9utOUcDJ\r\nsaJtPxh+y4l+p2uiv7qDOG1q1DobTaKYsZlRavVvKPG0kK793UCdqel5xHrH\r\n7xwaeXiUBYXAGh7b6D6Lq6O3ZddVSMAgmiopxfOsjPB1Ei90yraK13yqhfCo\r\ngde7T+KYgIn4rk+GnVwmZ6ekewKTXz6b3YkEWHnhKP8hGXZ5zr/9jq7+hW2F\r\neRs5P9L6WbiT1GuZshF+G2R4K3AdJGAgIbFEsNgMjVoLgkiidtXiusZU0ME4\r\nog89Z/ZAB2jXDC6q8b+59c5TVlMV8e9IR5yEygmyXpOLaJU5zAD3JWJ0SXDC\r\nzSlZJcMZp/djne4Vdm2ca0E4SElDsiTK/+0=\r\n=XzEC\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001469":{"name":"caniuse-lite","version":"1.0.30001469","dist":{"integrity":"sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==","shasum":"3dd505430c8522fdc9f94b4a19518e330f5c945a","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001469.tgz","fileCount":813,"unpackedSize":1935303,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCepuRkr7L6DeV7Td1RhBEq6qYNrqh/0fsReuLgFRJkwgIgFeVLRY9OTGbNmIKh6fv95nb/Pzr/uMKF4GWVkIGZYXQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGVMAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpBqg/+JUadd94fIeWboL62hxaokyaoBhYl1rkTb1ZyJbaN5JiaryFK\r\nZvMMAaRhqBCHI9wgVl5JP6iCDwL5NBY7J26CgHM/4pvnZkZl4kt3SL99UOOS\r\nrL60AVrkQArPu92hhwED08/IRCidJYuhLLwWYOF3GQqB23jOxW+TiUj8O9TP\r\nD4gWaSCxC85cjfrNV4zVFrZugMZ4qbr07Dz70XJPd0Fwxy+5w9GvzGMf7q/7\r\nqVCk2+ATOrKSNdE13YfigGFx1ZYY9sN34ciCbZdT/8Q5E2+er4OKVawa/8Ez\r\ny4V0dGHVsr5aly+JURDSoe7qXLXNL7aLwY+Ol09BLGqt59/ndSh9Ogb6SFeX\r\n0FL6PBQMQqtoYOxOv5TSeCfPyqPuBZa7E3BgG/uCbvqwXhbPoBs5UadjkjEM\r\nCsqG+6MbINndoDpBQzA/0LPi/bV/3bFrxNhwdeZEIyIg9f4fUa9XY+hyEHy1\r\npKh13kwzeLd8I++z5G3RcvrBtJvXXDZjFMTOswsTdRij/Vb1Xa877KX+lFhq\r\niszwA4iWmBVKVruKjZ2cDeWHqDEgTeclry1XAFLn+sPbIsOngzdVWna57EE8\r\nm5CDtBmls9aIRi8z/SVaAx1Uppges+i/AKL8c4bcOvnknejbgxPFZqBOcrda\r\nFVr8mo/Y6/NSQTj31cNs5pwEmzXeiREe/gY=\r\n=5nz4\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001470":{"name":"caniuse-lite","version":"1.0.30001470","dist":{"integrity":"sha512-065uNwY6QtHCBOExzbV6m236DDhYCCtPmQUCoQtwkVqzud8v5QPidoMr6CoMkC2nfp6nksjttqWQRRh75LqUmA==","shasum":"09c8e87c711f75ff5d39804db2613dd593feeb10","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001470.tgz","fileCount":813,"unpackedSize":1935315,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGjDimgf4Vkqw7YM2F7VAG15b9aegcWbY37tXlQwPf3SAiBlzA2NXNkD/Lu0AJibNz83CKtI4zR4qWXVfS6HKBR8sQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkH+qLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo6zw//VoJf+w8K6pMl9+eYS+om9TMgbzixRX56R4FbR8kyCHx5Y523\r\nX+khb0wsJq3yBfiWgK12kOpLZMHgSCEztHi8TRIoM6AOZaGi4bp5G8C6Zvaq\r\nfBDyOTP6q3voEUKJb1H3PEO69SQw8PWv7vSyewjmDqOTJpA6WXuCKUPO+TEd\r\noWn0lk/xC9hpoCYv1mkYXl2GUJU0BYjKxyslH1JRk2nAVQvCUH0FE0ubdszw\r\n89ybZWZXkS2OlExu8dU4P0DrxAFWln7CUtVo6x2cmfaC/tm0BIeQh+eaV4Fw\r\nortr/nmngaQZ14spOGSbRvJYiEtQEvX7y+5mKWZ/EmewbxvE4Jl+CpoJ2x/l\r\nC5pwB5N/FtSxssRkQhECgyiXLRQKXQvFPY37lv+7qbUMw1JPwrtejA6RcYtJ\r\nzg0Mqj7DkVsFbamcugOwaqMgTds58Sov8m7hXMF3Em8bj0xCgoM4tJDM+aCR\r\nLXVYwoAu1zRkRdbVREH/O8TRE/yZ5ZmmvD37mCFDHxJTWdbkdpc+jSsOs+Ge\r\n2liRK7m6idWNv65iJYaqaV/y3cTA0qvyHSZ50diVcPS/h8laqAIs8SGMWhVw\r\no36ioFp6/0cuE3qxrYuFgLekvQ72FtSwEv6ExadjTYquAtV5b8J6rn8EZknp\r\nYd4kRMdrkRR5JAbd6xFdReCuQLxb1iJyOVQ=\r\n=Nxsg\r\n-----END PGP SIGNATURE-----\r\n"},"funding":[{"type":"opencollective","url":"https://opencollective.com/browserslist"},{"type":"tidelift","url":"https://tidelift.com/funding/github/npm/caniuse-lite"}]},"1.0.30001472":{"name":"caniuse-lite","version":"1.0.30001472","dist":{"integrity":"sha512-xWC/0+hHHQgj3/vrKYY0AAzeIUgr7L9wlELIcAvZdDUHlhL/kNxMdnQLOSOQfP8R51ZzPhmHdyMkI0MMpmxCfg==","shasum":"3f484885f2a2986c019dc416e65d9d62798cdd64","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001472.tgz","fileCount":813,"unpackedSize":1938791,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBrAfmbzeo07SNISJ5NUrEWj3rQt2XX8qfAPx8Td6WysAiAaKNhLax+8iH8T2UkZ9DUiVJ3IHWTWRGJZXDc6vd4b2w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIn9/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo3lxAAgVhOFZZX3ckOEj6RzYZcDgfMgeZsyhv53Gv9mOBQGqEqC76R\r\nsv1hJQJbtaejG54p5X270YkR7RlPnxsfboc7EoaMWOTIIqHvmAyX/OU4kc+/\r\n7095tgqCgzlaF5obSRl6KS+zLP82/ntKuYRYe0P+49RbiYixb+lIfjmE2Tmx\r\nZIyUQkpi+PI0mt3faAXDfE1vCyu7Fibs79K5w9nmgI8fsnGF4TkIm2B7GG4d\r\nz5YC3/W2Q/3TrwdSVHZiF+ghBuTubu9xXzeXYjBIToNgNjYvG9+A3LfesE06\r\nayqej51pooYhiZuLFExMzw1L9Nte+UCjsw3nPAeVSBjLLbzjXVYaMcjnNK9k\r\nZPT6+ADbh1xZpczrFoVnCboWxkLfUzl9z/GgNtQUD264luYsOnhTmZWzlRxS\r\nSODSn6+YWb5dNBsq17j0WpxMk4mM6gzLeSVrJVezlurRfkTYn2wQ91mmEnjT\r\n7UqmcA8ub+BulJYM1LIFKTvYBIgkVqSzm29UNn992YsLtYHv1VshIsNFtNgx\r\n+Hzgmwanxr+JZ23lnZ0drdLqu9qycmEWfZqJQ4IT8Gfhv+SnXAT6OUJ4XjQt\r\nbL4RI905nISh8/4QpPIy5wf31jYvqoFpoBgrlMXSR0Iz083K3l9KkLfma+Hy\r\nvwO3Frz7euYW0Tc/pOfmnPoUbL4C+y9YF6A=\r\n=1Qw4\r\n-----END PGP SIGNATURE-----\r\n"},"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"}]},"1.0.30001473":{"name":"caniuse-lite","version":"1.0.30001473","dist":{"integrity":"sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==","shasum":"3859898b3cab65fc8905bb923df36ad35058153c","tarball":"http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001473.tgz","fileCount":813,"unpackedSize":1938805,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDA96k2NxLblWKvjPtSu8/jH3HEUgnYbV6AXVpA65dMxQIgLWlvFhAnkPArNdmgc0YEHN3oa95Z7aoEF0wKYnX30BY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkJTCSACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmolzQ//Rk4dCBjbIMaHqohfoo188C8JLY9+IbWiJJi/z5CXdHYch151\r\nF+U+eB2Qt6eTw24+v26xhytLA6k1q2hog3MmWdx3TVZAk8+KYVhuOhwgBqCL\r\nI4IzLj+UacdN5hidQkAYrMaBE4dJP4ilF+jDYloimiZsXvGgUPbkVfdXdL4n\r\nEWNsGSIoBMG95rI386ooT4gmLdyOIZ9U28ADvHqth2QLJRijfE9x/Rgppat1\r\nv8/9J+cpKuSn+6Icnw8HO4C2IXCcJ218oSmo4E5zyfcxKznKcx5Ka4eVtzvb\r\nr/6CSOj1DsC+3QtQgh61hRDbJzEC974hzcuPKcoatumYp7V727RSuVZlwNnZ\r\nLG0LULXSCamVho8f/njyyovG+ZMYXJknbvXH5lZm91SxXxWIjnEm+6jbXXhd\r\nLuGkSw9/ucEQtJ2w6WpH1vIzJSLaLo2o1ipF+ZpAlsIfKT37BHK7JY6o25Nd\r\nvLp/MaE1Hn3MD6/U0pOm4LrDoPmTIZtonnRCIROVK5jg/SHYYyCfn2CiKXYD\r\nZeVrLWNT4c19qGIRIBkplAPHht1Fw56Jb8vZ/9V6cFrIOWKK5P/8SXEs2kW6\r\nxvl50i3ZHgwW6O+GVZdXUNPB1QVoTaFoWNiAprTvhDII5ci1g1UAKHL+w+Xh\r\noH72n9zQcp7ZHE7twH+iUZE0TyxVfUM/G38=\r\n=+MLK\r\n-----END PGP SIGNATURE-----\r\n"},"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"}]}},"modified":"2023-03-30T06:47:46.169Z"} +{ + "name": "caniuse-lite", + "dist-tags": { + "latest": "1.0.30001473" + }, + "versions": { + "1.0.30001473": { + "name": "caniuse-lite", + "version": "1.0.30001473", + "dist": { + "integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", + "shasum": "3859898b3cab65fc8905bb923df36ad35058153c", + "tarball": "http://localhost:4260/caniuse-lite/caniuse-lite-1.0.30001473.tgz", + "fileCount": 813, + "unpackedSize": 1938805 + }, + "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" + } + ] + } + }, + "modified": "2023-03-30T06:47:46.169Z" +} diff --git a/tests/registry/npm/chai/registry.json b/tests/registry/npm/chai/registry.json index ea38b0eacb..ddf47de877 100644 --- a/tests/registry/npm/chai/registry.json +++ b/tests/registry/npm/chai/registry.json @@ -1 +1,88 @@ -{"_id":"chai","_rev":"521-75f303c8b52cd90c8d4a7f63f8a8d5ff","name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","dist-tags":{"latest":"4.3.6","canary":"4.0.0-canary.2"},"versions":{"0.0.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"Assertion framework for node.js and the browser.","version":"0.0.1","repository":{"type":"git","url":"git@github.com:logicalparadox/sherlock.git"},"main":"index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.0.1","_engineSupported":true,"_npmVersion":"1.1.0-alpha-6","_nodeVersion":"v0.6.5","_defaultsLoaded":true,"dist":{"shasum":"a858cf9ecc09afb1651022371dbe5ae0bdde77db","tarball":"http://localhost:4260/chai/chai-0.0.1.tgz","integrity":"sha512-/PpEI23OzrHfP9iz8rr2yoRdd/htzHr5c5s0DFtkZRkEOTo5H7whwa0q9+leSscZi2amrakrP8ZwClCv+JfZmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICBQqnR2FjWXC6sRjYpyASFwbxOjLbCZMd23fKKhOa6bAiEApfMLo5NeNZt20lwh2qdZCtgAuWzmGmZmfVnw5+2Sm8Y="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.0.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"Assertion framework for node.js and the browser.","version":"0.0.2","repository":{"type":"git","url":"git@github.com:logicalparadox/sherlock.git"},"main":"index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.0.2","_engineSupported":true,"_npmVersion":"1.1.0-alpha-6","_nodeVersion":"v0.6.5","_defaultsLoaded":true,"dist":{"shasum":"368ce03612b088606011f25a479ed8b4e0b1f2c8","tarball":"http://localhost:4260/chai/chai-0.0.2.tgz","integrity":"sha512-WTuc/QolyBjU1TZYgZjYfDAvBVX1Y16wKSkHVXk7mWAcuzfWobL9dwyS5ZId7CYCEuGzRNPVACQ35+1CW82Vbw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA+DFS1qRyvfx114k1GzY7I3recISKPH7m+D+PRsF5F5AiEAwh2oZucJagAgwKn+cCO8Ru9fGj18Xczo6D3P5dODu4g="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion framework for node.js and the browser.","keywords":["test","assertion","assert","testing"],"version":"0.1.0","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.0","_engineSupported":true,"_npmVersion":"1.1.0-alpha-6","_nodeVersion":"v0.6.5","_defaultsLoaded":true,"dist":{"shasum":"1216fa4b0585fb56d0b7a1e6c02f1682f709b306","tarball":"http://localhost:4260/chai/chai-0.1.0.tgz","integrity":"sha512-h4ASoCHwe77pHhotcSHrlsVKIpYaoXm0Hjt9XJdgsBgGertvqAHmCDc8TtuZtK8pVPLFvsG70twTxSxK7xMADQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFWV1IkFOzorVpcmzWerL3DTQcAH0uPK9XoG32XONXwdAiA7BV6rvqGlZoPWi28VOajH2sYM0r/k6fowoHS9keKIYQ=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.1","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.5"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.1","_engineSupported":true,"_npmVersion":"1.1.0-alpha-6","_nodeVersion":"v0.6.5","_defaultsLoaded":true,"dist":{"shasum":"951366f524d0b4be9d59d9fde5e152dd5a42ee39","tarball":"http://localhost:4260/chai/chai-0.1.1.tgz","integrity":"sha512-BqHXq0l/uyPFpui4KKgtxwjU7Q1Gtd9znEAi4XnMqpM3BJSnUTX9Na0i4m3UFPvhwShJHovX5+U6WRO9Mkg0QQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5NUrNkYuZhNZGqjOIncRFYV5Ylv/kU4utypxIBQ6nOgIgbaesxe1HnLd6Vjt/ouYXJUjhzxJMwHvDs0QLlHQnd8E="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.2","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.5"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.2","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"d7998a8c05bd1f34d8c663ca38a8cd3287d5e3c3","tarball":"http://localhost:4260/chai/chai-0.1.2.tgz","integrity":"sha512-nmRvLrL9Pn6ZRyQW2JwEyKbJ9SghkpK4YosEWe+tMCJY03qCpV0+PH28VElm3EYe+aMa8opNtDCPXyCJLoqIWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGm16Sf2yR7VFXi+v+HOZnMLyBbbx/38+KPeuyP5jaSWAiABtz8F/Q6y72NiYfBRt/ojwc58ksBwz6wGggCcRwoFGQ=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.3","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.5"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.3","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"1cda1032af49de75aac92bd9e739c4877111ee10","tarball":"http://localhost:4260/chai/chai-0.1.3.tgz","integrity":"sha512-EwwXEzRmpqdahmTteSY5JRwjER9QaqFPC4WjXOJKcIm+FikZ1SUajyQV+HfH0hlZQmEm9dcDip494ssMZVYKBA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIECajJtP7UyPwBG88rTcaCJb9wuCXOe7110AjxrTpmiCAiEAzMsptbF9mvbSoiqMxoXDh8WfNu0+tUhNyeE74W4TiMc="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.4":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.4","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.5"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.4","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"e19b494017f139bfdacd1c51c92a5acff2fd844d","tarball":"http://localhost:4260/chai/chai-0.1.4.tgz","integrity":"sha512-lxCbLppU1038JGZt9iu0YJwcoRyx/VfpjyMcnOhNVAluI7xccOCSbzddRdx4Hhh3sh3uR7szqgV8esmVeYBBHg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCnwEAGwSLtG9fFrkhcOBuV7YziE7Y8m3trXnR+i7OCAQIgRZfuSl9pOIpXfih0PrcTKBonr03w1TxVYbo/gr/qsvg="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.5":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.5","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.5"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.5","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"6906981636e139cf4229a03e558b2a8956276245","tarball":"http://localhost:4260/chai/chai-0.1.5.tgz","integrity":"sha512-p1FCxsT84/CCx9SXGn3AkpBLpTAAUCBfPx1sQDhgjAkTqyogx1lQnoSheFQ/+CcuKFHru52bJWgpiJPsft4TpA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4LiczjEaisIwzKgsrd1maaTLsPS19sqkApOt0LvsNiAIhAOZai3SpVDJJKc8xyxTFgc1mpMZC+AZd5WJEn2iMAXZT"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.6":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.6","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.6","_engineSupported":true,"_npmVersion":"1.1.0-beta-4","_nodeVersion":"v0.6.6","_defaultsLoaded":true,"dist":{"shasum":"bd6c9ad77c602d751f81d9febfc796aeb6b822b3","tarball":"http://localhost:4260/chai/chai-0.1.6.tgz","integrity":"sha512-TT9T71QCr6rB/Q1lRw/LzYamAteRhELvb8Ya42Z2ztj6ygiMgOiV0KPPfwmi3KU1iqF21DhZQb5YqyrWAFyjSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIQDcaUzgobYPuy9AdwJUoBOxaaIw2mBSpQhTgHoaX7r+DwIfZQR/Y17JctsERRnjpOmY0sXBn+eOjEkb7a8fvO5/pw=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.1.7":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.1.7","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.1.7","_engineSupported":true,"_npmVersion":"1.1.0-beta-10","_nodeVersion":"v0.6.8","_defaultsLoaded":true,"dist":{"shasum":"d7b79fefef46d8b32f5a3d179e84901e48be5960","tarball":"http://localhost:4260/chai/chai-0.1.7.tgz","integrity":"sha512-V/s0pXKKktPDmp0UCSKNosTnNlL3aNxwU6jG9YLU9TtJ6otyQIvJnhbfWYfwJxC8mWpZpnVd+gf0wezM5AXxTg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBOsK42FZYLKwqhgkKPz33SiP4/mLdsnOJVomQ79B4wwIhAJ+kMWyGRKJ8xxY5iELR6IZDFtiziZ2EmI9t70/HrXvk"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.2.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.2.0","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.2.0","_engineSupported":true,"_npmVersion":"1.1.0-beta-10","_nodeVersion":"v0.6.8","_defaultsLoaded":true,"dist":{"shasum":"41840eab17eee298bd6f3a9c0a5249e2dac71e71","tarball":"http://localhost:4260/chai/chai-0.2.0.tgz","integrity":"sha512-OLmVqdBriwQSbwixdea+bp8mIaWWA3dI7xkzGsI1Cnnc7aJmXXu1NVaN9q552UiDfe8K/O1Gc+vhDLmFzdvqBg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFQBGDdKiZ02z8yOs3ojmFZ+0b1ghoTOKmA3vpzSXKEwAiEAjAbxe+fXHoplGy3CE0l19uKnwhCuj9tbpfA3UxADXAo="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.2.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.2.1","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.2.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.9","_defaultsLoaded":true,"dist":{"shasum":"623d768ca2b9d2c4236dac8d374e3244a031ffef","tarball":"http://localhost:4260/chai/chai-0.2.1.tgz","integrity":"sha512-XePzOYHU+9TQOmg1CLeDJZMm8faTayGHQx6XpVL7XPtmH/lQrm9jbq4yuVIqj0wxxrVyN74Rxs6qxEdY7U558A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGdd0Ui9qa6iAyV/EDP91+yidDUwsLklr8diScmmOe9cAiBST18Zyw5censkyni7zDPfO02FnMS02ksuQmWKlXc7Aw=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.2.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.2.2","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.2.2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.9","_defaultsLoaded":true,"dist":{"shasum":"079271fc5bed65a1fbc9d7e469c62a9c5fb12ce9","tarball":"http://localhost:4260/chai/chai-0.2.2.tgz","integrity":"sha512-gkVC42UgHnRf+oci+QzPoeaqPC68rUANtkVSK9qL+JDufNJgTm35hQcsEAtW1NwGwVfsd95hPiM1oJHSlmCUcg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC11VnVk4Ta286kkz2eNf3bT5/yPpthYvD5Z0B4yhLL0QIhAK3/bE6Tz8hvy8gG8+9v72BAQGFRwAJaV6f5URrDNLnp"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.2.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.2.3","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.2.3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.9","_defaultsLoaded":true,"dist":{"shasum":"45bae892638b7c4c6089363cee499facb61f101b","tarball":"http://localhost:4260/chai/chai-0.2.3.tgz","integrity":"sha512-NzqQbn8aW9oBW4Zm/v1OfFKfW4iIRLzQPJHNkXQKj2ZpUJwa5RVlLzMwAU5eEoO+eep//dH1JV9dAHQQmFqzuw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDjQ1bnfY1dF8DDLKO7SWhOLCALdSF5sHCWcrigWWJTkAIhAK6kiHyL6LLuLBDCKTl4xwlQ2yaU42ndAK1C59FqHuUp"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.2.4":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.2.4","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.2.4","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.9","_defaultsLoaded":true,"dist":{"shasum":"487b27c075b7403d76981d54b3a7ab1c429d2fd1","tarball":"http://localhost:4260/chai/chai-0.2.4.tgz","integrity":"sha512-ero3/iybhdg9SAyCZFnzdHjpKfQQy75gn/cQddtcKrI/LHMNCJy+DoEh6vEFuKV4UzbqQWv5XF+ur7Dkmj6N1Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDBkpsPkif46aoOnHwKPbqYbuzhAgmgzXmMF9kqMQBFDAIgaky+BSk/IR8rFGSYJqUk9I/M6v27Ubdg2jtUQj1+gYI="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.3.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.3.0","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.3.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"dist":{"shasum":"9390e411fa5b84cd7944638d12b68aacb0335397","tarball":"http://localhost:4260/chai/chai-0.3.0.tgz","integrity":"sha512-dtlaeUEs1DbcQebQZ1lSwlA/gS+Kl72+SMpq+8SvMdmLzfFFQaJIbV97+OFdDSKqAWbPeGMHYGyc31m2wU6bsQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIWzHQUa7xZYMGURatNv40Q51cdV5unCyzmoTOhQmHQwIhAP6E5DoWPOkJlauYtroqXFv/btF9LjCcI0fZyVXLAnOE"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.3.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.3.1","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.0.6"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.3.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"dist":{"shasum":"5a4051934d2db65ce17820e08053d64a508326c4","tarball":"http://localhost:4260/chai/chai-0.3.1.tgz","integrity":"sha512-IOfKYFJBuGkp3hF5Xx4iRHspmsWzEOCLkStNGWyw+K0FOBQiIzckS/x/XFGQfiQl239Z7uPjunicJiuVcbOf4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCK01ijEricCo/NHfJuD0K9rrQiDJKkkgUnZK0IHE8IvwIgeSWwz5hazfFGL9dqLx5cpsqf3ZO9Uhx1ZlzwKAuKFfM="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.3.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.3.2","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.3.2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"dist":{"shasum":"d3c1e808cba2cac5099db822c4858c97e7d0edab","tarball":"http://localhost:4260/chai/chai-0.3.2.tgz","integrity":"sha512-gjN3uMj7bQxFWUjXl+Qx+pRf500Hh2zZRRIcfkpzhcfnh16dhFJH541HbXqcL7TXcBr/qgytqr608sdjNUCuDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG/oeoK8NAs/yJ4PwP3JXqg7G7Vxm2UdIx8mqeFbVvt5AiEAyF9QtiHPYeNAh3W76VKvw1EkzZSbfTy7ts4L31i4yks="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.3.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.3.3","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.3.3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"dist":{"shasum":"f497ba11bdda91f829d970ae516e5274baafdaf0","tarball":"http://localhost:4260/chai/chai-0.3.3.tgz","integrity":"sha512-IHJKjsMdvEju1/zl5EGl751VKvXNa34zjU4xNWeqGPWkUgZzIak2UOoBoI0XZjAgrgNC7ff7jZyfTvoZS2Jmig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFSf+m8QoVrdC4ypgG9w3JALxmf9F5Am87ppi/ukh3YmAiAgoJ+0Yrv2QTLP0ZEVYJ3PylGLz/wjqQwosvIMZT6DPg=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.3.4":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.3.4","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.3.4","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"ec653488a753bb4e9fabd016c6034e0c7ac665ba","tarball":"http://localhost:4260/chai/chai-0.3.4.tgz","integrity":"sha512-lIduGPf6Z7suVaAmDeSHGfL+1nvvdg0jgWo4sPap2uEIf8cbJqGzeE3Dj+1ehSr3pcQgyfxtuZblFt6TcEanGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEPsruXlq0YvJA6K4HOVoyiRRl3VR4+oabvaZZSsLBqsAiBIj7nA65alPyJy9eUhEk2cAP07zzHZ5eJzpeen29I7qA=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.4.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.4.0","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.4.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"87af908246300e03ab4b20ce2746a509267b8694","tarball":"http://localhost:4260/chai/chai-0.4.0.tgz","integrity":"sha512-DJLDCwY4edc7dan8M25yqo7pnNqebDIW/FAs1shbAor1+Kq+4ZK5XnAQ6fdOGra/WS/i2GNTyI8COuCpc+Ij6g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYODZFfWRzo1ipJqhduEAr9VR51LD1fHkFJUv+t2FBEgIgVb13nPtgGFQGzrJp76wme8Jpr+AJkwIpOV4ySqRKmkI="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.4.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.4.1","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.4.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"56d26f562e3bb26cd97b0b9dae848c0bf383e86c","tarball":"http://localhost:4260/chai/chai-0.4.1.tgz","integrity":"sha512-zy8XAVNsVVvKg0KU1b44XyK6CQ8/z8va0nziLZj1W4zhCSBxTu2SmmzrA4VOnK54Uo7MPxF3zex+ryVYZ72rpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC32JTyVyojch7YGig54GXBbURr4pRCtMpdOjsWsw0DTwIgLbzNLZp9iQssmhdovDbCE1F4lgZuV1a2Y4dqOXOKihE="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.4.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.4.2","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.4.2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"d942b3c559ccf93a76e481b1bc44aaafa75cdc17","tarball":"http://localhost:4260/chai/chai-0.4.2.tgz","integrity":"sha512-7xZdytpnwVWfxJ2KbbfJQ6IGj/3qMpUjQtA+kZW8ZbJHc8gZETgTwJApqEuDXrV4udGWsvuPRcL99AqupkLABQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+8n2ufBt6l3waoig63iIY3I//hw0s+UGTmSBC9FQGAgIhAI6nBahAxncg4Y//o1VpOLb5YwbUURvEsIigqcpG6nEM"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.5.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.5.0","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.5.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.12","_defaultsLoaded":true,"dist":{"shasum":"c3693f332d853a17c980a597143d5e6fe41d91c9","tarball":"http://localhost:4260/chai/chai-0.5.0.tgz","integrity":"sha512-m/RUAurTwOhMQf9MpMpjEgqJvRYgvrcS6PEklcDpRTazuU4Ow7cfrr6xPQ2z9l0T22XnkfVKh2GG/V0DNMg+mw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuX359fhiUQRNWZPG+WyA6G1JIe89Hf8YRJNCLuzEQEgIgLPuznYQur2uoarM5vrQoR676DVKjmRvDsw91At8htfs="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.5.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.5.1","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.5.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.12","_defaultsLoaded":true,"dist":{"shasum":"6072d7188093490afe9d722162494bea76561bd6","tarball":"http://localhost:4260/chai/chai-0.5.1.tgz","integrity":"sha512-Sm9+lCLPrMUaVuql8qoy7DnjzyUurX1XRiHdkwnmS4UDKeQKUyXrjnyMCsnJtZH10yoT40C+AGJfvK3wycA60Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF67l3FazGYjobzTDLewMmTKs35wB7CHq+GXUbtS9z3oAiEA9PUUZo0QktK/Rd07/Mo06LfLJ1pHC20H/j2Ntrh4OcE="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.5.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.5.2","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.5.2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.9","_nodeVersion":"v0.6.13","_defaultsLoaded":true,"dist":{"shasum":"2e93a86c45043face8cc947a22a05ef93f936202","tarball":"http://localhost:4260/chai/chai-0.5.2.tgz","integrity":"sha512-0/Cux6NcDwjP2Z0evtDhUwy5Fb+TM/uK/O2fZDQpVm6DV6gpBX0AlkmPJJMAcgpA5hjJ1nuEm7fsqwbBxU6Inw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBZ4nB4eUA3VOlQL/OJnaBQZZjfexpmH1kj39xeSxxaKAiADMQNX4Dwy9hrMNf0YVmNGa8ueZD/nAGQHaEeNoDzR9w=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"0.5.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing"],"version":"0.5.3","repository":{"type":"git","url":"git://github.com/logicalparadox/chai.git"},"bugs":{"url":"https://github.com/logicalparadox/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*","codex":"0.2.x"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@0.5.3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.15","_defaultsLoaded":true,"dist":{"shasum":"f191893b631e02216c12fc190a2ee56ef1bd360b","tarball":"http://localhost:4260/chai/chai-0.5.3.tgz","integrity":"sha512-rfJQEoc08fbJtcURiYtR34Q17UBOstTxUluQ9C/Xx4hVYOkajs7aRAdg/fIOz35HDk7R88rXDne0pJ5AwUksmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCVmmYzp3Kp9rZWmDm5SnBX0qsKBdBSbKMh+jDaiV+1XwIgGGpaPh+DPal7kWgwvPB/T1F+/T34VHsM1qj49pv1bZc="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.0.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.0.0","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.0.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.21","_nodeVersion":"v0.6.17","_defaultsLoaded":true,"dist":{"shasum":"81a863ae54469ab7cd009f09405d60b86d9a19b9","tarball":"http://localhost:4260/chai/chai-1.0.0.tgz","integrity":"sha512-sbyP9aEUKcnH0uAqnYgzcszgIXenz+rYzbizalqkdZRpPf1iEHMpq29hJjgTlMvEvLcwWVLTMYiefUCp8WdMDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYmedzhjZ11tuGQIDkg3HkdcfMifsh/as8aZez76gHTgIhAPl27PQ/q2oUfrfcthARLvwp/M84EH/d1d82McCaqctn"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.0.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.0.1","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.0.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.21","_nodeVersion":"v0.6.18","_defaultsLoaded":true,"dist":{"shasum":"348759800d013d84cedab77754a597e9e0c87a5d","tarball":"http://localhost:4260/chai/chai-1.0.1.tgz","integrity":"sha512-H852RSY4bO7S9Q+70aquHQLtIEXh/yXa0L4Riwi5lU0ifoJ+B7H7AFF1xga/6JvBmwLNMY1z/5h5wZHqiUt8uA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID9bcUP2yWJwQdpeCkcovhJGujgm3aRyxN2fHneuNC8lAiArGxDz7Ft7+LIq5IezZKZC3jjDSZCNq5WwYQPp61hQCg=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.0.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.0.2","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.0.2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.21","_nodeVersion":"v0.6.18","_defaultsLoaded":true,"dist":{"shasum":"70045831a1933cd770c12cf9af619babe0fbbe4b","tarball":"http://localhost:4260/chai/chai-1.0.2.tgz","integrity":"sha512-tQPAFBWfecoQbvGM0eBtW2yLwuZM/E0f7MFi3nRCIseFLvRjLdYnK9FjH3Y+FVFP412mk4o3+I2gaYGVSM2a/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGsux0rwFy5RP2BjTZWD5fkjr4sHIznUs29mxrYTNapwIhAN8c6WSwNOq6K1g5mj3BzYo0RdPYap0p2clUBisj4qti"}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.0.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.0.3","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.0.3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.21","_nodeVersion":"v0.6.18","_defaultsLoaded":true,"dist":{"shasum":"36662e56af0dd3c9044b4e4ae8a433f95e059c11","tarball":"http://localhost:4260/chai/chai-1.0.3.tgz","integrity":"sha512-EzMdTV+hPT6wxJSoiNe1xYLm2L/SYdtBaYEcAPXHzHdwGOokVAsgnTDWoqCVLS5vWKsPV92YFAcaL7RhwFK26Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIS5tfonLQ5UwEHDlylltmbIf5osYiuUtfmMLulH5X+gIgK5/W+0sHTqIuObvZv6BmiqGjDZ7DUlripyOLdtzam8E="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.0.4":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.0.4","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.0.4","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.21","_nodeVersion":"v0.6.18","_defaultsLoaded":true,"dist":{"shasum":"1364225605a3ce8204a0818b6b5db7924bf05fa2","tarball":"http://localhost:4260/chai/chai-1.0.4.tgz","integrity":"sha512-3AHY7Xs/u820130IJty+CuRGi4KjiOQEBG61ilv3ULK+LQ7D0kC/rdZ/y6aXbHUbPWUS1ZvFijMRlygG+DSt7w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICsGpAKrDt/H3yysUg4rHFSTppmDpj2N2pwUhdyIcxQ8AiEAuNjeLvOjHsqk2dzvK8wyqFz1zLvncPZIllD9Cb2iGts="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.1.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.1.0","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.1.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.8.0","_defaultsLoaded":true,"dist":{"shasum":"d5e2dc5d7dd96b6b401bc66df523dd48cdf5c325","tarball":"http://localhost:4260/chai/chai-1.1.0.tgz","integrity":"sha512-zZL3BIn75/9+LTCq324EmD5WZjGyXWGtc/k7a+GW7lyT9TC7c2Pgaxa3yeMIVkszdKVFKqk2VaV0VrjYmG1iVw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBWPdFEud7PeIieHo7t0TF+KpMRePJXYv+Lbu3D7d6zTAiAXY+UZ8UMFp+xPUj/C/AfIzH43FcFJYrlaQrBHbGlTVQ=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.1.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.1.1","repository":{"type":"git","url":"git://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_npmUser":{"name":"jakeluer","email":"jake.luer@incatern.com"},"_id":"chai@1.1.1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.8.1","_defaultsLoaded":true,"dist":{"shasum":"5f6cb181d64d6df77d8ddabb9f1b4be693946a97","tarball":"http://localhost:4260/chai/chai-1.1.1.tgz","integrity":"sha512-PKKjQAzR0sNSAbMiLEm4Kz0TDy9FKPPi7sHlZ6jTuUSQXLJhL8MVh97fTTGMeldrHt1w7OxSXuOopsSxyDeBPA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFwMusj4YZSYWxapbi6KdG7zeg+uykwsEkFTxIUlJqQlAiAXQO/nzUFt0P9OkAxTkqPCHJ2tuz+QbJjLRePEIMth/g=="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.2.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.2.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_id":"chai@1.2.0","dist":{"shasum":"7bf15ae137381b6e6db1e73b3831480e81457589","tarball":"http://localhost:4260/chai/chai-1.2.0.tgz","integrity":"sha512-A3epQNQAAzxmEWVUh6LUhrJsl6f5irEQGSVv3Ij/pI8lU8jHQBTl+e3GKWpYWHp32Pgp2EFdSisihnG12H3Tbg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAFvKa8zyEV/q2HSfEkd+byiuIp5q+7fHF61N8r6urCpAiEA+ffr9dIm5zoUexLXITJ377n7PwDz812V7uFjZjl1E1o="}]},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.3.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.3.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"mocha"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_id":"chai@1.3.0","dist":{"shasum":"6a597c6377c54e9dedc2ddb4641296fc05ff4fcc","tarball":"http://localhost:4260/chai/chai-1.3.0.tgz","integrity":"sha512-iAuEKsRk57Gav3NymoED+ecBW+kloFZni1urNTnGhU19wl//5lOVkbBT0iKNimBmFce8v3qWBz7+hYEGQgtPZA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHzhjMpLNRR+5IiBUWUQF6eeUpqgmQdIusoyMlzfxiUAIgDBmW0Qncw5hwveYoTVeLMNCVlQyoZrK9F+TNK4QPC6o="}]},"_npmVersion":"1.1.62","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.4.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.4.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"mocha"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_id":"chai@1.4.0","dist":{"shasum":"6884a97b3f9e0ebac83ecc58fc8b1617dd661444","tarball":"http://localhost:4260/chai/chai-1.4.0.tgz","integrity":"sha512-WZDMVJWgbbpH0mi19EeKIQq2p3Qei/5ZDPiqw7fTPc/FVkuKPUTpt1VQhDw4AhsBroN54g2yHsaB15GMmXoDhQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCteQSU37LjWAu62yfeJzkYhbN3JqHM8TDGk+SpGoWOIgIgZx2XTouJfS/eQiwUEA6Fy4qGYoOb0e1zuGH9yvkF9lw="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.4.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.4.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"mocha"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_id":"chai@1.4.1","dist":{"shasum":"7a0b484008d583298f54183a5774bee635e88c9d","tarball":"http://localhost:4260/chai/chai-1.4.1.tgz","integrity":"sha512-tVqs/RVig0bqS0mcR/iYT4/WHXgBje06+l2Vowhc2+zR8o47DPQgATMCEkKrA4qZDTD3PEDemWoNZYobmU+nxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCwZmQ+g3oesY7FY3oATTwX0pbyFrzlGZaCSLb0uCZcyQIgC6utsXrIvzdBBw55dl95Z3WvqpcH6iTgAeIJ122KqDI="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.4.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.4.2","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"mocha"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"folio":"0.3.x","mocha":"*"},"_id":"chai@1.4.2","dist":{"shasum":"8bf8e93e3690171cf2632e7a113514bc3b3b076a","tarball":"http://localhost:4260/chai/chai-1.4.2.tgz","integrity":"sha512-hXU7KNl1nFfSxTMmVADlfnTV/GLxIVYHwC8+dVEWkToy7i5tsjnpCJahy9NJeAU+CFc/EvjZDs7v11EcuBTsZQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGplFHVct5cQ0GY9SxRMUjrhm5FrYByNPl7VruIIgz7FAiEAjdUgmQz4kQOzs6w3TDuPgJHNkeu/MK76TnXyUoDZ9WU="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.5.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.5.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"component":"*","folio":"0.3.x","mocha":"*","mocha-cloud":"*","mocha-phantomjs":"*","connect":"2.7.x"},"_id":"chai@1.5.0","dist":{"shasum":"9afa2003cfcb732896f829568ee308a67cbeccf0","tarball":"http://localhost:4260/chai/chai-1.5.0.tgz","integrity":"sha512-MmczsQrJwRYBBBhpOvqVMPw27OOjj1Bg0NwT4NzLh5dwdfAQKoFx7NuB7DifbAHqCENncQl7QXu8fPof3am/4Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFxOybjkvwvBh5lDSmwMJSkoCACc6LmXcdeQzpPRo7hTAiEAn8XBMDawrIz1aLGAFxl9EbYts1ynk0bZsGVvKx/uCzY="}]},"_npmVersion":"1.2.0","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.6.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.6.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"component":"*","mocha":"*","mocha-cloud":"*","mocha-phantomjs":"*","connect":"2.7.x"},"_id":"chai@1.6.0","dist":{"shasum":"dbfca9d88710c436fcc78f9ddf8e795f6b5826ae","tarball":"http://localhost:4260/chai/chai-1.6.0.tgz","integrity":"sha512-N9JgkbAEM4T7y1wBE7qJgrs3QgaT7NNd5U9lBmqWXb0RvQuItBgGxVG18MNH18zS31/u9WHx2LAUlGyzvJkK2Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICNA0f+bLgx9GQWoMBNnEgahVO5+ZrkVn05tUktRuA6sAiEAr2yTfnEJDBuRGFPMEBQDawcbJayLohKR0Us9+eH/DaM="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.6.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.6.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{},"devDependencies":{"component":"*","mocha":"1.8.x","mocha-cloud":"*","mocha-phantomjs":"*","connect":"2.7.x"},"_id":"chai@1.6.1","dist":{"shasum":"ae400359111fba3eb538275b8be0e9145119b321","tarball":"http://localhost:4260/chai/chai-1.6.1.tgz","integrity":"sha512-JfkZUHyL/BSWoe66JjUGxtTwVfk5SVaA0yoN7IIwlTx0SoL5VgkWV2iLj2YyS2FbJBJ/i/T+gboLFdEuUIBJ0A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAuLJsKo3yWOumsULUUkNmzSO43BHJcW9wjvVdVWEokbAiEAw77/HveW1BhdLbEzv0nxOH6EwBqYUZouypvOshLaW08="}]},"_from":".","_npmVersion":"1.2.23","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.7.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.7.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0"},"devDependencies":{"component":"*","mocha":"1.8.2","mocha-cloud":"*","mocha-phantomjs":"2.0.2","connect":"2.7.x"},"_id":"chai@1.7.0","dist":{"shasum":"8fd9104ae4876210ebf25f4ee38f96be6ed6adea","tarball":"http://localhost:4260/chai/chai-1.7.0.tgz","integrity":"sha512-q4eAxsxbDUi+rMvyH71C30EqsoguEHOfoqrmYlutjgFUTXZnZYunHp8fCufLs3ZZDu+RUhefeh6amCxFm16mLg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGhdN3VvD2IzHap8feLNEvytTj799necG2Mh3E2bKz5+AiEArugySuQboNpek1v0zb+caOSwjvwhcj2dnDU2fYVtG6o="}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.7.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.7.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0"},"devDependencies":{"component":"*","mocha":"1.8.2","mocha-cloud":"*","mocha-phantomjs":"2.0.2","connect":"2.7.x"},"_id":"chai@1.7.1","dist":{"shasum":"dd581b599233d7de8e7f823711c8579bc74f38cf","tarball":"http://localhost:4260/chai/chai-1.7.1.tgz","integrity":"sha512-+/CkYqTqA9cd3drkIwZ+u/EHV83JvgATdtMY/ZQr3bwiNj5DM3Ecubf77urMXQdEmn3Q405HQiNDIZegjvRG9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCYP14+zV2RpKtUk0HQqdI0vij+anEX3PDH05geQBhggIhAI8K5wtYXQYwDEdKqb9EJnMjhxeHnG/sS6LXexakH21f"}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.7.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.7.2","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0"},"devDependencies":{"component":"*","coveralls":"2.0.16","mocha":"1.8.2","mocha-cloud":"*","mocha-lcov-reporter":"0.0.1","mocha-phantomjs":"2.0.2","connect":"2.7.x","jscoverage":"0.3.7"},"_id":"chai@1.7.2","dist":{"shasum":"ba07ebd4e1ac138a296cdf69077ce74b7f4a1317","tarball":"http://localhost:4260/chai/chai-1.7.2.tgz","integrity":"sha512-iTItmoMR+S+g8g0xU7db2mrr2LeLMJ6Y+YJwJEOUSaVTzm6qyTBfj5r+5x+XQhlXUfVn6WfFS4sXpEtMg6Qwaw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB8pem/0wX+KUKXrBdT/I2BhrX0+idI+qa1O7BlVjy8UAiEAzqQ235gZnaLoqg/DgEdTC+RNEpyNkXIR1nVnNSRDmBI="}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.8.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.8.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.2"},"devDependencies":{"component":"*","coveralls":"2.0.16","jscoverage":"0.3.7","karma":"canary","karma-mocha":"*","karma-sauce-launcher":"git://github.com/embarkmobile/karma-sauce-launcher.git#feature-passfail","mocha":"1.8.2","mocha-lcov-reporter":"0.0.1"},"_id":"chai@1.8.0","dist":{"shasum":"1f7accbe91e2e71a08d8208b31bbbdc6862699ac","tarball":"http://localhost:4260/chai/chai-1.8.0.tgz","integrity":"sha512-x0UjmqOXzz1tLY46Jiumdlcq6pZ+u9zWp1422oRXzVWRiahMq7irQVmyb5/42q4YX89/K1raILWZ69Lryjaucw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICPoMpe2DGTcUSk71d5V62CerTRgkZCcLi6pO5z732hwAiEA28NGdcDnr5Oa+dLpbRv8CI3r56ns4PZWhcUDUs5F1yg="}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.8.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.8.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","coveralls":"2.0.16","jscoverage":"0.3.7","karma":"canary","karma-mocha":"*","karma-sauce-launcher":"git://github.com/embarkmobile/karma-sauce-launcher.git#feature-passfail","mocha":"1.8.2","mocha-lcov-reporter":"0.0.1"},"_id":"chai@1.8.1","dist":{"shasum":"cc77866d5e7ebca2bd75144b1edc370a88785f72","tarball":"http://localhost:4260/chai/chai-1.8.1.tgz","integrity":"sha512-/pN2re53avlBUtKeC+mzMwvi70Wu+xCPtXwF4Aph1liB3OXjf/LHRMxcrNu+h4kFmhY/9pb24p30/O6ArjK2Kg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRK//pltEm+9gDJv3yDT7uF5g4N6tFdmB/x/23WMXHpwIhALjS9aJ9xfB5kz8TZJzfM9SXIY2WS9Ua4Lon7WJf3Xbc"}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.9.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.9.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.11.12","karma-mocha":"*","karma-sauce-launcher":"0.2.0","karma-phantomjs-launcher":"0.1.1","mocha":"1.8.2","istanbul":"~0.1.44"},"_id":"chai@1.9.0","dist":{"shasum":"3ebe99f3bab9241ed3fcd576f8fe96cad9ed7413","tarball":"http://localhost:4260/chai/chai-1.9.0.tgz","integrity":"sha512-a79o1CsOBi+6Sb8athh4YryOXi+2VDUrkeRrs1DJ11YPfyqDxnTOtXlTck4hb+KWDboNbDZ63htinWG87F+mrg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCdaTwrSzTasj9SjeqiCDtRjlaimc3T6V7P8JbLjs+G1gIgAOLs/X96T4RpoEQ55ZJX79WzDGDHjnyYo3DSRqHdh9I="}]},"_from":".","_npmVersion":"1.3.22","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"}],"directories":{}},"1.9.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.9.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.17.x","istanbul":"0.2.x"},"_id":"chai@1.9.1","dist":{"shasum":"3711bb6706e1568f34c0b36098bf8f19455c81ae","tarball":"http://localhost:4260/chai/chai-1.9.1.tgz","integrity":"sha512-2qKqOkqNwd88Ew129eoDL/CCXcaEqSbrSiM6h/+kJLkI5sQRitykJQ+JN7QsUqAJOjrDkyQmOXsfATJHCPs42Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEaWMOVA/VbfPaTWUMTbtr7Vp/GlGJvxNLDFhKlICMq1AiBiRBt75H3nxFNrafWqAujRWj9ZOpy6u87KHVHGkSrovA=="}]},"_from":".","_npmVersion":"1.3.25","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"directories":{}},"1.9.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.9.2","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"_id":"chai@1.9.2","_shasum":"3f1a20f82b0b9d7437577d24d6f12b1a69d3b590","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"3f1a20f82b0b9d7437577d24d6f12b1a69d3b590","tarball":"http://localhost:4260/chai/chai-1.9.2.tgz","integrity":"sha512-olRoaitftnzWHFEAza6MXR4w+FfZrOVyV7r7U/Z8ObJefCgL8IuWkAuASJjSXrpP9wvgoL8+1dB9RbMLc2FkNg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTxDGSKkSLaR1IyRrxxoIpAwlURxlIQSRgv9vyax07jAIhAMngyOIJTWvFHxc9+ucLU7kbHKj3Q9QsYod8T6WIoyE6"}]},"directories":{}},"1.10.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"1.10.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"c8b3208ce4237d4e0b16508174d616f155c984a2","_id":"chai@1.10.0","_shasum":"e4031cc87654461a75943e5a35ab46eaf39c1eb9","_from":".","_npmVersion":"2.0.0","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"e4031cc87654461a75943e5a35ab46eaf39c1eb9","tarball":"http://localhost:4260/chai/chai-1.10.0.tgz","integrity":"sha512-E3L9M2SeQU1XagJkE9KJyTAXXHKJkJ1EsKkFp0Rl53lYa3mro2PVgYHNiCb2YRa2nUeyg7aqmI1EIcSBayNd5w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAV9yjJ/am0eP8VVo7+aUvsdt1W4uRWCqgO5mydID4G3AiBkly/Gu0Fxz7m/jCHKHI/esrveiFdnFZsMbXYttOJMqw=="}]},"directories":{}},"2.0.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.0.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"2147e1d49eb5caa27e0afb9e18208de2d8741f39","_id":"chai@2.0.0","_shasum":"9cec0eab7d782628f2df51226a41651869a9f894","_from":".","_npmVersion":"2.3.0","_nodeVersion":"0.11.16","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"9cec0eab7d782628f2df51226a41651869a9f894","tarball":"http://localhost:4260/chai/chai-2.0.0.tgz","integrity":"sha512-tscgUV+es5m3o/wTwY0c/B4xj3zBHsbBeetSQe9mmsjRfVQYMF9+F0O0+CW1qPGMXv7Uf1tiID7s9DPc6GZRTg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICQoi451utAKYQLhP9UncHImvnWvJwwz9Tc6yh+fSQR7AiEAirRn4fSEAFfuuT0qs9ncoFUxgwOKUUmpDuV+2WTHH00="}]},"directories":{}},"2.1.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.1.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"09e17b9e090c02d38cd5ee441881dd2691635124","_id":"chai@2.1.0","_shasum":"7c8753895b03eeef2bf23f0f9e45fefa43ee4fcc","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"7c8753895b03eeef2bf23f0f9e45fefa43ee4fcc","tarball":"http://localhost:4260/chai/chai-2.1.0.tgz","integrity":"sha512-a51X6DEd0X3XWQPrvyPZcvu4sXkETo8vvmX9ZLcdm8hjMcqSYP4xM8CheuiGh39cukiDpDe4zd/TcvEM4ZpYog==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPekdfE16ReyiwBZ/MqE3TtKBPYKBdtbBdds8MGbFccwIgK5HTJk4kBhcZoNsaH2rgiufxfBUfCkEGEkDv9N7kPsM="}]},"directories":{}},"2.1.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.1.1","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"d7cafca0232756f767275bb00e66930a7823b027","_id":"chai@2.1.1","_shasum":"9c75e20d4dc73ee051650733938b46e7a9559058","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"9c75e20d4dc73ee051650733938b46e7a9559058","tarball":"http://localhost:4260/chai/chai-2.1.1.tgz","integrity":"sha512-32J8bV42RPXYhZoj0/6nvpl5I/yJ6TvONLW7n1Gam1lBBfR8NaAOqaQCqqZGjl2jQ354IbzQvdUisxNNdamZAg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICYIQAV+BQQ696+bFN/MwF6m7g/ezHTk4AzVL3U26baJAiA/YcNCIRycKd3Jm6dmGVN8jLsETFN06U8yWnt+zuUoQg=="}]},"directories":{}},"2.1.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.1.2","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"7ca2a3bee515f721d5ceb771a371170cef6a4874","_id":"chai@2.1.2","_shasum":"01e7cac8950ce356d520afe78132505b1cd5440f","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"01e7cac8950ce356d520afe78132505b1cd5440f","tarball":"http://localhost:4260/chai/chai-2.1.2.tgz","integrity":"sha512-nNVWgMiYCP0dWu7YiReJSScrWvy7/QWBT6gmX3Ngua+e10fhbLHMohzCTI6d2p7Fm7TD6CH3JSZiUulAvLRfRg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMRNI2M+K9ZuuTBMmjT4yKgtdYTwl7U1jBWFjNmvgUVAiAs9/UOgkymXceXPs4OdsdF2xP7ugvE4d7YSHl1gd+EQg=="}]},"directories":{}},"2.2.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.2.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"57df3888f66c4b34923ce8576aa93855a0ec2f75","_id":"chai@2.2.0","_shasum":"d21135623bd393ad4702d94536eca482ad78d01d","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jakeluer","email":"jake@alogicalparadox.com"},"maintainers":[{"name":"jakeluer","email":"jake.luer@incatern.com"}],"dist":{"shasum":"d21135623bd393ad4702d94536eca482ad78d01d","tarball":"http://localhost:4260/chai/chai-2.2.0.tgz","integrity":"sha512-7G060uuwwpCZr1yUPVyRhbAv1K7H7RMB42f0/QfuxultB+XSeR/oriXvUJmNeYHAde6Z+qSQWi461eK3Bmvzyw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDkd3X01R5kLkvCMgTItIRxwV1T2DQAaVnu5Jb5r30BFAiEA/cEeVRkLp/0oQLG3DsQEPJt0gIrqs3Z44yr3N3zH8Xo="}]},"directories":{}},"2.3.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"2.3.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"1.0.0","deep-eql":"0.1.3"},"devDependencies":{"component":"*","karma":"0.12.x","karma-mocha":"*","karma-sauce-launcher":"0.2.x","karma-phantomjs-launcher":"0.1.1","karma-firefox-launcher":"^0.1.4","mocha":"1.21.x","istanbul":"0.2.x"},"gitHead":"3de55026458ace296df354757361953ec1949859","_id":"chai@2.3.0","_shasum":"8a2f6a34748da801090fd73287b2aa739a4e909a","_from":".","_npmVersion":"2.7.6","_nodeVersion":"0.10.36","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"8a2f6a34748da801090fd73287b2aa739a4e909a","tarball":"http://localhost:4260/chai/chai-2.3.0.tgz","integrity":"sha512-/HtcZZzZolyYgU8x3qClyPGxWS0/TKihLbIuQHam40hZwgyx/6sbm2iLfk8I43mBm2Dk8GoyVstgQLSxUwgShw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYaO2b1Mvl9IDH4n1+rtttCPIWijucNdmVg14yR6VRbwIgAO56aehvV1zjsXGub7jEQu9Kx1FqU/aXgToOf0ckZrE="}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"3.0.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.0.0","repository":{"type":"git","url":"https://github.com/chaijs/chai"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"084a419d81338b4559fb56a53ec48bb552f2be82","_id":"chai@3.0.0","_shasum":"71bfd1034fc8c2d8c5053875bb38f59b2a6f1928","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"dist":{"shasum":"71bfd1034fc8c2d8c5053875bb38f59b2a6f1928","tarball":"http://localhost:4260/chai/chai-3.0.0.tgz","integrity":"sha512-h/7oAXvZAC4ENgCZgX0TqMSY628MEXZ5ZCCnuG/a5dCmUKmYPh9lUhHIqDrEaahpzvDEhdIGPFpeNkNsA60cAg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5x1p3+qRtT7e6zTJCXOU4CZi+AdhVjuglhYatCYVJigIhAM7N+t2HvxyZYc7plXTyE1uhv76gYRotZExpxvlRsegP"}]},"directories":{}},"3.1.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.1.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"9633cb19bc1085aa18c346ac36cd6f223ce3eeb3","_id":"chai@3.1.0","_shasum":"ae50e546a4c2315c88034ac9986a4f14bf711721","_from":".","_npmVersion":"2.12.1","_nodeVersion":"2.2.1","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"dist":{"shasum":"ae50e546a4c2315c88034ac9986a4f14bf711721","tarball":"http://localhost:4260/chai/chai-3.1.0.tgz","integrity":"sha512-5OPEKgEvTe5PHhB5aoFAQxZpK0va1lIfPgFtx8iMD1wWCQYc4HiRXj7/dGx3J00V0yC1roSt1KodgxzQMdJwbg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFVODtOEsIx/Q/ktIr6qY3TQVARN0RRW75TtnwFclcfLAiBLpPF4NLq92FtoyrGhgSnIn1eNqJCjobAVVM6JJYGWog=="}]},"directories":{}},"3.2.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.2.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"4e18d2a49394f21f49eaea97f556d6a17ecbcc7e","_id":"chai@3.2.0","_shasum":"a91c06acc01057f4f4b67ed7785bd7ff4466b2fb","_from":".","_npmVersion":"2.12.1","_nodeVersion":"2.2.1","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"a91c06acc01057f4f4b67ed7785bd7ff4466b2fb","tarball":"http://localhost:4260/chai/chai-3.2.0.tgz","integrity":"sha512-qwjMMh04wwassfJ9dWL1Lv+S757SYTh3S5B2PM53f9fsH0wlCLc64dWAv03SdEzFhieMrSu3oyYZNi8TnsiRrw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGyocO9dhAL15qxvT+lvG4FVDgKl6TdCml8Vyd0WKWSRAiBZzIJNepgU0WQMsKKjhQ/yFls4N7B02kohwm6mQByZoA=="}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"3.3.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.3.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"df954ccacf77cc740f45730c04a37bccf7387456","_id":"chai@3.3.0","_shasum":"ffc291674da551e589077d6627384acabca2e02c","_from":".","_npmVersion":"2.14.2","_nodeVersion":"2.2.1","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"ffc291674da551e589077d6627384acabca2e02c","tarball":"http://localhost:4260/chai/chai-3.3.0.tgz","integrity":"sha512-GRxKSa+oFlhTd/2XEEBnyhYZlLCa7ueexFZpDBVtkcpGFuwnB9/+RDiiSB2VjG3TpkgqYZUVfhI/KxLHMlYCyg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDOwlM51F7Eh3zznedg9+zCNKLmxaG0m9kmRwNuQ9o4BwIgOEoGohg+OATNfE92zwIRaTI6C8BK43K7Z30cgQjrGXI="}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"3.4.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.4.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"71b2512a9919a1490cdbb80e6d4c924399a283fe","_id":"chai@3.4.0","_shasum":"fd268ede01c3e081891ab59d30628fb3b9df4786","_from":".","_npmVersion":"3.3.8","_nodeVersion":"4.1.2","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"fd268ede01c3e081891ab59d30628fb3b9df4786","tarball":"http://localhost:4260/chai/chai-3.4.0.tgz","integrity":"sha512-c959X6Ydoah5nNc1BWkvB1nb8U3svL1f6UOH7zGZoc9ehqwnubtMPMLe7yKpJ5ZvsBn5czVtb+UTCisDZTHIZA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDXwoM34kxfcsclZ+5gAr8Vu++KvpRY8O5Io4lDK9NpVQIgK2o+JCWDMoaumk2IW5r6xnEX8J0QEmMTdJwuTPgsoWY="}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"3.4.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.4.1","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.12.0","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"5def52c217fa4fa90c0507dfe1d0000268908f1c","_id":"chai@3.4.1","_shasum":"330ae2f819124c26182036fa5e43a88ea4e1bd85","_from":".","_npmVersion":"3.3.8","_nodeVersion":"4.1.2","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"330ae2f819124c26182036fa5e43a88ea4e1bd85","tarball":"http://localhost:4260/chai/chai-3.4.1.tgz","integrity":"sha512-tUC1XLrSp1x+CI/nOucYeQ8mRTpi8TXr6oR5trVZBOKK8Uo3/G4AXRLylEETej7ukH+ZPSwtW6iSfUe7l7Lgag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDhNNlflL6FlDynpnq5258m/n3uenUYuMm+aLiwYbpMiwIhAOnZZgyyAKwqj0bPCFReiF+nl5sqqi8g+qBS4p6H5q/1"}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"3.5.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"3.5.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">= 0.4.0"},"dependencies":{"assertion-error":"^1.0.1","deep-eql":"^0.1.3","type-detect":"^1.0.0"},"devDependencies":{"browserify":"^10.2.1","bump-cli":"^1.1.3","karma":"^0.13.16","karma-mocha":"^0.1.10","karma-sauce-launcher":"^0.2.11","karma-phantomjs-launcher":"^0.2.0","karma-firefox-launcher":"^0.1.6","mocha":"^2.2.5","istanbul":"^0.3.14"},"gitHead":"4ca0218391cf947c6cfac2d1a7424a63a4b4c232","_id":"chai@3.5.0","_shasum":"4d02637b067fe958bdbfdd3a40ec56fef7373247","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.5.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"4d02637b067fe958bdbfdd3a40ec56fef7373247","tarball":"http://localhost:4260/chai/chai-3.5.0.tgz","integrity":"sha512-eRYY0vPS2a9zt5w5Z0aCeWbrXTEyvk7u/Xf71EzNObrjSCPgMm1Nku/D/u2tiqHBX5j40wWhj54YJLtgn8g55A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHY7HMw3T5OPEAqvW5IY6+9ehYbLuiZxcx0ZIX25F2pRAiEA1mq1W5yRiWS6PM0pl9M1NTpfKV8Jz8itPFv8pIZWeAU="}]},"maintainers":[{"name":"jakeluer","email":"jake@alogicalparadox.com"},{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{}},"4.0.0-canary.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.0.0-canary.1","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=0.10"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^1.0.3","get-func-name":"^1.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^13.0.1","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"43752b05df6fdcda89b8d6a42c05f0736bec8ec8","_id":"chai@4.0.0-canary.1","_shasum":"f4b5f24a4064795c4efac271bc85ce9f69c9f467","_from":".","_npmVersion":"2.15.1","_nodeVersion":"0.12.17","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"f4b5f24a4064795c4efac271bc85ce9f69c9f467","tarball":"http://localhost:4260/chai/chai-4.0.0-canary.1.tgz","integrity":"sha512-Kd39N5tBKQXHCKim+4n2LAL5X1Z+jbdFQGiWk1Yg0o+Q/syBcf9uBteQfL1zatQgFyd71gIsQehLbet0VriXWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEGdtIPs3J/NYT5xk7GHKXxNGyGgE3ch0fPOph4EM+5gAiEAtEGkA5l0uMmwV2vz1NbVzm0ZiTeN3iNJnAQttk/IYAc="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/chai-4.0.0-canary.1.tgz_1477347063850_0.18597974558360875"},"directories":{}},"4.0.0-canary.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.0.0-canary.2","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","browser":"./chai.js","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^13.0.1","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"850bd7e016606ce52292c0477320279a8b9cf294","_id":"chai@4.0.0-canary.2","_shasum":"a017f59d3ed2d64795c91a51b5034e41b873da87","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.8.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"a017f59d3ed2d64795c91a51b5034e41b873da87","tarball":"http://localhost:4260/chai/chai-4.0.0-canary.2.tgz","integrity":"sha512-tBhHOU0FDil7F5IXzWMGIRqDCeOtomI/YueXK/Epay6pSx7xZJzMOBGyCeIaRHY95iry8+arCNNIerRuW7ugOQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCzR+wyltN9Y0ixHzuXidN+MTQ3U9NhWuM2b9oGXKRRBAIhAPQKo5tNqc2WkCFkDJpsvRQuRPE/ADjDDYlRG1wZzJf4"}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/chai-4.0.0-canary.2.tgz_1492450394517_0.7511835743207484"},"directories":{}},"4.0.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.0.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","browser":"./chai.js","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^13.0.1","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"ab1fbadcfe4339072976e468382b3d875fdafe5d","_id":"chai@4.0.0","_shasum":"f6c989e45a5707d40c54d97ddd7ca89b30a6a06a","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"f6c989e45a5707d40c54d97ddd7ca89b30a6a06a","tarball":"http://localhost:4260/chai/chai-4.0.0.tgz","integrity":"sha512-FQdXBx+UlDU1RljcWV3/ha2Mm+ooF9IQApHXZA1Az+XYItNtzYPR7e1Ga6WwjTkhCPrE6WhvaCU6b4ljGKbgoQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+XOGqdf4Zsjb0phZJYk4dovALtCsooEuCX4/wcu6VuAiBqXZTn/XYS3XwcAnYWSEttaPy39kM2H1J9As/Zw9eDHg=="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.0.0.tgz_1495794695702_0.8961308586876839"},"directories":{}},"4.0.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.0.1","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^13.0.1","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"b38b8d765972d624f075cf173806b43164430dbc","_id":"chai@4.0.1","_shasum":"9e41e808e17a7f10807721e2ac5a589d5bb09082","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.3","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"9e41e808e17a7f10807721e2ac5a589d5bb09082","tarball":"http://localhost:4260/chai/chai-4.0.1.tgz","integrity":"sha512-YpPiiMNoEijEENHxbl/2Me8+kfebLMerG2mi7FEKNiWuQQ8gBYC7OKqcp7HVqw93hsCb8X4Pf4Ip9zcZTmnx4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAQwA84+9/ZrqNiXYwdzcfBVWVuGGpO/j85i61+Es/7sAiAOsPk4MkIxGcMhQfatV3gipMjc18pn+h0mtELxjEt8Lg=="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.0.1.tgz_1496265625036_0.6473847914021462"},"directories":{}},"4.0.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.0.2","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^13.0.1","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"616cf8bf883afa67f99a952901b4b44fcabc0cfe","_id":"chai@4.0.2","_shasum":"2f7327c4de6f385dd7787999e2ab02697a32b83b","_from":".","_npmVersion":"4.2.0","_nodeVersion":"7.10.0","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"2f7327c4de6f385dd7787999e2ab02697a32b83b","tarball":"http://localhost:4260/chai/chai-4.0.2.tgz","integrity":"sha512-SSBITzu/g8nD3cP/GUKPYP9OBX92s4hvz+t6spQ2SjknieqUGKqR8etHQXV/9an9Ot+8iLrnFoBRcsIxefcHGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBgjCy7yuAlAL5DbKqjciRcWmlyfIenQFGIjfEvXNzYoAiEAl4qTNueiAKWSYzW4tL22pDuzTmglOFNWMT+bzlY1t2w="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.0.2.tgz_1496691226691_0.649338636547327"},"directories":{}},"4.1.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.1.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^14.4.0","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"df9073cb8eb2bb4dbb173dcaef29d4dda7ad76a2","_id":"chai@4.1.0","_shasum":"331a0391b55c3af8740ae9c3b7458bc1c3805e6d","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.4","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"331a0391b55c3af8740ae9c3b7458bc1c3805e6d","tarball":"http://localhost:4260/chai/chai-4.1.0.tgz","integrity":"sha512-p7POs9utQIjw2WqC4J0993iRmr/rfgNVaJ6f4rd3k1XQRapM5v3lYXprYp+yxloEi+wasd8i2jLr/GE94mTIag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC32aDFBhfdeu1R5e6LREYTF3uoFgjH3lXKpijU5CmvoQIgESAJ6eERia1vTSZ2OEC/K7KW3Y/3BAwLR3Pl7Xicgbk="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.1.0.tgz_1499818629025_0.3245607155840844"},"directories":{}},"4.1.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.1.1","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^2.0.1","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^14.4.0","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"02ddebd8f274ba94f9eb95c1c8c21176be6fe20c","_id":"chai@4.1.1","_shasum":"66e21279e6f3c6415ff8231878227900e2171b39","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.4","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"66e21279e6f3c6415ff8231878227900e2171b39","tarball":"http://localhost:4260/chai/chai-4.1.1.tgz","integrity":"sha512-wXqQM5Ck2MhK3D6tHXozIB7hd65uLsR1QgII0WQRfI2HK9Ny/dJlkaWZgtp5fI2AZ7vOiVCAK66AIAWz0mKy2Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2BiuSthzwv0d/TLIoRetZCAWvWE2m8D4Go/+Zvr+VbQIgOlBo/QK5GXn4tVrLqBhvh6yWrZomPRiFv6w7Q4RDw9U="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.1.1.tgz_1501918384597_0.915291927754879"},"directories":{}},"4.1.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.1.2","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.0.1","check-error":"^1.0.1","deep-eql":"^3.0.0","get-func-name":"^2.0.0","pathval":"^1.0.0","type-detect":"^4.0.0"},"devDependencies":{"browserify":"^14.4.0","bump-cli":"^1.1.3","istanbul":"^0.4.3","karma":"^1.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.0.0","mocha":"^3.0.0"},"gitHead":"529d395fa08091af2a02a8398b1144c51ed62178","_id":"chai@4.1.2","_shasum":"0f64584ba642f0f2ace2806279f4f06ca23ad73c","_from":".","_npmVersion":"2.15.11","_nodeVersion":"4.8.4","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"shasum":"0f64584ba642f0f2ace2806279f4f06ca23ad73c","tarball":"http://localhost:4260/chai/chai-4.1.2.tgz","integrity":"sha512-YTHf80rJ8M5/cJoFKEV1y3PnexbGs0vSHjouRRU8gLM05Nc3Mqq9zor/P4SCqB/sgvKRLvya7wHLC1XQ9pTjgQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNK1/2v97LFLZrMNO6ISN2g/8FRg3+1uNpFabi6y1WOgIgZzDNakkbKzduXIi7TdV3fQDy7T/1gBBRTMjoKFTttHc="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai-4.1.2.tgz_1504215698412_0.9556753125507385"},"directories":{}},"4.2.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.2.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.0","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.0.0","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^2.0.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-phantomjs-launcher":"^1.0.0","karma-sauce-launcher":"^1.2.0","mocha":"^5.0.0"},"gitHead":"26c8a794ec6da695f004bdbd6362a466dc3d098f","_id":"chai@4.2.0","_npmVersion":"6.4.1","_nodeVersion":"8.9.4","_npmUser":{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},"dist":{"integrity":"sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==","shasum":"760aa72cf20e3795e84b12877ce0e83737aa29e5","tarball":"http://localhost:4260/chai/chai-4.2.0.tgz","fileCount":48,"unpackedSize":735419,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbq3haCRA9TVsSAnZWagAAVJYP/2TkPegZgegrYa0qukFY\noJiSaGUU0hJYP5cAwfrYTRNzMKuZnwIj0uTV2uEtC4FIl4/kGeI0tHoeEa4s\nY1W97C7e+5l96JVmODkTo9a8Z5Fz3YEeUk+fpqFRFqZuvRUtw6htqzKyg4yQ\n26hysm/79vCtPqzzK7Kvc2JCt5zen+NOcxOKKJ6e8ptMIemdq5FxnqJ7Pbeq\nH40DJzZXiQD6+PSfJs27NaIU5HlGNzCxFwgn0ZFhRUBrx7qALWDja917LTH8\nyKKAcxhjPsslPzeOctwJm0ckwC7/7rAUBhGL0TsTe7kyvqjNhAPikA4x2mf/\nPqGmpj5zjMIP7f0nN7a2cCq9gROaurxjr0YG63KnhXm2bqX5b2sAf2+kOiNU\nAjxFWA04/AgjCdU6oVIgwosMITqJY9MvCzq/r7wKv5vNBKMqtcTag3Y2muIE\npK73z34WKbNvInyWJ8tAWiK2CYIhKxhmEkd/VrOYSfyzaQxRD96PmCrRx3he\nCfcKUSCOcfWMFcyqq8GJuALbAli0nFeI8RBcG+d28b42J3CnncmqlvgQtitY\n0y5vqmcEWhoRz3zDk6qukvhBwZgkEFl/vorxOCCpeON2rjweKVBN423frjbl\nULvQhznTMfqhj3UDF4AXGYm43yyY/Ozu9dYG+b1tOj2GUEdH6xf+xLodTa6p\nd+Ec\r\n=8N+I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICiKHcqpvovYba+vLA8ms6KyuQmoKN0Wc5NxM4f6Yj62AiAMndUla4oO7SHLDXLCqavq1XB7CUMU42EuSd2RWWJxzw=="}]},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.2.0_1537964121939_0.6568203770301109"},"_hasShrinkwrap":false},"4.3.0":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.0","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./":"./"},"scripts":{"test":"make test"},"engines":{"node":">=8"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.0","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^2.0.0","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^1.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"39dd113f36fa747ae9b419ae30eb697891bf6709","_id":"chai@4.3.0","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-/BFd2J30EcOwmdOgXvVsmM48l0Br0nmZPlO0uOW4XKh6kpsUumRXBgPV+IlaqFaqr9cYbeoZAM1Npx0i4A+aiA==","shasum":"5523a5faf7f819c8a92480d70a8cccbadacfc25f","tarball":"http://localhost:4260/chai/chai-4.3.0.tgz","fileCount":50,"unpackedSize":741487,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgG9M/CRA9TVsSAnZWagAAiOkP/j82xQut+L9ZqU9EeR6N\njlHHCfveKshFORD7ngbGmsphDHSW9DYy7cppleCA9Exrn0Kyd3P0pDJ+ohf3\ndXrhftqaimEmlX5OQahHIEpRaA5SL4gMeg3mxnGHEtClzqtGI1mhtv99j8eS\nrx9cFdb5pn3bQVL0sVIMO3rWwHrkwhYtX/319s+G9L5kw7wxF7AqMHG7FdGd\nB5GjTmH1Dg9DsYSY03SZsZ5ktqLoNIEP7T/6RhhnQ6TNssDTpm6A567ao6EO\nQ5O9sb0g1D52udjtZ1b1YHAHfRWqolHrFZy5B65q2f9u8Jy+O554J07ld0jw\n94ihMMAg8BnQFlGu3CanqJFY/ETmevoi1CwWZhUECbqe3woqsFOa+vwT8X6f\nTTJfakwOb/gEEsMHH/5ug59jFOIBQxhIjhjkF+de1+YdQ01XZs/u/cN5CWul\n/SfRBkqo4OKbc1xvYR7xZPHyyNmN+METn3o4nRnL3TBtJPCDK0LnYS22cl4P\nOW96vcLWa9WtFkEIbBqDxvlYWpo/20rUjJ9bobcVutgbG21+6xDwKWpgp0z5\nP4RPBPFSQ4n1wythy+E3YF+QGO3Y60K39K9Yxz2qlZffg/ARg2WZOvdgqyCW\nOrjit4ZlaCS6Vya55xKAmqQJCkEeDQWM8uYEVlHOfGXivNC3mlKVkdJjfLlp\n803I\r\n=DhFc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDo1OLNB+GCN/PKsEmoYYm1rChUyJClwLVasxemvmls5AiA8kOv92QZfeI2D8abUkHA+leWFCM+b9PqPd4ZwoBxHjg=="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.0_1612436287207_0.34154702724570685"},"_hasShrinkwrap":false},"4.3.1":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.1","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./":"./"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"8a246661566227db3d37019bb0bab3bbcdf45841","_id":"chai@4.3.1","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-JClPZFGRcSl7X8dYzlCJY7v+X1fBA+9Y339Y8EqhBVfp0QC1hTnaf7nMfR+XZ74clkBC64b0iEw2cWKHt3EVqA==","shasum":"6fc6af447610709818e5c45116207d60b8a49cfd","tarball":"http://localhost:4260/chai/chai-4.3.1.tgz","fileCount":50,"unpackedSize":743273,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPoG8CRA9TVsSAnZWagAAoQIP/0pPLUSMvtOmgXxlgQ+3\nw0lbMWr3wfYfJHSprYFzrmm6tVbs4LcTHCHKx3yX45mQBKmDdSrk8c/enUZj\nMIMDriTZZAbTZcbL4qqjizP6tpkmW5eDeXEwxdPTESBEmbGkl4OuJ8/wK/4t\nFN0UF1/Wv/QoGGsOhb/CH13rYiZJo3zklLfOxKNgW9tDKZ8hYiZ08NOBJch4\nC5gbtud81rMIWRhAdDoulqVlaopS/3jmhmS+qCRsqRxMAd6jEVaxiscurbRG\nqI3++lcmAzp3I//lpmIjqsLyrJ+u3f+xEWMW1gHhyzhciIE4HyR6LHOG5dZB\nszOhwaKTRttAF63/jXK/yiQnX7bBvjlVB3trDao0ZL49PD89z1FXftlkw5oo\n7/8OKkEjmtIsmpLa9GtiaMOXZoIDCzj0ZpGP/62wwWKZnlgEQhHGh8hcuw/R\nAOwWvShp6a90s7maxopF8xaqBiKaPG1gVdDULyNfkq58kDlZDJW93AWSNBcL\naYjUulIzxiRGBOYQegMl6tZEf/vsrWMJLyz2pmkFvy3jR0kGboWcv7gyiLRy\ndxFJTUJIs+T2FwlHYit/y9Hy/nk19iPktIXg/t794x7iUx3UerHdcPuQIOT2\nyfKHvdoJJaX1E8wlx638Khgcw57Fm4qL/0+eTe1wLLTUK9r1s9474G5QXb1M\nlbmh\r\n=ToRb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGgJ+HhMj3XOJgjkUDhyo9ReORDAsFqJvJXVCwZRwo2wIgUZ5ek3uhOlNMCVCuEbQUZYaqfSMWGpfl0Zl0Ob+IIHw="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.1_1614709177189_0.33012824645885286"},"_hasShrinkwrap":false},"4.3.2":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.2","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./":"./"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"3b9bc7f56dc0321e349ab145154052aae8056bdd","_id":"chai@4.3.2","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-6VMblLfXGtgkcXBasYWrpU+HHTDrs0VNTlBnxIoV2H78PLey9vCPN931WnnFwBrn7HuJODSN/9qTYH/13fJX6g==","shasum":"74ca69d542015b8efc213fe1cb51162990f2bf5b","tarball":"http://localhost:4260/chai/chai-4.3.2.tgz","fileCount":50,"unpackedSize":743309,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgP9L5CRA9TVsSAnZWagAABQcP/1fTvNpKOGYkjBKTceHI\nbAXU1DBdSMFPiNyEMNTpxtp482iSWR8qX7TZ+OkTGGpD9/ioHQn+Btq0JImk\nmBI3ctn1W5szIbVqkDMLhZ6H3quyVBg4FoCeEY1iTHwtXnGypoP3RVj748wJ\n3n1iWBYuDZYoHWE5PmjSYOW/lX0pR7Q6ZqWlmPR1RO0Nhx3Z7woS3+pBSoj8\nwRGsvAF7mpkVvUbOpbTEMyMW8nBNvnXZzhvWW87AVNkE5PFBZ0C60TQNSLK6\n3nXoBirE+Wa6ZtvSftI8t8uMFnZo+iMkocMjKPy3GylIgfEmvyEqmKitT5qm\no/oBAV7TCnVR962x1jJJzgcs3OUqHqjgXH28TaEpVTnU9DvPhV3PNdroHGzG\niKlh8RJVEU6kVJtp4qCNUuo9ytG5eVkBZC3UOUpJMEp5YIw5XnWi+4vrBJ7n\nJAaYBQj4q30pljLWBLz3WbxWk8tcpMTf37/bPK5GrrEqObgs41NYm/jretBJ\n+c/q/6CtUwzy8XMxcj4+ztYFhGjMN9or/VxkeBn3ZMY/beoo8qyKjEe6CUN4\n4bQMwvct9MkNcvMDUUfL7ig01iQDsZTYJzpGGaiRSOTzTQtqhJg/HehXMeHe\nPy2AapT6NwF01Vva2VTqouU9LGYdnDYtrVvZ9Loq+iMJXPRDPBDaIBXbTCEm\nKDgu\r\n=4hcR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEolWFPJcuF7HOSJOkRq9aBTct5bnjslqwzVoU5GQhSIAiA2daQMIGkIDKTxNz+kFNA9mus+53eIlBtWYomh5WCIEQ=="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.2_1614795513310_0.6125462539766466"},"_hasShrinkwrap":false},"4.3.3":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.3","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./":"./"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"dc858a0353bb0eccca0de8185c140d4a1c1c6006","_id":"chai@4.3.3","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-MPSLOZwxxnA0DhLE84klnGPojWFK5KuhP7/j5dTsxpr2S3XlkqJP5WbyYl1gCTWvG2Z5N+HD4F472WsbEZL6Pw==","shasum":"f2b2ad9736999d07a7ff95cf1e7086c43a76f72d","tarball":"http://localhost:4260/chai/chai-4.3.3.tgz","fileCount":50,"unpackedSize":743350,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgP9PTCRA9TVsSAnZWagAAx2oP/3APIWS9up8luXq1Sp8E\nUTtZ8KZtGG0r1kYeNXP8Xl9OQ+EOKJAPYl8P+SRzc97WdS1yerTYhTalGaix\nPqXYWRcGusvk1k8SNGQDf670i4jljMf+rXfyCqsLkEkzaEU/tyjuVMpTgyj4\nsGno0mP6XfFeA5Y8cCueKi85gVQiU8wUB/FjPeV5qUw1OeNTpuU38qCnNmXF\n/yxyVgEIOJAmROLIJOGXjx6+R6IVOX95tXRZXBcshKkR2IfWmYC3b2DiXVXX\njdg6cBJfEdxf0KEc3a9V0T4DAJtYewCLZuOP4z9GB33PzLcnDu7ggYCy8GuJ\nmhpP/JCZkCvkcoWOx5eei65BS309XG0AjGAZmKcnBGV2p8QqUd7JDgU9e1Ee\nOrDgul4EcD2oukapEdjUpd1lCVnQ3L6M7Twpl2Y8aLN8FKjDKseAqOtN2y8i\nPgztVcY40I7SUptKjoLG+vcjaJ8p7SNrVMXk6pkM/lj0ZVNHppccnArjvcov\nbPbdoPyRXd3B45LHU3uy/fFOc/iMinhbKcFUFAtYBJLrdG8nuRB/yXrC0ClO\n4cPjySbZlswDPDF0Gzdb10okbKBqIPpMyKGJMrvQbLFD3NBxYh3IbXGAw+T6\nSN/GaeGjUcjn/dISkoJoJ9Vy1WW2i1q8qo3VxhaxYeILR+cUiMvDZccwL6Wr\nRxD6\r\n=UYFv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEvtBZ3gRRISYtzxmfC1c/UL+j7vTO5VzciNNzr3r00IAiEAyKGFj4YecS3LZVqh9IwXickXNxm9GVnpKoDpc/BVaCE="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.3_1614795730672_0.8598770755412406"},"_hasShrinkwrap":false},"4.3.4":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.4","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./":"./"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"ab41ed86cc154e1df125b16e74abaa0d6f6ade82","_id":"chai@4.3.4","_nodeVersion":"14.9.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==","shasum":"b55e655b31e1eac7099be4c08c21964fce2e6c49","tarball":"http://localhost:4260/chai/chai-4.3.4.tgz","fileCount":50,"unpackedSize":743510,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgS5vlCRA9TVsSAnZWagAAPRcQAJJEkkw8MSTZ41dLnRgi\nNB9LQxV+nohdCBuV9IBn47Q004/9Mi6/+gCM5PlMvcgxc4tRAbWeXIRLx09k\nHY8m/qgaq5a6DQrN6GxyUjgQUI6JxDRjK5Cn+3+FQAKrLq+31Wh6pqKUjDk7\nXlyFcartzLpU+vjdSYkafeoZSzKGEl+WGy/Yzn2/bj/q1KSkt8oLaZfm21n/\nO7rEAaIjugUrQZfl0Ck3SvD9ChilRyY0zFT9K3hVZr7xxBE5GsaIongQZOfJ\nFfaVREmRkr2F5Y8Upe1MQ3Od+Z4dum0tWtoEYhRrtVa7kmUM4H0ixbrF0VbN\n+xXxB/bA/+jcJJ5PDfpx/zl4/JTV1h2rs9TWLrRXdm1nCflBybWfSY5HJYXX\nTVt4Z+hg0yXe1Bq/MVJm2mQsAOUt/gRN6N/RCh3HEw3GC0BDnNOxu5zSfcw5\nc4NYsG0J3dctdyTqSXImjKfIorskQvoE5z4m0at5FfNzZVnnwEEL4a+6EOsV\nANByJhTXWNIFiFGAk8ZHivYiuB/cOJgkp8JfAOMJlcE06mKjB4BQtlDhCDPR\nvzQDQC9/avlByNh0wdLYN5ENC1I73QxIl71a3Qr/yVTVHOI3ZUjNtubUx35e\n4MjfkUiwPGykKNmg8n9OhlybORxydWrAKCRnCzrOpp/tLpYiF7LRjlwkUXpY\nNSrc\r\n=MuEB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBSzZ2rWU3i+X1HDER1qYsvULmZd/YQQ+ozOoJt2RpV/AiANC333DwlMGNCdT+RrwgKrozlXA8ZA1QszSCRXin7PFQ=="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.4_1615567844714_0.20594158906561932"},"_hasShrinkwrap":false},"4.3.5":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.5","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./*":"./*"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","loupe":"^2.3.0","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"99e36a83bbd79cc970c2c30e81c6cf89cca89660","_id":"chai@4.3.5","_nodeVersion":"17.4.0","_npmVersion":"8.3.1","dist":{"integrity":"sha512-0gKhNDL29PUlmwz1CG42p/OaBf1v0YD3oH4//YMS1niT7rLH9tC+lqTgk+SvdbhMLd7ToTtxA61orNBmpSO/DA==","shasum":"784cf398a30cd45b8980181ba1a8c866c225b5df","tarball":"http://localhost:4260/chai/chai-4.3.5.tgz","fileCount":50,"unpackedSize":765385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8A1HCRA9TVsSAnZWagAAh08QAI29nIF83qbemwEvUU2n\nD0VSXyxI0RV2a4znP9oGQ8heBa9aQx0scAfSAj+wqUcDDwbBFcxvbaQkhGuT\nvffsATIqyz6jRfCsF83sp0HvVyQdQiJ/HmwszBW08mFi2osvTBcqB/JR75p/\niOqbv97tZGwF/lgYYVRjFAe0oIzsiz6yiH1p4MsjAK0T19bAYUc0OVMH9SKD\nLumIfDuNKF5mgab+iyz4JpRy8KH+hnF6u7IvXr6rubcWggu3atXza7c9fAuD\nCv3CsJ2XUAnHM/ncuvcbYtHDCuXg/smMhd2rYdr70rWrU1NmmrnQ7YWipLlo\nzOTkQUmUIYrW+A41AcOSgz7DASWn12sPW156kMFhrfLWaWLqtb/9rPFkC3Un\nMNpMsStlZgHLeSn1gj04gWvCeMJwLuNUeiNDm2KqcG29/uDQc6ACY3zbAI96\nSM7OcHuA9S5KQ4TJBmNdZHZpGHtaRaue1V4QzFIjulF3/CmQ8F3HcNV8hWNC\nuSg2beo35zXrBOD+Z4xYe2EEfExyypkVEdL4kM0aDuTzcYLkFTLCi1s7S5q3\nqvzOjJh2xqSNS29brU+QNXCLiVA0qLZyx+kBhQURegUEco/BrGlxmlWKDbhb\nD6p0IMGiWp4d07VaK0P+s7J1HReTRsvxlteGj5QK5JDVz2nlxsFZfso0vRfT\nUi64\r\n=Zzvn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDMKo+Gr/o1ZO2BBeURIFAY3O3iDOCpUUCb28Ij/FiohAiEA/VyluMXk54Gmx6rErcuR4OrjNKA7PwFkHwSrVdMQKKA="}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.5_1643121991294_0.7076648559743657"},"_hasShrinkwrap":false},"4.3.6":{"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"name":"chai","description":"BDD/TDD assertion library for node.js and the browser. Test framework agnostic.","keywords":["test","assertion","assert","testing","chai"],"homepage":"http://chaijs.com","license":"MIT","contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"version":"4.3.6","repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"bugs":{"url":"https://github.com/chaijs/chai/issues"},"main":"./index","exports":{".":{"require":"./index.js","import":"./index.mjs"},"./*":"./*"},"scripts":{"test":"make test"},"engines":{"node":">=4"},"dependencies":{"assertion-error":"^1.1.0","check-error":"^1.0.2","deep-eql":"^3.0.1","get-func-name":"^2.0.0","loupe":"^2.3.1","pathval":"^1.1.1","type-detect":"^4.0.5"},"devDependencies":{"browserify":"^16.2.3","bump-cli":"^1.1.3","codecov":"^3.0.0","istanbul":"^0.4.3","karma":"^6.1.1","karma-chrome-launcher":"^2.2.0","karma-firefox-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-sauce-launcher":"^1.2.0","mocha":"^7.1.2"},"gitHead":"529b8b527ba99454471ac67d6aebca9d96cb5dd9","_id":"chai@4.3.6","_nodeVersion":"17.4.0","_npmVersion":"8.3.1","dist":{"integrity":"sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==","shasum":"ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c","tarball":"http://localhost:4260/chai/chai-4.3.6.tgz","fileCount":50,"unpackedSize":750564,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8UhgCRA9TVsSAnZWagAAv+YP/12t4uBk4xuCAA7pkDcj\nkJm0/jTdaEsIF0pyI4IDDzix91lwXhZCO5fNtlI8CYZ3NwOhtu5hROuOCAlp\ni/knLqRAilVcLpT6xNxOHtxPhaA8fMRMMyrtw029iH2nHevW3kt2kbzG3gNi\nWXO0E8EFmMURiAHKqucb9aV+Qbzh/d8Dmm67JoFPKY0bJktcbeSRB8qyNhTQ\nmTcKKpL4ZEboZ9ofpiICSLyEzmSU+3Hv53WlomWMG6nUz1+JsEZ2bXABQ6WJ\niqr+LkM2ipKgeq7ZNe1dTnY6h+1TpSXPidt6R2qtkdWavr0UuYNUp85eo0/C\n6HgtYcuYm2UysKrXJkzqpEl1FTzxo8atuVFubWphpvuPShkXpxj7Bi670Z8h\nuqpU2DX6CEZlBLhX6zF2Ly/DPDHDaKj9GMafg5g8zTOTXphnWOJ5vYmvqF7e\nTM9qwsxv1kPbZYYdmGUF1ADBDjy3vwG/+8py8j7TMLIa7LiMeR4mCUF4wLvU\nbSpxTYfAeHX7CQDTej1fD3LkwAzyBhHHEpJY2yRRwll/9FaNwb9JM8YcxpRO\nH+BsL9Mji/atpoK2WxEX/oqep17sGEA8yafHs9UiIqTo1fvunttqUwyYD+Lx\nd84syQ873+mg/tDuhx5L2AjmbANrQJAAjngMUBNOG9/NZz0sYQ9kSChqb9aK\nT/4b\r\n=ckEl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDDsAllykGfti9wvQhGkKpJ7jdFVZ99oozpeX8CutT2MQIhAO3f06HA/ygzzZLliUMSLrxEdzCnQmxGZH5TQMVZVGfj"}]},"_npmUser":{"name":"chai","email":"chaijs@keithcirkel.co.uk"},"directories":{},"maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chai_4.3.6_1643202656757_0.2797039481196104"},"_hasShrinkwrap":false}},"readme":"

\n \n \"ChaiJS\"\n \n
\n chai\n

\n\n

\n Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.\n

\n\n

\n \n \n \n \n \n \n \n \n \n
\n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n

\n\nFor more information or to download plugins, view the [documentation](http://chaijs.com).\n\n## What is Chai?\n\nChai is an _assertion library_, similar to Node's built-in `assert`. It makes testing much easier by giving you lots of assertions you can run against your code.\n\n## Installation\n\n### Node.js\n\n`chai` is available on [npm](http://npmjs.org). To install it, type:\n\n $ npm install --save-dev chai\n\n### Browsers\n\nYou can also use it within the browser; install via npm and use the `chai.js` file found within the download. For example:\n\n```html\n\n```\n\n## Usage\n\nImport the library in your code, and then pick one of the styles you'd like to use - either `assert`, `expect` or `should`:\n\n```js\nvar chai = require('chai'); \nvar assert = chai.assert; // Using Assert style\nvar expect = chai.expect; // Using Expect style\nvar should = chai.should(); // Using Should style\n```\n\n### Pre-Native Modules Usage (_registers the chai testing style globally_)\n\n```js\nrequire('chai/register-assert'); // Using Assert style\nrequire('chai/register-expect'); // Using Expect style\nrequire('chai/register-should'); // Using Should style\n```\n\n### Pre-Native Modules Usage (_as local variables_)\n\n```js\nconst { assert } = require('chai'); // Using Assert style\nconst { expect } = require('chai'); // Using Expect style\nconst { should } = require('chai'); // Using Should style\nshould(); // Modifies `Object.prototype`\n\nconst { expect, use } = require('chai'); // Creates local variables `expect` and `use`; useful for plugin use\n```\n\n### Native Modules Usage (_registers the chai testing style globally_)\n\n```js\nimport 'chai/register-assert'; // Using Assert style\nimport 'chai/register-expect'; // Using Expect style\nimport 'chai/register-should'; // Using Should style\n```\n\n### Native Modules Usage (_local import only_)\n\n```js\nimport { assert } from 'chai'; // Using Assert style\nimport { expect } from 'chai'; // Using Expect style\nimport { should } from 'chai'; // Using Should style\nshould(); // Modifies `Object.prototype`\n```\n\n### Usage with Mocha\n\n```bash\nmocha spec.js -r chai/register-assert # Using Assert style\nmocha spec.js -r chai/register-expect # Using Expect style\nmocha spec.js -r chai/register-should # Using Should style\n```\n\n[Read more about these styles in our docs](http://chaijs.com/guide/styles/).\n\n## Plugins\n\nChai offers a robust Plugin architecture for extending Chai's assertions and interfaces.\n\n- Need a plugin? View the [official plugin list](http://chaijs.com/plugins).\n- Want to build a plugin? Read the [plugin api documentation](http://chaijs.com/guide/plugins/).\n- Have a plugin and want it listed? Simply add the following keywords to your package.json:\n - `chai-plugin`\n - `browser` if your plugin works in the browser as well as Node.js\n - `browser-only` if your plugin does not work with Node.js\n\n### Related Projects\n\n- [chaijs / chai-docs](https://github.com/chaijs/chai-docs): The chaijs.com website source code.\n- [chaijs / assertion-error](https://github.com/chaijs/assertion-error): Custom `Error` constructor thrown upon an assertion failing.\n- [chaijs / deep-eql](https://github.com/chaijs/deep-eql): Improved deep equality testing for Node.js and the browser.\n- [chaijs / type-detect](https://github.com/chaijs/type-detect): Improved typeof detection for Node.js and the browser.\n- [chaijs / check-error](https://github.com/chaijs/check-error): Error comparison and information related utility for Node.js and the browser.\n- [chaijs / loupe](https://github.com/chaijs/loupe): Inspect utility for Node.js and browsers.\n- [chaijs / pathval](https://github.com/chaijs/pathval): Object value retrieval given a string path.\n- [chaijs / get-func-name](https://github.com/chaijs/get-func-name): Utility for getting a function's name for node and the browser.\n\n### Contributing\n\nThank you very much for considering to contribute!\n\nPlease make sure you follow our [Code Of Conduct](https://github.com/chaijs/chai/blob/master/CODE_OF_CONDUCT.md) and we also strongly recommend reading our [Contributing Guide](https://github.com/chaijs/chai/blob/master/CONTRIBUTING.md).\n\nHere are a few issues other contributors frequently ran into when opening pull requests:\n\n- Please do not commit changes to the `chai.js` build. We do it once per release.\n- Before pushing your commits, please make sure you [rebase](https://github.com/chaijs/chai/blob/master/CONTRIBUTING.md#pull-requests) them.\n\n### Contributors\n\nPlease see the full\n[Contributors Graph](https://github.com/chaijs/chai/graphs/contributors) for our\nlist of contributors.\n\n### Core Contributors\n\nFeel free to reach out to any of the core contributors with your questions or\nconcerns. We will do our best to respond in a timely manner.\n\n[![Jake Luer](https://avatars3.githubusercontent.com/u/58988?v=3&s=50)](https://github.com/logicalparadox)\n[![Veselin Todorov](https://avatars3.githubusercontent.com/u/330048?v=3&s=50)](https://github.com/vesln)\n[![Keith Cirkel](https://avatars3.githubusercontent.com/u/118266?v=3&s=50)](https://github.com/keithamus)\n[![Lucas Fernandes da Costa](https://avatars3.githubusercontent.com/u/6868147?v=3&s=50)](https://github.com/lucasfcosta)\n[![Grant Snodgrass](https://avatars3.githubusercontent.com/u/17260989?v=3&s=50)](https://github.com/meeber)\n","maintainers":[{"name":"chaijs","email":"chaijs@keithcirkel.co.uk"},{"name":"chai","email":"chaijs@keithcirkel.co.uk"}],"time":{"modified":"2022-06-13T05:50:44.765Z","created":"2011-12-07T06:53:41.352Z","0.0.1":"2011-12-07T06:53:41.900Z","0.0.2":"2011-12-07T17:00:00.424Z","0.1.0":"2011-12-15T13:08:30.039Z","0.1.1":"2011-12-16T11:59:55.093Z","0.1.2":"2011-12-18T12:39:07.896Z","0.1.3":"2011-12-18T14:07:58.584Z","0.1.4":"2011-12-26T18:19:32.070Z","0.1.5":"2012-01-02T05:52:02.087Z","0.1.6":"2012-01-02T06:14:32.954Z","0.1.7":"2012-01-25T21:38:50.993Z","0.2.0":"2012-01-27T00:18:10.762Z","0.2.1":"2012-01-30T01:27:23.446Z","0.2.2":"2012-02-02T02:58:10.166Z","0.2.3":"2012-02-02T03:04:58.003Z","0.2.4":"2012-02-02T05:56:12.690Z","0.3.0":"2012-02-07T22:00:09.627Z","0.3.1":"2012-02-07T22:35:07.180Z","0.3.2":"2012-02-10T16:39:01.206Z","0.3.3":"2012-02-12T23:07:21.594Z","0.3.4":"2012-02-23T05:09:36.234Z","0.4.0":"2012-02-25T17:19:57.585Z","0.4.1":"2012-02-26T18:09:19.479Z","0.4.2":"2012-02-28T18:00:19.749Z","0.5.0":"2012-03-07T18:05:54.280Z","0.5.1":"2012-03-14T21:02:11.159Z","0.5.2":"2012-03-21T11:16:47.421Z","0.5.3":"2012-04-21T23:05:07.666Z","1.0.0":"2012-05-15T18:36:40.803Z","1.0.1":"2012-05-18T18:26:57.249Z","1.0.2":"2012-05-27T03:39:38.781Z","1.0.3":"2012-05-27T22:19:56.587Z","1.0.4":"2012-06-03T23:29:47.478Z","1.1.0":"2012-06-26T18:32:58.510Z","1.1.1":"2012-07-09T16:49:29.326Z","1.2.0":"2012-08-07T05:08:26.130Z","1.3.0":"2012-10-01T21:32:46.812Z","1.4.0":"2012-11-29T08:26:31.063Z","1.4.1":"2012-12-21T17:55:54.552Z","1.4.2":"2012-12-21T20:15:17.977Z","1.5.0":"2013-02-04T01:47:40.289Z","1.6.0":"2013-04-30T00:16:06.350Z","1.6.1":"2013-06-05T20:48:19.927Z","1.7.0":"2013-06-17T20:07:08.283Z","1.7.1":"2013-06-24T18:52:23.112Z","1.7.2":"2013-06-27T18:16:00.676Z","1.8.0":"2013-09-18T19:05:09.714Z","1.8.1":"2013-10-10T10:47:56.478Z","1.9.0":"2014-01-29T23:39:50.699Z","1.9.1":"2014-03-19T16:22:17.031Z","1.9.2":"2014-09-29T23:25:14.568Z","1.10.0":"2014-11-10T14:06:22.387Z","2.0.0":"2015-02-11T17:37:17.897Z","2.1.0":"2015-02-23T21:46:00.053Z","2.1.1":"2015-03-04T20:29:32.671Z","2.1.2":"2015-03-15T21:45:04.461Z","2.2.0":"2015-03-27T11:19:56.615Z","2.3.0":"2015-04-26T16:25:25.613Z","3.0.0":"2015-06-03T23:30:35.867Z","3.1.0":"2015-07-16T21:42:30.681Z","3.2.0":"2015-07-19T17:05:37.829Z","3.3.0":"2015-09-21T08:59:50.508Z","3.4.0":"2015-10-21T11:28:04.494Z","3.4.1":"2015-11-07T23:24:54.150Z","3.5.0":"2016-01-28T12:05:41.615Z","4.0.0-canary.1":"2016-10-24T22:11:05.481Z","4.0.0-canary.2":"2017-04-17T17:33:16.519Z","4.0.0":"2017-05-26T10:31:36.905Z","4.0.1":"2017-05-31T21:20:26.265Z","4.0.2":"2017-06-05T19:33:48.117Z","4.1.0":"2017-07-12T00:17:10.329Z","4.1.1":"2017-08-05T07:33:06.266Z","4.1.2":"2017-08-31T21:41:39.965Z","4.2.0":"2018-09-26T12:15:22.143Z","4.3.0":"2021-02-04T10:58:07.504Z","4.3.1":"2021-03-02T18:19:37.502Z","4.3.2":"2021-03-03T18:18:33.492Z","4.3.3":"2021-03-03T18:22:10.884Z","4.3.4":"2021-03-12T16:50:44.874Z","4.3.5":"2022-01-25T14:46:31.511Z","4.3.6":"2022-01-26T13:10:56.920Z"},"author":{"name":"Jake Luer","email":"jake@alogicalparadox.com"},"repository":{"type":"git","url":"git+https://github.com/chaijs/chai.git"},"users":{"pwnall":true,"fgribreau":true,"jakeluer":true,"graemef":true,"m42am":true,"vesln":true,"zaphod1984":true,"blalor":true,"codylindley":true,"tmaximini":true,"kubakubula":true,"mpinteractiv":true,"poeticninja":true,"hypergeometric":true,"fiveisprime":true,"blakeembrey":true,"greelgorke":true,"darryl.west":true,"evkline":true,"runningtalus":true,"gdbtek":true,"juriwiens":true,"jbdoumenjou":true,"dizlexik":true,"maschs":true,"henrytseng":true,"yvesm":true,"maratyszcza":true,"bausmeier":true,"t1st3":true,"jits":true,"bkimminich":true,"rsalesc":true,"krisbarrett":true,"sergiodxa":true,"oncletom":true,"byossarian":true,"sasquatch":true,"dgarlitt":true,"mihaiv":true,"heckj":true,"citguy":true,"dimitriwalters":true,"italoacasas":true,"nickl":true,"mahoutsuk.ai":true,"kenlimmj":true,"wangnan0610":true,"stevenvachon":true,"mastayoda":true,"evan2x":true,"pnevares":true,"sahilsk":true,"pensierinmusica":true,"dnunez24":true,"ctd1500":true,"kevbaker":true,"koulmomo":true,"simplyianm":true,"paeblits":true,"lifecube":true,"tfentonz":true,"rsp":true,"mr_eaze":true,"jonatasnona":true,"tomrw":true,"subchen":true,"tzsiga":true,"irnnr":true,"jmelanson-balihoo":true,"gerst20051":true,"clholzin":true,"brentlintner":true,"samhwang1990":true,"jack546":true,"jason0518":true,"isik":true,"dbck":true,"battlemidget":true,"markthethomas":true,"tunght13488":true,"ericmash":true,"sixertoy":true,"feedm3":true,"ash0080":true,"lgvo":true,"jalcine":true,"starver":true,"demoive":true,"sopepos":true,"ridermansb":true,"mjurincic":true,"lherediawoodward":true,"bpatel":true,"chrisyipw":true,"abhisekp":true,"jerkovicl":true,"joelwallis":true,"markstos":true,"zhoutk":true,"kparkov":true,"panlw":true,"phajej":true,"mkoc":true,"liushoukai":true,"alectic":true,"xeoneux":true,"brad-christie":true,"ftornik":true,"vwal":true,"nalindak":true,"cascadejs":true,"antanst":true,"jclo":true,"monkeymonk":true,"bedican":true,"0x4c3p":true,"saravntbe":true,"corintho":true,"rainbow494":true,"arttse":true,"oka-hide":true,"makay":true,"demiurgosoft":true,"jrnail23":true,"cfleschhut":true,"rbartoli":true,"pdedkov":true,"adrien.d":true,"xunnamius":true,"jokja":true,"leodutra":true,"timdp":true,"ismaelvsqz":true,"hyteer":true,"yrocq":true,"shanemileham":true,"highlanderkev":true,"joris-van-der-wel":true,"anaumidis":true,"shipengyan":true,"nexume":true,"apehead":true,"floriannagel":true,"mikemimik":true,"djamseed":true,"ristostevcev":true,"sebastiendaniel":true,"figroc":true,"reamd":true,"erikvold":true,"taodong_wu":true,"loselovegirl":true,"superpaintman":true,"koskokos":true,"guidoschmidt":true,"nomemires":true,"spanser":true,"dac2205":true,"456wyc":true,"shanewholloway":true,"runjinz":true,"emarcs":true,"qmmr":true,"menoncello":true,"clarenceho":true,"pwn":true,"barwin":true,"freebird":true,"princetoad":true,"leejefon":true,"mrbgit":true,"eliaslfox":true,"asm2hex":true,"ajduke":true,"arielfr":true,"slavqa":true,"phgyorgygulyas":true,"drewigg":true,"monjer":true,"luismoramedina":true,"mark24code":true,"schwartzman":true,"james3299":true,"angrykoala":true,"fsgdez":true,"backnight":true,"mluberry":true,"evegreen":true,"razr9":true,"kwhitley":true,"ramzesucr":true,"abuelwafa":true,"pris54":true,"jtrh":true,"mhaidarh":true,"yuguo":true,"aaronforce1":true,"knoja4":true,"quafoo":true,"gilson004":true,"nohomey":true,"rickyrattlesnake":true,"fenrir":true,"jhal81":true,"ivan.marquez":true,"arnemahl":true,"langri-sha":true,"klimnikita":true,"hitalos":true,"largepuma":true,"vmleon":true,"lonjoy":true,"miroklarin":true,"seangenabe":true,"jamesbedont":true,"boopathisakthivel.in":true,"13lank.null":true,"bebeskin":true,"charlietango592":true,"sgvinci":true,"suemcnab":true,"mskjp":true,"drdanryan":true,"rocket0191":true,"junos":true,"goatandsheep":true,"blackrocky":true,"asaupup":true,"augiethornton":true,"1two3code":true,"gpuente":true,"dankle":true,"tsxuehu":true,"heartnett":true,"poslinskinet":true,"damonoverboe":true,"rubiadias":true,"landy2014":true,"ricardogobbosouza":true,"pddivine":true,"danyadsmith":true,"bertof":true,"cedx":true,"rks31":true,"aquafadas":true,"grabantot":true,"kulyk404":true,"lassevolkmann":true,"alek-s":true,"oldfish":true,"shuoshubao":true,"arthur.meyer":true,"rochejul":true,"rdca84":true,"sternelee":true,"rvyshnevskyi":true,"d-band":true,"paulkolesnyk":true,"daniel-lewis-bsc-hons":true,"cooboor":true,"dwqs":true,"cranndarach":true,"whats":true,"iamninad":true,"nuwaio":true,"andrew.oxenburgh":true,"tztz":true,"grin_zhou":true,"tjfwalker":true,"guiyuzhao":true,"tonyetro":true,"buzuli":true,"schacker":true,"sbskl":true,"arniu":true,"leor":true,"piotro83":true,"rubenjose75":true,"danday74":true,"yinfxs":true,"agplan":true,"renishskills":true,"stanleyfok":true,"mdedirudianto":true,"ashco":true,"shroudedcode":true,"alexdreptu":true,"jameskrill":true,"tstam":true,"lqweb":true,"midascreed":true,"losymear":true,"avivharuzi":true,"mgthomas99":true,"instriker":true,"lefthandhacker":true,"vijkris99":true,"naokikimura":true,"amiziara":true,"morogasper":true,"cxftj":true,"karzanosman984":true,"jiangxtx":true,"rioli":true,"mestar":true,"hugovila":true,"mrosata":true,"juanf03":true,"jhillacre":true,"bcowgi11":true,"peveylun":true},"readmeFilename":"README.md","homepage":"http://chaijs.com","keywords":["test","assertion","assert","testing","chai"],"contributors":[{"name":"Jake Luer","email":"jake@alogicalparadox.com"},{"name":"Domenic Denicola","email":"domenic@domenicdenicola.com","url":"http://domenicdenicola.com"},{"name":"Veselin Todorov","email":"hi@vesln.com"},{"name":"John Firebaugh","email":"john.firebaugh@gmail.com"}],"bugs":{"url":"https://github.com/chaijs/chai/issues"},"license":"MIT"} +{ + "name": "chai", + "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", + "dist-tags": { + "latest": "4.3.6" + }, + "versions": { + "4.3.6": { + "author": { + "name": "Jake Luer", + "email": "jake@alogicalparadox.com" + }, + "name": "chai", + "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", + "license": "MIT", + "version": "4.3.6", + "repository": { + "type": "git", + "url": "git+https://github.com/chaijs/chai.git" + }, + "bugs": { + "url": "https://github.com/chaijs/chai/issues" + }, + "main": "./index", + "exports": { + ".": { + "require": "./index.js", + "import": "./index.mjs" + }, + "./*": "./*" + }, + "scripts": { + "test": "make test" + }, + "engines": { + "node": ">=4" + }, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "devDependencies": { + "browserify": "^16.2.3", + "bump-cli": "^1.1.3", + "codecov": "^3.0.0", + "istanbul": "^0.4.3", + "karma": "^6.1.1", + "karma-chrome-launcher": "^2.2.0", + "karma-firefox-launcher": "^1.0.0", + "karma-mocha": "^2.0.1", + "karma-sauce-launcher": "^1.2.0", + "mocha": "^7.1.2" + }, + "gitHead": "529b8b527ba99454471ac67d6aebca9d96cb5dd9", + "_id": "chai@4.3.6", + "_nodeVersion": "17.4.0", + "_npmVersion": "8.3.1", + "dist": { + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "shasum": "ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c", + "tarball": "http://localhost:4260/chai/chai-4.3.6.tgz", + "fileCount": 50, + "unpackedSize": 750564 + }, + "directories": {}, + "_hasShrinkwrap": false + } + }, + "author": { + "name": "Jake Luer", + "email": "jake@alogicalparadox.com" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/chaijs/chai.git" + }, + "readmeFilename": "README.md", + "homepage": "http://chaijs.com", + "bugs": { + "url": "https://github.com/chaijs/chai/issues" + }, + "license": "MIT" +} diff --git a/tests/registry/npm/chalk/registry.json b/tests/registry/npm/chalk/registry.json index d9840b7c47..e148e60fe8 100644 --- a/tests/registry/npm/chalk/registry.json +++ b/tests/registry/npm/chalk/registry.json @@ -1 +1,150 @@ -{"_id":"chalk","_rev":"1184-02c377bc820f688de364ff0c69b7f25f","name":"chalk","description":"Terminal string styling done right","dist-tags":{"latest":"5.0.1","next":"3.0.0-beta.2"},"versions":{"0.1.0":{"name":"chalk","version":"0.1.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.1.0","dist":{"shasum":"69afbee2ffab5e0db239450767a6125cbea50fa2","tarball":"http://localhost:4260/chalk/chalk-0.1.0.tgz","integrity":"sha512-E1+My+HBCBHA6fBUZlbPnrOMrGKnc3QAXGEvCk/lpEG/ZKowZFg01dXt6RCYJMvTWYgxHWTyZQ6qkCrVPKJ2YQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICcizJ0CViMVIGAdOi/w9z8s5d3Zn23t9fMlbuGpzGENAiB4IAPyJ4DSwN/KaA6WIkJE7cqo3iZiTLD1ClLbpbCEiQ=="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.1.1":{"name":"chalk","version":"0.1.1","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.1.1","dist":{"shasum":"fe6d90ae2c270424720c87ed92d36490b7d36ea0","tarball":"http://localhost:4260/chalk/chalk-0.1.1.tgz","integrity":"sha512-NJbznmWlxmS5Co0rrLJYO0U3QW6IzWw2EuojeOFn4e8nD1CYR5Ie60CEEmHrF8DXtfd83pdF0xYWVCXbRysrDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyRcBiBgR63thSUFHx+SV7hi4FtDRy5WNaeEfCEr6c6wIhAJbSSa3GwYNrT0RVe6AVJcvtXcjsOVg7yTdLVbxlzfK7"}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.2.0":{"name":"chalk","version":"0.2.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.2.0","dist":{"shasum":"47270e80edce0e219911af65479d17db525ff5db","tarball":"http://localhost:4260/chalk/chalk-0.2.0.tgz","integrity":"sha512-CHq4xplBE+jhsJKGmh8AegFpEsC84kQNPMeL2mjrD5ojPc1LqNV1q5opCBU7BcRxWbpX+S8s+q4LFaqjP1rZmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfcM6X1OG63W5oEByNa/SCZJWAU3mNjL4zY35I5yHbGwIgNPIUWRFZl6a3ByWBLR4cXyn2WHnYru0PY39fougSJzQ="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.2.1":{"name":"chalk","version":"0.2.1","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.2.1","dist":{"shasum":"7613e1575145b21386483f7f485aa5ffa8cbd10c","tarball":"http://localhost:4260/chalk/chalk-0.2.1.tgz","integrity":"sha512-nmVapomwGksziCuynboy7I+dtW4ytIdqXPlrfY/ySx8l8EqFRGHyA04q6NMNpOri8XliGUGwXyfScVl48zFHbw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBda89bi2LZLymi7dToSY9rMAFRCXyg6fqyF15yoQO0tAiAT1ZyRicgVCJku8vgl5CUqx27uRUEnRK1GZ2kowTHh4g=="}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.3.0":{"name":"chalk","version":"0.3.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.3.0","dist":{"shasum":"1c98437737f1199ebcc1d4c48fd41b9f9c8e8f23","tarball":"http://localhost:4260/chalk/chalk-0.3.0.tgz","integrity":"sha512-OcfgS16PHpCu2Q4TNMtk0aZNx8PyeNiiB+6AgGH91fhT9hJ3v6pIIJ3lxlaOEDHlTm8t3wDe6bDGamvtIokQTg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/TMCMMPNIkr1dvG6kRR/CWZZJtqKGoMdimY4IY6MEsgIhAJ1HbZkkcygfBmN1N4nqpYpBdAbRlLQOQoHfhOmBxYT1"}]},"_from":".","_npmVersion":"1.3.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.4.0":{"name":"chalk","version":"0.4.0","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"has-color":"~0.1.0","ansi-styles":"~1.0.0","strip-ansi":"~0.1.0"},"devDependencies":{"mocha":"~1.x"},"bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.4.0","dist":{"shasum":"5199a3ddcd0c1efe23bc08c1b027b06176e0c64f","tarball":"http://localhost:4260/chalk/chalk-0.4.0.tgz","integrity":"sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBe296G5Ckfk2TKZTU3bGX1WzY2zO0oXe5yCT2EecEajAiABeRfWovOVYu9t02fFT3Pnrbreb2qwOUoA6c16yVmoUA=="}]},"_from":".","_npmVersion":"1.3.17","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.5.0":{"name":"chalk","version":"0.5.0","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^1.1.0","escape-string-regexp":"^1.0.0","has-ansi":"^0.1.0","strip-ansi":"^0.3.0","supports-color":"^0.2.0"},"devDependencies":{"matcha":"^0.5.0","mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.5.0","_shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","tarball":"http://localhost:4260/chalk/chalk-0.5.0.tgz","integrity":"sha512-rTCcbF0wrwC+kKzA/3SpBc6PrcOx/+PRQVtS3PEDw5tGzqycpB48dRS8ByxFDd8Ij5E1RtafZ34R1X9VLI/vUQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEGqQOniqI9HsAKeDEvFr1KDB3AZGGcdwYu4q0ylIHtUAiA65kQmXrb1YvhBtaJjhFQBrt7C9MIZfOOBOrg8SOziBA=="}]},"directories":{}},"0.5.1":{"name":"chalk","version":"0.5.1","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^1.1.0","escape-string-regexp":"^1.0.0","has-ansi":"^0.1.0","strip-ansi":"^0.3.0","supports-color":"^0.2.0"},"devDependencies":{"matcha":"^0.5.0","mocha":"*"},"gitHead":"994758f01293f1fdcf63282e9917cb9f2cfbdaac","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.5.1","_shasum":"663b3a648b68b55d04690d49167aa837858f2174","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"663b3a648b68b55d04690d49167aa837858f2174","tarball":"http://localhost:4260/chalk/chalk-0.5.1.tgz","integrity":"sha512-bIKA54hP8iZhyDT81TOsJiQvR1gW+ZYSXFaZUAvoD4wCHdbHY2actmpTE4x344ZlFqHbvoxKOaESULTZN2gstg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHm4uVj8/eT3R7g1Q6tzTAMZ2pdqmG9OumNXatGp4ykfAiEAqiq/PLZqnD8UaVvvHh3ElJAhsquDcnDKTEjLo6bZyNY="}]},"directories":{}},"1.0.0":{"name":"chalk","version":"1.0.0","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.0.1","escape-string-regexp":"^1.0.2","has-ansi":"^1.0.3","strip-ansi":"^2.0.1","supports-color":"^1.3.0"},"devDependencies":{"matcha":"^0.6.0","mocha":"*"},"gitHead":"8864d3563313ed15574a38dd5c9d5966080c46ce","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@1.0.0","_shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","tarball":"http://localhost:4260/chalk/chalk-1.0.0.tgz","integrity":"sha512-1TE3hpADga5iWinlcCpyhC7fTl9uQumLD8i2jJoJeVg7UbveY5jj7F6uCq8w0hQpSeLhaPn5QFe8e56toMVP1A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA2fHIK4HaMM5vT8+vgIZDSYl2yR1wBMDpQnyK2mEp73AiBv9R+hCSU6L2lKmjPk37XVGjJaJPMWSPFUT6HNBGXJJg=="}]},"directories":{}},"1.1.0":{"name":"chalk","version":"1.1.0","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"https://github.com/chalk/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.1.0","escape-string-regexp":"^1.0.2","has-ansi":"^2.0.0","strip-ansi":"^3.0.0","supports-color":"^2.0.0"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3"},"gitHead":"e9bb6e6000b1c5d4508afabfdc85dd70f582f515","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk","_id":"chalk@1.1.0","_shasum":"09b453cec497a75520e4a60ae48214a8700e0921","_from":".","_npmVersion":"2.10.1","_nodeVersion":"0.12.4","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"09b453cec497a75520e4a60ae48214a8700e0921","tarball":"http://localhost:4260/chalk/chalk-1.1.0.tgz","integrity":"sha512-pn7bzDYUIrL0KRp/KK5B+sej6uYtzQ5hYOdLU+L3MVWHCgoYi4aUYdh2/R2rsdURIoOK/ptZi5FDtLdjvKYQ7g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDvFUAscqbO0W1o8ynaLsS3H/qRFyNIcBpeciwTE0L2eAIhAJLC4kNijQLiP53FxwjKtIk/yb2Mz5bSJkvQcbmO38Lh"}]},"directories":{}},"1.1.1":{"name":"chalk","version":"1.1.1","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.1.0","escape-string-regexp":"^1.0.2","has-ansi":"^2.0.0","strip-ansi":"^3.0.0","supports-color":"^2.0.0"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"8b554e254e89c85c1fd04dcc444beeb15824e1a5","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.1","_shasum":"509afb67066e7499f7eb3535c77445772ae2d019","_from":".","_npmVersion":"2.13.5","_nodeVersion":"0.12.7","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"509afb67066e7499f7eb3535c77445772ae2d019","tarball":"http://localhost:4260/chalk/chalk-1.1.1.tgz","integrity":"sha512-W10W+QfIxJlTm3VRtg8eafwUBkDfUPFvRvPv4jCD9vF4+HzlAyXJ7P3Y5yw/r+gJ1TzFEU6oFqMgp1dIVpYr0A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJnOp0QV+THZBj97NAJIJ/7FOfH1ApR+V17cduIWef4QIgKx6kVG0zABWS4/A8EyL/AV5PuxB8aCmy9tNSXcFiXa8="}]},"directories":{}},"1.1.2":{"name":"chalk","version":"1.1.2","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.2.1","escape-string-regexp":"^1.0.2","supports-color":"^3.1.2"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^5.2.0","require-uncached":"^1.0.2","resolve-from":"^2.0.0","semver":"^5.1.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"a838948dcbf2674dd28adfbb78e791900ae741e9","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.2","_shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","_from":".","_npmVersion":"2.14.2","_nodeVersion":"0.10.32","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","tarball":"http://localhost:4260/chalk/chalk-1.1.2.tgz","integrity":"sha512-QBKX51aavmpKcCkgrJXhjS5b3rCgH2Wn99BYqUV2H1FjTP7Mm4KTcskSxuKrfhQKt69mBn9jH4Kb2xnchvEaOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDR73JAj03sZJRAoJDQVm+RirI4Iry8ZuCvjsoI7cTA4wIhAOjIHdQPS2bXbYZucSmdnq17cnoYJ4fHFrpbk9slQEst"}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/chalk-1.1.2.tgz_1459207923607_0.6091341155115515"},"deprecated":"chalk@1.1.2 introduces breaking changes. Please use 1.1.3 or above.","directories":{}},"1.1.3":{"name":"chalk","version":"1.1.3","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"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"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"0d8d8c204eb87a4038219131ad4d8369c9f59d24","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.3","_shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","_from":".","_npmVersion":"2.14.2","_nodeVersion":"0.10.32","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","tarball":"http://localhost:4260/chalk/chalk-1.1.3.tgz","integrity":"sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYydQMZbUiHhEF1lG6Vvl8dFiZehECOS8naCRKiBaDWAIhAMB+3sTOs5gMFmQyiUE6HzXaIsahGhReBUr4OYaI+iCX"}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/chalk-1.1.3.tgz_1459210604109_0.3892582862172276"},"directories":{}},"2.0.0":{"name":"chalk","version":"2.0.0","description":"Terminal string styling done right. Much color","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"coveralls":"^2.11.2","import-fresh":"^2.0.0","matcha":"^0.7.0","mocha":"*","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"3fca6150e23439e783409f5c8f948f767c2ddc5a","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.0.0","_npmVersion":"5.0.0","_nodeVersion":"8.0.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-7jy/5E6bVCRhLlvznnsbVPjsARuVC9HDkBjUKVaOmUrhsp6P3ExUUcW09htM7/qieRH+D2lHVpNbuYh7GjVJ0g==","shasum":"c25c5b823fedff921aa5d83da3ecb5392e84e533","tarball":"http://localhost:4260/chalk/chalk-2.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHTAVf6u8jvZCfxvAN3anX5/E4q4xlYfkCEkZENhrWYbAiBLQg/CjJ1n1peDolmlJB8V892hSsvTW1L1zOl0qA1IHA=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.0.0.tgz_1498780161964_0.21432337583974004"},"directories":{}},"2.0.1":{"name":"chalk","version":"2.0.1","description":"Terminal string styling done right. Much color","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"coveralls":"^2.11.2","import-fresh":"^2.0.0","matcha":"^0.7.0","mocha":"*","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"5827081719944a2f903b52a88baeec1ec8581f82","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.0.1","_npmVersion":"5.0.0","_nodeVersion":"8.0.0","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==","shasum":"dbec49436d2ae15f536114e76d14656cdbc0f44d","tarball":"http://localhost:4260/chalk/chalk-2.0.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICfJZUefrwq1SvzsgOv2Q/7HhKkcNRqOTzI/P/PsGm7dAiAVHrhAfBt0v3Bjqycj4E95pSguOX6OdYQeIElUAHjbvA=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.0.1.tgz_1498793206623_0.8611406192649156"},"deprecated":"Please upgrade to Chalk 2.1.0 - template literals in this version (2.0.1) are quite buggy.","directories":{}},"2.1.0":{"name":"chalk","version":"2.1.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^2.11.2","execa":"^0.7.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"38f641a222d7ee0e607e4e5209d3931d2af1e409","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.1.0","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==","shasum":"ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e","tarball":"http://localhost:4260/chalk/chalk-2.1.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAR2pBNunhcCtIpoVtR8CzUr4fkHHazxHsUmYiEOl3SyAiAj1UgZ9m1qQjHPwS0lWc7+x71FyiJ9BnT8LKzU8hZpaA=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.1.0.tgz_1502078203099_0.6595528507605195"},"directories":{}},"2.2.0":{"name":"chalk","version":"2.2.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"d86db88e778fa856f4d6f5f68c588750ca06b822","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.2.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==","shasum":"477b3bf2f9b8fd5ca9e429747e37f724ee7af240","tarball":"http://localhost:4260/chalk/chalk-2.2.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJ26ChsXMgEr8DGfcdGhwoECmCJIQc8C/WtfNNghWXpwIhALxt4sAYIddaWoA+laUzI/bv5TtudGNeOLEa+lB3iTKA"}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.2.0.tgz_1508296541817_0.8590951061341912"},"directories":{}},"2.2.2":{"name":"chalk","version":"2.2.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"e1177ec3628f6d0d37489c1e1accd2c389a376a8","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.2.2","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==","shasum":"4403f5cf18f35c05f51fbdf152bf588f956cf7cb","tarball":"http://localhost:4260/chalk/chalk-2.2.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfa8X3hU20LXJII/tFJYOtrI+If9MXC6lVP2kVo2TeagIhAJTH6/ofItVCqYxnT7cTqmAxRF8XTpQFWlvUr/dLjfi+"}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.2.2.tgz_1508815246099_0.3707860491704196"},"directories":{}},"2.3.0":{"name":"chalk","version":"2.3.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"14e0aa97727019b22f0a003fdc631aeec5e2e24c","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==","shasum":"b5ea48efc9c1793dccc9b4767c93914d3f2d52ba","tarball":"http://localhost:4260/chalk/chalk-2.3.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmt7XnAO8uN79Qxpb8HhB5EzqXR5F9Xz+dizDO68VggQIhAPCzW1TPRUP1vXrzImjrGiRQFFXTq6uWu8l+3dlLRyJm"}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.3.0.tgz_1508818375657_0.9021007190458477"},"directories":{}},"2.3.1":{"name":"chalk","version":"2.3.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.0","escape-string-regexp":"^1.0.5","supports-color":"^5.2.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"ae8a03f2c5c49896adeb3dd4ec5350e4ab9449a2","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==","shasum":"523fe2678aec7b04e8041909292fe8b17059b796","tarball":"http://localhost:4260/chalk/chalk-2.3.1.tgz","fileCount":6,"unpackedSize":24721,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDq923pbuma8n5CHp1BmZnEpfSBznm9pjEsnO89V1Fd1QIgPAoDos2IHJA/kzqVf2mD25YwAbgXJ4YOKduTvo92f94="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.3.1_1518355108425_0.3816906865374552"},"_hasShrinkwrap":false},"2.3.2":{"name":"chalk","version":"2.3.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"84f27d4bd86f7f482a32652ae536cd996ad204bd","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==","shasum":"250dc96b07491bfd601e648d66ddf5f60c7a5c65","tarball":"http://localhost:4260/chalk/chalk-2.3.2.tgz","fileCount":6,"unpackedSize":24713,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGrPWo1zy8RefMcSH+1wPT00s3HsqCjGvfnnE3kKN0BMAiA90/5NkYnkzLmda2udxxQfLxRPdxx1Gf9nafuAeaTxrA=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.3.2_1520012630405_0.9222977073145247"},"_hasShrinkwrap":false},"2.4.0":{"name":"chalk","version":"2.4.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"af8b3657e96a0a6ca5190fb0d0a1345797148320","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.0","_npmVersion":"5.6.0","_nodeVersion":"8.10.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==","shasum":"a060a297a6b57e15b61ca63ce84995daa0fe6e52","tarball":"http://localhost:4260/chalk/chalk-2.4.0.tgz","fileCount":7,"unpackedSize":27005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1Xf3CRA9TVsSAnZWagAA1DcP/2EhxWse6mGwicTqM2U5\nQl2Xol74cFmd6b4nCGZnGycgatfJtyhb1YoH/vL3uNqGFrQGBwAr4GoZxhGd\n7kL0xKWnfhGHFeUe//fSCklj4Aff700RteXornlDFxbK5jVELyYcXfG5xJ5i\ncAIuPb9YYXltdaSfvVcg49qIPcjRfZm5Wz8WxTaUAyD5Ag4lpWKVTgWZsU+c\nEKRQHu+UmpX2OsudafT6GL3ak7GE2+ysH1b0HcYVuf1Wdf39un+E0MXDs58C\nTLCZSASN99/KCEpjh8aa4YdXVU3x0rdf50KdKDBUMF3b6HnSfWqOS+OWZRFZ\nC0jvk58j4vmXCVb2puQI8HIuZXBlNeS59GaN3hB3rz7JMgrQC/LXycOU1x+5\nuKEKupRkkVsSRyAEUdHqx6dwkcm+TVGPnXjUMdYREL9VkyY9eB7lBYTEzH9I\nZN9H3JXrjo/dGVmFL6q+L7lCxLFsl1p+UCMxubUE9XV6C/QN4mQmiwIAwn04\nhJH1RFIFTHszVEUnAJMZ6SqRRJes5iSedAMyiUYi+1S86uQenyUqtIJbHsNO\n7+G3Jnfdw9e1+YMvk53PSJcdtt5ayOx7ezc0HLS5HD9g3bXhMbbxTupHOSAv\nVCiEoaKAmjJK7nbStTqrX3xjz85K+lNHZdKkIzPWX5TkEg8KMSGK3LxfXG8B\n+CuC\r\n=orOi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHWaTr0kn5hhbrdU9rauwwyPdBW6TxZnI4Lc23AJQgTCAiBJcOQo3Y7yHbfSuuL++TjazCour+dgSoT3qw/rRcCHgg=="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.0_1523939317754_0.3039215958746819"},"_hasShrinkwrap":false},"2.4.1":{"name":"chalk","version":"2.4.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"48ba5b0b9beadcabd9fc406ac4d9337d8fa6b36d","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==","shasum":"18c49ab16a037b6eb0152cc83e3471338215b66e","tarball":"http://localhost:4260/chalk/chalk-2.4.1.tgz","fileCount":7,"unpackedSize":26917,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4WCICRA9TVsSAnZWagAAhgwP/2M/ItinhR06BFhLMh91\nK/ru5t71NzSzoEvI2nh4W57Wk9cU1NOYi1cI17nUvICHCL4Vq9mjvU0hajTw\ncAYtM0Lwl+G4Hk4JtuiZITYj93QY3yLSJ8zkj95JznFbH0Zd9KkZrkoGukcG\nFY9at0cfNyhBmwi5sEDAFktcw7wThQ6Wy3iIttQ0N1M6Lf1XILg9Xyq6Id/W\nlz3TbkCt6AZCS1icmDPIiLdVQuD9SfpusIDsHm5/6FJPShwmQjUlM6Kdy7lx\n6M8uhcIknpxjfPTA6/aSBC4qgXnDhuPPi9xF657/81Mswz4Tb71KOf6UqLPi\n3zk1D5PF71ujWs3wmPll9TAVGnWuNzE+X/7GVIB4qCrib3SgvRzMhL0Wo95v\nzxTpNoD23hKYwofUyV3cTFh47YwkVoPtOStRAgdE87rx+v3VjbWSThQJc3V8\nHOsIeTjpQMwAr/d2DnasHKlps/q+gnGKqhBhcf11tAKn9C7PsAQ2l6+E4Erc\nfPKqDRC6TVG7ABdwOtyNonHhrJ2JLgYj8d4mHdtsMTtFsUTOQR/+Rx0V8HJS\n9gBLmPr3yc/yEedYW68wP5tPK2SfvFTzgMBw5v0+tgIxOjUunGxDUV4a1Bpp\npCBLN7iS77FLMiMonfcD2z/SsoB+Hb+7q5eT/gua3BIUNNZEdmgw9queXw+q\n7DFE\r\n=LSlF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTy37ycwX7bqoO0WDu7AVubgfxDHR/7neyxoLzwx8dIwIgJxP4QEC0TbUnC9iBA3w36fy7kAAd1tHPSQZtkZ1yOrA="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.1_1524719751701_0.7780175911150953"},"_hasShrinkwrap":false},"2.4.2":{"name":"chalk","version":"2.4.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"9776a2ae5b5b1712ccf16416b55f47e575a81fb9","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.2","_npmVersion":"6.5.0","_nodeVersion":"10.13.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==","shasum":"cd42541677a54333cf541a49108c1432b44c9424","tarball":"http://localhost:4260/chalk/chalk-2.4.2.tgz","fileCount":7,"unpackedSize":26924,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMNEwCRA9TVsSAnZWagAAmpUQAJgCZygaBX9qniyJ7YVF\nOXq9BNycBSnHyRd5YnaoO6HB7ejh/M4CYYGPqdSQ0OXEk1teNm7iPhGhocbW\n0eEcg0gsnVTgkUKx5p3o841VKydwy72FDgO9WJjKm2QC/mwuYHB9kI7zkq3h\nkakWBNGlKxbKNYX+7x04BXx1H8Fn1CSE//133uQnUWzM6NSXrUwpiZTzwtXi\nOybESujfKq6x6DxlYsTTScThCUodQQTslxIrdeS8PZxQL1RqCwnJSMHi81nI\nPR5BNVbAEYOsZuw88mNEtc6sHellN3ZFVlZwFDu4ZDskgoMiXZVv7Qp6AXbN\nCdsz1ej/OBFdwUfjS17igoHY3sO3+7o3IuFFaCXM4lkSE2zu79M2A7H0GL0R\nUcyfM1OC/nRcLgeEytIDBSOAgeN4tstswdyagFQ36jymeKUyz+q50ziBchey\nZnxPMGYDMKTx+me3TGpf3SbjiSstyZm8GLWPhRLbkjIDajFcFnq2HZXUu/LR\npdFJIWqnJihr9dxxiPSxddqZspb/Jo2mD2+ILNxROZB5+nzmlLnV/PsnnbxM\nPRN0iYDQt6NtXce/GOFMasLwtwidfHx8B4ybmObU3btbmg7V7Og++xpVg+h1\nQfACtop8sZyVN3l65vhonCmioqpSLQPeEkMvwGN6/7wi01BRi5VI4DdEtIet\nHcNL\r\n=DerQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHxDV26xkYTdx1T+EBh6zvEaa602qK7hNWXvOTB1yr5UAiEAqSxYcAo+BSotxMY2GjH1e25JFKt2I+5D19gPFGbdghE="}]},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.2_1546703152138_0.5501232329596948"},"_hasShrinkwrap":false},"3.0.0-beta.1":{"name":"chalk","version":"3.0.0-beta.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"main":"source","engines":{"node":">=8"},"scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"devDependencies":{"ava":"^2.4.0","coveralls":"^3.0.5","execa":"^2.0.3","import-fresh":"^3.1.0","matcha":"^0.7.0","nyc":"^14.1.1","resolve-from":"^5.0.0","tsd":"^0.7.4","xo":"^0.25.3"},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/prefer-includes":"off"}},"readme":"

\n\t
\n\t
\n\t\"Chalk\"\n\t
\n\t
\n\t
\n

\n\n> Terminal string styling done right\n\n[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg)\n\n\n\n**This readme reflects the next major version that is currently in development. You probably want [the v2 readme](https://www.npmjs.com/package/chalk).**\n\n\n## Highlights\n\n- Expressive API\n- Highly performant\n- Ability to nest styles\n- [256/Truecolor color support](#256-and-truecolor-color-support)\n- Auto-detects color support\n- Doesn't extend `String.prototype`\n- Clean and focused\n- Actively maintained\n- [Used by ~46,000 packages](https://www.npmjs.com/browse/depended/chalk) as of October 1, 2019\n\n\n## Install\n\n```console\n$ npm install chalk\n```\n\n\n## Usage\n\n```js\nconst chalk = require('chalk');\n\nconsole.log(chalk.blue('Hello world!'));\n```\n\nChalk comes with an easy to use composable API where you just chain and nest the styles you want.\n\n```js\nconst chalk = require('chalk');\nconst log = console.log;\n\n// Combine styled and normal strings\nlog(chalk.blue('Hello') + ' World' + chalk.red('!'));\n\n// Compose multiple styles using the chainable API\nlog(chalk.blue.bgRed.bold('Hello world!'));\n\n// Pass in multiple arguments\nlog(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));\n\n// Nest styles\nlog(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));\n\n// Nest styles of the same type even (color, underline, background)\nlog(chalk.green(\n\t'I am a green line ' +\n\tchalk.blue.underline.bold('with a blue substring') +\n\t' that becomes green again!'\n));\n\n// ES2015 template literal\nlog(`\nCPU: ${chalk.red('90%')}\nRAM: ${chalk.green('40%')}\nDISK: ${chalk.yellow('70%')}\n`);\n\n// ES2015 tagged template literal\nlog(chalk`\nCPU: {red ${cpu.totalPercent}%}\nRAM: {green ${ram.used / ram.total * 100}%}\nDISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}\n`);\n\n// Use RGB colors in terminal emulators that support it.\nlog(chalk.keyword('orange')('Yay for orange colored text!'));\nlog(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));\nlog(chalk.hex('#DEADED').bold('Bold gray!'));\n```\n\nEasily define your own themes:\n\n```js\nconst chalk = require('chalk');\n\nconst error = chalk.bold.red;\nconst warning = chalk.keyword('orange');\n\nconsole.log(error('Error!'));\nconsole.log(warning('Warning!'));\n```\n\nTake advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):\n\n```js\nconst name = 'Sindre';\nconsole.log(chalk.green('Hello %s'), name);\n//=> 'Hello Sindre'\n```\n\n\n## API\n\n### chalk.` \ No newline at end of file diff --git a/tests/specs/fmt/css/__test__.jsonc b/tests/specs/fmt/css/__test__.jsonc new file mode 100644 index 0000000000..a3ded6d431 --- /dev/null +++ b/tests/specs/fmt/css/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "tests": { + "badly_formatted": { + "args": "fmt badly_formatted.css", + "output": "[WILDLINE]badly_formatted.css\nChecked 1 file\n" + }, + "well_formatted": { + "args": "fmt --check well_formatted.css", + "output": "Checked 1 file\n" + } + } +} diff --git a/tests/specs/fmt/unstable_css/badly_formatted.css b/tests/specs/fmt/css/badly_formatted.css similarity index 100% rename from tests/specs/fmt/unstable_css/badly_formatted.css rename to tests/specs/fmt/css/badly_formatted.css diff --git a/tests/specs/fmt/css/well_formatted.css b/tests/specs/fmt/css/well_formatted.css new file mode 100644 index 0000000000..1653551f47 --- /dev/null +++ b/tests/specs/fmt/css/well_formatted.css @@ -0,0 +1,3 @@ +#app > .btn { + color: #000; +} diff --git a/tests/specs/fmt/default_ts/__test__.jsonc b/tests/specs/fmt/default_ts/__test__.jsonc new file mode 100644 index 0000000000..39772f5f80 --- /dev/null +++ b/tests/specs/fmt/default_ts/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "tests": { + "stdin": { + "args": "fmt -", + "input": "const x: string = \"foo\";", + "output": "const x: string = \"foo\";\n" + }, + "ext_flag": { + "args": "fmt --ext=ts as_ts.js", + "output": "Checked 1 file\n" + }, + "extensionless": { + "args": "fmt extensionless", + "output": "error: No target files found.\n", + "exitCode": 1 + }, + "extensionless_with_flag": { + "args": "fmt --ext=ts extensionless", + "output": "Checked 1 file\n" + } + } +} diff --git a/tests/specs/fmt/default_ts/as_ts.js b/tests/specs/fmt/default_ts/as_ts.js new file mode 100644 index 0000000000..72a35c2a88 --- /dev/null +++ b/tests/specs/fmt/default_ts/as_ts.js @@ -0,0 +1 @@ +const x: string = "foo"; diff --git a/tests/specs/fmt/default_ts/extensionless b/tests/specs/fmt/default_ts/extensionless new file mode 100644 index 0000000000..72a35c2a88 --- /dev/null +++ b/tests/specs/fmt/default_ts/extensionless @@ -0,0 +1 @@ +const x: string = "foo"; diff --git a/tests/specs/fmt/html/__test__.jsonc b/tests/specs/fmt/html/__test__.jsonc new file mode 100644 index 0000000000..2e6d08d4cc --- /dev/null +++ b/tests/specs/fmt/html/__test__.jsonc @@ -0,0 +1,17 @@ +{ + "tempDir": true, + "tests": { + "badly_formatted": { + "args": "fmt badly_formatted.html", + "output": "[WILDLINE]badly_formatted.html\nChecked 1 file\n" + }, + "well_formatted": { + "args": "fmt --check well_formatted.html", + "output": "Checked 1 file\n" + }, + "broken": { + "args": "fmt broken.html", + "output": "broken.out" + } + } +} diff --git a/tests/specs/fmt/unstable_html/badly_formatted.html b/tests/specs/fmt/html/badly_formatted.html similarity index 100% rename from tests/specs/fmt/unstable_html/badly_formatted.html rename to tests/specs/fmt/html/badly_formatted.html diff --git a/tests/specs/fmt/html/broken.html b/tests/specs/fmt/html/broken.html new file mode 100644 index 0000000000..a579b78724 --- /dev/null +++ b/tests/specs/fmt/html/broken.html @@ -0,0 +1,2 @@ +
content + diff --git a/tests/specs/fmt/html/broken.out b/tests/specs/fmt/html/broken.out new file mode 100644 index 0000000000..05021a1973 --- /dev/null +++ b/tests/specs/fmt/html/broken.out @@ -0,0 +1,4 @@ +Error formatting: [WILDCARD]broken.html + Syntax error (expected close tag) at file://[WILDCARD]broken.html:3:0 + +Checked 1 file diff --git a/tests/specs/fmt/html/well_formatted.html b/tests/specs/fmt/html/well_formatted.html new file mode 100644 index 0000000000..c0c06cd9bd --- /dev/null +++ b/tests/specs/fmt/html/well_formatted.html @@ -0,0 +1,11 @@ +
content
+ + + + diff --git a/tests/specs/fmt/njk/__test__.jsonc b/tests/specs/fmt/njk/__test__.jsonc new file mode 100644 index 0000000000..8b6bc87d47 --- /dev/null +++ b/tests/specs/fmt/njk/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "fmt --unstable-component", + "output": "[WILDLINE]badly_formatted.njk\nChecked 1 file\n" +} \ No newline at end of file diff --git a/tests/specs/fmt/njk/badly_formatted.njk b/tests/specs/fmt/njk/badly_formatted.njk new file mode 100644 index 0000000000..71b0578d15 --- /dev/null +++ b/tests/specs/fmt/njk/badly_formatted.njk @@ -0,0 +1,3 @@ +

{{ "Hello, world!" | upper }} +

+ diff --git a/tests/specs/fmt/unstable_component/__test__.jsonc b/tests/specs/fmt/unstable_component/__test__.jsonc index a8f8697da6..36057cbefa 100644 --- a/tests/specs/fmt/unstable_component/__test__.jsonc +++ b/tests/specs/fmt/unstable_component/__test__.jsonc @@ -6,14 +6,14 @@ "output": "Checked 1 file\n" }, "flag": { - "args": "fmt --unstable-css --unstable-component", + "args": "fmt --unstable-component", "output": "[WILDLINE]badly_formatted.svelte\nChecked 1 file\n" }, "config_file": { "steps": [{ "args": [ "eval", - "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-css\", \"fmt-component\"]\\n}\\n')" + "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-component\"]\\n}\\n')" ], "output": "[WILDCARD]" }, { diff --git a/tests/specs/fmt/unstable_css/__test__.jsonc b/tests/specs/fmt/unstable_css/__test__.jsonc deleted file mode 100644 index 32259f3ae4..0000000000 --- a/tests/specs/fmt/unstable_css/__test__.jsonc +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tempDir": true, - "tests": { - "nothing": { - "args": "fmt", - "output": "Checked 1 file\n" - }, - "flag": { - "args": "fmt --unstable-css", - "output": "[WILDLINE]badly_formatted.css\nChecked 1 file\n" - }, - "config_file": { - "steps": [{ - "args": [ - "eval", - "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-css\"]\\n}\\n')" - ], - "output": "[WILDCARD]" - }, { - "args": "fmt", - "output": "[WILDLINE]badly_formatted.css\nChecked 2 files\n" - }] - } - } -} diff --git a/tests/specs/fmt/unstable_html/__test__.jsonc b/tests/specs/fmt/unstable_html/__test__.jsonc deleted file mode 100644 index 2394805ade..0000000000 --- a/tests/specs/fmt/unstable_html/__test__.jsonc +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tempDir": true, - "tests": { - "nothing": { - "args": "fmt", - "output": "Checked 1 file\n" - }, - "flag": { - "args": "fmt --unstable-css --unstable-html", - "output": "[WILDLINE]badly_formatted.html\nChecked 1 file\n" - }, - "config_file": { - "steps": [{ - "args": [ - "eval", - "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-css\", \"fmt-html\"]\\n}\\n')" - ], - "output": "[WILDCARD]" - }, { - "args": "fmt", - "output": "[WILDLINE]badly_formatted.html\nChecked 2 files\n" - }] - } - } -} diff --git a/tests/specs/fmt/unstable_yaml/__test__.jsonc b/tests/specs/fmt/unstable_yaml/__test__.jsonc deleted file mode 100644 index 885db59b98..0000000000 --- a/tests/specs/fmt/unstable_yaml/__test__.jsonc +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tempDir": true, - "tests": { - "nothing": { - "args": "fmt", - "output": "Checked 1 file\n" - }, - "flag": { - "args": "fmt --unstable-yaml", - "output": "[WILDLINE]badly_formatted.yml\nChecked 1 file\n" - }, - "config_file": { - "steps": [{ - "args": [ - "eval", - "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-yaml\"]\\n}\\n')" - ], - "output": "[WILDCARD]" - }, { - "args": "fmt", - "output": "[WILDLINE]badly_formatted.yml\nChecked 2 files\n" - }] - } - } -} \ No newline at end of file diff --git a/tests/specs/fmt/vento/__test__.jsonc b/tests/specs/fmt/vento/__test__.jsonc new file mode 100644 index 0000000000..c3e3bbf7d1 --- /dev/null +++ b/tests/specs/fmt/vento/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "fmt --unstable-component", + "output": "[WILDLINE]badly_formatted.vto\nChecked 1 file\n" +} \ No newline at end of file diff --git a/tests/specs/fmt/vento/badly_formatted.vto b/tests/specs/fmt/vento/badly_formatted.vto new file mode 100644 index 0000000000..ad46443904 --- /dev/null +++ b/tests/specs/fmt/vento/badly_formatted.vto @@ -0,0 +1,3 @@ +

{{ "Hello, world!" |> toUpperCase }} +

+ diff --git a/tests/specs/fmt/yaml/__test__.jsonc b/tests/specs/fmt/yaml/__test__.jsonc new file mode 100644 index 0000000000..499b4144b7 --- /dev/null +++ b/tests/specs/fmt/yaml/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "tests": { + "badly_formatted": { + "args": "fmt badly_formatted.yml", + "output": "[WILDLINE]badly_formatted.yml\nChecked 1 file\n" + }, + "well_formatted": { + "args": "fmt --check well_formatted.yml", + "output": "Checked 1 file\n" + } + } +} diff --git a/tests/specs/fmt/unstable_yaml/badly_formatted.yml b/tests/specs/fmt/yaml/badly_formatted.yml similarity index 100% rename from tests/specs/fmt/unstable_yaml/badly_formatted.yml rename to tests/specs/fmt/yaml/badly_formatted.yml diff --git a/tests/specs/fmt/yaml/well_formatted.yml b/tests/specs/fmt/yaml/well_formatted.yml new file mode 100644 index 0000000000..016e0b9510 --- /dev/null +++ b/tests/specs/fmt/yaml/well_formatted.yml @@ -0,0 +1,3 @@ +- Test +- Test +- Test diff --git a/tests/specs/future/import_assertions/__test__.jsonc b/tests/specs/future/import_assertions/__test__.jsonc index 1c55d2220e..b7356d9244 100644 --- a/tests/specs/future/import_assertions/__test__.jsonc +++ b/tests/specs/future/import_assertions/__test__.jsonc @@ -1,25 +1,5 @@ { - "steps": [ - { - "args": "run main.js", - "output": "error.out", - "exitCode": 1, - "envs": { - "DENO_FUTURE": "1" - } - }, - // Running the same multiple times, should warn each time. - { - "args": "run main.js", - "output": "error.out", - "exitCode": 1, - "envs": { - "DENO_FUTURE": "1" - } - }, - { - "args": "run main.js", - "output": "success.out" - } - ] + "args": "run main.js", + "output": "error.out", + "exitCode": 1 } diff --git a/tests/specs/future/import_assertions/success.out b/tests/specs/future/import_assertions/success.out deleted file mode 100644 index fcf28b9436..0000000000 --- a/tests/specs/future/import_assertions/success.out +++ /dev/null @@ -1,7 +0,0 @@ -⚠️ Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword. - -import foo from "./main.json" assert { type: "json" }; - - at [WILDCARD]import_assertions/main.js:1:30 - -{ foo: "foo" } diff --git a/tests/specs/future/runtime_api/__test__.jsonc b/tests/specs/future/runtime_api/__test__.jsonc deleted file mode 100644 index c1b3b9b17b..0000000000 --- a/tests/specs/future/runtime_api/__test__.jsonc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "steps": [ - { - "args": "run -A --unstable-fs --config ../../../config/deno.json main.js", - "output": "main.out", - "envs": { - "DENO_FUTURE": "1" - } - }, - { - "args": "run -A --unstable-fs --config ../../../config/deno.json worker.js", - "output": "main.out", - "envs": { - "DENO_FUTURE": "1" - } - } - ] -} diff --git a/tests/specs/future/runtime_api/main.js b/tests/specs/future/runtime_api/main.js deleted file mode 100644 index eac8ed194a..0000000000 --- a/tests/specs/future/runtime_api/main.js +++ /dev/null @@ -1,131 +0,0 @@ -console.log("window is", globalThis.window); -console.log("Deno.Buffer is", Deno.Buffer); -console.log("Deno.close is", Deno.close); -console.log("Deno.copy is", Deno.copy); -console.log("Deno.File is", Deno.File); -console.log("Deno.fstat is", Deno.fstat); -console.log("Deno.fstatSync is", Deno.fstatSync); -console.log("Deno.ftruncate is", Deno.ftruncate); -console.log("Deno.ftruncateSync is", Deno.ftruncateSync); -console.log("Deno.flock is", Deno.flock); -console.log("Deno.flockSync is", Deno.flockSync); -console.log( - "Deno.FsFile.prototype.rid is", - Deno.openSync(import.meta.filename).rid, -); -console.log("Deno.funlock is", Deno.funlock); -console.log("Deno.funlockSync is", Deno.funlockSync); -console.log("Deno.iter is", Deno.iter); -console.log("Deno.iterSync is", Deno.iterSync); -console.log("Deno.metrics is", Deno.metrics); -console.log("Deno.readAll is", Deno.readAll); -console.log("Deno.readAllSync is", Deno.readAllSync); -console.log("Deno.read is", Deno.read); -console.log("Deno.readSync is", Deno.readSync); -console.log("Deno.resources is", Deno.resources); -console.log("Deno.seek is", Deno.seek); -console.log("Deno.seekSync is", Deno.seekSync); -console.log("Deno.shutdown is", Deno.shutdown); -console.log("Deno.writeAll is", Deno.writeAll); -console.log("Deno.writeAllSync is", Deno.writeAllSync); -console.log("Deno.write is", Deno.write); -console.log("Deno.writeSync is", Deno.writeSync); - -// TCP -// Since these tests may run in parallel, ensure this port is unique to this file -const tcpPort = 4509; -const tcpListener = Deno.listen({ port: tcpPort }); -console.log("Deno.Listener.prototype.rid is", tcpListener.rid); - -const tcpConn = await Deno.connect({ port: tcpPort }); -console.log("Deno.Conn.prototype.rid is", tcpConn.rid); - -tcpConn.close(); -tcpListener.close(); - -// Unix -if (Deno.build.os === "windows") { - console.log("Deno.UnixConn.prototype.rid is undefined"); -} else { - const socketPath = "./test.sock"; - const unixListener = Deno.listen({ transport: "unix", path: socketPath }); - - const unixConn = await Deno.connect({ transport: "unix", path: socketPath }); - console.log("Deno.UnixConn.prototype.rid is", unixConn.rid); - - unixConn.close(); - unixListener.close(); - Deno.removeSync(socketPath); -} - -// TLS -// Since these tests may run in parallel, ensure this port is unique to this file -const tlsPort = 4510; -const cert = Deno.readTextFileSync( - new URL("../../../testdata/tls/localhost.crt", import.meta.url), -); -const key = Deno.readTextFileSync( - new URL("../../../testdata/tls/localhost.key", import.meta.url), -); -const tlsListener = Deno.listenTls({ port: tlsPort, cert, key }); -console.log("Deno.TlsListener.prototype.rid is", tlsListener.rid); - -const tlsConn = await Deno.connectTls({ port: tlsPort }); -console.log("Deno.TlsConn.prototype.rid is", tlsConn.rid); - -tlsConn.close(); - -const watcher = Deno.watchFs("."); -console.log("Deno.FsWatcher.prototype.rid is", watcher.rid); -watcher.close(); - -try { - new Deno.FsFile(0); -} catch (error) { - if ( - error instanceof TypeError && - error.message === - "`Deno.FsFile` cannot be constructed, use `Deno.open()` or `Deno.openSync()` instead." - ) { - console.log("Deno.FsFile constructor is illegal"); - } -} - -// Note: this could throw with a `Deno.errors.NotFound` error if `keyFile` and -// `certFile` were used. -const conn1 = await Deno.connectTls({ - port: tlsPort, - certFile: "foo", - keyFile: "foo", -}); -conn1.close(); -console.log("Deno.ConnectTlsOptions.(certFile|keyFile) do nothing"); - -// Note: this could throw with a `Deno.errors.InvalidData` error if `certChain` -// and `privateKey` were used. -const conn2 = await Deno.connectTls({ - port: tlsPort, - certChain: "foo", - privateKey: "foo", -}); -conn2.close(); -console.log("Deno.ConnectTlsOptions.(certChain|privateKey) do nothing"); - -tlsListener.close(); - -// Note: this could throw with a `Deno.errors.NotFound` error if `keyFile` and -// `certFile` were used. -try { - Deno.listenTls({ port: tlsPort, keyFile: "foo", certFile: "foo" }); -} catch (error) { - if ( - error instanceof Deno.errors.InvalidData && - error.message === - "Deno.listenTls requires a key: Error creating TLS certificate" - ) { - console.log("Deno.ListenTlsOptions.(keyFile|certFile) do nothing"); - } -} -console.log("Deno.customInspect is", Deno.customInspect); - -self.close(); diff --git a/tests/specs/future/runtime_api/main.out b/tests/specs/future/runtime_api/main.out deleted file mode 100644 index 4712a06b06..0000000000 --- a/tests/specs/future/runtime_api/main.out +++ /dev/null @@ -1,40 +0,0 @@ -window is undefined -Deno.Buffer is undefined -Deno.close is undefined -Deno.copy is undefined -Deno.File is undefined -Deno.fstat is undefined -Deno.fstatSync is undefined -Deno.ftruncate is undefined -Deno.ftruncateSync is undefined -Deno.flock is undefined -Deno.flockSync is undefined -Deno.FsFile.prototype.rid is undefined -Deno.funlock is undefined -Deno.funlockSync is undefined -Deno.iter is undefined -Deno.iterSync is undefined -Deno.metrics is undefined -Deno.readAll is undefined -Deno.readAllSync is undefined -Deno.read is undefined -Deno.readSync is undefined -Deno.resources is undefined -Deno.seek is undefined -Deno.seekSync is undefined -Deno.shutdown is undefined -Deno.writeAll is undefined -Deno.writeAllSync is undefined -Deno.write is undefined -Deno.writeSync is undefined -Deno.Listener.prototype.rid is undefined -Deno.Conn.prototype.rid is undefined -Deno.UnixConn.prototype.rid is undefined -Deno.TlsListener.prototype.rid is undefined -Deno.TlsConn.prototype.rid is undefined -Deno.FsWatcher.prototype.rid is undefined -Deno.FsFile constructor is illegal -Deno.ConnectTlsOptions.(certFile|keyFile) do nothing -Deno.ConnectTlsOptions.(certChain|privateKey) do nothing -Deno.ListenTlsOptions.(keyFile|certFile) do nothing -Deno.customInspect is undefined diff --git a/tests/specs/future/runtime_api/worker.js b/tests/specs/future/runtime_api/worker.js deleted file mode 100644 index eac42fe56f..0000000000 --- a/tests/specs/future/runtime_api/worker.js +++ /dev/null @@ -1,5 +0,0 @@ -import { delay } from "@std/async/delay"; - -const worker = new Worker(import.meta.resolve("./main.js"), { type: "module" }); -await delay(1_000); -worker.terminate(); diff --git a/tests/specs/future/unstable_flags/__test__.jsonc b/tests/specs/future/unstable_flags/__test__.jsonc index 008ba12138..d21f60bbde 100644 --- a/tests/specs/future/unstable_flags/__test__.jsonc +++ b/tests/specs/future/unstable_flags/__test__.jsonc @@ -3,18 +3,12 @@ { // Notice `--unstable-*` flags are not needed anymore "args": "run -A --config ../../../config/deno.json main.js", - "output": "main.out", - "envs": { - "DENO_FUTURE": "1" - } + "output": "main.out" }, { // Notice `--unstable-*` flags are not needed anymore "args": "run -A --config ../../../config/deno.json worker.js", - "output": "main.out", - "envs": { - "DENO_FUTURE": "1" - } + "output": "main.out" } ] } diff --git a/tests/specs/info/_054_info_local_imports/005_more_imports.ts b/tests/specs/info/_054_info_local_imports/005_more_imports.ts new file mode 100644 index 0000000000..c69556be15 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/005_more_imports.ts @@ -0,0 +1,11 @@ +import { printHello3, returnsFoo2, returnsHi } from "./mod1.ts"; + +printHello3(); + +if (returnsHi() !== "Hi") { + throw Error("Unexpected"); +} + +if (returnsFoo2() !== "Foo") { + throw Error("Unexpected"); +} diff --git a/tests/specs/info/_054_info_local_imports/054_info_local_imports.out b/tests/specs/info/_054_info_local_imports/054_info_local_imports.out new file mode 100644 index 0000000000..388168a8b6 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/054_info_local_imports.out @@ -0,0 +1,9 @@ +local: [WILDCARD]005_more_imports.ts +type: TypeScript +dependencies: 3 unique +size: [WILDCARD] + +file://[WILDCARD]/005_more_imports.ts ([WILDCARD]) +└─┬ file://[WILDCARD]/mod1.ts ([WILDCARD]) + └─┬ file://[WILDCARD]/subdir2/mod2.ts ([WILDCARD]) + └── file://[WILDCARD]/print_hello.ts ([WILDCARD]) diff --git a/tests/specs/info/_054_info_local_imports/__test__.jsonc b/tests/specs/info/_054_info_local_imports/__test__.jsonc new file mode 100644 index 0000000000..4bfdfe1558 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet 005_more_imports.ts", + "output": "054_info_local_imports.out", + "exitCode": 0 +} diff --git a/tests/testdata/bundle/import_map/main.ts b/tests/specs/info/_054_info_local_imports/mod1.ts similarity index 80% rename from tests/testdata/bundle/import_map/main.ts rename to tests/specs/info/_054_info_local_imports/mod1.ts index 74834de20d..5e58f432ed 100644 --- a/tests/testdata/bundle/import_map/main.ts +++ b/tests/specs/info/_054_info_local_imports/mod1.ts @@ -1,4 +1,4 @@ -import { printHello2, returnsFoo } from "mod2"; +import { printHello2, returnsFoo } from "./subdir2/mod2.ts"; export function returnsHi(): string { return "Hi"; diff --git a/tests/specs/info/_054_info_local_imports/mod2.ts b/tests/specs/info/_054_info_local_imports/mod2.ts new file mode 100644 index 0000000000..ce1adc0e81 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/mod2.ts @@ -0,0 +1 @@ +export { printHello } from "./print_hello.ts"; diff --git a/tests/specs/info/_054_info_local_imports/print_hello.ts b/tests/specs/info/_054_info_local_imports/print_hello.ts new file mode 100644 index 0000000000..b9c0ad5275 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/print_hello.ts @@ -0,0 +1,3 @@ +export function printHello() { + console.log("Hello"); +} diff --git a/tests/specs/info/_054_info_local_imports/subdir2/dynamic_import.ts b/tests/specs/info/_054_info_local_imports/subdir2/dynamic_import.ts new file mode 100644 index 0000000000..59beb64c33 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/subdir2/dynamic_import.ts @@ -0,0 +1,4 @@ +(async () => { + const { printHello } = await import("../mod2.ts"); + printHello(); +})(); diff --git a/tests/specs/info/_054_info_local_imports/subdir2/mod2.ts b/tests/specs/info/_054_info_local_imports/subdir2/mod2.ts new file mode 100644 index 0000000000..9071d0aeb4 --- /dev/null +++ b/tests/specs/info/_054_info_local_imports/subdir2/mod2.ts @@ -0,0 +1,9 @@ +import { printHello } from "../print_hello.ts"; + +export function returnsFoo(): string { + return "Foo"; +} + +export function printHello2() { + printHello(); +} diff --git a/tests/specs/info/byonm/__test__.jsonc b/tests/specs/info/byonm/__test__.jsonc new file mode 100644 index 0000000000..6c9ba7dada --- /dev/null +++ b/tests/specs/info/byonm/__test__.jsonc @@ -0,0 +1,11 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "info npm:@denotest/add", + "output": "info.out", + "exitCode": 1 + }] +} diff --git a/tests/specs/info/byonm/deno.json b/tests/specs/info/byonm/deno.json new file mode 100644 index 0000000000..4b88c71fbb --- /dev/null +++ b/tests/specs/info/byonm/deno.json @@ -0,0 +1,6 @@ +{ + "nodeModulesDir": "manual", + "imports": { + "chalk": "npm:@denotest/add" + } +} diff --git a/tests/specs/info/byonm/info.out b/tests/specs/info/byonm/info.out new file mode 100644 index 0000000000..4e6f11a88f --- /dev/null +++ b/tests/specs/info/byonm/info.out @@ -0,0 +1 @@ +error: Resolving npm specifier entrypoints this way is currently not supported with "nodeModules": "manual". In the meantime, try with --node-modules-dir=auto instead diff --git a/tests/specs/info/byonm/package.json b/tests/specs/info/byonm/package.json new file mode 100644 index 0000000000..15a786ad71 --- /dev/null +++ b/tests/specs/info/byonm/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/add": "*" + } +} diff --git a/tests/specs/info/data_null_error/__test__.jsonc b/tests/specs/info/data_null_error/__test__.jsonc new file mode 100644 index 0000000000..782cca43d4 --- /dev/null +++ b/tests/specs/info/data_null_error/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info data_null_error/mod.ts", + "output": "data_null_error/data_null_error.out" +} diff --git a/tests/testdata/info/data_null_error/data_null_error.out b/tests/specs/info/data_null_error/data_null_error/data_null_error.out similarity index 100% rename from tests/testdata/info/data_null_error/data_null_error.out rename to tests/specs/info/data_null_error/data_null_error/data_null_error.out diff --git a/tests/testdata/info/data_null_error/mod.ts b/tests/specs/info/data_null_error/data_null_error/mod.ts similarity index 100% rename from tests/testdata/info/data_null_error/mod.ts rename to tests/specs/info/data_null_error/data_null_error/mod.ts diff --git a/tests/testdata/info/data_null_error/types.d.ts b/tests/specs/info/data_null_error/data_null_error/types.d.ts similarity index 100% rename from tests/testdata/info/data_null_error/types.d.ts rename to tests/specs/info/data_null_error/data_null_error/types.d.ts diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/__test__.jsonc b/tests/specs/info/dynamic_imports_tmpl_lit/__test__.jsonc new file mode 100644 index 0000000000..71f823a46f --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info dynamic_imports_tmp_lit/main.js", + "output": "dynamic_imports_tmp_lit/main.info.out", + "exitCode": 0 +} diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.info.out b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.info.out new file mode 100644 index 0000000000..57d730a643 --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.info.out @@ -0,0 +1,10 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 4 unique +size: [WILDCARD] + +file:///[WILDCARD]/dynamic_imports_tmp_lit/main.js ([WILDCARD]) +├── file:///[WILDCARD]/dynamic_imports_tmp_lit/sub/a.js ([WILDCARD]) +├── file:///[WILDCARD]/dynamic_imports_tmp_lit/sub/b.ts ([WILDCARD]) +├── file:///[WILDCARD]/dynamic_imports_tmp_lit/other/data.json ([WILDCARD]) +└── file:///[WILDCARD]/dynamic_imports_tmp_lit/other/sub/data2.json ([WILDCARD]) diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.js b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.js new file mode 100644 index 0000000000..3bda597724 --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/main.js @@ -0,0 +1,14 @@ +const fileNames = [ + "a.js", + "b.ts", +]; + +for (const fileName of fileNames) { + await import(`./sub/${fileName}`); +} + +const jsonFileNames = ["data.json", "sub/data2.json"]; +for (const fileName of jsonFileNames) { + const mod = await import(`./other/${fileName}`, { with: { type: "json" } }); + console.log(mod.default); +} diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/data.json b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/data.json new file mode 100644 index 0000000000..0131e01e4b --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/data.json @@ -0,0 +1,3 @@ +{ + "data": 5 +} diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/sub/data2.json b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/sub/data2.json new file mode 100644 index 0000000000..858a13cdd1 --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/other/sub/data2.json @@ -0,0 +1,3 @@ +{ + "data": 1 +} diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/a.js b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/a.js new file mode 100644 index 0000000000..7b2a346011 --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/a.js @@ -0,0 +1 @@ +console.log("a"); diff --git a/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/b.ts b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/b.ts new file mode 100644 index 0000000000..6d012e7f1f --- /dev/null +++ b/tests/specs/info/dynamic_imports_tmpl_lit/dynamic_imports_tmp_lit/sub/b.ts @@ -0,0 +1 @@ +console.log("b"); diff --git a/tests/testdata/info/041_info_flag.out b/tests/specs/info/flag/041_info_flag.out similarity index 83% rename from tests/testdata/info/041_info_flag.out rename to tests/specs/info/flag/041_info_flag.out index 3506a29e48..72a00be303 100644 --- a/tests/testdata/info/041_info_flag.out +++ b/tests/specs/info/flag/041_info_flag.out @@ -1,5 +1,5 @@ DENO_DIR location: [WILDCARD] -Remote modules cache: [WILDCARD]deps +Remote modules cache: [WILDCARD]remote npm modules cache: [WILDCARD]npm Emitted modules cache: [WILDCARD]gen Language server registries cache: [WILDCARD]registries diff --git a/tests/specs/info/flag/__test__.jsonc b/tests/specs/info/flag/__test__.jsonc new file mode 100644 index 0000000000..39b50c960e --- /dev/null +++ b/tests/specs/info/flag/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info", + "output": "041_info_flag.out" +} diff --git a/tests/testdata/info/041_info_flag_location.out b/tests/specs/info/flag_location/041_info_flag_location.out similarity index 87% rename from tests/testdata/info/041_info_flag_location.out rename to tests/specs/info/flag_location/041_info_flag_location.out index b9e72f6590..684db2eec5 100644 --- a/tests/testdata/info/041_info_flag_location.out +++ b/tests/specs/info/flag_location/041_info_flag_location.out @@ -1,5 +1,5 @@ DENO_DIR location: [WILDCARD] -Remote modules cache: [WILDCARD]deps +Remote modules cache: [WILDCARD]remote npm modules cache: [WILDCARD]npm Emitted modules cache: [WILDCARD]gen Language server registries cache: [WILDCARD]registries diff --git a/tests/specs/info/flag_location/__test__.jsonc b/tests/specs/info/flag_location/__test__.jsonc new file mode 100644 index 0000000000..436e7cd9a7 --- /dev/null +++ b/tests/specs/info/flag_location/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --location https://deno.land", + "output": "041_info_flag_location.out" +} diff --git a/tests/testdata/info/049_info_flag_script_jsx.out b/tests/specs/info/flag_script_jsx/049_info_flag_script_jsx.out similarity index 100% rename from tests/testdata/info/049_info_flag_script_jsx.out rename to tests/specs/info/flag_script_jsx/049_info_flag_script_jsx.out diff --git a/tests/specs/info/flag_script_jsx/__test__.jsonc b/tests/specs/info/flag_script_jsx/__test__.jsonc new file mode 100644 index 0000000000..6b6cdc4e12 --- /dev/null +++ b/tests/specs/info/flag_script_jsx/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --allow-import http://127.0.0.1:4545/run/048_media_types_jsx.ts", + "output": "049_info_flag_script_jsx.out" +} diff --git a/tests/specs/info/import_map/__test__.jsonc b/tests/specs/info/import_map/__test__.jsonc new file mode 100644 index 0000000000..7aba603e0b --- /dev/null +++ b/tests/specs/info/import_map/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "steps": [ + { + "args": "info preact/debug", + "output": "with_import_map.out", + "exitCode": 0 + } + ] +} diff --git a/tests/testdata/info/with_import_map/deno.json b/tests/specs/info/import_map/deno.json similarity index 100% rename from tests/testdata/info/with_import_map/deno.json rename to tests/specs/info/import_map/deno.json diff --git a/tests/testdata/info/with_import_map/deno.lock b/tests/specs/info/import_map/deno.lock similarity index 56% rename from tests/testdata/info/with_import_map/deno.lock rename to tests/specs/info/import_map/deno.lock index 540a44063a..cb5c6ca45d 100644 --- a/tests/testdata/info/with_import_map/deno.lock +++ b/tests/specs/info/import_map/deno.lock @@ -1,10 +1,10 @@ { "version": "3", "remote": { - "https://esm.sh/preact@10.15.1": "2b79349676a4942fbcf835c4efa909791c2f0aeca195225bf22bac9866e94b4e", - "https://esm.sh/preact@10.15.1/debug": "eb12af10d41f793ab3a8cf90bff89a9cd8efab57b541d43dada6efc5e3fa8e3c", + "https://esm.sh/preact@10.15.1": "4bfd0b2c5a2d432e0c8cda295d6b7304152ae08c85f7d0a22f91289c97085b89", + "https://esm.sh/preact@10.15.1/debug": "4bfd0b2c5a2d432e0c8cda295d6b7304152ae08c85f7d0a22f91289c97085b89", "https://esm.sh/stable/preact@10.15.1/denonext/debug.js": "e8e5e198bd48c93d484c91c4c78af1900bd81d9bfcfd543e8ac75216f5404c10", - "https://esm.sh/stable/preact@10.15.1/denonext/devtools.js": "7e3009ee2208a6cc8bbf747b61e9468d177ef55d94cf9b774ad2a6c926ae51cb", + "https://esm.sh/stable/preact@10.15.1/denonext/devtools.js": "f61430e179a84483f8ea8dc098d7d0d46b2f0546de4027518bfcef197cd665c9", "https://esm.sh/stable/preact@10.15.1/denonext/preact.mjs": "30710ac1d5ff3711ae0c04eddbeb706f34f82d97489f61aaf09897bc75d2a628" } } diff --git a/tests/testdata/info/with_import_map/main.tsx b/tests/specs/info/import_map/main.tsx similarity index 100% rename from tests/testdata/info/with_import_map/main.tsx rename to tests/specs/info/import_map/main.tsx diff --git a/tests/testdata/info/with_import_map/with_import_map.out b/tests/specs/info/import_map/with_import_map.out similarity index 100% rename from tests/testdata/info/with_import_map/with_import_map.out rename to tests/specs/info/import_map/with_import_map.out diff --git a/tests/specs/info/json/__test__.jsonc b/tests/specs/info/json/__test__.jsonc new file mode 100644 index 0000000000..4b50dc32ba --- /dev/null +++ b/tests/specs/info/json/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --json", + "output": "info_json.out" +} diff --git a/tests/testdata/info/info_json.out b/tests/specs/info/json/info_json.out similarity index 77% rename from tests/testdata/info/info_json.out rename to tests/specs/info/json/info_json.out index 3215af742b..551f61026d 100644 --- a/tests/testdata/info/info_json.out +++ b/tests/specs/info/json/info_json.out @@ -1,6 +1,7 @@ { + "version": 1, "denoDir": "[WILDCARD]", - "modulesCache": "[WILDCARD]deps", + "modulesCache": "[WILDCARD]remote", "npmCache": "[WILDCARD]npm", "typescriptCache": "[WILDCARD]gen", "registryCache": "[WILDCARD]registries", diff --git a/tests/testdata/info/076_info_json_deps_order.out b/tests/specs/info/json_deps_order/076_info_json_deps_order.out similarity index 99% rename from tests/testdata/info/076_info_json_deps_order.out rename to tests/specs/info/json_deps_order/076_info_json_deps_order.out index a1b15e00c0..92bf1d0130 100644 --- a/tests/testdata/info/076_info_json_deps_order.out +++ b/tests/specs/info/json_deps_order/076_info_json_deps_order.out @@ -1,4 +1,5 @@ { + "version": 1, "roots": [ "file://[WILDCARD]/076_info_json_deps_order.ts" ], diff --git a/tests/testdata/info/076_info_json_deps_order.ts b/tests/specs/info/json_deps_order/076_info_json_deps_order.ts similarity index 100% rename from tests/testdata/info/076_info_json_deps_order.ts rename to tests/specs/info/json_deps_order/076_info_json_deps_order.ts diff --git a/tests/specs/info/json_deps_order/__test__.jsonc b/tests/specs/info/json_deps_order/__test__.jsonc new file mode 100644 index 0000000000..f474f4d380 --- /dev/null +++ b/tests/specs/info/json_deps_order/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --json 076_info_json_deps_order.ts", + "output": "076_info_json_deps_order.out" +} diff --git a/tests/specs/info/json_deps_order/recursive_imports/A.ts b/tests/specs/info/json_deps_order/recursive_imports/A.ts new file mode 100644 index 0000000000..43ecdbe5e4 --- /dev/null +++ b/tests/specs/info/json_deps_order/recursive_imports/A.ts @@ -0,0 +1,7 @@ +import { B } from "./B.ts"; +import { thing } from "./common.ts"; + +export function A() { + thing(); + B(); +} diff --git a/tests/specs/info/json_deps_order/recursive_imports/B.ts b/tests/specs/info/json_deps_order/recursive_imports/B.ts new file mode 100644 index 0000000000..9fff0fdc9e --- /dev/null +++ b/tests/specs/info/json_deps_order/recursive_imports/B.ts @@ -0,0 +1,7 @@ +import { C } from "./C.ts"; +import { thing } from "./common.ts"; + +export function B() { + thing(); + C(); +} diff --git a/tests/specs/info/json_deps_order/recursive_imports/C.ts b/tests/specs/info/json_deps_order/recursive_imports/C.ts new file mode 100644 index 0000000000..e47e77b41d --- /dev/null +++ b/tests/specs/info/json_deps_order/recursive_imports/C.ts @@ -0,0 +1,8 @@ +import { A } from "./A.ts"; +import { thing } from "./common.ts"; + +export function C() { + if (A != null) { + thing(); + } +} diff --git a/tests/specs/info/json_deps_order/recursive_imports/common.ts b/tests/specs/info/json_deps_order/recursive_imports/common.ts new file mode 100644 index 0000000000..2b16a7bf14 --- /dev/null +++ b/tests/specs/info/json_deps_order/recursive_imports/common.ts @@ -0,0 +1,2 @@ +export function thing() { +} diff --git a/tests/specs/info/json_file/__test__.jsonc b/tests/specs/info/json_file/__test__.jsonc new file mode 100644 index 0000000000..61289da947 --- /dev/null +++ b/tests/specs/info/json_file/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet --json json_output/main.ts", + "output": "json_output/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/info/json_output/main.out b/tests/specs/info/json_file/json_output/main.out similarity index 76% rename from tests/testdata/info/json_output/main.out rename to tests/specs/info/json_file/json_output/main.out index 5a89d5cab0..bc8f4d0f84 100644 --- a/tests/testdata/info/json_output/main.out +++ b/tests/specs/info/json_file/json_output/main.out @@ -1,15 +1,16 @@ { + "version": 1, "roots": [ - "file://[WILDCARD]/info/json_output/main.ts" + "file://[WILDCARD]/json_output/main.ts" ], "modules": [ { "kind": "esm", "dependencies": [ { - "specifier": "../../subdir/mod1.ts", + "specifier": "../mod1.ts", "code": { - "specifier": "file://[WILDCARD]/subdir/mod1.ts", + "specifier": "file://[WILDCARD]/mod1.ts", "span": { "start": { "line": 0, @@ -17,7 +18,7 @@ }, "end": { "line": 0, - "character": 74 + "character": 64 } } } @@ -34,7 +35,7 @@ { "specifier": "./subdir2/mod2.ts", "code": { - "specifier": "file://[WILDCARD]/subdir/subdir2/mod2.ts", + "specifier": "file://[WILDCARD]/subdir2/mod2.ts", "span": { "start": { "line": 0, @@ -51,14 +52,14 @@ "local": "[WILDCARD]mod1.ts", [WILDCARD] "mediaType": "TypeScript", - "specifier": "file://[WILDCARD]/subdir/mod1.ts" + "specifier": "file://[WILDCARD]/mod1.ts" }, { "kind": "esm", "local": "[WILDCARD]print_hello.ts", [WILDCARD] "mediaType": "TypeScript", - "specifier": "file://[WILDCARD]/subdir/print_hello.ts" + "specifier": "file://[WILDCARD]/print_hello.ts" }, { "kind": "esm", @@ -66,7 +67,7 @@ { "specifier": "../print_hello.ts", "code": { - "specifier": "file://[WILDCARD]/subdir/print_hello.ts", + "specifier": "file://[WILDCARD]/print_hello.ts", "span": { "start": { "line": 0, @@ -83,7 +84,7 @@ "local": "[WILDCARD]mod2.ts", [WILDCARD] "mediaType": "TypeScript", - "specifier": "file://[WILDCARD]/subdir/subdir2/mod2.ts" + "specifier": "file://[WILDCARD]/subdir2/mod2.ts" } ], "redirects": {}, diff --git a/tests/testdata/info/json_output/main.ts b/tests/specs/info/json_file/json_output/main.ts similarity index 64% rename from tests/testdata/info/json_output/main.ts rename to tests/specs/info/json_file/json_output/main.ts index 927bc55ed0..d9029af8af 100644 --- a/tests/testdata/info/json_output/main.ts +++ b/tests/specs/info/json_file/json_output/main.ts @@ -1,4 +1,4 @@ -import { printHello3, returnsFoo2, returnsHi } from "../../subdir/mod1.ts"; +import { printHello3, returnsFoo2, returnsHi } from "../mod1.ts"; printHello3(); diff --git a/tests/specs/info/json_file/mod1.ts b/tests/specs/info/json_file/mod1.ts new file mode 100644 index 0000000000..5e58f432ed --- /dev/null +++ b/tests/specs/info/json_file/mod1.ts @@ -0,0 +1,17 @@ +import { printHello2, returnsFoo } from "./subdir2/mod2.ts"; + +export function returnsHi(): string { + return "Hi"; +} + +export function returnsFoo2(): string { + return returnsFoo(); +} + +export function printHello3() { + printHello2(); +} + +export function throwsError() { + throw Error("exception from mod1"); +} diff --git a/tests/specs/info/json_file/mod2.ts b/tests/specs/info/json_file/mod2.ts new file mode 100644 index 0000000000..ce1adc0e81 --- /dev/null +++ b/tests/specs/info/json_file/mod2.ts @@ -0,0 +1 @@ +export { printHello } from "./print_hello.ts"; diff --git a/tests/specs/info/json_file/print_hello.ts b/tests/specs/info/json_file/print_hello.ts new file mode 100644 index 0000000000..b9c0ad5275 --- /dev/null +++ b/tests/specs/info/json_file/print_hello.ts @@ -0,0 +1,3 @@ +export function printHello() { + console.log("Hello"); +} diff --git a/tests/specs/info/json_file/subdir2/dynamic_import.ts b/tests/specs/info/json_file/subdir2/dynamic_import.ts new file mode 100644 index 0000000000..59beb64c33 --- /dev/null +++ b/tests/specs/info/json_file/subdir2/dynamic_import.ts @@ -0,0 +1,4 @@ +(async () => { + const { printHello } = await import("../mod2.ts"); + printHello(); +})(); diff --git a/tests/specs/info/json_file/subdir2/mod2.ts b/tests/specs/info/json_file/subdir2/mod2.ts new file mode 100644 index 0000000000..9071d0aeb4 --- /dev/null +++ b/tests/specs/info/json_file/subdir2/mod2.ts @@ -0,0 +1,9 @@ +import { printHello } from "../print_hello.ts"; + +export function returnsFoo(): string { + return "Foo"; +} + +export function printHello2() { + printHello(); +} diff --git a/tests/specs/info/json_location/__test__.jsonc b/tests/specs/info/json_location/__test__.jsonc new file mode 100644 index 0000000000..0c1acc3d9c --- /dev/null +++ b/tests/specs/info/json_location/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --json --location https://deno.land", + "output": "info_json_location.out" +} diff --git a/tests/testdata/info/info_json_location.out b/tests/specs/info/json_location/info_json_location.out similarity index 83% rename from tests/testdata/info/info_json_location.out rename to tests/specs/info/json_location/info_json_location.out index 510fa77494..6d01ba451d 100644 --- a/tests/testdata/info/info_json_location.out +++ b/tests/specs/info/json_location/info_json_location.out @@ -1,6 +1,7 @@ { + "version": 1, "denoDir": "[WILDCARD]", - "modulesCache": "[WILDCARD]deps", + "modulesCache": "[WILDCARD]remote", "npmCache": "[WILDCARD]npm", "typescriptCache": "[WILDCARD]gen", "registryCache": "[WILDCARD]registries", diff --git a/tests/specs/info/missing_module/__test__.jsonc b/tests/specs/info/missing_module/__test__.jsonc new file mode 100644 index 0000000000..edc1519722 --- /dev/null +++ b/tests/specs/info/missing_module/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info error_009_missing_js_module.js", + "output": "info_missing_module.out" +} diff --git a/tests/specs/info/missing_module/error_009_missing_js_module.js b/tests/specs/info/missing_module/error_009_missing_js_module.js new file mode 100644 index 0000000000..e6ca88934b --- /dev/null +++ b/tests/specs/info/missing_module/error_009_missing_js_module.js @@ -0,0 +1 @@ +import "./bad-module.js"; diff --git a/tests/testdata/info/info_missing_module.out b/tests/specs/info/missing_module/info_missing_module.out similarity index 100% rename from tests/testdata/info/info_missing_module.out rename to tests/specs/info/missing_module/info_missing_module.out diff --git a/tests/specs/info/multiple_imports/__test__.jsonc b/tests/specs/info/multiple_imports/__test__.jsonc new file mode 100644 index 0000000000..32d72bcb3a --- /dev/null +++ b/tests/specs/info/multiple_imports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --allow-import http://127.0.0.1:4545/run/019_media_types.ts", + "output": "multiple_imports.out" +} diff --git a/tests/testdata/info/multiple_imports.out b/tests/specs/info/multiple_imports/multiple_imports.out similarity index 100% rename from tests/testdata/info/multiple_imports.out rename to tests/specs/info/multiple_imports/multiple_imports.out diff --git a/tests/specs/info/multiple_redirects/__test__.jsonc b/tests/specs/info/multiple_redirects/__test__.jsonc index 0e1808e0a9..205d21c130 100644 --- a/tests/specs/info/multiple_redirects/__test__.jsonc +++ b/tests/specs/info/multiple_redirects/__test__.jsonc @@ -1,4 +1,4 @@ { - "args": "info --json main.ts", + "args": "info --allow-import --json main.ts", "output": "main.out" } diff --git a/tests/specs/info/multiple_redirects/main.out b/tests/specs/info/multiple_redirects/main.out index bd18c17288..0021047deb 100644 --- a/tests/specs/info/multiple_redirects/main.out +++ b/tests/specs/info/multiple_redirects/main.out @@ -2,6 +2,7 @@ Download http://localhost:4548/subdir/redirects/redirect1.js Download http://localhost:4546/subdir/redirects/redirect1.js Download http://localhost:4545/subdir/redirects/redirect1.js { + "version": 1, "roots": [ "file:///[WILDLINE]/multiple_redirects/main.ts" ], @@ -27,8 +28,6 @@ Download http://localhost:4545/subdir/redirects/redirect1.js } ], "local": "[WILDLINE]main.ts", - "emit": null, - "map": null, "size": 97, "mediaType": "TypeScript", "specifier": "file:///[WILDLINE]/multiple_redirects/main.ts" @@ -36,8 +35,6 @@ Download http://localhost:4545/subdir/redirects/redirect1.js { "kind": "esm", "local": "[WILDLINE]", - "emit": null, - "map": null, "size": 27, "mediaType": "JavaScript", "specifier": "http://localhost:4545/subdir/redirects/redirect1.js" diff --git a/tests/specs/info/package_json_basic/__test__.jsonc b/tests/specs/info/package_json_basic/__test__.jsonc new file mode 100644 index 0000000000..c5672615cc --- /dev/null +++ b/tests/specs/info/package_json_basic/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { + "args": "info --quiet main.ts", + "output": "info.out" + } + ] +} diff --git a/tests/specs/info/package_json_basic/info.out b/tests/specs/info/package_json_basic/info.out new file mode 100644 index 0000000000..2430101311 --- /dev/null +++ b/tests/specs/info/package_json_basic/info.out @@ -0,0 +1,9 @@ +local: [WILDCARD]main.ts +type: TypeScript +dependencies: 3 unique +size: [WILDCARD] + +file:///[WILDCARD]/main.ts (63B) +└─┬ file:///[WILDCARD]/lib.ts (166B) + ├── file:///[WILDCARD]@denotest/esm-basic/main.mjs (unknown) + └── file:///[WILDCARD]@denotest/esm-basic/main.d.mts (unknown) diff --git a/tests/specs/info/package_json_basic/install.out b/tests/specs/info/package_json_basic/install.out new file mode 100644 index 0000000000..8f03ba6407 --- /dev/null +++ b/tests/specs/info/package_json_basic/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/info/package_json_basic/lib.ts b/tests/specs/info/package_json_basic/lib.ts new file mode 100644 index 0000000000..1deed81f7e --- /dev/null +++ b/tests/specs/info/package_json_basic/lib.ts @@ -0,0 +1,9 @@ +import * as test from "@denotest/esm-basic"; + +export function add(a: number, b: number) { + return a + b; +} + +export function getValue() { + return test.getValue(); +} diff --git a/tests/specs/info/package_json_basic/main.ts b/tests/specs/info/package_json_basic/main.ts new file mode 100644 index 0000000000..e241f30026 --- /dev/null +++ b/tests/specs/info/package_json_basic/main.ts @@ -0,0 +1,3 @@ +import { getValue } from "./lib.ts"; + +console.log(getValue()); diff --git a/tests/specs/info/package_json_basic/package.json b/tests/specs/info/package_json_basic/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/info/package_json_basic/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/specs/info/package_json_basic_auto_install/__test__.jsonc b/tests/specs/info/package_json_basic_auto_install/__test__.jsonc new file mode 100644 index 0000000000..a98f89e913 --- /dev/null +++ b/tests/specs/info/package_json_basic_auto_install/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "info --quiet main.ts", + "output": "info.out" + } + ] +} diff --git a/tests/specs/info/package_json_basic_auto_install/deno.json b/tests/specs/info/package_json_basic_auto_install/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/info/package_json_basic_auto_install/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/testdata/package_json/basic/main.info.out b/tests/specs/info/package_json_basic_auto_install/info.out similarity index 100% rename from tests/testdata/package_json/basic/main.info.out rename to tests/specs/info/package_json_basic_auto_install/info.out diff --git a/tests/specs/info/package_json_basic_auto_install/lib.ts b/tests/specs/info/package_json_basic_auto_install/lib.ts new file mode 100644 index 0000000000..1deed81f7e --- /dev/null +++ b/tests/specs/info/package_json_basic_auto_install/lib.ts @@ -0,0 +1,9 @@ +import * as test from "@denotest/esm-basic"; + +export function add(a: number, b: number) { + return a + b; +} + +export function getValue() { + return test.getValue(); +} diff --git a/tests/specs/info/package_json_basic_auto_install/main.ts b/tests/specs/info/package_json_basic_auto_install/main.ts new file mode 100644 index 0000000000..e241f30026 --- /dev/null +++ b/tests/specs/info/package_json_basic_auto_install/main.ts @@ -0,0 +1,3 @@ +import { getValue } from "./lib.ts"; + +console.log(getValue()); diff --git a/tests/specs/info/package_json_basic_auto_install/package.json b/tests/specs/info/package_json_basic_auto_install/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/info/package_json_basic_auto_install/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/specs/info/recursive_modules/__test__.jsonc b/tests/specs/info/recursive_modules/__test__.jsonc new file mode 100644 index 0000000000..c4313a2fbe --- /dev/null +++ b/tests/specs/info/recursive_modules/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet info_recursive_imports_test.ts", + "output": "info_recursive_imports_test.out", + "exitCode": 0 +} diff --git a/tests/testdata/info/info_recursive_imports_test.out b/tests/specs/info/recursive_modules/info_recursive_imports_test.out similarity index 100% rename from tests/testdata/info/info_recursive_imports_test.out rename to tests/specs/info/recursive_modules/info_recursive_imports_test.out diff --git a/tests/specs/info/recursive_modules/info_recursive_imports_test.ts b/tests/specs/info/recursive_modules/info_recursive_imports_test.ts new file mode 100644 index 0000000000..c9ba44755d --- /dev/null +++ b/tests/specs/info/recursive_modules/info_recursive_imports_test.ts @@ -0,0 +1,5 @@ +import { A } from "./recursive_imports/A.ts"; + +export function test() { + A(); +} diff --git a/tests/specs/info/recursive_modules/recursive_imports/A.ts b/tests/specs/info/recursive_modules/recursive_imports/A.ts new file mode 100644 index 0000000000..43ecdbe5e4 --- /dev/null +++ b/tests/specs/info/recursive_modules/recursive_imports/A.ts @@ -0,0 +1,7 @@ +import { B } from "./B.ts"; +import { thing } from "./common.ts"; + +export function A() { + thing(); + B(); +} diff --git a/tests/specs/info/recursive_modules/recursive_imports/B.ts b/tests/specs/info/recursive_modules/recursive_imports/B.ts new file mode 100644 index 0000000000..9fff0fdc9e --- /dev/null +++ b/tests/specs/info/recursive_modules/recursive_imports/B.ts @@ -0,0 +1,7 @@ +import { C } from "./C.ts"; +import { thing } from "./common.ts"; + +export function B() { + thing(); + C(); +} diff --git a/tests/specs/info/recursive_modules/recursive_imports/C.ts b/tests/specs/info/recursive_modules/recursive_imports/C.ts new file mode 100644 index 0000000000..e47e77b41d --- /dev/null +++ b/tests/specs/info/recursive_modules/recursive_imports/C.ts @@ -0,0 +1,8 @@ +import { A } from "./A.ts"; +import { thing } from "./common.ts"; + +export function C() { + if (A != null) { + thing(); + } +} diff --git a/tests/specs/info/recursive_modules/recursive_imports/common.ts b/tests/specs/info/recursive_modules/recursive_imports/common.ts new file mode 100644 index 0000000000..2b16a7bf14 --- /dev/null +++ b/tests/specs/info/recursive_modules/recursive_imports/common.ts @@ -0,0 +1,2 @@ +export function thing() { +} diff --git a/tests/specs/info/type_import/__test__.jsonc b/tests/specs/info/type_import/__test__.jsonc new file mode 100644 index 0000000000..2092ecf08b --- /dev/null +++ b/tests/specs/info/type_import/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info info_type_import.ts", + "output": "info_type_import.out" +} diff --git a/tests/testdata/info/info_type_import.out b/tests/specs/info/type_import/info_type_import.out similarity index 100% rename from tests/testdata/info/info_type_import.out rename to tests/specs/info/type_import/info_type_import.out diff --git a/tests/specs/info/type_import/info_type_import.ts b/tests/specs/info/type_import/info_type_import.ts new file mode 100644 index 0000000000..5d8ca21ced --- /dev/null +++ b/tests/specs/info/type_import/info_type_import.ts @@ -0,0 +1,3 @@ +import { AnInterface as _, isAnInterface } from "./type_and_code.ts"; + +isAnInterface({}); diff --git a/tests/specs/info/type_import/type_and_code.ts b/tests/specs/info/type_import/type_and_code.ts new file mode 100644 index 0000000000..b147134195 --- /dev/null +++ b/tests/specs/info/type_import/type_and_code.ts @@ -0,0 +1,7 @@ +export interface AnInterface { + a: string; +} + +export function isAnInterface(value: unknown): value is AnInterface { + return value && typeof value === "object" && "a" in value; +} diff --git a/tests/specs/info/types_header_direct/__test__.jsonc b/tests/specs/info/types_header_direct/__test__.jsonc new file mode 100644 index 0000000000..df0c1e5733 --- /dev/null +++ b/tests/specs/info/types_header_direct/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --allow-import --reload type_directives_01.ts", + "output": "types_header.out" +} diff --git a/tests/specs/info/types_header_direct/type_directives_01.ts b/tests/specs/info/types_header_direct/type_directives_01.ts new file mode 100644 index 0000000000..71305824c7 --- /dev/null +++ b/tests/specs/info/types_header_direct/type_directives_01.ts @@ -0,0 +1,3 @@ +import * as foo from "http://127.0.0.1:4545/xTypeScriptTypes.js"; + +console.log(foo.foo); diff --git a/tests/testdata/info/types_header.out b/tests/specs/info/types_header_direct/types_header.out similarity index 100% rename from tests/testdata/info/types_header.out rename to tests/specs/info/types_header_direct/types_header.out diff --git a/tests/specs/info/with_config_override/__test__.jsonc b/tests/specs/info/with_config_override/__test__.jsonc new file mode 100644 index 0000000000..02c7d2a78c --- /dev/null +++ b/tests/specs/info/with_config_override/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info with_config/test.ts --config with_config/deno-override.json --import-map with_config/import_map.json", + "output": "with_config/with_config.out" +} diff --git a/tests/testdata/info/with_config/deno-override.json b/tests/specs/info/with_config_override/with_config/deno-override.json similarity index 100% rename from tests/testdata/info/with_config/deno-override.json rename to tests/specs/info/with_config_override/with_config/deno-override.json diff --git a/tests/specs/info/with_config_override/with_config/deno.json b/tests/specs/info/with_config_override/with_config/deno.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tests/specs/info/with_config_override/with_config/deno.json @@ -0,0 +1 @@ +{} diff --git a/tests/specs/info/with_config_override/with_config/import_map.json b/tests/specs/info/with_config_override/with_config/import_map.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tests/specs/info/with_config_override/with_config/import_map.json @@ -0,0 +1 @@ +{} diff --git a/tests/testdata/info/with_config/test.ts b/tests/specs/info/with_config_override/with_config/test.ts similarity index 100% rename from tests/testdata/info/with_config/test.ts rename to tests/specs/info/with_config_override/with_config/test.ts diff --git a/tests/testdata/info/with_config/with_config.out b/tests/specs/info/with_config_override/with_config/with_config.out similarity index 100% rename from tests/testdata/info/with_config/with_config.out rename to tests/specs/info/with_config_override/with_config/with_config.out diff --git a/tests/specs/info/workspace_member/__test__.jsonc b/tests/specs/info/workspace_member/__test__.jsonc new file mode 100644 index 0000000000..d13d3b03e8 --- /dev/null +++ b/tests/specs/info/workspace_member/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "tests": { + "member_folder": { + "args": "info --quiet foo", + "cwd": "member", + "output": "info_workspace_member.out", + "exitCode": 0 + }, + "member_folder_sub": { + "args": "info --quiet foo", + "cwd": "member/sub", + "output": "info_workspace_member_sub.out", + "exitCode": 0 + } + } +} diff --git a/tests/specs/info/workspace_member/deno.json b/tests/specs/info/workspace_member/deno.json new file mode 100644 index 0000000000..f88028aeab --- /dev/null +++ b/tests/specs/info/workspace_member/deno.json @@ -0,0 +1,3 @@ +{ + "workspace": ["./member"] +} diff --git a/tests/specs/info/workspace_member/info_workspace_member.out b/tests/specs/info/workspace_member/info_workspace_member.out new file mode 100644 index 0000000000..e0dc0b6753 --- /dev/null +++ b/tests/specs/info/workspace_member/info_workspace_member.out @@ -0,0 +1,6 @@ +local: [WILDCARD]file.ts +type: TypeScript +dependencies: 0 unique +size: [WILDCARD] + +file://[WILDCARD]/member/sub/file.ts ([WILDCARD]) diff --git a/tests/specs/info/workspace_member/info_workspace_member_sub.out b/tests/specs/info/workspace_member/info_workspace_member_sub.out new file mode 100644 index 0000000000..e0dc0b6753 --- /dev/null +++ b/tests/specs/info/workspace_member/info_workspace_member_sub.out @@ -0,0 +1,6 @@ +local: [WILDCARD]file.ts +type: TypeScript +dependencies: 0 unique +size: [WILDCARD] + +file://[WILDCARD]/member/sub/file.ts ([WILDCARD]) diff --git a/tests/specs/info/workspace_member/member/deno.json b/tests/specs/info/workspace_member/member/deno.json new file mode 100644 index 0000000000..66aac29046 --- /dev/null +++ b/tests/specs/info/workspace_member/member/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "foo": "./sub/file.ts" + } +} diff --git a/tests/specs/info/workspace_member/member/sub/file.ts b/tests/specs/info/workspace_member/member/sub/file.ts new file mode 100644 index 0000000000..cb0ff5c3b5 --- /dev/null +++ b/tests/specs/info/workspace_member/member/sub/file.ts @@ -0,0 +1 @@ +export {}; diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/__test__.jsonc b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/__test__.jsonc new file mode 100644 index 0000000000..9a149219db --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "run --allow-read=. verify.ts", + "output": "verify.out" + }] +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/deno.json b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/deno.json new file mode 100644 index 0000000000..bbd5b9946a --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "alias": "jsr:@denotest/add" + } +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/package.json b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/package.json new file mode 100644 index 0000000000..01835ee933 --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "alias": "npm:@denotest/esm-basic" + } +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.out b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.out new file mode 100644 index 0000000000..dad0ca2d8f --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.out @@ -0,0 +1,2 @@ +@denotest/esm-basic +[Module: null prototype] { add: [Function: add] } diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.ts b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.ts new file mode 100644 index 0000000000..835442322e --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_jsr_pkg/verify.ts @@ -0,0 +1,13 @@ +import * as mod from "alias"; + +const data = JSON.parse( + Deno.readTextFileSync( + new URL("./node_modules/alias/package.json", import.meta.url), + ), +); + +// this should just setup the npm package anyway, even though the alias +// will resolve to the jsr package +console.log(data.name); + +console.log(mod); diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/__test__.jsonc b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/__test__.jsonc new file mode 100644 index 0000000000..9a149219db --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "run --allow-read=. verify.ts", + "output": "verify.out" + }] +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/deno.json b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/deno.json new file mode 100644 index 0000000000..a1adfb35e2 --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "alias": "npm:@denotest/add" + } +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/package.json b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/package.json new file mode 100644 index 0000000000..01835ee933 --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "alias": "npm:@denotest/esm-basic" + } +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.out b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.out new file mode 100644 index 0000000000..8c989abd4a --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.out @@ -0,0 +1,5 @@ +@denotest/esm-basic +[Module: null prototype] { + add: [Function (anonymous)], + default: { add: [Function (anonymous)] } +} diff --git a/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.ts b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.ts new file mode 100644 index 0000000000..bcc0a5d877 --- /dev/null +++ b/tests/specs/install/alias_pkg_json_and_deno_json_npm_pkg/verify.ts @@ -0,0 +1,10 @@ +import * as mod from "alias"; + +const data = JSON.parse( + Deno.readTextFileSync( + new URL("./node_modules/alias/package.json", import.meta.url), + ), +); + +console.log(data.name); +console.log(mod); diff --git a/tests/specs/install/byonm_jsr_npm_dep/__test__.jsonc b/tests/specs/install/byonm_jsr_npm_dep/__test__.jsonc new file mode 100644 index 0000000000..ca7064aaf3 --- /dev/null +++ b/tests/specs/install/byonm_jsr_npm_dep/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "run main.ts", + "output": "3\n4\n" + }] +} diff --git a/tests/specs/install/byonm_jsr_npm_dep/deno.json b/tests/specs/install/byonm_jsr_npm_dep/deno.json new file mode 100644 index 0000000000..2127bd2860 --- /dev/null +++ b/tests/specs/install/byonm_jsr_npm_dep/deno.json @@ -0,0 +1,6 @@ +{ + "imports": { + "@denotest/npm-add": "jsr:@denotest/npm-add@1", + "@denotest/npm-add-0-5": "jsr:@denotest/npm-add@0.5" + } +} diff --git a/tests/specs/install/byonm_jsr_npm_dep/main.ts b/tests/specs/install/byonm_jsr_npm_dep/main.ts new file mode 100644 index 0000000000..a75e65bd88 --- /dev/null +++ b/tests/specs/install/byonm_jsr_npm_dep/main.ts @@ -0,0 +1,5 @@ +import { add } from "@denotest/npm-add"; +import { sum } from "@denotest/npm-add-0-5"; + +console.log(add(1, 2)); +console.log(sum(2, 2)); diff --git a/tests/specs/install/byonm_jsr_npm_dep/package.json b/tests/specs/install/byonm_jsr_npm_dep/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/install/byonm_jsr_npm_dep/package.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/install/byonm_run_tag_after_install/__test__.jsonc b/tests/specs/install/byonm_run_tag_after_install/__test__.jsonc new file mode 100644 index 0000000000..3803fd26f7 --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/__test__.jsonc @@ -0,0 +1,44 @@ +{ + "tempDir": true, + + "tests": { + "tag_with_byonm": { + "steps": [ + { + "args": "install", + "output": "[WILDCARD]" + }, + { + "args": "run -A main.ts", + "output": "" + } + ] + }, + "no_tag_then_tag": { + "steps": [ + { + "args": "run -A replace-version-req.ts 1.0.0", + "output": "" + }, + { + "args": "install", + "output": "[WILDCARD]" + }, + { + "args": "run -A replace-version-req.ts latest", + "output": "" + }, + { + "args": "run -A main.ts", + "output": "node_modules_out_of_date.out", + "exitCode": 1 + }, + { + "args": "install", + "output": "[WILDCARD]" + }, + { "args": "run -A main.ts", "output": "" } + ] + } + } +} diff --git a/tests/specs/install/byonm_run_tag_after_install/deno.json b/tests/specs/install/byonm_run_tag_after_install/deno.json new file mode 100644 index 0000000000..13238b1697 --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@denotest/esm-basic": "npm:@denotest/esm-basic@latest" + } +} diff --git a/tests/specs/install/byonm_run_tag_after_install/main.ts b/tests/specs/install/byonm_run_tag_after_install/main.ts new file mode 100644 index 0000000000..7feb95f96a --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/main.ts @@ -0,0 +1 @@ +import { add } from "@denotest/esm-basic"; diff --git a/tests/specs/install/byonm_run_tag_after_install/node_modules_out_of_date.out b/tests/specs/install/byonm_run_tag_after_install/node_modules_out_of_date.out new file mode 100644 index 0000000000..2d7fc81d17 --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/node_modules_out_of_date.out @@ -0,0 +1,2 @@ +error: Could not find a matching package for 'npm:@denotest/esm-basic@latest' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `"nodeModulesDir": "auto"` in your deno.json file. + at [WILDCARD]main.ts:1:21 diff --git a/tests/specs/install/byonm_run_tag_after_install/package.json b/tests/specs/install/byonm_run_tag_after_install/package.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/package.json @@ -0,0 +1 @@ +{} diff --git a/tests/specs/install/byonm_run_tag_after_install/replace-version-req.ts b/tests/specs/install/byonm_run_tag_after_install/replace-version-req.ts new file mode 100644 index 0000000000..6f86ce2b71 --- /dev/null +++ b/tests/specs/install/byonm_run_tag_after_install/replace-version-req.ts @@ -0,0 +1,7 @@ +const newReq = Deno.args[0]?.trim(); +if (!newReq) { + throw new Error("Missing required argument"); +} +const config = JSON.parse(Deno.readTextFileSync("deno.json")); +config.imports["@denotest/esm-basic"] = `npm:@denotest/esm-basic@${newReq}`; +Deno.writeTextFileSync("deno.json", JSON.stringify(config)); diff --git a/tests/specs/install/future_install_add_dist_tag/__test__.jsonc b/tests/specs/install/future_install_add_dist_tag/__test__.jsonc index a3247d1607..c1c7861887 100644 --- a/tests/specs/install/future_install_add_dist_tag/__test__.jsonc +++ b/tests/specs/install/future_install_add_dist_tag/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "steps": [ { - "envs": { - "DENO_FUTURE": "1" - }, "args": "install npm:ajv@latest", "output": "install.out" } diff --git a/tests/specs/install/future_install_global/__test__.jsonc b/tests/specs/install/future_install_global/__test__.jsonc index e646164c6f..8c5e0cdbd0 100644 --- a/tests/specs/install/future_install_global/__test__.jsonc +++ b/tests/specs/install/future_install_global/__test__.jsonc @@ -1,8 +1,5 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install --global --root ./bins --name deno-test-bin ./pkg/main.js", diff --git a/tests/specs/install/future_install_global/install.out b/tests/specs/install/future_install_global/install.out index 58cd88ada1..0fa1b97191 100644 --- a/tests/specs/install/future_install_global/install.out +++ b/tests/specs/install/future_install_global/install.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz ✅ Successfully installed deno-test-bin[WILDCARD] [WILDCARD] diff --git a/tests/specs/install/future_install_local_add_deno/__test__.jsonc b/tests/specs/install/future_install_local_add_deno/__test__.jsonc index eaafafbdd3..60112d8582 100644 --- a/tests/specs/install/future_install_local_add_deno/__test__.jsonc +++ b/tests/specs/install/future_install_local_add_deno/__test__.jsonc @@ -1,8 +1,5 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install npm:@denotest/esm-basic", diff --git a/tests/specs/install/future_install_local_add_deno/install.out b/tests/specs/install/future_install_local_add_deno/install.out index 93894a020c..2f73e5afb5 100644 --- a/tests/specs/install/future_install_local_add_deno/install.out +++ b/tests/specs/install/future_install_local_add_deno/install.out @@ -1,3 +1,3 @@ Add npm:@denotest/esm-basic@1.0.0 -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz diff --git a/tests/specs/install/future_install_local_add_npm/__test__.jsonc b/tests/specs/install/future_install_local_add_npm/__test__.jsonc index 19ded2ab56..35d1bfce26 100644 --- a/tests/specs/install/future_install_local_add_npm/__test__.jsonc +++ b/tests/specs/install/future_install_local_add_npm/__test__.jsonc @@ -1,8 +1,5 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install npm:@denotest/esm-basic", diff --git a/tests/specs/install/future_install_local_add_npm/install.out b/tests/specs/install/future_install_local_add_npm/install.out index 42161f3ae1..44bd9cac7e 100644 --- a/tests/specs/install/future_install_local_add_npm/install.out +++ b/tests/specs/install/future_install_local_add_npm/install.out @@ -1,4 +1,4 @@ Add npm:@denotest/esm-basic@1.0.0 -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/future_install_local_add_npm/package.json.out b/tests/specs/install/future_install_local_add_npm/package.json.out index ad8518e791..613d986360 100644 --- a/tests/specs/install/future_install_local_add_npm/package.json.out +++ b/tests/specs/install/future_install_local_add_npm/package.json.out @@ -1,3 +1,5 @@ { - "dependencies": { "@denotest/esm-basic": "^1.0.0" } + "dependencies": { + "@denotest/esm-basic": "^1.0.0" + } } diff --git a/tests/specs/install/future_install_local_deno/__test__.jsonc b/tests/specs/install/future_install_local_deno/__test__.jsonc index 928030699c..d257fbc1ff 100644 --- a/tests/specs/install/future_install_local_deno/__test__.jsonc +++ b/tests/specs/install/future_install_local_deno/__test__.jsonc @@ -1,16 +1,13 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { - "args": "install", + "args": "install --allow-import", "output": "install.out" }, { // ensure deps are actually cached - "args": "run --cached-only main.js", + "args": "run --cached-only --allow-import main.js", "output": "" }, { diff --git a/tests/specs/install/future_install_local_deno/deno.json b/tests/specs/install/future_install_local_deno/deno.json index dbcf1c2203..9213ce8347 100644 --- a/tests/specs/install/future_install_local_deno/deno.json +++ b/tests/specs/install/future_install_local_deno/deno.json @@ -3,6 +3,8 @@ "@std/fs/": "https://deno.land/std@0.224.0/fs/", "@denotest/esm-basic": "npm:@denotest/esm-basic@^1.0.0", "@denotest/add": "jsr:@denotest/add", - "test-http": "http://localhost:4545/v1/extensionless" + "test-http": "http://localhost:4545/v1/extensionless", + "@std/testing": "jsr:@std/testing", + "@std/testing/": "jsr:/@std/testing/" } } diff --git a/tests/specs/install/future_install_local_deno/deno.lock.out b/tests/specs/install/future_install_local_deno/deno.lock.out index 188de5de90..5c9582fff4 100644 --- a/tests/specs/install/future_install_local_deno/deno.lock.out +++ b/tests/specs/install/future_install_local_deno/deno.lock.out @@ -1,12 +1,16 @@ { "version": "4", "specifiers": { - "jsr:@denotest/add": "jsr:@denotest/add@1.0.0", - "npm:@denotest/esm-basic@^1.0.0": "npm:@denotest/esm-basic@1.0.0" + "jsr:@denotest/add@*": "1.0.0", + "jsr:@std/testing@*": "1.0.0", + "npm:@denotest/esm-basic@1": "1.0.0" }, "jsr": { "@denotest/add@1.0.0": { "integrity": "[WILDCARD]" + }, + "@std/testing@1.0.0": { + "integrity": "[WILDCARD]" } }, "npm": { @@ -14,11 +18,17 @@ "integrity": "[WILDCARD]" } }, - "remote": [WILDCARD], + "remote": { + "http://localhost:4545/subdir/mod1.ts": "[WILDCARD]", + "http://localhost:4545/subdir/print_hello.ts": "[WILDCARD]", + "http://localhost:4545/subdir/subdir2/mod2.ts": "[WILDCARD]", + "http://localhost:4545/v1/extensionless": "[WILDCARD]" + }, "workspace": { "dependencies": [ - "jsr:@denotest/add", - "npm:@denotest/esm-basic@^1.0.0" + "jsr:@denotest/add@*", + "jsr:@std/testing@*", + "npm:@denotest/esm-basic@1" ] } } diff --git a/tests/specs/install/future_install_local_deno/install.out b/tests/specs/install/future_install_local_deno/install.out index eecba12991..d0972f69e8 100644 --- a/tests/specs/install/future_install_local_deno/install.out +++ b/tests/specs/install/future_install_local_deno/install.out @@ -1,4 +1,6 @@ [UNORDERED_START] +Download http://127.0.0.1:4250/@std/testing/meta.json +Download http://127.0.0.1:4250/@std/testing/1.0.0_meta.json Download http://localhost:4545/v1/extensionless Download http://localhost:4545/subdir/mod1.ts Download http://localhost:4545/subdir/subdir2/mod2.ts @@ -6,6 +8,8 @@ Download http://localhost:4545/subdir/print_hello.ts Download http://127.0.0.1:4250/@denotest/add/meta.json Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Download http://127.0.0.1:4250/@std/testing/1.0.0/bdd.ts +Download http://127.0.0.1:4250/@std/testing/1.0.0/types.ts [UNORDERED_END] diff --git a/tests/specs/install/future_install_node_modules/__test__.jsonc b/tests/specs/install/future_install_node_modules/__test__.jsonc index c705ad0f81..94cd8ee2e1 100644 --- a/tests/specs/install/future_install_node_modules/__test__.jsonc +++ b/tests/specs/install/future_install_node_modules/__test__.jsonc @@ -2,9 +2,6 @@ "tests": { "install_sets_up_node_modules": { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install", @@ -27,9 +24,6 @@ }, "install_sets_up_node_modules_with_lockfile": { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install", @@ -65,9 +59,6 @@ }, "install_errors_corrupted_lockfile": { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install", diff --git a/tests/specs/install/future_install_node_modules/corrupted.out b/tests/specs/install/future_install_node_modules/corrupted.out index ade0757447..abfbeadda1 100644 --- a/tests/specs/install/future_install_node_modules/corrupted.out +++ b/tests/specs/install/future_install_node_modules/corrupted.out @@ -1,2 +1,2 @@ error: Integrity check failed for package: "npm:@denotest/esm-basic@1.0.0".[WILDCARD] -Use the --lock-write flag to regenerate the lockfile at [WILDCARD] \ No newline at end of file +Investigate the lockfile; delete it to regenerate the lockfile at [WILDCARD] \ No newline at end of file diff --git a/tests/specs/install/future_install_node_modules/deno.lock.out b/tests/specs/install/future_install_node_modules/deno.lock.out index c8071adadc..3a6ae85868 100644 --- a/tests/specs/install/future_install_node_modules/deno.lock.out +++ b/tests/specs/install/future_install_node_modules/deno.lock.out @@ -1,7 +1,7 @@ { "version": "4", "specifiers": { - "npm:@denotest/esm-basic": "npm:@denotest/esm-basic@1.0.0" + "npm:@denotest/esm-basic@*": "1.0.0" }, "npm": { "@denotest/esm-basic@1.0.0": { @@ -11,7 +11,7 @@ "workspace": { "packageJson": { "dependencies": [ - "npm:@denotest/esm-basic" + "npm:@denotest/esm-basic@*" ] } } diff --git a/tests/specs/install/future_install_node_modules/install.out b/tests/specs/install/future_install_node_modules/install.out index b8114c12a0..8f03ba6407 100644 --- a/tests/specs/install/future_install_node_modules/install.out +++ b/tests/specs/install/future_install_node_modules/install.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/future_install_node_modules_tag/__test__.jsonc b/tests/specs/install/future_install_node_modules_tag/__test__.jsonc index 31c53749a5..254fe8b989 100644 --- a/tests/specs/install/future_install_node_modules_tag/__test__.jsonc +++ b/tests/specs/install/future_install_node_modules_tag/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "steps": [ { - "envs": { - "DENO_FUTURE": "1" - }, "args": "install", "output": "install.out" } diff --git a/tests/specs/install/import_map_with_dir/__test__.jsonc b/tests/specs/install/import_map_with_dir/__test__.jsonc new file mode 100644 index 0000000000..cbbc7cc2e1 --- /dev/null +++ b/tests/specs/install/import_map_with_dir/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "" + } + ] +} diff --git a/tests/specs/install/import_map_with_dir/deno.json b/tests/specs/install/import_map_with_dir/deno.json new file mode 100644 index 0000000000..5c3224b071 --- /dev/null +++ b/tests/specs/install/import_map_with_dir/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@assets": "./src/assets/" + } +} diff --git a/tests/specs/install/install_add_dep_existing/__test__.jsonc b/tests/specs/install/install_add_dep_existing/__test__.jsonc new file mode 100644 index 0000000000..74c509a57d --- /dev/null +++ b/tests/specs/install/install_add_dep_existing/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install npm:@denotest/esm-basic", + "output": "install.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + } + ] +} diff --git a/tests/specs/install/install_add_dep_existing/install.out b/tests/specs/install/install_add_dep_existing/install.out new file mode 100644 index 0000000000..44bd9cac7e --- /dev/null +++ b/tests/specs/install/install_add_dep_existing/install.out @@ -0,0 +1,4 @@ +Add npm:@denotest/esm-basic@1.0.0 +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/install_add_dep_existing/package.json b/tests/specs/install/install_add_dep_existing/package.json new file mode 100644 index 0000000000..d5ca56e004 --- /dev/null +++ b/tests/specs/install/install_add_dep_existing/package.json @@ -0,0 +1,3 @@ +{ + "devDependencies": { "@denotest/esm-basic": "^1.0.0" } +} diff --git a/tests/specs/install/install_add_dep_existing/package.json.out b/tests/specs/install/install_add_dep_existing/package.json.out new file mode 100644 index 0000000000..613d986360 --- /dev/null +++ b/tests/specs/install/install_add_dep_existing/package.json.out @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "^1.0.0" + } +} diff --git a/tests/specs/install/install_add_dev/__test__.jsonc b/tests/specs/install/install_add_dev/__test__.jsonc new file mode 100644 index 0000000000..e4e2f8a31c --- /dev/null +++ b/tests/specs/install/install_add_dev/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install --dev npm:@denotest/esm-basic", + "output": "install.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + } + ] +} diff --git a/tests/specs/install/install_add_dev/install.out b/tests/specs/install/install_add_dev/install.out new file mode 100644 index 0000000000..44bd9cac7e --- /dev/null +++ b/tests/specs/install/install_add_dev/install.out @@ -0,0 +1,4 @@ +Add npm:@denotest/esm-basic@1.0.0 +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/install_add_dev/package.json b/tests/specs/install/install_add_dev/package.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tests/specs/install/install_add_dev/package.json @@ -0,0 +1 @@ +{} diff --git a/tests/specs/install/install_add_dev/package.json.out b/tests/specs/install/install_add_dev/package.json.out new file mode 100644 index 0000000000..866724397f --- /dev/null +++ b/tests/specs/install/install_add_dev/package.json.out @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@denotest/esm-basic": "^1.0.0" + } +} diff --git a/tests/specs/install/install_add_dev_existing/__test__.jsonc b/tests/specs/install/install_add_dev_existing/__test__.jsonc new file mode 100644 index 0000000000..e4e2f8a31c --- /dev/null +++ b/tests/specs/install/install_add_dev_existing/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install --dev npm:@denotest/esm-basic", + "output": "install.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + } + ] +} diff --git a/tests/specs/install/install_add_dev_existing/install.out b/tests/specs/install/install_add_dev_existing/install.out new file mode 100644 index 0000000000..44bd9cac7e --- /dev/null +++ b/tests/specs/install/install_add_dev_existing/install.out @@ -0,0 +1,4 @@ +Add npm:@denotest/esm-basic@1.0.0 +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/install_add_dev_existing/package.json b/tests/specs/install/install_add_dev_existing/package.json new file mode 100644 index 0000000000..ad8518e791 --- /dev/null +++ b/tests/specs/install/install_add_dev_existing/package.json @@ -0,0 +1,3 @@ +{ + "dependencies": { "@denotest/esm-basic": "^1.0.0" } +} diff --git a/tests/specs/install/install_add_dev_existing/package.json.out b/tests/specs/install/install_add_dev_existing/package.json.out new file mode 100644 index 0000000000..866724397f --- /dev/null +++ b/tests/specs/install/install_add_dev_existing/package.json.out @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@denotest/esm-basic": "^1.0.0" + } +} diff --git a/tests/specs/install/install_deprecated_package/__test__.jsonc b/tests/specs/install/install_deprecated_package/__test__.jsonc new file mode 100644 index 0000000000..bca03b510d --- /dev/null +++ b/tests/specs/install/install_deprecated_package/__test__.jsonc @@ -0,0 +1,22 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install npm:@denotest/deprecated-package", + "output": "install.out" + }, + { + // make sure the dep got cached + "args": "run --cached-only main.js", + "exitCode": 0, + "output": "" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + } + ] +} diff --git a/tests/specs/install/install_deprecated_package/install.out b/tests/specs/install/install_deprecated_package/install.out new file mode 100644 index 0000000000..32661d971d --- /dev/null +++ b/tests/specs/install/install_deprecated_package/install.out @@ -0,0 +1,6 @@ +Add npm:@denotest/deprecated-package@1.0.0 +Download http://localhost:4260/@denotest%2fdeprecated-package +Download http://localhost:4260/@denotest/deprecated-package/1.0.0.tgz +Initialize @denotest/deprecated-package@1.0.0 +Warning The following packages are deprecated: +┖─ npm:@denotest/deprecated-package@1.0.0 (Deprecated version) diff --git a/tests/specs/install/install_deprecated_package/main.js b/tests/specs/install/install_deprecated_package/main.js new file mode 100644 index 0000000000..de5026c50e --- /dev/null +++ b/tests/specs/install/install_deprecated_package/main.js @@ -0,0 +1,2 @@ +import { setValue } from "@denotest/deprecated-package"; +setValue(5); diff --git a/tests/specs/install/install_deprecated_package/package.json b/tests/specs/install/install_deprecated_package/package.json new file mode 100644 index 0000000000..18a1e415e5 --- /dev/null +++ b/tests/specs/install/install_deprecated_package/package.json @@ -0,0 +1,3 @@ +{ + "dependencies": {} +} diff --git a/tests/specs/install/install_deprecated_package/package.json.out b/tests/specs/install/install_deprecated_package/package.json.out new file mode 100644 index 0000000000..0cf36cd24f --- /dev/null +++ b/tests/specs/install/install_deprecated_package/package.json.out @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/deprecated-package": "^1.0.0" + } +} diff --git a/tests/specs/install/install_entrypoint/__test__.jsonc b/tests/specs/install/install_entrypoint/__test__.jsonc new file mode 100644 index 0000000000..1afe195e28 --- /dev/null +++ b/tests/specs/install/install_entrypoint/__test__.jsonc @@ -0,0 +1,21 @@ +{ + "tempDir": true, + "tests": { + "basic": { + "steps": [ + { + "args": "install --entrypoint main.ts second.ts", + "output": "install.out" + } + ] + }, + "allow_scripts": { + "steps": [ + { + "args": "install --allow-scripts --node-modules-dir=auto --entrypoint lifecycle.ts", + "output": "lifecycle.out" + } + ] + } + } +} diff --git a/tests/specs/install/install_entrypoint/install.out b/tests/specs/install/install_entrypoint/install.out new file mode 100644 index 0000000000..da10f3aa03 --- /dev/null +++ b/tests/specs/install/install_entrypoint/install.out @@ -0,0 +1,7 @@ +[UNORDERED_START] +Download http://127.0.0.1:4250/@denotest/add/meta.json +Download http://localhost:4260/@denotest%2fesm-basic +Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +[UNORDERED_END] diff --git a/tests/specs/install/install_entrypoint/lifecycle.out b/tests/specs/install/install_entrypoint/lifecycle.out new file mode 100644 index 0000000000..b302ea3341 --- /dev/null +++ b/tests/specs/install/install_entrypoint/lifecycle.out @@ -0,0 +1,11 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fnode-lifecycle-scripts +Download http://localhost:4260/@denotest%2fbin +Download http://localhost:4260/@denotest/node-lifecycle-scripts/1.0.0.tgz +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +Initialize @denotest/node-lifecycle-scripts@1.0.0 +Initialize @denotest/bin@1.0.0 +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'preinstall' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'install' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'postinstall' script +[UNORDERED_END] diff --git a/tests/specs/install/install_entrypoint/lifecycle.ts b/tests/specs/install/install_entrypoint/lifecycle.ts new file mode 100644 index 0000000000..e9fb2cf9cc --- /dev/null +++ b/tests/specs/install/install_entrypoint/lifecycle.ts @@ -0,0 +1,3 @@ +import { value } from "npm:@denotest/node-lifecycle-scripts"; + +console.log(`value is ${value}`); diff --git a/tests/specs/install/install_entrypoint/main.ts b/tests/specs/install/install_entrypoint/main.ts new file mode 100644 index 0000000000..aceb2b3c88 --- /dev/null +++ b/tests/specs/install/install_entrypoint/main.ts @@ -0,0 +1,4 @@ +import { getValue, setValue } from "npm:@denotest/esm-basic"; + +setValue(5); +console.log(getValue()); diff --git a/tests/specs/install/install_entrypoint/second.ts b/tests/specs/install/install_entrypoint/second.ts new file mode 100644 index 0000000000..2c781286f8 --- /dev/null +++ b/tests/specs/install/install_entrypoint/second.ts @@ -0,0 +1 @@ +import { add } from "jsr:@denotest/add@1.0.0"; diff --git a/tests/specs/install/install_single_http_url_without_global_flag/__test__.jsonc b/tests/specs/install/install_single_http_url_without_global_flag/__test__.jsonc new file mode 100644 index 0000000000..b906a846d0 --- /dev/null +++ b/tests/specs/install/install_single_http_url_without_global_flag/__test__.jsonc @@ -0,0 +1,14 @@ +{ + "steps": [ + { + "args": "install http://example.com", + "output": "install_http.out", + "exitCode": 1 + }, + { + "args": "install https://example.com", + "output": "install_https.out", + "exitCode": 1 + } + ] +} diff --git a/tests/specs/install/install_single_http_url_without_global_flag/install_http.out b/tests/specs/install/install_single_http_url_without_global_flag/install_http.out new file mode 100644 index 0000000000..17f4b286d0 --- /dev/null +++ b/tests/specs/install/install_single_http_url_without_global_flag/install_http.out @@ -0,0 +1,2 @@ +error: Failed to install "http" specifier. If you are trying to install http://example.com/ globally, run again with `-g` flag: + deno install -g http://example.com/ diff --git a/tests/specs/install/install_single_http_url_without_global_flag/install_https.out b/tests/specs/install/install_single_http_url_without_global_flag/install_https.out new file mode 100644 index 0000000000..87597de128 --- /dev/null +++ b/tests/specs/install/install_single_http_url_without_global_flag/install_https.out @@ -0,0 +1,2 @@ +error: Failed to install "https" specifier. If you are trying to install https://example.com/ globally, run again with `-g` flag: + deno install -g https://example.com/ diff --git a/tests/specs/install/jsr_exports/__test__.jsonc b/tests/specs/install/jsr_exports/__test__.jsonc new file mode 100644 index 0000000000..7ccc5da4d9 --- /dev/null +++ b/tests/specs/install/jsr_exports/__test__.jsonc @@ -0,0 +1,7 @@ +{ + "tempDir": true, + "steps": [ + { "args": "install", "output": "install.out" }, + { "args": "run --cached-only main.ts", "output": "main.out" } + ] +} diff --git a/tests/specs/install/jsr_exports/deno.json b/tests/specs/install/jsr_exports/deno.json new file mode 100644 index 0000000000..4b281f80ae --- /dev/null +++ b/tests/specs/install/jsr_exports/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@denotest/multiple-exports": "jsr:@denotest/multiple-exports@^1.0.0" + } +} diff --git a/tests/specs/install/jsr_exports/install.out b/tests/specs/install/jsr_exports/install.out new file mode 100644 index 0000000000..bce0d79bb3 --- /dev/null +++ b/tests/specs/install/jsr_exports/install.out @@ -0,0 +1,13 @@ +[UNORDERED_START] +Download http://127.0.0.1:4250/@denotest/multiple-exports/meta.json +Download http://127.0.0.1:4250/@denotest/multiple-exports/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/multiple-exports/1.0.0/add.ts +Download http://127.0.0.1:4250/@denotest/multiple-exports/1.0.0/subtract.ts +Download http://127.0.0.1:4250/@denotest/multiple-exports/1.0.0/data.json +Download http://127.0.0.1:4250/@denotest/add/meta.json +Download http://127.0.0.1:4250/@denotest/subtract/meta.json +Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/subtract/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts +Download http://127.0.0.1:4250/@denotest/subtract/1.0.0/mod.ts +[UNORDERED_END] diff --git a/tests/specs/install/jsr_exports/main.out b/tests/specs/install/jsr_exports/main.out new file mode 100644 index 0000000000..6ce184bada --- /dev/null +++ b/tests/specs/install/jsr_exports/main.out @@ -0,0 +1,3 @@ +3 +-1 +{ a: 1 } diff --git a/tests/specs/install/jsr_exports/main.ts b/tests/specs/install/jsr_exports/main.ts new file mode 100644 index 0000000000..f7efdb0e98 --- /dev/null +++ b/tests/specs/install/jsr_exports/main.ts @@ -0,0 +1,7 @@ +import { add } from "@denotest/multiple-exports/add"; +import { subtract } from "@denotest/multiple-exports/subtract"; +import data from "@denotest/multiple-exports/data-json" with { type: "json" }; + +console.log(add(1, 2)); +console.log(subtract(1, 2)); +console.log(data); diff --git a/tests/specs/install/move_after_install/__test__.jsonc b/tests/specs/install/move_after_install/__test__.jsonc new file mode 100644 index 0000000000..ff79f49cf2 --- /dev/null +++ b/tests/specs/install/move_after_install/__test__.jsonc @@ -0,0 +1,27 @@ +{ + "tempDir": true, + "steps": [ + { + "cwd": "./test-project", + "args": "install", + "output": "[WILDCARD]" + }, + { + "cwd": "./test-project", + "args": "run -A main.mjs", + "output": "5\n" + }, + { + "args": [ + "eval", + "Deno.renameSync('test-project', 'test-project-moved')" + ], + "output": "" + }, + { + "cwd": "./test-project-moved", + "args": "run -A main.mjs", + "output": "5\n" + } + ] +} diff --git a/tests/specs/install/move_after_install/test-project/main.mjs b/tests/specs/install/move_after_install/test-project/main.mjs new file mode 100644 index 0000000000..1beed6ef4e --- /dev/null +++ b/tests/specs/install/move_after_install/test-project/main.mjs @@ -0,0 +1,4 @@ +import { getValue, setValue } from "@denotest/esm-basic"; + +setValue(5); +console.log(getValue()); diff --git a/tests/specs/install/move_after_install/test-project/package.json b/tests/specs/install/move_after_install/test-project/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/install/move_after_install/test-project/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/specs/install/no_future_install_global/__test__.jsonc b/tests/specs/install/no_future_install_global/__test__.jsonc deleted file mode 100644 index 657cdab803..0000000000 --- a/tests/specs/install/no_future_install_global/__test__.jsonc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "tempDir": true, - "steps": [ - { - "args": "install --root ./bins --name deno-test-bin ./pkg/main.js", - "output": "install.out" - }, - { - "args": "run -A ./assert.js", - "output": "" - } - ] -} diff --git a/tests/specs/install/no_future_install_global/assert.js b/tests/specs/install/no_future_install_global/assert.js deleted file mode 100644 index c7a6a06807..0000000000 --- a/tests/specs/install/no_future_install_global/assert.js +++ /dev/null @@ -1,11 +0,0 @@ -const dirs = Deno.readDir("./bins/bin"); - -let found = false; -for await (const entry of dirs) { - if (entry.name.includes("deno-test-bin")) { - found = true; - } -} -if (!found) { - throw new Error("Failed to find test bin"); -} diff --git a/tests/specs/install/no_future_install_global/install.out b/tests/specs/install/no_future_install_global/install.out deleted file mode 100644 index b1933f536a..0000000000 --- a/tests/specs/install/no_future_install_global/install.out +++ /dev/null @@ -1,6 +0,0 @@ -⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag. -Download http://localhost:4260/@denotest/esm-basic -Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz -[# there shouldn't be a line saying it initialized the node_modules folder here because this is a global install] -✅ Successfully installed deno-test-bin[WILDCARD] -[WILDCARD] diff --git a/tests/specs/install/no_future_install_global/pkg/main.js b/tests/specs/install/no_future_install_global/pkg/main.js deleted file mode 100644 index 6268d71362..0000000000 --- a/tests/specs/install/no_future_install_global/pkg/main.js +++ /dev/null @@ -1,3 +0,0 @@ -import { setValue } from "npm:@denotest/esm-basic"; - -setValue(5); diff --git a/tests/specs/install/non_existent_optional_peer/__test__.jsonc b/tests/specs/install/non_existent_optional_peer/__test__.jsonc new file mode 100644 index 0000000000..b6527f614c --- /dev/null +++ b/tests/specs/install/non_existent_optional_peer/__test__.jsonc @@ -0,0 +1,11 @@ +// test imitates what crossws 0.2.4 has https://www.npmjs.com/package/crossws/v/0.2.4 +// where uWebSockets.js is an optional peer dep, but doesn't exist on npm +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + } + ] +} diff --git a/tests/specs/install/non_existent_optional_peer/install.out b/tests/specs/install/non_existent_optional_peer/install.out new file mode 100644 index 0000000000..694d4b51b8 --- /dev/null +++ b/tests/specs/install/non_existent_optional_peer/install.out @@ -0,0 +1,6 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fnon-existent-optional-peer +Download http://localhost:4260/uWebSockets.js +Download http://localhost:4260/@denotest/non-existent-optional-peer/1.0.0.tgz +[UNORDERED_END] +Initialize @denotest/non-existent-optional-peer@1.0.0 diff --git a/tests/specs/install/non_existent_optional_peer/package.json b/tests/specs/install/non_existent_optional_peer/package.json new file mode 100644 index 0000000000..c8216ee3d5 --- /dev/null +++ b/tests/specs/install/non_existent_optional_peer/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/non-existent-optional-peer": "1.0.0" + } +} diff --git a/tests/specs/install/type_only_import/__test__.jsonc b/tests/specs/install/type_only_import/__test__.jsonc new file mode 100644 index 0000000000..22b8134ac3 --- /dev/null +++ b/tests/specs/install/type_only_import/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [ + { "args": "install -e main.ts", "output": "install.out" }, + { + "args": "run --check --cached-only main.ts", + "output": "run.out" + } + ] +} diff --git a/tests/specs/install/type_only_import/install.out b/tests/specs/install/type_only_import/install.out new file mode 100644 index 0000000000..1bdbec4e58 --- /dev/null +++ b/tests/specs/install/type_only_import/install.out @@ -0,0 +1,6 @@ +Download http://127.0.0.1:4250/@denotest/type-only-import/meta.json +Download http://127.0.0.1:4250/@denotest/type-only-import/1.0.0_meta.json +[UNORDERED_START] +Download http://127.0.0.1:4250/@denotest/type-only-import/1.0.0/mod.ts +Download http://127.0.0.1:4250/@denotest/type-only-import/1.0.0/foo.ts +[UNORDERED_END] diff --git a/tests/specs/install/type_only_import/main.ts b/tests/specs/install/type_only_import/main.ts new file mode 100644 index 0000000000..bf22935a2d --- /dev/null +++ b/tests/specs/install/type_only_import/main.ts @@ -0,0 +1,3 @@ +import { foo } from "jsr:@denotest/type-only-import"; + +console.log(foo.bar); diff --git a/tests/specs/install/type_only_import/run.out b/tests/specs/install/type_only_import/run.out new file mode 100644 index 0000000000..d36ac8aa37 --- /dev/null +++ b/tests/specs/install/type_only_import/run.out @@ -0,0 +1,2 @@ +Check [WILDCARD]main.ts +foo diff --git a/tests/specs/install/workspace_member_with_tag_dep/__test__.jsonc b/tests/specs/install/workspace_member_with_tag_dep/__test__.jsonc new file mode 100644 index 0000000000..254fe8b989 --- /dev/null +++ b/tests/specs/install/workspace_member_with_tag_dep/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + } + ] +} diff --git a/tests/specs/install/workspace_member_with_tag_dep/install.out b/tests/specs/install/workspace_member_with_tag_dep/install.out new file mode 100644 index 0000000000..8f03ba6407 --- /dev/null +++ b/tests/specs/install/workspace_member_with_tag_dep/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/install/workspace_member_with_tag_dep/package.json b/tests/specs/install/workspace_member_with_tag_dep/package.json new file mode 100644 index 0000000000..58aa5d5cc6 --- /dev/null +++ b/tests/specs/install/workspace_member_with_tag_dep/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@denotest/esm-basic": "latest" + }, + "workspaces": ["package1"] +} diff --git a/tests/specs/install/workspace_member_with_tag_dep/package1/package.json b/tests/specs/install/workspace_member_with_tag_dep/package1/package.json new file mode 100644 index 0000000000..150a7df6af --- /dev/null +++ b/tests/specs/install/workspace_member_with_tag_dep/package1/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "latest" + } +} diff --git a/tests/specs/install/workspace_node_modules_not_exists/__test__.jsonc b/tests/specs/install/workspace_node_modules_not_exists/__test__.jsonc new file mode 100644 index 0000000000..a39eb5e1f7 --- /dev/null +++ b/tests/specs/install/workspace_node_modules_not_exists/__test__.jsonc @@ -0,0 +1,15 @@ +// Regression test for https://github.com/denoland/deno/issues/25493 +// +// `deno install` where we need to create a `node_modules` for a workspace member +// due to conflicting package versions, but when we go to set it up, the +// symlink target path (`package2/node_modules/chalk`) has `node_modules` as its parent, +// and it doesn't exist yet +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + } + ] +} diff --git a/tests/specs/install/workspace_node_modules_not_exists/deno.json b/tests/specs/install/workspace_node_modules_not_exists/deno.json new file mode 100644 index 0000000000..b3cca048fd --- /dev/null +++ b/tests/specs/install/workspace_node_modules_not_exists/deno.json @@ -0,0 +1,7 @@ +{ + "nodeModulesDir": "auto", + "workspace": [ + "./package1", + "./package2" + ] +} diff --git a/tests/specs/install/workspace_node_modules_not_exists/install.out b/tests/specs/install/workspace_node_modules_not_exists/install.out new file mode 100644 index 0000000000..22f7e43072 --- /dev/null +++ b/tests/specs/install/workspace_node_modules_not_exists/install.out @@ -0,0 +1,22 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/chalk/chalk-5.0.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize supports-color@7.2.0 +Initialize chalk@4.1.2 +Initialize ansi-styles@4.3.0 +Initialize color-name@1.1.4 +Initialize color-convert@2.0.1 +Initialize has-flag@4.0.0 +Initialize chalk@5.0.1 +[UNORDERED_END] diff --git a/tests/specs/install/workspace_node_modules_not_exists/package1/package.json b/tests/specs/install/workspace_node_modules_not_exists/package1/package.json new file mode 100644 index 0000000000..0c5e77484b --- /dev/null +++ b/tests/specs/install/workspace_node_modules_not_exists/package1/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "chalk": "4.1.2" + } +} diff --git a/tests/specs/install/workspace_node_modules_not_exists/package2/package.json b/tests/specs/install/workspace_node_modules_not_exists/package2/package.json new file mode 100644 index 0000000000..48d3d69170 --- /dev/null +++ b/tests/specs/install/workspace_node_modules_not_exists/package2/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "chalk": "5.0.1" + } +} diff --git a/tests/specs/jsr/module_graph/main.out b/tests/specs/jsr/module_graph/main.out index 35905a63a2..d17238a9c2 100644 --- a/tests/specs/jsr/module_graph/main.out +++ b/tests/specs/jsr/module_graph/main.out @@ -1,4 +1,4 @@ -[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph/1.4.0/mod.ts +[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph/1.4.0/other.ts [WILDCARD] Test { other: Other {} } [WILDCARD] diff --git a/tests/specs/jsr/module_graph2/main.out b/tests/specs/jsr/module_graph2/main.out index ba2c06aaa4..fca91e2399 100644 --- a/tests/specs/jsr/module_graph2/main.out +++ b/tests/specs/jsr/module_graph2/main.out @@ -1,4 +1,4 @@ -[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph2/1.4.0/mod.ts +[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph2/1.4.0/other.ts [WILDCARD] Test { other: Other {} } [WILDCARD] diff --git a/tests/specs/lint/all/__test__.jsonc b/tests/specs/lint/all/__test__.jsonc new file mode 100644 index 0000000000..0583ceca96 --- /dev/null +++ b/tests/specs/lint/all/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint file1.js file2.ts ignored_file.ts", + "output": "expected.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected.out b/tests/specs/lint/all/expected.out similarity index 100% rename from tests/testdata/lint/expected.out rename to tests/specs/lint/all/expected.out diff --git a/tests/testdata/lint/without_config/file1.js b/tests/specs/lint/all/file1.js similarity index 100% rename from tests/testdata/lint/without_config/file1.js rename to tests/specs/lint/all/file1.js diff --git a/tests/testdata/lint/without_config/file2.ts b/tests/specs/lint/all/file2.ts similarity index 100% rename from tests/testdata/lint/without_config/file2.ts rename to tests/specs/lint/all/file2.ts diff --git a/tests/testdata/lint/without_config/ignored_file.ts b/tests/specs/lint/all/ignored_file.ts similarity index 100% rename from tests/testdata/lint/without_config/ignored_file.ts rename to tests/specs/lint/all/ignored_file.ts diff --git a/tests/specs/lint/compact/__test__.jsonc b/tests/specs/lint/compact/__test__.jsonc new file mode 100644 index 0000000000..d5e1eef546 --- /dev/null +++ b/tests/specs/lint/compact/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --compact file1.js ignored_file.tss", + "output": "expected_compact.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_compact.out b/tests/specs/lint/compact/expected_compact.out similarity index 100% rename from tests/testdata/lint/expected_compact.out rename to tests/specs/lint/compact/expected_compact.out diff --git a/tests/specs/lint/compact/file1.js b/tests/specs/lint/compact/file1.js new file mode 100644 index 0000000000..737f26818b --- /dev/null +++ b/tests/specs/lint/compact/file1.js @@ -0,0 +1,2 @@ +// deno-lint-ignore +while (false) {} diff --git a/tests/specs/lint/default_ts/__test__.jsonc b/tests/specs/lint/default_ts/__test__.jsonc new file mode 100644 index 0000000000..d7c618a5a7 --- /dev/null +++ b/tests/specs/lint/default_ts/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "tests": { + "stdin": { + "args": "lint -", + "input": "const _x: string = \"foo\";", + "output": "Checked 1 file\n" + }, + "ext_flag": { + "args": "lint --ext=ts as_ts.js", + "output": "Checked 1 file\n" + }, + "extensionless": { + "args": "lint extensionless", + "output": "error: No target files found.\n", + "exitCode": 1 + }, + "extensionless_with_flag": { + "args": "lint --ext=ts extensionless", + "output": "Checked 1 file\n" + } + } +} diff --git a/tests/specs/lint/default_ts/as_ts.js b/tests/specs/lint/default_ts/as_ts.js new file mode 100644 index 0000000000..3508e99b63 --- /dev/null +++ b/tests/specs/lint/default_ts/as_ts.js @@ -0,0 +1 @@ +const _x: string = "foo"; diff --git a/tests/specs/lint/default_ts/extensionless b/tests/specs/lint/default_ts/extensionless new file mode 100644 index 0000000000..3508e99b63 --- /dev/null +++ b/tests/specs/lint/default_ts/extensionless @@ -0,0 +1 @@ +const _x: string = "foo"; diff --git a/tests/specs/lint/glob/__test__.jsonc b/tests/specs/lint/glob/__test__.jsonc new file mode 100644 index 0000000000..454a55804b --- /dev/null +++ b/tests/specs/lint/glob/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --ignore=without_config/malformed.js,with_config/ without_config/", + "output": "expected_glob.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_glob.out b/tests/specs/lint/glob/expected_glob.out similarity index 100% rename from tests/testdata/lint/expected_glob.out rename to tests/specs/lint/glob/expected_glob.out diff --git a/tests/testdata/lint/with_config/a.ts b/tests/specs/lint/glob/with_config/a.ts similarity index 100% rename from tests/testdata/lint/with_config/a.ts rename to tests/specs/lint/glob/with_config/a.ts diff --git a/tests/testdata/lint/with_config/b.ts b/tests/specs/lint/glob/with_config/b.ts similarity index 100% rename from tests/testdata/lint/with_config/b.ts rename to tests/specs/lint/glob/with_config/b.ts diff --git a/tests/specs/lint/glob/without_config/file1.js b/tests/specs/lint/glob/without_config/file1.js new file mode 100644 index 0000000000..737f26818b --- /dev/null +++ b/tests/specs/lint/glob/without_config/file1.js @@ -0,0 +1,2 @@ +// deno-lint-ignore +while (false) {} diff --git a/tests/specs/lint/glob/without_config/file2.ts b/tests/specs/lint/glob/without_config/file2.ts new file mode 100644 index 0000000000..73c612c35f --- /dev/null +++ b/tests/specs/lint/glob/without_config/file2.ts @@ -0,0 +1,6 @@ +try { + await Deno.open("./some/file.txt"); +} catch (_e) {} + +// deno-lint-ignore no-explicit-any +function _foo(): any {} diff --git a/tests/specs/lint/glob/without_config/ignored_file.ts b/tests/specs/lint/glob/without_config/ignored_file.ts new file mode 100644 index 0000000000..97befafa38 --- /dev/null +++ b/tests/specs/lint/glob/without_config/ignored_file.ts @@ -0,0 +1,3 @@ +// deno-lint-ignore-file + +function foo(): any {} diff --git a/tests/testdata/lint/without_config/malformed.js b/tests/specs/lint/glob/without_config/malformed.js similarity index 100% rename from tests/testdata/lint/without_config/malformed.js rename to tests/specs/lint/glob/without_config/malformed.js diff --git a/tests/specs/lint/ignore/__test__.jsonc b/tests/specs/lint/ignore/__test__.jsonc new file mode 100644 index 0000000000..5bbe237ce8 --- /dev/null +++ b/tests/specs/lint/ignore/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --ignore=without_config/file1.js,without_config/malformed.js,without_config/lint_with_config/ without_config", + "output": "expected_ignore.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_ignore.out b/tests/specs/lint/ignore/expected_ignore.out similarity index 100% rename from tests/testdata/lint/expected_ignore.out rename to tests/specs/lint/ignore/expected_ignore.out diff --git a/tests/specs/lint/ignore/without_config/file1.js b/tests/specs/lint/ignore/without_config/file1.js new file mode 100644 index 0000000000..737f26818b --- /dev/null +++ b/tests/specs/lint/ignore/without_config/file1.js @@ -0,0 +1,2 @@ +// deno-lint-ignore +while (false) {} diff --git a/tests/specs/lint/ignore/without_config/file2.ts b/tests/specs/lint/ignore/without_config/file2.ts new file mode 100644 index 0000000000..73c612c35f --- /dev/null +++ b/tests/specs/lint/ignore/without_config/file2.ts @@ -0,0 +1,6 @@ +try { + await Deno.open("./some/file.txt"); +} catch (_e) {} + +// deno-lint-ignore no-explicit-any +function _foo(): any {} diff --git a/tests/specs/lint/ignore/without_config/ignored_file.ts b/tests/specs/lint/ignore/without_config/ignored_file.ts new file mode 100644 index 0000000000..97befafa38 --- /dev/null +++ b/tests/specs/lint/ignore/without_config/ignored_file.ts @@ -0,0 +1,3 @@ +// deno-lint-ignore-file + +function foo(): any {} diff --git a/tests/specs/lint/ignore/without_config/malformed.js b/tests/specs/lint/ignore/without_config/malformed.js new file mode 100644 index 0000000000..9b64da898c --- /dev/null +++ b/tests/specs/lint/ignore/without_config/malformed.js @@ -0,0 +1,4 @@ +// deno-fmt-ignore-file + +// intentionally malformed file +export class A B C \ No newline at end of file diff --git a/tests/specs/lint/ignore_unexplicit_files/__test__.jsonc b/tests/specs/lint/ignore_unexplicit_files/__test__.jsonc new file mode 100644 index 0000000000..7653c4e255 --- /dev/null +++ b/tests/specs/lint/ignore_unexplicit_files/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --ignore=./", + "output": "lint.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/ignore_unexplicit_files/lint.out b/tests/specs/lint/ignore_unexplicit_files/lint.out new file mode 100644 index 0000000000..33f4ddd933 --- /dev/null +++ b/tests/specs/lint/ignore_unexplicit_files/lint.out @@ -0,0 +1 @@ +error: No target files found. diff --git a/tests/specs/lint/json/__test__.jsonc b/tests/specs/lint/json/__test__.jsonc new file mode 100644 index 0000000000..fb577c0dd7 --- /dev/null +++ b/tests/specs/lint/json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --json file1.js file2.ts ignored_file.ts malformed.js", + "output": "expected_json.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_json.out b/tests/specs/lint/json/expected_json.out similarity index 98% rename from tests/testdata/lint/expected_json.out rename to tests/specs/lint/json/expected_json.out index 95c3d30ba4..6712c891a5 100644 --- a/tests/testdata/lint/expected_json.out +++ b/tests/specs/lint/json/expected_json.out @@ -1,4 +1,5 @@ { + "version": 1, "diagnostics": [ { "filename": "[WILDCARD]file1.js", diff --git a/tests/specs/lint/json/file1.js b/tests/specs/lint/json/file1.js new file mode 100644 index 0000000000..737f26818b --- /dev/null +++ b/tests/specs/lint/json/file1.js @@ -0,0 +1,2 @@ +// deno-lint-ignore +while (false) {} diff --git a/tests/specs/lint/json/file2.ts b/tests/specs/lint/json/file2.ts new file mode 100644 index 0000000000..73c612c35f --- /dev/null +++ b/tests/specs/lint/json/file2.ts @@ -0,0 +1,6 @@ +try { + await Deno.open("./some/file.txt"); +} catch (_e) {} + +// deno-lint-ignore no-explicit-any +function _foo(): any {} diff --git a/tests/specs/lint/json/ignored_file.ts b/tests/specs/lint/json/ignored_file.ts new file mode 100644 index 0000000000..97befafa38 --- /dev/null +++ b/tests/specs/lint/json/ignored_file.ts @@ -0,0 +1,3 @@ +// deno-lint-ignore-file + +function foo(): any {} diff --git a/tests/specs/lint/json/malformed.js b/tests/specs/lint/json/malformed.js new file mode 100644 index 0000000000..9b64da898c --- /dev/null +++ b/tests/specs/lint/json/malformed.js @@ -0,0 +1,4 @@ +// deno-fmt-ignore-file + +// intentionally malformed file +export class A B C \ No newline at end of file diff --git a/tests/specs/lint/jsr_pkg_no_version/__test__.jsonc b/tests/specs/lint/jsr_pkg_no_version/__test__.jsonc new file mode 100644 index 0000000000..d1783f1dcf --- /dev/null +++ b/tests/specs/lint/jsr_pkg_no_version/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint", + "output": "lint.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/jsr_pkg_no_version/deno.json b/tests/specs/lint/jsr_pkg_no_version/deno.json new file mode 100644 index 0000000000..50d49ffb64 --- /dev/null +++ b/tests/specs/lint/jsr_pkg_no_version/deno.json @@ -0,0 +1,4 @@ +{ + "name": "@scope/pkg", + "exports": "./mod.ts" +} diff --git a/tests/specs/lint/jsr_pkg_no_version/lint.out b/tests/specs/lint/jsr_pkg_no_version/lint.out new file mode 100644 index 0000000000..2084995902 --- /dev/null +++ b/tests/specs/lint/jsr_pkg_no_version/lint.out @@ -0,0 +1,14 @@ +error[no-slow-types]: missing explicit return type in the public API + --> [WILDLINE]:1:17 + | +1 | export function test() { + | ^^^^ this function is missing an explicit return type + | + = hint: add an explicit return type to the function + + info: all functions in the public API must have an explicit return type + docs: https://jsr.io/go/slow-type-missing-explicit-return-type + + +Found 1 problem +Checked 1 file diff --git a/tests/specs/lint/jsr_pkg_no_version/mod.ts b/tests/specs/lint/jsr_pkg_no_version/mod.ts new file mode 100644 index 0000000000..02abbfe2fd --- /dev/null +++ b/tests/specs/lint/jsr_pkg_no_version/mod.ts @@ -0,0 +1,3 @@ +export function test() { + return 1 + 2; +} diff --git a/tests/specs/lint/jsx/__test__.jsonc b/tests/specs/lint/jsx/__test__.jsonc new file mode 100644 index 0000000000..b929e12d45 --- /dev/null +++ b/tests/specs/lint/jsx/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "steps": [ + { + "args": "lint", + "cwd": "./react", + "output": "react.out", + "exitCode": 0 + }, + { + "args": "lint", + "cwd": "./react-jsx", + "output": "react-jsx.out", + "exitCode": 1 + } + ] +} diff --git a/tests/specs/lint/jsx/react-jsx.out b/tests/specs/lint/jsx/react-jsx.out new file mode 100644 index 0000000000..c8c7007791 --- /dev/null +++ b/tests/specs/lint/jsx/react-jsx.out @@ -0,0 +1,12 @@ +error[no-unused-vars]: `React` is never used + --> [WILDCARD]mod.tsx:1:7 + | +1 | const React = { createElement() {} }; + | ^^^^^ + = hint: If this is intentional, prefix it with an underscore like `_React` + + docs: https://lint.deno.land/rules/no-unused-vars + + +Found 1 problem +Checked 1 file diff --git a/tests/specs/lint/jsx/react-jsx/deno.json b/tests/specs/lint/jsx/react-jsx/deno.json new file mode 100644 index 0000000000..a224293f4e --- /dev/null +++ b/tests/specs/lint/jsx/react-jsx/deno.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsx": "react-jsx" + } +} diff --git a/tests/specs/lint/jsx/react-jsx/mod.tsx b/tests/specs/lint/jsx/react-jsx/mod.tsx new file mode 100644 index 0000000000..be1e843c14 --- /dev/null +++ b/tests/specs/lint/jsx/react-jsx/mod.tsx @@ -0,0 +1,3 @@ +const React = { createElement() {} }; + +const _div =
; diff --git a/tests/specs/lint/jsx/react.out b/tests/specs/lint/jsx/react.out new file mode 100644 index 0000000000..c05ac45a1e --- /dev/null +++ b/tests/specs/lint/jsx/react.out @@ -0,0 +1 @@ +Checked 1 file diff --git a/tests/specs/lint/jsx/react/deno.json b/tests/specs/lint/jsx/react/deno.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tests/specs/lint/jsx/react/deno.json @@ -0,0 +1 @@ +{} diff --git a/tests/specs/lint/jsx/react/mod.tsx b/tests/specs/lint/jsx/react/mod.tsx new file mode 100644 index 0000000000..be1e843c14 --- /dev/null +++ b/tests/specs/lint/jsx/react/mod.tsx @@ -0,0 +1,3 @@ +const React = { createElement() {} }; + +const _div =
; diff --git a/tests/specs/lint/node_globals_no_duplicate_imports/__test__.jsonc b/tests/specs/lint/node_globals_no_duplicate_imports/__test__.jsonc index d8e00f47ad..3feb6eaba9 100644 --- a/tests/specs/lint/node_globals_no_duplicate_imports/__test__.jsonc +++ b/tests/specs/lint/node_globals_no_duplicate_imports/__test__.jsonc @@ -3,7 +3,7 @@ "steps": [ { "args": "run main.ts", - "output": "error.out", + "output": "main.out", "exitCode": 1 }, { diff --git a/tests/specs/lint/node_globals_no_duplicate_imports/error.out b/tests/specs/lint/node_globals_no_duplicate_imports/error.out deleted file mode 100644 index 5671b17b46..0000000000 --- a/tests/specs/lint/node_globals_no_duplicate_imports/error.out +++ /dev/null @@ -1,4 +0,0 @@ -error: Uncaught (in promise) ReferenceError: process is not defined -const _foo = process.env.FOO; - ^ - at [WILDCARD]main.ts:3:14 diff --git a/tests/specs/lint/node_globals_no_duplicate_imports/lint.out b/tests/specs/lint/node_globals_no_duplicate_imports/lint.out index b396e71ebd..d9ff7f77e2 100644 --- a/tests/specs/lint/node_globals_no_duplicate_imports/lint.out +++ b/tests/specs/lint/node_globals_no_duplicate_imports/lint.out @@ -1,9 +1,9 @@ error[no-node-globals]: NodeJS globals are not available in Deno --> [WILDCARD]main.ts:3:14 | -3 | const _foo = process.env.FOO; - | ^^^^^^^ - = hint: Add `import process from "node:process";` +3 | const _foo = setImmediate; + | ^^^^^^^^^^^^ + = hint: Add `import { setImmediate } from "node:timers";` docs: https://lint.deno.land/rules/no-node-globals @@ -11,9 +11,9 @@ error[no-node-globals]: NodeJS globals are not available in Deno error[no-node-globals]: NodeJS globals are not available in Deno --> [WILDCARD]main.ts:7:14 | -7 | const _bar = process.env.BAR; - | ^^^^^^^ - = hint: Add `import process from "node:process";` +7 | const _bar = setImmediate; + | ^^^^^^^^^^^^ + = hint: Add `import { setImmediate } from "node:timers";` docs: https://lint.deno.land/rules/no-node-globals diff --git a/tests/specs/lint/node_globals_no_duplicate_imports/main.out b/tests/specs/lint/node_globals_no_duplicate_imports/main.out new file mode 100644 index 0000000000..56df10eba4 --- /dev/null +++ b/tests/specs/lint/node_globals_no_duplicate_imports/main.out @@ -0,0 +1,4 @@ +error: Uncaught (in promise) ReferenceError: setImmediate is not defined +const _foo = setImmediate; + ^ + at [WILDCARD]main.ts:3:14 diff --git a/tests/specs/lint/node_globals_no_duplicate_imports/main.ts b/tests/specs/lint/node_globals_no_duplicate_imports/main.ts index bff428d012..73ccb255e1 100644 --- a/tests/specs/lint/node_globals_no_duplicate_imports/main.ts +++ b/tests/specs/lint/node_globals_no_duplicate_imports/main.ts @@ -1,7 +1,7 @@ import {} from "node:console"; -const _foo = process.env.FOO; +const _foo = setImmediate; import {} from "node:assert"; -const _bar = process.env.BAR; +const _bar = setImmediate; diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/__test__.jsonc b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/__test__.jsonc new file mode 100644 index 0000000000..ce4db1883a --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "steps": [ + { + "if": "windows", + "args": "lint", + "output": "main_windows.out", + "exitCode": 1 + }, + { + "if": "unix", + "args": "lint", + "output": "main_unix.out", + "exitCode": 1 + } + ] +} diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/actually_excluded.ts b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/actually_excluded.ts new file mode 100644 index 0000000000..dd2bcc6112 --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/actually_excluded.ts @@ -0,0 +1 @@ +const a = 2; diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/deno.json b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/deno.json new file mode 100644 index 0000000000..a7689f16d6 --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/deno.json @@ -0,0 +1,6 @@ +{ + "lint": { + "exclude": ["!excluded.ts"] + }, + "exclude": ["excluded.ts", "actually_excluded.ts"] +} diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/excluded.ts b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/excluded.ts new file mode 100644 index 0000000000..dd2bcc6112 --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/excluded.ts @@ -0,0 +1 @@ +const a = 2; diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main.ts b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main.ts new file mode 100644 index 0000000000..54b82a09ad --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main.ts @@ -0,0 +1 @@ +const a = 1; diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_unix.out b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_unix.out new file mode 100644 index 0000000000..39a3e7746c --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_unix.out @@ -0,0 +1,24 @@ +[UNORDERED_START] +error[no-unused-vars]: `a` is never used + --> [WILDLINE]lint/opt_out_top_level_exclude_via_lint_inexclude/main.ts:1:7 + | +1 | const a = 1; + | ^ + = hint: If this is intentional, prefix it with an underscore like `_a` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `a` is never used + --> [WILDLINE]lint/opt_out_top_level_exclude_via_lint_inexclude/excluded.ts:1:7 + | +1 | const a = 2; + | ^ + = hint: If this is intentional, prefix it with an underscore like `_a` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 2 problems +Checked 2 files diff --git a/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_windows.out b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_windows.out new file mode 100644 index 0000000000..8edf1133ea --- /dev/null +++ b/tests/specs/lint/opt_out_top_level_exclude_via_lint_inexclude/main_windows.out @@ -0,0 +1,24 @@ +[UNORDERED_START] +error[no-unused-vars]: `a` is never used + --> [WILDLINE]lint\opt_out_top_level_exclude_via_lint_inexclude\main.ts:1:7 + | +1 | const a = 1; + | ^ + = hint: If this is intentional, prefix it with an underscore like `_a` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `a` is never used + --> [WILDLINE]lint\opt_out_top_level_exclude_via_lint_inexclude\excluded.ts:1:7 + | +1 | const a = 2; + | ^ + = hint: If this is intentional, prefix it with an underscore like `_a` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 2 problems +Checked 2 files diff --git a/tests/specs/lint/quiet/__test__.jsonc b/tests/specs/lint/quiet/__test__.jsonc new file mode 100644 index 0000000000..44434f7a1c --- /dev/null +++ b/tests/specs/lint/quiet/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --quiet ", + "output": "expected_quiet.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_quiet.out b/tests/specs/lint/quiet/expected_quiet.out similarity index 100% rename from tests/testdata/lint/expected_quiet.out rename to tests/specs/lint/quiet/expected_quiet.out diff --git a/tests/specs/lint/quiet/file1.js b/tests/specs/lint/quiet/file1.js new file mode 100644 index 0000000000..737f26818b --- /dev/null +++ b/tests/specs/lint/quiet/file1.js @@ -0,0 +1,2 @@ +// deno-lint-ignore +while (false) {} diff --git a/tests/specs/lint/rules/__test__.jsonc b/tests/specs/lint/rules/__test__.jsonc new file mode 100644 index 0000000000..d1b330b9ae --- /dev/null +++ b/tests/specs/lint/rules/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --rules", + "output": "expected_rules.out", + "exitCode": 0 +} diff --git a/tests/testdata/lint/expected_rules.out b/tests/specs/lint/rules/expected_rules.out similarity index 100% rename from tests/testdata/lint/expected_rules.out rename to tests/specs/lint/rules/expected_rules.out diff --git a/tests/specs/lint/rules_quiet/__test__.jsonc b/tests/specs/lint/rules_quiet/__test__.jsonc new file mode 100644 index 0000000000..0e7cc1a132 --- /dev/null +++ b/tests/specs/lint/rules_quiet/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --rules -q", + "output": "expected_rules.out", + "exitCode": 0 +} diff --git a/tests/specs/lint/rules_quiet/expected_rules.out b/tests/specs/lint/rules_quiet/expected_rules.out new file mode 100644 index 0000000000..4afab7b9bf --- /dev/null +++ b/tests/specs/lint/rules_quiet/expected_rules.out @@ -0,0 +1,2 @@ +Available rules: +[WILDCARD] diff --git a/tests/specs/lint/stdin/__test__.jsonc b/tests/specs/lint/stdin/__test__.jsonc new file mode 100644 index 0000000000..f6c688c16e --- /dev/null +++ b/tests/specs/lint/stdin/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint main.ts", + "output": "expected_from_stdin.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_from_stdin.out b/tests/specs/lint/stdin/expected_from_stdin.out similarity index 86% rename from tests/testdata/lint/expected_from_stdin.out rename to tests/specs/lint/stdin/expected_from_stdin.out index 735b271f52..f65331ebd9 100644 --- a/tests/testdata/lint/expected_from_stdin.out +++ b/tests/specs/lint/stdin/expected_from_stdin.out @@ -1,5 +1,5 @@ error[no-explicit-any]: `any` type is not allowed - --> [WILDCARD]$deno$stdin.ts:1:9 + --> [WILDCARD]main.ts:1:9 | 1 | let _a: any; | ^^^ diff --git a/tests/specs/lint/stdin/main.ts b/tests/specs/lint/stdin/main.ts new file mode 100644 index 0000000000..8abcd79b87 --- /dev/null +++ b/tests/specs/lint/stdin/main.ts @@ -0,0 +1 @@ +let _a: any; diff --git a/tests/specs/lint/stdin_json/__test__.jsonc b/tests/specs/lint/stdin_json/__test__.jsonc new file mode 100644 index 0000000000..a777147f6c --- /dev/null +++ b/tests/specs/lint/stdin_json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --json main.ts", + "output": "expected_from_stdin_json.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/expected_from_stdin_json.out b/tests/specs/lint/stdin_json/expected_from_stdin_json.out similarity index 87% rename from tests/testdata/lint/expected_from_stdin_json.out rename to tests/specs/lint/stdin_json/expected_from_stdin_json.out index 9e1188bcdb..5788248aa2 100644 --- a/tests/testdata/lint/expected_from_stdin_json.out +++ b/tests/specs/lint/stdin_json/expected_from_stdin_json.out @@ -1,7 +1,8 @@ { + "version": 1, "diagnostics": [ { - "filename": "[WILDCARD]$deno$stdin.ts", + "filename": "[WILDCARD]main.ts", "range": { "start": { "line": 1, diff --git a/tests/specs/lint/stdin_json/main.ts b/tests/specs/lint/stdin_json/main.ts new file mode 100644 index 0000000000..8abcd79b87 --- /dev/null +++ b/tests/specs/lint/stdin_json/main.ts @@ -0,0 +1 @@ +let _a: any; diff --git a/tests/testdata/lint/Deno.jsonc b/tests/specs/lint/with_config/Deno.jsonc similarity index 100% rename from tests/testdata/lint/Deno.jsonc rename to tests/specs/lint/with_config/Deno.jsonc diff --git a/tests/specs/lint/with_config/__test__.jsonc b/tests/specs/lint/with_config/__test__.jsonc new file mode 100644 index 0000000000..1e9bf97512 --- /dev/null +++ b/tests/specs/lint/with_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.jsonc with_config/", + "output": "with_config.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/with_config.out b/tests/specs/lint/with_config/with_config.out similarity index 100% rename from tests/testdata/lint/with_config.out rename to tests/specs/lint/with_config/with_config.out diff --git a/tests/specs/lint/with_config/with_config/a.ts b/tests/specs/lint/with_config/with_config/a.ts new file mode 100644 index 0000000000..c378218a32 --- /dev/null +++ b/tests/specs/lint/with_config/with_config/a.ts @@ -0,0 +1,4 @@ +// TODO: foo +function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/lint/with_config/with_config/b.ts b/tests/specs/lint/with_config/with_config/b.ts new file mode 100644 index 0000000000..d5647067ea --- /dev/null +++ b/tests/specs/lint/with_config/with_config/b.ts @@ -0,0 +1,4 @@ +// TODO: this file should be ignored +function subtract(a: number, b: number): number { + return a - b; +} diff --git a/tests/specs/lint/with_config_and_flags/Deno.jsonc b/tests/specs/lint/with_config_and_flags/Deno.jsonc new file mode 100644 index 0000000000..e9c03cca4e --- /dev/null +++ b/tests/specs/lint/with_config_and_flags/Deno.jsonc @@ -0,0 +1,10 @@ +{ + "lint": { + "include": ["with_config/"], + "exclude": ["with_config/b.ts"], + "rules": { + "tags": ["recommended"], + "include": ["ban-untagged-todo"] + } + } +} diff --git a/tests/specs/lint/with_config_and_flags/__test__.jsonc b/tests/specs/lint/with_config_and_flags/__test__.jsonc new file mode 100644 index 0000000000..926d1983b2 --- /dev/null +++ b/tests/specs/lint/with_config_and_flags/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.jsonc --ignore=with_config/a.ts", + "output": "with_config_and_flags.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/with_config_and_flags/with_config/a.ts b/tests/specs/lint/with_config_and_flags/with_config/a.ts new file mode 100644 index 0000000000..c378218a32 --- /dev/null +++ b/tests/specs/lint/with_config_and_flags/with_config/a.ts @@ -0,0 +1,4 @@ +// TODO: foo +function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/lint/with_config_and_flags/with_config/b.ts b/tests/specs/lint/with_config_and_flags/with_config/b.ts new file mode 100644 index 0000000000..d5647067ea --- /dev/null +++ b/tests/specs/lint/with_config_and_flags/with_config/b.ts @@ -0,0 +1,4 @@ +// TODO: this file should be ignored +function subtract(a: number, b: number): number { + return a - b; +} diff --git a/tests/testdata/lint/with_config_and_flags.out b/tests/specs/lint/with_config_and_flags/with_config_and_flags.out similarity index 100% rename from tests/testdata/lint/with_config_and_flags.out rename to tests/specs/lint/with_config_and_flags/with_config_and_flags.out diff --git a/tests/testdata/lint/Deno.no_tags.jsonc b/tests/specs/lint/with_config_without_args/Deno.no_tags.jsonc similarity index 100% rename from tests/testdata/lint/Deno.no_tags.jsonc rename to tests/specs/lint/with_config_without_args/Deno.no_tags.jsonc diff --git a/tests/specs/lint/with_config_without_args/__test__.jsonc b/tests/specs/lint/with_config_without_args/__test__.jsonc new file mode 100644 index 0000000000..9a1ae7cb4d --- /dev/null +++ b/tests/specs/lint/with_config_without_args/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.no_tags.jsonc with_config/", + "output": "with_config_without_tags.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/with_config_without_args/with_config/a.ts b/tests/specs/lint/with_config_without_args/with_config/a.ts new file mode 100644 index 0000000000..c378218a32 --- /dev/null +++ b/tests/specs/lint/with_config_without_args/with_config/a.ts @@ -0,0 +1,4 @@ +// TODO: foo +function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/lint/with_config_without_args/with_config/b.ts b/tests/specs/lint/with_config_without_args/with_config/b.ts new file mode 100644 index 0000000000..d5647067ea --- /dev/null +++ b/tests/specs/lint/with_config_without_args/with_config/b.ts @@ -0,0 +1,4 @@ +// TODO: this file should be ignored +function subtract(a: number, b: number): number { + return a - b; +} diff --git a/tests/testdata/lint/with_config_without_tags.out b/tests/specs/lint/with_config_without_args/with_config_without_tags.out similarity index 100% rename from tests/testdata/lint/with_config_without_tags.out rename to tests/specs/lint/with_config_without_args/with_config_without_tags.out diff --git a/tests/specs/lint/with_glob_config/__test__.jsonc b/tests/specs/lint/with_glob_config/__test__.jsonc new file mode 100644 index 0000000000..578ed2f852 --- /dev/null +++ b/tests/specs/lint/with_glob_config/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "steps": [ + { + "if": "windows", + "args": "lint --config deno.glob.json", + "output": "with_glob_config_windows.out", + "exitCode": 1 + }, + { + "if": "unix", + "args": "lint --config deno.glob.json", + "output": "with_glob_config_unix.out", + "exitCode": 1 + } + ] +} diff --git a/tests/testdata/lint/deno.glob.json b/tests/specs/lint/with_glob_config/deno.glob.json similarity index 100% rename from tests/testdata/lint/deno.glob.json rename to tests/specs/lint/with_glob_config/deno.glob.json diff --git a/tests/testdata/lint/glob/nested/fizz/fizz.ts b/tests/specs/lint/with_glob_config/glob/data/tes.ts similarity index 100% rename from tests/testdata/lint/glob/nested/fizz/fizz.ts rename to tests/specs/lint/with_glob_config/glob/data/tes.ts diff --git a/tests/testdata/lint/glob/data/test1.js b/tests/specs/lint/with_glob_config/glob/data/test1.js similarity index 73% rename from tests/testdata/lint/glob/data/test1.js rename to tests/specs/lint/with_glob_config/glob/data/test1.js index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/data/test1.js +++ b/tests/specs/lint/with_glob_config/glob/data/test1.js @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/data/test1.ts b/tests/specs/lint/with_glob_config/glob/data/test1.ts similarity index 73% rename from tests/testdata/lint/glob/data/test1.ts rename to tests/specs/lint/with_glob_config/glob/data/test1.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/data/test1.ts +++ b/tests/specs/lint/with_glob_config/glob/data/test1.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/data/test12.ts b/tests/specs/lint/with_glob_config/glob/data/test12.ts similarity index 73% rename from tests/testdata/lint/glob/data/test12.ts rename to tests/specs/lint/with_glob_config/glob/data/test12.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/data/test12.ts +++ b/tests/specs/lint/with_glob_config/glob/data/test12.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/fizz/bar.ts b/tests/specs/lint/with_glob_config/glob/nested/fizz/bar.ts similarity index 73% rename from tests/testdata/lint/glob/nested/fizz/bar.ts rename to tests/specs/lint/with_glob_config/glob/nested/fizz/bar.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/fizz/bar.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/fizz/bar.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/fizz/bazz.ts b/tests/specs/lint/with_glob_config/glob/nested/fizz/bazz.ts similarity index 73% rename from tests/testdata/lint/glob/nested/fizz/bazz.ts rename to tests/specs/lint/with_glob_config/glob/nested/fizz/bazz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/fizz/bazz.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/fizz/bazz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/foo/fizz.ts b/tests/specs/lint/with_glob_config/glob/nested/fizz/fizz.ts similarity index 73% rename from tests/testdata/lint/glob/nested/foo/fizz.ts rename to tests/specs/lint/with_glob_config/glob/nested/fizz/fizz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/foo/fizz.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/fizz/fizz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/fizz/foo.ts b/tests/specs/lint/with_glob_config/glob/nested/fizz/foo.ts similarity index 73% rename from tests/testdata/lint/glob/nested/fizz/foo.ts rename to tests/specs/lint/with_glob_config/glob/nested/fizz/foo.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/fizz/foo.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/fizz/foo.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/foo/bar.ts b/tests/specs/lint/with_glob_config/glob/nested/foo/bar.ts similarity index 73% rename from tests/testdata/lint/glob/nested/foo/bar.ts rename to tests/specs/lint/with_glob_config/glob/nested/foo/bar.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/foo/bar.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/foo/bar.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/nested/foo/bazz.ts b/tests/specs/lint/with_glob_config/glob/nested/foo/bazz.ts similarity index 73% rename from tests/testdata/lint/glob/nested/foo/bazz.ts rename to tests/specs/lint/with_glob_config/glob/nested/foo/bazz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/foo/bazz.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/foo/bazz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/specs/lint/with_glob_config/glob/nested/foo/fizz.ts b/tests/specs/lint/with_glob_config/glob/nested/foo/fizz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config/glob/nested/foo/fizz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/testdata/lint/glob/nested/foo/foo.ts b/tests/specs/lint/with_glob_config/glob/nested/foo/foo.ts similarity index 73% rename from tests/testdata/lint/glob/nested/foo/foo.ts rename to tests/specs/lint/with_glob_config/glob/nested/foo/foo.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/nested/foo/foo.ts +++ b/tests/specs/lint/with_glob_config/glob/nested/foo/foo.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/lint/glob/pages/[id].ts b/tests/specs/lint/with_glob_config/glob/pages/[id].ts similarity index 73% rename from tests/testdata/lint/glob/pages/[id].ts rename to tests/specs/lint/with_glob_config/glob/pages/[id].ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/pages/[id].ts +++ b/tests/specs/lint/with_glob_config/glob/pages/[id].ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/specs/lint/with_glob_config/with_glob_config_unix.out b/tests/specs/lint/with_glob_config/with_glob_config_unix.out new file mode 100644 index 0000000000..fad285cbe7 --- /dev/null +++ b/tests/specs/lint/with_glob_config/with_glob_config_unix.out @@ -0,0 +1,94 @@ +[UNORDERED_START] +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/fizz/bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/foo/foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/fizz/foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/foo/bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/data/test1.js:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/foo/fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/nested/fizz/fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/pages/[id].ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config/glob/data/test1.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 9 problems +Checked 9 files diff --git a/tests/specs/lint/with_glob_config/with_glob_config_windows.out b/tests/specs/lint/with_glob_config/with_glob_config_windows.out new file mode 100644 index 0000000000..2ba0787912 --- /dev/null +++ b/tests/specs/lint/with_glob_config/with_glob_config_windows.out @@ -0,0 +1,94 @@ +[UNORDERED_START] +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\fizz\bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\foo\foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\fizz\foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\foo\bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\data\test1.js:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\foo\fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\nested\fizz\fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\pages\[id].ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config\glob\data\test1.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 9 problems +Checked 9 files diff --git a/tests/specs/lint/with_glob_config_and_flags/__test__.jsonc b/tests/specs/lint/with_glob_config_and_flags/__test__.jsonc new file mode 100644 index 0000000000..3aed48ee87 --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "steps": [ + { + "if": "windows", + "args": "lint --config deno.glob.json --ignore=gleb/nested/**/bar.ts", + "output": "with_glob_config_and_flags_windows.out", + "exitCode": 1 + }, + { + "if": "unix", + "args": "lint --config deno.glob.json --ignore=gleb/nested/**/bar.ts", + "output": "with_glob_config_and_flags_unix.out", + "exitCode": 1 + } + ] +} diff --git a/tests/specs/lint/with_glob_config_and_flags/deno.glob.json b/tests/specs/lint/with_glob_config_and_flags/deno.glob.json new file mode 100644 index 0000000000..f6781b0d8a --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/deno.glob.json @@ -0,0 +1,11 @@ +{ + "lint": { + "include": [ + "glob/data/test1.?s", + "glob/nested/foo/*.ts", + "glob/nested/fizz/*.ts", + "glob/pages/[id].ts" + ], + "exclude": ["glob/nested/**/*bazz.ts"] + } +} diff --git a/tests/testdata/lint/glob/data/tes.ts b/tests/specs/lint/with_glob_config_and_flags/glob/data/tes.ts similarity index 73% rename from tests/testdata/lint/glob/data/tes.ts rename to tests/specs/lint/with_glob_config_and_flags/glob/data/tes.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/lint/glob/data/tes.ts +++ b/tests/specs/lint/with_glob_config_and_flags/glob/data/tes.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.js b/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.js new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.js @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.ts b/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/data/test1.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/data/test12.ts b/tests/specs/lint/with_glob_config_and_flags/glob/data/test12.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/data/test12.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bar.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bar.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bar.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bazz.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bazz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/bazz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/fizz.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/fizz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/fizz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/foo.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/foo.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/fizz/foo.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bar.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bar.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bar.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bazz.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bazz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/bazz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/fizz.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/fizz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/fizz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/foo.ts b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/foo.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/nested/foo/foo.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/glob/pages/[id].ts b/tests/specs/lint/with_glob_config_and_flags/glob/pages/[id].ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/glob/pages/[id].ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_unix.out b/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_unix.out new file mode 100644 index 0000000000..9afca955ba --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_unix.out @@ -0,0 +1,114 @@ +[UNORDERED_START] +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/fizz/bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/foo/bazz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/foo/foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/data/test1.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/foo/bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/fizz/bazz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/fizz/fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/fizz/foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/data/test1.js:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/nested/foo/fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint/with_glob_config_and_flags/glob/pages/[id].ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 11 problems +Checked 11 files diff --git a/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_windows.out b/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_windows.out new file mode 100644 index 0000000000..9446796ab9 --- /dev/null +++ b/tests/specs/lint/with_glob_config_and_flags/with_glob_config_and_flags_windows.out @@ -0,0 +1,114 @@ +[UNORDERED_START] +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\fizz\bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\foo\bazz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\foo\foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\data\test1.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\foo\bar.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\fizz\bazz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\fizz\fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\fizz\foo.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\data\test1.js:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\nested\foo\fizz.ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars + + +error[no-unused-vars]: `foo` is never used + --> [WILDLINE]lint\with_glob_config_and_flags\glob\pages\[id].ts:1:10 + | +1 | function foo() { + | ^^^ + = hint: If this is intentional, prefix it with an underscore like `_foo` + + docs: https://lint.deno.land/rules/no-unused-vars +[UNORDERED_END] + + +Found 11 problems +Checked 11 files diff --git a/tests/testdata/lint/Deno.malformed.jsonc b/tests/specs/lint/with_malformed_config/Deno.malformed.jsonc similarity index 100% rename from tests/testdata/lint/Deno.malformed.jsonc rename to tests/specs/lint/with_malformed_config/Deno.malformed.jsonc diff --git a/tests/specs/lint/with_malformed_config/__test__.jsonc b/tests/specs/lint/with_malformed_config/__test__.jsonc new file mode 100644 index 0000000000..86a47eda41 --- /dev/null +++ b/tests/specs/lint/with_malformed_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.malformed.jsonc", + "output": "with_malformed_config.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/with_malformed_config.out b/tests/specs/lint/with_malformed_config/with_malformed_config.out similarity index 100% rename from tests/testdata/lint/with_malformed_config.out rename to tests/specs/lint/with_malformed_config/with_malformed_config.out diff --git a/tests/testdata/lint/Deno.malformed2.jsonc b/tests/specs/lint/with_malformed_config2/Deno.malformed2.jsonc similarity index 100% rename from tests/testdata/lint/Deno.malformed2.jsonc rename to tests/specs/lint/with_malformed_config2/Deno.malformed2.jsonc diff --git a/tests/specs/lint/with_malformed_config2/__test__.jsonc b/tests/specs/lint/with_malformed_config2/__test__.jsonc new file mode 100644 index 0000000000..3210f5a595 --- /dev/null +++ b/tests/specs/lint/with_malformed_config2/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.malformed2.jsonc", + "output": "with_malformed_config2.out", + "exitCode": 1 +} diff --git a/tests/testdata/lint/with_malformed_config2.out b/tests/specs/lint/with_malformed_config2/with_malformed_config2.out similarity index 100% rename from tests/testdata/lint/with_malformed_config2.out rename to tests/specs/lint/with_malformed_config2/with_malformed_config2.out diff --git a/tests/testdata/lint/Deno.compact.format.jsonc b/tests/specs/lint/with_report_config/Deno.compact.format.jsonc similarity index 100% rename from tests/testdata/lint/Deno.compact.format.jsonc rename to tests/specs/lint/with_report_config/Deno.compact.format.jsonc diff --git a/tests/specs/lint/with_report_config/__test__.jsonc b/tests/specs/lint/with_report_config/__test__.jsonc new file mode 100644 index 0000000000..2b5c21ccec --- /dev/null +++ b/tests/specs/lint/with_report_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.compact.format.jsonc with_config/", + "output": "with_report_config_compact.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/with_report_config/with_config/a.ts b/tests/specs/lint/with_report_config/with_config/a.ts new file mode 100644 index 0000000000..c378218a32 --- /dev/null +++ b/tests/specs/lint/with_report_config/with_config/a.ts @@ -0,0 +1,4 @@ +// TODO: foo +function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/lint/with_report_config/with_config/b.ts b/tests/specs/lint/with_report_config/with_config/b.ts new file mode 100644 index 0000000000..d5647067ea --- /dev/null +++ b/tests/specs/lint/with_report_config/with_config/b.ts @@ -0,0 +1,4 @@ +// TODO: this file should be ignored +function subtract(a: number, b: number): number { + return a - b; +} diff --git a/tests/testdata/lint/with_report_config_compact.out b/tests/specs/lint/with_report_config/with_report_config_compact.out similarity index 100% rename from tests/testdata/lint/with_report_config_compact.out rename to tests/specs/lint/with_report_config/with_report_config_compact.out diff --git a/tests/specs/lint/with_report_config_override/Deno.compact.format.jsonc b/tests/specs/lint/with_report_config_override/Deno.compact.format.jsonc new file mode 100644 index 0000000000..f3487501a8 --- /dev/null +++ b/tests/specs/lint/with_report_config_override/Deno.compact.format.jsonc @@ -0,0 +1,11 @@ +{ + "lint": { + "include": ["with_config/"], + "exclude": ["with_config/b.ts"], + "rules": { + "tags": ["recommended"], + "include": ["ban-untagged-todo"] + }, + "report": "compact" + } +} diff --git a/tests/specs/lint/with_report_config_override/__test__.jsonc b/tests/specs/lint/with_report_config_override/__test__.jsonc new file mode 100644 index 0000000000..5b1739af3b --- /dev/null +++ b/tests/specs/lint/with_report_config_override/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "lint --config Deno.compact.format.jsonc with_config/ --json", + "output": "with_report_config_override.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/with_report_config_override/with_config/a.ts b/tests/specs/lint/with_report_config_override/with_config/a.ts new file mode 100644 index 0000000000..c378218a32 --- /dev/null +++ b/tests/specs/lint/with_report_config_override/with_config/a.ts @@ -0,0 +1,4 @@ +// TODO: foo +function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/lint/with_report_config_override/with_config/b.ts b/tests/specs/lint/with_report_config_override/with_config/b.ts new file mode 100644 index 0000000000..d5647067ea --- /dev/null +++ b/tests/specs/lint/with_report_config_override/with_config/b.ts @@ -0,0 +1,4 @@ +// TODO: this file should be ignored +function subtract(a: number, b: number): number { + return a - b; +} diff --git a/tests/testdata/lint/with_report_config_override.out b/tests/specs/lint/with_report_config_override/with_report_config_override.out similarity index 98% rename from tests/testdata/lint/with_report_config_override.out rename to tests/specs/lint/with_report_config_override/with_report_config_override.out index 7ca7481583..ad32e31236 100644 --- a/tests/testdata/lint/with_report_config_override.out +++ b/tests/specs/lint/with_report_config_override/with_report_config_override.out @@ -1,4 +1,5 @@ { + "version": 1, "diagnostics": [ { "filename": "[WILDCARD]a.ts", diff --git a/tests/specs/lockfile/adding_jsr_dep/lock01.out b/tests/specs/lockfile/adding_jsr_dep/lock01.out index 0ac0075265..7f5c754073 100644 --- a/tests/specs/lockfile/adding_jsr_dep/lock01.out +++ b/tests/specs/lockfile/adding_jsr_dep/lock01.out @@ -1,16 +1,13 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - }, - "jsr": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]" - } + "version": "4", + "specifiers": { + "jsr:@denotest/add@1": "1.0.0" + }, + "jsr": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ "jsr:@denotest/add@1", diff --git a/tests/specs/lockfile/adding_jsr_dep/lock02.out b/tests/specs/lockfile/adding_jsr_dep/lock02.out index 4293c7dfed..6519df0b35 100644 --- a/tests/specs/lockfile/adding_jsr_dep/lock02.out +++ b/tests/specs/lockfile/adding_jsr_dep/lock02.out @@ -1,20 +1,17 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0", - "jsr:@denotest/subtract@1": "jsr:@denotest/subtract@1.0.0" + "version": "4", + "specifiers": { + "jsr:@denotest/add@1": "1.0.0", + "jsr:@denotest/subtract@1": "1.0.0" + }, + "jsr": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" }, - "jsr": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]" - }, - "@denotest/subtract@1.0.0": { - "integrity": "[WILDLINE]" - } + "@denotest/subtract@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ "jsr:@denotest/add@1", diff --git a/tests/specs/lockfile/adding_jsr_export_new_dep/lock01.out b/tests/specs/lockfile/adding_jsr_export_new_dep/lock01.out index e78ea355a5..d3b8f82e7b 100644 --- a/tests/specs/lockfile/adding_jsr_export_new_dep/lock01.out +++ b/tests/specs/lockfile/adding_jsr_export_new_dep/lock01.out @@ -1,23 +1,20 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0", - "jsr:@denotest/different-deps-per-export@1": "jsr:@denotest/different-deps-per-export@1.0.0" + "version": "4", + "specifiers": { + "jsr:@denotest/add@1": "1.0.0", + "jsr:@denotest/different-deps-per-export@1": "1.0.0" + }, + "jsr": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" }, - "jsr": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]" - }, - "@denotest/different-deps-per-export@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": [ - "jsr:@denotest/add@1" - ] - } + "@denotest/different-deps-per-export@1.0.0": { + "integrity": "[WILDLINE]", + "dependencies": [ + "jsr:@denotest/add" + ] } }, - "remote": {}, "workspace": { "dependencies": [ "jsr:@denotest/different-deps-per-export@1" diff --git a/tests/specs/lockfile/adding_jsr_export_new_dep/lock02.out b/tests/specs/lockfile/adding_jsr_export_new_dep/lock02.out index 0f4a388c60..ddb1dfca01 100644 --- a/tests/specs/lockfile/adding_jsr_export_new_dep/lock02.out +++ b/tests/specs/lockfile/adding_jsr_export_new_dep/lock02.out @@ -1,28 +1,25 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0", - "jsr:@denotest/different-deps-per-export@1": "jsr:@denotest/different-deps-per-export@1.0.0", - "jsr:@denotest/subtract@1": "jsr:@denotest/subtract@1.0.0" + "version": "4", + "specifiers": { + "jsr:@denotest/add@1": "1.0.0", + "jsr:@denotest/different-deps-per-export@1": "1.0.0", + "jsr:@denotest/subtract@1": "1.0.0" + }, + "jsr": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" }, - "jsr": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]" - }, - "@denotest/different-deps-per-export@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": [ - "jsr:@denotest/add@1", - "jsr:@denotest/subtract@1" - ] - }, - "@denotest/subtract@1.0.0": { - "integrity": "[WILDLINE]" - } + "@denotest/different-deps-per-export@1.0.0": { + "integrity": "[WILDLINE]", + "dependencies": [ + "jsr:@denotest/add", + "jsr:@denotest/subtract" + ] + }, + "@denotest/subtract@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ "jsr:@denotest/different-deps-per-export@1" diff --git a/tests/specs/lockfile/adding_npm_dep/lock01.out b/tests/specs/lockfile/adding_npm_dep/lock01.out index 5d5567dc06..82b6a5b3db 100644 --- a/tests/specs/lockfile/adding_npm_dep/lock01.out +++ b/tests/specs/lockfile/adding_npm_dep/lock01.out @@ -1,17 +1,13 @@ { - "version": "3", - "packages": { - "specifiers": { - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - }, - "npm": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": {} - } + "version": "4", + "specifiers": { + "npm:@denotest/add@1": "1.0.0" + }, + "npm": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ "npm:@denotest/add@1", diff --git a/tests/specs/lockfile/adding_npm_dep/lock02.out b/tests/specs/lockfile/adding_npm_dep/lock02.out index 6042b1cb9a..f22cbc4280 100644 --- a/tests/specs/lockfile/adding_npm_dep/lock02.out +++ b/tests/specs/lockfile/adding_npm_dep/lock02.out @@ -1,22 +1,17 @@ { - "version": "3", - "packages": { - "specifiers": { - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0" + "version": "4", + "specifiers": { + "npm:@denotest/add@1": "1.0.0", + "npm:@denotest/subtract@1": "1.0.0" + }, + "npm": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" }, - "npm": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": {} - }, - "@denotest/subtract@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": {} - } + "@denotest/subtract@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ "npm:@denotest/add@1", diff --git a/tests/specs/lockfile/adding_redirect/__test__.jsonc b/tests/specs/lockfile/adding_redirect/__test__.jsonc index d53beedbd4..75933a6b4e 100644 --- a/tests/specs/lockfile/adding_redirect/__test__.jsonc +++ b/tests/specs/lockfile/adding_redirect/__test__.jsonc @@ -1,13 +1,13 @@ { "tempDir": true, "steps": [{ - "args": "run 1.ts", + "args": "run --allow-import 1.ts", "output": "[WILDCARD]" }, { "args": "task --quiet cat deno.lock", "output": "lock01.out" }, { - "args": "run 2.ts", + "args": "run --allow-import 2.ts", "output": "[WILDCARD]" }, { "args": "task --quiet cat deno.lock", diff --git a/tests/specs/lockfile/adding_redirect/lock01.out b/tests/specs/lockfile/adding_redirect/lock01.out index f00cefa6a8..b7b217cd6a 100644 --- a/tests/specs/lockfile/adding_redirect/lock01.out +++ b/tests/specs/lockfile/adding_redirect/lock01.out @@ -1,5 +1,5 @@ { - "version": "3", + "version": "4", "remote": { "http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31" } diff --git a/tests/specs/lockfile/adding_redirect/lock02.out b/tests/specs/lockfile/adding_redirect/lock02.out index 70c38c9661..1c0227cb98 100644 --- a/tests/specs/lockfile/adding_redirect/lock02.out +++ b/tests/specs/lockfile/adding_redirect/lock02.out @@ -1,5 +1,5 @@ { - "version": "3", + "version": "4", "redirects": { "http://localhost:4546/welcome.ts": "http://localhost:4545/welcome.ts" }, diff --git a/tests/specs/lockfile/auto_discover_lockfile/__test__.jsonc b/tests/specs/lockfile/auto_discover_lockfile/__test__.jsonc index 50213381ad..27f6d97871 100644 --- a/tests/specs/lockfile/auto_discover_lockfile/__test__.jsonc +++ b/tests/specs/lockfile/auto_discover_lockfile/__test__.jsonc @@ -1,5 +1,5 @@ { - "args": "run main.ts", + "args": "run --allow-import main.ts", "output": "main.out", "exitCode": 10 } diff --git a/tests/specs/lockfile/auto_discover_lockfile/main.out b/tests/specs/lockfile/auto_discover_lockfile/main.out index aa24320d14..110f7e85ba 100644 --- a/tests/specs/lockfile/auto_discover_lockfile/main.out +++ b/tests/specs/lockfile/auto_discover_lockfile/main.out @@ -10,4 +10,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/checksum_at_redirect/run.out b/tests/specs/lockfile/checksum_at_redirect/run.out index 75a34777f5..6180bf55d2 100644 --- a/tests/specs/lockfile/checksum_at_redirect/run.out +++ b/tests/specs/lockfile/checksum_at_redirect/run.out @@ -9,4 +9,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/config_file_lock_boolean/__test__.jsonc b/tests/specs/lockfile/config_file_lock_boolean/__test__.jsonc index 65679a1c81..651ed113dc 100644 --- a/tests/specs/lockfile/config_file_lock_boolean/__test__.jsonc +++ b/tests/specs/lockfile/config_file_lock_boolean/__test__.jsonc @@ -1,12 +1,12 @@ { "tests": { "true": { - "args": "run --config=true.json main.ts", + "args": "run --allow-import --config=true.json main.ts", "output": "true.main.out", "exitCode": 10 }, "false": { - "args": "run --config=false.json main.ts", + "args": "run --allow-import --config=false.json main.ts", "output": "false.main.out" } } diff --git a/tests/specs/lockfile/config_file_lock_boolean/true.main.out b/tests/specs/lockfile/config_file_lock_boolean/true.main.out index 11dfc07408..69b467ef0c 100644 --- a/tests/specs/lockfile/config_file_lock_boolean/true.main.out +++ b/tests/specs/lockfile/config_file_lock_boolean/true.main.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/config_file_lock_path/__test__.jsonc b/tests/specs/lockfile/config_file_lock_path/__test__.jsonc index defb113b38..5c901e709e 100644 --- a/tests/specs/lockfile/config_file_lock_path/__test__.jsonc +++ b/tests/specs/lockfile/config_file_lock_path/__test__.jsonc @@ -1,12 +1,12 @@ { "tests": { "error_bad_checksum": { - "args": "run --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts", + "args": "run --allow-import --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts", "output": "config_file_lock_path.out", "exitCode": 10 }, "lock_flag_override": { - "args": "run --lock=run/lock_check_ok2.json --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts", + "args": "run --allow-import --lock=run/lock_check_ok2.json --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts", "output": "019_media_types.ts.out" } } diff --git a/tests/specs/lockfile/config_file_lock_path/config_file_lock_path.out b/tests/specs/lockfile/config_file_lock_path/config_file_lock_path.out index 1383d945d0..3043b102a5 100644 --- a/tests/specs/lockfile/config_file_lock_path/config_file_lock_path.out +++ b/tests/specs/lockfile/config_file_lock_path/config_file_lock_path.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/config_file_lock_path/lock_check_err2.out b/tests/specs/lockfile/config_file_lock_path/lock_check_err2.out index 1383d945d0..3043b102a5 100644 --- a/tests/specs/lockfile/config_file_lock_path/lock_check_err2.out +++ b/tests/specs/lockfile/config_file_lock_path/lock_check_err2.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/frozen_lockfile/__test__.jsonc b/tests/specs/lockfile/frozen_lockfile/__test__.jsonc index 3036c8db52..07ec2c4c14 100644 --- a/tests/specs/lockfile/frozen_lockfile/__test__.jsonc +++ b/tests/specs/lockfile/frozen_lockfile/__test__.jsonc @@ -60,16 +60,17 @@ "error_when_package_json_changed": { "steps": [ { - "envs": { - "DENO_FUTURE": "1" - }, + "args": [ + "eval", + "Deno.writeTextFileSync('deno.json', `{ \"nodeModulesDir\": \"auto\" }`)" + ], + "output": "[WILDCARD]" + }, + { "args": "cache add.ts", "output": "[WILDCARD]" }, { - "envs": { - "DENO_FUTURE": "1" - }, "args": [ "eval", "Deno.writeTextFileSync(\"package.json\", JSON.stringify({ dependencies: { \"@denotest/bin\": \"0.7.0\" } }))" @@ -77,17 +78,11 @@ "output": "" }, { - "envs": { - "DENO_FUTURE": "1" - }, "args": "cache --frozen add.ts", "output": "frozen_package_json_changed.out", "exitCode": 1 }, { - "envs": { - "DENO_FUTURE": "1" - }, "args": "install --frozen", "output": "frozen_package_json_changed_install.out", "exitCode": 1 @@ -123,7 +118,6 @@ } ] }, - "lockfile_config": { "steps": [ { @@ -151,7 +145,6 @@ } ] }, - "non_analyzable_dynamic_npm": { "steps": [ { @@ -185,11 +178,24 @@ "output": "[WILDCARD]" }, { - "args": "run --frozen --allow-net http-dynamic.ts", + "args": "run --frozen --allow-import http-dynamic.ts", "output": "frozen_new_dep_dynamic_http.out", "exitCode": 1 } ] + }, + "check_subcommand": { + "steps": [ + { + "args": "check --frozen=true add.ts", + "output": "[WILDCARD]The lockfile is out of date[WILDCARD]", + "exitCode": 1 + }, + { + "args": "check --frozen=false add.ts", + "output": "[WILDCARD]Check [WILDCARD]add.ts\n" + } + ] } } } diff --git a/tests/specs/lockfile/frozen_lockfile/deno.json b/tests/specs/lockfile/frozen_lockfile/deno.json index 176354f98f..fbd70ec480 100644 --- a/tests/specs/lockfile/frozen_lockfile/deno.json +++ b/tests/specs/lockfile/frozen_lockfile/deno.json @@ -1,3 +1,3 @@ { - "nodeModulesDir": true + "nodeModulesDir": "auto" } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out index bf6c033670..3998a04593 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out @@ -1,11 +1,10 @@ -error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - 6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0" -11 | - } -12 | + }, -13 | + "@denotest/subtract@1.0.0": { -14 | + "integrity": "[WILDCARD]", -15 | + "dependencies": {} -16 | + } + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "npm:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/subtract@1": "1.0.0" + 9 | - } +10 | + }, +11 | + "@denotest/subtract@1.0.0": { +12 | + "integrity": "[WILDCARD]" +13 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out index 99c884e9c8..7c86a23cf3 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out @@ -1,10 +1,11 @@ Download http://localhost:4545/welcome.ts -error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: -14 | - "remote": {} -14 | + "remote": { -15 | + "http://localhost:4545/welcome.ts": "[WILDCARD]" -16 | + } +10 | - } +10 | + }, +11 | + "remote": { +12 | + "http://localhost:4545/welcome.ts": "[WILDCARD]" +13 | + } const _ = await import(scheme + "localhost:4545/welcome.ts"); ^ at [WILDCARD] \ No newline at end of file diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out index e77853ab23..c22b529edb 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out @@ -1,16 +1,16 @@ Download http://127.0.0.1:4250/@denotest/add/meta.json Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts -error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 5 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0", - 6 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 7 | + }, - 8 | + "jsr": { - 9 | + "@denotest/add@1.0.0": { -10 | + "integrity": "[WILDCARD]" -11 | + } + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "jsr:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/add@1": "1.0.0" + 6 | + }, + 7 | + "jsr": { + 8 | + "@denotest/add@1.0.0": { + 9 | + "integrity": "[WILDCARD]" +10 | + } const { add } = await import(scheme + "@denotest/add@1"); ^ at [WILDCARD] \ No newline at end of file diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out index 9b2efa462f..4fc016c57c 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out @@ -1,15 +1,14 @@ -Download http://localhost:4260/@denotest/subtract -error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +Download http://localhost:4260/@denotest%2fsubtract +error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - 6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0" -11 | - } -12 | + }, -13 | + "@denotest/subtract@1.0.0": { -14 | + "integrity": "[WILDCARD]", -15 | + "dependencies": {} -16 | + } + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "npm:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/subtract@1": "1.0.0" + 9 | - } +10 | + }, +11 | + "@denotest/subtract@1.0.0": { +12 | + "integrity": "[WILDCARD]" +13 | + } const { subtract } = await import(scheme + "@denotest/subtract@1"); ^ at [WILDCARD] diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out index bb523deff4..9c0fa7edcc 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out @@ -1,12 +1,12 @@ -error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - 6 | - }, - 7 | - "jsr": { - 5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0", - 6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - 7 | + }, - 8 | + "jsr": { - 9 | + "@denotest/add@0.2.0": { -10 | + "integrity": "[WILDCARD]" -11 | + }, + 4 | - "jsr:@denotest/add@1": "1.0.0" + 5 | - }, + 6 | - "jsr": { + 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", + 5 | + "jsr:@denotest/add@1": "1.0.0" + 6 | + }, + 7 | + "jsr": { + 8 | + "@denotest/add@0.2.0": { + 9 | + "integrity": "[WILDCARD]" +10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out index 3a0d51678c..fe628a454a 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out @@ -1,14 +1,14 @@ Download http://127.0.0.1:4250/@denotest/add/0.2.0_meta.json Download http://127.0.0.1:4250/@denotest/add/0.2.0/mod.ts -error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - 6 | - }, - 7 | - "jsr": { - 5 | + "jsr:@denotest/add@0.2.0": "jsr:@denotest/add@0.2.0", - 6 | + "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - 7 | + }, - 8 | + "jsr": { - 9 | + "@denotest/add@0.2.0": { -10 | + "integrity": "[WILDCARD]" -11 | + }, + 4 | - "jsr:@denotest/add@1": "1.0.0" + 5 | - }, + 6 | - "jsr": { + 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", + 5 | + "jsr:@denotest/add@1": "1.0.0" + 6 | + }, + 7 | + "jsr": { + 8 | + "@denotest/add@0.2.0": { + 9 | + "integrity": "[WILDCARD]" +10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out index 6dad6f6f42..07b37b925a 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out @@ -1,12 +1,11 @@ -Download http://localhost:4260/@denotest/subtract -error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +Download http://localhost:4260/@denotest%2fsubtract +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 5 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - 6 | + "npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0" -11 | - } -12 | + }, -13 | + "@denotest/subtract@1.0.0": { -14 | + "integrity": "[WILDCARD]", -15 | + "dependencies": {} -16 | + } + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "npm:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/subtract@1": "1.0.0" + 9 | - } +10 | + }, +11 | + "@denotest/subtract@1.0.0": { +12 | + "integrity": "[WILDCARD]" +13 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out index 60a01158dd..626007478f 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out @@ -1,9 +1,9 @@ -Download http://localhost:4260/@denotest/bin -error: The lockfile is out of date. Run `deno cache --frozen=false`, `deno install --frozen=false`, or rerun with `--frozen=false` to update it. +Download http://localhost:4260/@denotest%2fbin +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 4 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 4 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - 5 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0" + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "npm:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" 9 | - } 10 | + }, 11 | + "@denotest/bin@0.7.0": { diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out index 3971795966..8690396c0e 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out @@ -1,8 +1,8 @@ -error: The lockfile is out of date. Run `deno cache --frozen=false`, `deno install --frozen=false`, or rerun with `--frozen=false` to update it. +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 4 | - "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 4 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0", - 5 | + "npm:@denotest/bin@0.7.0": "npm:@denotest/bin@0.7.0" + 4 | - "npm:@denotest/add@1": "1.0.0" + 4 | + "npm:@denotest/add@1": "1.0.0", + 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" 9 | - } 10 | + }, 11 | + "@denotest/bin@0.7.0": { diff --git a/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out b/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out index 2ae84b1106..047bfdb4ac 100644 --- a/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out +++ b/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out @@ -1,20 +1,16 @@ -Download http://localhost:4260/@denotest/add -error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it. +Download http://localhost:4260/@denotest%2fadd +error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: 1 | - 1 | +{ - 2 | + "version": "3", - 3 | + "packages": { - 4 | + "specifiers": { - 5 | + "npm:@denotest/add@1": "npm:@denotest/add@1.0.0" - 6 | + }, - 7 | + "npm": { - 8 | + "@denotest/add@1.0.0": { - 9 | + "integrity": "[WILDCARD]", -10 | + "dependencies": {} -11 | + } -12 | + } -13 | + }, -14 | + "remote": {} -15 | +} -16 | + + 2 | + "version": "4", + 3 | + "specifiers": { + 4 | + "npm:@denotest/add@1": "1.0.0" + 5 | + }, + 6 | + "npm": { + 7 | + "@denotest/add@1.0.0": { + 8 | + "integrity": "[WILDCARD]" + 9 | + } +10 | + } +11 | +} +12 | + diff --git a/tests/specs/lockfile/lock_check_err/lock_check_err.out b/tests/specs/lockfile/lock_check_err/lock_check_err.out index 25d22490da..031ae85e61 100644 --- a/tests/specs/lockfile/lock_check_err/lock_check_err.out +++ b/tests/specs/lockfile/lock_check_err/lock_check_err.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/lock_check_err2/lock_check_err2.out b/tests/specs/lockfile/lock_check_err2/lock_check_err2.out index 1383d945d0..3043b102a5 100644 --- a/tests/specs/lockfile/lock_check_err2/lock_check_err2.out +++ b/tests/specs/lockfile/lock_check_err2/lock_check_err2.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/lock_dynamic_imports/lock_dynamic_imports.out b/tests/specs/lockfile/lock_dynamic_imports/lock_dynamic_imports.out index 2b8bdfc96e..6a63a01b43 100644 --- a/tests/specs/lockfile/lock_dynamic_imports/lock_dynamic_imports.out +++ b/tests/specs/lockfile/lock_dynamic_imports/lock_dynamic_imports.out @@ -9,4 +9,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/lock_v2_check_err/lock_v2_check_err.out b/tests/specs/lockfile/lock_v2_check_err/lock_v2_check_err.out index 25d22490da..031ae85e61 100644 --- a/tests/specs/lockfile/lock_v2_check_err/lock_v2_check_err.out +++ b/tests/specs/lockfile/lock_v2_check_err/lock_v2_check_err.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/lock_v2_check_err2/lock_v2_check_err2.out b/tests/specs/lockfile/lock_v2_check_err2/lock_v2_check_err2.out index 1383d945d0..3043b102a5 100644 --- a/tests/specs/lockfile/lock_v2_check_err2/lock_v2_check_err2.out +++ b/tests/specs/lockfile/lock_v2_check_err2/lock_v2_check_err2.out @@ -8,4 +8,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/lock_v2_dynamic_imports/lock_v2_dynamic_imports.out b/tests/specs/lockfile/lock_v2_dynamic_imports/lock_v2_dynamic_imports.out index 2b8bdfc96e..6a63a01b43 100644 --- a/tests/specs/lockfile/lock_v2_dynamic_imports/lock_v2_dynamic_imports.out +++ b/tests/specs/lockfile/lock_v2_dynamic_imports/lock_v2_dynamic_imports.out @@ -9,4 +9,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/no_declaration_files/__test__.jsonc b/tests/specs/lockfile/no_declaration_files/__test__.jsonc new file mode 100644 index 0000000000..3c82828253 --- /dev/null +++ b/tests/specs/lockfile/no_declaration_files/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [{ + "args": "cache --allow-import --lock --frozen=false main.ts", + "output": "main.cache.out" + }, { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('deno.lock').trim())" + ], + "output": "deno.lock.out" + }] +} diff --git a/tests/testdata/lockfile/no_dts/deno.lock.out b/tests/specs/lockfile/no_declaration_files/deno.lock.out similarity index 88% rename from tests/testdata/lockfile/no_dts/deno.lock.out rename to tests/specs/lockfile/no_declaration_files/deno.lock.out index 6aa547e282..3066e9b159 100644 --- a/tests/testdata/lockfile/no_dts/deno.lock.out +++ b/tests/specs/lockfile/no_declaration_files/deno.lock.out @@ -1,5 +1,5 @@ { - "version": "3", + "version": "4", "remote": { "http://localhost:4545/lockfile/no_dts/mod.js": "3f576f37a301d298c3032eb1835240bd83f3762db26fc1d358c5d67088d6ffc8" } diff --git a/tests/testdata/lockfile/no_dts/main.cache.out b/tests/specs/lockfile/no_declaration_files/main.cache.out similarity index 60% rename from tests/testdata/lockfile/no_dts/main.cache.out rename to tests/specs/lockfile/no_declaration_files/main.cache.out index 84e728d662..ee8ad33ab7 100644 --- a/tests/testdata/lockfile/no_dts/main.cache.out +++ b/tests/specs/lockfile/no_declaration_files/main.cache.out @@ -1,3 +1,2 @@ -Warning "--lock-write" flag is deprecated and will be removed in Deno 2. Download http://localhost:4545/lockfile/no_dts/mod.js Download http://localhost:4545/lockfile/no_dts/mod.d.ts diff --git a/tests/testdata/lockfile/no_dts/main.ts b/tests/specs/lockfile/no_declaration_files/main.ts similarity index 100% rename from tests/testdata/lockfile/no_dts/main.ts rename to tests/specs/lockfile/no_declaration_files/main.ts diff --git a/tests/specs/lockfile/no_lock/__test__.jsonc b/tests/specs/lockfile/no_lock/__test__.jsonc index 75821ac64c..d8172a7ca7 100644 --- a/tests/specs/lockfile/no_lock/__test__.jsonc +++ b/tests/specs/lockfile/no_lock/__test__.jsonc @@ -1,39 +1,39 @@ { "tests": { "info": { - "args": "info main.ts", + "args": "info --allow-import main.ts", "output": "fail.out", "exitCode": 10 }, "info_no_lock": { - "args": "info --no-lock main.ts", + "args": "info --allow-import --no-lock main.ts", "output": "info.nolock.out" }, "bench": { - "args": "bench", + "args": "bench --allow-import", "output": "fail.out", "exitCode": 10 }, "bench_no_lock": { - "args": "bench --no-lock", + "args": "bench --allow-import --no-lock", "output": "bench.nolock.out" }, "doc": { - "args": "doc main.ts", + "args": "doc --allow-import main.ts", "exitCode": 10, "output": "fail.out" }, "doc_no_lock": { - "args": "doc --no-lock main.ts", + "args": "doc --allow-import --no-lock main.ts", "output": "doc.nolock.out" }, "test": { - "args": "test", + "args": "test --allow-import", "exitCode": 10, "output": "fail.out" }, "test_no_lock": { - "args": "test --no-lock", + "args": "test --allow-import --no-lock", "output": "test.nolock.out" } } diff --git a/tests/specs/lockfile/no_lock/bench.nolock.out b/tests/specs/lockfile/no_lock/bench.nolock.out index 83e4de242b..1aa6db378c 100644 --- a/tests/specs/lockfile/no_lock/bench.nolock.out +++ b/tests/specs/lockfile/no_lock/bench.nolock.out @@ -1,6 +1,6 @@ Download http://localhost:4545/lockfile/basic/mod.ts Check file:///[WILDCARD]/main.bench.ts -cpu: [WILDCARD] -runtime: [WILDCARD] + CPU | [WILDCARD] +Runtime | [WILDCARD] [WILDCARD] diff --git a/tests/specs/lockfile/no_lock/fail.out b/tests/specs/lockfile/no_lock/fail.out index 0d67cd4788..14a8d19cfe 100644 --- a/tests/specs/lockfile/no_lock/fail.out +++ b/tests/specs/lockfile/no_lock/fail.out @@ -9,4 +9,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server. +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/lockfile/only_package_json/__test__.jsonc b/tests/specs/lockfile/only_package_json/__test__.jsonc index 6b28a7a924..f53d68f7df 100644 --- a/tests/specs/lockfile/only_package_json/__test__.jsonc +++ b/tests/specs/lockfile/only_package_json/__test__.jsonc @@ -2,8 +2,8 @@ "tempDir": true, "steps": [ { - "args": "cache index.js", - "output": "cache.out" + "args": "install", + "output": "install.out" }, { "args": [ diff --git a/tests/specs/lockfile/only_package_json/deno.lock.out b/tests/specs/lockfile/only_package_json/deno.lock.out index b302329967..d390a59c13 100644 --- a/tests/specs/lockfile/only_package_json/deno.lock.out +++ b/tests/specs/lockfile/only_package_json/deno.lock.out @@ -1,18 +1,15 @@ { - "version": "3", - "packages": { - "specifiers": { - "npm:@denotest/esm-basic": "npm:@denotest/esm-basic@1.0.0" - }, - "npm": { - "@denotest/esm-basic@1.0.0": [WILDCARD] - } + "version": "4", + "specifiers": { + "npm:@denotest/esm-basic@*": "1.0.0" + }, + "npm": { + "@denotest/esm-basic@1.0.0": [WILDCARD] }, - "remote": {}, "workspace": { "packageJson": { "dependencies": [ - "npm:@denotest/esm-basic" + "npm:@denotest/esm-basic@*" ] } } diff --git a/tests/specs/lockfile/only_package_json/install.out b/tests/specs/lockfile/only_package_json/install.out new file mode 100644 index 0000000000..8f03ba6407 --- /dev/null +++ b/tests/specs/lockfile/only_package_json/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/mod.rs b/tests/specs/mod.rs index 7a3572a942..34221dd9da 100644 --- a/tests/specs/mod.rs +++ b/tests/specs/mod.rs @@ -56,6 +56,8 @@ struct MultiTestMetaData { pub cwd: Option, #[serde(default)] pub tests: BTreeMap, + #[serde(default)] + pub ignore: bool, } impl MultiTestMetaData { @@ -90,6 +92,9 @@ impl MultiTestMetaData { } } } + if multi_test_meta_data.ignore && !value.contains_key("ignore") { + value.insert("ignore".to_string(), true.into()); + } } let mut collected_tests = Vec::with_capacity(self.tests.len()); @@ -125,6 +130,8 @@ struct MultiStepMetaData { pub repeat: Option, #[serde(default)] pub steps: Vec, + #[serde(default)] + pub ignore: bool, } #[derive(Clone, Deserialize)] @@ -138,6 +145,8 @@ struct SingleTestMetaData { pub repeat: Option, #[serde(flatten)] pub step: StepMetaData, + #[serde(default)] + pub ignore: bool, } impl SingleTestMetaData { @@ -149,6 +158,7 @@ impl SingleTestMetaData { repeat: self.repeat, envs: Default::default(), steps: vec![self.step], + ignore: self.ignore, } } } @@ -166,6 +176,7 @@ struct StepMetaData { pub command_name: Option, #[serde(default)] pub envs: HashMap, + pub input: Option, pub output: String, #[serde(default)] pub exit_code: i32, @@ -236,7 +247,9 @@ fn run_test(test: &CollectedTest) -> TestResult { let diagnostic_logger = Rc::new(RefCell::new(Vec::::new())); let result = TestResult::from_maybe_panic_or_result(AssertUnwindSafe(|| { let metadata = deserialize_value(metadata_value); - if let Some(repeat) = metadata.repeat { + if metadata.ignore { + TestResult::Ignored + } else if let Some(repeat) = metadata.repeat { TestResult::SubTests( (0..repeat) .map(|i| { @@ -394,6 +407,10 @@ fn run_step( true => command.show_output(), false => command, }; + let command = match &step.input { + Some(input) => command.stdin_text(input), + None => command, + }; let output = command.run(); if step.output.ends_with(".out") { let test_output_path = cwd.join(&step.output); diff --git a/tests/specs/node/child_process_extra_pipes/main.out b/tests/specs/node/child_process_extra_pipes/main.out index 694126b924..436afd2f75 100644 --- a/tests/specs/node/child_process_extra_pipes/main.out +++ b/tests/specs/node/child_process_extra_pipes/main.out @@ -1,5 +1,5 @@ -data: hello world [UNORDERED_START] child closed +got: hello world pipe closed [UNORDERED_END] diff --git a/tests/specs/node/child_process_extra_pipes/main.ts b/tests/specs/node/child_process_extra_pipes/main.ts index a3683fe9ee..2837cdc53c 100644 --- a/tests/specs/node/child_process_extra_pipes/main.ts +++ b/tests/specs/node/child_process_extra_pipes/main.ts @@ -1,5 +1,4 @@ import child_process from "node:child_process"; -import { Buffer } from "node:buffer"; import console from "node:console"; const child = child_process.spawn("./test-pipe/target/debug/test-pipe", [], { @@ -8,19 +7,32 @@ const child = child_process.spawn("./test-pipe/target/debug/test-pipe", [], { const extra = child.stdio[4]; -const p = Promise.withResolvers(); +if (!extra) { + throw new Error("no extra pipe"); +} + +const p = Promise.withResolvers(); + +let got = ""; child.on("close", () => { console.log("child closed"); - p.resolve(); + console.log("got:", got); + if (got === "hello world") { + p.resolve(); + } else { + p.reject(new Error(`wanted "hello world", got "${got}"`)); + } }); extra.on("data", (d) => { - console.log("data:", d.toString().trim()); + got += d.toString(); }); extra.on("close", () => { console.log("pipe closed"); }); +extra.write("start"); + await p.promise; diff --git a/tests/specs/node/child_process_extra_pipes/test-pipe/src/main.rs b/tests/specs/node/child_process_extra_pipes/test-pipe/src/main.rs index 192f827313..acc034830f 100644 --- a/tests/specs/node/child_process_extra_pipes/test-pipe/src/main.rs +++ b/tests/specs/node/child_process_extra_pipes/test-pipe/src/main.rs @@ -1,12 +1,31 @@ +use std::fs::File; use std::io::prelude::*; use std::os::fd::FromRawFd; -use std::os::unix::net::UnixStream; fn main() { #[cfg(unix)] { - let mut stream = unsafe { UnixStream::from_raw_fd(4) }; + let mut pipe = unsafe { File::from_raw_fd(4) }; - stream.write_all(b"hello world\n").unwrap(); + let mut read = 0; + let mut buf = [0u8; 1024]; + loop { + if read > 4 { + assert_eq!(&buf[..5], b"start"); + break; + } + match pipe.read(&mut buf) { + Ok(n) => { + read += n; + } + Ok(0) => { + return; + } + Err(e) => { + eprintln!("GOT ERROR: {e:?}"); + } + } + } + pipe.write_all(b"hello world").unwrap(); } } diff --git a/tests/specs/node/cjs_dynamic_import_esm_with_exports/__test__.jsonc b/tests/specs/node/cjs_dynamic_import_esm_with_exports/__test__.jsonc index 980245cb9b..8955fcda2e 100644 --- a/tests/specs/node/cjs_dynamic_import_esm_with_exports/__test__.jsonc +++ b/tests/specs/node/cjs_dynamic_import_esm_with_exports/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "args": "run --check main.ts", "output": "main.out" } diff --git a/tests/specs/node/cjs_reexport_node_condition/__test__.jsonc b/tests/specs/node/cjs_reexport_node_condition/__test__.jsonc new file mode 100644 index 0000000000..030f2aa072 --- /dev/null +++ b/tests/specs/node/cjs_reexport_node_condition/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "[WILDCARD]" + }, + { + "args": "run -A ./main.ts", + "output": "from node\n" + } + ] +} diff --git a/tests/specs/node/cjs_reexport_node_condition/deno.json b/tests/specs/node/cjs_reexport_node_condition/deno.json new file mode 100644 index 0000000000..fde86a1efb --- /dev/null +++ b/tests/specs/node/cjs_reexport_node_condition/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "manual" +} diff --git a/tests/specs/node/cjs_reexport_node_condition/main.ts b/tests/specs/node/cjs_reexport_node_condition/main.ts new file mode 100644 index 0000000000..09b8418a67 --- /dev/null +++ b/tests/specs/node/cjs_reexport_node_condition/main.ts @@ -0,0 +1,3 @@ +import { hello } from "@denotest/mjs-reexport-cjs"; + +console.log(hello); diff --git a/tests/specs/node/cjs_reexport_node_condition/package.json b/tests/specs/node/cjs_reexport_node_condition/package.json new file mode 100644 index 0000000000..85ded5d507 --- /dev/null +++ b/tests/specs/node/cjs_reexport_node_condition/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/mjs-reexport-cjs": "*" + } +} diff --git a/tests/specs/node/cjs_reexport_same_specifier_in_sub_folder/main.out b/tests/specs/node/cjs_reexport_same_specifier_in_sub_folder/main.out index 321d995b8a..c50f064d7f 100644 --- a/tests/specs/node/cjs_reexport_same_specifier_in_sub_folder/main.out +++ b/tests/specs/node/cjs_reexport_same_specifier_in_sub_folder/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/cjs-reexport-same-specifier-in-sub-folder +Download http://localhost:4260/@denotest%2fcjs-reexport-same-specifier-in-sub-folder Download http://localhost:4260/@denotest/cjs-reexport-same-specifier-in-sub-folder/1.0.0.tgz [Module: null prototype] { default: { main: [Getter], sub: [Getter] }, diff --git a/tests/specs/node/imports_wildcard/__test__.jsonc b/tests/specs/node/imports_wildcard/__test__.jsonc index a71e270631..1f5a1fb87f 100644 --- a/tests/specs/node/imports_wildcard/__test__.jsonc +++ b/tests/specs/node/imports_wildcard/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "args": "run main.mjs", "output": "main.out" } diff --git a/tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/__test__.jsonc b/tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/__test__.jsonc new file mode 100644 index 0000000000..0f3b33300b --- /dev/null +++ b/tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run process_beforeexit_exit_events.ts", + "output": "process_beforeexit_exit_events.out", + "exitCode": 0 +} diff --git a/tests/testdata/node/process_beforeexit_exit_events.out b/tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/process_beforeexit_exit_events.out similarity index 100% rename from tests/testdata/node/process_beforeexit_exit_events.out rename to tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/process_beforeexit_exit_events.out diff --git a/tests/testdata/node/process_beforeexit_exit_events.ts b/tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/process_beforeexit_exit_events.ts similarity index 100% rename from tests/testdata/node/process_beforeexit_exit_events.ts rename to tests/specs/node/node_process_beforeexit_exit_events_emitted_without_listeners/process_beforeexit_exit_events.ts diff --git a/tests/specs/node/node_test_module/__test__.jsonc b/tests/specs/node/node_test_module/__test__.jsonc new file mode 100644 index 0000000000..701917bf35 --- /dev/null +++ b/tests/specs/node/node_test_module/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test test.js", + "output": "test.out", + "exitCode": 1 +} diff --git a/tests/testdata/node/test.js b/tests/specs/node/node_test_module/test.js similarity index 100% rename from tests/testdata/node/test.js rename to tests/specs/node/node_test_module/test.js diff --git a/tests/testdata/node/test.out b/tests/specs/node/node_test_module/test.out similarity index 88% rename from tests/testdata/node/test.out rename to tests/specs/node/node_test_module/test.out index 2579f605d2..c37fb355f4 100644 --- a/tests/testdata/node/test.out +++ b/tests/specs/node/node_test_module/test.out @@ -1,5 +1,5 @@ [WILDCARD] -running 63 tests from ./node/test.js +running 63 tests from ./test.js sync pass todo ... ------- output ------- Warning: Not implemented: test.TestContext.todo @@ -57,7 +57,7 @@ async assertion fail ... FAILED [WILDCARD] resolve pass ... ok [WILDCARD] reject fail ... FAILED [WILDCARD] unhandled rejection - passes but warns ... -Uncaught error from ./node/test.js FAILED +Uncaught error from ./test.js FAILED unhandled rejection - passes but warns ... cancelled ([WILDCARD]) async unhandled rejection - passes but warns ... cancelled ([WILDCARD]) immediate throw - passes but warns ... cancelled ([WILDCARD]) @@ -108,32 +108,32 @@ unfinished test with unhandledRejection ... cancelled ([WILDCARD]) ERRORS -sync fail todo => ./node/test.js:20:1 +sync fail todo => ./test.js:20:1 error: Error: thrown from sync fail todo throw new Error("thrown from sync fail todo"); [WILDCARD] -sync fail todo with message => ./node/test.js:25:1 +sync fail todo with message => ./test.js:25:1 error: Error: thrown from sync fail todo with message throw new Error("thrown from sync fail todo with message"); [WILDCARD] -sync throw fail => ./node/test.js:42:1 +sync throw fail => ./test.js:42:1 error: Error: thrown from sync throw fail throw new Error("thrown from sync throw fail"); [WILDCARD] -async throw fail => ./node/test.js:53:1 +async throw fail => ./test.js:53:1 error: Error: thrown from async throw fail throw new Error("thrown from async throw fail"); [WILDCARD] -async skip fail => ./node/test.js:64:1 +async skip fail => ./test.js:64:1 error: Error: thrown from async throw fail throw new Error("thrown from async throw fail"); [WILDCARD] -async assertion fail => ./node/test.js:69:1 +async assertion fail => ./test.js:69:1 error: AssertionError: Values are not strictly equal: @@ -145,13 +145,13 @@ error: AssertionError: Values are not strictly equal: at [WILDCARD] -reject fail => ./node/test.js:78:1 +reject fail => ./test.js:78:1 error: Error: rejected from reject fail return Promise.reject(new Error("rejected from reject fail")); ^ at [WILDCARD] -./node/test.js (uncaught error) +./test.js (uncaught error) error: (in promise) Error: rejected from unhandled rejection fail Promise.reject(new Error("rejected from unhandled rejection fail")); ^ @@ -161,14 +161,14 @@ It most likely originated from a dangling promise, event/timeout handler or top- FAILURES -sync fail todo => ./node/test.js:20:1 -sync fail todo with message => ./node/test.js:25:1 -sync throw fail => ./node/test.js:42:1 -async throw fail => ./node/test.js:53:1 -async skip fail => ./node/test.js:64:1 -async assertion fail => ./node/test.js:69:1 -reject fail => ./node/test.js:78:1 -./node/test.js (uncaught error) +sync fail todo => ./test.js:20:1 +sync fail todo with message => ./test.js:25:1 +sync throw fail => ./test.js:42:1 +async throw fail => ./test.js:53:1 +async skip fail => ./test.js:64:1 +async assertion fail => ./test.js:69:1 +reject fail => ./test.js:78:1 +./test.js (uncaught error) FAILED | 9 passed (2 steps) | 51 failed | 4 ignored [WILDCARD] diff --git a/tests/specs/node/node_test_module_no_sanitizers/__test__.jsonc b/tests/specs/node/node_test_module_no_sanitizers/__test__.jsonc new file mode 100644 index 0000000000..8830e48dde --- /dev/null +++ b/tests/specs/node/node_test_module_no_sanitizers/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test -A --no-check test_no_sanitizers/test.js", + "output": "test_no_sanitizers/test.out", + "exitCode": 0 +} diff --git a/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/cat.ts b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/cat.ts new file mode 100644 index 0000000000..62c82ebca0 --- /dev/null +++ b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/cat.ts @@ -0,0 +1,4 @@ +const filename = Deno.args[0]; +using file = await Deno.open(filename); + +await file.readable.pipeTo(Deno.stdout.writable); diff --git a/tests/testdata/node/test_no_sanitizers/test.js b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.js similarity index 83% rename from tests/testdata/node/test_no_sanitizers/test.js rename to tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.js index edd5587107..52d0f13258 100644 --- a/tests/testdata/node/test_no_sanitizers/test.js +++ b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.js @@ -1,12 +1,11 @@ import test from "node:test"; - test("should not complain about resource and op sanitizers", async (t) => { // resource - const _file1 = Deno.open("welcome.ts"); + const _file1 = Deno.open("test_no_sanitizers/welcome.ts"); await t.test("nested test", () => { // resource - const _file2 = Deno.open("cat.ts"); + const _file2 = Deno.open("test_no_sanitizers/cat.ts"); // op crypto.subtle.digest( diff --git a/tests/testdata/node/test_no_sanitizers/test.out b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.out similarity index 79% rename from tests/testdata/node/test_no_sanitizers/test.out rename to tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.out index 5bd41aadfd..dc5ab7cfd1 100644 --- a/tests/testdata/node/test_no_sanitizers/test.out +++ b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/test.out @@ -1,4 +1,4 @@ -running 1 test from ./node/test_no_sanitizers/test.js +running 1 test from ./test_no_sanitizers/test.js should not complain about resource and op sanitizers ... nested test ... ok ([WILDCARD]) should not complain about resource and op sanitizers ... ok ([WILDCARD]) diff --git a/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/welcome.ts b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/welcome.ts new file mode 100644 index 0000000000..f983ca89ba --- /dev/null +++ b/tests/specs/node/node_test_module_no_sanitizers/test_no_sanitizers/welcome.ts @@ -0,0 +1 @@ +console.log("Welcome to Deno!"); diff --git a/tests/specs/node/web_node_events_dispatched_in_correct_order/__test__.jsonc b/tests/specs/node/web_node_events_dispatched_in_correct_order/__test__.jsonc new file mode 100644 index 0000000000..cb5e48878b --- /dev/null +++ b/tests/specs/node/web_node_events_dispatched_in_correct_order/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run events_order.ts", + "output": "events_order.out", + "exitCode": 0 +} diff --git a/tests/testdata/node/events_order.out b/tests/specs/node/web_node_events_dispatched_in_correct_order/events_order.out similarity index 100% rename from tests/testdata/node/events_order.out rename to tests/specs/node/web_node_events_dispatched_in_correct_order/events_order.out diff --git a/tests/testdata/node/events_order.ts b/tests/specs/node/web_node_events_dispatched_in_correct_order/events_order.ts similarity index 100% rename from tests/testdata/node/events_order.ts rename to tests/specs/node/web_node_events_dispatched_in_correct_order/events_order.ts diff --git a/tests/specs/npm/adding_npm_dep_in_dynamic_import/deno.json b/tests/specs/npm/adding_npm_dep_in_dynamic_import/deno.json index 38bbf89a0c..70897da12c 100644 --- a/tests/specs/npm/adding_npm_dep_in_dynamic_import/deno.json +++ b/tests/specs/npm/adding_npm_dep_in_dynamic_import/deno.json @@ -1,5 +1,5 @@ { - "nodeModulesDir": true, + "nodeModulesDir": "auto", "tasks": { "cat": "cat", "rm_node_modules": "rm -rf node_modules" diff --git a/tests/specs/npm/adding_npm_dep_in_dynamic_import/lock.out b/tests/specs/npm/adding_npm_dep_in_dynamic_import/lock.out index c67be75c93..e80d56bd87 100644 --- a/tests/specs/npm/adding_npm_dep_in_dynamic_import/lock.out +++ b/tests/specs/npm/adding_npm_dep_in_dynamic_import/lock.out @@ -1,20 +1,15 @@ { - "version": "3", - "packages": { - "specifiers": { - "npm:@denotest/add": "npm:@denotest/add@1.0.0", - "npm:@denotest/subtract": "npm:@denotest/subtract@1.0.0" - }, - "npm": { - "@denotest/add@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": {} - }, - "@denotest/subtract@1.0.0": { - "integrity": "[WILDLINE]", - "dependencies": {} - } - } + "version": "4", + "specifiers": { + "npm:@denotest/add@*": "1.0.0", + "npm:@denotest/subtract@*": "1.0.0" }, - "remote": {} + "npm": { + "@denotest/add@1.0.0": { + "integrity": "[WILDLINE]" + }, + "@denotest/subtract@1.0.0": { + "integrity": "[WILDLINE]" + } + } } diff --git a/tests/specs/npm/adding_npm_dep_in_dynamic_import/main.out b/tests/specs/npm/adding_npm_dep_in_dynamic_import/main.out index fe612aa3c1..44c76f28d1 100644 --- a/tests/specs/npm/adding_npm_dep_in_dynamic_import/main.out +++ b/tests/specs/npm/adding_npm_dep_in_dynamic_import/main.out @@ -1,8 +1,8 @@ -Download http://localhost:4260/@denotest/add +Download http://localhost:4260/@denotest%2fadd Download http://localhost:4260/@denotest/add/1.0.0.tgz Initialize @denotest/add@1.0.0 3 -Download http://localhost:4260/@denotest/subtract +Download http://localhost:4260/@denotest%2fsubtract Download http://localhost:4260/@denotest/subtract/1.0.0.tgz Initialize @denotest/subtract@1.0.0 1 diff --git a/tests/specs/npm/bin_entries_prefer_closer/__test__.jsonc b/tests/specs/npm/bin_entries_prefer_closer/__test__.jsonc index 90d788518f..4e9c682df3 100644 --- a/tests/specs/npm/bin_entries_prefer_closer/__test__.jsonc +++ b/tests/specs/npm/bin_entries_prefer_closer/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [ { @@ -21,6 +18,13 @@ { "args": "task run-no-ext", "output": "Task run-no-ext cli-no-ext hello world\n@denotest/bin 0.7.0\n" + }, + { + // even though we didn't put it in .bin, make sure the bin entry is marked executable + "if": "unix", + "commandName": "node_modules/.deno/@denotest+bin@1.0.0/node_modules/@denotest/bin/cli-cjs.js", + "args": "hello", + "output": "hello\n" } ] } diff --git a/tests/specs/npm/bin_entries_prefer_closer/deno.json b/tests/specs/npm/bin_entries_prefer_closer/deno.json index 176354f98f..fbd70ec480 100644 --- a/tests/specs/npm/bin_entries_prefer_closer/deno.json +++ b/tests/specs/npm/bin_entries_prefer_closer/deno.json @@ -1,3 +1,3 @@ { - "nodeModulesDir": true + "nodeModulesDir": "auto" } diff --git a/tests/specs/npm/bin_entries_prefer_closer/install.out b/tests/specs/npm/bin_entries_prefer_closer/install.out index 1d3a995b80..1c9472f46f 100644 --- a/tests/specs/npm/bin_entries_prefer_closer/install.out +++ b/tests/specs/npm/bin_entries_prefer_closer/install.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/transitive-bin -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2ftransitive-bin +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/bin/1.0.0.tgz Download http://localhost:4260/@denotest/transitive-bin/1.0.0.tgz Download http://localhost:4260/@denotest/bin/0.7.0.tgz diff --git a/tests/specs/npm/builtin_module_module/__test__.jsonc b/tests/specs/npm/builtin_module_module/__test__.jsonc new file mode 100644 index 0000000000..eb211eda16 --- /dev/null +++ b/tests/specs/npm/builtin_module_module/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet builtin_module_module/main.js", + "output": "builtin_module_module/main.out" +} diff --git a/tests/testdata/npm/builtin_module_module/main.js b/tests/specs/npm/builtin_module_module/builtin_module_module/main.js similarity index 100% rename from tests/testdata/npm/builtin_module_module/main.js rename to tests/specs/npm/builtin_module_module/builtin_module_module/main.js diff --git a/tests/testdata/npm/builtin_module_module/main.out b/tests/specs/npm/builtin_module_module/builtin_module_module/main.out similarity index 100% rename from tests/testdata/npm/builtin_module_module/main.out rename to tests/specs/npm/builtin_module_module/builtin_module_module/main.out diff --git a/tests/specs/npm/byonm/__test__.jsonc b/tests/specs/npm/byonm/__test__.jsonc index 8edb6b0bf6..011b4b6c82 100644 --- a/tests/specs/npm/byonm/__test__.jsonc +++ b/tests/specs/npm/byonm/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "future_not_installed": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "run -A not_installed.ts", "output": "future_not_installed.out", @@ -12,9 +9,6 @@ }] }, "future_invalid_sub_path": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "[WILDCARD]" diff --git a/tests/specs/npm/byonm/not_installed.out b/tests/specs/npm/byonm/not_installed.out index 29f8651407..2e608c37e0 100644 --- a/tests/specs/npm/byonm/not_installed.out +++ b/tests/specs/npm/byonm/not_installed.out @@ -1,2 +1,2 @@ -error: Could not find "chalk" in a node_modules folder. Deno expects the node_modules/ directory to be up to date. Did you forget to run `npm install`? +error: Could not find "chalk" in a node_modules folder. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`? at file:///[WILDCARD]/not_installed.ts:1:19 diff --git a/tests/specs/npm/byonm_run_npm/__test__.jsonc b/tests/specs/npm/byonm_run_npm/__test__.jsonc new file mode 100644 index 0000000000..4f0b21b0ff --- /dev/null +++ b/tests/specs/npm/byonm_run_npm/__test__.jsonc @@ -0,0 +1,30 @@ +{ + "tests": { + "not_in_deps": { + "steps": [{ + "args": "run -A --quiet npm:cowsay moo", + "output": "not_in_deps.out" + }, { + // ensure it doesn't make any lockfile modifications and thus doesn't write to the lockfile + "args": [ + "eval", + "try { Deno.statSync('deno.lock') } catch (e) { console.log(e instanceof Deno.errors.NotFound); }" + ], + "output": "true\n" + }] + }, + "in_deps": { + "tempDir": true, + "steps": [{ + "args": "install npm:cowsay", + "output": "[WILDCARD]" + }, { + "args": "run --allow-write overwrite.ts", + "output": "[WILDCARD]" + }, { + "args": "run -A npm:cowsay moo", + "output": "replaced\n" + }] + } + } +} diff --git a/tests/specs/npm/byonm_run_npm/deno.json b/tests/specs/npm/byonm_run_npm/deno.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/npm/byonm_run_npm/deno.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/npm/byonm_run_npm/not_in_deps.out b/tests/specs/npm/byonm_run_npm/not_in_deps.out new file mode 100644 index 0000000000..dc07eb43ee --- /dev/null +++ b/tests/specs/npm/byonm_run_npm/not_in_deps.out @@ -0,0 +1,8 @@ + _____ +< moo > + ----- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/tests/specs/npm/byonm_run_npm/overwrite.ts b/tests/specs/npm/byonm_run_npm/overwrite.ts new file mode 100644 index 0000000000..3749c5e4e8 --- /dev/null +++ b/tests/specs/npm/byonm_run_npm/overwrite.ts @@ -0,0 +1,4 @@ +Deno.writeTextFileSync( + "node_modules/cowsay/cli.js", + "console.log('replaced');", +); diff --git a/tests/specs/npm/byonm_run_npm/package.json b/tests/specs/npm/byonm_run_npm/package.json new file mode 100644 index 0000000000..9664f260a7 --- /dev/null +++ b/tests/specs/npm/byonm_run_npm/package.json @@ -0,0 +1,4 @@ +{ + "dependencies": { + } +} diff --git a/tests/specs/npm/cached_only/__test__.jsonc b/tests/specs/npm/cached_only/__test__.jsonc new file mode 100644 index 0000000000..b2190d110d --- /dev/null +++ b/tests/specs/npm/cached_only/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --cached-only cached_only/main.ts", + "output": "cached_only/main.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/cached_only/cached_only/main.out b/tests/specs/npm/cached_only/cached_only/main.out new file mode 100644 index 0000000000..0d0cdad094 --- /dev/null +++ b/tests/specs/npm/cached_only/cached_only/main.out @@ -0,0 +1,2 @@ +error: Error getting response at http://localhost:4260/chalk for package "chalk": An npm specifier not found in cache: "chalk", --cached-only is specified. + at file:///[WILDCARD]/main.ts:1:19 diff --git a/tests/specs/npm/cached_only/cached_only/main.ts b/tests/specs/npm/cached_only/cached_only/main.ts new file mode 100644 index 0000000000..1ccc441a15 --- /dev/null +++ b/tests/specs/npm/cached_only/cached_only/main.ts @@ -0,0 +1,3 @@ +import chalk from "npm:chalk@5"; + +console.log(chalk); diff --git a/tests/specs/npm/check_all/__test__.jsonc b/tests/specs/npm/check_all/__test__.jsonc new file mode 100644 index 0000000000..e78f7e67d8 --- /dev/null +++ b/tests/specs/npm/check_all/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --all check_errors/main.ts", + "output": "check_errors/main_all.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/check_errors/main.ts b/tests/specs/npm/check_all/check_errors/main.ts similarity index 100% rename from tests/testdata/npm/check_errors/main.ts rename to tests/specs/npm/check_all/check_errors/main.ts diff --git a/tests/testdata/npm/check_errors/main_all.out b/tests/specs/npm/check_all/check_errors/main_all.out similarity index 93% rename from tests/testdata/npm/check_errors/main_all.out rename to tests/specs/npm/check_all/check_errors/main_all.out index 4c624c0eaa..c7797e43d2 100644 --- a/tests/testdata/npm/check_errors/main_all.out +++ b/tests/specs/npm/check_all/check_errors/main_all.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/check-error +Download http://localhost:4260/@denotest%2fcheck-error Download http://localhost:4260/@denotest/check-error/1.0.0.tgz Check file:///[WILDCARD]/check_errors/main.ts error: TS2506 [ERROR]: 'Class1' is referenced directly or indirectly in its own base expression. diff --git a/tests/testdata/npm/check_errors/main_local.out b/tests/specs/npm/check_all/check_errors/main_local.out similarity index 86% rename from tests/testdata/npm/check_errors/main_local.out rename to tests/specs/npm/check_all/check_errors/main_local.out index 4d3a892e74..ac58a29c76 100644 --- a/tests/testdata/npm/check_errors/main_local.out +++ b/tests/specs/npm/check_all/check_errors/main_local.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/check-error +Download http://localhost:4260/@denotest%2fcheck-error Download http://localhost:4260/@denotest/check-error/1.0.0.tgz Check file:///[WILDCARD]/check_errors/main.ts error: TS2339 [ERROR]: Property 'Asdf' does not exist on type 'typeof import("file:///[WILDCARD]/@denotest/check-error/1.0.0/index.d.ts")'. diff --git a/tests/specs/npm/check_local/__test__.jsonc b/tests/specs/npm/check_local/__test__.jsonc new file mode 100644 index 0000000000..2cf3ae5ef0 --- /dev/null +++ b/tests/specs/npm/check_local/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check check_errors/main.ts", + "output": "check_errors/main_local.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/check_local/check_errors/main.ts b/tests/specs/npm/check_local/check_errors/main.ts new file mode 100644 index 0000000000..4b86841956 --- /dev/null +++ b/tests/specs/npm/check_local/check_errors/main.ts @@ -0,0 +1,3 @@ +import * as test from "npm:@denotest/check-error"; + +console.log(test.Asdf); // should error diff --git a/tests/specs/npm/check_local/check_errors/main_all.out b/tests/specs/npm/check_local/check_errors/main_all.out new file mode 100644 index 0000000000..c7797e43d2 --- /dev/null +++ b/tests/specs/npm/check_local/check_errors/main_all.out @@ -0,0 +1,19 @@ +Download http://localhost:4260/@denotest%2fcheck-error +Download http://localhost:4260/@denotest/check-error/1.0.0.tgz +Check file:///[WILDCARD]/check_errors/main.ts +error: TS2506 [ERROR]: 'Class1' is referenced directly or indirectly in its own base expression. +export class Class1 extends Class2 { + ~~~~~~ + at file:///[WILDCARD]/check-error/1.0.0/index.d.ts:2:14 + +TS2506 [ERROR]: 'Class2' is referenced directly or indirectly in its own base expression. +export class Class2 extends Class1 { + ~~~~~~ + at file:///[WILDCARD]/check-error/1.0.0/index.d.ts:5:14 + +TS2339 [ERROR]: Property 'Asdf' does not exist on type 'typeof import("file:///[WILDCARD]/@denotest/check-error/1.0.0/index.d.ts")'. +console.log(test.Asdf); // should error + ~~~~ + at file:///[WILDCARD]/check_errors/main.ts:3:18 + +Found 3 errors. diff --git a/tests/specs/npm/check_local/check_errors/main_local.out b/tests/specs/npm/check_local/check_errors/main_local.out new file mode 100644 index 0000000000..1eb8eef9fe --- /dev/null +++ b/tests/specs/npm/check_local/check_errors/main_local.out @@ -0,0 +1,7 @@ +Download http://localhost:4260/@denotest%2fcheck-error +Download http://localhost:4260/@denotest/check-error/1.0.0.tgz +Check file:///[WILDCARD]/check_errors/main.ts +error: TS2339 [ERROR]: Property 'Asdf' does not exist on type 'typeof import("file:///[WILDCARD]/@denotest/check-error/1.0.0/index.d.ts")'. +console.log(test.Asdf); // should error + ~~~~ + at file:///[WILDCARD]/check_errors/main.ts:3:18 diff --git a/tests/specs/npm/check_package_file_dts_dmts_dcts/__test__.jsonc b/tests/specs/npm/check_package_file_dts_dmts_dcts/__test__.jsonc new file mode 100644 index 0000000000..5caaa23aaf --- /dev/null +++ b/tests/specs/npm/check_package_file_dts_dmts_dcts/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check file_dts_dmts_dcts/main.ts", + "output": "file_dts_dmts_dcts/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/file_dts_dmts_dcts/main.out b/tests/specs/npm/check_package_file_dts_dmts_dcts/file_dts_dmts_dcts/main.out similarity index 90% rename from tests/testdata/npm/file_dts_dmts_dcts/main.out rename to tests/specs/npm/check_package_file_dts_dmts_dcts/file_dts_dmts_dcts/main.out index 507d2c2f79..6ab72f53b7 100644 --- a/tests/testdata/npm/file_dts_dmts_dcts/main.out +++ b/tests/specs/npm/check_package_file_dts_dmts_dcts/file_dts_dmts_dcts/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/file-dts-dmts-dcts +Download http://localhost:4260/@denotest%2ffile-dts-dmts-dcts Download http://localhost:4260/@denotest/file-dts-dmts-dcts/1.0.0.tgz Check file:///[WILDCARD]/main.ts error: TS2322 [ERROR]: Type '5' is not assignable to type '"dts"'. diff --git a/tests/testdata/npm/file_dts_dmts_dcts/main.ts b/tests/specs/npm/check_package_file_dts_dmts_dcts/file_dts_dmts_dcts/main.ts similarity index 100% rename from tests/testdata/npm/file_dts_dmts_dcts/main.ts rename to tests/specs/npm/check_package_file_dts_dmts_dcts/file_dts_dmts_dcts/main.ts diff --git a/tests/specs/npm/check_pkg_json_import/main.out b/tests/specs/npm/check_pkg_json_import/main.out index b60509c9a7..11f94272a5 100644 --- a/tests/specs/npm/check_pkg_json_import/main.out +++ b/tests/specs/npm/check_pkg_json_import/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/types-pkg-json-import +Download http://localhost:4260/@denotest%2ftypes-pkg-json-import Download http://localhost:4260/@denotest/types-pkg-json-import/1.0.0.tgz Check file:///[WILDLINE]/main.ts diff --git a/tests/specs/npm/check_prefers_non_types_node_pkg/__test__.jsonc b/tests/specs/npm/check_prefers_non_types_node_pkg/__test__.jsonc index 8c4d0fb206..fc6746d877 100644 --- a/tests/specs/npm/check_prefers_non_types_node_pkg/__test__.jsonc +++ b/tests/specs/npm/check_prefers_non_types_node_pkg/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "byonm": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "[WILDCARD]" @@ -15,12 +12,12 @@ }] }, "auto_install": { - "args": "check --node-modules-dir=true --quiet main.ts", + "args": "check --node-modules-dir=auto --quiet main.ts", "exitCode": 1, "output": "expected.out" }, "global_folder": { - "args": "check --node-modules-dir=false --quiet main.ts", + "args": "check --node-modules-dir=none --quiet main.ts", "exitCode": 1, "output": "expected.out" } diff --git a/tests/specs/npm/check_types_in_types_pkg/__test__.jsonc b/tests/specs/npm/check_types_in_types_pkg/__test__.jsonc index 7b7a429f4d..965a58aea3 100644 --- a/tests/specs/npm/check_types_in_types_pkg/__test__.jsonc +++ b/tests/specs/npm/check_types_in_types_pkg/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "byonm": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "[WILDCARD]" @@ -15,12 +12,12 @@ }] }, "auto_install": { - "args": "check --node-modules-dir=true --quiet main_auto_install.ts", + "args": "check --node-modules-dir=auto --quiet main_auto_install.ts", "exitCode": 1, "output": "expected.out" }, "global_folder": { - "args": "check --node-modules-dir=false --quiet main_auto_install.ts", + "args": "check --node-modules-dir=none --quiet main_auto_install.ts", "exitCode": 1, "output": "expected.out" } diff --git a/tests/specs/npm/child_process_fork_test/__test__.jsonc b/tests/specs/npm/child_process_fork_test/__test__.jsonc new file mode 100644 index 0000000000..a4bdf0c92e --- /dev/null +++ b/tests/specs/npm/child_process_fork_test/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet child_process_fork_test/main.ts", + "output": "child_process_fork_test/main.out" +} diff --git a/tests/testdata/npm/child_process_fork_test/main.out b/tests/specs/npm/child_process_fork_test/child_process_fork_test/main.out similarity index 100% rename from tests/testdata/npm/child_process_fork_test/main.out rename to tests/specs/npm/child_process_fork_test/child_process_fork_test/main.out diff --git a/tests/testdata/npm/child_process_fork_test/main.ts b/tests/specs/npm/child_process_fork_test/child_process_fork_test/main.ts similarity index 100% rename from tests/testdata/npm/child_process_fork_test/main.ts rename to tests/specs/npm/child_process_fork_test/child_process_fork_test/main.ts diff --git a/tests/specs/npm/cjs_import_dual/check.out b/tests/specs/npm/cjs_import_dual/check.out index be1fe86a69..c2d1daa17b 100644 --- a/tests/specs/npm/cjs_import_dual/check.out +++ b/tests/specs/npm/cjs_import_dual/check.out @@ -1,5 +1,5 @@ -Download http://localhost:4260/@denotest/cjs-import-dual -Download http://localhost:4260/@denotest/dual-cjs-esm +Download http://localhost:4260/@denotest%2fcjs-import-dual +Download http://localhost:4260/@denotest%2fdual-cjs-esm Download http://localhost:4260/@denotest/cjs-import-dual/1.0.0.tgz Download http://localhost:4260/@denotest/dual-cjs-esm/1.0.0.tgz Check file:///[WILDLINE]/cjs_import_dual/main.ts diff --git a/tests/specs/npm/cjs_import_dual/run.out b/tests/specs/npm/cjs_import_dual/run.out index 2c05e125e1..0307bf2503 100644 --- a/tests/specs/npm/cjs_import_dual/run.out +++ b/tests/specs/npm/cjs_import_dual/run.out @@ -1,5 +1,5 @@ -Download http://localhost:4260/@denotest/cjs-import-dual -Download http://localhost:4260/@denotest/dual-cjs-esm +Download http://localhost:4260/@denotest%2fcjs-import-dual +Download http://localhost:4260/@denotest%2fdual-cjs-esm Download http://localhost:4260/@denotest/cjs-import-dual/1.0.0.tgz Download http://localhost:4260/@denotest/dual-cjs-esm/1.0.0.tgz cjs diff --git a/tests/specs/npm/cjs_internal_types_default_export/__test__.jsonc b/tests/specs/npm/cjs_internal_types_default_export/__test__.jsonc index dc8aabedb9..c207216f4c 100644 --- a/tests/specs/npm/cjs_internal_types_default_export/__test__.jsonc +++ b/tests/specs/npm/cjs_internal_types_default_export/__test__.jsonc @@ -1,8 +1,5 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "commandName": "npm", "args": "install", diff --git a/tests/specs/npm/cjs_invalid_name_exports/__test__.jsonc b/tests/specs/npm/cjs_invalid_name_exports/__test__.jsonc new file mode 100644 index 0000000000..1d66adbd23 --- /dev/null +++ b/tests/specs/npm/cjs_invalid_name_exports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet cjs-invalid-name-exports/main.ts", + "output": "cjs-invalid-name-exports/main.out" +} diff --git a/tests/testdata/npm/cjs-invalid-name-exports/main.out b/tests/specs/npm/cjs_invalid_name_exports/cjs-invalid-name-exports/main.out similarity index 100% rename from tests/testdata/npm/cjs-invalid-name-exports/main.out rename to tests/specs/npm/cjs_invalid_name_exports/cjs-invalid-name-exports/main.out diff --git a/tests/testdata/npm/cjs-invalid-name-exports/main.ts b/tests/specs/npm/cjs_invalid_name_exports/cjs-invalid-name-exports/main.ts similarity index 100% rename from tests/testdata/npm/cjs-invalid-name-exports/main.ts rename to tests/specs/npm/cjs_invalid_name_exports/cjs-invalid-name-exports/main.ts diff --git a/tests/specs/npm/cjs_local_global_decls/__test__.jsonc b/tests/specs/npm/cjs_local_global_decls/__test__.jsonc new file mode 100644 index 0000000000..6a42f26e6d --- /dev/null +++ b/tests/specs/npm/cjs_local_global_decls/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read cjs_local_global_decls/main.ts", + "output": "cjs_local_global_decls/main.out" +} diff --git a/tests/testdata/npm/cjs_local_global_decls/main.out b/tests/specs/npm/cjs_local_global_decls/cjs_local_global_decls/main.out similarity index 55% rename from tests/testdata/npm/cjs_local_global_decls/main.out rename to tests/specs/npm/cjs_local_global_decls/cjs_local_global_decls/main.out index 5e7a36c8d0..5c48b5b5cf 100644 --- a/tests/testdata/npm/cjs_local_global_decls/main.out +++ b/tests/specs/npm/cjs_local_global_decls/cjs_local_global_decls/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/cjs-local-global-decls +Download http://localhost:4260/@denotest%2fcjs-local-global-decls Download http://localhost:4260/@denotest/cjs-local-global-decls/1.0.0.tgz Loaded. diff --git a/tests/testdata/npm/cjs_local_global_decls/main.ts b/tests/specs/npm/cjs_local_global_decls/cjs_local_global_decls/main.ts similarity index 100% rename from tests/testdata/npm/cjs_local_global_decls/main.ts rename to tests/specs/npm/cjs_local_global_decls/cjs_local_global_decls/main.ts diff --git a/tests/specs/npm/cjs_module_export_assignment/__test__.jsonc b/tests/specs/npm/cjs_module_export_assignment/__test__.jsonc new file mode 100644 index 0000000000..3a8c104aba --- /dev/null +++ b/tests/specs/npm/cjs_module_export_assignment/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet --check=all cjs_module_export_assignment/main.ts", + "output": "cjs_module_export_assignment/main.out" +} diff --git a/tests/testdata/npm/cjs_module_export_assignment/main.out b/tests/specs/npm/cjs_module_export_assignment/cjs_module_export_assignment/main.out similarity index 100% rename from tests/testdata/npm/cjs_module_export_assignment/main.out rename to tests/specs/npm/cjs_module_export_assignment/cjs_module_export_assignment/main.out diff --git a/tests/testdata/npm/cjs_module_export_assignment/main.ts b/tests/specs/npm/cjs_module_export_assignment/cjs_module_export_assignment/main.ts similarity index 100% rename from tests/testdata/npm/cjs_module_export_assignment/main.ts rename to tests/specs/npm/cjs_module_export_assignment/cjs_module_export_assignment/main.ts diff --git a/tests/specs/npm/cjs_module_export_assignment_number/__test__.jsonc b/tests/specs/npm/cjs_module_export_assignment_number/__test__.jsonc new file mode 100644 index 0000000000..1b44f98c37 --- /dev/null +++ b/tests/specs/npm/cjs_module_export_assignment_number/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet --check=all cjs_module_export_assignment_number/main.ts", + "output": "cjs_module_export_assignment_number/main.out" +} diff --git a/tests/testdata/npm/cjs_module_export_assignment_number/main.out b/tests/specs/npm/cjs_module_export_assignment_number/cjs_module_export_assignment_number/main.out similarity index 100% rename from tests/testdata/npm/cjs_module_export_assignment_number/main.out rename to tests/specs/npm/cjs_module_export_assignment_number/cjs_module_export_assignment_number/main.out diff --git a/tests/testdata/npm/cjs_module_export_assignment_number/main.ts b/tests/specs/npm/cjs_module_export_assignment_number/cjs_module_export_assignment_number/main.ts similarity index 100% rename from tests/testdata/npm/cjs_module_export_assignment_number/main.ts rename to tests/specs/npm/cjs_module_export_assignment_number/cjs_module_export_assignment_number/main.ts diff --git a/tests/specs/npm/cjs_pkg_imports/__test__.jsonc b/tests/specs/npm/cjs_pkg_imports/__test__.jsonc new file mode 100644 index 0000000000..0ab9d873d9 --- /dev/null +++ b/tests/specs/npm/cjs_pkg_imports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A cjs_pkg_imports/main.ts", + "output": "cjs_pkg_imports/main.out" +} diff --git a/tests/testdata/npm/cjs_pkg_imports/main.out b/tests/specs/npm/cjs_pkg_imports/cjs_pkg_imports/main.out similarity index 67% rename from tests/testdata/npm/cjs_pkg_imports/main.out rename to tests/specs/npm/cjs_pkg_imports/cjs_pkg_imports/main.out index 661146bd03..f9390fb1bc 100644 --- a/tests/testdata/npm/cjs_pkg_imports/main.out +++ b/tests/specs/npm/cjs_pkg_imports/cjs_pkg_imports/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/cjs-pkg-imports +Download http://localhost:4260/@denotest%2fcjs-pkg-imports Download http://localhost:4260/@denotest/cjs-pkg-imports/1.0.0.tgz { crypto: Crypto { subtle: SubtleCrypto {} }, number: 5 } diff --git a/tests/testdata/npm/cjs_pkg_imports/main.ts b/tests/specs/npm/cjs_pkg_imports/cjs_pkg_imports/main.ts similarity index 100% rename from tests/testdata/npm/cjs_pkg_imports/main.ts rename to tests/specs/npm/cjs_pkg_imports/cjs_pkg_imports/main.ts diff --git a/tests/specs/npm/cjs_reexport_collision/__test__.jsonc b/tests/specs/npm/cjs_reexport_collision/__test__.jsonc new file mode 100644 index 0000000000..582b2c9574 --- /dev/null +++ b/tests/specs/npm/cjs_reexport_collision/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet cjs_reexport_collision/main.ts", + "output": "cjs_reexport_collision/main.out" +} diff --git a/tests/testdata/npm/cjs_reexport_collision/main.out b/tests/specs/npm/cjs_reexport_collision/cjs_reexport_collision/main.out similarity index 100% rename from tests/testdata/npm/cjs_reexport_collision/main.out rename to tests/specs/npm/cjs_reexport_collision/cjs_reexport_collision/main.out diff --git a/tests/testdata/npm/cjs_reexport_collision/main.ts b/tests/specs/npm/cjs_reexport_collision/cjs_reexport_collision/main.ts similarity index 100% rename from tests/testdata/npm/cjs_reexport_collision/main.ts rename to tests/specs/npm/cjs_reexport_collision/cjs_reexport_collision/main.ts diff --git a/tests/specs/npm/cjs_require_esm/__test__.jsonc b/tests/specs/npm/cjs_require_esm/__test__.jsonc new file mode 100644 index 0000000000..b4e03afa3b --- /dev/null +++ b/tests/specs/npm/cjs_require_esm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet cjs_require_esm/main.ts", + "output": "cjs_require_esm/main.out" +} diff --git a/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.out b/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.out new file mode 100644 index 0000000000..4afceccc95 --- /dev/null +++ b/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.out @@ -0,0 +1,4 @@ +[Module: null prototype] { + Test: [Module: null prototype] { Test: [class Test] }, + default: { Test: [Module: null prototype] { Test: [class Test] } } +} diff --git a/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.ts b/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.ts new file mode 100644 index 0000000000..069d4b60eb --- /dev/null +++ b/tests/specs/npm/cjs_require_esm/cjs_require_esm/main.ts @@ -0,0 +1,2 @@ +import * as ns from "npm:@denotest/cjs-require-esm"; +console.log(ns); diff --git a/tests/specs/npm/cjs_require_esm_mjs/__test__.jsonc b/tests/specs/npm/cjs_require_esm_mjs/__test__.jsonc new file mode 100644 index 0000000000..6bcb382e8d --- /dev/null +++ b/tests/specs/npm/cjs_require_esm_mjs/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet cjs_require_esm_mjs/main.ts", + "output": "cjs_require_esm_mjs/main.out" +} diff --git a/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.out b/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.out new file mode 100644 index 0000000000..4afceccc95 --- /dev/null +++ b/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.out @@ -0,0 +1,4 @@ +[Module: null prototype] { + Test: [Module: null prototype] { Test: [class Test] }, + default: { Test: [Module: null prototype] { Test: [class Test] } } +} diff --git a/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.ts b/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.ts new file mode 100644 index 0000000000..d753c2a831 --- /dev/null +++ b/tests/specs/npm/cjs_require_esm_mjs/cjs_require_esm_mjs/main.ts @@ -0,0 +1,2 @@ +import * as ns from "npm:@denotest/cjs-require-esm/require_mjs.js"; +console.log(ns); diff --git a/tests/specs/npm/cjs_sub_path/__test__.jsonc b/tests/specs/npm/cjs_sub_path/__test__.jsonc new file mode 100644 index 0000000000..6a22c17649 --- /dev/null +++ b/tests/specs/npm/cjs_sub_path/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read cjs_sub_path/main.js", + "output": "cjs_sub_path/main.out" +} diff --git a/tests/testdata/npm/cjs_sub_path/main.js b/tests/specs/npm/cjs_sub_path/cjs_sub_path/main.js similarity index 100% rename from tests/testdata/npm/cjs_sub_path/main.js rename to tests/specs/npm/cjs_sub_path/cjs_sub_path/main.js diff --git a/tests/testdata/npm/cjs_sub_path/main.out b/tests/specs/npm/cjs_sub_path/cjs_sub_path/main.out similarity index 100% rename from tests/testdata/npm/cjs_sub_path/main.out rename to tests/specs/npm/cjs_sub_path/cjs_sub_path/main.out diff --git a/tests/specs/npm/cjs_this_in_exports/__test__.jsonc b/tests/specs/npm/cjs_this_in_exports/__test__.jsonc new file mode 100644 index 0000000000..f3b5985810 --- /dev/null +++ b/tests/specs/npm/cjs_this_in_exports/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --allow-read --quiet cjs_this_in_exports/main.js", + "output": "cjs_this_in_exports/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/cjs_this_in_exports/main.js b/tests/specs/npm/cjs_this_in_exports/cjs_this_in_exports/main.js similarity index 100% rename from tests/testdata/npm/cjs_this_in_exports/main.js rename to tests/specs/npm/cjs_this_in_exports/cjs_this_in_exports/main.js diff --git a/tests/testdata/npm/cjs_this_in_exports/main.out b/tests/specs/npm/cjs_this_in_exports/cjs_this_in_exports/main.out similarity index 69% rename from tests/testdata/npm/cjs_this_in_exports/main.out rename to tests/specs/npm/cjs_this_in_exports/cjs_this_in_exports/main.out index ba436bddc9..88c18dbe4e 100644 --- a/tests/testdata/npm/cjs_this_in_exports/main.out +++ b/tests/specs/npm/cjs_this_in_exports/cjs_this_in_exports/main.out @@ -2,4 +2,4 @@ 1 error: Uncaught (in promise) TypeError: this.otherMethod is not a function at getValue (file://[WILDCARD]/@denotest/cjs-this-in-exports/1.0.0/index.js:3:17) - at file://[WILDCARD]/testdata/npm/cjs_this_in_exports/main.js:11:1 + at file://[WILDCARD]/main.js:11:1 diff --git a/tests/specs/npm/cjs_with_deps/__test__.jsonc b/tests/specs/npm/cjs_with_deps/__test__.jsonc new file mode 100644 index 0000000000..e79fda5c77 --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --allow-env cjs_with_deps/main.js", + "output": "cjs_with_deps/main.out" +} diff --git a/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.js b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.out b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info.out b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..8e37c88eb0 --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info_json.out b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..137b9f8ce5 --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_info_json.out @@ -0,0 +1,148 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ] + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [] + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ] + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ] + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [] + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ] + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [] + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ] + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [] + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [] + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ] + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [] + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ] + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [] + } + } +} diff --git a/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_node_modules.out b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/cjs_with_deps/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/compare_globals/__test__.jsonc b/tests/specs/npm/compare_globals/__test__.jsonc new file mode 100644 index 0000000000..e096ddeb22 --- /dev/null +++ b/tests/specs/npm/compare_globals/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --check=all compare_globals/main.ts", + "output": "compare_globals/main.out" +} diff --git a/tests/specs/npm/compare_globals/compare_globals/main.out b/tests/specs/npm/compare_globals/compare_globals/main.out new file mode 100644 index 0000000000..5be6125b08 --- /dev/null +++ b/tests/specs/npm/compare_globals/compare_globals/main.out @@ -0,0 +1,30 @@ +[UNORDERED_START] +Download http://localhost:4260/@types%2fnode +Download http://localhost:4260/undici-types +Download http://localhost:4260/@denotest%2fglobals +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/globals/1.0.0.tgz +Download http://localhost:4260/@types/node/node-22.5.4.tgz +Download http://localhost:4260/undici-types/undici-types-6.19.8.tgz +[UNORDERED_END] +Check file:///[WILDCARD]/compare_globals/main.ts +true +true +[] +setTimeout 1 false +setTimeout 2 function +setTimeout 3 function +setTimeout 4 function +setTimeout 5 undefined +window 1 false +window 2 false +false +false +self 1 true +self 2 true +false +false +bar +bar +true diff --git a/tests/testdata/npm/compare_globals/main.ts b/tests/specs/npm/compare_globals/compare_globals/main.ts similarity index 72% rename from tests/testdata/npm/compare_globals/main.ts rename to tests/specs/npm/compare_globals/compare_globals/main.ts index 5d082386fe..9482798d8c 100644 --- a/tests/testdata/npm/compare_globals/main.ts +++ b/tests/specs/npm/compare_globals/compare_globals/main.ts @@ -17,36 +17,33 @@ controller.abort("reason"); // in the NodeJS declaration it doesn't have a reaso // Some globals are not the same between Node and Deno. // @ts-expect-error incompatible types between Node and Deno -console.log(globalThis.setTimeout === globals.getSetTimeout()); +console.log("setTimeout 1", globalThis.setTimeout === globals.getSetTimeout()); // Super edge case where some Node code deletes a global where the // Node code has its own global and the Deno code has the same global, // but it's different. Basically if some Node code deletes // one of these globals then we don't want it to suddenly inherit // the Deno global (or touch the Deno global at all). -console.log(typeof globalThis.setTimeout); -console.log(typeof globals.getSetTimeout()); +console.log("setTimeout 2", typeof globalThis.setTimeout); +console.log("setTimeout 3", typeof globals.getSetTimeout()); globals.deleteSetTimeout(); -console.log(typeof globalThis.setTimeout); -console.log(typeof globals.getSetTimeout()); +console.log("setTimeout 4", typeof globalThis.setTimeout); +console.log("setTimeout 5", typeof globals.getSetTimeout()); -// In Deno, the process global is not defined, but in Node it is. -console.log("process" in globalThis); -console.log( - Object.getOwnPropertyDescriptor(globalThis, "process") !== undefined, -); -globals.checkProcessGlobal(); - -// In Deno, the window and self globals are defined, but in Node they are not. -console.log("window" in globalThis); -console.log("self" in globalThis); +// In Deno 2 and Node.js, the window global is not defined. +console.log("window 1", "window" in globalThis); console.log( + "window 2", Object.getOwnPropertyDescriptor(globalThis, "window") !== undefined, ); +globals.checkWindowGlobal(); + +// In Deno 2 self global is defined, but in Node it is not. +console.log("self 1", "self" in globalThis); console.log( + "self 2", Object.getOwnPropertyDescriptor(globalThis, "self") !== undefined, ); -globals.checkWindowGlobal(); globals.checkSelfGlobal(); // "Non-managed" globals are shared between Node and Deno. diff --git a/tests/specs/npm/conditional_exports/main.out b/tests/specs/npm/conditional_exports/main.out index 8bd31321b6..8b5b2715be 100644 --- a/tests/specs/npm/conditional_exports/main.out +++ b/tests/specs/npm/conditional_exports/main.out @@ -1,8 +1,8 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/conditional-exports +Download http://localhost:4260/@denotest%2fconditional-exports Download http://localhost:4260/supports-esm Download http://localhost:4260/has-package-exports -Download http://localhost:4260/@ljharb/has-package-exports-patterns +Download http://localhost:4260/@ljharb%2fhas-package-exports-patterns [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/conditional-exports/1.0.0.tgz diff --git a/tests/specs/npm/conditional_exports_node_modules_dir/__test__.jsonc b/tests/specs/npm/conditional_exports_node_modules_dir/__test__.jsonc index 757e1c4e0e..745b28f4f2 100644 --- a/tests/specs/npm/conditional_exports_node_modules_dir/__test__.jsonc +++ b/tests/specs/npm/conditional_exports_node_modules_dir/__test__.jsonc @@ -1,5 +1,5 @@ { "tempDir": true, - "args": "run --allow-read --node-modules-dir main.js", + "args": "run --allow-read --node-modules-dir=auto main.js", "output": "main.out" } diff --git a/tests/specs/npm/conditional_exports_node_modules_dir/main.out b/tests/specs/npm/conditional_exports_node_modules_dir/main.out index 5fbba560d3..ee4a64be61 100644 --- a/tests/specs/npm/conditional_exports_node_modules_dir/main.out +++ b/tests/specs/npm/conditional_exports_node_modules_dir/main.out @@ -1,8 +1,8 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/conditional-exports +Download http://localhost:4260/@denotest%2fconditional-exports Download http://localhost:4260/supports-esm Download http://localhost:4260/has-package-exports -Download http://localhost:4260/@ljharb/has-package-exports-patterns +Download http://localhost:4260/@ljharb%2fhas-package-exports-patterns [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/conditional-exports/1.0.0.tgz diff --git a/tests/specs/npm/create_require/__test__.jsonc b/tests/specs/npm/create_require/__test__.jsonc new file mode 100644 index 0000000000..901a977d7c --- /dev/null +++ b/tests/specs/npm/create_require/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --reload --allow-read create_require/main.ts", + "output": "create_require/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/create_require/main.out b/tests/specs/npm/create_require/create_require/main.out similarity index 100% rename from tests/testdata/npm/create_require/main.out rename to tests/specs/npm/create_require/create_require/main.out diff --git a/tests/testdata/npm/create_require/main.ts b/tests/specs/npm/create_require/create_require/main.ts similarity index 100% rename from tests/testdata/npm/create_require/main.ts rename to tests/specs/npm/create_require/create_require/main.ts diff --git a/tests/specs/npm/deno_cache/__test__.jsonc b/tests/specs/npm/deno_cache/__test__.jsonc new file mode 100644 index 0000000000..302b25e413 --- /dev/null +++ b/tests/specs/npm/deno_cache/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "cache --reload npm:chalk npm:mkdirp", + "output": "deno_cache.out" +} diff --git a/tests/testdata/npm/deno_cache.out b/tests/specs/npm/deno_cache/deno_cache.out similarity index 100% rename from tests/testdata/npm/deno_cache.out rename to tests/specs/npm/deno_cache/deno_cache.out diff --git a/tests/specs/npm/deno_run_bin_cjs/__test__.jsonc b/tests/specs/npm/deno_run_bin_cjs/__test__.jsonc new file mode 100644 index 0000000000..cd4bcb119c --- /dev/null +++ b/tests/specs/npm/deno_run_bin_cjs/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/bin/cli-cjs this is a test", + "output": "deno_run_cjs.out" +} diff --git a/tests/testdata/npm/deno_run_no_ext.out b/tests/specs/npm/deno_run_bin_cjs/deno_run_cjs.out similarity index 100% rename from tests/testdata/npm/deno_run_no_ext.out rename to tests/specs/npm/deno_run_bin_cjs/deno_run_cjs.out diff --git a/tests/specs/npm/deno_run_bin_cjs_no_bin_entrypoint/__test__.jsonc b/tests/specs/npm/deno_run_bin_cjs_no_bin_entrypoint/__test__.jsonc new file mode 100644 index 0000000000..0e86d9974c --- /dev/null +++ b/tests/specs/npm/deno_run_bin_cjs_no_bin_entrypoint/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/bin@0.6.0/cli-cjs.js this is a test", + "output": "deno_run_cjs.out" +} diff --git a/tests/testdata/npm/deno_run_special_chars_in_bin_name.out b/tests/specs/npm/deno_run_bin_cjs_no_bin_entrypoint/deno_run_cjs.out similarity index 100% rename from tests/testdata/npm/deno_run_special_chars_in_bin_name.out rename to tests/specs/npm/deno_run_bin_cjs_no_bin_entrypoint/deno_run_cjs.out diff --git a/tests/specs/npm/deno_run_bin_esm/__test__.jsonc b/tests/specs/npm/deno_run_bin_esm/__test__.jsonc new file mode 100644 index 0000000000..828cf6b0da --- /dev/null +++ b/tests/specs/npm/deno_run_bin_esm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/bin/cli-esm this is a test", + "output": "deno_run_esm.out" +} diff --git a/tests/specs/npm/deno_run_bin_esm/deno_run_esm.out b/tests/specs/npm/deno_run_bin_esm/deno_run_esm.out new file mode 100644 index 0000000000..ffe7cbd891 --- /dev/null +++ b/tests/specs/npm/deno_run_bin_esm/deno_run_esm.out @@ -0,0 +1,4 @@ +this +is +a +test diff --git a/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/__test__.jsonc b/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/__test__.jsonc new file mode 100644 index 0000000000..c2c0117f7a --- /dev/null +++ b/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/bin@0.6.0/cli.mjs this is a test", + "output": "deno_run_esm.out" +} diff --git a/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/deno_run_esm.out b/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/deno_run_esm.out new file mode 100644 index 0000000000..ffe7cbd891 --- /dev/null +++ b/tests/specs/npm/deno_run_bin_esm_no_bin_entrypoint/deno_run_esm.out @@ -0,0 +1,4 @@ +this +is +a +test diff --git a/tests/specs/npm/deno_run_bin_no_ext/__test__.jsonc b/tests/specs/npm/deno_run_bin_no_ext/__test__.jsonc new file mode 100644 index 0000000000..3f5cc3f2a4 --- /dev/null +++ b/tests/specs/npm/deno_run_bin_no_ext/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/bin/cli-no-ext this is a test", + "output": "deno_run_no_ext.out" +} diff --git a/tests/specs/npm/deno_run_bin_no_ext/deno_run_no_ext.out b/tests/specs/npm/deno_run_bin_no_ext/deno_run_no_ext.out new file mode 100644 index 0000000000..ffe7cbd891 --- /dev/null +++ b/tests/specs/npm/deno_run_bin_no_ext/deno_run_no_ext.out @@ -0,0 +1,4 @@ +this +is +a +test diff --git a/tests/specs/npm/deno_run_bin_special_chars/__test__.jsonc b/tests/specs/npm/deno_run_bin_special_chars/__test__.jsonc new file mode 100644 index 0000000000..23a339349d --- /dev/null +++ b/tests/specs/npm/deno_run_bin_special_chars/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:@denotest/special-chars-in-bin-name/\\foo\" this is a test", + "output": "deno_run_special_chars_in_bin_name.out" +} diff --git a/tests/specs/npm/deno_run_bin_special_chars/deno_run_special_chars_in_bin_name.out b/tests/specs/npm/deno_run_bin_special_chars/deno_run_special_chars_in_bin_name.out new file mode 100644 index 0000000000..ffe7cbd891 --- /dev/null +++ b/tests/specs/npm/deno_run_bin_special_chars/deno_run_special_chars_in_bin_name.out @@ -0,0 +1,4 @@ +this +is +a +test diff --git a/tests/specs/npm/deno_run_cowsay/__test__.jsonc b/tests/specs/npm/deno_run_cowsay/__test__.jsonc new file mode 100644 index 0000000000..36a677534c --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:cowsay@1.5.0 Hello", + "output": "deno_run_cowsay.out" +} diff --git a/tests/specs/npm/deno_run_cowsay/deno_run_cowsay.out b/tests/specs/npm/deno_run_cowsay/deno_run_cowsay.out new file mode 100644 index 0000000000..46de827306 --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay/deno_run_cowsay.out @@ -0,0 +1,8 @@ + _______ +< Hello > + ------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/tests/specs/npm/deno_run_cowsay_explicit/__test__.jsonc b/tests/specs/npm/deno_run_cowsay_explicit/__test__.jsonc new file mode 100644 index 0000000000..a515fd16ce --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay_explicit/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:cowsay@1.5.0/cowsay Hello", + "output": "deno_run_cowsay.out" +} diff --git a/tests/specs/npm/deno_run_cowsay_explicit/deno_run_cowsay.out b/tests/specs/npm/deno_run_cowsay_explicit/deno_run_cowsay.out new file mode 100644 index 0000000000..46de827306 --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay_explicit/deno_run_cowsay.out @@ -0,0 +1,8 @@ + _______ +< Hello > + ------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/__test__.jsonc b/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/__test__.jsonc new file mode 100644 index 0000000000..fdc0a7da1e --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run -A --quiet --node-modules-dir npm:cowsay@1.5.0 Hello", + "output": "deno_run_cowsay.out" +} diff --git a/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/deno_run_cowsay.out b/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/deno_run_cowsay.out new file mode 100644 index 0000000000..46de827306 --- /dev/null +++ b/tests/specs/npm/deno_run_cowsay_with_node_modules_dir/deno_run_cowsay.out @@ -0,0 +1,8 @@ + _______ +< Hello > + ------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/tests/specs/npm/deno_run_cowthink/__test__.jsonc b/tests/specs/npm/deno_run_cowthink/__test__.jsonc new file mode 100644 index 0000000000..622c0a51c3 --- /dev/null +++ b/tests/specs/npm/deno_run_cowthink/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet npm:cowsay@1.5.0/cowthink Hello", + "output": "deno_run_cowthink.out" +} diff --git a/tests/specs/npm/deno_run_cowthink/deno_run_cowthink.out b/tests/specs/npm/deno_run_cowthink/deno_run_cowthink.out new file mode 100644 index 0000000000..8dd990ed6f --- /dev/null +++ b/tests/specs/npm/deno_run_cowthink/deno_run_cowthink.out @@ -0,0 +1,8 @@ + _______ +( Hello ) + ------- + o ^__^ + o (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/tests/specs/npm/deno_run_no_bin_entrypoint/__test__.jsonc b/tests/specs/npm/deno_run_no_bin_entrypoint/__test__.jsonc new file mode 100644 index 0000000000..43a2701f19 --- /dev/null +++ b/tests/specs/npm/deno_run_no_bin_entrypoint/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet npm:@denotest/esm-basic", + "output": "deno_run_no_bin_entrypoint.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/deno_run_no_bin_entrypoint.out b/tests/specs/npm/deno_run_no_bin_entrypoint/deno_run_no_bin_entrypoint.out similarity index 100% rename from tests/testdata/npm/deno_run_no_bin_entrypoint.out rename to tests/specs/npm/deno_run_no_bin_entrypoint/deno_run_no_bin_entrypoint.out diff --git a/tests/specs/npm/deno_run_no_bin_entrypoint_non_existent_subpath/__test__.jsonc b/tests/specs/npm/deno_run_no_bin_entrypoint_non_existent_subpath/__test__.jsonc new file mode 100644 index 0000000000..94b12f2b4a --- /dev/null +++ b/tests/specs/npm/deno_run_no_bin_entrypoint_non_existent_subpath/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet npm:@denotest/esm-basic/non-existent.js", + "output": "deno_run_no_bin_entrypoint_non_existent_subpath.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/deno_run_no_bin_entrypoint_non_existent_subpath.out b/tests/specs/npm/deno_run_no_bin_entrypoint_non_existent_subpath/deno_run_no_bin_entrypoint_non_existent_subpath.out similarity index 100% rename from tests/testdata/npm/deno_run_no_bin_entrypoint_non_existent_subpath.out rename to tests/specs/npm/deno_run_no_bin_entrypoint_non_existent_subpath/deno_run_no_bin_entrypoint_non_existent_subpath.out diff --git a/tests/specs/npm/deno_run_non_existent/__test__.jsonc b/tests/specs/npm/deno_run_non_existent/__test__.jsonc new file mode 100644 index 0000000000..d112c96699 --- /dev/null +++ b/tests/specs/npm/deno_run_non_existent/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run npm:mkdirp@0.5.125", + "output": "deno_run_non_existent.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/deno_run_non_existent.out b/tests/specs/npm/deno_run_non_existent/deno_run_non_existent.out similarity index 100% rename from tests/testdata/npm/deno_run_non_existent.out rename to tests/specs/npm/deno_run_non_existent/deno_run_non_existent.out diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_false/__test__.jsonc b/tests/specs/npm/different_nested_dep_node_modules_dir_false/__test__.jsonc new file mode 100644 index 0000000000..07db0a1acb --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_false/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --no-lock --node-modules-dir=none different_nested_dep/main.js", + "output": "different_nested_dep/main.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/main.js b/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/main.js new file mode 100644 index 0000000000..5677eb094a --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/main.js @@ -0,0 +1,5 @@ +import dep from "@denotest/different-nested-dep"; +import childDep from "@denotest/different-nested-dep-child"; + +console.log(dep); +console.log(childDep); diff --git a/tests/testdata/package_json/deno_json/main.out b/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/main.out similarity index 100% rename from tests/testdata/package_json/deno_json/main.out rename to tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/main.out diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/package.json b/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/package.json new file mode 100644 index 0000000000..c204258514 --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_false/different_nested_dep/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@denotest/different-nested-dep": "1.0.0", + "@denotest/different-nested-dep-child": "2.0.0" + } +} diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_true/__test__.jsonc b/tests/specs/npm/different_nested_dep_node_modules_dir_true/__test__.jsonc new file mode 100644 index 0000000000..7fd130e506 --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_true/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run --no-lock --quiet --node-modules-dir=auto different_nested_dep/main.js", + "output": "different_nested_dep/main.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.js b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.js new file mode 100644 index 0000000000..5677eb094a --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.js @@ -0,0 +1,5 @@ +import dep from "@denotest/different-nested-dep"; +import childDep from "@denotest/different-nested-dep-child"; + +console.log(dep); +console.log(childDep); diff --git a/tests/testdata/task/package_json_pre_only/echo.out b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.out similarity index 50% rename from tests/testdata/task/package_json_pre_only/echo.out rename to tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.out index d00491fd7e..1191247b6d 100644 --- a/tests/testdata/task/package_json_pre_only/echo.out +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/main.out @@ -1 +1,2 @@ 1 +2 diff --git a/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/package.json b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/package.json new file mode 100644 index 0000000000..c204258514 --- /dev/null +++ b/tests/specs/npm/different_nested_dep_node_modules_dir_true/different_nested_dep/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@denotest/different-nested-dep": "1.0.0", + "@denotest/different-nested-dep-child": "2.0.0" + } +} diff --git a/tests/specs/npm/directory_import_folder_index_js/__test__.jsonc b/tests/specs/npm/directory_import_folder_index_js/__test__.jsonc new file mode 100644 index 0000000000..b3f7b64cbd --- /dev/null +++ b/tests/specs/npm/directory_import_folder_index_js/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run directory_import/folder_index_js.ts", + "output": "directory_import/folder_index_js.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/directory_import/folder_index_js.out b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_index_js.out similarity index 83% rename from tests/testdata/npm/directory_import/folder_index_js.out rename to tests/specs/npm/directory_import_folder_index_js/directory_import/folder_index_js.out index a700b8fdb6..c1eb2a4801 100644 --- a/tests/testdata/npm/directory_import/folder_index_js.out +++ b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_index_js.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/sub-folders +Download http://localhost:4260/@denotest%2fsub-folders Download http://localhost:4260/@denotest/sub-folders/1.0.0.tgz error: Directory import [WILDCARD]folder_index_js is not supported resolving import from file:///[WILDCARD]/directory_import/folder_index_js.ts Did you mean to import index.js within the directory? diff --git a/tests/testdata/npm/directory_import/folder_index_js.ts b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_index_js.ts similarity index 100% rename from tests/testdata/npm/directory_import/folder_index_js.ts rename to tests/specs/npm/directory_import_folder_index_js/directory_import/folder_index_js.ts diff --git a/tests/testdata/npm/directory_import/folder_no_index.out b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_no_index.out similarity index 79% rename from tests/testdata/npm/directory_import/folder_no_index.out rename to tests/specs/npm/directory_import_folder_index_js/directory_import/folder_no_index.out index 844419b4c6..c19c4bcaa4 100644 --- a/tests/testdata/npm/directory_import/folder_no_index.out +++ b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_no_index.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/sub-folders +Download http://localhost:4260/@denotest%2fsub-folders Download http://localhost:4260/@denotest/sub-folders/1.0.0.tgz error: Directory import [WILDCARD]folder_no_index is not supported resolving import from file:///[WILDCARD]/folder_no_index.ts diff --git a/tests/testdata/npm/directory_import/folder_no_index.ts b/tests/specs/npm/directory_import_folder_index_js/directory_import/folder_no_index.ts similarity index 100% rename from tests/testdata/npm/directory_import/folder_no_index.ts rename to tests/specs/npm/directory_import_folder_index_js/directory_import/folder_no_index.ts diff --git a/tests/specs/npm/directory_import_folder_no_index/__test__.jsonc b/tests/specs/npm/directory_import_folder_no_index/__test__.jsonc new file mode 100644 index 0000000000..e0bb868ad8 --- /dev/null +++ b/tests/specs/npm/directory_import_folder_no_index/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run directory_import/folder_no_index.ts", + "output": "directory_import/folder_no_index.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.out b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.out new file mode 100644 index 0000000000..c1eb2a4801 --- /dev/null +++ b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.out @@ -0,0 +1,7 @@ +Download http://localhost:4260/@denotest%2fsub-folders +Download http://localhost:4260/@denotest/sub-folders/1.0.0.tgz +error: Directory import [WILDCARD]folder_index_js is not supported resolving import from file:///[WILDCARD]/directory_import/folder_index_js.ts +Did you mean to import index.js within the directory? + +Caused by: + [WILDCARD] diff --git a/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.ts b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.ts new file mode 100644 index 0000000000..b0d51fcd97 --- /dev/null +++ b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_index_js.ts @@ -0,0 +1,2 @@ +import test from "npm:@denotest/sub-folders/folder_index_js"; +console.log(test); diff --git a/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.out b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.out new file mode 100644 index 0000000000..c19c4bcaa4 --- /dev/null +++ b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.out @@ -0,0 +1,6 @@ +Download http://localhost:4260/@denotest%2fsub-folders +Download http://localhost:4260/@denotest/sub-folders/1.0.0.tgz +error: Directory import [WILDCARD]folder_no_index is not supported resolving import from file:///[WILDCARD]/folder_no_index.ts + +Caused by: + [WILDCARD] diff --git a/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.ts b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.ts new file mode 100644 index 0000000000..4c5fb7ec09 --- /dev/null +++ b/tests/specs/npm/directory_import_folder_no_index/directory_import/folder_no_index.ts @@ -0,0 +1,2 @@ +import test from "npm:@denotest/sub-folders/folder_no_index"; +console.log(test); diff --git a/tests/specs/npm/dual_cjs_esm/__test__.jsonc b/tests/specs/npm/dual_cjs_esm/__test__.jsonc new file mode 100644 index 0000000000..f2b0d694e3 --- /dev/null +++ b/tests/specs/npm/dual_cjs_esm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet dual_cjs_esm/main.ts", + "output": "dual_cjs_esm/main.out" +} diff --git a/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.out b/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.out new file mode 100644 index 0000000000..32e232f11c --- /dev/null +++ b/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.out @@ -0,0 +1,3 @@ +esm +cjs +cjs diff --git a/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.ts b/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.ts new file mode 100644 index 0000000000..4f3b796678 --- /dev/null +++ b/tests/specs/npm/dual_cjs_esm/dual_cjs_esm/main.ts @@ -0,0 +1,6 @@ +import { getKind } from "npm:@denotest/dual-cjs-esm@latest"; // test out @latest dist tag +import * as cjs from "npm:@denotest/dual-cjs-esm@latest/cjs/main.cjs"; + +console.log(getKind()); +console.log(cjs.getKind()); +console.log(cjs.getSubPathKind()); diff --git a/tests/specs/npm/dynamic_import_deno_ts_from_npm/__test__.jsonc b/tests/specs/npm/dynamic_import_deno_ts_from_npm/__test__.jsonc new file mode 100644 index 0000000000..61ad30115d --- /dev/null +++ b/tests/specs/npm/dynamic_import_deno_ts_from_npm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet dynamic_import_deno_ts_from_npm/main.ts", + "output": "dynamic_import_deno_ts_from_npm/main.out" +} diff --git a/tests/testdata/npm/dynamic_import_deno_ts_from_npm/add.ts b/tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/add.ts similarity index 100% rename from tests/testdata/npm/dynamic_import_deno_ts_from_npm/add.ts rename to tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/add.ts diff --git a/tests/testdata/npm/dynamic_import_deno_ts_from_npm/main.out b/tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/main.out similarity index 100% rename from tests/testdata/npm/dynamic_import_deno_ts_from_npm/main.out rename to tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/main.out diff --git a/tests/testdata/npm/dynamic_import_deno_ts_from_npm/main.ts b/tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/main.ts similarity index 100% rename from tests/testdata/npm/dynamic_import_deno_ts_from_npm/main.ts rename to tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/main.ts diff --git a/tests/testdata/npm/dynamic_import_deno_ts_from_npm/subtract.mts b/tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/subtract.mts similarity index 100% rename from tests/testdata/npm/dynamic_import_deno_ts_from_npm/subtract.mts rename to tests/specs/npm/dynamic_import_deno_ts_from_npm/dynamic_import_deno_ts_from_npm/subtract.mts diff --git a/tests/specs/npm/dynamic_import_invalid_package_name/__test__.jsonc b/tests/specs/npm/dynamic_import_invalid_package_name/__test__.jsonc new file mode 100644 index 0000000000..912ff43147 --- /dev/null +++ b/tests/specs/npm/dynamic_import_invalid_package_name/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --reload dynamic_import_invalid_package_name/main.ts", + "output": "dynamic_import_invalid_package_name/main.out" +} diff --git a/tests/testdata/npm/dynamic_import_invalid_package_name/main.out b/tests/specs/npm/dynamic_import_invalid_package_name/dynamic_import_invalid_package_name/main.out similarity index 100% rename from tests/testdata/npm/dynamic_import_invalid_package_name/main.out rename to tests/specs/npm/dynamic_import_invalid_package_name/dynamic_import_invalid_package_name/main.out diff --git a/tests/testdata/npm/dynamic_import_invalid_package_name/main.ts b/tests/specs/npm/dynamic_import_invalid_package_name/dynamic_import_invalid_package_name/main.ts similarity index 100% rename from tests/testdata/npm/dynamic_import_invalid_package_name/main.ts rename to tests/specs/npm/dynamic_import_invalid_package_name/dynamic_import_invalid_package_name/main.ts diff --git a/tests/specs/npm/dynamic_import_json/__test__.jsonc b/tests/specs/npm/dynamic_import_json/__test__.jsonc new file mode 100644 index 0000000000..ee05ba69af --- /dev/null +++ b/tests/specs/npm/dynamic_import_json/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet import_json/main.js", + "output": "import_json/main.out" +} diff --git a/tests/testdata/npm/import_json/main.js b/tests/specs/npm/dynamic_import_json/import_json/main.js similarity index 100% rename from tests/testdata/npm/import_json/main.js rename to tests/specs/npm/dynamic_import_json/import_json/main.js diff --git a/tests/testdata/npm/import_json/main.out b/tests/specs/npm/dynamic_import_json/import_json/main.out similarity index 100% rename from tests/testdata/npm/import_json/main.out rename to tests/specs/npm/dynamic_import_json/import_json/main.out diff --git a/tests/specs/npm/dynamic_import_reload_same_package/__test__.jsonc b/tests/specs/npm/dynamic_import_reload_same_package/__test__.jsonc new file mode 100644 index 0000000000..4434b794dd --- /dev/null +++ b/tests/specs/npm/dynamic_import_reload_same_package/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --reload dynamic_import_reload_same_package/main.ts", + "output": "dynamic_import_reload_same_package/main.out" +} diff --git a/tests/testdata/npm/dynamic_import_reload_same_package/main.out b/tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/main.out similarity index 100% rename from tests/testdata/npm/dynamic_import_reload_same_package/main.out rename to tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/main.out diff --git a/tests/testdata/npm/dynamic_import_reload_same_package/main.ts b/tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/main.ts similarity index 100% rename from tests/testdata/npm/dynamic_import_reload_same_package/main.ts rename to tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/main.ts diff --git a/tests/testdata/npm/dynamic_import_reload_same_package/other.ts b/tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/other.ts similarity index 100% rename from tests/testdata/npm/dynamic_import_reload_same_package/other.ts rename to tests/specs/npm/dynamic_import_reload_same_package/dynamic_import_reload_same_package/other.ts diff --git a/tests/specs/npm/dynamic_npm_resolution_failure/main.out b/tests/specs/npm/dynamic_npm_resolution_failure/main.out index 03c733567b..8888c4f0ae 100644 --- a/tests/specs/npm/dynamic_npm_resolution_failure/main.out +++ b/tests/specs/npm/dynamic_npm_resolution_failure/main.out @@ -1,14 +1,14 @@ [UNORDERED_START] Download http://localhost:4260/chalk -Download http://localhost:4260/@denotest/dep-cannot-parse +Download http://localhost:4260/@denotest%2fdep-cannot-parse [UNORDERED_END] Download http://localhost:4260/chalk/chalk-5.0.1.tgz Hi -TypeError: Error in @denotest/dep-cannot-parse@1.0.0 parsing version requirement for dependency: @denotest/esm-basic@unknown-scheme:unknown - -Invalid npm version requirement. Unexpected character. - unknown-scheme:unknown - ~ +TypeError: Error in @denotest/dep-cannot-parse@1.0.0 parsing version requirement for dependency "@denotest/esm-basic": "unknown-scheme:unknown" + 0: Invalid version requirement + 1: Unexpected character. + unknown-scheme:unknown + ~ at async file:///[WILDLINE]main.ts:5:3 { code: "ERR_MODULE_NOT_FOUND" } diff --git a/tests/specs/npm/env_var_re_export_dev/__test__.jsonc b/tests/specs/npm/env_var_re_export_dev/__test__.jsonc new file mode 100644 index 0000000000..50d8353ca1 --- /dev/null +++ b/tests/specs/npm/env_var_re_export_dev/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --allow-env --quiet env_var_re_export/main.js", + "output": "dev\n" +} diff --git a/tests/testdata/npm/env_var_re_export/main.js b/tests/specs/npm/env_var_re_export_dev/env_var_re_export/main.js similarity index 100% rename from tests/testdata/npm/env_var_re_export/main.js rename to tests/specs/npm/env_var_re_export_dev/env_var_re_export/main.js diff --git a/tests/specs/npm/env_var_re_export_prod/__test__.jsonc b/tests/specs/npm/env_var_re_export_prod/__test__.jsonc new file mode 100644 index 0000000000..64b19e1a7a --- /dev/null +++ b/tests/specs/npm/env_var_re_export_prod/__test__.jsonc @@ -0,0 +1,7 @@ +{ + "args": "run --allow-read --allow-env --quiet env_var_re_export/main.js", + "output": "prod\n", + "envs": { + "NODE_ENV": "production" + } +} diff --git a/tests/specs/npm/env_var_re_export_prod/env_var_re_export/main.js b/tests/specs/npm/env_var_re_export_prod/env_var_re_export/main.js new file mode 100644 index 0000000000..ed91487a0b --- /dev/null +++ b/tests/specs/npm/env_var_re_export_prod/env_var_re_export/main.js @@ -0,0 +1,3 @@ +import { getEnv } from "npm:@denotest/env-var-re-export"; + +console.log(getEnv()); diff --git a/tests/specs/npm/error_version_after_subpath/__test__.jsonc b/tests/specs/npm/error_version_after_subpath/__test__.jsonc new file mode 100644 index 0000000000..467d42157e --- /dev/null +++ b/tests/specs/npm/error_version_after_subpath/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet error_version_after_subpath/main.js", + "output": "error_version_after_subpath/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/error_version_after_subpath/main.js b/tests/specs/npm/error_version_after_subpath/error_version_after_subpath/main.js similarity index 100% rename from tests/testdata/npm/error_version_after_subpath/main.js rename to tests/specs/npm/error_version_after_subpath/error_version_after_subpath/main.js diff --git a/tests/testdata/npm/error_version_after_subpath/main.out b/tests/specs/npm/error_version_after_subpath/error_version_after_subpath/main.out similarity index 65% rename from tests/testdata/npm/error_version_after_subpath/main.out rename to tests/specs/npm/error_version_after_subpath/error_version_after_subpath/main.out index 0cdd1b6da0..4e5f03e23c 100644 --- a/tests/testdata/npm/error_version_after_subpath/main.out +++ b/tests/specs/npm/error_version_after_subpath/error_version_after_subpath/main.out @@ -1,2 +1,2 @@ error: Invalid package specifier 'npm:react-dom/server@18.2.0'. Did you mean to write 'npm:react-dom@18.2.0/server'? - at [WILDCARD]/npm/error_version_after_subpath/main.js:1:8 + at [WILDCARD]/error_version_after_subpath/main.js:1:8 diff --git a/tests/specs/npm/es_module/__test__.jsonc b/tests/specs/npm/es_module/__test__.jsonc index d72db753f8..2ab61686ef 100644 --- a/tests/specs/npm/es_module/__test__.jsonc +++ b/tests/specs/npm/es_module/__test__.jsonc @@ -14,11 +14,6 @@ "import chalk from 'npm:chalk@5'; console.log(chalk.green('chalk esm loads'));" ], "output": "main.out" - }, - "bundle": { - "args": "bundle --quiet main.js", - "output": "bundle.out", - "exitCode": 1 } } } diff --git a/tests/specs/npm/es_module/bundle.out b/tests/specs/npm/es_module/bundle.out deleted file mode 100644 index c749a236a6..0000000000 --- a/tests/specs/npm/es_module/bundle.out +++ /dev/null @@ -1 +0,0 @@ -error: npm specifiers have not yet been implemented for this subcommand (https://github.com/denoland/deno/issues/15960). Found: npm:/chalk@5.0.1 diff --git a/tests/specs/npm/esm_import_cjs_default/main.out b/tests/specs/npm/esm_import_cjs_default/main.out index ec7962e5a3..6528a68d7c 100644 --- a/tests/specs/npm/esm_import_cjs_default/main.out +++ b/tests/specs/npm/esm_import_cjs_default/main.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/esm-import-cjs-default -Download http://localhost:4260/@denotest/cjs-default-export +Download http://localhost:4260/@denotest%2fesm-import-cjs-default +Download http://localhost:4260/@denotest%2fcjs-default-export Download http://localhost:4260/@denotest/cjs-default-export/1.0.0.tgz Download http://localhost:4260/@denotest/esm-import-cjs-default/1.0.0.tgz [UNORDERED_END] diff --git a/tests/specs/npm/future_auto_install_no_package_json/__test__.jsonc b/tests/specs/npm/future_auto_install_no_package_json/__test__.jsonc index ea3cce88fa..495b49266d 100644 --- a/tests/specs/npm/future_auto_install_no_package_json/__test__.jsonc +++ b/tests/specs/npm/future_auto_install_no_package_json/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ // should auto-install because no package.json "args": "run --quiet main.ts", diff --git a/tests/specs/npm/future_node_modules_dir_setting/__test__.jsonc b/tests/specs/npm/future_node_modules_dir_setting/__test__.jsonc index b7c3b90d77..e9c9bd81dd 100644 --- a/tests/specs/npm/future_node_modules_dir_setting/__test__.jsonc +++ b/tests/specs/npm/future_node_modules_dir_setting/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ // byonm where this fails be @@ -10,11 +7,11 @@ "exitCode": 1 }, { // this should override byonm - "args": "run --node-modules-dir=false --quiet main.ts", + "args": "run --node-modules-dir=none --quiet main.ts", "output": "main.out" }, { // same with this - "args": "run --node-modules-dir --quiet main.ts", + "args": "run --node-modules-dir=auto --quiet main.ts", "output": "main.out" }] } diff --git a/tests/specs/npm/import_json/__test__.jsonc b/tests/specs/npm/import_json/__test__.jsonc new file mode 100644 index 0000000000..ee05ba69af --- /dev/null +++ b/tests/specs/npm/import_json/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet import_json/main.js", + "output": "import_json/main.out" +} diff --git a/tests/specs/npm/import_json/import_json/main.js b/tests/specs/npm/import_json/import_json/main.js new file mode 100644 index 0000000000..ac6cee9a83 --- /dev/null +++ b/tests/specs/npm/import_json/import_json/main.js @@ -0,0 +1,4 @@ +import json from "npm:@denotest/binary-package@1/package.json" with { + type: "json", +}; +console.log(json); diff --git a/tests/specs/npm/import_json/import_json/main.out b/tests/specs/npm/import_json/import_json/main.out new file mode 100644 index 0000000000..7db7ec4ea4 --- /dev/null +++ b/tests/specs/npm/import_json/import_json/main.out @@ -0,0 +1,10 @@ +{ + name: "@denotest/binary-package", + version: "1.0.0", + main: "index.js", + optionalDependencies: { + "@denotest/binary-package-linux": "1.0.0", + "@denotest/binary-package-mac": "1.0.0", + "@denotest/binary-package-windows": "1.0.0" + } +} diff --git a/tests/specs/npm/import_map/__test__.jsonc b/tests/specs/npm/import_map/__test__.jsonc new file mode 100644 index 0000000000..7c39e48e9d --- /dev/null +++ b/tests/specs/npm/import_map/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --allow-env --import-map import_map/import_map.json import_map/main.js", + "output": "import_map/main.out" +} diff --git a/tests/testdata/npm/import_map/import_map.json b/tests/specs/npm/import_map/import_map/import_map.json similarity index 100% rename from tests/testdata/npm/import_map/import_map.json rename to tests/specs/npm/import_map/import_map/import_map.json diff --git a/tests/testdata/npm/import_map/main.js b/tests/specs/npm/import_map/import_map/main.js similarity index 100% rename from tests/testdata/npm/import_map/main.js rename to tests/specs/npm/import_map/import_map/main.js diff --git a/tests/testdata/npm/import_map/main.out b/tests/specs/npm/import_map/import_map/main.out similarity index 81% rename from tests/testdata/npm/import_map/main.out rename to tests/specs/npm/import_map/import_map/main.out index 05f313d4e9..2698fb695c 100644 --- a/tests/testdata/npm/import_map/main.out +++ b/tests/specs/npm/import_map/import_map/main.out @@ -1,6 +1,6 @@ [UNORDERED_START] Download http://localhost:4260/chalk -Download http://localhost:4260/@denotest/dual-cjs-esm +Download http://localhost:4260/@denotest%2fdual-cjs-esm [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/dual-cjs-esm/1.0.0.tgz diff --git a/tests/specs/npm/imports_package_json/__test__.jsonc b/tests/specs/npm/imports_package_json/__test__.jsonc new file mode 100644 index 0000000000..35eabd4e15 --- /dev/null +++ b/tests/specs/npm/imports_package_json/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --no-lock --node-modules-dir=none imports_package_json/main.js", + "output": "imports_package_json/main.out" +} diff --git a/tests/testdata/npm/imports_package_json/import_not_defined.js b/tests/specs/npm/imports_package_json/imports_package_json/import_not_defined.js similarity index 100% rename from tests/testdata/npm/imports_package_json/import_not_defined.js rename to tests/specs/npm/imports_package_json/imports_package_json/import_not_defined.js diff --git a/tests/testdata/npm/imports_package_json/import_not_defined.out b/tests/specs/npm/imports_package_json/imports_package_json/import_not_defined.out similarity index 79% rename from tests/testdata/npm/imports_package_json/import_not_defined.out rename to tests/specs/npm/imports_package_json/imports_package_json/import_not_defined.out index 70d1145a37..abfa414030 100644 --- a/tests/testdata/npm/imports_package_json/import_not_defined.out +++ b/tests/specs/npm/imports_package_json/imports_package_json/import_not_defined.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/imports-package-json +Download http://localhost:4260/@denotest%2fimports-package-json Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#not-defined" is not defined in package [WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/testdata/npm/imports_package_json/main.js b/tests/specs/npm/imports_package_json/imports_package_json/main.js similarity index 100% rename from tests/testdata/npm/imports_package_json/main.js rename to tests/specs/npm/imports_package_json/imports_package_json/main.js diff --git a/tests/testdata/npm/imports_package_json/main.out b/tests/specs/npm/imports_package_json/imports_package_json/main.out similarity index 62% rename from tests/testdata/npm/imports_package_json/main.out rename to tests/specs/npm/imports_package_json/imports_package_json/main.out index 979e355765..70d787b251 100644 --- a/tests/testdata/npm/imports_package_json/main.out +++ b/tests/specs/npm/imports_package_json/imports_package_json/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/imports-package-json +Download http://localhost:4260/@denotest%2fimports-package-json Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz hi bye diff --git a/tests/testdata/npm/imports_package_json/package.json b/tests/specs/npm/imports_package_json/imports_package_json/package.json similarity index 100% rename from tests/testdata/npm/imports_package_json/package.json rename to tests/specs/npm/imports_package_json/imports_package_json/package.json diff --git a/tests/testdata/npm/imports_package_json/sub_path_import_not_defined.js b/tests/specs/npm/imports_package_json/imports_package_json/sub_path_import_not_defined.js similarity index 100% rename from tests/testdata/npm/imports_package_json/sub_path_import_not_defined.js rename to tests/specs/npm/imports_package_json/imports_package_json/sub_path_import_not_defined.js diff --git a/tests/testdata/npm/imports_package_json/sub_path_import_not_defined.out b/tests/specs/npm/imports_package_json/imports_package_json/sub_path_import_not_defined.out similarity index 80% rename from tests/testdata/npm/imports_package_json/sub_path_import_not_defined.out rename to tests/specs/npm/imports_package_json/imports_package_json/sub_path_import_not_defined.out index 7c803f2bf1..95524202ae 100644 --- a/tests/testdata/npm/imports_package_json/sub_path_import_not_defined.out +++ b/tests/specs/npm/imports_package_json/imports_package_json/sub_path_import_not_defined.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/imports-package-json +Download http://localhost:4260/@denotest%2fimports-package-json Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#hi" is not defined in package [WILDCARD]sub_path[WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/specs/npm/imports_package_json_import_not_defined/__test__.jsonc b/tests/specs/npm/imports_package_json_import_not_defined/__test__.jsonc new file mode 100644 index 0000000000..983ec31263 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --no-lock --node-modules-dir=none imports_package_json/import_not_defined.js", + "output": "imports_package_json/import_not_defined.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.js b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.js new file mode 100644 index 0000000000..dc4d2df165 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.js @@ -0,0 +1,3 @@ +import data from "@denotest/imports-package-json/import-not-defined"; + +console.log(data); diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.out b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.out new file mode 100644 index 0000000000..abfa414030 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/import_not_defined.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#not-defined" is not defined in package [WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.js b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.js new file mode 100644 index 0000000000..53090dd948 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.js @@ -0,0 +1,7 @@ +import data from "@denotest/imports-package-json"; + +console.log(data.hi); +console.log(data.bye); +console.log(typeof data.fs.readFile); +console.log(typeof data.path.join); +console.log(typeof data.fs2.writeFile); diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.out b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.out new file mode 100644 index 0000000000..70d787b251 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/main.out @@ -0,0 +1,7 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +hi +bye +function +function +function diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/package.json b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/package.json new file mode 100644 index 0000000000..cb6a08d1a5 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/package.json @@ -0,0 +1,6 @@ +{ + "name": "my-test", + "dependencies": { + "@denotest/imports-package-json": "1.0.0" + } +} diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.js b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.js new file mode 100644 index 0000000000..f1097aa064 --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.js @@ -0,0 +1,3 @@ +import data from "@denotest/imports-package-json/sub-path-import-not-defined"; + +console.log(data); diff --git a/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.out b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.out new file mode 100644 index 0000000000..95524202ae --- /dev/null +++ b/tests/specs/npm/imports_package_json_import_not_defined/imports_package_json/sub_path_import_not_defined.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#hi" is not defined in package [WILDCARD]sub_path[WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/__test__.jsonc b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/__test__.jsonc new file mode 100644 index 0000000000..cd9b260f48 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --no-lock --node-modules-dir=none imports_package_json/sub_path_import_not_defined.js", + "output": "imports_package_json/sub_path_import_not_defined.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.js b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.js new file mode 100644 index 0000000000..dc4d2df165 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.js @@ -0,0 +1,3 @@ +import data from "@denotest/imports-package-json/import-not-defined"; + +console.log(data); diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.out b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.out new file mode 100644 index 0000000000..abfa414030 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/import_not_defined.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#not-defined" is not defined in package [WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.js b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.js new file mode 100644 index 0000000000..53090dd948 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.js @@ -0,0 +1,7 @@ +import data from "@denotest/imports-package-json"; + +console.log(data.hi); +console.log(data.bye); +console.log(typeof data.fs.readFile); +console.log(typeof data.path.join); +console.log(typeof data.fs2.writeFile); diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.out b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.out new file mode 100644 index 0000000000..70d787b251 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/main.out @@ -0,0 +1,7 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +hi +bye +function +function +function diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/package.json b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/package.json new file mode 100644 index 0000000000..cb6a08d1a5 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/package.json @@ -0,0 +1,6 @@ +{ + "name": "my-test", + "dependencies": { + "@denotest/imports-package-json": "1.0.0" + } +} diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.js b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.js new file mode 100644 index 0000000000..f1097aa064 --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.js @@ -0,0 +1,3 @@ +import data from "@denotest/imports-package-json/sub-path-import-not-defined"; + +console.log(data); diff --git a/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.out b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.out new file mode 100644 index 0000000000..95524202ae --- /dev/null +++ b/tests/specs/npm/imports_package_json_sub_path_import_not_defined/imports_package_json/sub_path_import_not_defined.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fimports-package-json +Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz +error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#hi" is not defined in package [WILDCARD]sub_path[WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js' diff --git a/tests/specs/npm/info_chalk_display/__test__.jsonc b/tests/specs/npm/info_chalk_display/__test__.jsonc new file mode 100644 index 0000000000..54b5b74396 --- /dev/null +++ b/tests/specs/npm/info_chalk_display/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet cjs_with_deps/main.js", + "output": "cjs_with_deps/main_info.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_chalk_display/cjs_with_deps/main.js b/tests/specs/npm/info_chalk_display/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/info_chalk_display/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/info_chalk_display/cjs_with_deps/main.out b/tests/specs/npm/info_chalk_display/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/info_chalk_display/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info.out b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..8e37c88eb0 --- /dev/null +++ b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info_json.out b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..137b9f8ce5 --- /dev/null +++ b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_info_json.out @@ -0,0 +1,148 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ] + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [] + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ] + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ] + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [] + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ] + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [] + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ] + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [] + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [] + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ] + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [] + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ] + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [] + } + } +} diff --git a/tests/specs/npm/info_chalk_display/cjs_with_deps/main_node_modules.out b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/info_chalk_display/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/__test__.jsonc b/tests/specs/npm/info_chalk_display_node_modules_dir/__test__.jsonc new file mode 100644 index 0000000000..4358f64883 --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "info --quiet --node-modules-dir cjs_with_deps/main.js", + "output": "cjs_with_deps/main_info.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.js b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.out b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info.out b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..8e37c88eb0 --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info_json.out b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..137b9f8ce5 --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_info_json.out @@ -0,0 +1,148 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ] + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [] + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ] + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ] + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [] + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ] + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [] + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ] + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [] + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [] + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ] + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [] + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ] + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [] + } + } +} diff --git a/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_node_modules.out b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/info_chalk_display_node_modules_dir/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_json/__test__.jsonc b/tests/specs/npm/info_chalk_json/__test__.jsonc new file mode 100644 index 0000000000..c6e65db94b --- /dev/null +++ b/tests/specs/npm/info_chalk_json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet --json cjs_with_deps/main.js", + "output": "cjs_with_deps/main_info_json.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_chalk_json/cjs_with_deps/main.js b/tests/specs/npm/info_chalk_json/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/info_chalk_json/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/info_chalk_json/cjs_with_deps/main.out b/tests/specs/npm/info_chalk_json/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/info_chalk_json/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info.out b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..8e37c88eb0 --- /dev/null +++ b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info_json.out b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..2f7dde2d98 --- /dev/null +++ b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_info_json.out @@ -0,0 +1,172 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + }, + { + "kind": "npm", + "specifier": "npm:/chai@4.3.6", + "npmPackage": "chai@4.3.6" + }, + { + "kind": "npm", + "specifier": "npm:/chalk@4.1.2", + "npmPackage": "chalk@4.1.2" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ], + "registryUrl": "http://localhost:4260/" + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ], + "registryUrl": "http://localhost:4260/" + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ], + "registryUrl": "http://localhost:4260/" + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ], + "registryUrl": "http://localhost:4260/" + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + } + } +} diff --git a/tests/specs/npm/info_chalk_json/cjs_with_deps/main_node_modules.out b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/info_chalk_json/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/__test__.jsonc b/tests/specs/npm/info_chalk_json_node_modules_dir/__test__.jsonc new file mode 100644 index 0000000000..29c5e8bdff --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "info --quiet --node-modules-dir --json cjs_with_deps/main.js", + "output": "cjs_with_deps/main_info_json.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.js b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.out b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info.out b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..8e37c88eb0 --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info_json.out b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..2f7dde2d98 --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_info_json.out @@ -0,0 +1,172 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + }, + { + "kind": "npm", + "specifier": "npm:/chai@4.3.6", + "npmPackage": "chai@4.3.6" + }, + { + "kind": "npm", + "specifier": "npm:/chalk@4.1.2", + "npmPackage": "chalk@4.1.2" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ], + "registryUrl": "http://localhost:4260/" + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ], + "registryUrl": "http://localhost:4260/" + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ], + "registryUrl": "http://localhost:4260/" + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ], + "registryUrl": "http://localhost:4260/" + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + } + } +} diff --git a/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_node_modules.out b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/info_chalk_json_node_modules_dir/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/info_cli_chalk_display/__test__.jsonc b/tests/specs/npm/info_cli_chalk_display/__test__.jsonc new file mode 100644 index 0000000000..902bb2dae6 --- /dev/null +++ b/tests/specs/npm/info_cli_chalk_display/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet npm:chalk@4", + "output": "info/chalk.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/info/chalk.out b/tests/specs/npm/info_cli_chalk_display/info/chalk.out similarity index 100% rename from tests/testdata/npm/info/chalk.out rename to tests/specs/npm/info_cli_chalk_display/info/chalk.out diff --git a/tests/testdata/npm/info/chalk_json.out b/tests/specs/npm/info_cli_chalk_display/info/chalk_json.out similarity index 98% rename from tests/testdata/npm/info/chalk_json.out rename to tests/specs/npm/info_cli_chalk_display/info/chalk_json.out index bffed4ad44..21fc7edf1a 100644 --- a/tests/testdata/npm/info/chalk_json.out +++ b/tests/specs/npm/info_cli_chalk_display/info/chalk_json.out @@ -1,4 +1,5 @@ { + "version": 1, "roots": [ "npm:chalk@4" ], diff --git a/tests/specs/npm/info_cli_chalk_json/__test__.jsonc b/tests/specs/npm/info_cli_chalk_json/__test__.jsonc new file mode 100644 index 0000000000..ee34abae7f --- /dev/null +++ b/tests/specs/npm/info_cli_chalk_json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet --json npm:chalk@4", + "output": "info/chalk_json.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_cli_chalk_json/info/chalk.out b/tests/specs/npm/info_cli_chalk_json/info/chalk.out new file mode 100644 index 0000000000..63fa20da54 --- /dev/null +++ b/tests/specs/npm/info_cli_chalk_json/info/chalk.out @@ -0,0 +1,9 @@ +dependencies: 5 unique +size: [WILDCARD] + +npm:/chalk@4.1.2 ([WILDCARD]) +├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ └── npm:/color-name@1.1.4 ([WILDCARD]) +└─┬ npm:/supports-color@7.2.0 ([WILDCARD]) + └── npm:/has-flag@4.0.0 ([WILDCARD]) diff --git a/tests/specs/npm/info_cli_chalk_json/info/chalk_json.out b/tests/specs/npm/info_cli_chalk_json/info/chalk_json.out new file mode 100644 index 0000000000..fd2aa9ab0d --- /dev/null +++ b/tests/specs/npm/info_cli_chalk_json/info/chalk_json.out @@ -0,0 +1,63 @@ +{ + "version": 1, + "roots": [ + "npm:chalk@4" + ], + "modules": [ + { + "kind": "npm", + "specifier": "npm:/chalk@4.1.2", + "npmPackage": "chalk@4.1.2" + } + ], + "redirects": { + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ], + "registryUrl": "http://localhost:4260/" + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ], + "registryUrl": "http://localhost:4260/" + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ], + "registryUrl": "http://localhost:4260/" + } + } +} diff --git a/tests/specs/npm/info_peer_deps/__test__.jsonc b/tests/specs/npm/info_peer_deps/__test__.jsonc new file mode 100644 index 0000000000..00dfbc98b7 --- /dev/null +++ b/tests/specs/npm/info_peer_deps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet peer_deps_with_copied_folders/main.ts", + "output": "peer_deps_with_copied_folders/main_info.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.out b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.out new file mode 100644 index 0000000000..b7a5835577 --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.out @@ -0,0 +1,14 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-child/2.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-grandchild/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-peer/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-peer/2.0.0.tgz +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.ts b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.ts new file mode 100644 index 0000000000..a8ea8104a9 --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main.ts @@ -0,0 +1,5 @@ +import version1 from "npm:@denotest/peer-dep-test-child@1"; +import version2 from "npm:@denotest/peer-dep-test-child@2"; + +console.error(version1); +console.error(version2); diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info.out b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info.out new file mode 100644 index 0000000000..e8b92399df --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info.out @@ -0,0 +1,14 @@ +local: [WILDCARD]main.ts +type: TypeScript +dependencies: 6 unique +size: [WILDCARD] + +file:///[WILDCARD]/peer_deps_with_copied_folders/main.ts (171B) +├─┬ npm:/@denotest/peer-dep-test-child@1.0.0 ([WILDCARD]) +│ ├─┬ npm:/@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0 ([WILDCARD]) +│ │ └── npm:/@denotest/peer-dep-test-peer@1.0.0 ([WILDCARD]) +│ └── npm:/@denotest/peer-dep-test-peer@1.0.0 ([WILDCARD]) +└─┬ npm:/@denotest/peer-dep-test-child@2.0.0 ([WILDCARD]) + ├─┬ npm:/@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0 ([WILDCARD]) + │ └── npm:/@denotest/peer-dep-test-peer@2.0.0 ([WILDCARD]) + └── npm:/@denotest/peer-dep-test-peer@2.0.0 ([WILDCARD]) diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info_json.out b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info_json.out new file mode 100644 index 0000000000..46cc35c650 --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_info_json.out @@ -0,0 +1,97 @@ +{ + "version": 1, + "roots": [ + "[WILDCARD]/peer_deps_with_copied_folders/main.ts" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:@denotest/peer-dep-test-child@1", + "code": { + "specifier": "npm:@denotest/peer-dep-test-child@1", + "span": { + "start": { + "line": 0, + "character": 21 + }, + "end": { + "line": 0, + "character": 58 + } + } + }, + "npmPackage": "@denotest/peer-dep-test-child@1.0.0_@denotest+peer-dep-test-peer@1.0.0" + }, + { + "specifier": "npm:@denotest/peer-dep-test-child@2", + "code": { + "specifier": "npm:@denotest/peer-dep-test-child@2", + "span": { + "start": { + "line": 1, + "character": 21 + }, + "end": { + "line": 1, + "character": 58 + } + } + }, + "npmPackage": "@denotest/peer-dep-test-child@2.0.0_@denotest+peer-dep-test-peer@2.0.0" + } + ], + "local": "[WILDCARD]main.ts", + "size": 171, + "mediaType": "TypeScript", + "specifier": "file://[WILDCARD]/main.ts" + } + ], + "redirects": { + "npm:@denotest/peer-dep-test-child@1": "npm:/@denotest/peer-dep-test-child@1.0.0", + "npm:@denotest/peer-dep-test-child@2": "npm:/@denotest/peer-dep-test-child@2.0.0" + }, + "npmPackages": { + "@denotest/peer-dep-test-child@1.0.0_@denotest+peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-child", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0", + "@denotest/peer-dep-test-peer@1.0.0" + ] + }, + "@denotest/peer-dep-test-child@2.0.0_@denotest+peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-child", + "version": "2.0.0", + "dependencies": [ + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0", + "@denotest/peer-dep-test-peer@2.0.0" + ] + }, + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-grandchild", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-peer@1.0.0" + ] + }, + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-grandchild", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-peer@2.0.0" + ] + }, + "@denotest/peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-peer", + "version": "1.0.0", + "dependencies": [] + }, + "@denotest/peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-peer", + "version": "2.0.0", + "dependencies": [] + } + } +} diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules.out b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules.out new file mode 100644 index 0000000000..02b5cbafd6 --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules.out @@ -0,0 +1,9 @@ +[UNORDERED_START] +Initialize @denotest/peer-dep-test-child@1.0.0 +Initialize @denotest/peer-dep-test-child@2.0.0 +Initialize @denotest/peer-dep-test-grandchild@1.0.0 +Initialize @denotest/peer-dep-test-peer@1.0.0 +Initialize @denotest/peer-dep-test-peer@2.0.0 +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules_reload.out b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules_reload.out new file mode 100644 index 0000000000..18d7f7865b --- /dev/null +++ b/tests/specs/npm/info_peer_deps/peer_deps_with_copied_folders/main_node_modules_reload.out @@ -0,0 +1,19 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz +Initialize @denotest/peer-dep-test-child@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-child/2.0.0.tgz +Initialize @denotest/peer-dep-test-child@2.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-grandchild/1.0.0.tgz +Initialize @denotest/peer-dep-test-grandchild@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-peer/1.0.0.tgz +Initialize @denotest/peer-dep-test-peer@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-peer/2.0.0.tgz +Initialize @denotest/peer-dep-test-peer@2.0.0 +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/info_peer_deps_json/__test__.jsonc b/tests/specs/npm/info_peer_deps_json/__test__.jsonc new file mode 100644 index 0000000000..5dd08c325f --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "info --quiet --json peer_deps_with_copied_folders/main.ts", + "output": "peer_deps_with_copied_folders/main_info_json.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.out b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.out new file mode 100644 index 0000000000..b7a5835577 --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.out @@ -0,0 +1,14 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-child/2.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-grandchild/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-peer/1.0.0.tgz +Download http://localhost:4260/@denotest/peer-dep-test-peer/2.0.0.tgz +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.ts b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.ts new file mode 100644 index 0000000000..a8ea8104a9 --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main.ts @@ -0,0 +1,5 @@ +import version1 from "npm:@denotest/peer-dep-test-child@1"; +import version2 from "npm:@denotest/peer-dep-test-child@2"; + +console.error(version1); +console.error(version2); diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info.out b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info.out new file mode 100644 index 0000000000..e8b92399df --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info.out @@ -0,0 +1,14 @@ +local: [WILDCARD]main.ts +type: TypeScript +dependencies: 6 unique +size: [WILDCARD] + +file:///[WILDCARD]/peer_deps_with_copied_folders/main.ts (171B) +├─┬ npm:/@denotest/peer-dep-test-child@1.0.0 ([WILDCARD]) +│ ├─┬ npm:/@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0 ([WILDCARD]) +│ │ └── npm:/@denotest/peer-dep-test-peer@1.0.0 ([WILDCARD]) +│ └── npm:/@denotest/peer-dep-test-peer@1.0.0 ([WILDCARD]) +└─┬ npm:/@denotest/peer-dep-test-child@2.0.0 ([WILDCARD]) + ├─┬ npm:/@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0 ([WILDCARD]) + │ └── npm:/@denotest/peer-dep-test-peer@2.0.0 ([WILDCARD]) + └── npm:/@denotest/peer-dep-test-peer@2.0.0 ([WILDCARD]) diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info_json.out b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info_json.out new file mode 100644 index 0000000000..2ee6268f55 --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_info_json.out @@ -0,0 +1,113 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.ts" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:@denotest/peer-dep-test-child@1", + "code": { + "specifier": "npm:@denotest/peer-dep-test-child@1", + "span": { + "start": { + "line": 0, + "character": 21 + }, + "end": { + "line": 0, + "character": 58 + } + } + }, + "npmPackage": "@denotest/peer-dep-test-child@1.0.0_@denotest+peer-dep-test-peer@1.0.0" + }, + { + "specifier": "npm:@denotest/peer-dep-test-child@2", + "code": { + "specifier": "npm:@denotest/peer-dep-test-child@2", + "span": { + "start": { + "line": 1, + "character": 21 + }, + "end": { + "line": 1, + "character": 58 + } + } + }, + "npmPackage": "@denotest/peer-dep-test-child@2.0.0_@denotest+peer-dep-test-peer@2.0.0" + } + ], + "local": "[WILDCARD]main.ts", + "size": 171, + "mediaType": "TypeScript", + "specifier": "file://[WILDCARD]/main.ts" + }, + { + "kind": "npm", + "specifier": "npm:/@denotest/peer-dep-test-child@1.0.0", + "npmPackage": "@denotest/peer-dep-test-child@1.0.0_@denotest+peer-dep-test-peer@1.0.0" + }, + { + "kind": "npm", + "specifier": "npm:/@denotest/peer-dep-test-child@2.0.0", + "npmPackage": "@denotest/peer-dep-test-child@2.0.0_@denotest+peer-dep-test-peer@2.0.0" + } + ], + "redirects": { + "npm:@denotest/peer-dep-test-child@1": "npm:/@denotest/peer-dep-test-child@1.0.0", + "npm:@denotest/peer-dep-test-child@2": "npm:/@denotest/peer-dep-test-child@2.0.0" + }, + "npmPackages": { + "@denotest/peer-dep-test-child@1.0.0_@denotest+peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-child", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0", + "@denotest/peer-dep-test-peer@1.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "@denotest/peer-dep-test-child@2.0.0_@denotest+peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-child", + "version": "2.0.0", + "dependencies": [ + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0", + "@denotest/peer-dep-test-peer@2.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-grandchild", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-peer@1.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "@denotest/peer-dep-test-grandchild@1.0.0_@denotest+peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-grandchild", + "version": "1.0.0", + "dependencies": [ + "@denotest/peer-dep-test-peer@2.0.0" + ], + "registryUrl": "http://localhost:4260/" + }, + "@denotest/peer-dep-test-peer@1.0.0": { + "name": "@denotest/peer-dep-test-peer", + "version": "1.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + }, + "@denotest/peer-dep-test-peer@2.0.0": { + "name": "@denotest/peer-dep-test-peer", + "version": "2.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4260/" + } + } +} diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules.out b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules.out new file mode 100644 index 0000000000..02b5cbafd6 --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules.out @@ -0,0 +1,9 @@ +[UNORDERED_START] +Initialize @denotest/peer-dep-test-child@1.0.0 +Initialize @denotest/peer-dep-test-child@2.0.0 +Initialize @denotest/peer-dep-test-grandchild@1.0.0 +Initialize @denotest/peer-dep-test-peer@1.0.0 +Initialize @denotest/peer-dep-test-peer@2.0.0 +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules_reload.out b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules_reload.out new file mode 100644 index 0000000000..18d7f7865b --- /dev/null +++ b/tests/specs/npm/info_peer_deps_json/peer_deps_with_copied_folders/main_node_modules_reload.out @@ -0,0 +1,19 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz +Initialize @denotest/peer-dep-test-child@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-child/2.0.0.tgz +Initialize @denotest/peer-dep-test-child@2.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-grandchild/1.0.0.tgz +Initialize @denotest/peer-dep-test-grandchild@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-peer/1.0.0.tgz +Initialize @denotest/peer-dep-test-peer@1.0.0 +Download http://localhost:4260/@denotest/peer-dep-test-peer/2.0.0.tgz +Initialize @denotest/peer-dep-test-peer@2.0.0 +[UNORDERED_END] +1 +2 diff --git a/tests/specs/npm/invalid_package_name/__test__.jsonc b/tests/specs/npm/invalid_package_name/__test__.jsonc new file mode 100644 index 0000000000..34db0174e5 --- /dev/null +++ b/tests/specs/npm/invalid_package_name/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A main.js", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/invalid_package_name/main.js b/tests/specs/npm/invalid_package_name/main.js similarity index 100% rename from tests/testdata/npm/invalid_package_name/main.js rename to tests/specs/npm/invalid_package_name/main.js diff --git a/tests/specs/npm/invalid_package_name/main.out b/tests/specs/npm/invalid_package_name/main.out new file mode 100644 index 0000000000..09c989dea0 --- /dev/null +++ b/tests/specs/npm/invalid_package_name/main.out @@ -0,0 +1,3 @@ +error: Invalid package specifier 'npm:@foo' + 0: Did not contain a valid package name + at [WILDCARD]/invalid_package_name/main.js:1:22 diff --git a/tests/specs/npm/lifecycle_scripts/__test__.jsonc b/tests/specs/npm/lifecycle_scripts/__test__.jsonc index 302b40d1e3..589c131dda 100644 --- a/tests/specs/npm/lifecycle_scripts/__test__.jsonc +++ b/tests/specs/npm/lifecycle_scripts/__test__.jsonc @@ -1,11 +1,11 @@ { + "tempDir": true, "tests": { "node_gyp": { - "tempDir": true, "steps": [ { "args": "cache --allow-scripts=npm:@denotest/node-addon main.js", - "output": "[WILDCARD]gyp info ok \n" + "output": "[WILDCARD]Initialize @denotest/node-addon@1.0.0: running 'install' script\n" }, { "args": "run -A main.js", @@ -14,7 +14,6 @@ ] }, "run_without_scripts": { - "tempDir": true, "steps": [ { "args": "run -A main.js", @@ -24,11 +23,9 @@ ] }, "implicit_node_gyp": { - "tempDir": true, "steps": [ { "envs": { - // I don't think this will work on windows "PATH": "" }, "args": "cache --allow-scripts implicit_node_gyp.js", @@ -38,11 +35,10 @@ ] }, "lifecycle_scripts": { - "tempDir": true, "steps": [ { // without running scripts (should warn) - "args": "cache all_lifecycles.js", + "args": "run all_lifecycles.js", "output": "all_lifecycles_not_run.out" }, { @@ -55,29 +51,75 @@ } ] }, - "only_warns_first": { - "tempDir": true, + "deno_run_lifecycle_scripts": { "steps": [ { // without running scripts (should warn) "args": "run all_lifecycles.js", - "output": "only_warns_first1.out", - "exitCode": 1 + "output": "all_lifecycles_not_run.out" + }, + { + // now run scripts + "args": "run --allow-scripts all_lifecycles.js", + // this test package covers running preinstall, install, and postinstall scripts + // it also exercises running bin packages (esbuild in this case), using `node` in a script + // (with and without node-only CLI flags), and using `npx` in a script + "output": "all_lifecycles_deno_run.out" + } + ] + }, + "global_lifecycle_scripts": { + "steps": [ + { + "args": ["eval", "Deno.removeSync('deno.json')"], + "output": "" + }, + { + // without running scripts (should warn) + "args": "install -e all_lifecycles.js", + "output": "all_lifecycles_not_run_global.out" + }, + { + // should not warn + "args": "run all_lifecycles_global.js", + "output": "" + }, + { + // should warn still + "args": "install -e all_lifecycles.js", + "output": "all_lifecycles_not_run_global_cached.out" + } + ] + }, + "only_warns_first_run": { + "steps": [ + { + // without running scripts (should warn) + "args": "run all_lifecycles.js", + "output": "only_warns_first1.out" }, { // without running scripts (does not warn) "args": "run all_lifecycles.js", - "output": "only_warns_first2.out", - "exitCode": 1 + "output": "only_warns_first2.out" + }, + { + // should warn because this is an explicit install + "args": "install -e all_lifecycles.js", + "output": "warns_again_on_install.out" } ] }, "future_install_lifecycle_scripts": { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ + { + "args": [ + "eval", + "Deno.removeSync('./deno.json')" + ], + "output": "[WILDCARD]" + }, { "args": [ "eval", @@ -92,7 +134,6 @@ ] }, "lifecycle_scripts_conflicting_bin": { - "tempDir": true, "steps": [ { // we import @denotest/says-hello-on-install, which executes `say-hello` from `@denotest/say-hello` in its @@ -102,11 +143,17 @@ // we run the install script, we should use the correct binary (relative to the package) "args": "cache --allow-scripts conflicting_bin.js", "output": "conflicting_bin.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('./say-hello-output.txt'))" + ], + "output": "conflicting_bin2.out" } ] }, "fsevents_default_install_script": { - "tempDir": true, "steps": [ { "if": "mac", @@ -121,27 +168,25 @@ ] }, "lifecycle_scripts_no_deno_json": { - "tempDir": true, "steps": [ { "args": ["eval", "Deno.removeSync('deno.json')"], "output": "" }, { - "args": "cache --allow-scripts --node-modules-dir=true no_deno_json.js", + "args": "cache --allow-scripts --node-modules-dir=auto no_deno_json.js", "output": "no_deno_json.out" } ] }, "lifecycle_scripts_no_deno_json_conflicting_bin": { - "tempDir": true, "steps": [ { "args": ["eval", "Deno.removeSync('deno.json')"], "output": "" }, { - "args": "cache --allow-scripts --node-modules-dir=true conflicting_bin.js", + "args": "cache --allow-scripts --node-modules-dir=auto conflicting_bin.js", "output": "conflicting_bin.out" } ] diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles.out b/tests/specs/npm/lifecycle_scripts/all_lifecycles.out index 956c006ddc..bdbb2b08ea 100644 --- a/tests/specs/npm/lifecycle_scripts/all_lifecycles.out +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles.out @@ -1,14 +1,3 @@ -preinstall -deno preinstall.js -node preinstall.js -install -hello from install script -postinstall[WILDCARD] - _____________ -< postinstall > - ------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'preinstall' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'install' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'postinstall' script diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles_deno_run.out b/tests/specs/npm/lifecycle_scripts/all_lifecycles_deno_run.out new file mode 100644 index 0000000000..5f06f6214c --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles_deno_run.out @@ -0,0 +1,4 @@ +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'preinstall' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'install' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'postinstall' script +value is 42 diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles_global.js b/tests/specs/npm/lifecycle_scripts/all_lifecycles_global.js new file mode 100644 index 0000000000..eccf11a6db --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles_global.js @@ -0,0 +1,3 @@ +try { + const _ = await import("npm:@denotest/node-lifecycle-scripts"); +} catch (_) {} diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run.out b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run.out index 0792674145..645556b26d 100644 --- a/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run.out +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run.out @@ -1,12 +1,15 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/node-lifecycle-scripts -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fnode-lifecycle-scripts +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/node-lifecycle-scripts/1.0.0.tgz Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/node-lifecycle-scripts@1.0.0 Initialize @denotest/bin@1.0.0 [UNORDERED_END] -warning: Packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed. - This may cause the packages to not work correctly. To run them, use the `--allow-scripts` flag with `deno cache` - (e.g. `deno cache --allow-scripts=pkg1,pkg2 `): - npm:@denotest/node-lifecycle-scripts@1.0.0 +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`: + deno install --allow-scripts=npm:@denotest/node-lifecycle-scripts@1.0.0 +value is 42 diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global.out b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global.out new file mode 100644 index 0000000000..1b06bccb8a --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global.out @@ -0,0 +1,13 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fnode-lifecycle-scripts +Download http://localhost:4260/@denotest%2fbin +Download http://localhost:4260/@denotest/node-lifecycle-scripts/1.0.0.tgz +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +[UNORDERED_END] +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┠─ Lifecycle scripts are only supported when using a `node_modules` directory. +┠─ Enable it in your deno config file: +┖─ "nodeModulesDir": "auto" diff --git a/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global_cached.out b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global_cached.out new file mode 100644 index 0000000000..789c9346ab --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/all_lifecycles_not_run_global_cached.out @@ -0,0 +1,7 @@ +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┠─ Lifecycle scripts are only supported when using a `node_modules` directory. +┠─ Enable it in your deno config file: +┖─ "nodeModulesDir": "auto" diff --git a/tests/specs/npm/lifecycle_scripts/conflicting_bin.out b/tests/specs/npm/lifecycle_scripts/conflicting_bin.out index c70aafdd53..33282ee81c 100644 --- a/tests/specs/npm/lifecycle_scripts/conflicting_bin.out +++ b/tests/specs/npm/lifecycle_scripts/conflicting_bin.out @@ -1,13 +1,12 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/better-say-hello -Download http://localhost:4260/@denotest/say-hello-on-install -Download http://localhost:4260/@denotest/say-hello +Download http://localhost:4260/@denotest%2fbetter-say-hello +Download http://localhost:4260/@denotest%2fsay-hello-on-install +Download http://localhost:4260/@denotest%2fsay-hello Download http://localhost:4260/@denotest/better-say-hello/1.0.0.tgz Download http://localhost:4260/@denotest/say-hello-on-install/1.0.0.tgz Download http://localhost:4260/@denotest/say-hello/1.0.0.tgz Initialize @denotest/better-say-hello@1.0.0 Initialize @denotest/say-hello-on-install@1.0.0 Initialize @denotest/say-hello@1.0.0 +Initialize @denotest/say-hello-on-install@1.0.0: running 'install' script [UNORDERED_END] -install script -@denotest/say-hello says hello! diff --git a/tests/specs/npm/lifecycle_scripts/conflicting_bin2.out b/tests/specs/npm/lifecycle_scripts/conflicting_bin2.out new file mode 100644 index 0000000000..b4640b02c5 --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/conflicting_bin2.out @@ -0,0 +1 @@ +@denotest/say-hello says hello! diff --git a/tests/specs/npm/lifecycle_scripts/deno.json b/tests/specs/npm/lifecycle_scripts/deno.json index 176354f98f..fbd70ec480 100644 --- a/tests/specs/npm/lifecycle_scripts/deno.json +++ b/tests/specs/npm/lifecycle_scripts/deno.json @@ -1,3 +1,3 @@ { - "nodeModulesDir": true + "nodeModulesDir": "auto" } diff --git a/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles.out b/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles.out index f62079d3fe..bdbb2b08ea 100644 --- a/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles.out +++ b/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles.out @@ -1,15 +1,3 @@ -preinstall -deno preinstall.js -node preinstall.js -install -hello from install script -postinstall -[WILDCARD] - _____________ -< postinstall > - ------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'preinstall' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'install' script +Initialize @denotest/node-lifecycle-scripts@1.0.0: running 'postinstall' script diff --git a/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles_not_run.out b/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles_not_run.out index 7d432ead90..d72f3c8b2d 100644 --- a/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles_not_run.out +++ b/tests/specs/npm/lifecycle_scripts/future_install_all_lifecycles_not_run.out @@ -1,12 +1,14 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/node-lifecycle-scripts -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fnode-lifecycle-scripts +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/node-lifecycle-scripts/1.0.0.tgz Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/node-lifecycle-scripts@1.0.0 Initialize @denotest/bin@1.0.0 [UNORDERED_END] -warning: Packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed. - This may cause the packages to not work correctly. To run them, use the `--allow-scripts` flag with `deno cache` or `deno install` - (e.g. `deno cache --allow-scripts=pkg1,pkg2 ` or `deno install --allow-scripts=pkg1,pkg2`): - npm:@denotest/node-lifecycle-scripts@1.0.0 +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`: + deno install --allow-scripts=npm:@denotest/node-lifecycle-scripts@1.0.0 diff --git a/tests/specs/npm/lifecycle_scripts/no_deno_json.out b/tests/specs/npm/lifecycle_scripts/no_deno_json.out index 38a4614494..1966396a31 100644 --- a/tests/specs/npm/lifecycle_scripts/no_deno_json.out +++ b/tests/specs/npm/lifecycle_scripts/no_deno_json.out @@ -1,11 +1,10 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/lifecycle-scripts-cjs -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2flifecycle-scripts-cjs +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/lifecycle-scripts-cjs/1.0.0.tgz Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/lifecycle-scripts-cjs@1.0.0 Initialize @denotest/bin@1.0.0 +Initialize @denotest/lifecycle-scripts-cjs@1.0.0: running 'preinstall' script +Initialize @denotest/lifecycle-scripts-cjs@1.0.0: running 'install' script [UNORDERED_END] -preinstall -install -hello from install script diff --git a/tests/specs/npm/lifecycle_scripts/node_gyp_not_found.out b/tests/specs/npm/lifecycle_scripts/node_gyp_not_found.out index 65ea53d586..339384f732 100644 --- a/tests/specs/npm/lifecycle_scripts/node_gyp_not_found.out +++ b/tests/specs/npm/lifecycle_scripts/node_gyp_not_found.out @@ -1,8 +1,12 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/node-addon-implicit-node-gyp +Download http://localhost:4260/@denotest%2fnode-addon-implicit-node-gyp Download http://localhost:4260/@denotest/node-addon-implicit-node-gyp/1.0.0.tgz Initialize @denotest/node-addon-implicit-node-gyp@1.0.0 +Initialize @denotest/node-addon-implicit-node-gyp@1.0.0: running 'install' script [UNORDERED_END] -warning: node-gyp was used in a script, but was not listed as a dependency. Either add it as a dependency or install it globally (e.g. `npm install -g node-gyp`) -[WILDCARD] +Warning node-gyp was used in a script, but was not listed as a dependency. Either add it as a dependency or install it globally (e.g. `npm install -g node-gyp`) error: script 'install' in '@denotest/node-addon-implicit-node-gyp@1.0.0' failed with exit code 1 +stderr: +Error launching 'node-gyp': [WILDCARD] + +error: failed to run scripts for packages: @denotest/node-addon-implicit-node-gyp@1.0.0 diff --git a/tests/specs/npm/lifecycle_scripts/node_gyp_not_run.out b/tests/specs/npm/lifecycle_scripts/node_gyp_not_run.out index c718e7c862..da5bb4f7b5 100644 --- a/tests/specs/npm/lifecycle_scripts/node_gyp_not_run.out +++ b/tests/specs/npm/lifecycle_scripts/node_gyp_not_run.out @@ -1,9 +1,11 @@ -Download http://localhost:4260/@denotest/node-addon +Download http://localhost:4260/@denotest%2fnode-addon Download http://localhost:4260/node-gyp [WILDCARD] -warning: Packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed. - This may cause the packages to not work correctly. To run them, use the `--allow-scripts` flag with `deno cache` - (e.g. `deno cache --allow-scripts=pkg1,pkg2 `): - npm:@denotest/node-addon@1.0.0 +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-addon@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`: + deno install --allow-scripts=npm:@denotest/node-addon@1.0.0 error: Uncaught (in promise) Error: Cannot find module './build/Release/node_addon' [WILDCARD] diff --git a/tests/specs/npm/lifecycle_scripts/only_warns_first1.out b/tests/specs/npm/lifecycle_scripts/only_warns_first1.out index 6ebf960289..645556b26d 100644 --- a/tests/specs/npm/lifecycle_scripts/only_warns_first1.out +++ b/tests/specs/npm/lifecycle_scripts/only_warns_first1.out @@ -1,14 +1,15 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/node-lifecycle-scripts -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fnode-lifecycle-scripts +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/node-lifecycle-scripts/1.0.0.tgz Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/node-lifecycle-scripts@1.0.0 Initialize @denotest/bin@1.0.0 [UNORDERED_END] -warning: Packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed. - This may cause the packages to not work correctly. To run them, use the `--allow-scripts` flag with `deno cache` - (e.g. `deno cache --allow-scripts=pkg1,pkg2 `): - npm:@denotest/node-lifecycle-scripts@1.0.0 -error: Uncaught SyntaxError: The requested module 'npm:@denotest/node-lifecycle-scripts' does not provide an export named 'value' -[WILDCARD] +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`: + deno install --allow-scripts=npm:@denotest/node-lifecycle-scripts@1.0.0 +value is 42 diff --git a/tests/specs/npm/lifecycle_scripts/only_warns_first2.out b/tests/specs/npm/lifecycle_scripts/only_warns_first2.out index f6a02c7279..9e78061598 100644 --- a/tests/specs/npm/lifecycle_scripts/only_warns_first2.out +++ b/tests/specs/npm/lifecycle_scripts/only_warns_first2.out @@ -1,3 +1 @@ -[# note no warning] -error: Uncaught SyntaxError: The requested module 'npm:@denotest/node-lifecycle-scripts' does not provide an export named 'value' -[WILDCARD] +value is 42 diff --git a/tests/specs/npm/lifecycle_scripts/warns_again_on_install.out b/tests/specs/npm/lifecycle_scripts/warns_again_on_install.out new file mode 100644 index 0000000000..fe7eedc564 --- /dev/null +++ b/tests/specs/npm/lifecycle_scripts/warns_again_on_install.out @@ -0,0 +1,6 @@ +Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed: +┠─ npm:@denotest/node-lifecycle-scripts@1.0.0 +┃ +┠─ This may cause the packages to not work correctly. +┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`: + deno install --allow-scripts=npm:@denotest/node-lifecycle-scripts@1.0.0 diff --git a/tests/specs/npm/local_dir_no_duplicate_resolution/deno.json b/tests/specs/npm/local_dir_no_duplicate_resolution/deno.json index ae2f9c1ae8..fe867fcc83 100644 --- a/tests/specs/npm/local_dir_no_duplicate_resolution/deno.json +++ b/tests/specs/npm/local_dir_no_duplicate_resolution/deno.json @@ -1,5 +1,5 @@ { - "nodeModulesDir": true, + "nodeModulesDir": "auto", "imports": { "preact": "npm:preact", "preact-render-to-string": "npm:preact-render-to-string" diff --git a/tests/specs/npm/local_dir_resolves_symlinks/__test__.jsonc b/tests/specs/npm/local_dir_resolves_symlinks/__test__.jsonc new file mode 100644 index 0000000000..a846fdcb4e --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks/__test__.jsonc @@ -0,0 +1,14 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { + "args": "run -A index.js", + "output": "index.out", + "exitCode": 0 + } + ] +} diff --git a/tests/testdata/npm/local_dir_resolves_symlinks/index.js b/tests/specs/npm/local_dir_resolves_symlinks/index.js similarity index 100% rename from tests/testdata/npm/local_dir_resolves_symlinks/index.js rename to tests/specs/npm/local_dir_resolves_symlinks/index.js diff --git a/tests/specs/npm/local_dir_resolves_symlinks/index.out b/tests/specs/npm/local_dir_resolves_symlinks/index.out new file mode 100644 index 0000000000..7550ee1323 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks/index.out @@ -0,0 +1 @@ +true it works diff --git a/tests/specs/npm/local_dir_resolves_symlinks/install.out b/tests/specs/npm/local_dir_resolves_symlinks/install.out new file mode 100644 index 0000000000..0c15b2a0e9 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks/install.out @@ -0,0 +1,23 @@ +[UNORDERED_START] +Download http://localhost:4260/define-properties +Download http://localhost:4260/has-property-descriptors +Download http://localhost:4260/object-keys +Download http://localhost:4260/get-intrinsic +Download http://localhost:4260/function-bind +Download http://localhost:4260/has +Download http://localhost:4260/has-symbols +Download http://localhost:4260/define-properties/define-properties-1.2.0.tgz +Download http://localhost:4260/has-property-descriptors/has-property-descriptors-1.0.0.tgz +Download http://localhost:4260/object-keys/object-keys-1.1.1.tgz +Download http://localhost:4260/get-intrinsic/get-intrinsic-1.2.0.tgz +Download http://localhost:4260/has-symbols/has-symbols-1.0.3.tgz +Download http://localhost:4260/has/has-1.0.3.tgz +Download http://localhost:4260/function-bind/function-bind-1.1.1.tgz +Initialize has@1.0.3 +Initialize define-properties@1.2.0 +Initialize has-property-descriptors@1.0.0 +Initialize object-keys@1.1.1 +Initialize get-intrinsic@1.2.0 +Initialize function-bind@1.1.1 +Initialize has-symbols@1.0.3 +[UNORDERED_END] diff --git a/tests/testdata/npm/local_dir_resolves_symlinks/package.json b/tests/specs/npm/local_dir_resolves_symlinks/package.json similarity index 100% rename from tests/testdata/npm/local_dir_resolves_symlinks/package.json rename to tests/specs/npm/local_dir_resolves_symlinks/package.json diff --git a/tests/specs/npm/local_dir_resolves_symlinks_auto/__test__.jsonc b/tests/specs/npm/local_dir_resolves_symlinks_auto/__test__.jsonc new file mode 100644 index 0000000000..78cd876f2b --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks_auto/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "run -A index.js", + "output": "index.out", + "exitCode": 0 + } + ] +} diff --git a/tests/specs/npm/local_dir_resolves_symlinks_auto/deno.json b/tests/specs/npm/local_dir_resolves_symlinks_auto/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks_auto/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/npm/local_dir_resolves_symlinks_auto/index.js b/tests/specs/npm/local_dir_resolves_symlinks_auto/index.js new file mode 100644 index 0000000000..72d8913f51 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks_auto/index.js @@ -0,0 +1,3 @@ +import * as d from "define-properties"; + +console.log(typeof d.default === "function", "it works"); diff --git a/tests/specs/npm/local_dir_resolves_symlinks_auto/index.out b/tests/specs/npm/local_dir_resolves_symlinks_auto/index.out new file mode 100644 index 0000000000..0cb3a15938 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks_auto/index.out @@ -0,0 +1,24 @@ +[UNORDERED_START] +Download http://localhost:4260/define-properties +Download http://localhost:4260/has-property-descriptors +Download http://localhost:4260/object-keys +Download http://localhost:4260/get-intrinsic +Download http://localhost:4260/function-bind +Download http://localhost:4260/has +Download http://localhost:4260/has-symbols +Download http://localhost:4260/define-properties/define-properties-1.2.0.tgz +Download http://localhost:4260/has-property-descriptors/has-property-descriptors-1.0.0.tgz +Download http://localhost:4260/object-keys/object-keys-1.1.1.tgz +Download http://localhost:4260/get-intrinsic/get-intrinsic-1.2.0.tgz +Download http://localhost:4260/has-symbols/has-symbols-1.0.3.tgz +Download http://localhost:4260/has/has-1.0.3.tgz +Download http://localhost:4260/function-bind/function-bind-1.1.1.tgz +Initialize has@1.0.3 +Initialize define-properties@1.2.0 +Initialize has-property-descriptors@1.0.0 +Initialize object-keys@1.1.1 +Initialize get-intrinsic@1.2.0 +Initialize function-bind@1.1.1 +Initialize has-symbols@1.0.3 +[UNORDERED_END] +true it works diff --git a/tests/specs/npm/local_dir_resolves_symlinks_auto/package.json b/tests/specs/npm/local_dir_resolves_symlinks_auto/package.json new file mode 100644 index 0000000000..4c974022e3 --- /dev/null +++ b/tests/specs/npm/local_dir_resolves_symlinks_auto/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "type": "module", + "dependencies": { + "define-properties": "^1.2.0" + } +} diff --git a/tests/specs/npm/lock_file_integrity_failure/main.out b/tests/specs/npm/lock_file_integrity_failure/main.out index 741edd9d22..1f0fca91ec 100644 --- a/tests/specs/npm/lock_file_integrity_failure/main.out +++ b/tests/specs/npm/lock_file_integrity_failure/main.out @@ -9,4 +9,4 @@ This could be caused by: * the lock file may be corrupt * the source itself may be corrupt -Use the --lock-write flag to regenerate the lockfile at "[WILDCARD]lock.json". +Investigate the lockfile; delete it to regenerate the lockfile at "[WILDCARD]lock.json". diff --git a/tests/specs/npm/lossy_utf8_module/main.out b/tests/specs/npm/lossy_utf8_module/main.out index 0e96f9ebb3..d046d2ec55 100644 --- a/tests/specs/npm/lossy_utf8_module/main.out +++ b/tests/specs/npm/lossy_utf8_module/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/lossy-utf8-module +Download http://localhost:4260/@denotest%2flossy-utf8-module Download http://localhost:4260/@denotest/lossy-utf8-module/1.0.0.tgz ���� diff --git a/tests/specs/npm/lossy_utf8_package_json/main.out b/tests/specs/npm/lossy_utf8_package_json/main.out index 99aa5ab61f..69f6870392 100644 --- a/tests/specs/npm/lossy_utf8_package_json/main.out +++ b/tests/specs/npm/lossy_utf8_package_json/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/lossy-utf8-package-json +Download http://localhost:4260/@denotest%2flossy-utf8-package-json Download http://localhost:4260/@denotest/lossy-utf8-package-json/1.0.0.tgz hello diff --git a/tests/specs/npm/lossy_utf8_script/main.out b/tests/specs/npm/lossy_utf8_script/main.out index 180ecdf1c3..0883392fd9 100644 --- a/tests/specs/npm/lossy_utf8_script/main.out +++ b/tests/specs/npm/lossy_utf8_script/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/lossy-utf8-script +Download http://localhost:4260/@denotest%2flossy-utf8-script Download http://localhost:4260/@denotest/lossy-utf8-script/1.0.0.tgz ���� diff --git a/tests/specs/npm/lossy_utf8_script_from_cjs/__test__.jsonc b/tests/specs/npm/lossy_utf8_script_from_cjs/__test__.jsonc index c8d353de00..fa00d6b9d3 100644 --- a/tests/specs/npm/lossy_utf8_script_from_cjs/__test__.jsonc +++ b/tests/specs/npm/lossy_utf8_script_from_cjs/__test__.jsonc @@ -1,5 +1,5 @@ { - "args": "run --node-modules-dir --allow-read main.mjs", + "args": "run --node-modules-dir=auto --allow-read main.mjs", "output": "main.out", "exitCode": 0, "tempDir": true diff --git a/tests/specs/npm/lossy_utf8_script_from_cjs/main.out b/tests/specs/npm/lossy_utf8_script_from_cjs/main.out index 4f062a2aef..635ea5b3a1 100644 --- a/tests/specs/npm/lossy_utf8_script_from_cjs/main.out +++ b/tests/specs/npm/lossy_utf8_script_from_cjs/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/lossy-utf8-script +Download http://localhost:4260/@denotest%2flossy-utf8-script Download http://localhost:4260/@denotest/lossy-utf8-script/1.0.0.tgz Initialize @denotest/lossy-utf8-script@1.0.0 ���� diff --git a/tests/specs/npm/mixed_case_package_name_global_dir/__test__.jsonc b/tests/specs/npm/mixed_case_package_name_global_dir/__test__.jsonc new file mode 100644 index 0000000000..db980472de --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_global_dir/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run mixed_case_package_name/global.ts", + "output": "mixed_case_package_name/global.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/mixed_case_package_name/global.out b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/global.out similarity index 64% rename from tests/testdata/npm/mixed_case_package_name/global.out rename to tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/global.out index fdacea3852..a1d3a6e2c5 100644 --- a/tests/testdata/npm/mixed_case_package_name/global.out +++ b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/global.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/MixedCase -Download http://localhost:4260/@denotest/CAPITALS +Download http://localhost:4260/@denotest%2fMixedCase +Download http://localhost:4260/@denotest%2fCAPITALS [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/CAPITALS/1.0.0.tgz diff --git a/tests/testdata/npm/mixed_case_package_name/global.ts b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/global.ts similarity index 100% rename from tests/testdata/npm/mixed_case_package_name/global.ts rename to tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/global.ts diff --git a/tests/testdata/npm/mixed_case_package_name/local.out b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/local.out similarity index 72% rename from tests/testdata/npm/mixed_case_package_name/local.out rename to tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/local.out index 6ab989d80c..c8c9ed396c 100644 --- a/tests/testdata/npm/mixed_case_package_name/local.out +++ b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/local.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/MixedCase -Download http://localhost:4260/@denotest/CAPITALS +Download http://localhost:4260/@denotest%2fMixedCase +Download http://localhost:4260/@denotest%2fCAPITALS [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/CAPITALS/1.0.0.tgz diff --git a/tests/testdata/npm/mixed_case_package_name/local.ts b/tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/local.ts similarity index 100% rename from tests/testdata/npm/mixed_case_package_name/local.ts rename to tests/specs/npm/mixed_case_package_name_global_dir/mixed_case_package_name/local.ts diff --git a/tests/specs/npm/mixed_case_package_name_local_dir/__test__.jsonc b/tests/specs/npm/mixed_case_package_name_local_dir/__test__.jsonc new file mode 100644 index 0000000000..a214b6f4a3 --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_local_dir/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run --node-modules-dir=auto -A mixed_case_package_name/local.ts", + "output": "mixed_case_package_name/local.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.out b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.out new file mode 100644 index 0000000000..a1d3a6e2c5 --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.out @@ -0,0 +1,9 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fMixedCase +Download http://localhost:4260/@denotest%2fCAPITALS +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/CAPITALS/1.0.0.tgz +Download http://localhost:4260/@denotest/MixedCase/1.0.0.tgz +[UNORDERED_END] +5 diff --git a/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.ts b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.ts new file mode 100644 index 0000000000..a721b3d784 --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/global.ts @@ -0,0 +1,2 @@ +import value from "npm:@denotest/MixedCase"; +console.log(value); diff --git a/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.out b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.out new file mode 100644 index 0000000000..c8c9ed396c --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.out @@ -0,0 +1,13 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fMixedCase +Download http://localhost:4260/@denotest%2fCAPITALS +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/@denotest/CAPITALS/1.0.0.tgz +Initialize @denotest/CAPITALS@1.0.0 +Download http://localhost:4260/@denotest/MixedCase/1.0.0.tgz +Initialize @denotest/MixedCase@1.0.0 +[UNORDERED_END] +5 +true +true diff --git a/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.ts b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.ts new file mode 100644 index 0000000000..6ca6cb581a --- /dev/null +++ b/tests/specs/npm/mixed_case_package_name_local_dir/mixed_case_package_name/local.ts @@ -0,0 +1,18 @@ +import value from "npm:@denotest/MixedCase"; +console.log(value); +console.log(pathExists("./node_modules/.deno")); +console.log( + pathExists("./node_modules/.deno/_ibsgk3tporsxg5bpinavaskuifgfg@1.0.0"), +); + +function pathExists(filePath: string) { + try { + Deno.lstatSync(filePath); + return true; + } catch (error) { + if (error instanceof Deno.errors.NotFound) { + return false; + } + throw error; + } +} diff --git a/tests/specs/npm/no_types_cjs/main.out b/tests/specs/npm/no_types_cjs/main.out index 4747a9a325..c993d5fbf4 100644 --- a/tests/specs/npm/no_types_cjs/main.out +++ b/tests/specs/npm/no_types_cjs/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/no-types-cjs +Download http://localhost:4260/@denotest%2fno-types-cjs Download http://localhost:4260/@denotest/no-types-cjs/1.0.0.tgz Check file:///[WILDLINE]/no_types_cjs/main.ts diff --git a/tests/specs/npm/no_types_in_conditional_exports/main.out b/tests/specs/npm/no_types_in_conditional_exports/main.out index 46c5832347..593cb23370 100644 --- a/tests/specs/npm/no_types_in_conditional_exports/main.out +++ b/tests/specs/npm/no_types_in_conditional_exports/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/no-types-in-conditional-exports +Download http://localhost:4260/@denotest%2fno-types-in-conditional-exports Download http://localhost:4260/@denotest/no-types-in-conditional-exports/1.0.0.tgz Check [WILDCARD]npm/no_types_in_conditional_exports/main.ts { foo: "bar" } diff --git a/tests/specs/npm/node_modules_deno_node_modules/__test__.jsonc b/tests/specs/npm/node_modules_deno_node_modules/__test__.jsonc new file mode 100644 index 0000000000..a1fbfef7c9 --- /dev/null +++ b/tests/specs/npm/node_modules_deno_node_modules/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet node_modules_deno_node_modules/main.ts", + "output": "node_modules_deno_node_modules/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/node_modules_deno_node_modules/main.out b/tests/specs/npm/node_modules_deno_node_modules/node_modules_deno_node_modules/main.out similarity index 100% rename from tests/testdata/npm/node_modules_deno_node_modules/main.out rename to tests/specs/npm/node_modules_deno_node_modules/node_modules_deno_node_modules/main.out diff --git a/tests/testdata/npm/node_modules_deno_node_modules/main.ts b/tests/specs/npm/node_modules_deno_node_modules/node_modules_deno_node_modules/main.ts similarity index 100% rename from tests/testdata/npm/node_modules_deno_node_modules/main.ts rename to tests/specs/npm/node_modules_deno_node_modules/node_modules_deno_node_modules/main.ts diff --git a/tests/specs/npm/node_modules_deno_node_modules_local/__test__.jsonc b/tests/specs/npm/node_modules_deno_node_modules_local/__test__.jsonc new file mode 100644 index 0000000000..d283b758bb --- /dev/null +++ b/tests/specs/npm/node_modules_deno_node_modules_local/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run --quiet --node-modules-dir node_modules_deno_node_modules/main.ts", + "output": "node_modules_deno_node_modules/main.out", + "exitCode": 0 +} diff --git a/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.out b/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.out new file mode 100644 index 0000000000..1ebdb2dd57 --- /dev/null +++ b/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.out @@ -0,0 +1,2 @@ +esm +esm diff --git a/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.ts b/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.ts new file mode 100644 index 0000000000..6e4a32d8e8 --- /dev/null +++ b/tests/specs/npm/node_modules_deno_node_modules_local/node_modules_deno_node_modules/main.ts @@ -0,0 +1,7 @@ +import { getKind as getKind1 } from "npm:@denotest/dual-cjs-esm-dep"; +// this should still be able to be resolved even though it's missing the +// "@denotest/dual-cjs-esm" package because the above import will resolve it +import { getKind as getKind2 } from "npm:@denotest/dual-cjs-esm-dep-missing"; + +console.log(getKind1()); +console.log(getKind2()); diff --git a/tests/specs/npm/node_modules_dir_require_added_node_modules_folder/__test__.jsonc b/tests/specs/npm/node_modules_dir_require_added_node_modules_folder/__test__.jsonc new file mode 100644 index 0000000000..d0b1d081cb --- /dev/null +++ b/tests/specs/npm/node_modules_dir_require_added_node_modules_folder/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run --node-modules-dir=auto -A --quiet require_added_nm_folder/main.js", + "output": "require_added_nm_folder/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/require_added_nm_folder/main.js b/tests/specs/npm/node_modules_dir_require_added_node_modules_folder/require_added_nm_folder/main.js similarity index 100% rename from tests/testdata/npm/require_added_nm_folder/main.js rename to tests/specs/npm/node_modules_dir_require_added_node_modules_folder/require_added_nm_folder/main.js diff --git a/tests/testdata/npm/require_added_nm_folder/main.out b/tests/specs/npm/node_modules_dir_require_added_node_modules_folder/require_added_nm_folder/main.out similarity index 100% rename from tests/testdata/npm/require_added_nm_folder/main.out rename to tests/specs/npm/node_modules_dir_require_added_node_modules_folder/require_added_nm_folder/main.out diff --git a/tests/specs/npm/node_modules_dir_require_main_entry/__test__.jsonc b/tests/specs/npm/node_modules_dir_require_main_entry/__test__.jsonc new file mode 100644 index 0000000000..a2b936d661 --- /dev/null +++ b/tests/specs/npm/node_modules_dir_require_main_entry/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run --node-modules-dir -A --quiet require_main/main.js", + "output": "require_main/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/require_main/main.js b/tests/specs/npm/node_modules_dir_require_main_entry/require_main/main.js similarity index 100% rename from tests/testdata/npm/require_main/main.js rename to tests/specs/npm/node_modules_dir_require_main_entry/require_main/main.js diff --git a/tests/specs/npm/node_modules_dir_require_main_entry/require_main/main.out b/tests/specs/npm/node_modules_dir_require_main_entry/require_main/main.out new file mode 100644 index 0000000000..e2dbde096f --- /dev/null +++ b/tests/specs/npm/node_modules_dir_require_main_entry/require_main/main.out @@ -0,0 +1 @@ +function diff --git a/tests/specs/npm/node_modules_dir_with_deps/__test__.jsonc b/tests/specs/npm/node_modules_dir_with_deps/__test__.jsonc new file mode 100644 index 0000000000..945a3f4d4b --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run --allow-read --allow-env --node-modules-dir=auto cjs_with_deps/main.js", + "output": "cjs_with_deps/main_node_modules.out" +} diff --git a/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.js b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.js new file mode 100644 index 0000000000..568726874e --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.js @@ -0,0 +1,12 @@ +import chalk from "npm:chalk@4"; +import { expect } from "npm:chai@4.3"; + +console.log(chalk.green("chalk cjs loads")); + +const timeout = setTimeout(() => {}, 0); +expect(timeout).to.be.a("number"); +clearTimeout(timeout); + +const interval = setInterval(() => {}, 100); +expect(interval).to.be.a("number"); +clearInterval(interval); diff --git a/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.out b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.out new file mode 100644 index 0000000000..7051c23953 --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main.out @@ -0,0 +1,33 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Download http://localhost:4260/chai/chai-4.3.6.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info.out b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info.out new file mode 100644 index 0000000000..bcaaf1eecf --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info.out @@ -0,0 +1,22 @@ +local: [WILDCARD]main.js +type: JavaScript +dependencies: 14 unique +size: [WILDCARD] + +file:///[WILDCARD]/npm/cjs_with_deps/main.js ([WILDCARD]) +├─┬ npm:/chalk@4.1.2 ([WILDCARD]) +│ ├─┬ npm:/ansi-styles@4.3.0 ([WILDCARD]) +│ │ └─┬ npm:/color-convert@2.0.1 ([WILDCARD]) +│ │ └── npm:/color-name@1.1.4 ([WILDCARD]) +│ └─┬ npm:/supports-color@7.2.0 ([WILDCARD]) +│ └── npm:/has-flag@4.0.0 ([WILDCARD]) +└─┬ npm:/chai@4.3.6 ([WILDCARD]) + ├── npm:/assertion-error@1.1.0 ([WILDCARD]) + ├── npm:/check-error@1.0.2 ([WILDCARD]) + ├─┬ npm:/deep-eql@3.0.1 ([WILDCARD]) + │ └── npm:/type-detect@4.0.8 ([WILDCARD]) + ├── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├─┬ npm:/loupe@2.3.4 ([WILDCARD]) + │ └── npm:/get-func-name@2.0.0 ([WILDCARD]) + ├── npm:/pathval@1.1.1 ([WILDCARD]) + └── npm:/type-detect@4.0.8 ([WILDCARD]) diff --git a/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info_json.out b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info_json.out new file mode 100644 index 0000000000..137b9f8ce5 --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_info_json.out @@ -0,0 +1,148 @@ +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "npm:chalk@4", + "code": { + "specifier": "npm:chalk@4", + "span": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 31 + } + } + }, + "npmPackage": "chalk@4.1.2" + }, + { + "specifier": "npm:chai@4.3", + "code": { + "specifier": "npm:chai@4.3", + "span": { + "start": { + "line": 1, + "character": 23 + }, + "end": { + "line": 1, + "character": 37 + } + } + }, + "npmPackage": "chai@4.3.6" + } + ], + "local": "[WILDCARD]main.js", + "size": 325, + "mediaType": "JavaScript", + "specifier": "[WILDCARD]/main.js" + } + ], + "redirects": { + "npm:chai@4.3": "npm:/chai@4.3.6", + "npm:chalk@4": "npm:/chalk@4.1.2" + }, + "npmPackages": { + "ansi-styles@4.3.0": { + "name": "ansi-styles", + "version": "4.3.0", + "dependencies": [ + "color-convert@2.0.1" + ] + }, + "assertion-error@1.1.0": { + "name": "assertion-error", + "version": "1.1.0", + "dependencies": [] + }, + "chai@4.3.6": { + "name": "chai", + "version": "4.3.6", + "dependencies": [ + "assertion-error@1.1.0", + "check-error@1.0.2", + "deep-eql@3.0.1", + "get-func-name@2.0.0", + "loupe@2.3.4", + "pathval@1.1.1", + "type-detect@4.0.8" + ] + }, + "chalk@4.1.2": { + "name": "chalk", + "version": "4.1.2", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ] + }, + "check-error@1.0.2": { + "name": "check-error", + "version": "1.0.2", + "dependencies": [] + }, + "color-convert@2.0.1": { + "name": "color-convert", + "version": "2.0.1", + "dependencies": [ + "color-name@1.1.4" + ] + }, + "color-name@1.1.4": { + "name": "color-name", + "version": "1.1.4", + "dependencies": [] + }, + "deep-eql@3.0.1": { + "name": "deep-eql", + "version": "3.0.1", + "dependencies": [ + "type-detect@4.0.8" + ] + }, + "get-func-name@2.0.0": { + "name": "get-func-name", + "version": "2.0.0", + "dependencies": [] + }, + "has-flag@4.0.0": { + "name": "has-flag", + "version": "4.0.0", + "dependencies": [] + }, + "loupe@2.3.4": { + "name": "loupe", + "version": "2.3.4", + "dependencies": [ + "get-func-name@2.0.0" + ] + }, + "pathval@1.1.1": { + "name": "pathval", + "version": "1.1.1", + "dependencies": [] + }, + "supports-color@7.2.0": { + "name": "supports-color", + "version": "7.2.0", + "dependencies": [ + "has-flag@4.0.0" + ] + }, + "type-detect@4.0.8": { + "name": "type-detect", + "version": "4.0.8", + "dependencies": [] + } + } +} diff --git a/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_node_modules.out b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_node_modules.out new file mode 100644 index 0000000000..1ab3679521 --- /dev/null +++ b/tests/specs/npm/node_modules_dir_with_deps/cjs_with_deps/main_node_modules.out @@ -0,0 +1,47 @@ +[UNORDERED_START] +Download http://localhost:4260/chalk +Download http://localhost:4260/chai +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/assertion-error +Download http://localhost:4260/check-error +Download http://localhost:4260/deep-eql +Download http://localhost:4260/get-func-name +Download http://localhost:4260/loupe +Download http://localhost:4260/pathval +Download http://localhost:4260/type-detect +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Initialize ansi-styles@4.3.0 +Download http://localhost:4260/assertion-error/assertion-error-1.1.0.tgz +Initialize assertion-error@1.1.0 +Download http://localhost:4260/chai/chai-4.3.6.tgz +Initialize chai@4.3.6 +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Initialize chalk@4.1.2 +Download http://localhost:4260/check-error/check-error-1.0.2.tgz +Initialize check-error@1.0.2 +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Initialize color-convert@2.0.1 +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize color-name@1.1.4 +Download http://localhost:4260/deep-eql/deep-eql-3.0.1.tgz +Initialize deep-eql@3.0.1 +Download http://localhost:4260/get-func-name/get-func-name-2.0.0.tgz +Initialize get-func-name@2.0.0 +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Initialize has-flag@4.0.0 +Download http://localhost:4260/loupe/loupe-2.3.4.tgz +Initialize loupe@2.3.4 +Download http://localhost:4260/pathval/pathval-1.1.1.tgz +Initialize pathval@1.1.1 +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Initialize supports-color@7.2.0 +Download http://localhost:4260/type-detect/type-detect-4.0.8.tgz +Initialize type-detect@4.0.8 +[UNORDERED_END] +chalk cjs loads diff --git a/tests/specs/npm/node_modules_dir_yargs/__test__.jsonc b/tests/specs/npm/node_modules_dir_yargs/__test__.jsonc new file mode 100644 index 0000000000..ffb9b41f82 --- /dev/null +++ b/tests/specs/npm/node_modules_dir_yargs/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run --allow-read --allow-env --node-modules-dir=auto cjs_yargs/main.js", + "output": "cjs_yargs/main.out" +} diff --git a/tests/testdata/npm/cjs_yargs/main.js b/tests/specs/npm/node_modules_dir_yargs/cjs_yargs/main.js similarity index 100% rename from tests/testdata/npm/cjs_yargs/main.js rename to tests/specs/npm/node_modules_dir_yargs/cjs_yargs/main.js diff --git a/tests/testdata/npm/cjs_yargs/main.out b/tests/specs/npm/node_modules_dir_yargs/cjs_yargs/main.out similarity index 100% rename from tests/testdata/npm/cjs_yargs/main.out rename to tests/specs/npm/node_modules_dir_yargs/cjs_yargs/main.out diff --git a/tests/specs/npm/node_modules_import/__test__.jsonc b/tests/specs/npm/node_modules_import/__test__.jsonc new file mode 100644 index 0000000000..61a1706a88 --- /dev/null +++ b/tests/specs/npm/node_modules_import/__test__.jsonc @@ -0,0 +1,31 @@ +{ + "tempDir": true, + "tests": { + "node_modules_import_run": { + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { + "args": "run --quiet main.ts", + "output": "main.out", + "exitCode": 0 + } + ] + }, + "node_modules_import_check": { + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { + "args": "check --quiet main.ts", + "output": "main_check.out", + "exitCode": 1 + } + ] + } + } +} diff --git a/tests/specs/npm/node_modules_import/install.out b/tests/specs/npm/node_modules_import/install.out new file mode 100644 index 0000000000..8f03ba6407 --- /dev/null +++ b/tests/specs/npm/node_modules_import/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/testdata/npm/node_modules_import/main.out b/tests/specs/npm/node_modules_import/main.out similarity index 100% rename from tests/testdata/npm/node_modules_import/main.out rename to tests/specs/npm/node_modules_import/main.out diff --git a/tests/testdata/npm/node_modules_import/main.ts b/tests/specs/npm/node_modules_import/main.ts similarity index 100% rename from tests/testdata/npm/node_modules_import/main.ts rename to tests/specs/npm/node_modules_import/main.ts diff --git a/tests/testdata/npm/node_modules_import/main_check.out b/tests/specs/npm/node_modules_import/main_check.out similarity index 67% rename from tests/testdata/npm/node_modules_import/main_check.out rename to tests/specs/npm/node_modules_import/main_check.out index cf7cc110d4..7fd7013fc4 100644 --- a/tests/testdata/npm/node_modules_import/main_check.out +++ b/tests/specs/npm/node_modules_import/main_check.out @@ -1,16 +1,16 @@ error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. const value1: string = myImport1.getValue(); ~~~~~~ - at file:///[WILDCARD]/npm/node_modules_import/main.ts:9:7 + at file:///[WILDCARD]/main.ts:9:7 TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. const value2: string = myImport2.getValue(); ~~~~~~ - at file:///[WILDCARD]/npm/node_modules_import/main.ts:10:7 + at file:///[WILDCARD]/main.ts:10:7 TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. const value3: string = myImport3.getValue(); ~~~~~~ - at file:///[WILDCARD]/npm/node_modules_import/main.ts:11:7 + at file:///[WILDCARD]/main.ts:11:7 Found 3 errors. diff --git a/tests/testdata/npm/node_modules_import/package.json b/tests/specs/npm/node_modules_import/package.json similarity index 100% rename from tests/testdata/npm/node_modules_import/package.json rename to tests/specs/npm/node_modules_import/package.json diff --git a/tests/specs/npm/node_modules_import_auto/__test__.jsonc b/tests/specs/npm/node_modules_import_auto/__test__.jsonc new file mode 100644 index 0000000000..4f18ebe60b --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "tests": { + "node_modules_import_run": { + "steps": [ + { + "args": "run main.ts", + "output": "main.out", + "exitCode": 0 + } + ] + }, + "node_modules_import_check": { + "steps": [ + { + "args": "check main.ts", + "output": "main_check.out", + "exitCode": 1 + } + ] + } + } +} diff --git a/tests/specs/npm/node_modules_import_auto/deno.json b/tests/specs/npm/node_modules_import_auto/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/npm/node_modules_import_auto/main.out b/tests/specs/npm/node_modules_import_auto/main.out new file mode 100644 index 0000000000..18194e3a0c --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/main.out @@ -0,0 +1,6 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 +2 +2 +2 diff --git a/tests/specs/npm/node_modules_import_auto/main.ts b/tests/specs/npm/node_modules_import_auto/main.ts new file mode 100644 index 0000000000..848ca0f81e --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/main.ts @@ -0,0 +1,16 @@ +import * as myImport1 from "@denotest/esm-basic"; +import * as myImport2 from "./node_modules/@denotest/esm-basic/main.mjs"; +import * as myImport3 from "@denotest/esm-basic/main.mjs"; + +myImport1.setValue(5); +myImport2.setValue(2); + +// these should all give type errors +const value1: string = myImport1.getValue(); +const value2: string = myImport2.getValue(); +const value3: string = myImport3.getValue(); + +// these should all be equal because it should be mutating the same module +console.log(value1); +console.log(value2); +console.log(value3); diff --git a/tests/specs/npm/node_modules_import_auto/main_check.out b/tests/specs/npm/node_modules_import_auto/main_check.out new file mode 100644 index 0000000000..093b0c051a --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/main_check.out @@ -0,0 +1,20 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 +Check file:///[WILDCARD]/main.ts +error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. +const value1: string = myImport1.getValue(); + ~~~~~~ + at file:///[WILDCARD]/main.ts:9:7 + +TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. +const value2: string = myImport2.getValue(); + ~~~~~~ + at file:///[WILDCARD]/main.ts:10:7 + +TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. +const value3: string = myImport3.getValue(); + ~~~~~~ + at file:///[WILDCARD]/main.ts:11:7 + +Found 3 errors. diff --git a/tests/specs/npm/node_modules_import_auto/package.json b/tests/specs/npm/node_modules_import_auto/package.json new file mode 100644 index 0000000000..ed77298e0c --- /dev/null +++ b/tests/specs/npm/node_modules_import_auto/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "^1" + } +} diff --git a/tests/specs/npm/non_existent_dep/__test__.jsonc b/tests/specs/npm/non_existent_dep/__test__.jsonc new file mode 100644 index 0000000000..8608e00f3e --- /dev/null +++ b/tests/specs/npm/non_existent_dep/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "cache npm:@denotest/non-existent-dep", + "exitCode": 1, + "output": "[UNORDERED_START]\nDownload http://localhost:4260/@denotest%2fnon-existent-dep\nDownload http://localhost:4260/@denotest%2fnon-existent\n[UNORDERED_END]\nerror: npm package '@denotest/non-existent' does not exist.\n" +} diff --git a/tests/specs/npm/non_existent_dep_version/__test__.jsonc b/tests/specs/npm/non_existent_dep_version/__test__.jsonc new file mode 100644 index 0000000000..dd91c66243 --- /dev/null +++ b/tests/specs/npm/non_existent_dep_version/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "cache npm:@denotest/non-existent-dep-version", + "exitCode": 1, + "output": "[UNORDERED_START]\nDownload http://localhost:4260/@denotest%2fnon-existent-dep-version\nDownload http://localhost:4260/@denotest%2fesm-basic\n[UNORDERED_END]\nerror: Could not find npm package '@denotest/esm-basic' matching '=99.99.99'.\n" +} diff --git a/tests/specs/npm/nonexistent_file/__test__.jsonc b/tests/specs/npm/nonexistent_file/__test__.jsonc new file mode 100644 index 0000000000..2ad137bf4a --- /dev/null +++ b/tests/specs/npm/nonexistent_file/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet nonexistent_file/main.js", + "output": "nonexistent_file/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/nonexistent_file/main.js b/tests/specs/npm/nonexistent_file/nonexistent_file/main.js similarity index 100% rename from tests/testdata/npm/nonexistent_file/main.js rename to tests/specs/npm/nonexistent_file/nonexistent_file/main.js diff --git a/tests/testdata/npm/nonexistent_file/main.out b/tests/specs/npm/nonexistent_file/nonexistent_file/main.out similarity index 100% rename from tests/testdata/npm/nonexistent_file/main.out rename to tests/specs/npm/nonexistent_file/nonexistent_file/main.out diff --git a/tests/specs/npm/nonexistent_file_node_modules_dir/__test__.jsonc b/tests/specs/npm/nonexistent_file_node_modules_dir/__test__.jsonc new file mode 100644 index 0000000000..82b282c04b --- /dev/null +++ b/tests/specs/npm/nonexistent_file_node_modules_dir/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "run -A --quiet --node-modules-dir nonexistent_file/main.js", + "output": "nonexistent_file/main.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.js b/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.js new file mode 100644 index 0000000000..c480b0548f --- /dev/null +++ b/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.js @@ -0,0 +1,2 @@ +import hmacSHA512 from "npm:crypto-js/non-existent"; +console.log(hmacSHA512); diff --git a/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.out b/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.out new file mode 100644 index 0000000000..baa79b1cef --- /dev/null +++ b/tests/specs/npm/nonexistent_file_node_modules_dir/nonexistent_file/main.out @@ -0,0 +1,4 @@ +error: Unable to load [WILDCARD]non-existent imported from [WILDCARD]main.js + +Caused by: +[WILDCARD] diff --git a/tests/specs/npm/npm_pkg_depend_dep_same_name/__test__.jsonc b/tests/specs/npm/npm_pkg_depend_dep_same_name/__test__.jsonc index d2f4cf6fb9..4bca3ecab0 100644 --- a/tests/specs/npm/npm_pkg_depend_dep_same_name/__test__.jsonc +++ b/tests/specs/npm/npm_pkg_depend_dep_same_name/__test__.jsonc @@ -1,8 +1,5 @@ { "tempDir": true, - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "[WILDCARD]" diff --git a/tests/specs/npm/npmrc/__test__.jsonc b/tests/specs/npm/npmrc/__test__.jsonc index 106842d2b1..88ef2d8102 100644 --- a/tests/specs/npm/npmrc/__test__.jsonc +++ b/tests/specs/npm/npmrc/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "deno_install": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "install.out" @@ -14,8 +11,12 @@ }] }, "run_node_modules_dir": { - "args": "run --node-modules-dir -A --quiet main.js", + "args": "run --node-modules-dir=auto -A --quiet main.js", "output": "main.out" + }, + "info": { + "args": "info --node-modules-dir=auto --json main.js", + "output": "info.out" } } } diff --git a/tests/specs/npm/npmrc/info.out b/tests/specs/npm/npmrc/info.out new file mode 100644 index 0000000000..ee9aa9ee96 --- /dev/null +++ b/tests/specs/npm/npmrc/info.out @@ -0,0 +1,87 @@ +[UNORDERED_START] +Download http://localhost:4262/@denotest2%2fbasic +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4261/@denotest/basic/1.0.0.tgz +Download http://localhost:4262/@denotest2/basic/1.0.0.tgz +[UNORDERED_END] +[UNORDERED_START] +Initialize @denotest/basic@1.0.0 +Initialize @denotest2/basic@1.0.0 +[UNORDERED_END] +{ + "version": 1, + "roots": [ + "file://[WILDCARD]/main.js" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "@denotest/basic", + "code": { + "specifier": "npm:@denotest/basic@1.0.0", + "span": { + "start": { + "line": 0, + "character": 35 + }, + "end": { + "line": 0, + "character": 52 + } + } + } + }, + { + "specifier": "@denotest2/basic", + "code": { + "specifier": "npm:@denotest2/basic@1.0.0", + "span": { + "start": { + "line": 1, + "character": 22 + }, + "end": { + "line": 1, + "character": 40 + } + } + } + } + ], + "local": "[WILDCARD]main.js", + "size": 192, + "mediaType": "JavaScript", + "specifier": "file://[WILDCARD]/main.js" + }, + { + "kind": "npm", + "specifier": "npm:/@denotest/basic@1.0.0", + "npmPackage": "@denotest/basic@1.0.0" + }, + { + "kind": "npm", + "specifier": "npm:/@denotest2/basic@1.0.0", + "npmPackage": "@denotest2/basic@1.0.0" + } + ], + "redirects": { + "npm:@denotest/basic@1.0.0": "npm:/@denotest/basic@1.0.0", + "npm:@denotest2/basic@1.0.0": "npm:/@denotest2/basic@1.0.0" + }, + "npmPackages": { + "@denotest/basic@1.0.0": { + "name": "@denotest/basic", + "version": "1.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4261/" + }, + "@denotest2/basic@1.0.0": { + "name": "@denotest2/basic", + "version": "1.0.0", + "dependencies": [], + "registryUrl": "http://localhost:4262/" + } + } +} diff --git a/tests/specs/npm/npmrc/install.out b/tests/specs/npm/npmrc/install.out index 30643527e6..f2ea78c3f8 100644 --- a/tests/specs/npm/npmrc/install.out +++ b/tests/specs/npm/npmrc/install.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4261/@denotest/basic -Download http://localhost:4262/@denotest2/basic +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4262/@denotest2%2fbasic Download http://localhost:4261/@denotest/basic/1.0.0.tgz Download http://localhost:4262/@denotest2/basic/1.0.0.tgz Initialize @denotest2/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_bad_registry_config/__test__.jsonc b/tests/specs/npm/npmrc_bad_registry_config/__test__.jsonc index fe99247b1b..d1f4855d05 100644 --- a/tests/specs/npm/npmrc_bad_registry_config/__test__.jsonc +++ b/tests/specs/npm/npmrc_bad_registry_config/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "args": "install", "output": "main.out", diff --git a/tests/specs/npm/npmrc_bad_registry_config/main.out b/tests/specs/npm/npmrc_bad_registry_config/main.out index 990d4a47fa..5d778d32e9 100644 --- a/tests/specs/npm/npmrc_bad_registry_config/main.out +++ b/tests/specs/npm/npmrc_bad_registry_config/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4261/@denotest/basic -error: Error getting response at http://localhost:4261/@denotest/basic for package "@denotest/basic": Bad response: 401 +Download http://localhost:4261/@denotest%2fbasic +error: Error getting response at http://localhost:4261/@denotest%2fbasic for package "@denotest/basic": Bad response: 401 [WILDCARD] \ No newline at end of file diff --git a/tests/specs/npm/npmrc_bad_token/__test__.jsonc b/tests/specs/npm/npmrc_bad_token/__test__.jsonc index fe99247b1b..d1f4855d05 100644 --- a/tests/specs/npm/npmrc_bad_token/__test__.jsonc +++ b/tests/specs/npm/npmrc_bad_token/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "args": "install", "output": "main.out", diff --git a/tests/specs/npm/npmrc_bad_token/main.out b/tests/specs/npm/npmrc_bad_token/main.out index 990d4a47fa..5d778d32e9 100644 --- a/tests/specs/npm/npmrc_bad_token/main.out +++ b/tests/specs/npm/npmrc_bad_token/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4261/@denotest/basic -error: Error getting response at http://localhost:4261/@denotest/basic for package "@denotest/basic": Bad response: 401 +Download http://localhost:4261/@denotest%2fbasic +error: Error getting response at http://localhost:4261/@denotest%2fbasic for package "@denotest/basic": Bad response: 401 [WILDCARD] \ No newline at end of file diff --git a/tests/specs/npm/npmrc_basic_auth/__test__.jsonc b/tests/specs/npm/npmrc_basic_auth/__test__.jsonc index 44298ed2f5..38cc92e7a1 100644 --- a/tests/specs/npm/npmrc_basic_auth/__test__.jsonc +++ b/tests/specs/npm/npmrc_basic_auth/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ "args": "install", diff --git a/tests/specs/npm/npmrc_basic_auth/install.out b/tests/specs/npm/npmrc_basic_auth/install.out index 30643527e6..f2ea78c3f8 100644 --- a/tests/specs/npm/npmrc_basic_auth/install.out +++ b/tests/specs/npm/npmrc_basic_auth/install.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4261/@denotest/basic -Download http://localhost:4262/@denotest2/basic +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4262/@denotest2%2fbasic Download http://localhost:4261/@denotest/basic/1.0.0.tgz Download http://localhost:4262/@denotest2/basic/1.0.0.tgz Initialize @denotest2/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_deno_json/__test__.jsonc b/tests/specs/npm/npmrc_deno_json/__test__.jsonc index 5d07b70342..f942507716 100644 --- a/tests/specs/npm/npmrc_deno_json/__test__.jsonc +++ b/tests/specs/npm/npmrc_deno_json/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "args": "run -A main.js", "output": "main.out" diff --git a/tests/specs/npm/npmrc_deno_json/main.out b/tests/specs/npm/npmrc_deno_json/main.out index 62750088bd..c3d6be8a1a 100644 --- a/tests/specs/npm/npmrc_deno_json/main.out +++ b/tests/specs/npm/npmrc_deno_json/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4261/@denotest/basic +Download http://localhost:4261/@denotest%2fbasic Download http://localhost:4261/@denotest/basic/1.0.0.tgz 0 42 diff --git a/tests/specs/npm/npmrc_homedir/__test__.jsonc b/tests/specs/npm/npmrc_homedir/__test__.jsonc index fa993901b9..45a3c6770c 100644 --- a/tests/specs/npm/npmrc_homedir/__test__.jsonc +++ b/tests/specs/npm/npmrc_homedir/__test__.jsonc @@ -1,7 +1,6 @@ { "tempDir": true, "envs": { - "DENO_FUTURE": "1", "HOME": "$PWD/../", "USERPROFILE": "$PWD\\..\\" }, diff --git a/tests/specs/npm/npmrc_homedir/install.out b/tests/specs/npm/npmrc_homedir/install.out index 30643527e6..f2ea78c3f8 100644 --- a/tests/specs/npm/npmrc_homedir/install.out +++ b/tests/specs/npm/npmrc_homedir/install.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4261/@denotest/basic -Download http://localhost:4262/@denotest2/basic +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4262/@denotest2%2fbasic Download http://localhost:4261/@denotest/basic/1.0.0.tgz Download http://localhost:4262/@denotest2/basic/1.0.0.tgz Initialize @denotest2/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_install_arg/.npmrc b/tests/specs/npm/npmrc_install_arg/.npmrc new file mode 100644 index 0000000000..de3704b924 --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/.npmrc @@ -0,0 +1,2 @@ +@denotest:registry=http://localhost:4261/ +//localhost:4261/:_authToken=private-reg-token diff --git a/tests/specs/npm/npmrc_install_arg/__test__.jsonc b/tests/specs/npm/npmrc_install_arg/__test__.jsonc new file mode 100644 index 0000000000..f34cfe116a --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "tests": { + "deno_install_add": { + "steps": [{ + "args": "install npm:@denotest/basic", + "output": "install.out" + }, { + "args": "run -A main.js", + "output": "main.out" + }] + }, + "deno_add": { + "steps": [{ + "args": "add npm:@denotest/basic", + "output": "add.out" + }, { + "args": "run -A main.js", + "output": "main.out" + }] + } + } +} diff --git a/tests/specs/npm/npmrc_install_arg/add.out b/tests/specs/npm/npmrc_install_arg/add.out new file mode 100644 index 0000000000..11948e54d5 --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/add.out @@ -0,0 +1,4 @@ +Add npm:@denotest/basic@1.0.0 +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4261/@denotest/basic/1.0.0.tgz +Initialize @denotest/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_install_arg/install.out b/tests/specs/npm/npmrc_install_arg/install.out new file mode 100644 index 0000000000..11948e54d5 --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/install.out @@ -0,0 +1,4 @@ +Add npm:@denotest/basic@1.0.0 +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4261/@denotest/basic/1.0.0.tgz +Initialize @denotest/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_install_arg/main.js b/tests/specs/npm/npmrc_install_arg/main.js new file mode 100644 index 0000000000..e8ccf7611c --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/main.js @@ -0,0 +1,5 @@ +import { getValue, setValue } from "@denotest/basic"; + +console.log(getValue()); +setValue(42); +console.log(getValue()); diff --git a/tests/specs/npm/npmrc_install_arg/main.out b/tests/specs/npm/npmrc_install_arg/main.out new file mode 100644 index 0000000000..dcd912c89f --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/main.out @@ -0,0 +1,2 @@ +0 +42 diff --git a/tests/specs/npm/npmrc_install_arg/package.json b/tests/specs/npm/npmrc_install_arg/package.json new file mode 100644 index 0000000000..c1318b361a --- /dev/null +++ b/tests/specs/npm/npmrc_install_arg/package.json @@ -0,0 +1,5 @@ +{ + "name": "npmrc_test", + "version": "0.0.1", + "dependencies": {} +} diff --git a/tests/specs/npm/npmrc_no_auth/.npmrc b/tests/specs/npm/npmrc_no_auth/.npmrc new file mode 100644 index 0000000000..860a7c3d9a --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/.npmrc @@ -0,0 +1 @@ +@denotest3:registry=http://localhost:4263/ diff --git a/tests/specs/npm/npmrc_no_auth/__test__.jsonc b/tests/specs/npm/npmrc_no_auth/__test__.jsonc new file mode 100644 index 0000000000..efd04f0e46 --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "tests": { + "deno_install_arg": { + "steps": [{ + "args": "install npm:@denotest3/basic", + "output": "install.out" + }, { + "args": "run -A main.js", + "output": "main.out" + }] + }, + "deno_add_arg": { + "steps": [{ + "args": "add npm:@denotest3/basic", + "output": "add.out" + }, { + "args": "run -A main.js", + "output": "main.out" + }] + } + } +} diff --git a/tests/specs/npm/npmrc_no_auth/add.out b/tests/specs/npm/npmrc_no_auth/add.out new file mode 100644 index 0000000000..31b34da13f --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/add.out @@ -0,0 +1,4 @@ +Add npm:@denotest3/basic@1.0.0 +Download http://localhost:4263/@denotest3%2fbasic +Download http://localhost:4263/@denotest3/basic/1.0.0.tgz +Initialize @denotest3/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_no_auth/install.out b/tests/specs/npm/npmrc_no_auth/install.out new file mode 100644 index 0000000000..31b34da13f --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/install.out @@ -0,0 +1,4 @@ +Add npm:@denotest3/basic@1.0.0 +Download http://localhost:4263/@denotest3%2fbasic +Download http://localhost:4263/@denotest3/basic/1.0.0.tgz +Initialize @denotest3/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_no_auth/main.js b/tests/specs/npm/npmrc_no_auth/main.js new file mode 100644 index 0000000000..22713bb0da --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/main.js @@ -0,0 +1,5 @@ +import { getValue, setValue } from "@denotest3/basic"; + +console.log(getValue()); +setValue(42); +console.log(getValue()); diff --git a/tests/specs/npm/npmrc_no_auth/main.out b/tests/specs/npm/npmrc_no_auth/main.out new file mode 100644 index 0000000000..dcd912c89f --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/main.out @@ -0,0 +1,2 @@ +0 +42 diff --git a/tests/specs/npm/npmrc_no_auth/package.json b/tests/specs/npm/npmrc_no_auth/package.json new file mode 100644 index 0000000000..dddaaac464 --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth/package.json @@ -0,0 +1,6 @@ +{ + "name": "npmrc_test", + "version": "0.0.1", + "dependencies": { + } +} diff --git a/tests/specs/npm/npmrc_no_auth_install/.npmrc b/tests/specs/npm/npmrc_no_auth_install/.npmrc new file mode 100644 index 0000000000..860a7c3d9a --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/.npmrc @@ -0,0 +1 @@ +@denotest3:registry=http://localhost:4263/ diff --git a/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc b/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc new file mode 100644 index 0000000000..56a598e3b9 --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc @@ -0,0 +1,14 @@ +{ + "tempDir": true, + "tests": { + "deno_install_arg": { + "steps": [{ + "args": "install", + "output": "install.out" + }, { + "args": "run -A main.js", + "output": "main.out" + }] + } + } +} diff --git a/tests/specs/npm/npmrc_no_auth_install/install.out b/tests/specs/npm/npmrc_no_auth_install/install.out new file mode 100644 index 0000000000..b82747af79 --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4263/@denotest3%2fbasic +Download http://localhost:4263/@denotest3/basic/1.0.0.tgz +Initialize @denotest3/basic@1.0.0 diff --git a/tests/specs/npm/npmrc_no_auth_install/main.js b/tests/specs/npm/npmrc_no_auth_install/main.js new file mode 100644 index 0000000000..22713bb0da --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/main.js @@ -0,0 +1,5 @@ +import { getValue, setValue } from "@denotest3/basic"; + +console.log(getValue()); +setValue(42); +console.log(getValue()); diff --git a/tests/specs/npm/npmrc_no_auth_install/main.out b/tests/specs/npm/npmrc_no_auth_install/main.out new file mode 100644 index 0000000000..dcd912c89f --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/main.out @@ -0,0 +1,2 @@ +0 +42 diff --git a/tests/specs/npm/npmrc_no_auth_install/package.json b/tests/specs/npm/npmrc_no_auth_install/package.json new file mode 100644 index 0000000000..2d4fb15bae --- /dev/null +++ b/tests/specs/npm/npmrc_no_auth_install/package.json @@ -0,0 +1,7 @@ +{ + "name": "npmrc_test", + "version": "0.0.1", + "dependencies": { + "@denotest3/basic": "1.0.0" + } +} diff --git a/tests/specs/npm/npmrc_not_next_to_package_json/__test__.jsonc b/tests/specs/npm/npmrc_not_next_to_package_json/__test__.jsonc index 56c50bae50..1f4952ed9b 100644 --- a/tests/specs/npm/npmrc_not_next_to_package_json/__test__.jsonc +++ b/tests/specs/npm/npmrc_not_next_to_package_json/__test__.jsonc @@ -1,11 +1,10 @@ { "envs": { - "DENO_FUTURE": "1", "USERPROFILE": "$DENO_DIR", "HOME": "$DENO_DIR" }, "tempDir": true, - "args": "install -A -L debug", + "args": "install -L debug", "output": "main.out", "cwd": "subdir" } diff --git a/tests/specs/npm/npmrc_not_next_to_package_json/main.out b/tests/specs/npm/npmrc_not_next_to_package_json/main.out index 8f42fb6d81..b128959a7c 100644 --- a/tests/specs/npm/npmrc_not_next_to_package_json/main.out +++ b/tests/specs/npm/npmrc_not_next_to_package_json/main.out @@ -2,5 +2,8 @@ [# that serves the same packages. The important bit is the message below.] [WILDCARD] No .npmrc file found [WILDCARD] +Download http://localhost:4260/@denotest%2fesm-basic +[WILDCARD] Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +[WILDCARD] Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/npm/npmrc_password_no_username/__test__.jsonc b/tests/specs/npm/npmrc_password_no_username/__test__.jsonc index a36537cb76..ad130c0f6c 100644 --- a/tests/specs/npm/npmrc_password_no_username/__test__.jsonc +++ b/tests/specs/npm/npmrc_password_no_username/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ "args": "install", diff --git a/tests/specs/npm/npmrc_password_no_username/install.out b/tests/specs/npm/npmrc_password_no_username/install.out index d49a2ba0d8..b198bcd27e 100644 --- a/tests/specs/npm/npmrc_password_no_username/install.out +++ b/tests/specs/npm/npmrc_password_no_username/install.out @@ -1,3 +1,3 @@ [UNORDERED_START] -error: Error getting response at http://localhost:4261/@denotest/basic for package "@denotest/basic": Both the username and password must be provided for basic auth +error: Error getting response at http://localhost:4261/@denotest%2fbasic for package "@denotest/basic": Both the username and password must be provided for basic auth [UNORDERED_END] diff --git a/tests/specs/npm/npmrc_tarball_other_server/__test__.jsonc b/tests/specs/npm/npmrc_tarball_other_server/__test__.jsonc index dfb311c1ec..a60339fae9 100644 --- a/tests/specs/npm/npmrc_tarball_other_server/__test__.jsonc +++ b/tests/specs/npm/npmrc_tarball_other_server/__test__.jsonc @@ -3,13 +3,13 @@ "tests": { "auth_success": { "cwd": "success", - "args": "run --node-modules-dir -A main.js", + "args": "run --node-modules-dir=auto -A main.js", "output": "success/main.out", "exitCode": 1 }, "auth_fail": { "cwd": "fail", - "args": "run --node-modules-dir -A main.js", + "args": "run --node-modules-dir=auto -A main.js", "output": "fail/main.out", "exitCode": 1 } diff --git a/tests/specs/npm/npmrc_tarball_other_server/fail/main.out b/tests/specs/npm/npmrc_tarball_other_server/fail/main.out index 08a84a477c..2c68dba54e 100644 --- a/tests/specs/npm/npmrc_tarball_other_server/fail/main.out +++ b/tests/specs/npm/npmrc_tarball_other_server/fail/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4261/@denotest/tarballs-privateserver2 +Download http://localhost:4261/@denotest%2ftarballs-privateserver2 Download http://localhost:4262/@denotest/tarballs-privateserver2/1.0.0.tgz error: Failed caching npm package '@denotest/tarballs-privateserver2@1.0.0'. diff --git a/tests/specs/npm/npmrc_tarball_other_server/success/main.out b/tests/specs/npm/npmrc_tarball_other_server/success/main.out index d75f26e336..5322a1a17d 100644 --- a/tests/specs/npm/npmrc_tarball_other_server/success/main.out +++ b/tests/specs/npm/npmrc_tarball_other_server/success/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4261/@denotest/tarballs-privateserver2 +Download http://localhost:4261/@denotest%2ftarballs-privateserver2 Download http://localhost:4262/@denotest/tarballs-privateserver2/1.0.0.tgz [# This fails on a checksum issue, because the test server isn't smart enough] [# to serve proper checksums for a package at another registry. That's fine] diff --git a/tests/specs/npm/npmrc_username_no_password/__test__.jsonc b/tests/specs/npm/npmrc_username_no_password/__test__.jsonc index a36537cb76..ad130c0f6c 100644 --- a/tests/specs/npm/npmrc_username_no_password/__test__.jsonc +++ b/tests/specs/npm/npmrc_username_no_password/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ "args": "install", diff --git a/tests/specs/npm/npmrc_username_no_password/install.out b/tests/specs/npm/npmrc_username_no_password/install.out index d49a2ba0d8..b198bcd27e 100644 --- a/tests/specs/npm/npmrc_username_no_password/install.out +++ b/tests/specs/npm/npmrc_username_no_password/install.out @@ -1,3 +1,3 @@ [UNORDERED_START] -error: Error getting response at http://localhost:4261/@denotest/basic for package "@denotest/basic": Both the username and password must be provided for basic auth +error: Error getting response at http://localhost:4261/@denotest%2fbasic for package "@denotest/basic": Both the username and password must be provided for basic auth [UNORDERED_END] diff --git a/tests/specs/npm/npmrc_username_password/__test__.jsonc b/tests/specs/npm/npmrc_username_password/__test__.jsonc index 44298ed2f5..38cc92e7a1 100644 --- a/tests/specs/npm/npmrc_username_password/__test__.jsonc +++ b/tests/specs/npm/npmrc_username_password/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ "args": "install", diff --git a/tests/specs/npm/npmrc_username_password/install.out b/tests/specs/npm/npmrc_username_password/install.out index 30643527e6..f2ea78c3f8 100644 --- a/tests/specs/npm/npmrc_username_password/install.out +++ b/tests/specs/npm/npmrc_username_password/install.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4261/@denotest/basic -Download http://localhost:4262/@denotest2/basic +Download http://localhost:4261/@denotest%2fbasic +Download http://localhost:4262/@denotest2%2fbasic Download http://localhost:4261/@denotest/basic/1.0.0.tgz Download http://localhost:4262/@denotest2/basic/1.0.0.tgz Initialize @denotest2/basic@1.0.0 diff --git a/tests/specs/npm/permissions_outside_package/__test__.jsonc b/tests/specs/npm/permissions_outside_package/__test__.jsonc new file mode 100644 index 0000000000..56228296b3 --- /dev/null +++ b/tests/specs/npm/permissions_outside_package/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read permissions_outside_package/main.ts", + "output": "permissions_outside_package/main.out" +} diff --git a/tests/testdata/npm/permissions_outside_package/foo/config.js b/tests/specs/npm/permissions_outside_package/permissions_outside_package/foo/config.js similarity index 100% rename from tests/testdata/npm/permissions_outside_package/foo/config.js rename to tests/specs/npm/permissions_outside_package/permissions_outside_package/foo/config.js diff --git a/tests/testdata/npm/permissions_outside_package/foo/package.json b/tests/specs/npm/permissions_outside_package/permissions_outside_package/foo/package.json similarity index 100% rename from tests/testdata/npm/permissions_outside_package/foo/package.json rename to tests/specs/npm/permissions_outside_package/permissions_outside_package/foo/package.json diff --git a/tests/testdata/npm/permissions_outside_package/main.out b/tests/specs/npm/permissions_outside_package/permissions_outside_package/main.out similarity index 62% rename from tests/testdata/npm/permissions_outside_package/main.out rename to tests/specs/npm/permissions_outside_package/permissions_outside_package/main.out index 089f329c4f..0fde8cf87f 100644 --- a/tests/testdata/npm/permissions_outside_package/main.out +++ b/tests/specs/npm/permissions_outside_package/permissions_outside_package/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/permissions-outside-package +Download http://localhost:4260/@denotest%2fpermissions-outside-package Download http://localhost:4260/@denotest/permissions-outside-package/1.0.0.tgz { name: "foobar", version: "0.0.1" } diff --git a/tests/testdata/npm/permissions_outside_package/main.ts b/tests/specs/npm/permissions_outside_package/permissions_outside_package/main.ts similarity index 63% rename from tests/testdata/npm/permissions_outside_package/main.ts rename to tests/specs/npm/permissions_outside_package/permissions_outside_package/main.ts index b0b82b6260..934a3eebcf 100644 --- a/tests/testdata/npm/permissions_outside_package/main.ts +++ b/tests/specs/npm/permissions_outside_package/permissions_outside_package/main.ts @@ -1,5 +1,5 @@ import { loadConfigFile } from "npm:@denotest/permissions-outside-package"; -const fileName = `${Deno.cwd()}/npm/permissions_outside_package/foo/config.js`; +const fileName = `${Deno.cwd()}/permissions_outside_package/foo/config.js`; const config = loadConfigFile(fileName); console.log(config); diff --git a/tests/specs/npm/remote_npm_specifier/__test__.jsonc b/tests/specs/npm/remote_npm_specifier/__test__.jsonc new file mode 100644 index 0000000000..0cf7c4c87d --- /dev/null +++ b/tests/specs/npm/remote_npm_specifier/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet -A remote_npm_specifier/main.ts", + "output": "remote_npm_specifier/main.out", + "exitCode": 0 +} diff --git a/tests/testdata/npm/remote_npm_specifier/main.out b/tests/specs/npm/remote_npm_specifier/remote_npm_specifier/main.out similarity index 100% rename from tests/testdata/npm/remote_npm_specifier/main.out rename to tests/specs/npm/remote_npm_specifier/remote_npm_specifier/main.out diff --git a/tests/specs/npm/remote_npm_specifier/remote_npm_specifier/main.ts b/tests/specs/npm/remote_npm_specifier/remote_npm_specifier/main.ts new file mode 100644 index 0000000000..ea9442059e --- /dev/null +++ b/tests/specs/npm/remote_npm_specifier/remote_npm_specifier/main.ts @@ -0,0 +1 @@ +import "./remote.ts"; diff --git a/tests/testdata/npm/remote_npm_specifier/remote.ts b/tests/specs/npm/remote_npm_specifier/remote_npm_specifier/remote.ts similarity index 100% rename from tests/testdata/npm/remote_npm_specifier/remote.ts rename to tests/specs/npm/remote_npm_specifier/remote_npm_specifier/remote.ts diff --git a/tests/specs/npm/require_esm/__test__.jsonc b/tests/specs/npm/require_esm/__test__.jsonc new file mode 100644 index 0000000000..83859c8f10 --- /dev/null +++ b/tests/specs/npm/require_esm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read --quiet require_esm/main.ts", + "output": "require_esm/main.out" +} diff --git a/tests/testdata/node/require_esm_error/esm.js b/tests/specs/npm/require_esm/require_esm/esm.js similarity index 100% rename from tests/testdata/node/require_esm_error/esm.js rename to tests/specs/npm/require_esm/require_esm/esm.js diff --git a/tests/specs/npm/require_esm/require_esm/main.out b/tests/specs/npm/require_esm/require_esm/main.out new file mode 100644 index 0000000000..aab0d5c285 --- /dev/null +++ b/tests/specs/npm/require_esm/require_esm/main.out @@ -0,0 +1 @@ +[Module: null prototype] { Test: [class Test] } diff --git a/tests/testdata/node/require_esm_error/main.ts b/tests/specs/npm/require_esm/require_esm/main.ts similarity index 73% rename from tests/testdata/node/require_esm_error/main.ts rename to tests/specs/npm/require_esm/require_esm/main.ts index 612e917144..67ac808f06 100644 --- a/tests/testdata/node/require_esm_error/main.ts +++ b/tests/specs/npm/require_esm/require_esm/main.ts @@ -2,4 +2,4 @@ import { createRequire } from "node:module"; const require = createRequire(import.meta.url); -require("./esm.js"); +console.log(require("./esm.js")); diff --git a/tests/specs/npm/require_json/__test__.jsonc b/tests/specs/npm/require_json/__test__.jsonc new file mode 100644 index 0000000000..c24572f144 --- /dev/null +++ b/tests/specs/npm/require_json/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet require_json/main.js", + "output": "require_json/main.out" +} diff --git a/tests/testdata/npm/require_json/main.js b/tests/specs/npm/require_json/require_json/main.js similarity index 100% rename from tests/testdata/npm/require_json/main.js rename to tests/specs/npm/require_json/require_json/main.js diff --git a/tests/testdata/npm/require_json/main.out b/tests/specs/npm/require_json/require_json/main.out similarity index 100% rename from tests/testdata/npm/require_json/main.out rename to tests/specs/npm/require_json/require_json/main.out diff --git a/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out index 3cc8a82794..2e82e68027 100644 --- a/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out +++ b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/esm-basic -Download http://localhost:4260/@denotest/require-resolve +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest%2frequire-resolve [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz diff --git a/tests/specs/npm/require_type_commonjs/__test__.jsonc b/tests/specs/npm/require_type_commonjs/__test__.jsonc new file mode 100644 index 0000000000..c9ba97ff52 --- /dev/null +++ b/tests/specs/npm/require_type_commonjs/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --allow-read --quiet main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/require_type_commonjs/main.out b/tests/specs/npm/require_type_commonjs/main.out new file mode 100644 index 0000000000..d715db8a94 --- /dev/null +++ b/tests/specs/npm/require_type_commonjs/main.out @@ -0,0 +1,4 @@ +error: 'import', and 'export' cannot be used outside of module code at file://[WILDCARD]/@denotest/type-commonjs/1.0.0/index.js:1:1 + + export {}; + ~~~~~~ diff --git a/tests/specs/npm/require_type_commonjs/main.ts b/tests/specs/npm/require_type_commonjs/main.ts new file mode 100644 index 0000000000..243eb216e4 --- /dev/null +++ b/tests/specs/npm/require_type_commonjs/main.ts @@ -0,0 +1 @@ +import "npm:@denotest/type-commonjs"; diff --git a/tests/specs/npm/reserved_word_exports/__test__.jsonc b/tests/specs/npm/reserved_word_exports/__test__.jsonc new file mode 100644 index 0000000000..01d5974c38 --- /dev/null +++ b/tests/specs/npm/reserved_word_exports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run reserved_word_exports/main.ts", + "output": "reserved_word_exports/main.out" +} diff --git a/tests/testdata/npm/reserved_word_exports/main.out b/tests/specs/npm/reserved_word_exports/reserved_word_exports/main.out similarity index 97% rename from tests/testdata/npm/reserved_word_exports/main.out rename to tests/specs/npm/reserved_word_exports/reserved_word_exports/main.out index ccfd35bc86..2a82194e37 100644 --- a/tests/testdata/npm/reserved_word_exports/main.out +++ b/tests/specs/npm/reserved_word_exports/reserved_word_exports/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/reserved-word-exports +Download http://localhost:4260/@denotest%2freserved-word-exports Download http://localhost:4260/@denotest/reserved-word-exports/1.0.0.tgz [Module: null prototype] { abstract: "abstract", diff --git a/tests/testdata/npm/reserved_word_exports/main.ts b/tests/specs/npm/reserved_word_exports/reserved_word_exports/main.ts similarity index 100% rename from tests/testdata/npm/reserved_word_exports/main.ts rename to tests/specs/npm/reserved_word_exports/reserved_word_exports/main.ts diff --git a/tests/specs/npm/run_existing_npm_package_with_subpath/__test__.jsonc b/tests/specs/npm/run_existing_npm_package_with_subpath/__test__.jsonc new file mode 100644 index 0000000000..3509fc5adb --- /dev/null +++ b/tests/specs/npm/run_existing_npm_package_with_subpath/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run --allow-read --node-modules-dir=auto npm:@denotest/bin/cli-esm dev --help", + "output": "run_existing_npm_package_with_subpath/main.out" +} diff --git a/tests/testdata/npm/run_existing_npm_package_with_subpath/main.out b/tests/specs/npm/run_existing_npm_package_with_subpath/run_existing_npm_package_with_subpath/main.out similarity index 67% rename from tests/testdata/npm/run_existing_npm_package_with_subpath/main.out rename to tests/specs/npm/run_existing_npm_package_with_subpath/run_existing_npm_package_with_subpath/main.out index f6ee03ef1b..a473c32cc6 100644 --- a/tests/testdata/npm/run_existing_npm_package_with_subpath/main.out +++ b/tests/specs/npm/run_existing_npm_package_with_subpath/run_existing_npm_package_with_subpath/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/bin@1.0.0 dev diff --git a/tests/testdata/npm/run_existing_npm_package_with_subpath/package.json b/tests/specs/npm/run_existing_npm_package_with_subpath/run_existing_npm_package_with_subpath/package.json similarity index 100% rename from tests/testdata/npm/run_existing_npm_package_with_subpath/package.json rename to tests/specs/npm/run_existing_npm_package_with_subpath/run_existing_npm_package_with_subpath/package.json diff --git a/tests/specs/npm/sub_paths/__test__.jsonc b/tests/specs/npm/sub_paths/__test__.jsonc new file mode 100644 index 0000000000..4023fb197b --- /dev/null +++ b/tests/specs/npm/sub_paths/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet sub_paths/main.jsx", + "output": "sub_paths/main.out" +} diff --git a/tests/testdata/npm/sub_paths/main.jsx b/tests/specs/npm/sub_paths/sub_paths/main.jsx similarity index 100% rename from tests/testdata/npm/sub_paths/main.jsx rename to tests/specs/npm/sub_paths/sub_paths/main.jsx diff --git a/tests/testdata/npm/sub_paths/main.out b/tests/specs/npm/sub_paths/sub_paths/main.out similarity index 100% rename from tests/testdata/npm/sub_paths/main.out rename to tests/specs/npm/sub_paths/sub_paths/main.out diff --git a/tests/specs/npm/tarball_with_global_header/__test__.jsonc b/tests/specs/npm/tarball_with_global_header/__test__.jsonc new file mode 100644 index 0000000000..af6f891836 --- /dev/null +++ b/tests/specs/npm/tarball_with_global_header/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet tarball_with_global_header/main.js", + "output": "tarball_with_global_header/main.out" +} diff --git a/tests/testdata/npm/tarball_with_global_header/main.js b/tests/specs/npm/tarball_with_global_header/tarball_with_global_header/main.js similarity index 100% rename from tests/testdata/npm/tarball_with_global_header/main.js rename to tests/specs/npm/tarball_with_global_header/tarball_with_global_header/main.js diff --git a/tests/testdata/npm/tarball_with_global_header/main.out b/tests/specs/npm/tarball_with_global_header/tarball_with_global_header/main.out similarity index 100% rename from tests/testdata/npm/tarball_with_global_header/main.out rename to tests/specs/npm/tarball_with_global_header/tarball_with_global_header/main.out diff --git a/tests/specs/npm/translate_cjs_to_esm/__test__.jsonc b/tests/specs/npm/translate_cjs_to_esm/__test__.jsonc new file mode 100644 index 0000000000..59f5873582 --- /dev/null +++ b/tests/specs/npm/translate_cjs_to_esm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet translate_cjs_to_esm/main.js", + "output": "translate_cjs_to_esm/main.out" +} diff --git a/tests/testdata/npm/translate_cjs_to_esm/main.js b/tests/specs/npm/translate_cjs_to_esm/translate_cjs_to_esm/main.js similarity index 100% rename from tests/testdata/npm/translate_cjs_to_esm/main.js rename to tests/specs/npm/translate_cjs_to_esm/translate_cjs_to_esm/main.js diff --git a/tests/testdata/npm/translate_cjs_to_esm/main.out b/tests/specs/npm/translate_cjs_to_esm/translate_cjs_to_esm/main.out similarity index 100% rename from tests/testdata/npm/translate_cjs_to_esm/main.out rename to tests/specs/npm/translate_cjs_to_esm/translate_cjs_to_esm/main.out diff --git a/tests/specs/npm/types_ambient_module/__test__.jsonc b/tests/specs/npm/types_ambient_module/__test__.jsonc new file mode 100644 index 0000000000..966d8d8ed4 --- /dev/null +++ b/tests/specs/npm/types_ambient_module/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --quiet types_ambient_module/main.ts", + "output": "types_ambient_module/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/types_ambient_module/import_map.json b/tests/specs/npm/types_ambient_module/types_ambient_module/import_map.json similarity index 100% rename from tests/testdata/npm/types_ambient_module/import_map.json rename to tests/specs/npm/types_ambient_module/types_ambient_module/import_map.json diff --git a/tests/testdata/npm/types_ambient_module/main.out b/tests/specs/npm/types_ambient_module/types_ambient_module/main.out similarity index 100% rename from tests/testdata/npm/types_ambient_module/main.out rename to tests/specs/npm/types_ambient_module/types_ambient_module/main.out diff --git a/tests/testdata/npm/types_ambient_module/main.ts b/tests/specs/npm/types_ambient_module/types_ambient_module/main.ts similarity index 100% rename from tests/testdata/npm/types_ambient_module/main.ts rename to tests/specs/npm/types_ambient_module/types_ambient_module/main.ts diff --git a/tests/testdata/npm/types_ambient_module/main_import_map.out b/tests/specs/npm/types_ambient_module/types_ambient_module/main_import_map.out similarity index 100% rename from tests/testdata/npm/types_ambient_module/main_import_map.out rename to tests/specs/npm/types_ambient_module/types_ambient_module/main_import_map.out diff --git a/tests/testdata/npm/types_ambient_module/main_import_map.ts b/tests/specs/npm/types_ambient_module/types_ambient_module/main_import_map.ts similarity index 100% rename from tests/testdata/npm/types_ambient_module/main_import_map.ts rename to tests/specs/npm/types_ambient_module/types_ambient_module/main_import_map.ts diff --git a/tests/specs/npm/types_ambient_module_import_map/__test__.jsonc b/tests/specs/npm/types_ambient_module_import_map/__test__.jsonc new file mode 100644 index 0000000000..bbfa93a99b --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --quiet --import-map=types_ambient_module/import_map.json types_ambient_module/main_import_map.ts", + "output": "types_ambient_module/main_import_map.out", + "exitCode": 1 +} diff --git a/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/import_map.json b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/import_map.json new file mode 100644 index 0000000000..f61d99b474 --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/import_map.json @@ -0,0 +1,5 @@ +{ + "imports": { + "types-ambient": "npm:@denotest/types-ambient" + } +} diff --git a/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.out b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.out new file mode 100644 index 0000000000..c84130707e --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.out @@ -0,0 +1,21 @@ +error: TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'? +console.log(import1.Test2); // should error + ~~~~~ + at file:///[WILDCARD]/types_ambient_module/main.ts:5:21 + + 'Test' is declared here. + class Test { + ~~~~ + at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9 + +TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'? +console.log(import2.Test2); // should error + ~~~~~ + at file:///[WILDCARD]/types_ambient_module/main.ts:7:21 + + 'Test' is declared here. + class Test { + ~~~~ + at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9 + +Found 2 errors. diff --git a/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.ts b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.ts new file mode 100644 index 0000000000..8f77cabe8e --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main.ts @@ -0,0 +1,7 @@ +import * as import1 from "npm:@denotest/types-ambient"; +import * as import2 from "npm:@denotest/types-ambient@1"; + +console.log(import1.Test); +console.log(import1.Test2); // should error +console.log(import2.Test); +console.log(import2.Test2); // should error diff --git a/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.out b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.out new file mode 100644 index 0000000000..548f9b479c --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.out @@ -0,0 +1,9 @@ +error: TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'? +console.log(mod.Test2); // should error + ~~~~~ + at file:///[WILDCARD]/main_import_map.ts:4:17 + + 'Test' is declared here. + class Test { + ~~~~ + at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9 diff --git a/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.ts b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.ts new file mode 100644 index 0000000000..2694c94b7a --- /dev/null +++ b/tests/specs/npm/types_ambient_module_import_map/types_ambient_module/main_import_map.ts @@ -0,0 +1,4 @@ +import * as mod from "npm:@denotest/types-ambient"; + +console.log(mod.Test); +console.log(mod.Test2); // should error diff --git a/tests/specs/npm/types_d_ext/__test__.jsonc b/tests/specs/npm/types_d_ext/__test__.jsonc new file mode 100644 index 0000000000..0af9e08b12 --- /dev/null +++ b/tests/specs/npm/types_d_ext/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "check --all d_ext/main.ts", + "output": "d_ext/main.out" +} diff --git a/tests/specs/npm/types_d_ext/d_ext/main.out b/tests/specs/npm/types_d_ext/d_ext/main.out new file mode 100644 index 0000000000..5a834fbeb6 --- /dev/null +++ b/tests/specs/npm/types_d_ext/d_ext/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fd-ext +Download http://localhost:4260/@denotest/d-ext/1.0.0.tgz +Check file:///[WILDCARD]/d_ext/main.ts diff --git a/tests/testdata/npm/d_ext/main.ts b/tests/specs/npm/types_d_ext/d_ext/main.ts similarity index 100% rename from tests/testdata/npm/d_ext/main.ts rename to tests/specs/npm/types_d_ext/d_ext/main.ts diff --git a/tests/specs/npm/types_entry_value_not_exists/__test__.jsonc b/tests/specs/npm/types_entry_value_not_exists/__test__.jsonc new file mode 100644 index 0000000000..5f66e8a389 --- /dev/null +++ b/tests/specs/npm/types_entry_value_not_exists/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --all types_entry_value_not_exists/main.ts", + "output": "types_entry_value_not_exists/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/types_entry_value_not_exists/main.out b/tests/specs/npm/types_entry_value_not_exists/types_entry_value_not_exists/main.out similarity index 80% rename from tests/testdata/npm/types_entry_value_not_exists/main.out rename to tests/specs/npm/types_entry_value_not_exists/types_entry_value_not_exists/main.out index 017a17ea2e..62ef51d9f1 100644 --- a/tests/testdata/npm/types_entry_value_not_exists/main.out +++ b/tests/specs/npm/types_entry_value_not_exists/types_entry_value_not_exists/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/types-entry-value-not-exists +Download http://localhost:4260/@denotest%2ftypes-entry-value-not-exists Download http://localhost:4260/@denotest/types-entry-value-not-exists/1.0.0.tgz Check file://[WILDCARD]/types_entry_value_not_exists/main.ts error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. diff --git a/tests/testdata/npm/types_entry_value_not_exists/main.ts b/tests/specs/npm/types_entry_value_not_exists/types_entry_value_not_exists/main.ts similarity index 100% rename from tests/testdata/npm/types_entry_value_not_exists/main.ts rename to tests/specs/npm/types_entry_value_not_exists/types_entry_value_not_exists/main.ts diff --git a/tests/specs/npm/types_exports_import_types/__test__.jsonc b/tests/specs/npm/types_exports_import_types/__test__.jsonc new file mode 100644 index 0000000000..b7dab5d3dc --- /dev/null +++ b/tests/specs/npm/types_exports_import_types/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --all types_exports_import_types/main.ts", + "output": "types_exports_import_types/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/types_exports_import_types/main.out b/tests/specs/npm/types_exports_import_types/types_exports_import_types/main.out similarity index 80% rename from tests/testdata/npm/types_exports_import_types/main.out rename to tests/specs/npm/types_exports_import_types/types_exports_import_types/main.out index 10f9425ca4..bb69bf86fb 100644 --- a/tests/testdata/npm/types_exports_import_types/main.out +++ b/tests/specs/npm/types_exports_import_types/types_exports_import_types/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/types-exports-import-types +Download http://localhost:4260/@denotest%2ftypes-exports-import-types Download http://localhost:4260/@denotest/types-exports-import-types/1.0.0.tgz Check file://[WILDCARD]/types_exports_import_types/main.ts error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. diff --git a/tests/testdata/npm/types_exports_import_types/main.ts b/tests/specs/npm/types_exports_import_types/types_exports_import_types/main.ts similarity index 100% rename from tests/testdata/npm/types_exports_import_types/main.ts rename to tests/specs/npm/types_exports_import_types/types_exports_import_types/main.ts diff --git a/tests/specs/npm/types_general/main.out b/tests/specs/npm/types_general/main.out index ffba4f84db..edc83f2a26 100644 --- a/tests/specs/npm/types_general/main.out +++ b/tests/specs/npm/types_general/main.out @@ -1,7 +1,7 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/types -Download http://localhost:4260/@denotest/types_imported -Download http://localhost:4260/@denotest/types-exports-subpaths +Download http://localhost:4260/@denotest%2ftypes +Download http://localhost:4260/@denotest%2ftypes_imported +Download http://localhost:4260/@denotest%2ftypes-exports-subpaths Download http://localhost:4260/@denotest/types_imported/1.0.0.tgz Download http://localhost:4260/@denotest/types-exports-subpaths/1.0.0.tgz Download http://localhost:4260/@denotest/types/1.0.0.tgz diff --git a/tests/specs/npm/types_no_types_entry/__test__.jsonc b/tests/specs/npm/types_no_types_entry/__test__.jsonc new file mode 100644 index 0000000000..3625122bf6 --- /dev/null +++ b/tests/specs/npm/types_no_types_entry/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --all types_no_types_entry/main.ts", + "output": "types_no_types_entry/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/types_no_types_entry/main.out b/tests/specs/npm/types_no_types_entry/types_no_types_entry/main.out similarity index 76% rename from tests/testdata/npm/types_no_types_entry/main.out rename to tests/specs/npm/types_no_types_entry/types_no_types_entry/main.out index 53e872eaf1..c867253ad9 100644 --- a/tests/testdata/npm/types_no_types_entry/main.out +++ b/tests/specs/npm/types_no_types_entry/types_no_types_entry/main.out @@ -1,6 +1,6 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/types-no-types-entry -Download http://localhost:4260/@denotest/types-entry-value-not-exists +Download http://localhost:4260/@denotest%2ftypes-no-types-entry +Download http://localhost:4260/@denotest%2ftypes-entry-value-not-exists [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/types-entry-value-not-exists/1.0.0.tgz diff --git a/tests/testdata/npm/types_no_types_entry/main.ts b/tests/specs/npm/types_no_types_entry/types_no_types_entry/main.ts similarity index 100% rename from tests/testdata/npm/types_no_types_entry/main.ts rename to tests/specs/npm/types_no_types_entry/types_no_types_entry/main.ts diff --git a/tests/specs/npm/typescript_file_in_package/__test__.jsonc b/tests/specs/npm/typescript_file_in_package/__test__.jsonc new file mode 100644 index 0000000000..08979ed257 --- /dev/null +++ b/tests/specs/npm/typescript_file_in_package/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run typescript_file_in_package/main.ts", + "output": "typescript_file_in_package/main.out", + "exitCode": 1 +} diff --git a/tests/testdata/npm/typescript_file_in_package/main.out b/tests/specs/npm/typescript_file_in_package/typescript_file_in_package/main.out similarity index 81% rename from tests/testdata/npm/typescript_file_in_package/main.out rename to tests/specs/npm/typescript_file_in_package/typescript_file_in_package/main.out index 3c3b971907..b3faa87900 100644 --- a/tests/testdata/npm/typescript_file_in_package/main.out +++ b/tests/specs/npm/typescript_file_in_package/typescript_file_in_package/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/typescript-file +Download http://localhost:4260/@denotest%2ftypescript-file Download http://localhost:4260/@denotest/typescript-file/1.0.0.tgz error: Could not resolve 'npm:@denotest/typescript-file@1.0.0'. diff --git a/tests/testdata/npm/typescript_file_in_package/main.ts b/tests/specs/npm/typescript_file_in_package/typescript_file_in_package/main.ts similarity index 100% rename from tests/testdata/npm/typescript_file_in_package/main.ts rename to tests/specs/npm/typescript_file_in_package/typescript_file_in_package/main.ts diff --git a/tests/specs/npm/workspace_basic/__test__.jsonc b/tests/specs/npm/workspace_basic/__test__.jsonc index 7415a9aeb2..8ecde6887c 100644 --- a/tests/specs/npm/workspace_basic/__test__.jsonc +++ b/tests/specs/npm/workspace_basic/__test__.jsonc @@ -2,21 +2,18 @@ "tempDir": true, "tests": { "global_cache": { - "args": "run --node-modules-dir=false b/main.ts", + "args": "run --node-modules-dir=none b/main.ts", "output": "b/main_global_cache.out" }, "global_cache_bare_specifier_not_in_pkg": { - "args": "run --node-modules-dir=false main.ts", + "args": "run --node-modules-dir=none main.ts", "output": "main.out" }, "node_modules_dir": { - "args": "run --node-modules-dir=true b/main.ts", + "args": "run --node-modules-dir=auto b/main.ts", "output": "b/main_node_modules_dir.out" }, "byonm": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [{ "args": "install", "output": "[WILDCARD]" @@ -26,11 +23,15 @@ }] }, "exports_sub_path_not_exists": { + // TODO(2.0): this test appears legitimately broken + "ignore": true, "args": "run b/exports-sub-path-not-exists.ts", "output": "b/exports-sub-path-not-exists.out", "exitCode": 1 }, "no_exports_sub_path_not_exists": { + // TODO(2.0): this test appears legitimately broken + "ignore": true, "args": "run b/no-exports-sub-path-not-exists.ts", "output": "b/no-exports-sub-path-not-exists.out", "exitCode": 1 diff --git a/tests/specs/npm/workspace_basic/b/main_global_cache.out b/tests/specs/npm/workspace_basic/b/main_global_cache.out index 203ac5a991..879f6ab050 100644 --- a/tests/specs/npm/workspace_basic/b/main_global_cache.out +++ b/tests/specs/npm/workspace_basic/b/main_global_cache.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Hello 5 Hello 5 diff --git a/tests/specs/npm/workspace_basic/b/main_node_modules_dir.out b/tests/specs/npm/workspace_basic/b/main_node_modules_dir.out index eeb4556526..464c05c57c 100644 --- a/tests/specs/npm/workspace_basic/b/main_node_modules_dir.out +++ b/tests/specs/npm/workspace_basic/b/main_node_modules_dir.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Initialize @denotest/esm-basic@1.0.0 Hello 5 diff --git a/tests/specs/npm/workspace_basic/main.out b/tests/specs/npm/workspace_basic/main.out index 92404af878..52d8267bb4 100644 --- a/tests/specs/npm/workspace_basic/main.out +++ b/tests/specs/npm/workspace_basic/main.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Hello 5 C: Hi! diff --git a/tests/specs/npm/workspace_conflicting_dep/__test__.jsonc b/tests/specs/npm/workspace_conflicting_dep/__test__.jsonc index 82d59906e6..1e5d34381a 100644 --- a/tests/specs/npm/workspace_conflicting_dep/__test__.jsonc +++ b/tests/specs/npm/workspace_conflicting_dep/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "conflicting_deps": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install", diff --git a/tests/specs/npm/workspace_dep_aliases/__test__.jsonc b/tests/specs/npm/workspace_dep_aliases/__test__.jsonc index 82d59906e6..1e5d34381a 100644 --- a/tests/specs/npm/workspace_dep_aliases/__test__.jsonc +++ b/tests/specs/npm/workspace_dep_aliases/__test__.jsonc @@ -2,9 +2,6 @@ "tempDir": true, "tests": { "conflicting_deps": { - "envs": { - "DENO_FUTURE": "1" - }, "steps": [ { "args": "install", diff --git a/tests/specs/npm/workspace_sub_deno_json/__test__.jsonc b/tests/specs/npm/workspace_sub_deno_json/__test__.jsonc index c96e91abfb..dbf35dcb0f 100644 --- a/tests/specs/npm/workspace_sub_deno_json/__test__.jsonc +++ b/tests/specs/npm/workspace_sub_deno_json/__test__.jsonc @@ -2,10 +2,14 @@ "tempDir": true, "tests": { "member": { + // TODO(2.0): this test appears legitimately broken + "ignore": true, "args": "run --allow-read member/main.ts", "output": "member.out" }, "member_with_deno_json": { + // TODO(2.0): this test appears legitimately broken + "ignore": true, "args": "run --allow-read member_with_deno_json/main.ts", "output": "member.out" }, diff --git a/tests/specs/npm/workspace_sub_deno_json/member_with_deno_json/deno.jsonc b/tests/specs/npm/workspace_sub_deno_json/member_with_deno_json/deno.jsonc index 99bd145fe7..e246bc65df 100644 --- a/tests/specs/npm/workspace_sub_deno_json/member_with_deno_json/deno.jsonc +++ b/tests/specs/npm/workspace_sub_deno_json/member_with_deno_json/deno.jsonc @@ -1,4 +1,4 @@ { // will cause a warning - "nodeModulesDir": true + "nodeModules": "local-auto" } diff --git a/tests/specs/npm/workspace_sub_deno_json/non_member/deno.json b/tests/specs/npm/workspace_sub_deno_json/non_member/deno.json index 176354f98f..fbd70ec480 100644 --- a/tests/specs/npm/workspace_sub_deno_json/non_member/deno.json +++ b/tests/specs/npm/workspace_sub_deno_json/non_member/deno.json @@ -1,3 +1,3 @@ { - "nodeModulesDir": true + "nodeModulesDir": "auto" } diff --git a/tests/specs/npm/workspace_wildcards/__test__.jsonc b/tests/specs/npm/workspace_wildcards/__test__.jsonc index eeb1629ec0..6067beb51d 100644 --- a/tests/specs/npm/workspace_wildcards/__test__.jsonc +++ b/tests/specs/npm/workspace_wildcards/__test__.jsonc @@ -1,4 +1,4 @@ { - "args": "run --node-modules-dir=false main.ts", + "args": "run --node-modules-dir=none main.ts", "output": "main.out" } diff --git a/tests/specs/permission/allow_import/__test__.jsonc b/tests/specs/permission/allow_import/__test__.jsonc new file mode 100644 index 0000000000..4135a24be1 --- /dev/null +++ b/tests/specs/permission/allow_import/__test__.jsonc @@ -0,0 +1,57 @@ +{ + "tests": { + "info": { + "args": "info main.ts", + "output": "info.out" + }, + "cache": { + "args": "cache main.ts", + "output": "cache.out", + "exitCode": 1 + }, + "check": { + "args": "check main.ts", + "output": "check.out", + "exitCode": 1 + }, + "compile": { + "args": "compile main.ts", + "output": "compile.out", + "exitCode": 1 + }, + "doc": { + "args": "doc doc.ts", + "output": "doc.out", + "exitCode": 0 + }, + "doc_allowed": { + "args": "doc --allow-import doc.ts", + "output": "doc_allowed.out", + "exitCode": 0 + }, + "run": { + "args": "run main.ts", + "output": "run.out", + "exitCode": 1 + }, + "run_allow_all": { + "args": "run --quiet --allow-all success.ts", + "output": "3\n", + "exitCode": 0 + }, + "serve": { + "args": "serve main.ts", + "output": "serve.out", + "exitCode": 1 + }, + "builtin_host": { + "args": "run --quiet builtin_host.ts", + "output": "3\n" + }, + "builtin_host_replaced": { + "args": "run --quiet --allow-import=other.host builtin_host.ts", + "output": "[WILDCARD]Requires import access[WILDCARD]", + "exitCode": 1 + } + } +} diff --git a/tests/specs/permission/allow_import/builtin_host.ts b/tests/specs/permission/allow_import/builtin_host.ts new file mode 100644 index 0000000000..a3ca2df76a --- /dev/null +++ b/tests/specs/permission/allow_import/builtin_host.ts @@ -0,0 +1,4 @@ +// this is the JSR url for the test server +import { add } from "http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts"; + +console.log(add(1, 2)); diff --git a/tests/specs/permission/allow_import/cache.out b/tests/specs/permission/allow_import/cache.out new file mode 100644 index 0000000000..da40ede3a8 --- /dev/null +++ b/tests/specs/permission/allow_import/cache.out @@ -0,0 +1,2 @@ +error: Requires import access to "example.com:443", run again with the --allow-import flag + at file:///[WILDLINE]/main.ts:1:8 diff --git a/tests/specs/permission/allow_import/check.out b/tests/specs/permission/allow_import/check.out new file mode 100644 index 0000000000..da40ede3a8 --- /dev/null +++ b/tests/specs/permission/allow_import/check.out @@ -0,0 +1,2 @@ +error: Requires import access to "example.com:443", run again with the --allow-import flag + at file:///[WILDLINE]/main.ts:1:8 diff --git a/tests/specs/permission/allow_import/compile.out b/tests/specs/permission/allow_import/compile.out new file mode 100644 index 0000000000..da40ede3a8 --- /dev/null +++ b/tests/specs/permission/allow_import/compile.out @@ -0,0 +1,2 @@ +error: Requires import access to "example.com:443", run again with the --allow-import flag + at file:///[WILDLINE]/main.ts:1:8 diff --git a/tests/specs/permission/allow_import/doc.out b/tests/specs/permission/allow_import/doc.out new file mode 100644 index 0000000000..6a57eafe69 --- /dev/null +++ b/tests/specs/permission/allow_import/doc.out @@ -0,0 +1,7 @@ +Warning Requires import access to "localhost:4545", run again with the --allow-import flag + at file:///[WILDLINE]/doc.ts:1:15 +Defined in file:///[WILDLINE]/doc.ts:3:1 + +class Test + + diff --git a/tests/specs/permission/allow_import/doc.ts b/tests/specs/permission/allow_import/doc.ts new file mode 100644 index 0000000000..622506c9bf --- /dev/null +++ b/tests/specs/permission/allow_import/doc.ts @@ -0,0 +1,3 @@ +export * from "http://localhost:4545/add.ts"; + +export class Test {} diff --git a/tests/specs/permission/allow_import/doc_allowed.out b/tests/specs/permission/allow_import/doc_allowed.out new file mode 100644 index 0000000000..61886be383 --- /dev/null +++ b/tests/specs/permission/allow_import/doc_allowed.out @@ -0,0 +1,10 @@ +Download http://localhost:4545/add.ts +Defined in http://localhost:4545/add.ts:1:1 + +function add(a: number, b: number): number + +Defined in file:///[WILDLINE]/doc.ts:3:1 + +class Test + + diff --git a/tests/specs/permission/allow_import/info.out b/tests/specs/permission/allow_import/info.out new file mode 100644 index 0000000000..2e364ff278 --- /dev/null +++ b/tests/specs/permission/allow_import/info.out @@ -0,0 +1,7 @@ +local: [WILDLINE]main.ts +type: TypeScript +dependencies: 0 unique +size: [WILDLINE] + +file:///[WILDLINE]/main.ts ([WILDLINE]) +└── https://example.com/malicious_string (not capable, requires --allow-import) diff --git a/tests/specs/permission/allow_import/main.ts b/tests/specs/permission/allow_import/main.ts new file mode 100644 index 0000000000..8dfed682e4 --- /dev/null +++ b/tests/specs/permission/allow_import/main.ts @@ -0,0 +1 @@ +import "https://example.com/malicious_string"; diff --git a/tests/specs/permission/allow_import/run.out b/tests/specs/permission/allow_import/run.out new file mode 100644 index 0000000000..da40ede3a8 --- /dev/null +++ b/tests/specs/permission/allow_import/run.out @@ -0,0 +1,2 @@ +error: Requires import access to "example.com:443", run again with the --allow-import flag + at file:///[WILDLINE]/main.ts:1:8 diff --git a/tests/specs/permission/allow_import/serve.out b/tests/specs/permission/allow_import/serve.out new file mode 100644 index 0000000000..da40ede3a8 --- /dev/null +++ b/tests/specs/permission/allow_import/serve.out @@ -0,0 +1,2 @@ +error: Requires import access to "example.com:443", run again with the --allow-import flag + at file:///[WILDLINE]/main.ts:1:8 diff --git a/tests/specs/permission/allow_import/success.ts b/tests/specs/permission/allow_import/success.ts new file mode 100644 index 0000000000..e83ab4b9b5 --- /dev/null +++ b/tests/specs/permission/allow_import/success.ts @@ -0,0 +1,3 @@ +import { add } from "http://localhost:4545/add.ts"; + +console.log(add(1, 2)); diff --git a/tests/specs/permission/allow_import_jsx/__test__.jsonc b/tests/specs/permission/allow_import_jsx/__test__.jsonc new file mode 100644 index 0000000000..cb80deb72c --- /dev/null +++ b/tests/specs/permission/allow_import_jsx/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run main.tsx", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/permission/allow_import_jsx/deno.jsonc b/tests/specs/permission/allow_import_jsx/deno.jsonc new file mode 100644 index 0000000000..311409ea37 --- /dev/null +++ b/tests/specs/permission/allow_import_jsx/deno.jsonc @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "http://localhost:4545/jsx" + } +} diff --git a/tests/specs/permission/allow_import_jsx/main.out b/tests/specs/permission/allow_import_jsx/main.out new file mode 100644 index 0000000000..fda79f89d2 --- /dev/null +++ b/tests/specs/permission/allow_import_jsx/main.out @@ -0,0 +1,3 @@ +[# do not allow exfiltrating data via the deno.json] +error: Requires import access to "localhost:4545", run again with the --allow-import flag + at file:///[WILDLINE]/main.tsx:1:1 diff --git a/tests/specs/permission/allow_import_jsx/main.tsx b/tests/specs/permission/allow_import_jsx/main.tsx new file mode 100644 index 0000000000..f03d10c5b0 --- /dev/null +++ b/tests/specs/permission/allow_import_jsx/main.tsx @@ -0,0 +1,3 @@ +export function Component() { + return
Hi
; +} diff --git a/tests/specs/permission/allow_import_main_module/__test__.jsonc b/tests/specs/permission/allow_import_main_module/__test__.jsonc new file mode 100644 index 0000000000..c0a92bfc31 --- /dev/null +++ b/tests/specs/permission/allow_import_main_module/__test__.jsonc @@ -0,0 +1,17 @@ +{ + // won't need --allow-import because it's implied from the main module + "tests": { + "run": { + "args": "run http://localhost:4545/run/002_hello.ts", + "output": "Download http://localhost:4545/run/002_hello.ts\nHello World\n" + }, + "cache": { + "args": "cache http://localhost:4545/run/002_hello.ts", + "output": "Download http://localhost:4545/run/002_hello.ts\n" + }, + "check": { + "args": "check http://localhost:4545/run/002_hello.ts", + "output": "Download http://localhost:4545/run/002_hello.ts\nCheck http://localhost:4545/run/002_hello.ts\n" + } + } +} diff --git a/tests/specs/permission/allow_import_not_on_redirect/__test__.jsonc b/tests/specs/permission/allow_import_not_on_redirect/__test__.jsonc new file mode 100644 index 0000000000..b05d0c0cbd --- /dev/null +++ b/tests/specs/permission/allow_import_not_on_redirect/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --allow-import=localhost:4547 --quiet --reload main.js", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/permission/allow_import_not_on_redirect/main.js b/tests/specs/permission/allow_import_not_on_redirect/main.js new file mode 100644 index 0000000000..226a6b622c --- /dev/null +++ b/tests/specs/permission/allow_import_not_on_redirect/main.js @@ -0,0 +1,2 @@ +import { value } from "http://localhost:4547/redirects/redirect3.js"; +console.log(value); diff --git a/tests/specs/permission/allow_import_not_on_redirect/main.out b/tests/specs/permission/allow_import_not_on_redirect/main.out new file mode 100644 index 0000000000..3cab01e14c --- /dev/null +++ b/tests/specs/permission/allow_import_not_on_redirect/main.out @@ -0,0 +1,2 @@ +error: Requires import access to "localhost:4545", run again with the --allow-import flag + at file:///[WILDLINE]/main.js:1:23 diff --git a/tests/specs/permission/allow_import_worker/__test__.jsonc b/tests/specs/permission/allow_import_worker/__test__.jsonc new file mode 100644 index 0000000000..21ac653033 --- /dev/null +++ b/tests/specs/permission/allow_import_worker/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tests": { + "allowed": { + "args": "run -A --unstable-worker-options --quiet main.ts", + "output": "1\n" + }, + "denied": { + "args": "run -A --unstable-worker-options --quiet main_denied.ts", + "output": "denied.out", + "exitCode": 1 + } + } +} diff --git a/tests/specs/permission/allow_import_worker/denied.out b/tests/specs/permission/allow_import_worker/denied.out new file mode 100644 index 0000000000..6e4dcaee09 --- /dev/null +++ b/tests/specs/permission/allow_import_worker/denied.out @@ -0,0 +1,7 @@ +error: Uncaught (in worker "") (in promise) TypeError: JSR package manifest for '@std/assert' failed to load. Requires import access to "127.0.0.1:4250", run again with the --allow-import flag +await import(specifier); +^ + at async file:///[WILDLINE] +error: Uncaught (in promise) Error: Unhandled error in child worker. + at [WILDLINE] + at [WILDLINE] \ No newline at end of file diff --git a/tests/specs/permission/allow_import_worker/main.ts b/tests/specs/permission/allow_import_worker/main.ts new file mode 100644 index 0000000000..af65c40658 --- /dev/null +++ b/tests/specs/permission/allow_import_worker/main.ts @@ -0,0 +1,8 @@ +new Worker(import.meta.resolve("./worker.ts"), { + type: "module", + deno: { + permissions: { + import: ["127.0.0.1:4250"], + }, + }, +}); diff --git a/tests/specs/permission/allow_import_worker/main_denied.ts b/tests/specs/permission/allow_import_worker/main_denied.ts new file mode 100644 index 0000000000..e0d5a1d457 --- /dev/null +++ b/tests/specs/permission/allow_import_worker/main_denied.ts @@ -0,0 +1,8 @@ +new Worker(import.meta.resolve("./worker.ts"), { + type: "module", + deno: { + permissions: { + import: [], + }, + }, +}); diff --git a/tests/specs/permission/allow_import_worker/worker.ts b/tests/specs/permission/allow_import_worker/worker.ts new file mode 100644 index 0000000000..fd5757ba8d --- /dev/null +++ b/tests/specs/permission/allow_import_worker/worker.ts @@ -0,0 +1,4 @@ +const specifier = "jsr:@std/assert/assert"; +await import(specifier); +console.log(1); +close(); diff --git a/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc b/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc new file mode 100644 index 0000000000..fac0d928ac --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "envs": { + "DYLD_FALLBACK_LIBRARY_PATH": "", + "LD_LIBRARY_PATH": "" + }, + "args": "run --allow-run --deny-run=deno --allow-read main.ts", + "output": "main.out" +} diff --git a/tests/specs/permission/deny_run_binary_absolute_path/main.out b/tests/specs/permission/deny_run_binary_absolute_path/main.out new file mode 100644 index 0000000000..45b2283879 --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/main.out @@ -0,0 +1,8 @@ +NotCapable: Requires run access to "deno", run again with the --allow-run flag + at [WILDCARD] { + name: "NotCapable" +} +NotCapable: Requires run access to "[WILDLINE]", run again with the --allow-run flag + at [WILDCARD] { + name: "NotCapable" +} diff --git a/tests/specs/permission/deny_run_binary_absolute_path/main.ts b/tests/specs/permission/deny_run_binary_absolute_path/main.ts new file mode 100644 index 0000000000..eca5e5a33e --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/main.ts @@ -0,0 +1,15 @@ +try { + new Deno.Command("deno", { + args: ["--version"], + }).outputSync(); +} catch (err) { + console.error(err); +} + +try { + new Deno.Command(Deno.execPath(), { + args: ["--version"], + }).outputSync(); +} catch (err) { + console.error(err); +} diff --git a/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out new file mode 100644 index 0000000000..7144e088ce --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out @@ -0,0 +1,4 @@ +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] diff --git a/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts new file mode 100644 index 0000000000..28661973cf --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts @@ -0,0 +1,52 @@ +Deno.mkdirSync("subdir"); + +// async file +{ + const path = await Deno.makeTempFile({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} +// sync file +{ + const path = Deno.makeTempFileSync({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} + +// async dir +{ + const path = await Deno.makeTempDir({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} + +// sync dir +{ + const path = Deno.makeTempDirSync({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} diff --git a/tests/specs/permission/make_temp_write_perm/__test__.jsonc b/tests/specs/permission/make_temp_write_perm/__test__.jsonc new file mode 100644 index 0000000000..80a503215e --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/__test__.jsonc @@ -0,0 +1,15 @@ +{ + "tempDir": true, + "tests": { + "reduced_perms": { + // this should not expose the full directory + "args": "run --quiet --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts", + "output": "056_make_temp_file_write_perm.out" + }, + "all_perms": { + // this will work the same as above + "args": "run --quiet -A 056_make_temp_file_write_perm.ts", + "output": "056_make_temp_file_write_perm.out" + } + } +} diff --git a/tests/specs/permission/path_not_permitted/__test__.jsonc b/tests/specs/permission/path_not_permitted/__test__.jsonc new file mode 100644 index 0000000000..f10e8b389e --- /dev/null +++ b/tests/specs/permission/path_not_permitted/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "envs": { + "LD_LIBRARY_PATH": "", + "LD_PRELOAD": "", + "DYLD_FALLBACK_LIBRARY_PATH": "" + }, + "args": "run -A main.ts", + "output": "main.out" +} diff --git a/tests/specs/permission/path_not_permitted/main.out b/tests/specs/permission/path_not_permitted/main.out new file mode 100644 index 0000000000..02e5b937f9 --- /dev/null +++ b/tests/specs/permission/path_not_permitted/main.out @@ -0,0 +1,11 @@ +Running... +NotCapable: Requires run access to "binary", run again with the --allow-run flag + [WILDCARD] + at file:///[WILDLINE]/sub.ts:15:5 { + name: "NotCapable" +} +NotCapable: Requires run access to "binary", run again with the --allow-run flag + [WILDCARD] + at file:///[WILDLINE]/sub.ts:23:22 { + name: "NotCapable" +} diff --git a/tests/specs/permission/path_not_permitted/main.ts b/tests/specs/permission/path_not_permitted/main.ts new file mode 100644 index 0000000000..0587db916b --- /dev/null +++ b/tests/specs/permission/path_not_permitted/main.ts @@ -0,0 +1,21 @@ +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; +Deno.copyFileSync(Deno.execPath(), binaryName); + +console.log("Running..."); +new Deno.Command( + Deno.execPath(), + { + args: [ + "run", + "--allow-write", + "--allow-read", + `--allow-run=binary`, + "sub.ts", + ], + env: { + PATH: Deno.cwd(), + }, + stderr: "inherit", + stdout: "inherit", + }, +).outputSync(); diff --git a/tests/specs/permission/path_not_permitted/sub.ts b/tests/specs/permission/path_not_permitted/sub.ts new file mode 100644 index 0000000000..e501b5b7b6 --- /dev/null +++ b/tests/specs/permission/path_not_permitted/sub.ts @@ -0,0 +1,34 @@ +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; +const pathSep = Deno.build.os === "windows" ? "\\" : "/"; + +Deno.mkdirSync("subdir"); +Deno.copyFileSync(binaryName, "subdir/" + binaryName); + +try { + const commandResult = new Deno.Command( + "binary", + { + env: { "PATH": Deno.cwd() + pathSep + "subdir" }, + stdout: "inherit", + stderr: "inherit", + }, + ).outputSync(); + + console.log(commandResult.code); +} catch (err) { + console.log(err); +} + +try { + const child = Deno.run( + { + cmd: ["binary"], + env: { "PATH": Deno.cwd() + pathSep + "subdir" }, + stdout: "inherit", + stderr: "inherit", + }, + ); + console.log((await child.status()).code); +} catch (err) { + console.log(err); +} diff --git a/tests/specs/permission/special/main.js b/tests/specs/permission/special/main.js index 59ec4f7b50..721e0c392c 100644 --- a/tests/specs/permission/special/main.js +++ b/tests/specs/permission/special/main.js @@ -7,10 +7,10 @@ const testCases = [ [["darwin", "linux"], null, "/etc/passwd"], [["windows"], null, "\\\\.\\nul"], // Denied, requires `--allow-all` - [["darwin", "linux"], /PermissionDenied/, "/dev/ptmx"], - [["linux"], /PermissionDenied/, "/proc/self/environ"], - [["linux"], /PermissionDenied/, "/proc/self/mem"], - [["windows"], /PermissionDenied/, "\\\\.\\PhysicalDrive0"], + [["darwin", "linux"], /NotCapable/, "/dev/ptmx"], + [["linux"], /NotCapable/, "/proc/self/environ"], + [["linux"], /NotCapable/, "/proc/self/mem"], + [["windows"], /NotCapable/, "\\\\.\\PhysicalDrive0"], ]; const os = Deno.build.os; diff --git a/tests/specs/permission/write_allow_binary/__test__.jsonc b/tests/specs/permission/write_allow_binary/__test__.jsonc new file mode 100644 index 0000000000..a47fed572d --- /dev/null +++ b/tests/specs/permission/write_allow_binary/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run -A main.ts", + "output": "main.out" +} diff --git a/tests/specs/permission/write_allow_binary/main.out b/tests/specs/permission/write_allow_binary/main.out new file mode 100644 index 0000000000..0432ee6c92 --- /dev/null +++ b/tests/specs/permission/write_allow_binary/main.out @@ -0,0 +1,6 @@ +Running... +error: Uncaught (in promise) NotCapable: Requires write access to "binary[WILDLINE]", run again with the --allow-write flag +Deno.writeTextFileSync(binaryName, ""); + ^ + at [WILDCARD] + at file:///[WILDLINE]sub.ts:3:6 diff --git a/tests/specs/permission/write_allow_binary/main.ts b/tests/specs/permission/write_allow_binary/main.ts new file mode 100644 index 0000000000..73deeab9a7 --- /dev/null +++ b/tests/specs/permission/write_allow_binary/main.ts @@ -0,0 +1,14 @@ +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; +Deno.copyFileSync(Deno.execPath(), binaryName); + +console.log("Running..."); +const result = new Deno.Command( + Deno.execPath(), + { + args: ["run", "--allow-write", `--allow-run=./${binaryName}`, "sub.ts"], + stderr: "inherit", + stdout: "inherit", + }, +).outputSync(); + +console.assert(result.code == 1, "Expected failure"); diff --git a/tests/specs/permission/write_allow_binary/sub.ts b/tests/specs/permission/write_allow_binary/sub.ts new file mode 100644 index 0000000000..e865597b15 --- /dev/null +++ b/tests/specs/permission/write_allow_binary/sub.ts @@ -0,0 +1,3 @@ +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; + +Deno.writeTextFileSync(binaryName, ""); diff --git a/tests/specs/publish/banned_triple_slash_directives/publish.out b/tests/specs/publish/banned_triple_slash_directives/publish.out index f1827538ae..ab5db6f6e1 100644 --- a/tests/specs/publish/banned_triple_slash_directives/publish.out +++ b/tests/specs/publish/banned_triple_slash_directives/publish.out @@ -1,6 +1,5 @@ Check file:///[WILDLINE]/mod.ts Checking for slow types in the public API... -Check file:///[WILDLINE]/mod.ts error[banned-triple-slash-directives]: triple slash directives that modify globals are not allowed --> [WILDLINE]mod.ts:1:1 | diff --git a/tests/specs/publish/bare_node_builtins/bare_node_builtins.out b/tests/specs/publish/bare_node_builtins/bare_node_builtins.out index 8646ef540f..6baedd906f 100644 --- a/tests/specs/publish/bare_node_builtins/bare_node_builtins.out +++ b/tests/specs/publish/bare_node_builtins/bare_node_builtins.out @@ -1,7 +1,11 @@ -Warning: Resolving "url" as "node:url" at file:///[WILDLINE]/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix. -Warning: Resolving "url" as "node:url" at file:///[WILDLINE]/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix. -Download http://localhost:4260/@types/node -Download http://localhost:4260/@types/node/node-18.16.19.tgz +Warning Resolving "url" as "node:url" at file:///[WILDLINE]/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix. +Warning Resolving "url" as "node:url" at file:///[WILDLINE]/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix. +[UNORDERED_START] +Download http://localhost:4260/@types%2fnode +Download http://localhost:4260/undici-types +Download http://localhost:4260/@types/node/node-22.5.4.tgz +Download http://localhost:4260/undici-types/undici-types-6.19.8.tgz +[UNORDERED_END] Check file:///[WILDLINE]/mod.ts Checking for slow types in the public API... Check file:///[WILDLINE]/mod.ts diff --git a/tests/specs/publish/byonm_with_package_json/__test__.jsonc b/tests/specs/publish/byonm_with_package_json/__test__.jsonc index 77c23bae12..98dc95fe11 100644 --- a/tests/specs/publish/byonm_with_package_json/__test__.jsonc +++ b/tests/specs/publish/byonm_with_package_json/__test__.jsonc @@ -1,7 +1,4 @@ { - "envs": { - "DENO_FUTURE": "1" - }, "tempDir": true, "steps": [{ "args": "install", diff --git a/tests/specs/publish/invalid_import/invalid_import.out b/tests/specs/publish/invalid_import/invalid_import.out index 929fc72cd3..6914dc51e0 100644 --- a/tests/specs/publish/invalid_import/invalid_import.out +++ b/tests/specs/publish/invalid_import/invalid_import.out @@ -1,10 +1,7 @@ -Download http://localhost:4545/welcome.ts -Download http://localhost:4545/echo.ts +[# notice that the remote module is not downloaded here. This is so we do not need to add an --allow-import permission here] Download http://localhost:4260/chalk Download http://localhost:4260/chalk/chalk-5.0.1.tgz -Check file:///[WILDCARD]/mod.ts Checking for slow types in the public API... -Check file://[WILDCARD]mod.ts error[invalid-external-import]: invalid import to a non-JSR 'http' specifier --> [WILDCARD]mod.ts:1:8 | diff --git a/tests/specs/publish/invalid_import_esm_sh_suggestion/invalid_import_esm_sh_suggestion.out b/tests/specs/publish/invalid_import_esm_sh_suggestion/invalid_import_esm_sh_suggestion.out index a7235cbf16..b0a544df89 100644 --- a/tests/specs/publish/invalid_import_esm_sh_suggestion/invalid_import_esm_sh_suggestion.out +++ b/tests/specs/publish/invalid_import_esm_sh_suggestion/invalid_import_esm_sh_suggestion.out @@ -1,7 +1,4 @@ -[WILDCARD] -Check file:///[WILDCARD]/mod.ts Checking for slow types in the public API... -Check file:///[WILDCARD]mod.ts error[invalid-external-import]: invalid import to a non-JSR 'http' specifier --> [WILDCARD]mod.ts:1:8 | diff --git a/tests/specs/publish/missing_constraint/publish.out b/tests/specs/publish/missing_constraint/publish.out index 601035b059..7d2c293c0e 100644 --- a/tests/specs/publish/missing_constraint/publish.out +++ b/tests/specs/publish/missing_constraint/publish.out @@ -1,6 +1,22 @@ -[WILDCARD] -Checking for slow types in the public API... +[UNORDERED_START] +Download http://127.0.0.1:4250/@denotest/add/meta.json +Download http://127.0.0.1:4250/@denotest/deps/meta.json +Download http://localhost:4260/@denotest%2fesm-basic +Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/deps/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/module-graph/meta.json +Download http://127.0.0.1:4250/@denotest/no-module-graph/meta.json +Download http://127.0.0.1:4250/@denotest/module-graph/1.4.0_meta.json +Download http://127.0.0.1:4250/@denotest/no-module-graph/0.1.1_meta.json +Download http://127.0.0.1:4250/@denotest/no-module-graph/0.1.1/mod.ts +Download http://127.0.0.1:4250/@denotest/no-module-graph/0.1.1/TestClass.ts +Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts +Download http://127.0.0.1:4250/@denotest/deps/1.0.0/mod.ts +Download http://127.0.0.1:4250/@denotest/module-graph/1.4.0/other.ts +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +[UNORDERED_END] Check file:///[WILDLINE]/mod.ts +Checking for slow types in the public API... error[missing-constraint]: specifier 'jsr:@denotest/add' is missing a version constraint --> [WILDLINE]mod.ts:[WILDLINE] | diff --git a/tests/specs/publish/missing_constraint_jsx_import_source/mod.out b/tests/specs/publish/missing_constraint_jsx_import_source/mod.out index d1da06be81..fa06d8c389 100644 --- a/tests/specs/publish/missing_constraint_jsx_import_source/mod.out +++ b/tests/specs/publish/missing_constraint_jsx_import_source/mod.out @@ -1,6 +1,13 @@ -[WILDCARD] +[UNORDERED_START] +Download http://localhost:4260/preact +Download http://localhost:4260/preact-render-to-string +Download http://localhost:4260/pretty-format +Download http://localhost:4260/preact-render-to-string/preact-render-to-string-6.4.0.tgz +Download http://localhost:4260/preact/preact-10.19.6.tgz +Download http://localhost:4260/pretty-format/pretty-format-3.8.0.tgz +[UNORDERED_END] +Check file:///[WILDLINE]/mod.ts Checking for slow types in the public API... -Check file:///[WILDCARD]/mod.ts error[missing-constraint]: specifier 'npm:preact/jsx-runtime' is missing a version constraint --> [WILDLINE] = hint: specify a version constraint for the specifier diff --git a/tests/specs/publish/node_specifier/node_specifier.out b/tests/specs/publish/node_specifier/node_specifier.out index 3c0bc48d8c..0ba14043df 100644 --- a/tests/specs/publish/node_specifier/node_specifier.out +++ b/tests/specs/publish/node_specifier/node_specifier.out @@ -1,5 +1,9 @@ -Download http://localhost:4260/@types/node -Download http://localhost:4260/@types/node/node-[WILDCARD].tgz +[UNORDERED_START] +Download http://localhost:4260/@types%2fnode +Download http://localhost:4260/undici-types +Download http://localhost:4260/@types/node/node-22.5.4.tgz +Download http://localhost:4260/undici-types/undici-types-6.19.8.tgz +[UNORDERED_END] Check file:///[WILDCARD]/mod.ts Checking for slow types in the public API... Check file:///[WILDCARD]/publish/node_specifier/mod.ts diff --git a/tests/specs/publish/npm_workspace_jsr_pkg_with_npm_dep/__test__.jsonc b/tests/specs/publish/npm_workspace_jsr_pkg_with_npm_dep/__test__.jsonc index 8819e630dd..cee2fe12d9 100644 --- a/tests/specs/publish/npm_workspace_jsr_pkg_with_npm_dep/__test__.jsonc +++ b/tests/specs/publish/npm_workspace_jsr_pkg_with_npm_dep/__test__.jsonc @@ -1,4 +1,7 @@ { + // TODO(2.0): these tests are actually broken now, some code needs + // to be updated to make them work + "ignore": true, "tests": { "dep_and_workspace_dep": { "args": "publish --dry-run --no-check --log-level=debug", diff --git a/tests/specs/publish/package_json/deno.json b/tests/specs/publish/package_json/deno.json index 6e2826ef5e..949be1f270 100644 --- a/tests/specs/publish/package_json/deno.json +++ b/tests/specs/publish/package_json/deno.json @@ -4,5 +4,5 @@ "exports": { ".": "./mod.ts" }, - "nodeModulesDir": false + "nodeModulesDir": "none" } diff --git a/tests/specs/publish/prefer_fast_check_graph/main.out b/tests/specs/publish/prefer_fast_check_graph/main.out index 64296206f0..dd7d052c92 100644 --- a/tests/specs/publish/prefer_fast_check_graph/main.out +++ b/tests/specs/publish/prefer_fast_check_graph/main.out @@ -1,7 +1,4 @@ -[WILDCARD] -Check [WILDLINE]/tests/specs/publish/prefer_fast_check_graph/mod.ts Checking for slow types in the public API... -Check [WILDLINE]/tests/specs/publish/prefer_fast_check_graph/mod.ts error[invalid-external-import]: invalid import to a non-JSR 'https' specifier --> [WILDLINE]deps.ts:1:15 | diff --git a/tests/specs/remove/alias/__test__.jsonc b/tests/specs/remove/alias/__test__.jsonc new file mode 100644 index 0000000000..a0c98edd90 --- /dev/null +++ b/tests/specs/remove/alias/__test__.jsonc @@ -0,0 +1,29 @@ +{ + "tempDir": true, + "tests": { + "alias_with_pkg": { + "steps": [{ + "args": "remove my-alias@npm:@denotest/add", + "output": "[WILDCARD]" + }, { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + }] + }, + "alias": { + "steps": [{ + "args": "remove my-alias", + "output": "[WILDCARD]" + }, { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "package.json.out" + }] + } + } +} diff --git a/tests/specs/remove/alias/package.json b/tests/specs/remove/alias/package.json new file mode 100644 index 0000000000..b6326e8bfb --- /dev/null +++ b/tests/specs/remove/alias/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "my-alias": "npm:@denotest/add@^1.0.0" + } +} diff --git a/tests/specs/remove/alias/package.json.out b/tests/specs/remove/alias/package.json.out new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/remove/alias/package.json.out @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/remove/basic/__test__.jsonc b/tests/specs/remove/basic/__test__.jsonc index 2f4d82c88f..3ca396f8ba 100644 --- a/tests/specs/remove/basic/__test__.jsonc +++ b/tests/specs/remove/basic/__test__.jsonc @@ -1,16 +1,19 @@ { "tempDir": true, "steps": [{ - "args": ["add", "@std/assert", "@std/http"], + "args": ["add", "jsr:@std/assert", "jsr:@std/http"], "output": "add.out" }, { "args": ["eval", "console.log(Deno.readTextFileSync('deno.lock').trim())"], "output": "add_lock.out" }, { - "args": ["remove", "@std/assert", "@std/http"], + "args": ["remove", "jsr:@std/assert", "@std/http"], "output": "rm.out" }, { "args": ["eval", "console.log(Deno.readTextFileSync('deno.lock').trim())"], "output": "remove_lock.out" + }, { + "args": ["eval", "console.log(Deno.readTextFileSync('deno.json').trim())"], + "output": "{\n}\n" }] } diff --git a/tests/specs/remove/basic/add.out b/tests/specs/remove/basic/add.out index a93b0ab528..75848b7c6f 100644 --- a/tests/specs/remove/basic/add.out +++ b/tests/specs/remove/basic/add.out @@ -1,9 +1,9 @@ Created deno.json configuration file. -Add jsr:@std/assert@1.0.0 -Add jsr:@std/http@1.0.0 [UNORDERED_START] -Download http://127.0.0.1:4250/@std/http/1.0.0_meta.json -Download http://127.0.0.1:4250/@std/assert/1.0.0_meta.json +Add jsr:@std/http@1.0.0 +Add jsr:@std/assert@1.0.0 +[UNORDERED_END] +[UNORDERED_START] Download http://127.0.0.1:4250/@std/http/1.0.0/mod.ts Download http://127.0.0.1:4250/@std/assert/1.0.0/mod.ts Download http://127.0.0.1:4250/@std/assert/1.0.0/assert_equals.ts diff --git a/tests/specs/remove/basic/add_lock.out b/tests/specs/remove/basic/add_lock.out index cda0fc34a2..1f6589380e 100644 --- a/tests/specs/remove/basic/add_lock.out +++ b/tests/specs/remove/basic/add_lock.out @@ -1,24 +1,21 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@std/assert@^1.0.0": "jsr:@std/assert@1.0.0", - "jsr:@std/http@^1.0.0": "jsr:@std/http@1.0.0" + "version": "4", + "specifiers": { + "jsr:@std/assert@1": "1.0.0", + "jsr:@std/http@1": "1.0.0" + }, + "jsr": { + "@std/assert@1.0.0": { + "integrity": "[WILDLINE]" }, - "jsr": { - "@std/assert@1.0.0": { - "integrity": "[WILDLINE]" - }, - "@std/http@1.0.0": { - "integrity": "[WILDLINE]" - } + "@std/http@1.0.0": { + "integrity": "[WILDLINE]" } }, - "remote": {}, "workspace": { "dependencies": [ - "jsr:@std/assert@^1.0.0", - "jsr:@std/http@^1.0.0" + "jsr:@std/assert@1", + "jsr:@std/http@1" ] } } diff --git a/tests/specs/remove/basic/remove_lock.out b/tests/specs/remove/basic/remove_lock.out index 37f10ce95e..a39b837e98 100644 --- a/tests/specs/remove/basic/remove_lock.out +++ b/tests/specs/remove/basic/remove_lock.out @@ -1,4 +1,3 @@ { - "version": "3", - "remote": {} + "version": "4" } diff --git a/tests/specs/remove/package_json/__test__.jsonc b/tests/specs/remove/package_json/__test__.jsonc new file mode 100644 index 0000000000..c51b00d0fc --- /dev/null +++ b/tests/specs/remove/package_json/__test__.jsonc @@ -0,0 +1,27 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "remove @denotest/add", + "output": "rm_add.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "rm_add_package.json.out" + }, + { + "args": "remove @denotest/esm-basic", + "output": "rm_esm_basic.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('package.json').trim())" + ], + "output": "rm_esm_basic_package.json.out" + } + ] +} diff --git a/tests/specs/remove/package_json/package.json b/tests/specs/remove/package_json/package.json new file mode 100644 index 0000000000..6de96bc201 --- /dev/null +++ b/tests/specs/remove/package_json/package.json @@ -0,0 +1,4 @@ +{ + "dependencies": { "@denotest/add": "^1.0.0" }, + "devDependencies": { "@denotest/esm-basic": "^1.0.0" } +} diff --git a/tests/specs/remove/package_json/rm_add.out b/tests/specs/remove/package_json/rm_add.out new file mode 100644 index 0000000000..af72f5f99d --- /dev/null +++ b/tests/specs/remove/package_json/rm_add.out @@ -0,0 +1,4 @@ +Removed @denotest/add +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/specs/remove/package_json/rm_add_package.json.out b/tests/specs/remove/package_json/rm_add_package.json.out new file mode 100644 index 0000000000..d5ca56e004 --- /dev/null +++ b/tests/specs/remove/package_json/rm_add_package.json.out @@ -0,0 +1,3 @@ +{ + "devDependencies": { "@denotest/esm-basic": "^1.0.0" } +} diff --git a/tests/specs/remove/package_json/rm_esm_basic.out b/tests/specs/remove/package_json/rm_esm_basic.out new file mode 100644 index 0000000000..86ad9e28da --- /dev/null +++ b/tests/specs/remove/package_json/rm_esm_basic.out @@ -0,0 +1 @@ +Removed @denotest/esm-basic diff --git a/tests/specs/remove/package_json/rm_esm_basic_package.json.out b/tests/specs/remove/package_json/rm_esm_basic_package.json.out new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/remove/package_json/rm_esm_basic_package.json.out @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/repl/console_log/093_console_log_format.js b/tests/specs/repl/console_log/093_console_log_format.js new file mode 100644 index 0000000000..15022411ca --- /dev/null +++ b/tests/specs/repl/console_log/093_console_log_format.js @@ -0,0 +1,16 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +class Frac { + constructor(num, den) { + this.num = num; + this.den = den; + } + [Symbol.toPrimitive]() { + return this.num / this.den; + } + display() { + const result = this.num / this.den; + process.stdout.write(`${result}`); + } +} +const f = new Frac(1, 2); +f.display(); diff --git a/tests/specs/repl/console_log/093_console_log_format.out b/tests/specs/repl/console_log/093_console_log_format.out new file mode 100644 index 0000000000..ea2303bc03 --- /dev/null +++ b/tests/specs/repl/console_log/093_console_log_format.out @@ -0,0 +1 @@ +0.5 \ No newline at end of file diff --git a/tests/specs/repl/console_log/__test__.jsonc b/tests/specs/repl/console_log/__test__.jsonc new file mode 100644 index 0000000000..641bc1f68a --- /dev/null +++ b/tests/specs/repl/console_log/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A --quiet 093_console_log_format.js", + "output": "093_console_log_format.out" +} diff --git a/tests/specs/run/045_proxy/proxy_test.ts b/tests/specs/run/045_proxy/proxy_test.ts index 70781f97d9..22115a3aa8 100644 --- a/tests/specs/run/045_proxy/proxy_test.ts +++ b/tests/specs/run/045_proxy/proxy_test.ts @@ -108,7 +108,6 @@ async function testFetchProgrammaticProxy() { "--quiet", "--reload", "--allow-net=localhost:4545,localhost:4555", - "--unstable", "programmatic_proxy_client.ts", ], }).output(); diff --git a/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc b/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc new file mode 100644 index 0000000000..3e5d86adf4 --- /dev/null +++ b/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "envs": { + "DYLD_FALLBACK_LIBRARY_PATH": "", + "LD_LIBRARY_PATH": "" + }, + "args": "run --quiet -A main.ts", + "output": "main.out" +} diff --git a/tests/testdata/allow_run_allowlist_resolution.ts.out b/tests/specs/run/allow_run_allowlist_resolution/main.out similarity index 66% rename from tests/testdata/allow_run_allowlist_resolution.ts.out rename to tests/specs/run/allow_run_allowlist_resolution/main.out index 16ba6754a9..b494bb52f2 100644 --- a/tests/testdata/allow_run_allowlist_resolution.ts.out +++ b/tests/specs/run/allow_run_allowlist_resolution/main.out @@ -1,15 +1,15 @@ -PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "granted", onchange: null } - -PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "prompt", onchange: null } -PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "prompt", onchange: null } - PermissionStatus { state: "granted", onchange: null } PermissionStatus { state: "granted", onchange: null } PermissionStatus { state: "prompt", onchange: null } PermissionStatus { state: "granted", onchange: null } - +--- +Info Failed to resolve 'binary' for allow-run: cannot find binary path +PermissionStatus { state: "prompt", onchange: null } +PermissionStatus { state: "prompt", onchange: null } +PermissionStatus { state: "prompt", onchange: null } +PermissionStatus { state: "prompt", onchange: null } +--- +PermissionStatus { state: "granted", onchange: null } +PermissionStatus { state: "granted", onchange: null } +PermissionStatus { state: "prompt", onchange: null } +PermissionStatus { state: "granted", onchange: null } diff --git a/tests/specs/run/allow_run_allowlist_resolution/main.ts b/tests/specs/run/allow_run_allowlist_resolution/main.ts new file mode 100644 index 0000000000..e43e0b5da0 --- /dev/null +++ b/tests/specs/run/allow_run_allowlist_resolution/main.ts @@ -0,0 +1,72 @@ +// Testing the following: +// | `deno run --allow-run=binary` | `which path == "/usr/bin/binary"` at startup | `which path != "/usr/bin/binary"` at startup | +// |---------------------------------------|----------------------------------------------|--------------------------------------------| +// | **`Deno.Command("binary")`** | :white_check_mark: | :white_check_mark: | +// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :x: | +// | `deno run --allow-run=/usr/bin/binary | `which path == "/usr/bin/binary"` at runtime | `which path != "/usr/bin/binary"` at runtime | +// |---------------------------------------|----------------------------------------------|--------------------------------------------| +// | **`Deno.Command("binary")`** | :white_check_mark: | :x: | +// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :white_check_mark: | + +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; +const pathSep = Deno.build.os === "windows" ? "\\" : "/"; +const cwd = Deno.cwd(); +const execPathParent = `${Deno.cwd()}${pathSep}sub`; +const execPath = `${execPathParent}${pathSep}${binaryName}`; + +Deno.mkdirSync(execPathParent); +Deno.copyFileSync(Deno.execPath(), execPath); + +const testUrl = `data:application/typescript;base64,${ + btoa(` + console.error(await Deno.permissions.query({ name: "run", command: "binary" })); + console.error(await Deno.permissions.query({ name: "run", command: "${ + execPath.replaceAll("\\", "\\\\") + }" })); + Deno.env.set("PATH", ""); + console.error(await Deno.permissions.query({ name: "run", command: "binary" })); + console.error(await Deno.permissions.query({ name: "run", command: "${ + execPath.replaceAll("\\", "\\\\") + }" })); +`) +}`; + +await new Deno.Command(Deno.execPath(), { + args: [ + "run", + "--allow-env", + "--allow-run=binary", + testUrl, + ], + stdout: "inherit", + stderr: "inherit", + env: { "PATH": execPathParent }, +}).output(); + +console.error("---"); + +await new Deno.Command(Deno.execPath(), { + args: [ + "run", + "--allow-env", + "--allow-run=binary", + testUrl, + ], + stderr: "inherit", + stdout: "inherit", + env: { "PATH": "" }, +}).output(); + +console.error("---"); + +await new Deno.Command(Deno.execPath(), { + args: [ + "run", + "--allow-env", + `--allow-run=${execPath}`, + testUrl, + ], + stderr: "inherit", + stdout: "inherit", + env: { "PATH": execPathParent }, +}).output(); diff --git a/tests/specs/run/bare_specifier_without_import/__test__.jsonc b/tests/specs/run/bare_specifier_without_import/__test__.jsonc new file mode 100644 index 0000000000..7b5c5e1b67 --- /dev/null +++ b/tests/specs/run/bare_specifier_without_import/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/run/bare_specifier_without_import/main.out b/tests/specs/run/bare_specifier_without_import/main.out new file mode 100644 index 0000000000..59ea233922 --- /dev/null +++ b/tests/specs/run/bare_specifier_without_import/main.out @@ -0,0 +1,3 @@ +error: Relative import path "@std/dotenv/load" not prefixed with / or ./ or ../ + hint: If you want to use a JSR or npm package, try running `deno add jsr:@std/dotenv/load` or `deno add npm:@std/dotenv/load` + at [WILDCARD]bare_specifier_without_import/main.ts:1:8 diff --git a/tests/specs/run/bare_specifier_without_import/main.ts b/tests/specs/run/bare_specifier_without_import/main.ts new file mode 100644 index 0000000000..67e57b26b3 --- /dev/null +++ b/tests/specs/run/bare_specifier_without_import/main.ts @@ -0,0 +1,3 @@ +import "@std/dotenv/load"; + +console.log(Deno.env.get("GREETING")); // hello world diff --git a/tests/specs/run/cjs_reexport_non_analyzable/__test__.jsonc b/tests/specs/run/cjs_reexport_non_analyzable/__test__.jsonc new file mode 100644 index 0000000000..81f29b685d --- /dev/null +++ b/tests/specs/run/cjs_reexport_non_analyzable/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "run -A main.ts", + "output": "" + } + ] +} diff --git a/tests/specs/run/cjs_reexport_non_analyzable/deno.json b/tests/specs/run/cjs_reexport_non_analyzable/deno.json new file mode 100644 index 0000000000..fde86a1efb --- /dev/null +++ b/tests/specs/run/cjs_reexport_non_analyzable/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "manual" +} diff --git a/tests/specs/run/cjs_reexport_non_analyzable/main.ts b/tests/specs/run/cjs_reexport_non_analyzable/main.ts new file mode 100644 index 0000000000..a9e32af4e1 --- /dev/null +++ b/tests/specs/run/cjs_reexport_non_analyzable/main.ts @@ -0,0 +1,3 @@ +import assert from "./node_modules/foo.cjs"; + +assert.equal(1 + 1, 2); diff --git a/tests/specs/run/cjs_reexport_non_analyzable/node_modules/foo.cjs b/tests/specs/run/cjs_reexport_non_analyzable/node_modules/foo.cjs new file mode 100644 index 0000000000..924d8a96a9 --- /dev/null +++ b/tests/specs/run/cjs_reexport_non_analyzable/node_modules/foo.cjs @@ -0,0 +1,5 @@ +try { + module.exports = require("nonexistent"); +} catch(_e) { + module.exports = require("assert"); +} diff --git a/tests/specs/run/default_ts/__test__.jsonc b/tests/specs/run/default_ts/__test__.jsonc new file mode 100644 index 0000000000..07e3d83368 --- /dev/null +++ b/tests/specs/run/default_ts/__test__.jsonc @@ -0,0 +1,18 @@ +{ + "tempDir": true, + "tests": { + "stdin": { + "args": "run -", + "input": "const x: string = \"foo\";console.log(x)", + "output": "foo\n" + }, + "ext_flag": { + "args": "run --ext=ts as_ts.js", + "output": "foo\n" + }, + "extensionless": { + "args": "run extensionless", + "output": "foo\n" + } + } +} diff --git a/tests/specs/run/default_ts/as_ts.js b/tests/specs/run/default_ts/as_ts.js new file mode 100644 index 0000000000..cef8995bcd --- /dev/null +++ b/tests/specs/run/default_ts/as_ts.js @@ -0,0 +1,2 @@ +const x: string = "foo"; +console.log(x); diff --git a/tests/specs/run/default_ts/extensionless b/tests/specs/run/default_ts/extensionless new file mode 100644 index 0000000000..cef8995bcd --- /dev/null +++ b/tests/specs/run/default_ts/extensionless @@ -0,0 +1,2 @@ +const x: string = "foo"; +console.log(x); diff --git a/tests/specs/run/document/__test__.jsonc b/tests/specs/run/document/__test__.jsonc new file mode 100644 index 0000000000..cf20f9e1b2 --- /dev/null +++ b/tests/specs/run/document/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tests": { + "document": { + "args": "run document.js", + "exitCode": 1, + "output": "document.out" + } + } +} diff --git a/tests/specs/run/document/document.js b/tests/specs/run/document/document.js new file mode 100644 index 0000000000..63e43b72f0 --- /dev/null +++ b/tests/specs/run/document/document.js @@ -0,0 +1 @@ +document.querySelector("div"); diff --git a/tests/specs/run/document/document.out b/tests/specs/run/document/document.out new file mode 100644 index 0000000000..eefedb8f2b --- /dev/null +++ b/tests/specs/run/document/document.out @@ -0,0 +1,8 @@ +error: Uncaught (in promise) ReferenceError: document is not defined +document.querySelector("div"); +^ + at [WILDCARD]document.js:1:1 + + info: document global is not available in Deno. + hint: Use a library like happy-dom, deno_dom, linkedom or JSDom + and setup the document global according to the library documentation. diff --git a/tests/specs/run/import_common_js/__test__.jsonc b/tests/specs/run/import_common_js/__test__.jsonc new file mode 100644 index 0000000000..6510dbad7b --- /dev/null +++ b/tests/specs/run/import_common_js/__test__.jsonc @@ -0,0 +1,21 @@ +{ + "steps": [ + { "args": "run -R index.cjs", "output": "index.out" }, + { "args": "run -R main.ts", "output": "main.out" }, + { + "args": "run module_error.js", + "output": "module_error.out", + "exitCode": 1 + }, + { + "args": "run exports_error.js", + "output": "exports_error.out", + "exitCode": 1 + }, + { + "args": "run require_error.js", + "output": "require_error.out", + "exitCode": 1 + } + ] +} diff --git a/tests/specs/run/import_common_js/a.js b/tests/specs/run/import_common_js/a.js new file mode 100644 index 0000000000..c465ab588b --- /dev/null +++ b/tests/specs/run/import_common_js/a.js @@ -0,0 +1,7 @@ +function foobar() { + console.log("foobar"); +} + +module.exports = { + foobar, +}; diff --git a/tests/specs/run/import_common_js/exports_error.js b/tests/specs/run/import_common_js/exports_error.js new file mode 100644 index 0000000000..a6a850fe28 --- /dev/null +++ b/tests/specs/run/import_common_js/exports_error.js @@ -0,0 +1 @@ +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/specs/run/import_common_js/exports_error.out b/tests/specs/run/import_common_js/exports_error.out new file mode 100644 index 0000000000..b979cce5c7 --- /dev/null +++ b/tests/specs/run/import_common_js/exports_error.out @@ -0,0 +1,12 @@ +error: Uncaught (in promise) ReferenceError: exports is not defined +Object.defineProperty(exports, "__esModule", { value: true }); + ^ + at [WILDCARD]exports_error.js:1:23 + + info: Deno supports CommonJS modules in .cjs files, or when there's a package.json + with "type": "commonjs" option and --unstable-detect-cjs flag is used. + hint: Rewrite this module to ESM, + or change the file extension to .cjs, + or add package.json next to the file with "type": "commonjs" option + and pass --unstable-detect-cjs flag. + docs: https://docs.deno.com/go/commonjs diff --git a/tests/specs/run/import_common_js/index.cjs b/tests/specs/run/import_common_js/index.cjs new file mode 100644 index 0000000000..18caf81e94 --- /dev/null +++ b/tests/specs/run/import_common_js/index.cjs @@ -0,0 +1,9 @@ +const process = require("process"); +const a = require("./a"); + +console.log(process.cwd()); + +module.exports = { + cwd: process.cwd, + foobar: a.foobar, +}; diff --git a/tests/specs/run/import_common_js/index.out b/tests/specs/run/import_common_js/index.out new file mode 100644 index 0000000000..3650631b7a --- /dev/null +++ b/tests/specs/run/import_common_js/index.out @@ -0,0 +1 @@ +[WILDCARD]import_common_js diff --git a/tests/specs/run/import_common_js/main.out b/tests/specs/run/import_common_js/main.out new file mode 100644 index 0000000000..03301b3620 --- /dev/null +++ b/tests/specs/run/import_common_js/main.out @@ -0,0 +1,5 @@ +hello from foo node module +[WILDCARD]import_common_js +cjsModule.cwd() [WILDCARD]import_common_js +foobar +cjsModule.foobar() undefined diff --git a/tests/specs/run/import_common_js/main.ts b/tests/specs/run/import_common_js/main.ts new file mode 100644 index 0000000000..65b75b7293 --- /dev/null +++ b/tests/specs/run/import_common_js/main.ts @@ -0,0 +1,3 @@ +import foo from "foo"; + +foo(); diff --git a/tests/specs/run/import_common_js/module_error.js b/tests/specs/run/import_common_js/module_error.js new file mode 100644 index 0000000000..59a3cc0e7d --- /dev/null +++ b/tests/specs/run/import_common_js/module_error.js @@ -0,0 +1,3 @@ +module.exports = { + foobar: "foobar", +}; diff --git a/tests/specs/run/import_common_js/module_error.out b/tests/specs/run/import_common_js/module_error.out new file mode 100644 index 0000000000..654ee838dd --- /dev/null +++ b/tests/specs/run/import_common_js/module_error.out @@ -0,0 +1,12 @@ +error: Uncaught (in promise) ReferenceError: module is not defined +module.exports = { +^ + at [WILDCARD]module_error.js:1:1 + + info: Deno supports CommonJS modules in .cjs files, or when there's a package.json + with "type": "commonjs" option and --unstable-detect-cjs flag is used. + hint: Rewrite this module to ESM, + or change the file extension to .cjs, + or add package.json next to the file with "type": "commonjs" option + and pass --unstable-detect-cjs flag. + docs: https://docs.deno.com/go/commonjs diff --git a/tests/specs/run/import_common_js/node_modules/foo/index.mjs b/tests/specs/run/import_common_js/node_modules/foo/index.mjs new file mode 100644 index 0000000000..cc93554c73 --- /dev/null +++ b/tests/specs/run/import_common_js/node_modules/foo/index.mjs @@ -0,0 +1,14 @@ +import process from "node:process"; +import path from "node:path"; +import url from "node:url"; + +export default async function () { + console.log("hello from foo node module"); + + const cjsFileToImport = path.join(process.cwd(), "index.cjs"); + + const cjsModule = await import(url.pathToFileURL(cjsFileToImport)); + + console.log("cjsModule.cwd()", cjsModule.cwd()); + console.log("cjsModule.foobar()", cjsModule.foobar()); +} diff --git a/tests/specs/run/import_common_js/node_modules/foo/package.json b/tests/specs/run/import_common_js/node_modules/foo/package.json new file mode 100644 index 0000000000..ac525b7b86 --- /dev/null +++ b/tests/specs/run/import_common_js/node_modules/foo/package.json @@ -0,0 +1,3 @@ +{ + "main": "./index.mjs" +} \ No newline at end of file diff --git a/tests/specs/run/import_common_js/package.json b/tests/specs/run/import_common_js/package.json new file mode 100644 index 0000000000..03457387ac --- /dev/null +++ b/tests/specs/run/import_common_js/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "foo": "*" + } +} diff --git a/tests/specs/run/import_common_js/require_error.js b/tests/specs/run/import_common_js/require_error.js new file mode 100644 index 0000000000..9567689331 --- /dev/null +++ b/tests/specs/run/import_common_js/require_error.js @@ -0,0 +1,2 @@ +const process = require("process"); +const a = require("./a"); diff --git a/tests/specs/run/import_common_js/require_error.out b/tests/specs/run/import_common_js/require_error.out new file mode 100644 index 0000000000..81ffd6591f --- /dev/null +++ b/tests/specs/run/import_common_js/require_error.out @@ -0,0 +1,12 @@ +error: Uncaught (in promise) ReferenceError: require is not defined +const process = require("process"); + ^ + at [WILDCARD]require_error.js:1:17 + + info: Deno supports CommonJS modules in .cjs files, or when there's a package.json + with "type": "commonjs" option and --unstable-detect-cjs flag is used. + hint: Rewrite this module to ESM, + or change the file extension to .cjs, + or add package.json next to the file with "type": "commonjs" option + and pass --unstable-detect-cjs flag. + docs: https://docs.deno.com/go/commonjs diff --git a/tests/specs/run/ld_preload/__test__.jsonc b/tests/specs/run/ld_preload/__test__.jsonc new file mode 100644 index 0000000000..16ae697a74 --- /dev/null +++ b/tests/specs/run/ld_preload/__test__.jsonc @@ -0,0 +1,17 @@ +{ + "envs": { + "LD_LIBRARY_PATH": "", + "LD_PRELOAD": "", + "DYLD_FALLBACK_LIBRARY_PATH": "" + }, + "tests": { + "env_arg": { + "args": "run --allow-run=curl env_arg.ts", + "output": "env_arg.out" + }, + "set_with_allow_env": { + "args": "run --allow-run=curl --allow-env set_with_allow_env.ts", + "output": "set_with_allow_env.out" + } + } +} diff --git a/tests/specs/run/ld_preload/env_arg.out b/tests/specs/run/ld_preload/env_arg.out new file mode 100644 index 0000000000..945737e65b --- /dev/null +++ b/tests/specs/run/ld_preload/env_arg.out @@ -0,0 +1,8 @@ +NotCapable: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable. + [WILDCARD] + name: "NotCapable" +} +NotCapable: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable. + [WILDCARD] + name: "NotCapable" +} diff --git a/tests/specs/run/ld_preload/env_arg.ts b/tests/specs/run/ld_preload/env_arg.ts new file mode 100644 index 0000000000..d7ca1073df --- /dev/null +++ b/tests/specs/run/ld_preload/env_arg.ts @@ -0,0 +1,20 @@ +try { + new Deno.Command("echo", { + env: { + "LD_PRELOAD": "./libpreload.so", + }, + }).spawn(); +} catch (err) { + console.log(err); +} + +try { + Deno.run({ + cmd: ["echo"], + env: { + "LD_PRELOAD": "./libpreload.so", + }, + }); +} catch (err) { + console.log(err); +} diff --git a/tests/specs/run/ld_preload/set_with_allow_env.out b/tests/specs/run/ld_preload/set_with_allow_env.out new file mode 100644 index 0000000000..f89582d6c8 --- /dev/null +++ b/tests/specs/run/ld_preload/set_with_allow_env.out @@ -0,0 +1,8 @@ +NotCapable: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable. + [WILDCARD] + name: "NotCapable" +} +NotCapable: Requires --allow-all permissions to spawn subprocess with DYLD_FALLBACK_LIBRARY_PATH, LD_PRELOAD environment variables. + [WILDCARD] + name: "NotCapable" +} diff --git a/tests/specs/run/ld_preload/set_with_allow_env.ts b/tests/specs/run/ld_preload/set_with_allow_env.ts new file mode 100644 index 0000000000..a3e8dd3976 --- /dev/null +++ b/tests/specs/run/ld_preload/set_with_allow_env.ts @@ -0,0 +1,15 @@ +Deno.env.set("LD_PRELOAD", "./libpreload.so"); + +try { + new Deno.Command("curl").spawn(); +} catch (err) { + console.log(err); +} + +Deno.env.set("DYLD_FALLBACK_LIBRARY_PATH", "./libpreload.so"); + +try { + Deno.run({ cmd: ["curl"] }).spawnSync(); +} catch (err) { + console.log(err); +} diff --git a/tests/specs/run/location/__test__.jsonc b/tests/specs/run/location/__test__.jsonc new file mode 100644 index 0000000000..551463d594 --- /dev/null +++ b/tests/specs/run/location/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "tests": { + "location_object_define_property": { + "args": "run location.js", + "output": "location.out" + } + } +} diff --git a/tests/specs/run/location/location.js b/tests/specs/run/location/location.js new file mode 100644 index 0000000000..8562a39957 --- /dev/null +++ b/tests/specs/run/location/location.js @@ -0,0 +1,24 @@ +let _location = undefined; + +console.log(globalThis.location); + +Object.defineProperty(globalThis, "location", { + get() { + return _location; + }, + set(v) { + _location = v; + }, + configurable: true, +}); + +console.log(globalThis.location); + +globalThis.location = "https://deno.com"; + +console.log(_location); +console.log(location); + +delete globalThis["location"]; + +console.log(globalThis.location); diff --git a/tests/specs/run/location/location.out b/tests/specs/run/location/location.out new file mode 100644 index 0000000000..bcb3ff67b9 --- /dev/null +++ b/tests/specs/run/location/location.out @@ -0,0 +1,5 @@ +undefined +undefined +https://deno.com +https://deno.com +undefined diff --git a/tests/specs/run/netlify_edge_bundler_hack/__test__.jsonc b/tests/specs/run/netlify_edge_bundler_hack/__test__.jsonc deleted file mode 100644 index 4ae0ebe862..0000000000 --- a/tests/specs/run/netlify_edge_bundler_hack/__test__.jsonc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "args": [ - "run", - "--allow-read", - "--allow-write", - "node_modules/@netlify/edge-bundler/deno/config.ts" - ], - "output": "main.out" -} diff --git a/tests/specs/run/netlify_edge_bundler_hack/main.out b/tests/specs/run/netlify_edge_bundler_hack/main.out deleted file mode 100644 index 35821117c8..0000000000 --- a/tests/specs/run/netlify_edge_bundler_hack/main.out +++ /dev/null @@ -1 +0,0 @@ -Success diff --git a/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/deno/config.ts b/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/deno/config.ts deleted file mode 100644 index f1b207f5b7..0000000000 --- a/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/deno/config.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("Success"); diff --git a/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/package.json b/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/package.json deleted file mode 100644 index d6043710ff..0000000000 --- a/tests/specs/run/netlify_edge_bundler_hack/node_modules/@netlify/edge-bundler/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@netlify/edge-bundler", - "version": "1.0.0", - "exports": "./index.js", -} \ No newline at end of file diff --git a/tests/specs/run/netlify_edge_bundler_hack/package.json b/tests/specs/run/netlify_edge_bundler_hack/package.json deleted file mode 100644 index bd0ecbc6ee..0000000000 --- a/tests/specs/run/netlify_edge_bundler_hack/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "my-package", - "version": "1.0.0" -} diff --git a/tests/specs/run/no_deno_json/__test__.jsonc b/tests/specs/run/no_deno_json/__test__.jsonc index 5da0209b90..b27e3cbff1 100644 --- a/tests/specs/run/no_deno_json/__test__.jsonc +++ b/tests/specs/run/no_deno_json/__test__.jsonc @@ -29,15 +29,33 @@ "cwd": "code" }, "auto_discovered": { - // auto-discovered node_modules relative package.json - "args": "run -A main.js", - "output": "code/sub_dir/main.out", - "cwd": "code/sub_dir" + "steps": [ + { + "args": "install", + "output": "code/install.out", + "cwd": "code" + }, + { + // auto-discovered node_modules relative package.json + "args": "run -A main.js", + "output": "code/sub_dir/main.out", + "cwd": "code/sub_dir" + } + ] }, "auto_discovered_arg": { - // auto-discovered for local script arg - "args": "run -L debug -A code/main.ts", // notice this is not in the sub dir - "output": "main.out" + "steps": [ + { + "args": "install", + "output": "code/install.out", + "cwd": "code" + }, + { + // auto-discovered for local script arg + "args": "run -L debug -A code/main.ts", // notice this is not in the sub dir + "output": "main.out" + } + ] } } } diff --git a/tests/specs/run/no_deno_json/code/install.out b/tests/specs/run/no_deno_json/code/install.out new file mode 100644 index 0000000000..ddaf104c3b --- /dev/null +++ b/tests/specs/run/no_deno_json/code/install.out @@ -0,0 +1,26 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fcheck-error +Download http://localhost:4260/@denotest%2fcjs-default-export +Download http://localhost:4260/chalk +Download http://localhost:4260/ansi-styles +Download http://localhost:4260/supports-color +Download http://localhost:4260/color-convert +Download http://localhost:4260/has-flag +Download http://localhost:4260/color-name +Download http://localhost:4260/@denotest/check-error/1.0.0.tgz +Download http://localhost:4260/@denotest/cjs-default-export/1.0.0.tgz +Download http://localhost:4260/chalk/chalk-4.1.2.tgz +Download http://localhost:4260/ansi-styles/ansi-styles-4.3.0.tgz +Download http://localhost:4260/supports-color/supports-color-7.2.0.tgz +Download http://localhost:4260/color-convert/color-convert-2.0.1.tgz +Download http://localhost:4260/has-flag/has-flag-4.0.0.tgz +Download http://localhost:4260/color-name/color-name-1.1.4.tgz +Initialize @denotest/cjs-default-export@1.0.0 +Initialize color-name@1.1.4 +Initialize ansi-styles@4.3.0 +Initialize has-flag@4.0.0 +Initialize supports-color@7.2.0 +Initialize color-convert@2.0.1 +Initialize chalk@4.1.2 +Initialize @denotest/check-error@1.0.0 +[UNORDERED_END] diff --git a/tests/specs/run/no_deno_json/code/sub_dir/main.out b/tests/specs/run/no_deno_json/code/sub_dir/main.out index 0ec7919604..b34a051240 100644 --- a/tests/specs/run/no_deno_json/code/sub_dir/main.out +++ b/tests/specs/run/no_deno_json/code/sub_dir/main.out @@ -1,4 +1,3 @@ -Download http://[WILDCARD] [WILDCARD]sub_dir { [WILDCARD] diff --git a/tests/specs/run/node_builtin_modules/__test__.jsonc b/tests/specs/run/node_builtin_modules/__test__.jsonc new file mode 100644 index 0000000000..f3d637ac61 --- /dev/null +++ b/tests/specs/run/node_builtin_modules/__test__.jsonc @@ -0,0 +1,12 @@ +{ + "tests": { + "ts": { + "args": "run --quiet --allow-read mod.ts hello there", + "output": "mod.ts.out" + }, + "js": { + "args": "run --quiet --allow-read mod.js hello there", + "output": "mod.js.out" + } + } +} diff --git a/tests/testdata/run/node_builtin_modules/mod.js b/tests/specs/run/node_builtin_modules/mod.js similarity index 100% rename from tests/testdata/run/node_builtin_modules/mod.js rename to tests/specs/run/node_builtin_modules/mod.js diff --git a/tests/testdata/run/node_builtin_modules/mod.js.out b/tests/specs/run/node_builtin_modules/mod.js.out similarity index 100% rename from tests/testdata/run/node_builtin_modules/mod.js.out rename to tests/specs/run/node_builtin_modules/mod.js.out diff --git a/tests/testdata/run/node_builtin_modules/mod.ts b/tests/specs/run/node_builtin_modules/mod.ts similarity index 100% rename from tests/testdata/run/node_builtin_modules/mod.ts rename to tests/specs/run/node_builtin_modules/mod.ts diff --git a/tests/testdata/run/node_builtin_modules/mod.ts.out b/tests/specs/run/node_builtin_modules/mod.ts.out similarity index 100% rename from tests/testdata/run/node_builtin_modules/mod.ts.out rename to tests/specs/run/node_builtin_modules/mod.ts.out diff --git a/tests/specs/run/node_prefix_missing/__test__.jsonc b/tests/specs/run/node_prefix_missing/__test__.jsonc new file mode 100644 index 0000000000..305020ed97 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/__test__.jsonc @@ -0,0 +1,35 @@ +{ + "tests": { + "basic": { + "args": "run --quiet main.ts", + "output": "main.ts.out", + "exitCode": 1 + }, + "unstable_bare_node_builtins_enabled": { + "args": "run --unstable-bare-node-builtins main.ts", + "output": "feature_enabled.out" + }, + "unstable_bare_node_builtins_enbaled_by_env": { + "args": "run main.ts", + "envs": { + "DENO_UNSTABLE_BARE_NODE_BUILTINS": "1" + }, + "output": "feature_enabled.out" + }, + "enabled_by_config": { + "args": "run --config=config.json main.ts", + "output": "feature_enabled.out" + }, + "byonm_missing": { + "cwd": "byonm", + "exitCode": 1, + "args": "run missing.ts", + "output": "byonm/missing.out" + }, + "byonm_has": { + "cwd": "byonm", + "args": "run has.ts", + "output": "byonm/has.out" + } + } +} diff --git a/tests/specs/run/node_prefix_missing/byonm/has.out b/tests/specs/run/node_prefix_missing/byonm/has.out new file mode 100644 index 0000000000..e223dcff58 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/byonm/has.out @@ -0,0 +1 @@ +[Function: writeFile] diff --git a/tests/specs/run/node_prefix_missing/byonm/has.ts b/tests/specs/run/node_prefix_missing/byonm/has.ts new file mode 100644 index 0000000000..a52c1e3f0d --- /dev/null +++ b/tests/specs/run/node_prefix_missing/byonm/has.ts @@ -0,0 +1,3 @@ +import fs from "node:fs"; + +console.log(fs.writeFile); diff --git a/tests/specs/run/node_prefix_missing/byonm/missing.out b/tests/specs/run/node_prefix_missing/byonm/missing.out new file mode 100644 index 0000000000..4129e79a51 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/byonm/missing.out @@ -0,0 +1,3 @@ +error: Relative import path "fs" not prefixed with / or ./ or ../ + hint: If you want to use a built-in Node module, add a "node:" prefix (ex. "node:fs"). + at file:///[WILDLINE]/missing.ts:1:16 diff --git a/tests/testdata/run/node_prefix_missing/main.ts b/tests/specs/run/node_prefix_missing/byonm/missing.ts similarity index 100% rename from tests/testdata/run/node_prefix_missing/main.ts rename to tests/specs/run/node_prefix_missing/byonm/missing.ts diff --git a/tests/specs/run/node_prefix_missing/byonm/package.json b/tests/specs/run/node_prefix_missing/byonm/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/byonm/package.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/run/node_prefix_missing/config.json b/tests/specs/run/node_prefix_missing/config.json new file mode 100644 index 0000000000..72f40aaf36 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/config.json @@ -0,0 +1,3 @@ +{ + "unstable": ["bare-node-builtins"] +} diff --git a/tests/specs/run/node_prefix_missing/feature_enabled.out b/tests/specs/run/node_prefix_missing/feature_enabled.out new file mode 100644 index 0000000000..3eff4bc324 --- /dev/null +++ b/tests/specs/run/node_prefix_missing/feature_enabled.out @@ -0,0 +1,2 @@ +[WILDCARD]Warning Resolving "fs" as "node:fs" at file:///[WILDCARD]/main.ts:1:16. If you want to use a built-in Node module, add a "node:" prefix. +[Function: writeFile] diff --git a/tests/specs/run/node_prefix_missing/main.ts b/tests/specs/run/node_prefix_missing/main.ts new file mode 100644 index 0000000000..c5c1885a2f --- /dev/null +++ b/tests/specs/run/node_prefix_missing/main.ts @@ -0,0 +1,3 @@ +import fs from "fs"; + +console.log(fs.writeFile); diff --git a/tests/testdata/run/node_prefix_missing/main.ts.out b/tests/specs/run/node_prefix_missing/main.ts.out similarity index 54% rename from tests/testdata/run/node_prefix_missing/main.ts.out rename to tests/specs/run/node_prefix_missing/main.ts.out index fd19ed55f7..48b4e37e27 100644 --- a/tests/testdata/run/node_prefix_missing/main.ts.out +++ b/tests/specs/run/node_prefix_missing/main.ts.out @@ -1,3 +1,3 @@ error: Relative import path "fs" not prefixed with / or ./ or ../ -If you want to use a built-in Node module, add a "node:" prefix (ex. "node:fs"). + hint: If you want to use a built-in Node module, add a "node:" prefix (ex. "node:fs"). at file:///[WILDCARD]/main.ts:1:16 diff --git a/tests/specs/run/package_json/invalid_value/__test__.jsonc b/tests/specs/run/package_json/invalid_value/__test__.jsonc new file mode 100644 index 0000000000..195734d95f --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/__test__.jsonc @@ -0,0 +1,30 @@ +{ + "tempDir": true, + "tests": { + // should run fine when not referencing a failing dep entry + "run_ok_auto": { + "args": "run --quiet --node-modules-dir=auto ok.ts", + "output": "ok.ts.out" + }, + // should fail when referencing a failing dep entry + "run_error_auto": { + "args": "run --node-modules-dir=auto error.ts", + "exitCode": 1, + "output": "error_auto.out" + }, + "install_error_byonm": { + "args": "install", + "output": "install.out", + "exitCode": 1 + }, + "add_error_byonm": { + "args": "add npm:cowsay", + "output": "add.out", + "exitCode": 1 + }, + "task_test": { + "args": "task --node-modules-dir=auto test", + "output": "task.out" + } + } +} diff --git a/tests/specs/run/package_json/invalid_value/add.out b/tests/specs/run/package_json/invalid_value/add.out new file mode 100644 index 0000000000..9b7493c1a2 --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/add.out @@ -0,0 +1,8 @@ +Add npm:cowsay@1.5.0 +error: Failed to install from package.json + +Caused by: + 0: Invalid version requirement + 1: Unexpected character. + invalid stuff that won't parse + ~ diff --git a/tests/specs/run/package_json/invalid_value/error.out b/tests/specs/run/package_json/invalid_value/error.out new file mode 100644 index 0000000000..5975351131 --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/error.out @@ -0,0 +1,2 @@ +error: Could not resolve "@denotest/cjs-default-export", but found it in a package.json. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`? + at file:///[WILDCARD]/error.ts:2:23 diff --git a/tests/testdata/package_json/invalid_value/error.ts b/tests/specs/run/package_json/invalid_value/error.ts similarity index 100% rename from tests/testdata/package_json/invalid_value/error.ts rename to tests/specs/run/package_json/invalid_value/error.ts diff --git a/tests/specs/run/package_json/invalid_value/error_auto.out b/tests/specs/run/package_json/invalid_value/error_auto.out new file mode 100644 index 0000000000..966375a3df --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/error_auto.out @@ -0,0 +1,8 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 +error: Invalid version requirement + 0: Unexpected character. + invalid stuff that won't parse + ~ + at file:///[WILDCARD]/error.ts:2:23 diff --git a/tests/specs/run/package_json/invalid_value/install.out b/tests/specs/run/package_json/invalid_value/install.out new file mode 100644 index 0000000000..cc82b345b0 --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/install.out @@ -0,0 +1,7 @@ +error: Failed to install from package.json + +Caused by: + 0: Invalid version requirement + 1: Unexpected character. + invalid stuff that won't parse + ~ diff --git a/tests/testdata/package_json/invalid_value/ok.ts b/tests/specs/run/package_json/invalid_value/ok.ts similarity index 100% rename from tests/testdata/package_json/invalid_value/ok.ts rename to tests/specs/run/package_json/invalid_value/ok.ts diff --git a/tests/specs/run/package_json/invalid_value/ok.ts.out b/tests/specs/run/package_json/invalid_value/ok.ts.out new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/ok.ts.out @@ -0,0 +1 @@ +2 diff --git a/tests/testdata/package_json/invalid_value/package.json b/tests/specs/run/package_json/invalid_value/package.json similarity index 100% rename from tests/testdata/package_json/invalid_value/package.json rename to tests/specs/run/package_json/invalid_value/package.json diff --git a/tests/specs/run/package_json/invalid_value/task.out b/tests/specs/run/package_json/invalid_value/task.out new file mode 100644 index 0000000000..2f9580fa61 --- /dev/null +++ b/tests/specs/run/package_json/invalid_value/task.out @@ -0,0 +1,5 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 +Task test echo 1 +1 diff --git a/tests/specs/run/package_json/with_deno_json/__test__.jsonc b/tests/specs/run/package_json/with_deno_json/__test__.jsonc new file mode 100644 index 0000000000..13b6b6de10 --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/__test__.jsonc @@ -0,0 +1,16 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "run --quiet -A main.ts", + "output": "main.out" + }, + { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('deno.lock').trim())" + ], + "output": "lock.out" + } + ] +} diff --git a/tests/specs/run/package_json/with_deno_json/deno.json b/tests/specs/run/package_json/with_deno_json/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/run/package_json/with_deno_json/lib.ts b/tests/specs/run/package_json/with_deno_json/lib.ts new file mode 100644 index 0000000000..1deed81f7e --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/lib.ts @@ -0,0 +1,9 @@ +import * as test from "@denotest/esm-basic"; + +export function add(a: number, b: number) { + return a + b; +} + +export function getValue() { + return test.getValue(); +} diff --git a/tests/specs/run/package_json/with_deno_json/lock.out b/tests/specs/run/package_json/with_deno_json/lock.out new file mode 100644 index 0000000000..92aa561b8a --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/lock.out @@ -0,0 +1,18 @@ +{ + "version": "4", + "specifiers": { + "npm:@denotest/esm-basic@*": "1.0.0" + }, + "npm": { + "@denotest/esm-basic@1.0.0": { + "integrity": "sha512-[WILDCARD]" + } + }, + "workspace": { + "packageJson": { + "dependencies": [ + "npm:@denotest/esm-basic@*" + ] + } + } +} diff --git a/tests/testdata/task/deno_json_pre_post/echo.out b/tests/specs/run/package_json/with_deno_json/main.out similarity index 100% rename from tests/testdata/task/deno_json_pre_post/echo.out rename to tests/specs/run/package_json/with_deno_json/main.out diff --git a/tests/specs/run/package_json/with_deno_json/main.ts b/tests/specs/run/package_json/with_deno_json/main.ts new file mode 100644 index 0000000000..e241f30026 --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/main.ts @@ -0,0 +1,3 @@ +import { getValue } from "./lib.ts"; + +console.log(getValue()); diff --git a/tests/specs/run/package_json/with_deno_json/package.json b/tests/specs/run/package_json/with_deno_json/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/run/package_json/with_deno_json/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/specs/run/package_json_auto_discovered_for_npm_binary/__test__.jsonc b/tests/specs/run/package_json_auto_discovered_for_npm_binary/__test__.jsonc new file mode 100644 index 0000000000..dab6ad8d55 --- /dev/null +++ b/tests/specs/run/package_json_auto_discovered_for_npm_binary/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "run -L debug npm:@denotest/bin/cli-esm this is a test", + "output": "main.out" +} diff --git a/tests/specs/run/package_json_auto_discovered_for_npm_binary/deno.json b/tests/specs/run/package_json_auto_discovered_for_npm_binary/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/run/package_json_auto_discovered_for_npm_binary/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/run/package_json_auto_discovered_for_npm_binary/main.out b/tests/specs/run/package_json_auto_discovered_for_npm_binary/main.out new file mode 100644 index 0000000000..5f687a098a --- /dev/null +++ b/tests/specs/run/package_json_auto_discovered_for_npm_binary/main.out @@ -0,0 +1,8 @@ +[WILDCARD] +[WILDCARD]package.json file found at '[WILDCARD]package.json' +[WILDCARD] +this +is +a +test +[WILDCARD] diff --git a/tests/testdata/run/with_package_json/npm_binary/package.json b/tests/specs/run/package_json_auto_discovered_for_npm_binary/package.json similarity index 100% rename from tests/testdata/run/with_package_json/npm_binary/package.json rename to tests/specs/run/package_json_auto_discovered_for_npm_binary/package.json diff --git a/tests/specs/run/package_json_type/commonjs/__test__.jsonc b/tests/specs/run/package_json_type/commonjs/__test__.jsonc new file mode 100644 index 0000000000..85b7219fa0 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/__test__.jsonc @@ -0,0 +1,34 @@ +{ + "tests": { + "main_cjs": { + "args": "run --allow-read=. main_cjs.js", + "output": "3\n" + }, + "main_esm": { + "args": "run --allow-read=. main_esm.js", + "output": "3\n" + }, + "main_mix": { + "args": "run --allow-read=. main_mix.js", + "output": "main_mix.out", + "exitCode": 1 + }, + "import_import_meta": { + "args": "run import_import_meta.js", + "output": "[WILDLINE]/import_meta.js\n" + }, + "main_import_meta": { + "args": "run main_esm_import_meta.js", + "output": "main_esm_import_meta.out", + "exitCode": 1 + }, + "not_import_meta": { + "args": "run --allow-read=. not_import_meta.js", + "output": "3\n" + }, + "tla": { + "args": "run --allow-read=. tla.js", + "output": "loaded\n" + } + } +} diff --git a/tests/specs/run/package_json_type/commonjs/add.js b/tests/specs/run/package_json_type/commonjs/add.js new file mode 100644 index 0000000000..2a886fbc18 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/add.js @@ -0,0 +1,3 @@ +module.exports.add = function (a, b) { + return a + b; +}; diff --git a/tests/specs/run/package_json_type/commonjs/deno.jsonc b/tests/specs/run/package_json_type/commonjs/deno.jsonc new file mode 100644 index 0000000000..35f64c86f4 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/deno.jsonc @@ -0,0 +1,5 @@ +{ + "unstable": [ + "detect-cjs" + ] +} diff --git a/tests/specs/run/package_json_type/commonjs/import_import_meta.js b/tests/specs/run/package_json_type/commonjs/import_import_meta.js new file mode 100644 index 0000000000..f07518985a --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/import_import_meta.js @@ -0,0 +1,3 @@ +import { value } from "./import_meta.js"; + +console.log(value); diff --git a/tests/specs/run/package_json_type/commonjs/import_meta.js b/tests/specs/run/package_json_type/commonjs/import_meta.js new file mode 100644 index 0000000000..2bdbc30fe6 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/import_meta.js @@ -0,0 +1 @@ +export const value = import.meta.url; diff --git a/tests/specs/run/package_json_type/commonjs/main_cjs.js b/tests/specs/run/package_json_type/commonjs/main_cjs.js new file mode 100644 index 0000000000..365e8e06f8 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_cjs.js @@ -0,0 +1,2 @@ +const { add } = require("./add"); +console.log(add(1, 2)); diff --git a/tests/specs/run/package_json_type/commonjs/main_esm.js b/tests/specs/run/package_json_type/commonjs/main_esm.js new file mode 100644 index 0000000000..8c55f673b0 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_esm.js @@ -0,0 +1,3 @@ +import { add } from "./add.js"; + +console.log(add(1, 2)); diff --git a/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.js b/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.js new file mode 100644 index 0000000000..f1dff20b57 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.js @@ -0,0 +1,2 @@ +console.log(import.meta.url); +console.log(require("./add")); diff --git a/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.out b/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.out new file mode 100644 index 0000000000..e177defffd --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_esm_import_meta.out @@ -0,0 +1,2 @@ +[WILDLINE]main_esm_import_meta.js +error: Uncaught (in promise) ReferenceError: require is not defined[WILDCARD] diff --git a/tests/specs/run/package_json_type/commonjs/main_mix.js b/tests/specs/run/package_json_type/commonjs/main_mix.js new file mode 100644 index 0000000000..2a2c2c62a2 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_mix.js @@ -0,0 +1,6 @@ +import { add } from "./add.js"; + +console.log(add(1, 2)); + +// will error +console.log(require("./add").add(1, 2)); diff --git a/tests/specs/run/package_json_type/commonjs/main_mix.out b/tests/specs/run/package_json_type/commonjs/main_mix.out new file mode 100644 index 0000000000..78f421644c --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/main_mix.out @@ -0,0 +1,13 @@ +3 +error: Uncaught (in promise) ReferenceError: require is not defined +console.log(require("./add").add(1, 2)); + ^ + at file:///[WILDLINE]main_mix.js:[WILDLINE] + + info: Deno supports CommonJS modules in .cjs files, or when there's a package.json + with "type": "commonjs" option and --unstable-detect-cjs flag is used. + hint: Rewrite this module to ESM, + or change the file extension to .cjs, + or add package.json next to the file with "type": "commonjs" option + and pass --unstable-detect-cjs flag. + docs: https://docs.deno.com/go/commonjs diff --git a/tests/specs/run/package_json_type/commonjs/not_import_meta.js b/tests/specs/run/package_json_type/commonjs/not_import_meta.js new file mode 100644 index 0000000000..216b900df6 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/not_import_meta.js @@ -0,0 +1,8 @@ +try { + console.log(test.import.meta.url); +} catch { + // ignore +} + +// should work because this is not an ESM file +console.log(require("./add").add(1, 2)); diff --git a/tests/specs/run/package_json_type/commonjs/package.json b/tests/specs/run/package_json_type/commonjs/package.json new file mode 100644 index 0000000000..5bbefffbab --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/tests/specs/run/package_json_type/commonjs/tla.js b/tests/specs/run/package_json_type/commonjs/tla.js new file mode 100644 index 0000000000..978578de46 --- /dev/null +++ b/tests/specs/run/package_json_type/commonjs/tla.js @@ -0,0 +1,2 @@ +await new Promise((r) => r()); +console.log("loaded"); diff --git a/tests/specs/run/package_json_type/none/__test__.jsonc b/tests/specs/run/package_json_type/none/__test__.jsonc new file mode 100644 index 0000000000..fa1d22ca18 --- /dev/null +++ b/tests/specs/run/package_json_type/none/__test__.jsonc @@ -0,0 +1,18 @@ +{ + "tests": { + "main_cjs": { + "args": "run --allow-read=. main_cjs.js", + "output": "main_cjs.out", + "exitCode": 1 + }, + "main_esm": { + "args": "run --allow-read=. main_esm.js", + "output": "main_esm.out", + "exitCode": 1 + }, + "sub_folder_cjs": { + "args": "run --allow-read=. sub_folder_cjs.js", + "output": "3\n" + } + } +} diff --git a/tests/specs/run/package_json_type/none/add.js b/tests/specs/run/package_json_type/none/add.js new file mode 100644 index 0000000000..2a886fbc18 --- /dev/null +++ b/tests/specs/run/package_json_type/none/add.js @@ -0,0 +1,3 @@ +module.exports.add = function (a, b) { + return a + b; +}; diff --git a/tests/specs/run/package_json_type/none/commonjs/add.js b/tests/specs/run/package_json_type/none/commonjs/add.js new file mode 100644 index 0000000000..2a886fbc18 --- /dev/null +++ b/tests/specs/run/package_json_type/none/commonjs/add.js @@ -0,0 +1,3 @@ +module.exports.add = function (a, b) { + return a + b; +}; diff --git a/tests/specs/run/package_json_type/none/commonjs/package.json b/tests/specs/run/package_json_type/none/commonjs/package.json new file mode 100644 index 0000000000..5bbefffbab --- /dev/null +++ b/tests/specs/run/package_json_type/none/commonjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/tests/specs/run/package_json_type/none/deno.jsonc b/tests/specs/run/package_json_type/none/deno.jsonc new file mode 100644 index 0000000000..35f64c86f4 --- /dev/null +++ b/tests/specs/run/package_json_type/none/deno.jsonc @@ -0,0 +1,5 @@ +{ + "unstable": [ + "detect-cjs" + ] +} diff --git a/tests/specs/run/package_json_type/none/main_cjs.js b/tests/specs/run/package_json_type/none/main_cjs.js new file mode 100644 index 0000000000..365e8e06f8 --- /dev/null +++ b/tests/specs/run/package_json_type/none/main_cjs.js @@ -0,0 +1,2 @@ +const { add } = require("./add"); +console.log(add(1, 2)); diff --git a/tests/specs/run/package_json_type/none/main_cjs.out b/tests/specs/run/package_json_type/none/main_cjs.out new file mode 100644 index 0000000000..8d34808fb1 --- /dev/null +++ b/tests/specs/run/package_json_type/none/main_cjs.out @@ -0,0 +1,12 @@ +error: Uncaught (in promise) ReferenceError: require is not defined +const { add } = require("./add"); + ^ + at file:///[WILDLINE] + + info: Deno supports CommonJS modules in .cjs files, or when there's a package.json + with "type": "commonjs" option and --unstable-detect-cjs flag is used. + hint: Rewrite this module to ESM, + or change the file extension to .cjs, + or add package.json next to the file with "type": "commonjs" option + and pass --unstable-detect-cjs flag. + docs: https://docs.deno.com/go/commonjs diff --git a/tests/specs/run/package_json_type/none/main_esm.js b/tests/specs/run/package_json_type/none/main_esm.js new file mode 100644 index 0000000000..8c55f673b0 --- /dev/null +++ b/tests/specs/run/package_json_type/none/main_esm.js @@ -0,0 +1,3 @@ +import { add } from "./add.js"; + +console.log(add(1, 2)); diff --git a/tests/specs/run/package_json_type/none/main_esm.out b/tests/specs/run/package_json_type/none/main_esm.out new file mode 100644 index 0000000000..5f16c5f350 --- /dev/null +++ b/tests/specs/run/package_json_type/none/main_esm.out @@ -0,0 +1,4 @@ +error: Uncaught SyntaxError: The requested module './add.js' does not provide an export named 'add' +import { add } from "./add.js"; + ^ + at (file:///[WILDLINE]) diff --git a/tests/specs/run/package_json_type/none/package.json b/tests/specs/run/package_json_type/none/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/run/package_json_type/none/package.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/run/package_json_type/none/sub_folder_cjs.js b/tests/specs/run/package_json_type/none/sub_folder_cjs.js new file mode 100644 index 0000000000..ad04e67301 --- /dev/null +++ b/tests/specs/run/package_json_type/none/sub_folder_cjs.js @@ -0,0 +1,3 @@ +import { add } from "./commonjs/add.js"; + +console.log(add(1, 2)); diff --git a/tests/specs/run/redirect_javascript/__test__.jsonc b/tests/specs/run/redirect_javascript/__test__.jsonc index 1fd0b4cb12..d999a67f91 100644 --- a/tests/specs/run/redirect_javascript/__test__.jsonc +++ b/tests/specs/run/redirect_javascript/__test__.jsonc @@ -1,4 +1,4 @@ { - "args": "run --quiet --reload main.js", + "args": "run --allow-import --quiet --reload main.js", "output": "main.out" } diff --git a/tests/specs/run/remote_cjs_main/__test__.jsonc b/tests/specs/run/remote_cjs_main/__test__.jsonc new file mode 100644 index 0000000000..f45d09406e --- /dev/null +++ b/tests/specs/run/remote_cjs_main/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run http://localhost:4545/run/add.cjs", + "output": "output.out", + "exitCode": 1 +} diff --git a/tests/specs/run/remote_cjs_main/output.out b/tests/specs/run/remote_cjs_main/output.out new file mode 100644 index 0000000000..f75c33907a --- /dev/null +++ b/tests/specs/run/remote_cjs_main/output.out @@ -0,0 +1,3 @@ +Download http://localhost:4545/run/add.cjs +error: Expected a JavaScript or TypeScript module, but identified a Cjs module. Importing these types of modules is currently not supported. + Specifier: http://localhost:4545/run/add.cjs diff --git a/tests/specs/run/require_esm/__test__.jsonc b/tests/specs/run/require_esm/__test__.jsonc new file mode 100644 index 0000000000..ee7d1eee96 --- /dev/null +++ b/tests/specs/run/require_esm/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A main.cjs", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/run/require_esm/async.js b/tests/specs/run/require_esm/async.js new file mode 100644 index 0000000000..b116c66acf --- /dev/null +++ b/tests/specs/run/require_esm/async.js @@ -0,0 +1,2 @@ +export const async_js = 1; +await {}; diff --git a/tests/specs/run/require_esm/main.cjs b/tests/specs/run/require_esm/main.cjs new file mode 100644 index 0000000000..b3418abe1a --- /dev/null +++ b/tests/specs/run/require_esm/main.cjs @@ -0,0 +1,5 @@ +"use strict"; + +console.log(require("./sync.js")); +console.log(require("./sync.mjs")); +require("./async.js"); diff --git a/tests/specs/run/require_esm/main.out b/tests/specs/run/require_esm/main.out new file mode 100644 index 0000000000..d17b1ead55 --- /dev/null +++ b/tests/specs/run/require_esm/main.out @@ -0,0 +1,13 @@ +[Module: null prototype] { sync_js: 1 } +[Module: null prototype] { sync_mjs: 1 } +error: Uncaught Error: Top-level await is not allowed in synchronous evaluation + at loadESMFromCJS (node:module:[WILDCARD]) + at Module._compile (node:module:[WILDCARD]) + at Object.Module._extensions..js (node:module:[WILDCARD]) + at Module.load (node:module:[WILDCARD]) + at Function.Module._load (node:module:[WILDCARD]) + at Module.require (node:module:[WILDCARD]) + at require (node:module:[WILDCARD]) + at Object. (file:[WILDCARD]/tests/specs/run/require_esm/main.cjs:[WILDCARD]) + at Object. (file:[WILDCARD]/tests/specs/run/require_esm/main.cjs:[WILDCARD]) + at Module._compile (node:module:[WILDCARD]) diff --git a/tests/specs/run/require_esm/sync.js b/tests/specs/run/require_esm/sync.js new file mode 100644 index 0000000000..ca40d4eb78 --- /dev/null +++ b/tests/specs/run/require_esm/sync.js @@ -0,0 +1 @@ +export const sync_js = 1; diff --git a/tests/specs/run/require_esm/sync.mjs b/tests/specs/run/require_esm/sync.mjs new file mode 100644 index 0000000000..7a3cc3e276 --- /dev/null +++ b/tests/specs/run/require_esm/sync.mjs @@ -0,0 +1 @@ +export const sync_mjs = 1; diff --git a/tests/specs/run/run_task/__test__.jsonc b/tests/specs/run/run_task/__test__.jsonc index 0d1c82efdd..dcf0e66b85 100644 --- a/tests/specs/run/run_task/__test__.jsonc +++ b/tests/specs/run/run_task/__test__.jsonc @@ -1,5 +1,10 @@ { "tests": { + "deno_run_empty": { + "args": "run", + "output": "empty.out", + "exitCode": 1 + }, "deno_run_task": { "args": "run main", "output": "main.out" @@ -8,6 +13,10 @@ "args": "run not_found", "output": "not_found.out", "exitCode": 1 + }, + "deno_run_task_colon": { + "args": "run main:foo", + "output": "main_foo.out" } } } diff --git a/tests/specs/run/run_task/deno.json b/tests/specs/run/run_task/deno.json index 54772504e8..3597b5b47f 100644 --- a/tests/specs/run/run_task/deno.json +++ b/tests/specs/run/run_task/deno.json @@ -1,5 +1,6 @@ { "tasks": { - "main": "deno run main.ts" + "main": "deno run main.ts", + "main:foo": "deno run main.ts" } } diff --git a/tests/specs/run/run_task/empty.out b/tests/specs/run/run_task/empty.out new file mode 100644 index 0000000000..e9edf494a1 --- /dev/null +++ b/tests/specs/run/run_task/empty.out @@ -0,0 +1,4 @@ +error: [SCRIPT_ARG] may only be omitted with --v8-flags=--help + +Usage: deno run [OPTIONS] [SCRIPT_ARG]... + diff --git a/tests/specs/run/run_task/main_foo.out b/tests/specs/run/run_task/main_foo.out new file mode 100644 index 0000000000..7e5f826328 --- /dev/null +++ b/tests/specs/run/run_task/main_foo.out @@ -0,0 +1,2 @@ +Task main:foo deno run main.ts +main diff --git a/tests/specs/run/sloppy_imports/__test__.jsonc b/tests/specs/run/sloppy_imports/__test__.jsonc index 79aaaba69d..a992f390ba 100644 --- a/tests/specs/run/sloppy_imports/__test__.jsonc +++ b/tests/specs/run/sloppy_imports/__test__.jsonc @@ -1,10 +1,13 @@ { - "steps": [{ - "args": "run main.ts", - "output": "no_sloppy.out", - "exitCode": 1 - }, { - "args": "run --unstable-sloppy-imports main.ts", - "output": "sloppy.out" - }] + "tests": { + "no_sloppy": { + "args": "run --check main.ts", + "output": "no_sloppy.out", + "exitCode": 1 + }, + "sloppy": { + "args": "run --unstable-sloppy-imports --check main.ts", + "output": "sloppy.out" + } + } } diff --git a/tests/specs/run/sloppy_imports/sloppy.out b/tests/specs/run/sloppy_imports/sloppy.out index 170a4bb167..2cc57b6fc3 100644 --- a/tests/specs/run/sloppy_imports/sloppy.out +++ b/tests/specs/run/sloppy_imports/sloppy.out @@ -1,3 +1,4 @@ +Check file:///[WILDLINE]/main.ts [class A] [class B] [class C] diff --git a/tests/specs/run/ts_import_assertions/__test__.jsonc b/tests/specs/run/ts_import_assertions/__test__.jsonc new file mode 100644 index 0000000000..6e3ffb044e --- /dev/null +++ b/tests/specs/run/ts_import_assertions/__test__.jsonc @@ -0,0 +1,22 @@ +{ + "tests": { + "assertion": { + // TODO(2.0): disable import assertion support in TS. + "ignore": true, + "steps": [{ + "args": "run assertion.ts", + "exitCode": 1, + "output": "assertion.out" + }, { + // should output the same because the emit won't be cached + "args": "run assertion.ts", + "exitCode": 1, + "output": "assertion.out" + }] + }, + "with": { + "args": "run with.ts", + "output": "with.out" + } + } +} diff --git a/tests/specs/run/ts_import_assertions/assertion.out b/tests/specs/run/ts_import_assertions/assertion.out new file mode 100644 index 0000000000..3ca7ac8ae5 --- /dev/null +++ b/tests/specs/run/ts_import_assertions/assertion.out @@ -0,0 +1,6 @@ +error: Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword. + +import test from "./data.json" assert { type: "json" }; + + at file:///[WILDLINE]/assertion.ts:1:1 + diff --git a/tests/specs/run/ts_import_assertions/assertion.ts b/tests/specs/run/ts_import_assertions/assertion.ts new file mode 100644 index 0000000000..cb653ffc73 --- /dev/null +++ b/tests/specs/run/ts_import_assertions/assertion.ts @@ -0,0 +1,5 @@ +import test from "./data.json" assert { type: "json" }; +console.log(test); +console.log( + (await import("./data.json", { assert: { type: "json" } })).default, +); diff --git a/tests/specs/run/ts_import_assertions/data.json b/tests/specs/run/ts_import_assertions/data.json new file mode 100644 index 0000000000..e5b07266c5 --- /dev/null +++ b/tests/specs/run/ts_import_assertions/data.json @@ -0,0 +1,3 @@ +{ + "prop": "data" +} diff --git a/tests/specs/run/ts_import_assertions/with.out b/tests/specs/run/ts_import_assertions/with.out new file mode 100644 index 0000000000..6141f8c07f --- /dev/null +++ b/tests/specs/run/ts_import_assertions/with.out @@ -0,0 +1,2 @@ +{ prop: "data" } +{ prop: "data" } diff --git a/tests/specs/run/ts_import_assertions/with.ts b/tests/specs/run/ts_import_assertions/with.ts new file mode 100644 index 0000000000..58b7fb03d3 --- /dev/null +++ b/tests/specs/run/ts_import_assertions/with.ts @@ -0,0 +1,3 @@ +import test from "./data.json" with { type: "json" }; +console.log(test); +console.log((await import("./data.json", { with: { type: "json" } })).default); diff --git a/tests/specs/run/unstable/__test__.jsonc b/tests/specs/run/unstable/__test__.jsonc new file mode 100644 index 0000000000..3ddcdb583c --- /dev/null +++ b/tests/specs/run/unstable/__test__.jsonc @@ -0,0 +1,29 @@ +{ + "tests": { + "broadcast_channel": { + "args": "run broadcast_channel.ts", + "exitCode": 1, + "output": "broadcast_channel.out" + }, + "cron": { + "args": "run cron.ts", + "exitCode": 1, + "output": "cron.out" + }, + "http_wss": { + "args": "run http_wss.ts", + "exitCode": 1, + "output": "http_wss.out" + }, + "kv": { + "args": "run kv.ts", + "exitCode": 1, + "output": "kv.out" + }, + "temporal": { + "args": "run temporal.ts", + "exitCode": 1, + "output": "temporal.out" + } + } +} diff --git a/tests/specs/run/unstable/broadcast_channel.out b/tests/specs/run/unstable/broadcast_channel.out new file mode 100644 index 0000000000..8a9a09ef24 --- /dev/null +++ b/tests/specs/run/unstable/broadcast_channel.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: BroadcastChannel is not defined +new BroadcastChannel("hello"); +^ + at [WILDCARD]broadcast_channel.ts:1:1 + + info: BroadcastChannel is an unstable API. + hint: Run again with `--unstable-broadcast-channel` flag to enable this API. diff --git a/tests/specs/run/unstable/broadcast_channel.ts b/tests/specs/run/unstable/broadcast_channel.ts new file mode 100644 index 0000000000..5fcbc34b57 --- /dev/null +++ b/tests/specs/run/unstable/broadcast_channel.ts @@ -0,0 +1 @@ +new BroadcastChannel("hello"); diff --git a/tests/specs/run/unstable/cron.out b/tests/specs/run/unstable/cron.out new file mode 100644 index 0000000000..76558bb384 --- /dev/null +++ b/tests/specs/run/unstable/cron.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) TypeError: Deno.cron is not a function +Deno.cron(); + ^ + at [WILDCARD]cron.ts:1:6 + + info: Deno.cron() is an unstable API. + hint: Run again with `--unstable-cron` flag to enable this API. diff --git a/tests/specs/run/unstable/cron.ts b/tests/specs/run/unstable/cron.ts new file mode 100644 index 0000000000..8ec4f21ea2 --- /dev/null +++ b/tests/specs/run/unstable/cron.ts @@ -0,0 +1 @@ +Deno.cron(); diff --git a/tests/specs/run/unstable/http_wss.out b/tests/specs/run/unstable/http_wss.out new file mode 100644 index 0000000000..f62deaee89 --- /dev/null +++ b/tests/specs/run/unstable/http_wss.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: WebSocketStream is not defined +const wss = new WebSocketStream("ws://127.0.0.1:4513"); + ^ + at [WILDCARD]http_wss.ts:1:13 + + info: new WebSocketStream() is an unstable API. + hint: Run again with `--unstable-net` flag to enable this API. diff --git a/tests/specs/run/unstable/http_wss.ts b/tests/specs/run/unstable/http_wss.ts new file mode 100644 index 0000000000..f4885f20fb --- /dev/null +++ b/tests/specs/run/unstable/http_wss.ts @@ -0,0 +1 @@ +const wss = new WebSocketStream("ws://127.0.0.1:4513"); diff --git a/tests/specs/run/unstable/kv.out b/tests/specs/run/unstable/kv.out new file mode 100644 index 0000000000..d0916604c6 --- /dev/null +++ b/tests/specs/run/unstable/kv.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) TypeError: Deno.openKv is not a function +const db = await Deno.openKv(); + ^ + at [WILDCARD]kv.ts:1:23 + + info: Deno.openKv() is an unstable API. + hint: Run again with `--unstable-kv` flag to enable this API. diff --git a/tests/specs/run/unstable/kv.ts b/tests/specs/run/unstable/kv.ts new file mode 100644 index 0000000000..591bc3e373 --- /dev/null +++ b/tests/specs/run/unstable/kv.ts @@ -0,0 +1 @@ +const db = await Deno.openKv(); diff --git a/tests/specs/run/unstable/temporal.out b/tests/specs/run/unstable/temporal.out new file mode 100644 index 0000000000..f29f9acf8f --- /dev/null +++ b/tests/specs/run/unstable/temporal.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: Temporal is not defined +Temporal.Now.instant(); +^ + at [WILDCARD]temporal.ts:1:1 + + info: Temporal is an unstable API. + hint: Run again with `--unstable-temporal` flag to enable this API. diff --git a/tests/testdata/run/unstable_temporal_api/missing_flag.js b/tests/specs/run/unstable/temporal.ts similarity index 100% rename from tests/testdata/run/unstable_temporal_api/missing_flag.js rename to tests/specs/run/unstable/temporal.ts diff --git a/tests/specs/run/unstable_temporal_api/__test__.jsonc b/tests/specs/run/unstable_temporal_api/__test__.jsonc new file mode 100644 index 0000000000..226e0ce048 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api/__test__.jsonc @@ -0,0 +1,19 @@ +{ + "tests": { + "basic": { + "args": "run --no-config --unstable-temporal --check main.ts", + "output": "main.out", + "exitCode": 0 + }, + "config": { + "args": "run --unstable-temporal --check main.ts", + "output": "main.out", + "exitCode": 0 + }, + "missing_flag": { + "args": "run --no-config missing_flag.js", + "output": "missing_flag.out", + "exitCode": 1 + } + } +} diff --git a/tests/testdata/run/unstable_temporal_api/deno.json b/tests/specs/run/unstable_temporal_api/deno.json similarity index 100% rename from tests/testdata/run/unstable_temporal_api/deno.json rename to tests/specs/run/unstable_temporal_api/deno.json diff --git a/tests/testdata/run/unstable_temporal_api/main.out b/tests/specs/run/unstable_temporal_api/main.out similarity index 85% rename from tests/testdata/run/unstable_temporal_api/main.out rename to tests/specs/run/unstable_temporal_api/main.out index 46d25c3ea7..d916a4cc20 100644 --- a/tests/testdata/run/unstable_temporal_api/main.out +++ b/tests/specs/run/unstable_temporal_api/main.out @@ -8,5 +8,3 @@ Temporal.PlainDateTime 1995-12-07T15:00:00 Temporal.PlainYearMonth 2020-10 Temporal.PlainMonthDay 07-14 Temporal.Duration PT130H20M -Temporal.TimeZone Africa/Cairo -Temporal.Calendar 1999-12-31 diff --git a/tests/testdata/run/unstable_temporal_api/main.ts b/tests/specs/run/unstable_temporal_api/main.ts similarity index 83% rename from tests/testdata/run/unstable_temporal_api/main.ts rename to tests/specs/run/unstable_temporal_api/main.ts index 1641b90bf8..351b30e7d6 100644 --- a/tests/testdata/run/unstable_temporal_api/main.ts +++ b/tests/specs/run/unstable_temporal_api/main.ts @@ -57,15 +57,3 @@ console.log( minutes: 20, }), ); -console.log( - "Temporal.TimeZone", - Temporal.TimeZone.from("Africa/Cairo"), -); -console.log( - "Temporal.Calendar", - Temporal.Calendar.from("iso8601").dateFromFields({ - year: 1999, - month: 12, - day: 31, - }, {}), -); diff --git a/tests/specs/run/unstable_temporal_api/missing_flag.js b/tests/specs/run/unstable_temporal_api/missing_flag.js new file mode 100644 index 0000000000..92aed79314 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api/missing_flag.js @@ -0,0 +1 @@ +Temporal.Now.instant(); diff --git a/tests/testdata/run/unstable_temporal_api/missing_flag.out b/tests/specs/run/unstable_temporal_api/missing_flag.out similarity index 54% rename from tests/testdata/run/unstable_temporal_api/missing_flag.out rename to tests/specs/run/unstable_temporal_api/missing_flag.out index 8f8e23e706..03ed5abb96 100644 --- a/tests/testdata/run/unstable_temporal_api/missing_flag.out +++ b/tests/specs/run/unstable_temporal_api/missing_flag.out @@ -2,3 +2,6 @@ error: Uncaught (in promise) ReferenceError: Temporal is not defined Temporal.Now.instant(); ^ at [WILDCARD]missing_flag.js:1:1 + + info: Temporal is an unstable API. + hint: Run again with `--unstable-temporal` flag to enable this API. diff --git a/tests/specs/run/unstable_temporal_api_list/__test__.jsonc b/tests/specs/run/unstable_temporal_api_list/__test__.jsonc new file mode 100644 index 0000000000..b5b12ed260 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_list/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --no-config --unstable-temporal --check main.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/specs/run/unstable_temporal_api_list/main.out b/tests/specs/run/unstable_temporal_api_list/main.out new file mode 100644 index 0000000000..bdfeab5ace --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_list/main.out @@ -0,0 +1,148 @@ +Check [WILDCARD] +Temporal +[ + "Duration", + "Instant", + "Now", + "PlainDate", + "PlainDateTime", + "PlainMonthDay", + "PlainTime", + "PlainYearMonth", + "ZonedDateTime" +] +Temporal.Now +[ + "instant", + "plainDateISO", + "plainDateTimeISO", + "plainTimeISO", + "timeZoneId", + "zonedDateTimeISO" +] +Temporal.Instant.prototype +[ + "add", + "constructor", + "epochMilliseconds", + "epochNanoseconds", + "equals", + "round", + "since", + "subtract", + "toJSON", + "toLocaleString", + "toString", + "toZonedDateTimeISO", + "until", + "valueOf" +] +Temporal.ZonedDateTime.prototype +[ + "add", "calendarId", "constructor", + "day", "dayOfWeek", "dayOfYear", + "daysInMonth", "daysInWeek", "daysInYear", + "epochMilliseconds", "epochNanoseconds", "equals", + "era", "eraYear", "hour", + "hoursInDay", "inLeapYear", "microsecond", + "millisecond", "minute", "month", + "monthCode", "monthsInYear", "nanosecond", + "offset", "offsetNanoseconds", "round", + "second", "since", "startOfDay", + "subtract", "timeZoneId", "toInstant", + "toJSON", "toLocaleString", "toPlainDate", + "toPlainDateTime", "toPlainTime", "toString", + "until", "valueOf", "weekOfYear", + "with", "withCalendar", "withPlainTime", + "withTimeZone", "year" +] +Temporal.PlainDate.prototype +[ + "add", "calendarId", + "constructor", "day", + "dayOfWeek", "dayOfYear", + "daysInMonth", "daysInWeek", + "daysInYear", "equals", + "era", "eraYear", + "inLeapYear", "month", + "monthCode", "monthsInYear", + "since", "subtract", + "toJSON", "toLocaleString", + "toPlainDateTime", "toPlainMonthDay", + "toPlainYearMonth", "toString", + "toZonedDateTime", "until", + "valueOf", "weekOfYear", + "with", "withCalendar", + "year" +] +Temporal.PlainTime.prototype +[ + "add", "constructor", + "equals", "hour", + "microsecond", "millisecond", + "minute", "nanosecond", + "round", "second", + "since", "subtract", + "toJSON", "toLocaleString", + "toString", "until", + "valueOf", "with" +] +Temporal.PlainDateTime.prototype +[ + "add", "calendarId", "constructor", + "day", "dayOfWeek", "dayOfYear", + "daysInMonth", "daysInWeek", "daysInYear", + "equals", "era", "eraYear", + "hour", "inLeapYear", "microsecond", + "millisecond", "minute", "month", + "monthCode", "monthsInYear", "nanosecond", + "round", "second", "since", + "subtract", "toJSON", "toLocaleString", + "toPlainDate", "toPlainTime", "toString", + "toZonedDateTime", "until", "valueOf", + "weekOfYear", "with", "withCalendar", + "withPlainTime", "year" +] +Temporal.PlainYearMonth.prototype +[ + "add", "calendarId", + "constructor", "daysInMonth", + "daysInYear", "equals", + "era", "eraYear", + "inLeapYear", "month", + "monthCode", "monthsInYear", + "since", "subtract", + "toJSON", "toLocaleString", + "toPlainDate", "toString", + "until", "valueOf", + "with", "year" +] +Temporal.PlainMonthDay.prototype +[ + "calendarId", + "constructor", + "day", + "equals", + "monthCode", + "toJSON", + "toLocaleString", + "toPlainDate", + "toString", + "valueOf", + "with" +] +Temporal.Duration.prototype +[ + "abs", "add", + "blank", "constructor", + "days", "hours", + "microseconds", "milliseconds", + "minutes", "months", + "nanoseconds", "negated", + "round", "seconds", + "sign", "subtract", + "toJSON", "toLocaleString", + "toString", "total", + "valueOf", "weeks", + "with", "years" +] diff --git a/tests/specs/run/unstable_temporal_api_list/main.ts b/tests/specs/run/unstable_temporal_api_list/main.ts new file mode 100644 index 0000000000..548bb320aa --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_list/main.ts @@ -0,0 +1,37 @@ +console.log("Temporal"); +console.log(Object.getOwnPropertyNames(Temporal).sort()); + +console.log("Temporal.Now"); +console.log(Object.getOwnPropertyNames(Temporal.Now).sort()); + +console.log("Temporal.Instant.prototype"); +console.log(Object.getOwnPropertyNames(Temporal.Instant.prototype).sort()); + +console.log("Temporal.ZonedDateTime.prototype"); +console.log( + Object.getOwnPropertyNames(Temporal.ZonedDateTime.prototype).sort(), +); + +console.log("Temporal.PlainDate.prototype"); +console.log(Object.getOwnPropertyNames(Temporal.PlainDate.prototype).sort()); + +console.log("Temporal.PlainTime.prototype"); +console.log(Object.getOwnPropertyNames(Temporal.PlainTime.prototype).sort()); + +console.log("Temporal.PlainDateTime.prototype"); +console.log( + Object.getOwnPropertyNames(Temporal.PlainDateTime.prototype).sort(), +); + +console.log("Temporal.PlainYearMonth.prototype"); +console.log( + Object.getOwnPropertyNames(Temporal.PlainYearMonth.prototype).sort(), +); + +console.log("Temporal.PlainMonthDay.prototype"); +console.log( + Object.getOwnPropertyNames(Temporal.PlainMonthDay.prototype).sort(), +); + +console.log("Temporal.Duration.prototype"); +console.log(Object.getOwnPropertyNames(Temporal.Duration.prototype).sort()); diff --git a/tests/specs/run/unstable_temporal_api_patch/__test__.jsonc b/tests/specs/run/unstable_temporal_api_patch/__test__.jsonc new file mode 100644 index 0000000000..b5b12ed260 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_patch/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --no-config --unstable-temporal --check main.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/specs/run/unstable_temporal_api_patch/main.out b/tests/specs/run/unstable_temporal_api_patch/main.out new file mode 100644 index 0000000000..a17d3a9e20 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_patch/main.out @@ -0,0 +1,7 @@ +Check [WILDCARD] +[WILDCARD] +undefined +iso8601 +UTC +undefined +undefined diff --git a/tests/specs/run/unstable_temporal_api_patch/main.ts b/tests/specs/run/unstable_temporal_api_patch/main.ts new file mode 100644 index 0000000000..6a40780535 --- /dev/null +++ b/tests/specs/run/unstable_temporal_api_patch/main.ts @@ -0,0 +1,11 @@ +console.log(Temporal.Now.timeZoneId()); +// @ts-expect-error: undefined check +console.log(Temporal.Now.timeZone); + +const zoned = new Temporal.ZonedDateTime(0n, "UTC"); +console.log(zoned.calendarId); +console.log(zoned.timeZoneId); +// @ts-expect-error: undefined check +console.log(zoned.calendar); +// @ts-expect-error: undefined check +console.log(zoned.timeZone); diff --git a/tests/specs/run/window/__test__.jsonc b/tests/specs/run/window/__test__.jsonc new file mode 100644 index 0000000000..1ee4449b57 --- /dev/null +++ b/tests/specs/run/window/__test__.jsonc @@ -0,0 +1,19 @@ +{ + "tests": { + "window1": { + "args": "run window1.js", + "exitCode": 1, + "output": "window1.out" + }, + "window2": { + "args": "run window2.js", + "exitCode": 1, + "output": "window2.out" + }, + "window3": { + "args": "run window3.js", + "exitCode": 1, + "output": "window3.out" + } + } +} diff --git a/tests/specs/run/window/window1.js b/tests/specs/run/window/window1.js new file mode 100644 index 0000000000..a480d4c2c6 --- /dev/null +++ b/tests/specs/run/window/window1.js @@ -0,0 +1 @@ +"TextEncoder" in window; diff --git a/tests/specs/run/window/window1.out b/tests/specs/run/window/window1.out new file mode 100644 index 0000000000..4e16744252 --- /dev/null +++ b/tests/specs/run/window/window1.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: window is not defined +"TextEncoder" in window; + ^ + at [WILDCARD]window1.js:1:18 + + info: window global is not available in Deno 2. + hint: Replace `window` with `globalThis`. diff --git a/tests/specs/run/window/window2.js b/tests/specs/run/window/window2.js new file mode 100644 index 0000000000..0fdf5dcb98 --- /dev/null +++ b/tests/specs/run/window/window2.js @@ -0,0 +1 @@ +window.atob; diff --git a/tests/specs/run/window/window2.out b/tests/specs/run/window/window2.out new file mode 100644 index 0000000000..7d00cd7ed1 --- /dev/null +++ b/tests/specs/run/window/window2.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: window is not defined +window.atob; +^ + at [WILDCARD]window2.js:1:1 + + info: window global is not available in Deno 2. + hint: Replace `window` with `globalThis`. diff --git a/tests/specs/run/window/window3.js b/tests/specs/run/window/window3.js new file mode 100644 index 0000000000..24fa32b5ac --- /dev/null +++ b/tests/specs/run/window/window3.js @@ -0,0 +1 @@ +window.navigator; diff --git a/tests/specs/run/window/window3.out b/tests/specs/run/window/window3.out new file mode 100644 index 0000000000..9a157975f8 --- /dev/null +++ b/tests/specs/run/window/window3.out @@ -0,0 +1,7 @@ +error: Uncaught (in promise) ReferenceError: window is not defined +window.navigator; +^ + at [WILDCARD]window3.js:1:1 + + info: window global is not available in Deno 2. + hint: Replace `window` with `globalThis`. diff --git a/tests/specs/run/workspaces/explicit_import_map/__test__.jsonc b/tests/specs/run/workspaces/explicit_import_map/__test__.jsonc index 2bd0d3bcce..e9bb0442be 100644 --- a/tests/specs/run/workspaces/explicit_import_map/__test__.jsonc +++ b/tests/specs/run/workspaces/explicit_import_map/__test__.jsonc @@ -1,5 +1,13 @@ { - "args": "run -A --import-map=./import_map.json main.ts", - "output": "main.out", - "tempDir": true + "tempDir": true, + "steps": [ + { + "args": "install --import-map=./import_map.json", + "output": "install.out" + }, + { + "args": "run -A --import-map=./import_map.json main.ts", + "output": "main.out" + } + ] } diff --git a/tests/specs/run/workspaces/explicit_import_map/install.out b/tests/specs/run/workspaces/explicit_import_map/install.out new file mode 100644 index 0000000000..51d2fb9a28 --- /dev/null +++ b/tests/specs/run/workspaces/explicit_import_map/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/chalk +Download http://localhost:4260/chalk/chalk-5.0.1.tgz +Initialize chalk@5.0.1 diff --git a/tests/specs/run/workspaces/explicit_import_map/main.out b/tests/specs/run/workspaces/explicit_import_map/main.out index c420c18532..ce01362503 100644 --- a/tests/specs/run/workspaces/explicit_import_map/main.out +++ b/tests/specs/run/workspaces/explicit_import_map/main.out @@ -1,2 +1 @@ -[WILDCARD] hello diff --git a/tests/specs/schema.json b/tests/specs/schema.json index bf57b4826a..8f3953ee44 100644 --- a/tests/specs/schema.json +++ b/tests/specs/schema.json @@ -50,6 +50,9 @@ }, "exitCode": { "type": "integer" + }, + "ignore": { + "type": "boolean" } } }, @@ -77,6 +80,9 @@ "items": { "$ref": "#/definitions/single_test" } + }, + "ignore": { + "type": "boolean" } } }, { @@ -126,6 +132,9 @@ "additionalProperties": { "$ref": "#/definitions/single_or_multi_step_test" } + }, + "ignore": { + "type": "boolean" } } } diff --git a/tests/specs/serve/basic/__test__.jsonc b/tests/specs/serve/basic/__test__.jsonc index a8eaca0b6d..be63f793aa 100644 --- a/tests/specs/serve/basic/__test__.jsonc +++ b/tests/specs/serve/basic/__test__.jsonc @@ -3,12 +3,12 @@ "tests": { "basic_win": { "if": "windows", - "args": "serve --host 0.0.0.0 --port 12345 main.ts", + "args": "serve --check --host 0.0.0.0 --port 12345 main.ts", "output": "main.out" }, "basic_not_win": { "if": "unix", - "args": "serve --host 0.0.0.0 --port 12345 main.ts", + "args": "serve --check --host 0.0.0.0 --port 12345 main.ts", "output": "main_not_win.out" } } diff --git a/tests/specs/serve/basic/main.out b/tests/specs/serve/basic/main.out index e79d76af53..8247920e20 100644 --- a/tests/specs/serve/basic/main.out +++ b/tests/specs/serve/basic/main.out @@ -1 +1,2 @@ +Check [WILDCARD] deno serve: Listening on http://localhost:12345/ diff --git a/tests/specs/serve/basic/main.ts b/tests/specs/serve/basic/main.ts index 9e299ab219..8aa061b1e9 100644 --- a/tests/specs/serve/basic/main.ts +++ b/tests/specs/serve/basic/main.ts @@ -15,4 +15,4 @@ export default { fetch(req) { return new Response("Hello world!"); }, -}; +} satisfies Deno.ServeDefaultExport; diff --git a/tests/specs/serve/basic/main_not_win.out b/tests/specs/serve/basic/main_not_win.out index cbfd3395eb..6b4a66750f 100644 --- a/tests/specs/serve/basic/main_not_win.out +++ b/tests/specs/serve/basic/main_not_win.out @@ -1 +1,2 @@ +Check [WILDCARD] deno serve: Listening on http://0.0.0.0:12345/ diff --git a/tests/specs/serve/conn_info/__test__.jsonc b/tests/specs/serve/conn_info/__test__.jsonc new file mode 100644 index 0000000000..faefad0ad9 --- /dev/null +++ b/tests/specs/serve/conn_info/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "args": "serve --check --port 12468 main.ts", + "output": "main.out", + "tempDir": true, + "exitCode": 0 +} diff --git a/tests/specs/serve/conn_info/main.out b/tests/specs/serve/conn_info/main.out new file mode 100644 index 0000000000..790c4775dc --- /dev/null +++ b/tests/specs/serve/conn_info/main.out @@ -0,0 +1,3 @@ +Check [WILDCARD]main.ts +deno serve: Listening on http://[WILDCARD] +ServeHandlerInfo {} diff --git a/tests/specs/serve/conn_info/main.ts b/tests/specs/serve/conn_info/main.ts new file mode 100644 index 0000000000..dbc1b7f070 --- /dev/null +++ b/tests/specs/serve/conn_info/main.ts @@ -0,0 +1,19 @@ +(async () => { + for (let i = 0; i < 1000; i++) { + try { + const resp = await fetch("http://localhost:12468/"); + Deno.exit(0); + } catch { + await new Promise((r) => setTimeout(r, 10)); + } + } + + Deno.exit(2); +})(); + +export default { + fetch(request, connInfo) { + console.log(connInfo); + return new Response("Hello world!"); + }, +} satisfies Deno.ServeDefaultExport; diff --git a/tests/specs/task/additional_args/__test__.jsonc b/tests/specs/task/additional_args/__test__.jsonc new file mode 100644 index 0000000000..713c5a6b60 --- /dev/null +++ b/tests/specs/task/additional_args/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json echo 2", + "output": "task_additional_args.out" +} diff --git a/tests/specs/task/additional_args/deno.json b/tests/specs/task/additional_args/deno.json new file mode 100644 index 0000000000..c1a379c46a --- /dev/null +++ b/tests/specs/task/additional_args/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo": "echo 1" + } +} diff --git a/tests/testdata/task/deno_json/task_additional_args.out b/tests/specs/task/additional_args/task_additional_args.out similarity index 100% rename from tests/testdata/task/deno_json/task_additional_args.out rename to tests/specs/task/additional_args/task_additional_args.out diff --git a/tests/specs/task/additional_args_nested_strings/__test__.jsonc b/tests/specs/task/additional_args_nested_strings/__test__.jsonc new file mode 100644 index 0000000000..fe0c326b83 --- /dev/null +++ b/tests/specs/task/additional_args_nested_strings/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json echo string \"quoted string\"", + "output": "task_additional_args_nested_strings.out" +} diff --git a/tests/specs/task/additional_args_nested_strings/deno.json b/tests/specs/task/additional_args_nested_strings/deno.json new file mode 100644 index 0000000000..c1a379c46a --- /dev/null +++ b/tests/specs/task/additional_args_nested_strings/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo": "echo 1" + } +} diff --git a/tests/testdata/task/deno_json/task_additional_args_nested_strings.out b/tests/specs/task/additional_args_nested_strings/task_additional_args_nested_strings.out similarity index 100% rename from tests/testdata/task/deno_json/task_additional_args_nested_strings.out rename to tests/specs/task/additional_args_nested_strings/task_additional_args_nested_strings.out diff --git a/tests/specs/task/additional_args_no_logic/__test__.jsonc b/tests/specs/task/additional_args_no_logic/__test__.jsonc new file mode 100644 index 0000000000..dc4fbf09a9 --- /dev/null +++ b/tests/specs/task/additional_args_no_logic/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json echo || echo 5", + "output": "task_additional_args_no_logic.out" +} diff --git a/tests/specs/task/additional_args_no_logic/deno.json b/tests/specs/task/additional_args_no_logic/deno.json new file mode 100644 index 0000000000..c1a379c46a --- /dev/null +++ b/tests/specs/task/additional_args_no_logic/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo": "echo 1" + } +} diff --git a/tests/testdata/task/deno_json/task_additional_args_no_logic.out b/tests/specs/task/additional_args_no_logic/task_additional_args_no_logic.out similarity index 100% rename from tests/testdata/task/deno_json/task_additional_args_no_logic.out rename to tests/specs/task/additional_args_no_logic/task_additional_args_no_logic.out diff --git a/tests/specs/task/additional_args_no_shell_expansion/__test__.jsonc b/tests/specs/task/additional_args_no_shell_expansion/__test__.jsonc new file mode 100644 index 0000000000..cb467ea83b --- /dev/null +++ b/tests/specs/task/additional_args_no_shell_expansion/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json echo $(echo 5)", + "output": "task_additional_args_no_shell_expansion.out" +} diff --git a/tests/specs/task/additional_args_no_shell_expansion/deno.json b/tests/specs/task/additional_args_no_shell_expansion/deno.json new file mode 100644 index 0000000000..c1a379c46a --- /dev/null +++ b/tests/specs/task/additional_args_no_shell_expansion/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo": "echo 1" + } +} diff --git a/tests/testdata/task/deno_json/task_additional_args_no_shell_expansion.out b/tests/specs/task/additional_args_no_shell_expansion/task_additional_args_no_shell_expansion.out similarity index 100% rename from tests/testdata/task/deno_json/task_additional_args_no_shell_expansion.out rename to tests/specs/task/additional_args_no_shell_expansion/task_additional_args_no_shell_expansion.out diff --git a/tests/specs/task/bin_package/deno.json b/tests/specs/task/bin_package/deno.json index 176354f98f..fbd70ec480 100644 --- a/tests/specs/task/bin_package/deno.json +++ b/tests/specs/task/bin_package/deno.json @@ -1,3 +1,3 @@ { - "nodeModulesDir": true + "nodeModulesDir": "auto" } diff --git a/tests/specs/task/bin_package/task.out b/tests/specs/task/bin_package/task.out index 69b4f75082..d2c130905a 100644 --- a/tests/specs/task/bin_package/task.out +++ b/tests/specs/task/bin_package/task.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/bin/1.0.0.tgz Initialize @denotest/bin@1.0.0 Task sayhi cli-esm hi hello diff --git a/tests/specs/task/bin_pkg_with_scope_auto/__test__.jsonc b/tests/specs/task/bin_pkg_with_scope_auto/__test__.jsonc new file mode 100644 index 0000000000..2e126f6b16 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_auto/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "task bin extra", + "output": "bin_auto.out" +} diff --git a/tests/specs/task/bin_pkg_with_scope_auto/bin_auto.out b/tests/specs/task/bin_pkg_with_scope_auto/bin_auto.out new file mode 100644 index 0000000000..1eb196a7aa --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_auto/bin_auto.out @@ -0,0 +1,14 @@ +Download http://localhost:4260/@denotest%2fbin +[UNORDERED_START] +Download http://localhost:4260/@denotest/bin/0.5.0.tgz +Initialize @denotest/bin@0.5.0 +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +Initialize @denotest/bin@1.0.0 +[UNORDERED_END] +Task bin bin hi && cli-esm testing this out && npx cli-cjs test "extra" +hi +testing +this +out +test +extra diff --git a/tests/specs/task/bin_pkg_with_scope_auto/bin_none.out b/tests/specs/task/bin_pkg_with_scope_auto/bin_none.out new file mode 100644 index 0000000000..f44b234bf3 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_auto/bin_none.out @@ -0,0 +1,12 @@ +Download http://localhost:4260/@denotest%2fbin +[UNORDERED_START] +Download http://localhost:4260/@denotest/bin/0.5.0.tgz +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +[UNORDERED_END] +Task bin bin hi && cli-esm testing this out && npx cli-cjs test "extra" +hi +testing +this +out +test +extra diff --git a/tests/specs/task/bin_pkg_with_scope_auto/deno.json b/tests/specs/task/bin_pkg_with_scope_auto/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_auto/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/task/bin_pkg_with_scope_auto/package.json b/tests/specs/task/bin_pkg_with_scope_auto/package.json new file mode 100644 index 0000000000..2ee4c2bbb1 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_auto/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "bin": "bin hi && cli-esm testing this out && npx cli-cjs test" + }, + "dependencies": { + "@denotest/bin": "0.5", + "other": "npm:@denotest/bin@1.0" + } +} diff --git a/tests/specs/task/bin_pkg_with_scope_none/__test__.jsonc b/tests/specs/task/bin_pkg_with_scope_none/__test__.jsonc new file mode 100644 index 0000000000..9f88b275fd --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_none/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "tempDir": true, + "args": "task bin extra", + "output": "bin_none.out" +} diff --git a/tests/specs/task/bin_pkg_with_scope_none/bin_none.out b/tests/specs/task/bin_pkg_with_scope_none/bin_none.out new file mode 100644 index 0000000000..f44b234bf3 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_none/bin_none.out @@ -0,0 +1,12 @@ +Download http://localhost:4260/@denotest%2fbin +[UNORDERED_START] +Download http://localhost:4260/@denotest/bin/0.5.0.tgz +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +[UNORDERED_END] +Task bin bin hi && cli-esm testing this out && npx cli-cjs test "extra" +hi +testing +this +out +test +extra diff --git a/tests/specs/task/bin_pkg_with_scope_none/deno.json b/tests/specs/task/bin_pkg_with_scope_none/deno.json new file mode 100644 index 0000000000..38af4024b0 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_none/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "none" +} diff --git a/tests/specs/task/bin_pkg_with_scope_none/package.json b/tests/specs/task/bin_pkg_with_scope_none/package.json new file mode 100644 index 0000000000..2ee4c2bbb1 --- /dev/null +++ b/tests/specs/task/bin_pkg_with_scope_none/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "bin": "bin hi && cli-esm testing this out && npx cli-cjs test" + }, + "dependencies": { + "@denotest/bin": "0.5", + "other": "npm:@denotest/bin@1.0" + } +} diff --git a/tests/specs/task/boolean_logic/__test__.jsonc b/tests/specs/task/boolean_logic/__test__.jsonc new file mode 100644 index 0000000000..426a558c00 --- /dev/null +++ b/tests/specs/task/boolean_logic/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json boolean_logic", + "output": "task_boolean_logic.out" +} diff --git a/tests/specs/task/boolean_logic/deno.json b/tests/specs/task/boolean_logic/deno.json new file mode 100644 index 0000000000..4d3aeb4ce2 --- /dev/null +++ b/tests/specs/task/boolean_logic/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "boolean_logic": "sleep 0.1 && echo 3 && echo 4 & echo 1 && echo 2 || echo NOPE" + } +} diff --git a/tests/testdata/task/deno_json/task_boolean_logic.out b/tests/specs/task/boolean_logic/task_boolean_logic.out similarity index 100% rename from tests/testdata/task/deno_json/task_boolean_logic.out rename to tests/specs/task/boolean_logic/task_boolean_logic.out diff --git a/tests/specs/task/both_deno_json_selected/__test__.jsonc b/tests/specs/task/both_deno_json_selected/__test__.jsonc new file mode 100644 index 0000000000..333a314ea4 --- /dev/null +++ b/tests/specs/task/both_deno_json_selected/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json other", + "output": "deno_selected.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/both/deno.json b/tests/specs/task/both_deno_json_selected/deno.json similarity index 100% rename from tests/testdata/task/both/deno.json rename to tests/specs/task/both_deno_json_selected/deno.json diff --git a/tests/testdata/task/both/deno_selected.out b/tests/specs/task/both_deno_json_selected/deno_selected.out similarity index 100% rename from tests/testdata/task/both/deno_selected.out rename to tests/specs/task/both_deno_json_selected/deno_selected.out diff --git a/tests/specs/task/both_no_arg/__test__.jsonc b/tests/specs/task/both_no_arg/__test__.jsonc new file mode 100644 index 0000000000..ad469793b8 --- /dev/null +++ b/tests/specs/task/both_no_arg/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json", + "output": "no_args.out", + "exitCode": 0 +} diff --git a/tests/specs/task/both_no_arg/deno.json b/tests/specs/task/both_no_arg/deno.json new file mode 100644 index 0000000000..1038609a4a --- /dev/null +++ b/tests/specs/task/both_no_arg/deno.json @@ -0,0 +1,6 @@ +{ + "tasks": { + "output": "deno eval 'console.log(1)'", + "other": "deno eval 'console.log(2)'" + } +} diff --git a/tests/testdata/task/both/no_args.out b/tests/specs/task/both_no_arg/no_args.out similarity index 100% rename from tests/testdata/task/both/no_args.out rename to tests/specs/task/both_no_arg/no_args.out diff --git a/tests/testdata/task/both/package.json b/tests/specs/task/both_no_arg/package.json similarity index 100% rename from tests/testdata/task/both/package.json rename to tests/specs/task/both_no_arg/package.json diff --git a/tests/specs/task/both_package_json_selected/__test__.jsonc b/tests/specs/task/both_package_json_selected/__test__.jsonc new file mode 100644 index 0000000000..acdb7892d0 --- /dev/null +++ b/tests/specs/task/both_package_json_selected/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { "args": "task bin asdf", "output": "package_json_selected.out" } + ] +} diff --git a/tests/specs/task/both_package_json_selected/deno.json b/tests/specs/task/both_package_json_selected/deno.json new file mode 100644 index 0000000000..1038609a4a --- /dev/null +++ b/tests/specs/task/both_package_json_selected/deno.json @@ -0,0 +1,6 @@ +{ + "tasks": { + "output": "deno eval 'console.log(1)'", + "other": "deno eval 'console.log(2)'" + } +} diff --git a/tests/specs/task/both_package_json_selected/install.out b/tests/specs/task/both_package_json_selected/install.out new file mode 100644 index 0000000000..08b70a0f21 --- /dev/null +++ b/tests/specs/task/both_package_json_selected/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fbin +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +Initialize @denotest/bin@1.0.0 diff --git a/tests/specs/task/both_package_json_selected/package.json b/tests/specs/task/both_package_json_selected/package.json new file mode 100644 index 0000000000..708ccc6b19 --- /dev/null +++ b/tests/specs/task/both_package_json_selected/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "bin": "cli-esm testing this out", + "output": "echo should never be called or shown" + }, + "dependencies": { + "other": "npm:@denotest/bin@1.0" + } +} diff --git a/tests/specs/task/both_package_json_selected/package_json_selected.out b/tests/specs/task/both_package_json_selected/package_json_selected.out new file mode 100644 index 0000000000..6c42a2efb5 --- /dev/null +++ b/tests/specs/task/both_package_json_selected/package_json_selected.out @@ -0,0 +1,5 @@ +Task bin cli-esm testing this out "asdf" +testing +this +out +asdf diff --git a/tests/specs/task/both_prefers_deno/__test__.jsonc b/tests/specs/task/both_prefers_deno/__test__.jsonc new file mode 100644 index 0000000000..99e9e822ba --- /dev/null +++ b/tests/specs/task/both_prefers_deno/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json output some text", + "output": "prefers_deno.out", + "exitCode": 0 +} diff --git a/tests/specs/task/both_prefers_deno/deno.json b/tests/specs/task/both_prefers_deno/deno.json new file mode 100644 index 0000000000..1038609a4a --- /dev/null +++ b/tests/specs/task/both_prefers_deno/deno.json @@ -0,0 +1,6 @@ +{ + "tasks": { + "output": "deno eval 'console.log(1)'", + "other": "deno eval 'console.log(2)'" + } +} diff --git a/tests/testdata/task/both/prefers_deno.out b/tests/specs/task/both_prefers_deno/prefers_deno.out similarity index 100% rename from tests/testdata/task/both/prefers_deno.out rename to tests/specs/task/both_prefers_deno/prefers_deno.out diff --git a/tests/specs/task/byonm/__test__.jsonc b/tests/specs/task/byonm/__test__.jsonc index 3d62a7887d..508b3e8579 100644 --- a/tests/specs/task/byonm/__test__.jsonc +++ b/tests/specs/task/byonm/__test__.jsonc @@ -32,10 +32,6 @@ "args": "install", "output": "[WILDCARD]" }, { - // implied byonm from DENO_FUTURE - "envs": { - "DENO_FUTURE": "1" - }, "args": "task say", "output": "package_json_say.out" }, { diff --git a/tests/specs/task/cwd/__test__.jsonc b/tests/specs/task/cwd/__test__.jsonc new file mode 100644 index 0000000000..49b6b41782 --- /dev/null +++ b/tests/specs/task/cwd/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task -q --config deno.json --cwd .. echo_cwd", + "output": "task_cwd.out", + "exitCode": 0 +} diff --git a/tests/specs/task/cwd/deno.json b/tests/specs/task/cwd/deno.json new file mode 100644 index 0000000000..b7f513a3f9 --- /dev/null +++ b/tests/specs/task/cwd/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo_cwd": "echo $(pwd)" + } +} diff --git a/tests/specs/task/cwd/task_cwd.out b/tests/specs/task/cwd/task_cwd.out new file mode 100644 index 0000000000..1a8bf6ad05 --- /dev/null +++ b/tests/specs/task/cwd/task_cwd.out @@ -0,0 +1 @@ +[WILDCARD]task diff --git a/tests/specs/task/cwd_resolves_config_from_specified_dir/__test__.jsonc b/tests/specs/task/cwd_resolves_config_from_specified_dir/__test__.jsonc new file mode 100644 index 0000000000..9fc3a488c9 --- /dev/null +++ b/tests/specs/task/cwd_resolves_config_from_specified_dir/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task -q --cwd deno.json", + "output": "task_no_args.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/deno_json/deno.json b/tests/specs/task/cwd_resolves_config_from_specified_dir/deno.json similarity index 100% rename from tests/testdata/task/deno_json/deno.json rename to tests/specs/task/cwd_resolves_config_from_specified_dir/deno.json diff --git a/tests/testdata/task/deno_json/task_no_args.out b/tests/specs/task/cwd_resolves_config_from_specified_dir/task_no_args.out similarity index 100% rename from tests/testdata/task/deno_json/task_no_args.out rename to tests/specs/task/cwd_resolves_config_from_specified_dir/task_no_args.out diff --git a/tests/specs/task/deno_exe_no_env/__test__.jsonc b/tests/specs/task/deno_exe_no_env/__test__.jsonc new file mode 100644 index 0000000000..289f9483a5 --- /dev/null +++ b/tests/specs/task/deno_exe_no_env/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json deno_echo", + "output": "task_deno_exe_no_env.out" +} diff --git a/tests/specs/task/deno_exe_no_env/deno.json b/tests/specs/task/deno_exe_no_env/deno.json new file mode 100644 index 0000000000..d519e21392 --- /dev/null +++ b/tests/specs/task/deno_exe_no_env/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "deno_echo": "deno eval 'console.log(5)'" + } +} diff --git a/tests/testdata/task/deno_json/task_deno_exe_no_env.out b/tests/specs/task/deno_exe_no_env/task_deno_exe_no_env.out similarity index 100% rename from tests/testdata/task/deno_json/task_deno_exe_no_env.out rename to tests/specs/task/deno_exe_no_env/task_deno_exe_no_env.out diff --git a/tests/specs/task/deno_no_pre_post/__test__.jsonc b/tests/specs/task/deno_no_pre_post/__test__.jsonc new file mode 100644 index 0000000000..a29eece48b --- /dev/null +++ b/tests/specs/task/deno_no_pre_post/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json test", + "output": "bin.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/deno_json_pre_post/bin.out b/tests/specs/task/deno_no_pre_post/bin.out similarity index 100% rename from tests/testdata/task/deno_json_pre_post/bin.out rename to tests/specs/task/deno_no_pre_post/bin.out diff --git a/tests/testdata/task/deno_json_pre_post/deno.json b/tests/specs/task/deno_no_pre_post/deno.json similarity index 100% rename from tests/testdata/task/deno_json_pre_post/deno.json rename to tests/specs/task/deno_no_pre_post/deno.json diff --git a/tests/specs/task/doc_comments_incorrect/__test__.jsonc b/tests/specs/task/doc_comments_incorrect/__test__.jsonc index e564690e6d..7346290292 100644 --- a/tests/specs/task/doc_comments_incorrect/__test__.jsonc +++ b/tests/specs/task/doc_comments_incorrect/__test__.jsonc @@ -1,6 +1,5 @@ { "args": "task doesntexist", - "envs": { "NO_COLOR": "1" }, "output": "task.out", "exitCode": 1 } diff --git a/tests/specs/task/doc_comments_no_args/__test__.jsonc b/tests/specs/task/doc_comments_no_args/__test__.jsonc index 2f9db088a6..f3e76cdaa7 100644 --- a/tests/specs/task/doc_comments_no_args/__test__.jsonc +++ b/tests/specs/task/doc_comments_no_args/__test__.jsonc @@ -1,6 +1,5 @@ { "args": "task", - "envs": { "NO_COLOR": "1" }, "output": "task.out", - "exitCode": 1 + "exitCode": 0 } diff --git a/tests/specs/task/emoji/__test__.jsonc b/tests/specs/task/emoji/__test__.jsonc new file mode 100644 index 0000000000..fde5b1545f --- /dev/null +++ b/tests/specs/task/emoji/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --cwd deno.json echo_emoji", + "output": "main.out" +} diff --git a/tests/specs/task/emoji/deno.json b/tests/specs/task/emoji/deno.json new file mode 100644 index 0000000000..5ef0d014a7 --- /dev/null +++ b/tests/specs/task/emoji/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo_emoji": "echo 🔥" + } +} diff --git a/tests/specs/task/emoji/main.out b/tests/specs/task/emoji/main.out new file mode 100644 index 0000000000..6ece63dc1f --- /dev/null +++ b/tests/specs/task/emoji/main.out @@ -0,0 +1 @@ +🔥 diff --git a/tests/specs/task/exit_code_5/__test__.jsonc b/tests/specs/task/exit_code_5/__test__.jsonc new file mode 100644 index 0000000000..0a09cd57f8 --- /dev/null +++ b/tests/specs/task/exit_code_5/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json exit_code_5", + "output": "task_exit_code_5.out", + "exitCode": 5 +} diff --git a/tests/specs/task/exit_code_5/deno.json b/tests/specs/task/exit_code_5/deno.json new file mode 100644 index 0000000000..a6e19c031c --- /dev/null +++ b/tests/specs/task/exit_code_5/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "exit_code_5": "echo $(echo 10 ; exit 2) && exit 5" + } +} diff --git a/tests/testdata/task/deno_json/task_exit_code_5.out b/tests/specs/task/exit_code_5/task_exit_code_5.out similarity index 100% rename from tests/testdata/task/deno_json/task_exit_code_5.out rename to tests/specs/task/exit_code_5/task_exit_code_5.out diff --git a/tests/specs/task/init_cwd/__test__.jsonc b/tests/specs/task/init_cwd/__test__.jsonc new file mode 100644 index 0000000000..b228e94e6a --- /dev/null +++ b/tests/specs/task/init_cwd/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task -q --config deno.json --cwd .. echo_init_cwd", + "output": "task_init_cwd.out", + "exitCode": 0 +} diff --git a/tests/specs/task/init_cwd/deno.json b/tests/specs/task/init_cwd/deno.json new file mode 100644 index 0000000000..93abead1dd --- /dev/null +++ b/tests/specs/task/init_cwd/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo_init_cwd": "echo $INIT_CWD" + } +} diff --git a/tests/specs/task/init_cwd/task_init_cwd.out b/tests/specs/task/init_cwd/task_init_cwd.out new file mode 100644 index 0000000000..fee54862e3 --- /dev/null +++ b/tests/specs/task/init_cwd/task_init_cwd.out @@ -0,0 +1 @@ +[WILDCARD]init_cwd diff --git a/tests/specs/task/init_cwd_already_set/__test__.jsonc b/tests/specs/task/init_cwd_already_set/__test__.jsonc new file mode 100644 index 0000000000..27b817916f --- /dev/null +++ b/tests/specs/task/init_cwd_already_set/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "args": "task -q --config deno.json echo_init_cwd", + "output": "task_init_cwd_already_set.out", + "envs": { + "INIT_CWD": "HELLO" + }, + "exitCode": 0 +} diff --git a/tests/specs/task/init_cwd_already_set/deno.json b/tests/specs/task/init_cwd_already_set/deno.json new file mode 100644 index 0000000000..93abead1dd --- /dev/null +++ b/tests/specs/task/init_cwd_already_set/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "echo_init_cwd": "echo $INIT_CWD" + } +} diff --git a/tests/testdata/task/deno_json/task_init_cwd_already_set.out b/tests/specs/task/init_cwd_already_set/task_init_cwd_already_set.out similarity index 100% rename from tests/testdata/task/deno_json/task_init_cwd_already_set.out rename to tests/specs/task/init_cwd_already_set/task_init_cwd_already_set.out diff --git a/tests/specs/task/no_args/__test__.jsonc b/tests/specs/task/no_args/__test__.jsonc new file mode 100644 index 0000000000..6a0c23750a --- /dev/null +++ b/tests/specs/task/no_args/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task -q --config deno.json", + "output": "task_no_args.out", + "exitCode": 0 +} diff --git a/tests/specs/task/no_args/deno.json b/tests/specs/task/no_args/deno.json new file mode 100644 index 0000000000..c57426d250 --- /dev/null +++ b/tests/specs/task/no_args/deno.json @@ -0,0 +1,13 @@ +{ + "tasks": { + "boolean_logic": "sleep 0.1 && echo 3 && echo 4 & echo 1 && echo 2 || echo NOPE", + "echo": "echo 1", + "deno_echo": "deno eval 'console.log(5)'", + "strings": "deno run main.ts && deno eval \"console.log(\\\"test\\\")\"", + "piped": "echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')", + "exit_code_5": "echo $(echo 10 ; exit 2) && exit 5", + "echo_cwd": "echo $(pwd)", + "echo_init_cwd": "echo $INIT_CWD", + "echo_emoji": "echo 🔥" + } +} diff --git a/tests/specs/task/no_args/task_no_args.out b/tests/specs/task/no_args/task_no_args.out new file mode 100644 index 0000000000..18f86fce6c --- /dev/null +++ b/tests/specs/task/no_args/task_no_args.out @@ -0,0 +1,19 @@ +Available tasks: +- boolean_logic + sleep 0.1 && echo 3 && echo 4 & echo 1 && echo 2 || echo NOPE +- echo + echo 1 +- deno_echo + deno eval 'console.log(5)' +- strings + deno run main.ts && deno eval "console.log(\"test\")" +- piped + echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)') +- exit_code_5 + echo $(echo 10 ; exit 2) && exit 5 +- echo_cwd + echo $(pwd) +- echo_init_cwd + echo $INIT_CWD +- echo_emoji + echo 🔥 diff --git a/tests/specs/task/node_modules_dir_false/deno.json b/tests/specs/task/node_modules_dir_false/deno.json index cacff662c6..ac5f8ba14c 100644 --- a/tests/specs/task/node_modules_dir_false/deno.json +++ b/tests/specs/task/node_modules_dir_false/deno.json @@ -1,5 +1,5 @@ { - "nodeModulesDir": true, + "nodeModulesDir": "auto", "tasks": { "repro": "echo hi" } diff --git a/tests/specs/task/non_existent/__test__.jsonc b/tests/specs/task/non_existent/__test__.jsonc new file mode 100644 index 0000000000..f0394819be --- /dev/null +++ b/tests/specs/task/non_existent/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --config deno.json non_existent", + "output": "task_non_existent.out", + "exitCode": 1 +} diff --git a/tests/specs/task/non_existent/deno.json b/tests/specs/task/non_existent/deno.json new file mode 100644 index 0000000000..c57426d250 --- /dev/null +++ b/tests/specs/task/non_existent/deno.json @@ -0,0 +1,13 @@ +{ + "tasks": { + "boolean_logic": "sleep 0.1 && echo 3 && echo 4 & echo 1 && echo 2 || echo NOPE", + "echo": "echo 1", + "deno_echo": "deno eval 'console.log(5)'", + "strings": "deno run main.ts && deno eval \"console.log(\\\"test\\\")\"", + "piped": "echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')", + "exit_code_5": "echo $(echo 10 ; exit 2) && exit 5", + "echo_cwd": "echo $(pwd)", + "echo_init_cwd": "echo $INIT_CWD", + "echo_emoji": "echo 🔥" + } +} diff --git a/tests/testdata/task/deno_json/task_non_existent.out b/tests/specs/task/non_existent/task_non_existent.out similarity index 100% rename from tests/testdata/task/deno_json/task_non_existent.out rename to tests/specs/task/non_existent/task_non_existent.out diff --git a/tests/specs/task/npx_installed_pkg_non_byonm/deno.jsonc b/tests/specs/task/npx_installed_pkg_non_byonm/deno.jsonc index 00303820ba..a21a7745b9 100644 --- a/tests/specs/task/npx_installed_pkg_non_byonm/deno.jsonc +++ b/tests/specs/task/npx_installed_pkg_non_byonm/deno.jsonc @@ -1,6 +1,6 @@ { // not byonm - "nodeModulesDir": true, + "nodeModules": "local-auto", "tasks": { "say": "npx cowsay moo" } diff --git a/tests/specs/task/npx_non_existent/__test__.jsonc b/tests/specs/task/npx_non_existent/__test__.jsonc new file mode 100644 index 0000000000..d0d3416464 --- /dev/null +++ b/tests/specs/task/npx_non_existent/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task non-existent", + "output": "non_existent.out", + "exitCode": 1 +} diff --git a/tests/testdata/task/npx/non_existent.out b/tests/specs/task/npx_non_existent/non_existent.out similarity index 100% rename from tests/testdata/task/npx/non_existent.out rename to tests/specs/task/npx_non_existent/non_existent.out diff --git a/tests/specs/task/npx_non_existent/package.json b/tests/specs/task/npx_non_existent/package.json new file mode 100644 index 0000000000..59602b96fe --- /dev/null +++ b/tests/specs/task/npx_non_existent/package.json @@ -0,0 +1,6 @@ +{ + "scripts": { + "non-existent": "npx this-command-should-not-exist-for-you", + "on-own": "npx" + } +} diff --git a/tests/specs/task/package_json_echo/__test__.jsonc b/tests/specs/task/package_json_echo/__test__.jsonc new file mode 100644 index 0000000000..e6f0708b84 --- /dev/null +++ b/tests/specs/task/package_json_echo/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task --quiet echo", + "output": "echo.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/package_json/echo.out b/tests/specs/task/package_json_echo/echo.out similarity index 100% rename from tests/testdata/task/package_json/echo.out rename to tests/specs/task/package_json_echo/echo.out diff --git a/tests/specs/task/package_json_echo/package.json b/tests/specs/task/package_json_echo/package.json new file mode 100644 index 0000000000..cedbe2d5bd --- /dev/null +++ b/tests/specs/task/package_json_echo/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "echo": "deno eval 'console.log(1)'", + "bin": "@denotest/bin hi && cli-esm testing this out && npx cli-cjs test" + }, + "dependencies": { + "@denotest/bin": "0.5", + "other": "npm:@denotest/bin@1.0" + } +} diff --git a/tests/specs/task/package_json_no_arg/__test__.jsonc b/tests/specs/task/package_json_no_arg/__test__.jsonc new file mode 100644 index 0000000000..6b4ffa96d7 --- /dev/null +++ b/tests/specs/task/package_json_no_arg/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task", + "output": "no_args.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/package_json/no_args.out b/tests/specs/task/package_json_no_arg/no_args.out similarity index 100% rename from tests/testdata/task/package_json/no_args.out rename to tests/specs/task/package_json_no_arg/no_args.out diff --git a/tests/specs/task/package_json_no_arg/package.json b/tests/specs/task/package_json_no_arg/package.json new file mode 100644 index 0000000000..cedbe2d5bd --- /dev/null +++ b/tests/specs/task/package_json_no_arg/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "echo": "deno eval 'console.log(1)'", + "bin": "@denotest/bin hi && cli-esm testing this out && npx cli-cjs test" + }, + "dependencies": { + "@denotest/bin": "0.5", + "other": "npm:@denotest/bin@1.0" + } +} diff --git a/tests/specs/task/package_json_node_modules_dir_none/__test__.jsonc b/tests/specs/task/package_json_node_modules_dir_none/__test__.jsonc new file mode 100644 index 0000000000..21d9d73ba0 --- /dev/null +++ b/tests/specs/task/package_json_node_modules_dir_none/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "task echo", + "output": "bin.out", + "exitCode": 0 +} diff --git a/tests/specs/task/package_json_node_modules_dir_none/bin.out b/tests/specs/task/package_json_node_modules_dir_none/bin.out new file mode 100644 index 0000000000..ff60cc3d0b --- /dev/null +++ b/tests/specs/task/package_json_node_modules_dir_none/bin.out @@ -0,0 +1,8 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fbin +Download http://localhost:4260/@denotest/bin/1.0.0.tgz +Download http://localhost:4260/@denotest/bin/0.5.0.tgz +[UNORDERED_END] +Task echo deno eval 'console.log(1)' && cli-esm hi +1 +hi diff --git a/tests/specs/task/package_json_node_modules_dir_none/deno.json b/tests/specs/task/package_json_node_modules_dir_none/deno.json new file mode 100644 index 0000000000..38af4024b0 --- /dev/null +++ b/tests/specs/task/package_json_node_modules_dir_none/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "none" +} diff --git a/tests/testdata/task/package_json_node_modules_dir_false/package.json b/tests/specs/task/package_json_node_modules_dir_none/package.json similarity index 67% rename from tests/testdata/task/package_json_node_modules_dir_false/package.json rename to tests/specs/task/package_json_node_modules_dir_none/package.json index 081e076b9f..713a9dc5b4 100644 --- a/tests/testdata/task/package_json_node_modules_dir_false/package.json +++ b/tests/specs/task/package_json_node_modules_dir_none/package.json @@ -1,6 +1,6 @@ { "scripts": { - "echo": "deno eval 'console.log(1)'" + "echo": "deno eval 'console.log(1)' && cli-esm hi" }, "dependencies": { "@denotest/bin": "0.5", diff --git a/tests/specs/task/piped_stdin/__test__.jsonc b/tests/specs/task/piped_stdin/__test__.jsonc new file mode 100644 index 0000000000..541e53b177 --- /dev/null +++ b/tests/specs/task/piped_stdin/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "task -q --config deno.json piped", + "output": "task_piped_stdin.out" +} diff --git a/tests/specs/task/piped_stdin/deno.json b/tests/specs/task/piped_stdin/deno.json new file mode 100644 index 0000000000..bb3d1cd29e --- /dev/null +++ b/tests/specs/task/piped_stdin/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "piped": "echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')" + } +} diff --git a/tests/testdata/task/deno_json/task_piped_stdin.out b/tests/specs/task/piped_stdin/task_piped_stdin.out similarity index 100% rename from tests/testdata/task/deno_json/task_piped_stdin.out rename to tests/specs/task/piped_stdin/task_piped_stdin.out diff --git a/tests/specs/task/post/__test__.jsonc b/tests/specs/task/post/__test__.jsonc new file mode 100644 index 0000000000..d22f77cc2b --- /dev/null +++ b/tests/specs/task/post/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task test", + "output": "bin.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/package_json_post/bin.out b/tests/specs/task/post/bin.out similarity index 100% rename from tests/testdata/task/package_json_post/bin.out rename to tests/specs/task/post/bin.out diff --git a/tests/testdata/task/package_json_post/package.json b/tests/specs/task/post/package.json similarity index 100% rename from tests/testdata/task/package_json_post/package.json rename to tests/specs/task/post/package.json diff --git a/tests/specs/task/post_only/__test__.jsonc b/tests/specs/task/post_only/__test__.jsonc new file mode 100644 index 0000000000..606f9eb1f5 --- /dev/null +++ b/tests/specs/task/post_only/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task test", + "output": "bin.out", + "exitCode": 1 +} diff --git a/tests/testdata/task/package_json_post_only/bin.out b/tests/specs/task/post_only/bin.out similarity index 100% rename from tests/testdata/task/package_json_post_only/bin.out rename to tests/specs/task/post_only/bin.out diff --git a/tests/testdata/task/package_json_post_only/package.json b/tests/specs/task/post_only/package.json similarity index 100% rename from tests/testdata/task/package_json_post_only/package.json rename to tests/specs/task/post_only/package.json diff --git a/tests/specs/task/pre/__test__.jsonc b/tests/specs/task/pre/__test__.jsonc new file mode 100644 index 0000000000..d22f77cc2b --- /dev/null +++ b/tests/specs/task/pre/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task test", + "output": "bin.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/package_json_pre/bin.out b/tests/specs/task/pre/bin.out similarity index 100% rename from tests/testdata/task/package_json_pre/bin.out rename to tests/specs/task/pre/bin.out diff --git a/tests/testdata/task/package_json_pre/package.json b/tests/specs/task/pre/package.json similarity index 100% rename from tests/testdata/task/package_json_pre/package.json rename to tests/specs/task/pre/package.json diff --git a/tests/specs/task/pre_only/__test__.jsonc b/tests/specs/task/pre_only/__test__.jsonc new file mode 100644 index 0000000000..606f9eb1f5 --- /dev/null +++ b/tests/specs/task/pre_only/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task test", + "output": "bin.out", + "exitCode": 1 +} diff --git a/tests/testdata/task/package_json_pre_only/bin.out b/tests/specs/task/pre_only/bin.out similarity index 100% rename from tests/testdata/task/package_json_pre_only/bin.out rename to tests/specs/task/pre_only/bin.out diff --git a/tests/testdata/task/package_json_pre_only/package.json b/tests/specs/task/pre_only/package.json similarity index 100% rename from tests/testdata/task/package_json_pre_only/package.json rename to tests/specs/task/pre_only/package.json diff --git a/tests/specs/task/pre_post/__test__.jsonc b/tests/specs/task/pre_post/__test__.jsonc new file mode 100644 index 0000000000..d22f77cc2b --- /dev/null +++ b/tests/specs/task/pre_post/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "task test", + "output": "bin.out", + "exitCode": 0 +} diff --git a/tests/testdata/task/package_json_pre_post/bin.out b/tests/specs/task/pre_post/bin.out similarity index 100% rename from tests/testdata/task/package_json_pre_post/bin.out rename to tests/specs/task/pre_post/bin.out diff --git a/tests/testdata/task/package_json_pre_post/package.json b/tests/specs/task/pre_post/package.json similarity index 100% rename from tests/testdata/task/package_json_pre_post/package.json rename to tests/specs/task/pre_post/package.json diff --git a/tests/specs/task/workspace/__test__.jsonc b/tests/specs/task/workspace/__test__.jsonc index b08f35afca..5a3ad1356a 100644 --- a/tests/specs/task/workspace/__test__.jsonc +++ b/tests/specs/task/workspace/__test__.jsonc @@ -3,25 +3,25 @@ "root": { "args": "task", "output": "root.out", - "exitCode": 1 + "exitCode": 0 }, "package_a": { "args": "task", "cwd": "package-a", "output": "package-a.out", - "exitCode": 1 + "exitCode": 0 }, "package_b": { "args": "task", "cwd": "package-b", "output": "package-b.out", - "exitCode": 1 + "exitCode": 0 }, "scripts": { "args": "task", "cwd": "scripts", "output": "scripts.out", - "exitCode": 1 + "exitCode": 0 }, "package_b_tasks": { "steps": [{ diff --git a/tests/specs/test/aggregate_error/__test__.jsonc b/tests/specs/test/aggregate_error/__test__.jsonc new file mode 100644 index 0000000000..a02376f871 --- /dev/null +++ b/tests/specs/test/aggregate_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/aggregate_error/main.out b/tests/specs/test/aggregate_error/main.out new file mode 100644 index 0000000000..aa790e5505 --- /dev/null +++ b/tests/specs/test/aggregate_error/main.out @@ -0,0 +1,22 @@ +running 1 test from ./main.ts +aggregate ... FAILED ([WILDCARD]) + + ERRORS + +aggregate => ./main.ts:[WILDCARD] +error: AggregateError + Error: Error 1 + at [WILDCARD]/main.ts:2:18 + Error: Error 2 + at [WILDCARD]/main.ts:3:18 + throw new AggregateError([error1, error2]); + ^ + at [WILDCARD]/main.ts:5:9 + + FAILURES + +aggregate => ./main.ts:[WILDCARD] + +FAILED | 0 passed | 1 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/aggregate_error.ts b/tests/specs/test/aggregate_error/main.ts similarity index 100% rename from tests/testdata/test/aggregate_error.ts rename to tests/specs/test/aggregate_error/main.ts diff --git a/tests/specs/test/allow_all/__test__.jsonc b/tests/specs/test/allow_all/__test__.jsonc new file mode 100644 index 0000000000..badffe7c4d --- /dev/null +++ b/tests/specs/test/allow_all/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config deno.json --allow-all main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/allow_all/deno.json b/tests/specs/test/allow_all/deno.json new file mode 100644 index 0000000000..105514e133 --- /dev/null +++ b/tests/specs/test/allow_all/deno.json @@ -0,0 +1,4 @@ +{ + "lock": false, + "importMap": "../../../../import_map.json" +} diff --git a/tests/testdata/test/allow_all.out b/tests/specs/test/allow_all/main.out similarity index 72% rename from tests/testdata/test/allow_all.out rename to tests/specs/test/allow_all/main.out index 8b783b8236..b3bf5275f8 100644 --- a/tests/testdata/test/allow_all.out +++ b/tests/specs/test/allow_all/main.out @@ -1,5 +1,5 @@ [WILDCARD] -running 14 tests from [WILDCARD] +running 12 tests from [WILDCARD] read false ... ok [WILDCARD] read true ... ok [WILDCARD] write false ... ok [WILDCARD] @@ -12,7 +12,5 @@ run false ... ok [WILDCARD] run true ... ok [WILDCARD] ffi false ... ok [WILDCARD] ffi true ... ok [WILDCARD] -hrtime false ... ok [WILDCARD] -hrtime true ... ok [WILDCARD] -ok | 14 passed | 0 failed [WILDCARD] +ok | 12 passed | 0 failed [WILDCARD] diff --git a/tests/testdata/test/allow_all.ts b/tests/specs/test/allow_all/main.ts similarity index 98% rename from tests/testdata/test/allow_all.ts rename to tests/specs/test/allow_all/main.ts index 01341d9e5e..7faa58c612 100644 --- a/tests/testdata/test/allow_all.ts +++ b/tests/specs/test/allow_all/main.ts @@ -7,7 +7,6 @@ const permissions: Deno.PermissionName[] = [ "env", "run", "ffi", - "hrtime", ]; for (const name of permissions) { diff --git a/tests/specs/test/allow_none/__test__.jsonc b/tests/specs/test/allow_none/__test__.jsonc new file mode 100644 index 0000000000..5e21e89436 --- /dev/null +++ b/tests/specs/test/allow_none/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config deno.json main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/allow_none/deno.json b/tests/specs/test/allow_none/deno.json new file mode 100644 index 0000000000..105514e133 --- /dev/null +++ b/tests/specs/test/allow_none/deno.json @@ -0,0 +1,4 @@ +{ + "lock": false, + "importMap": "../../../../import_map.json" +} diff --git a/tests/specs/test/allow_none/main.out b/tests/specs/test/allow_none/main.out new file mode 100644 index 0000000000..1914997cd4 --- /dev/null +++ b/tests/specs/test/allow_none/main.out @@ -0,0 +1,45 @@ +[WILDCARD] +running 6 tests from [WILDCARD] +read ... FAILED [WILDCARD] +write ... FAILED [WILDCARD] +net ... FAILED [WILDCARD] +env ... FAILED [WILDCARD] +run ... FAILED [WILDCARD] +ffi ... FAILED [WILDCARD] + + ERRORS + +read => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + +write => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + +net => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + +env => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + +run => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + +ffi => ./main.ts:[WILDCARD] +error: NotCapable: Can't escalate parent thread permissions +[WILDCARD] + + FAILURES + +read => ./main.ts:[WILDCARD] +write => ./main.ts:[WILDCARD] +net => ./main.ts:[WILDCARD] +env => ./main.ts:[WILDCARD] +run => ./main.ts:[WILDCARD] +ffi => ./main.ts:[WILDCARD] + +FAILED | 0 passed | 6 failed [WILDCARD] diff --git a/tests/testdata/test/allow_none.ts b/tests/specs/test/allow_none/main.ts similarity index 96% rename from tests/testdata/test/allow_none.ts rename to tests/specs/test/allow_none/main.ts index 17a6f4014e..e59a30c4d8 100644 --- a/tests/testdata/test/allow_none.ts +++ b/tests/specs/test/allow_none/main.ts @@ -7,7 +7,6 @@ const permissions: Deno.PermissionName[] = [ "env", "run", "ffi", - "hrtime", ]; for (const name of permissions) { diff --git a/tests/specs/test/before_unload_prevent_default/__test__.jsonc b/tests/specs/test/before_unload_prevent_default/__test__.jsonc new file mode 100644 index 0000000000..602250082b --- /dev/null +++ b/tests/specs/test/before_unload_prevent_default/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test --quiet main.ts", + "output": "main.out" +} diff --git a/tests/testdata/test/before_unload_prevent_default.out b/tests/specs/test/before_unload_prevent_default/main.out similarity index 50% rename from tests/testdata/test/before_unload_prevent_default.out rename to tests/specs/test/before_unload_prevent_default/main.out index 09da32ff96..9ccad312d8 100644 --- a/tests/testdata/test/before_unload_prevent_default.out +++ b/tests/specs/test/before_unload_prevent_default/main.out @@ -1,4 +1,4 @@ -running 1 test from [WILDCARD]/before_unload_prevent_default.ts +running 1 test from [WILDCARD]/main.ts foo ... ok ([WILDCARD]) ok | 1 passed | 0 failed ([WILDCARD]) diff --git a/tests/testdata/test/before_unload_prevent_default.ts b/tests/specs/test/before_unload_prevent_default/main.ts similarity index 100% rename from tests/testdata/test/before_unload_prevent_default.ts rename to tests/specs/test/before_unload_prevent_default/main.ts diff --git a/tests/specs/test/captured_output/__test__.jsonc b/tests/specs/test/captured_output/__test__.jsonc new file mode 100644 index 0000000000..f320f9581d --- /dev/null +++ b/tests/specs/test/captured_output/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test -A captured_output.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/testdata/test/captured_output.ts b/tests/specs/test/captured_output/captured_output.ts similarity index 94% rename from tests/testdata/test/captured_output.ts rename to tests/specs/test/captured_output/captured_output.ts index 3eed249a2e..77e1d1b08e 100644 --- a/tests/testdata/test/captured_output.ts +++ b/tests/specs/test/captured_output/captured_output.ts @@ -19,7 +19,7 @@ Deno.test("output", async () => { }).spawn(); await c.status; const worker = new Worker( - import.meta.resolve("./captured_output.worker.js"), + import.meta.resolve("./captured_output.worker.ts"), { type: "module" }, ); diff --git a/tests/testdata/test/captured_output.worker.js b/tests/specs/test/captured_output/captured_output.worker.ts similarity index 100% rename from tests/testdata/test/captured_output.worker.js rename to tests/specs/test/captured_output/captured_output.worker.ts diff --git a/tests/specs/test/captured_output/main.out b/tests/specs/test/captured_output/main.out new file mode 100644 index 0000000000..ba313beafb --- /dev/null +++ b/tests/specs/test/captured_output/main.out @@ -0,0 +1,22 @@ +Check [WILDCARD]/captured_output.ts +running 1 test from ./captured_output.ts +output ... +------- output ------- +[UNORDERED_START] +1 +0 +3 +2 +5 +4 +7 +6 +Check [WILDLINE]/captured_output.worker.ts +9 +8 +[UNORDERED_END] +----- output end ----- +output ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/check_local_by_default/__test__.jsonc b/tests/specs/test/check_local_by_default/__test__.jsonc new file mode 100644 index 0000000000..138d007adb --- /dev/null +++ b/tests/specs/test/check_local_by_default/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test --allow-import --quiet main.ts", + "output": "main.out" +} diff --git a/tests/specs/test/check_local_by_default/main.out b/tests/specs/test/check_local_by_default/main.out new file mode 100644 index 0000000000..be21aa963c --- /dev/null +++ b/tests/specs/test/check_local_by_default/main.out @@ -0,0 +1,4 @@ +running 0 tests from ./main.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/testdata/bundle/check_local_by_default/no_errors.ts b/tests/specs/test/check_local_by_default/main.ts similarity index 100% rename from tests/testdata/bundle/check_local_by_default/no_errors.ts rename to tests/specs/test/check_local_by_default/main.ts diff --git a/tests/specs/test/check_local_by_default2/__test__.jsonc b/tests/specs/test/check_local_by_default2/__test__.jsonc new file mode 100644 index 0000000000..79068d63f0 --- /dev/null +++ b/tests/specs/test/check_local_by_default2/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --allow-import --quiet main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/check_local_by_default2.out b/tests/specs/test/check_local_by_default2/main.out similarity index 63% rename from tests/testdata/test/check_local_by_default2.out rename to tests/specs/test/check_local_by_default2/main.out index b933ac4833..5b145afd25 100644 --- a/tests/testdata/test/check_local_by_default2.out +++ b/tests/specs/test/check_local_by_default2/main.out @@ -1,4 +1,4 @@ error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'. const b: "b" = 12; ^ - at [WILDCARD]test/check_local_by_default2.ts:3:7 + at [WILDCARD]/main.ts:3:7 diff --git a/tests/testdata/bundle/check_local_by_default/type_error.ts b/tests/specs/test/check_local_by_default2/main.ts similarity index 100% rename from tests/testdata/bundle/check_local_by_default/type_error.ts rename to tests/specs/test/check_local_by_default2/main.ts diff --git a/tests/specs/test/clean_flag/__test__.jsonc b/tests/specs/test/clean_flag/__test__.jsonc index b94612d36e..6283a44e1c 100644 --- a/tests/specs/test/clean_flag/__test__.jsonc +++ b/tests/specs/test/clean_flag/__test__.jsonc @@ -1,5 +1,5 @@ { - "args": "run -A --config ../../../config/deno.json main.js", + "args": "run -A --config deno.json main.js", "exitCode": 0, "output": "main.out" } diff --git a/tests/specs/test/clean_flag/deno.json b/tests/specs/test/clean_flag/deno.json new file mode 100644 index 0000000000..105514e133 --- /dev/null +++ b/tests/specs/test/clean_flag/deno.json @@ -0,0 +1,4 @@ +{ + "lock": false, + "importMap": "../../../../import_map.json" +} diff --git a/tests/specs/test/clear_timeout/__test__.jsonc b/tests/specs/test/clear_timeout/__test__.jsonc new file mode 100644 index 0000000000..d7ed453a94 --- /dev/null +++ b/tests/specs/test/clear_timeout/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/clear_timeout.out b/tests/specs/test/clear_timeout/main.out similarity index 59% rename from tests/testdata/test/clear_timeout.out rename to tests/specs/test/clear_timeout/main.out index 4d3ff88626..be639f7280 100644 --- a/tests/testdata/test/clear_timeout.out +++ b/tests/specs/test/clear_timeout/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/clear_timeout.ts -running 3 tests from ./test/clear_timeout.ts +Check [WILDCARD]/main.ts +running 3 tests from ./main.ts test 1 ... ok ([WILDCARD]) test 2 ... ok ([WILDCARD]) test 3 ... ok ([WILDCARD]) diff --git a/tests/testdata/test/clear_timeout.ts b/tests/specs/test/clear_timeout/main.ts similarity index 100% rename from tests/testdata/test/clear_timeout.ts rename to tests/specs/test/clear_timeout/main.ts diff --git a/tests/specs/test/collect/__test__.jsonc b/tests/specs/test/collect/__test__.jsonc new file mode 100644 index 0000000000..3a45c41a43 --- /dev/null +++ b/tests/specs/test/collect/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --ignore=collect/ignore collect", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/collect/deno.jsonc b/tests/specs/test/collect/collect/deno.jsonc similarity index 100% rename from tests/testdata/test/collect/deno.jsonc rename to tests/specs/test/collect/collect/deno.jsonc diff --git a/tests/testdata/test/collect/deno.malformed.jsonc b/tests/specs/test/collect/collect/deno.malformed.jsonc similarity index 100% rename from tests/testdata/test/collect/deno.malformed.jsonc rename to tests/specs/test/collect/collect/deno.malformed.jsonc diff --git a/tests/testdata/test/collect/deno2.jsonc b/tests/specs/test/collect/collect/deno2.jsonc similarity index 100% rename from tests/testdata/test/collect/deno2.jsonc rename to tests/specs/test/collect/collect/deno2.jsonc diff --git a/tests/testdata/test/collect/ignore/test.ts b/tests/specs/test/collect/collect/ignore/test.ts similarity index 100% rename from tests/testdata/test/collect/ignore/test.ts rename to tests/specs/test/collect/collect/ignore/test.ts diff --git a/tests/specs/test/collect/collect/include.ts b/tests/specs/test/collect/collect/include.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/collect/collect/include/2_test.ts b/tests/specs/test/collect/collect/include/2_test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/collect/collect/include/test.ts b/tests/specs/test/collect/collect/include/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/collect/collect/test.ts b/tests/specs/test/collect/collect/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/collect/main.out b/tests/specs/test/collect/main.out new file mode 100644 index 0000000000..13a76fc375 --- /dev/null +++ b/tests/specs/test/collect/main.out @@ -0,0 +1,9 @@ +Check [WILDCARD]/collect/include/2_test.ts +Check [WILDCARD]/collect/include/test.ts +Check [WILDCARD]/collect/test.ts +running 0 tests from [WILDCARD]/collect/include/2_test.ts +running 0 tests from [WILDCARD]/collect/include/test.ts +running 0 tests from [WILDCARD]/collect/test.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/default_ts/__test__.jsonc b/tests/specs/test/default_ts/__test__.jsonc new file mode 100644 index 0000000000..778fca5c51 --- /dev/null +++ b/tests/specs/test/default_ts/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "tests": { + "ext_flag": { + "args": "test --ext=ts as_ts.js", + "output": "ext.out" + }, + "extensionless": { + "args": "test extensionless", + "output": "extensionless.out" + } + } +} diff --git a/tests/specs/test/default_ts/as_ts.js b/tests/specs/test/default_ts/as_ts.js new file mode 100644 index 0000000000..52cb8eaccc --- /dev/null +++ b/tests/specs/test/default_ts/as_ts.js @@ -0,0 +1,3 @@ +Deno.test(function foo() { + const x: string = "foo"; +}); diff --git a/tests/specs/test/default_ts/ext.out b/tests/specs/test/default_ts/ext.out new file mode 100644 index 0000000000..55f7526a54 --- /dev/null +++ b/tests/specs/test/default_ts/ext.out @@ -0,0 +1,4 @@ +Check file:///[WILDCARD]/as_ts.js +running 1 test from ./as_ts.js +[WILDCARD] + diff --git a/tests/specs/test/default_ts/extensionless b/tests/specs/test/default_ts/extensionless new file mode 100644 index 0000000000..52cb8eaccc --- /dev/null +++ b/tests/specs/test/default_ts/extensionless @@ -0,0 +1,3 @@ +Deno.test(function foo() { + const x: string = "foo"; +}); diff --git a/tests/specs/test/default_ts/extensionless.out b/tests/specs/test/default_ts/extensionless.out new file mode 100644 index 0000000000..20d4ee2cb0 --- /dev/null +++ b/tests/specs/test/default_ts/extensionless.out @@ -0,0 +1,4 @@ +Check file:///[WILDCARD]/extensionless +running 1 test from ./extensionless +[WILDCARD] + diff --git a/tests/specs/test/doc/__test__.jsonc b/tests/specs/test/doc/__test__.jsonc new file mode 100644 index 0000000000..095ab4c592 --- /dev/null +++ b/tests/specs/test/doc/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/doc/main.out b/tests/specs/test/doc/main.out new file mode 100644 index 0000000000..a255823708 --- /dev/null +++ b/tests/specs/test/doc/main.out @@ -0,0 +1,9 @@ +Check [WILDCARD]/main.ts$6-9.js +Check [WILDCARD]/main.ts$10-13.jsx +Check [WILDCARD]/main.ts$14-17.ts +Check [WILDCARD]/main.ts$18-21.tsx +Check [WILDCARD]/main.ts$30-35.ts +error: TS2367 [ERROR]: This comparison appears to be unintentional because the types 'string' and 'number' have no overlap. + console.assert(check() == 42); + ~~~~~~~~~~~~~ + at [WILDCARD]/main.ts$30-35.ts:3:20 diff --git a/tests/specs/test/doc/main.ts b/tests/specs/test/doc/main.ts new file mode 100644 index 0000000000..213a9f44d3 --- /dev/null +++ b/tests/specs/test/doc/main.ts @@ -0,0 +1,38 @@ +/** + * ``` + * import * as doc from "./main.ts"; + * ``` + * + * ```js + * import * as doc from "./main.ts"; + * ``` + * + * ```jsx + * import * as doc from "./main.ts"; + * ``` + * + * ```ts + * import * as doc from "./main.ts"; + * ``` + * + * ```tsx + * import * as doc from "./main.ts"; + * ``` + * + * ```text + * import * as doc from "./main.ts"; + * ``` + * + * @module doc + */ + +/** + * ```ts + * import { check } from "./main.ts"; + * + * console.assert(check() == 42); + * ``` + */ +export function check(): string { + return "check"; +} diff --git a/tests/specs/test/doc_duplicate_identifier/__test__.jsonc b/tests/specs/test/doc_duplicate_identifier/__test__.jsonc new file mode 100644 index 0000000000..2a8e6aafca --- /dev/null +++ b/tests/specs/test/doc_duplicate_identifier/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/doc_duplicate_identifier/main.out b/tests/specs/test/doc_duplicate_identifier/main.out new file mode 100644 index 0000000000..9196405a65 --- /dev/null +++ b/tests/specs/test/doc_duplicate_identifier/main.out @@ -0,0 +1,11 @@ +Check [WILDCARD]/main.ts +Check [WILDCARD]/main.ts$11-19.ts +Check [WILDCARD]/main.ts$25-30.ts +running 0 tests from ./main.ts +running 1 test from ./main.ts$11-19.ts +[WILDCARD]/main.ts$11-19.ts ... ok ([WILDCARD]ms) +running 1 test from ./main.ts$25-30.ts +[WILDCARD]/main.ts$25-30.ts ... ok ([WILDCARD]ms) + +ok | 2 passed | 0 failed ([WILDCARD]ms) + diff --git a/tests/specs/test/doc_duplicate_identifier/main.ts b/tests/specs/test/doc_duplicate_identifier/main.ts new file mode 100644 index 0000000000..df78294d0a --- /dev/null +++ b/tests/specs/test/doc_duplicate_identifier/main.ts @@ -0,0 +1,33 @@ +// `deno test --doc` tries to convert the example code snippets into pseudo +// test files in a way that all the exported items are available without +// explicit import statements. Therefore, in the test code, you don't have to +// write like `import { add } from "./main.ts";`. +// However, this automatic import resolution might conflict with other +// explicitly declared identifiers in the test code you write. This spec test +// makes sure that such cases will not cause any issues - explicit identifiers +// take precedence. + +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * import { getModuleName, createFoo } from "./mod.ts"; + * + * const foo = createFoo(); + * assertEquals(getModuleName(), "mod.ts"); + * assertEquals(add(1, 2), foo()); + * ``` + */ +export function add(a: number, b: number): number { + return a + b; +} + +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(getModuleName(), "main.ts"); + * ``` + */ +export const getModuleName = () => "main.ts"; + +export let foo = 1234; diff --git a/tests/specs/test/doc_duplicate_identifier/mod.ts b/tests/specs/test/doc_duplicate_identifier/mod.ts new file mode 100644 index 0000000000..c613a99adf --- /dev/null +++ b/tests/specs/test/doc_duplicate_identifier/mod.ts @@ -0,0 +1,7 @@ +export function getModuleName() { + return "mod.ts"; +} + +export const createFoo = () => { + return () => 3; +}; diff --git a/tests/specs/test/doc_failure/__test__.jsonc b/tests/specs/test/doc_failure/__test__.jsonc new file mode 100644 index 0000000000..79f16ad8d8 --- /dev/null +++ b/tests/specs/test/doc_failure/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/doc_failure/main.out b/tests/specs/test/doc_failure/main.out new file mode 100644 index 0000000000..01b03297f8 --- /dev/null +++ b/tests/specs/test/doc_failure/main.out @@ -0,0 +1,60 @@ +Check [WILDCARD]/main.ts +Check [WILDCARD]/main.ts$2-9.ts +Check [WILDCARD]/main.ts$13-18.ts +Check [WILDCARD]/main.ts$24-29.ts +running 0 tests from ./main.ts +running 1 test from ./main.ts$2-9.ts +[WILDCARD]/main.ts$2-9.ts ... FAILED ([WILDCARD]ms) +running 1 test from ./main.ts$13-18.ts +[WILDCARD]/main.ts$13-18.ts ... FAILED ([WILDCARD]ms) +running 1 test from ./main.ts$24-29.ts +[WILDCARD]/main.ts$24-29.ts ... FAILED ([WILDCARD]ms) + + ERRORS + +[WILDCARD]/main.ts$13-18.ts => ./main.ts$13-18.ts:3:6 +error: AssertionError: Values are not equal. + + + [Diff] Actual / Expected + + +- 3 ++ 4 + + throw new AssertionError(message); + ^ + at assertEquals ([WILDCARD]/std/assert/equals.ts:[WILDCARD]) + at [WILDCARD]/main.ts$13-18.ts:4:5 + +[WILDCARD]/main.ts$2-9.ts => ./main.ts$2-9.ts:3:6 +error: AssertionError: Expected actual: "2.5e+0" to be close to "2": delta "5e-1" is greater than "2e-7". + throw new AssertionError( + ^ + at assertAlmostEquals ([WILDCARD]/std/assert/almost_equals.ts:[WILDCARD]) + at [WILDCARD]/main.ts$2-9.ts:6:5 + +[WILDCARD]/main.ts$24-29.ts => ./main.ts$24-29.ts:3:6 +error: AssertionError: Values are not equal. + + + [Diff] Actual / Expected + + +- 4 ++ 3 + + throw new AssertionError(message); + ^ + at assertEquals ([WILDCARD]/std/assert/equals.ts:[WILDCARD]) + at [WILDCARD]/main.ts$24-29.ts:4:5 + + FAILURES + +[WILDCARD]/main.ts$13-18.ts => ./main.ts$13-18.ts:3:6 +[WILDCARD]/main.ts$2-9.ts => ./main.ts$2-9.ts:3:6 +[WILDCARD]/main.ts$24-29.ts => ./main.ts$24-29.ts:3:6 + +FAILED | 0 passed | 3 failed ([WILDCARD]ms) + +error: Test failed diff --git a/tests/specs/test/doc_failure/main.ts b/tests/specs/test/doc_failure/main.ts new file mode 100644 index 0000000000..7ec678c034 --- /dev/null +++ b/tests/specs/test/doc_failure/main.ts @@ -0,0 +1,32 @@ +/** + * ```ts + * import { assertAlmostEquals } from "@std/assert/almost-equals"; + * + * const x = sub(3, 1); + * const y = div(5, x); + * assertAlmostEquals(y, 2.0); // throws + * ``` + * @module doc + */ + +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(div(6, 2), 4); // throws + * ``` + */ +export function div(a: number, b: number): number { + return a / b; +} + +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(sub(6, 2), 3); // throws + * ``` + */ +const sub = (a: number, b: number): number => a - b; + +export { sub }; diff --git a/tests/specs/test/doc_only/__test__.jsonc b/tests/specs/test/doc_only/__test__.jsonc new file mode 100644 index 0000000000..f40260ae72 --- /dev/null +++ b/tests/specs/test/doc_only/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json doc_only", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/doc_only/mod.ts b/tests/specs/test/doc_only/doc_only/mod.ts similarity index 69% rename from tests/testdata/test/doc_only/mod.ts rename to tests/specs/test/doc_only/doc_only/mod.ts index 467d850a27..a389302ce8 100644 --- a/tests/testdata/test/doc_only/mod.ts +++ b/tests/specs/test/doc_only/doc_only/mod.ts @@ -1,6 +1,8 @@ /** * ```ts - * import "./mod.ts"; + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(42, 40 + 2); * ``` */ Deno.test("unreachable", function () { diff --git a/tests/specs/test/doc_only/main.out b/tests/specs/test/doc_only/main.out new file mode 100644 index 0000000000..634bd7636d --- /dev/null +++ b/tests/specs/test/doc_only/main.out @@ -0,0 +1,6 @@ +Check [WILDCARD]/doc_only/mod.ts$2-7.ts +running 1 test from ./doc_only/mod.ts$2-7.ts +[WILDCARD]/doc_only/mod.ts$2-7.ts ... ok ([WILDCARD]ms) + +ok | 1 passed | 0 failed ([WILDCARD]ms) + diff --git a/tests/specs/test/doc_permission_respected/__test__.jsonc b/tests/specs/test/doc_permission_respected/__test__.jsonc new file mode 100644 index 0000000000..43c2910844 --- /dev/null +++ b/tests/specs/test/doc_permission_respected/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-env=PATH --reload main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/doc_permission_respected/main.out b/tests/specs/test/doc_permission_respected/main.out new file mode 100644 index 0000000000..928d4f3cec --- /dev/null +++ b/tests/specs/test/doc_permission_respected/main.out @@ -0,0 +1,25 @@ +Check [WILDCARD]/main.ts +Check [WILDCARD]/main.ts$3-6.ts +Check [WILDCARD]/main.ts$8-11.ts +running 0 tests from ./main.ts +running 1 test from ./main.ts$3-6.ts +[WILDCARD]/main.ts$3-6.ts ... ok ([WILDCARD]ms) +running 1 test from ./main.ts$8-11.ts +[WILDCARD]/main.ts$8-11.ts ... FAILED ([WILDCARD]ms) + + ERRORS + +[WILDCARD]/main.ts$8-11.ts => ./main.ts$8-11.ts:1:6 +error: NotCapable: Requires env access to "USER", run again with the --allow-env flag + const _user = Deno.env.get("USER"); + ^ + at Object.getEnv [as get] ([WILDCARD]) + at [WILDCARD]/main.ts$8-11.ts:2:28 + + FAILURES + +[WILDCARD]/main.ts$8-11.ts => ./main.ts$8-11.ts:1:6 + +FAILED | 1 passed | 1 failed ([WILDCARD]ms) + +error: Test failed diff --git a/tests/specs/test/doc_permission_respected/main.ts b/tests/specs/test/doc_permission_respected/main.ts new file mode 100644 index 0000000000..fdc7743a86 --- /dev/null +++ b/tests/specs/test/doc_permission_respected/main.ts @@ -0,0 +1,12 @@ +/** + * This should succeed because we pass `--allow-env=PATH` + * ```ts + * const _path = Deno.env.get("PATH"); + * ``` + * + * This should fail because we don't allow for env access to `USER` + * ```ts + * const _user = Deno.env.get("USER"); + * ``` + * @module doc + */ diff --git a/tests/specs/test/doc_success/__test__.jsonc b/tests/specs/test/doc_success/__test__.jsonc new file mode 100644 index 0000000000..2a8e6aafca --- /dev/null +++ b/tests/specs/test/doc_success/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/doc_success/main.out b/tests/specs/test/doc_success/main.out new file mode 100644 index 0000000000..0eb8db49a1 --- /dev/null +++ b/tests/specs/test/doc_success/main.out @@ -0,0 +1,19 @@ +Check [WILDCARD]/main.ts$8-13.js +Check [WILDCARD]/main.ts$14-19.jsx +Check [WILDCARD]/main.ts$20-25.ts +Check [WILDCARD]/main.ts$26-31.tsx +Check [WILDCARD]/main.ts$42-47.ts +running 0 tests from ./main.ts +running 1 test from ./main.ts$8-13.js +[WILDCARD]/main.ts$8-13.js ... ok ([WILDCARD]s) +running 1 test from ./main.ts$14-19.jsx +[WILDCARD]/main.ts$14-19.jsx ... ok ([WILDCARD]s) +running 1 test from ./main.ts$20-25.ts +[WILDCARD]/main.ts$20-25.ts ... ok ([WILDCARD]s) +running 1 test from ./main.ts$26-31.tsx +[WILDCARD]/main.ts$26-31.tsx ... ok ([WILDCARD]s) +running 1 test from ./main.ts$42-47.ts +[WILDCARD]/main.ts$42-47.ts ... ok ([WILDCARD]s) + +ok | 5 passed | 0 failed ([WILDCARD]s) + diff --git a/tests/specs/test/doc_success/main.ts b/tests/specs/test/doc_success/main.ts new file mode 100644 index 0000000000..6ab339ca4f --- /dev/null +++ b/tests/specs/test/doc_success/main.ts @@ -0,0 +1,50 @@ +/** + * ``` + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * ```js + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * ```jsx + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * ```tsx + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * ```text + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + * + * @module doc + */ + +/** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * + * assertEquals(add(1, 2), 3); + * ``` + */ +export function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/test/doc_ts_declare_global/__test__.jsonc b/tests/specs/test/doc_ts_declare_global/__test__.jsonc new file mode 100644 index 0000000000..db1e607aad --- /dev/null +++ b/tests/specs/test/doc_ts_declare_global/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json lib.d.ts", + "exitCode": 0, + "output": "lib.d.ts.out" +} diff --git a/tests/specs/test/doc_ts_declare_global/lib.d.ts b/tests/specs/test/doc_ts_declare_global/lib.d.ts new file mode 100644 index 0000000000..a5f4429100 --- /dev/null +++ b/tests/specs/test/doc_ts_declare_global/lib.d.ts @@ -0,0 +1,13 @@ +export {}; + +declare global { + /** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * import "./mod.js"; + * + * assertEquals(myFunction(1, 2), 3); + * ``` + */ + export function myFunction(a: number, b: number): number; +} diff --git a/tests/specs/test/doc_ts_declare_global/lib.d.ts.out b/tests/specs/test/doc_ts_declare_global/lib.d.ts.out new file mode 100644 index 0000000000..2d6d8dbc85 --- /dev/null +++ b/tests/specs/test/doc_ts_declare_global/lib.d.ts.out @@ -0,0 +1,6 @@ +Check [WILDCARD]/lib$d$ts$5-11.ts +running 1 test from ./lib$d$ts$5-11.ts +[WILDCARD]/lib$d$ts$5-11.ts ... ok ([WILDCARD]ms) + +ok | 1 passed | 0 failed ([WILDCARD]ms) + diff --git a/tests/specs/test/doc_ts_declare_global/mod.js b/tests/specs/test/doc_ts_declare_global/mod.js new file mode 100644 index 0000000000..1b378d2a7a --- /dev/null +++ b/tests/specs/test/doc_ts_declare_global/mod.js @@ -0,0 +1 @@ +globalThis.myFunction = (a, b) => a + b; diff --git a/tests/specs/test/doc_ts_namespace_decl/__test__.jsonc b/tests/specs/test/doc_ts_namespace_decl/__test__.jsonc new file mode 100644 index 0000000000..db1e607aad --- /dev/null +++ b/tests/specs/test/doc_ts_namespace_decl/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --config ../../../config/deno.json lib.d.ts", + "exitCode": 0, + "output": "lib.d.ts.out" +} diff --git a/tests/specs/test/doc_ts_namespace_decl/lib.d.ts b/tests/specs/test/doc_ts_namespace_decl/lib.d.ts new file mode 100644 index 0000000000..e7c81cb5f1 --- /dev/null +++ b/tests/specs/test/doc_ts_namespace_decl/lib.d.ts @@ -0,0 +1,11 @@ +declare namespace MyNamespace { + /** + * ```ts + * import { assertEquals } from "@std/assert/equals"; + * import "./mod.js"; + * + * assertEquals(MyNamespace.add(1, 2), 3); + * ``` + */ + export function add(a: number, b: number): number; +} diff --git a/tests/specs/test/doc_ts_namespace_decl/lib.d.ts.out b/tests/specs/test/doc_ts_namespace_decl/lib.d.ts.out new file mode 100644 index 0000000000..2c9e71dc4a --- /dev/null +++ b/tests/specs/test/doc_ts_namespace_decl/lib.d.ts.out @@ -0,0 +1,6 @@ +Check [WILDCARD]/lib$d$ts$3-9.ts +running 1 test from ./lib$d$ts$3-9.ts +[WILDCARD]/lib$d$ts$3-9.ts ... ok ([WILDCARD]ms) + +ok | 1 passed | 0 failed ([WILDCARD]ms) + diff --git a/tests/specs/test/doc_ts_namespace_decl/mod.js b/tests/specs/test/doc_ts_namespace_decl/mod.js new file mode 100644 index 0000000000..6a96c342fb --- /dev/null +++ b/tests/specs/test/doc_ts_namespace_decl/mod.js @@ -0,0 +1,5 @@ +globalThis.MyNamespace = { + add(a, b) { + return a + b; + }, +}; diff --git a/tests/specs/test/document/__test__.jsonc b/tests/specs/test/document/__test__.jsonc new file mode 100644 index 0000000000..cf73b4bab8 --- /dev/null +++ b/tests/specs/test/document/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tests": { + "document": { + "args": "test document_test.js", + "exitCode": 1, + "output": "document_test.out" + } + } +} diff --git a/tests/specs/test/document/document_test.js b/tests/specs/test/document/document_test.js new file mode 100644 index 0000000000..d60d6893cc --- /dev/null +++ b/tests/specs/test/document/document_test.js @@ -0,0 +1,3 @@ +Deno.test("document query selector", () => { + document.querySelector("div"); +}); diff --git a/tests/specs/test/document/document_test.out b/tests/specs/test/document/document_test.out new file mode 100644 index 0000000000..342cee0e47 --- /dev/null +++ b/tests/specs/test/document/document_test.out @@ -0,0 +1,22 @@ +running 1 test from ./document_test.js +document query selector ... FAILED [WILDCARD] + + ERRORS + +document query selector => ./document_test.js:1:6 +error: ReferenceError: document is not defined + document.querySelector("div"); + ^ + at [WILDCARD]document_test.js:2:3 + + info: document global is not available in Deno. + hint: Use a library like happy-dom, deno_dom, linkedom or JSDom + and setup the document global according to the library documentation. + + FAILURES + +document query selector => ./document_test.js:1:6 + +FAILED | 0 passed | 1 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/specs/test/exit_code/main.out b/tests/specs/test/exit_code/main.out index 2562695a02..d5fe6c4751 100644 --- a/tests/specs/test/exit_code/main.out +++ b/tests/specs/test/exit_code/main.out @@ -4,7 +4,7 @@ Deno.exitCode ... FAILED ([WILDCARD]) ERRORS Deno.exitCode => ./main.js:1:6 -error: Error: Test case finished with exit code set to 42. +error: Error: Test case finished with exit code set to 42 at exitSanitizer (ext:cli/40_test.js:113:15) at async outerWrapped (ext:cli/40_test.js:134:14) diff --git a/tests/specs/test/exit_code2/main.out b/tests/specs/test/exit_code2/main.out index adc9cb5775..4943846520 100644 --- a/tests/specs/test/exit_code2/main.out +++ b/tests/specs/test/exit_code2/main.out @@ -11,7 +11,7 @@ error: Error at [WILDCARD]/exit_code2/main.js:3:9 success => ./main.js:6:6 -error: Error: Test case finished with exit code set to 5. +error: Error: Test case finished with exit code set to 5 at exitSanitizer (ext:cli/40_test.js:113:15) at async outerWrapped (ext:cli/40_test.js:134:14) diff --git a/tests/specs/test/exit_code3/main.out b/tests/specs/test/exit_code3/main.out index 6e333bf425..a461db2f6f 100644 --- a/tests/specs/test/exit_code3/main.out +++ b/tests/specs/test/exit_code3/main.out @@ -5,7 +5,7 @@ success ... ok ([WILDCARD]) ERRORS Deno.exitCode => ./main.js:1:6 -error: Error: Test case finished with exit code set to 42. +error: Error: Test case finished with exit code set to 42 at exitSanitizer (ext:cli/40_test.js:113:15) at async outerWrapped (ext:cli/40_test.js:134:14) diff --git a/tests/specs/test/exit_sanitizer/__test__.jsonc b/tests/specs/test/exit_sanitizer/__test__.jsonc new file mode 100644 index 0000000000..79d075d670 --- /dev/null +++ b/tests/specs/test/exit_sanitizer/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test exit_sanitizer.ts", + "output": "exit_sanitizer.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/sanitizer/exit_sanitizer.out b/tests/specs/test/exit_sanitizer/exit_sanitizer.out similarity index 100% rename from tests/testdata/test/sanitizer/exit_sanitizer.out rename to tests/specs/test/exit_sanitizer/exit_sanitizer.out diff --git a/tests/testdata/test/sanitizer/exit_sanitizer.ts b/tests/specs/test/exit_sanitizer/exit_sanitizer.ts similarity index 100% rename from tests/testdata/test/sanitizer/exit_sanitizer.ts rename to tests/specs/test/exit_sanitizer/exit_sanitizer.ts diff --git a/tests/specs/test/fail/__test__.jsonc b/tests/specs/test/fail/__test__.jsonc new file mode 100644 index 0000000000..2c4ae3868d --- /dev/null +++ b/tests/specs/test/fail/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/fail/main.out b/tests/specs/test/fail/main.out new file mode 100644 index 0000000000..e305f93bd0 --- /dev/null +++ b/tests/specs/test/fail/main.out @@ -0,0 +1,91 @@ +Check [WILDCARD]/main.ts +running 10 tests from ./main.ts +test 0 ... FAILED ([WILDCARD]) +test 1 ... FAILED ([WILDCARD]) +test 2 ... FAILED ([WILDCARD]) +test 3 ... FAILED ([WILDCARD]) +test 4 ... FAILED ([WILDCARD]) +test 5 ... FAILED ([WILDCARD]) +test 6 ... FAILED ([WILDCARD]) +test 7 ... FAILED ([WILDCARD]) +test 8 ... FAILED ([WILDCARD]) +test 9 ... FAILED ([WILDCARD]) + + ERRORS + +test 0 => ./main.ts:1:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:2:9 + +test 1 => ./main.ts:4:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:5:9 + +test 2 => ./main.ts:7:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:8:9 + +test 3 => ./main.ts:10:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:11:9 + +test 4 => ./main.ts:13:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:14:9 + +test 5 => ./main.ts:16:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:17:9 + +test 6 => ./main.ts:19:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:20:9 + +test 7 => ./main.ts:22:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:23:9 + +test 8 => ./main.ts:25:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:26:9 + +test 9 => ./main.ts:28:6 +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:29:9 + + FAILURES + +test 0 => ./main.ts:1:6 +test 1 => ./main.ts:4:6 +test 2 => ./main.ts:7:6 +test 3 => ./main.ts:10:6 +test 4 => ./main.ts:13:6 +test 5 => ./main.ts:16:6 +test 6 => ./main.ts:19:6 +test 7 => ./main.ts:22:6 +test 8 => ./main.ts:25:6 +test 9 => ./main.ts:28:6 + +FAILED | 0 passed | 10 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/fail.ts b/tests/specs/test/fail/main.ts similarity index 100% rename from tests/testdata/test/fail.ts rename to tests/specs/test/fail/main.ts diff --git a/tests/specs/test/fail_fast/__test__.jsonc b/tests/specs/test/fail_fast/__test__.jsonc new file mode 100644 index 0000000000..a819df39f0 --- /dev/null +++ b/tests/specs/test/fail_fast/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --fail-fast fail_fast.ts fail_fast_other.ts", + "exitCode": 1, + "output": "fail_fast.out" +} diff --git a/tests/specs/test/fail_fast/fail_fast.out b/tests/specs/test/fail_fast/fail_fast.out new file mode 100644 index 0000000000..164c9c6a6b --- /dev/null +++ b/tests/specs/test/fail_fast/fail_fast.out @@ -0,0 +1,20 @@ +Check [WILDCARD]/fail_fast.ts +Check [WILDCARD]/fail_fast_other.ts +running 10 tests from ./fail_fast.ts +test 1 ... FAILED ([WILDCARD]) + + ERRORS + +test 1 => ./fail_fast.ts:[WILDCARD] +error: Error + throw new Error(); + ^ + at [WILDCARD]/fail_fast.ts:2:9 + + FAILURES + +test 1 => ./fail_fast.ts:[WILDCARD] + +FAILED | 0 passed | 1 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/fail_fast.ts b/tests/specs/test/fail_fast/fail_fast.ts similarity index 100% rename from tests/testdata/test/fail_fast.ts rename to tests/specs/test/fail_fast/fail_fast.ts diff --git a/tests/testdata/test/fail_fast_other.ts b/tests/specs/test/fail_fast/fail_fast_other.ts similarity index 100% rename from tests/testdata/test/fail_fast_other.ts rename to tests/specs/test/fail_fast/fail_fast_other.ts diff --git a/tests/specs/test/fail_with_contain_unicode_filename/__test__.jsonc b/tests/specs/test/fail_with_contain_unicode_filename/__test__.jsonc new file mode 100644 index 0000000000..d8887f7538 --- /dev/null +++ b/tests/specs/test/fail_with_contain_unicode_filename/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/test/fail_with_contain_unicode_filename/main.out b/tests/specs/test/fail_with_contain_unicode_filename/main.out new file mode 100644 index 0000000000..5cea77dc0f --- /dev/null +++ b/tests/specs/test/fail_with_contain_unicode_filename/main.out @@ -0,0 +1,19 @@ +Check [WILDCARD]/main.ts +running 1 test from ./main.ts +test 0 ... FAILED ([WILDCARD]) + + ERRORS + +test 0 => ./main.ts:[WILDCARD] +error: Error + throw new Error(); + ^ + at [WILDCARD]/main.ts:[WILDCARD] + + FAILURES + +test 0 => ./main.ts:[WILDCARD] + +FAILED | 0 passed | 1 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/specs/test/fail_with_contain_unicode_filename/main.ts b/tests/specs/test/fail_with_contain_unicode_filename/main.ts new file mode 100644 index 0000000000..9fe04c1313 --- /dev/null +++ b/tests/specs/test/fail_with_contain_unicode_filename/main.ts @@ -0,0 +1,3 @@ +Deno.test("test 0", () => { + throw new Error(); +}); diff --git a/tests/specs/test/file_protocol/__test__.jsonc b/tests/specs/test/file_protocol/__test__.jsonc new file mode 100644 index 0000000000..931a8c64e1 --- /dev/null +++ b/tests/specs/test/file_protocol/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test main.ts", + "output": "main.out" +} diff --git a/tests/specs/test/file_protocol/main.out b/tests/specs/test/file_protocol/main.out new file mode 100644 index 0000000000..d02b728d18 --- /dev/null +++ b/tests/specs/test/file_protocol/main.out @@ -0,0 +1,6 @@ +Check file://[WILDCARD]/main.ts +running 1 test from ./main.ts +test 0 ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/testdata/test/file_protocol.ts b/tests/specs/test/file_protocol/main.ts similarity index 100% rename from tests/testdata/test/file_protocol.ts rename to tests/specs/test/file_protocol/main.ts diff --git a/tests/specs/test/filter/__test__.jsonc b/tests/specs/test/filter/__test__.jsonc new file mode 100644 index 0000000000..b7c1bb9fe6 --- /dev/null +++ b/tests/specs/test/filter/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --filter=foo filter", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/filter/a_test.ts b/tests/specs/test/filter/filter/a_test.ts similarity index 100% rename from tests/testdata/test/filter/a_test.ts rename to tests/specs/test/filter/filter/a_test.ts diff --git a/tests/testdata/test/filter/b_test.ts b/tests/specs/test/filter/filter/b_test.ts similarity index 100% rename from tests/testdata/test/filter/b_test.ts rename to tests/specs/test/filter/filter/b_test.ts diff --git a/tests/testdata/test/filter/c_test.ts b/tests/specs/test/filter/filter/c_test.ts similarity index 100% rename from tests/testdata/test/filter/c_test.ts rename to tests/specs/test/filter/filter/c_test.ts diff --git a/tests/specs/test/filter/main.out b/tests/specs/test/filter/main.out new file mode 100644 index 0000000000..605214b8e1 --- /dev/null +++ b/tests/specs/test/filter/main.out @@ -0,0 +1,12 @@ +Check [WILDCARD]/filter/a_test.ts +Check [WILDCARD]/filter/b_test.ts +Check [WILDCARD]/filter/c_test.ts +running 1 test from [WILDCARD]/filter/a_test.ts +foo ... ok ([WILDCARD]) +running 1 test from [WILDCARD]/filter/b_test.ts +foo ... ok ([WILDCARD]) +running 1 test from [WILDCARD]/filter/c_test.ts +foo ... ok ([WILDCARD]) + +ok | 3 passed | 0 failed | 6 filtered out ([WILDCARD]) + diff --git a/tests/specs/test/finally_timeout/__test__.jsonc b/tests/specs/test/finally_timeout/__test__.jsonc new file mode 100644 index 0000000000..2c4ae3868d --- /dev/null +++ b/tests/specs/test/finally_timeout/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/finally_timeout/main.out b/tests/specs/test/finally_timeout/main.out new file mode 100644 index 0000000000..cdc081f47d --- /dev/null +++ b/tests/specs/test/finally_timeout/main.out @@ -0,0 +1,20 @@ +Check [WILDCARD]/main.ts +running 2 tests from ./main.ts +error ... FAILED ([WILDCARD]) +success ... ok ([WILDCARD]) + + ERRORS + +error => ./main.ts:[WILDCARD] +error: Error: fail + throw new Error("fail"); + ^ + at [WILDCARD]/main.ts:4:11 + + FAILURES + +error => ./main.ts:[WILDCARD] + +FAILED | 1 passed | 1 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/finally_timeout.ts b/tests/specs/test/finally_timeout/main.ts similarity index 100% rename from tests/testdata/test/finally_timeout.ts rename to tests/specs/test/finally_timeout/main.ts diff --git a/tests/specs/test/hide_empty_suites/__test__.jsonc b/tests/specs/test/hide_empty_suites/__test__.jsonc new file mode 100644 index 0000000000..4abef92054 --- /dev/null +++ b/tests/specs/test/hide_empty_suites/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --filter none main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/hide_empty_suites.out b/tests/specs/test/hide_empty_suites/main.out similarity index 65% rename from tests/testdata/test/hide_empty_suites.out rename to tests/specs/test/hide_empty_suites/main.out index d270cb05a5..bfc30e0846 100644 --- a/tests/testdata/test/hide_empty_suites.out +++ b/tests/specs/test/hide_empty_suites/main.out @@ -1,4 +1,4 @@ -Check [WILDCARD]/test/pass.ts +Check [WILDCARD]/main.ts ok | 0 passed | 0 failed | 16 filtered out ([WILDCARD]) diff --git a/tests/testdata/test/pass.ts b/tests/specs/test/hide_empty_suites/main.ts similarity index 100% rename from tests/testdata/test/pass.ts rename to tests/specs/test/hide_empty_suites/main.ts diff --git a/tests/specs/test/ignore/__test__.jsonc b/tests/specs/test/ignore/__test__.jsonc new file mode 100644 index 0000000000..e1ed1b926c --- /dev/null +++ b/tests/specs/test/ignore/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/ignore.out b/tests/specs/test/ignore/main.out similarity index 84% rename from tests/testdata/test/ignore.out rename to tests/specs/test/ignore/main.out index e67406c635..390d4f9161 100644 --- a/tests/testdata/test/ignore.out +++ b/tests/specs/test/ignore/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/ignore.ts -running 10 tests from ./test/ignore.ts +Check [WILDCARD]/main.ts +running 10 tests from ./main.ts test 0 ... ignored ([WILDCARD]) test 1 ... ignored ([WILDCARD]) test 2 ... ignored ([WILDCARD]) diff --git a/tests/testdata/test/ignore.ts b/tests/specs/test/ignore/main.ts similarity index 100% rename from tests/testdata/test/ignore.ts rename to tests/specs/test/ignore/main.ts diff --git a/tests/specs/test/ignore_persmissions/__test__.jsonc b/tests/specs/test/ignore_persmissions/__test__.jsonc new file mode 100644 index 0000000000..e1ed1b926c --- /dev/null +++ b/tests/specs/test/ignore_persmissions/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/ignore_persmissions/main.out b/tests/specs/test/ignore_persmissions/main.out new file mode 100644 index 0000000000..d5cec67c03 --- /dev/null +++ b/tests/specs/test/ignore_persmissions/main.out @@ -0,0 +1,6 @@ +Check [WILDCARD]/main.ts +running 1 test from ./main.ts +ignore ... ignored ([WILDCARD]) + +ok | 0 passed | 0 failed | 1 ignored ([WILDCARD]) + diff --git a/tests/testdata/test/ignore_permissions.ts b/tests/specs/test/ignore_persmissions/main.ts similarity index 92% rename from tests/testdata/test/ignore_permissions.ts rename to tests/specs/test/ignore_persmissions/main.ts index ff30844413..e9ade6dfe9 100644 --- a/tests/testdata/test/ignore_permissions.ts +++ b/tests/specs/test/ignore_persmissions/main.ts @@ -7,7 +7,6 @@ Deno.test({ env: true, run: true, ffi: true, - hrtime: true, }, ignore: true, fn() { diff --git a/tests/specs/test/interval/__test__.jsonc b/tests/specs/test/interval/__test__.jsonc new file mode 100644 index 0000000000..e1ed1b926c --- /dev/null +++ b/tests/specs/test/interval/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/interval/main.out b/tests/specs/test/interval/main.out new file mode 100644 index 0000000000..7e5ef2914e --- /dev/null +++ b/tests/specs/test/interval/main.out @@ -0,0 +1,5 @@ +Check [WILDCARD]/main.ts +running 0 tests from ./main.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/testdata/test/interval.ts b/tests/specs/test/interval/main.ts similarity index 100% rename from tests/testdata/test/interval.ts rename to tests/specs/test/interval/main.ts diff --git a/tests/specs/test/junit/__test__.jsonc b/tests/specs/test/junit/__test__.jsonc new file mode 100644 index 0000000000..5e91e5287c --- /dev/null +++ b/tests/specs/test/junit/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test --reporter junit main.ts", + "output": "main.out" +} diff --git a/tests/specs/test/junit/main.out b/tests/specs/test/junit/main.out new file mode 100644 index 0000000000..ca9558118b --- /dev/null +++ b/tests/specs/test/junit/main.out @@ -0,0 +1,38 @@ +Check file:///[WILDCARD]/main.ts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/specs/test/junit/main.ts b/tests/specs/test/junit/main.ts new file mode 100644 index 0000000000..c4c0f45dcd --- /dev/null +++ b/tests/specs/test/junit/main.ts @@ -0,0 +1,37 @@ +Deno.test("test 0", () => {}); +Deno.test("test 1", () => {}); +Deno.test("test 2", () => {}); +Deno.test("test 3", () => {}); +Deno.test("test 4", () => {}); +Deno.test("test 5", () => {}); +Deno.test("test 6", () => {}); +Deno.test("test 7", () => {}); +Deno.test("test 8", () => { + console.log("console.log"); +}); +Deno.test("test 9", () => { + console.error("console.error"); +}); + +Deno.test("test\b", () => { + console.error("console.error"); +}); +Deno.test("test\f", () => { + console.error("console.error"); +}); + +Deno.test("test\t", () => { + console.error("console.error"); +}); + +Deno.test("test\n", () => { + console.error("console.error"); +}); + +Deno.test("test\r", () => { + console.error("console.error"); +}); + +Deno.test("test\v", () => { + console.error("console.error"); +}); diff --git a/tests/specs/test/junit_multiple_test_files/__test__.jsonc b/tests/specs/test/junit_multiple_test_files/__test__.jsonc new file mode 100644 index 0000000000..d9b01bcb45 --- /dev/null +++ b/tests/specs/test/junit_multiple_test_files/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter junit pass.ts fail.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/fail_fast_with_val.ts b/tests/specs/test/junit_multiple_test_files/fail.ts similarity index 100% rename from tests/testdata/test/fail_fast_with_val.ts rename to tests/specs/test/junit_multiple_test_files/fail.ts index 637e825ece..9340db5569 100644 --- a/tests/testdata/test/fail_fast_with_val.ts +++ b/tests/specs/test/junit_multiple_test_files/fail.ts @@ -1,3 +1,6 @@ +Deno.test("test 0", () => { + throw new Error(); +}); Deno.test("test 1", () => { throw new Error(); }); @@ -25,6 +28,3 @@ Deno.test("test 8", () => { Deno.test("test 9", () => { throw new Error(); }); -Deno.test("test 0", () => { - throw new Error(); -}); diff --git a/tests/specs/test/junit_multiple_test_files/main.out b/tests/specs/test/junit_multiple_test_files/main.out new file mode 100644 index 0000000000..4ca962fd85 --- /dev/null +++ b/tests/specs/test/junit_multiple_test_files/main.out @@ -0,0 +1,102 @@ +Check file:///[WILDCARD]/pass.ts +Check file:///[WILDCARD]/fail.ts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:2:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:5:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:8:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:11:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:14:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:17:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:20:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:23:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:26:9 + + + Error + throw new Error(); + ^ + at file:///[WILDCARD]/fail.ts:29:9 + + + +error: Test failed diff --git a/tests/specs/test/junit_multiple_test_files/pass.ts b/tests/specs/test/junit_multiple_test_files/pass.ts new file mode 100644 index 0000000000..c4c0f45dcd --- /dev/null +++ b/tests/specs/test/junit_multiple_test_files/pass.ts @@ -0,0 +1,37 @@ +Deno.test("test 0", () => {}); +Deno.test("test 1", () => {}); +Deno.test("test 2", () => {}); +Deno.test("test 3", () => {}); +Deno.test("test 4", () => {}); +Deno.test("test 5", () => {}); +Deno.test("test 6", () => {}); +Deno.test("test 7", () => {}); +Deno.test("test 8", () => { + console.log("console.log"); +}); +Deno.test("test 9", () => { + console.error("console.error"); +}); + +Deno.test("test\b", () => { + console.error("console.error"); +}); +Deno.test("test\f", () => { + console.error("console.error"); +}); + +Deno.test("test\t", () => { + console.error("console.error"); +}); + +Deno.test("test\n", () => { + console.error("console.error"); +}); + +Deno.test("test\r", () => { + console.error("console.error"); +}); + +Deno.test("test\v", () => { + console.error("console.error"); +}); diff --git a/tests/specs/test/junit_nested/__test__.jsonc b/tests/specs/test/junit_nested/__test__.jsonc new file mode 100644 index 0000000000..79b73474d5 --- /dev/null +++ b/tests/specs/test/junit_nested/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter junit main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/junit_nested/main.out b/tests/specs/test/junit_nested/main.out new file mode 100644 index 0000000000..f2ac00f299 --- /dev/null +++ b/tests/specs/test/junit_nested/main.out @@ -0,0 +1,47 @@ +Check file:///[WILDCARD]/main.ts + + + + + 1 test step failed. + + + 2 test steps failed. + + + + + + + Error: Fail. + throw new Error("Fail."); + ^ + at file:///[WILDCARD]/main.ts:4:11 + [WILDCARD] + + + 1 test step failed. + + + + + Error: Fail. + throw new Error("Fail."); + ^ + at file:///[WILDCARD]/main.ts:12:13 + [WILDCARD] + + + Error: Fail. + throw new Error("Fail."); + ^ + at file:///[WILDCARD]/main.ts:16:11 + [WILDCARD] + + + + + + + +error: Test failed diff --git a/tests/testdata/test/nested_failures.ts b/tests/specs/test/junit_nested/main.ts similarity index 100% rename from tests/testdata/test/nested_failures.ts rename to tests/specs/test/junit_nested/main.ts diff --git a/tests/specs/test/load_unload/__test__.jsonc b/tests/specs/test/load_unload/__test__.jsonc new file mode 100644 index 0000000000..e1ed1b926c --- /dev/null +++ b/tests/specs/test/load_unload/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/load_unload.out b/tests/specs/test/load_unload/main.out similarity index 77% rename from tests/testdata/test/load_unload.out rename to tests/specs/test/load_unload/main.out index 75187fa7be..6a818d911b 100644 --- a/tests/testdata/test/load_unload.out +++ b/tests/specs/test/load_unload/main.out @@ -1,8 +1,8 @@ -Check [WILDCARD]/load_unload.ts +Check [WILDCARD]/main.ts ------- pre-test output ------- load ----- pre-test output end ----- -running 1 test from [WILDCARD]/load_unload.ts +running 1 test from [WILDCARD]/main.ts test ... ------- output ------- test diff --git a/tests/testdata/test/load_unload.ts b/tests/specs/test/load_unload/main.ts similarity index 100% rename from tests/testdata/test/load_unload.ts rename to tests/specs/test/load_unload/main.ts diff --git a/tests/specs/test/markdown/__test__.jsonc b/tests/specs/test/markdown/__test__.jsonc new file mode 100644 index 0000000000..558106d555 --- /dev/null +++ b/tests/specs/test/markdown/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.md", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/markdown_windows.md b/tests/specs/test/markdown/main.md similarity index 100% rename from tests/testdata/test/markdown_windows.md rename to tests/specs/test/markdown/main.md diff --git a/tests/specs/test/markdown/main.out b/tests/specs/test/markdown/main.out new file mode 100644 index 0000000000..bdbd4325f0 --- /dev/null +++ b/tests/specs/test/markdown/main.out @@ -0,0 +1,7 @@ +Check [WILDCARD]/main.md$11-14.js +Check [WILDCARD]/main.md$17-20.ts +Check [WILDCARD]/main.md$29-32.ts +error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. + const a: string = 42; + ^ + at [WILDCARD]/main.md$29-32.ts:2:11 diff --git a/tests/specs/test/markdown_full_block_names/__test__.jsonc b/tests/specs/test/markdown_full_block_names/__test__.jsonc new file mode 100644 index 0000000000..558106d555 --- /dev/null +++ b/tests/specs/test/markdown_full_block_names/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.md", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/markdown_full_block_names.md b/tests/specs/test/markdown_full_block_names/main.md similarity index 100% rename from tests/testdata/test/markdown_full_block_names.md rename to tests/specs/test/markdown_full_block_names/main.md diff --git a/tests/specs/test/markdown_full_block_names/main.out b/tests/specs/test/markdown_full_block_names/main.out new file mode 100644 index 0000000000..d7e991ce10 --- /dev/null +++ b/tests/specs/test/markdown_full_block_names/main.out @@ -0,0 +1,6 @@ +Check [WILDCARD]/main.md$5-8.js +Check [WILDCARD]/main.md$17-20.ts +error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. + const a: string = 42; + ^ + at [WILDCARD]/main.md$17-20.ts:2:11 diff --git a/tests/specs/test/markdown_ignore_html_comment/__test__.jsonc b/tests/specs/test/markdown_ignore_html_comment/__test__.jsonc new file mode 100644 index 0000000000..558106d555 --- /dev/null +++ b/tests/specs/test/markdown_ignore_html_comment/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.md", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/markdown_with_comment.md b/tests/specs/test/markdown_ignore_html_comment/main.md similarity index 100% rename from tests/testdata/test/markdown_with_comment.md rename to tests/specs/test/markdown_ignore_html_comment/main.md diff --git a/tests/specs/test/markdown_ignore_html_comment/main.out b/tests/specs/test/markdown_ignore_html_comment/main.out new file mode 100644 index 0000000000..d30ba7822b --- /dev/null +++ b/tests/specs/test/markdown_ignore_html_comment/main.out @@ -0,0 +1,5 @@ +Check [WILDCARD]/main.md$34-37.ts +error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. + const a: string = 42; + ^ + at [WILDCARD]/main.md$34-37.ts:2:11 diff --git a/tests/specs/test/markdown_windows/__test__.jsonc b/tests/specs/test/markdown_windows/__test__.jsonc new file mode 100644 index 0000000000..558106d555 --- /dev/null +++ b/tests/specs/test/markdown_windows/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.md", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/markdown_windows/main.md b/tests/specs/test/markdown_windows/main.md new file mode 100644 index 0000000000..d18dbd1087 --- /dev/null +++ b/tests/specs/test/markdown_windows/main.md @@ -0,0 +1,31 @@ +# Documentation + +The following block does not have a language attribute and should be ignored: + +``` +This is a fenced block without attributes, it's invalid and it should be ignored. +``` + +The following block should be given a js extension on extraction: + +```js +console.log("js"); +``` + +The following block should be given a ts extension on extraction: + +```ts +console.log("ts"); +``` + +The following example contains the ignore attribute and will be ignored: + +```ts ignore +const value: Invalid = "ignored"; +``` + +The following example will trigger the type-checker to fail: + +```ts +const a: string = 42; +``` diff --git a/tests/specs/test/markdown_windows/main.out b/tests/specs/test/markdown_windows/main.out new file mode 100644 index 0000000000..bdbd4325f0 --- /dev/null +++ b/tests/specs/test/markdown_windows/main.out @@ -0,0 +1,7 @@ +Check [WILDCARD]/main.md$11-14.js +Check [WILDCARD]/main.md$17-20.ts +Check [WILDCARD]/main.md$29-32.ts +error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. + const a: string = 42; + ^ + at [WILDCARD]/main.md$29-32.ts:2:11 diff --git a/tests/specs/test/meta/__test__.jsonc b/tests/specs/test/meta/__test__.jsonc new file mode 100644 index 0000000000..e1ed1b926c --- /dev/null +++ b/tests/specs/test/meta/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/meta.out b/tests/specs/test/meta/main.out similarity index 60% rename from tests/testdata/test/meta.out rename to tests/specs/test/meta/main.out index c46315ece7..06a0daa7b8 100644 --- a/tests/testdata/test/meta.out +++ b/tests/specs/test/meta/main.out @@ -1,9 +1,9 @@ -Check [WILDCARD]/test/meta.ts -running 1 test from ./test/meta.ts +Check [WILDCARD]/main.ts +running 1 test from ./main.ts check values ... ------- output ------- import.meta.main: false -import.meta.url: [WILDCARD]/test/meta.ts +import.meta.url: [WILDCARD]/main.ts ----- output end ----- check values ... ok ([WILDCARD]) diff --git a/tests/testdata/test/meta.ts b/tests/specs/test/meta/main.ts similarity index 100% rename from tests/testdata/test/meta.ts rename to tests/specs/test/meta/main.ts diff --git a/tests/specs/test/no_check/__test__.jsonc b/tests/specs/test/no_check/__test__.jsonc new file mode 100644 index 0000000000..3d0c743360 --- /dev/null +++ b/tests/specs/test/no_check/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --no-check main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/no_check.out b/tests/specs/test/no_check/main.out similarity index 77% rename from tests/testdata/test/no_check.out rename to tests/specs/test/no_check/main.out index 66ad07e268..cd9e7d0fae 100644 --- a/tests/testdata/test/no_check.out +++ b/tests/specs/test/no_check/main.out @@ -1,8 +1,8 @@ -Uncaught error from ./test/no_check.ts FAILED +Uncaught error from ./main.ts FAILED ERRORS -./test/no_check.ts (uncaught error) +./main.ts (uncaught error) error: (in promise) TypeError: Cannot read properties of undefined (reading 'fn') Deno.test(); ^ @@ -12,7 +12,7 @@ It most likely originated from a dangling promise, event/timeout handler or top- FAILURES -./test/no_check.ts (uncaught error) +./main.ts (uncaught error) FAILED | 0 passed | 1 failed ([WILDCARD]) diff --git a/tests/testdata/test/no_check.ts b/tests/specs/test/no_check/main.ts similarity index 100% rename from tests/testdata/test/no_check.ts rename to tests/specs/test/no_check/main.ts diff --git a/tests/specs/test/no_color/__test__.jsonc b/tests/specs/test/no_color/__test__.jsonc new file mode 100644 index 0000000000..2c4ae3868d --- /dev/null +++ b/tests/specs/test/no_color/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/no_color/main.out b/tests/specs/test/no_color/main.out new file mode 100644 index 0000000000..834bbaf6e4 --- /dev/null +++ b/tests/specs/test/no_color/main.out @@ -0,0 +1,21 @@ +Check [WILDCARD]/main.ts +running 3 tests from ./main.ts +success ... ok ([WILDCARD]) +fail ... FAILED ([WILDCARD]) +ignored ... ignored ([WILDCARD]) + + ERRORS + +fail => ./main.ts:6:6 +error: Error: fail + throw new Error("fail"); + ^ + at fn ([WILDCARD]/main.ts:9:11) + + FAILURES + +fail => ./main.ts:6:6 + +FAILED | 1 passed | 1 failed | 1 ignored ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/no_color.ts b/tests/specs/test/no_color/main.ts similarity index 100% rename from tests/testdata/test/no_color.ts rename to tests/specs/test/no_color/main.ts diff --git a/tests/specs/test/no_files/__test__.jsonc b/tests/specs/test/no_files/__test__.jsonc index 0bb252ec77..3440a4907a 100644 --- a/tests/specs/test/no_files/__test__.jsonc +++ b/tests/specs/test/no_files/__test__.jsonc @@ -9,11 +9,6 @@ "args": "test --permit-no-files", "output": "permit_no_files.out", "exitCode": 0 - }, - "allow_none": { - "args": "test --allow-none", - "output": "allow_none.out", - "exitCode": 0 } } } diff --git a/tests/specs/test/no_files/allow_none.out b/tests/specs/test/no_files/allow_none.out deleted file mode 100644 index 1cc973bb52..0000000000 --- a/tests/specs/test/no_files/allow_none.out +++ /dev/null @@ -1,5 +0,0 @@ -⚠️ The `--allow-none` flag is deprecated and will be removed in Deno 2.0. -Use the `--permit-no-files` flag instead. - -ok | 0 passed | 0 failed (0ms) - diff --git a/tests/specs/test/no_prompt_by_default/__test__.jsonc b/tests/specs/test/no_prompt_by_default/__test__.jsonc new file mode 100644 index 0000000000..a02376f871 --- /dev/null +++ b/tests/specs/test/no_prompt_by_default/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/no_prompt_by_default/main.out b/tests/specs/test/no_prompt_by_default/main.out new file mode 100644 index 0000000000..e0d1290ecd --- /dev/null +++ b/tests/specs/test/no_prompt_by_default/main.out @@ -0,0 +1,16 @@ +running 1 test from ./main.ts +no prompt ... FAILED ([WILDCARD]s) + + ERRORS + +no prompt => ./main.ts:[WILDCARD] +error: NotCapable: Requires read access to "./some_file.txt", run again with the --allow-read flag +[WILDCARD] + + FAILURES + +no prompt => ./main.ts:[WILDCARD] + +FAILED | 0 passed | 1 failed ([WILDCARD]s) + +error: Test failed diff --git a/tests/testdata/test/no_prompt_by_default.ts b/tests/specs/test/no_prompt_by_default/main.ts similarity index 100% rename from tests/testdata/test/no_prompt_by_default.ts rename to tests/specs/test/no_prompt_by_default/main.ts diff --git a/tests/specs/test/no_prompt_with_denied_perms/__test__.jsonc b/tests/specs/test/no_prompt_with_denied_perms/__test__.jsonc new file mode 100644 index 0000000000..26050de002 --- /dev/null +++ b/tests/specs/test/no_prompt_with_denied_perms/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet --allow-read main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/no_prompt_with_denied_perms/main.out b/tests/specs/test/no_prompt_with_denied_perms/main.out new file mode 100644 index 0000000000..e0d1290ecd --- /dev/null +++ b/tests/specs/test/no_prompt_with_denied_perms/main.out @@ -0,0 +1,16 @@ +running 1 test from ./main.ts +no prompt ... FAILED ([WILDCARD]s) + + ERRORS + +no prompt => ./main.ts:[WILDCARD] +error: NotCapable: Requires read access to "./some_file.txt", run again with the --allow-read flag +[WILDCARD] + + FAILURES + +no prompt => ./main.ts:[WILDCARD] + +FAILED | 0 passed | 1 failed ([WILDCARD]s) + +error: Test failed diff --git a/tests/testdata/test/no_prompt_with_denied_perms.ts b/tests/specs/test/no_prompt_with_denied_perms/main.ts similarity index 100% rename from tests/testdata/test/no_prompt_with_denied_perms.ts rename to tests/specs/test/no_prompt_with_denied_perms/main.ts diff --git a/tests/specs/test/no_run/__test__.jsonc b/tests/specs/test/no_run/__test__.jsonc new file mode 100644 index 0000000000..6a6d714eeb --- /dev/null +++ b/tests/specs/test/no_run/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --no-run main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/no_run.out b/tests/specs/test/no_run/main.out similarity index 61% rename from tests/testdata/test/no_run.out rename to tests/specs/test/no_run/main.out index 5edf03fe0f..ff98849433 100644 --- a/tests/testdata/test/no_run.out +++ b/tests/specs/test/no_run/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/no_run.ts +Check [WILDCARD]/main.ts error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. const _value: string = 1; ~~~~~~ - at [WILDCARD]/test/no_run.ts:1:7 + at [WILDCARD]/main.ts:1:7 diff --git a/tests/testdata/test/no_run.ts b/tests/specs/test/no_run/main.ts similarity index 100% rename from tests/testdata/test/no_run.ts rename to tests/specs/test/no_run/main.ts diff --git a/tests/specs/test/non_error_thrown/__test__.jsonc b/tests/specs/test/non_error_thrown/__test__.jsonc new file mode 100644 index 0000000000..a02376f871 --- /dev/null +++ b/tests/specs/test/non_error_thrown/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/non_error_thrown/main.out b/tests/specs/test/non_error_thrown/main.out new file mode 100644 index 0000000000..7e0de8028b --- /dev/null +++ b/tests/specs/test/non_error_thrown/main.out @@ -0,0 +1,40 @@ +running 6 tests from [WILDCARD]/main.ts +foo ... FAILED ([WILDCARD]) +bar ... FAILED ([WILDCARD]) +baz ... FAILED ([WILDCARD]) +qux ... FAILED ([WILDCARD]) +quux ... FAILED ([WILDCARD]) +quuz ... FAILED ([WILDCARD]) + + ERRORS + +foo => [WILDCARD]/main.ts:1:6 +error: undefined + +bar => [WILDCARD]/main.ts:5:6 +error: null + +baz => [WILDCARD]/main.ts:9:6 +error: 123 + +qux => [WILDCARD]/main.ts:13:6 +error: "Hello, world!" + +quux => [WILDCARD]/main.ts:17:6 +error: [ 1, 2, 3 ] + +quuz => [WILDCARD]/main.ts:21:6 +error: { a: "Hello, world!", b: [ 1, 2, 3 ] } + + FAILURES + +foo => [WILDCARD]/main.ts:1:6 +bar => [WILDCARD]/main.ts:5:6 +baz => [WILDCARD]/main.ts:9:6 +qux => [WILDCARD]/main.ts:13:6 +quux => [WILDCARD]/main.ts:17:6 +quuz => [WILDCARD]/main.ts:21:6 + +FAILED | 0 passed | 6 failed ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/non_error_thrown.ts b/tests/specs/test/non_error_thrown/main.ts similarity index 100% rename from tests/testdata/test/non_error_thrown.ts rename to tests/specs/test/non_error_thrown/main.ts diff --git a/tests/specs/test/only/__test__.jsonc b/tests/specs/test/only/__test__.jsonc new file mode 100644 index 0000000000..2c4ae3868d --- /dev/null +++ b/tests/specs/test/only/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/testdata/test/only.out b/tests/specs/test/only/main.out similarity index 71% rename from tests/testdata/test/only.out rename to tests/specs/test/only/main.out index 2e66ed22b4..e1c745bcdf 100644 --- a/tests/testdata/test/only.out +++ b/tests/specs/test/only/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/only.ts -running 2 tests from ./test/only.ts +Check [WILDCARD]/main.ts +running 2 tests from ./main.ts only ... ok ([WILDCARD]) only2 ... ok ([WILDCARD]) diff --git a/tests/testdata/test/only.ts b/tests/specs/test/only/main.ts similarity index 100% rename from tests/testdata/test/only.ts rename to tests/specs/test/only/main.ts diff --git a/tests/specs/test/ops_sanitizer_closed_inside_started_before/__test__.jsonc b/tests/specs/test/ops_sanitizer_closed_inside_started_before/__test__.jsonc new file mode 100644 index 0000000000..a427ea6b86 --- /dev/null +++ b/tests/specs/test/ops_sanitizer_closed_inside_started_before/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --trace-leaks ops_sanitizer_closed_inside_started_before.ts", + "exitCode": 1, + "output": "ops_sanitizer_closed_inside_started_before.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_closed_inside_started_before.out b/tests/specs/test/ops_sanitizer_closed_inside_started_before/ops_sanitizer_closed_inside_started_before.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_closed_inside_started_before.out rename to tests/specs/test/ops_sanitizer_closed_inside_started_before/ops_sanitizer_closed_inside_started_before.out diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_closed_inside_started_before.ts b/tests/specs/test/ops_sanitizer_closed_inside_started_before/ops_sanitizer_closed_inside_started_before.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_closed_inside_started_before.ts rename to tests/specs/test/ops_sanitizer_closed_inside_started_before/ops_sanitizer_closed_inside_started_before.ts diff --git a/tests/specs/test/ops_sanitizer_multiple_timeout_tests/__test__.jsonc b/tests/specs/test/ops_sanitizer_multiple_timeout_tests/__test__.jsonc new file mode 100644 index 0000000000..71776d566c --- /dev/null +++ b/tests/specs/test/ops_sanitizer_multiple_timeout_tests/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --trace-leaks ops_sanitizer_multiple_timeout_tests.ts", + "exitCode": 1, + "output": "ops_sanitizer_multiple_timeout_tests.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests.out b/tests/specs/test/ops_sanitizer_multiple_timeout_tests/ops_sanitizer_multiple_timeout_tests.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests.out rename to tests/specs/test/ops_sanitizer_multiple_timeout_tests/ops_sanitizer_multiple_timeout_tests.out diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests.ts b/tests/specs/test/ops_sanitizer_multiple_timeout_tests/ops_sanitizer_multiple_timeout_tests.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests.ts rename to tests/specs/test/ops_sanitizer_multiple_timeout_tests/ops_sanitizer_multiple_timeout_tests.ts diff --git a/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/__test__.jsonc b/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/__test__.jsonc new file mode 100644 index 0000000000..c1e1438cda --- /dev/null +++ b/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test ops_sanitizer_multiple_timeout_tests.ts", + "exitCode": 1, + "output": "ops_sanitizer_multiple_timeout_tests_no_trace.out" +} diff --git a/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/ops_sanitizer_multiple_timeout_tests.ts b/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/ops_sanitizer_multiple_timeout_tests.ts new file mode 100644 index 0000000000..1f52d481f6 --- /dev/null +++ b/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/ops_sanitizer_multiple_timeout_tests.ts @@ -0,0 +1,10 @@ +// https://github.com/denoland/deno/issues/8965 + +function test() { + setTimeout(() => {}, 10000); + setTimeout(() => {}, 10001); +} + +Deno.test("test 1", () => test()); + +Deno.test("test 2", () => test()); diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests_no_trace.out b/tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/ops_sanitizer_multiple_timeout_tests_no_trace.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_multiple_timeout_tests_no_trace.out rename to tests/specs/test/ops_sanitizer_multiple_timeout_tests_no_trace/ops_sanitizer_multiple_timeout_tests_no_trace.out diff --git a/tests/specs/test/ops_sanitizer_nexttick/__test__.jsonc b/tests/specs/test/ops_sanitizer_nexttick/__test__.jsonc new file mode 100644 index 0000000000..29604e2fd7 --- /dev/null +++ b/tests/specs/test/ops_sanitizer_nexttick/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test --no-check ops_sanitizer_nexttick.ts", + "output": "ops_sanitizer_nexttick.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_nexttick.out b/tests/specs/test/ops_sanitizer_nexttick/ops_sanitizer_nexttick.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_nexttick.out rename to tests/specs/test/ops_sanitizer_nexttick/ops_sanitizer_nexttick.out diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_nexttick.ts b/tests/specs/test/ops_sanitizer_nexttick/ops_sanitizer_nexttick.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_nexttick.ts rename to tests/specs/test/ops_sanitizer_nexttick/ops_sanitizer_nexttick.ts diff --git a/tests/specs/test/ops_sanitizer_tcp/__test__.jsonc b/tests/specs/test/ops_sanitizer_tcp/__test__.jsonc new file mode 100644 index 0000000000..48f9404f4b --- /dev/null +++ b/tests/specs/test/ops_sanitizer_tcp/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --allow-net --trace-leaks ops_sanitizer_tcp.ts", + "exitCode": 1, + "output": "ops_sanitizer_tcp.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_tcp.out b/tests/specs/test/ops_sanitizer_tcp/ops_sanitizer_tcp.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_tcp.out rename to tests/specs/test/ops_sanitizer_tcp/ops_sanitizer_tcp.out diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_tcp.ts b/tests/specs/test/ops_sanitizer_tcp/ops_sanitizer_tcp.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_tcp.ts rename to tests/specs/test/ops_sanitizer_tcp/ops_sanitizer_tcp.ts diff --git a/tests/specs/test/ops_sanitizer_timeout_failure/__test__.jsonc b/tests/specs/test/ops_sanitizer_timeout_failure/__test__.jsonc new file mode 100644 index 0000000000..c044382baf --- /dev/null +++ b/tests/specs/test/ops_sanitizer_timeout_failure/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test ops_sanitizer_timeout_failure.ts", + "output": "ops_sanitizer_timeout_failure.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_timeout_failure.out b/tests/specs/test/ops_sanitizer_timeout_failure/ops_sanitizer_timeout_failure.out similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_timeout_failure.out rename to tests/specs/test/ops_sanitizer_timeout_failure/ops_sanitizer_timeout_failure.out diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_timeout_failure.ts b/tests/specs/test/ops_sanitizer_timeout_failure/ops_sanitizer_timeout_failure.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_timeout_failure.ts rename to tests/specs/test/ops_sanitizer_timeout_failure/ops_sanitizer_timeout_failure.ts diff --git a/tests/specs/test/ops_sanitizer_unstable/__test__.jsonc b/tests/specs/test/ops_sanitizer_unstable/__test__.jsonc new file mode 100644 index 0000000000..b9ec3c8784 --- /dev/null +++ b/tests/specs/test/ops_sanitizer_unstable/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --trace-leaks ops_sanitizer_unstable.ts", + "exitCode": 1, + "output": "ops_sanitizer_unstable.out" +} diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_unstable.out b/tests/specs/test/ops_sanitizer_unstable/ops_sanitizer_unstable.out similarity index 85% rename from tests/testdata/test/sanitizer/ops_sanitizer_unstable.out rename to tests/specs/test/ops_sanitizer_unstable/ops_sanitizer_unstable.out index 115d8cefad..a09f34592b 100644 --- a/tests/testdata/test/sanitizer/ops_sanitizer_unstable.out +++ b/tests/specs/test/ops_sanitizer_unstable/ops_sanitizer_unstable.out @@ -1,5 +1,3 @@ -⚠️ The `--trace-ops` flag is deprecated and will be removed in Deno 2.0. -Use the `--trace-leaks` flag instead. Check [WILDCARD]/ops_sanitizer_unstable.ts running 2 tests from [WILDCARD]/ops_sanitizer_unstable.ts no-op ... ok ([WILDCARD]) diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_unstable.ts b/tests/specs/test/ops_sanitizer_unstable/ops_sanitizer_unstable.ts similarity index 100% rename from tests/testdata/test/sanitizer/ops_sanitizer_unstable.ts rename to tests/specs/test/ops_sanitizer_unstable/ops_sanitizer_unstable.ts diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/__test__.jsonc b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/__test__.jsonc new file mode 100644 index 0000000000..ec4ab0127a --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/actually_excluded.test.ts b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/actually_excluded.test.ts new file mode 100644 index 0000000000..da1a8f7a04 --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/actually_excluded.test.ts @@ -0,0 +1 @@ +Deno.test("test3", () => {}); diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/deno.json b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/deno.json new file mode 100644 index 0000000000..e9c181e771 --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/deno.json @@ -0,0 +1,6 @@ +{ + "test": { + "exclude": ["!excluded.test.ts"] + }, + "exclude": ["excluded.test.ts", "actually_excluded.test.ts"] +} diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/excluded.test.ts b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/excluded.test.ts new file mode 100644 index 0000000000..afb582199b --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/excluded.test.ts @@ -0,0 +1 @@ +Deno.test("test2", () => {}); diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.out b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.out new file mode 100644 index 0000000000..6ed39696e2 --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.out @@ -0,0 +1,9 @@ +Check [WILDCARD]/excluded.test.ts +Check [WILDCARD]/main.test.ts +running 1 test from ./excluded.test.ts +test2 ... ok ([WILDCARD]) +running 1 test from ./main.test.ts +test1 ... ok ([WILDCARD]) + +ok | 2 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.test.ts b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.test.ts new file mode 100644 index 0000000000..8d0131f756 --- /dev/null +++ b/tests/specs/test/opt_out_top_level_exclude_via_test_unexclude/main.test.ts @@ -0,0 +1 @@ +Deno.test("test1", () => {}); diff --git a/tests/specs/test/overloads/__test__.jsonc b/tests/specs/test/overloads/__test__.jsonc new file mode 100644 index 0000000000..955107ebc2 --- /dev/null +++ b/tests/specs/test/overloads/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/testdata/test/overloads.out b/tests/specs/test/overloads/main.out similarity index 73% rename from tests/testdata/test/overloads.out rename to tests/specs/test/overloads/main.out index 87a3f07cb0..92ec46d0b3 100644 --- a/tests/testdata/test/overloads.out +++ b/tests/specs/test/overloads/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/overloads.ts -running 6 tests from ./test/overloads.ts +Check [WILDCARD]/overloads/main.ts +running 6 tests from ./main.ts test0 ... ok ([WILDCARD]) test1 ... ok ([WILDCARD]) test2 ... ok ([WILDCARD]) diff --git a/tests/testdata/test/overloads.ts b/tests/specs/test/overloads/main.ts similarity index 100% rename from tests/testdata/test/overloads.ts rename to tests/specs/test/overloads/main.ts diff --git a/tests/specs/test/package_json_basic/__test__.jsonc b/tests/specs/test/package_json_basic/__test__.jsonc new file mode 100644 index 0000000000..64e43afa57 --- /dev/null +++ b/tests/specs/test/package_json_basic/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + }, + { + "args": "test", + "output": "test.out" + } + ] +} diff --git a/tests/specs/test/package_json_basic/install.out b/tests/specs/test/package_json_basic/install.out new file mode 100644 index 0000000000..8f03ba6407 --- /dev/null +++ b/tests/specs/test/package_json_basic/install.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Initialize @denotest/esm-basic@1.0.0 diff --git a/tests/testdata/package_json/basic/lib.test.ts b/tests/specs/test/package_json_basic/lib.test.ts similarity index 100% rename from tests/testdata/package_json/basic/lib.test.ts rename to tests/specs/test/package_json_basic/lib.test.ts diff --git a/tests/specs/test/package_json_basic/lib.ts b/tests/specs/test/package_json_basic/lib.ts new file mode 100644 index 0000000000..1deed81f7e --- /dev/null +++ b/tests/specs/test/package_json_basic/lib.ts @@ -0,0 +1,9 @@ +import * as test from "@denotest/esm-basic"; + +export function add(a: number, b: number) { + return a + b; +} + +export function getValue() { + return test.getValue(); +} diff --git a/tests/specs/test/package_json_basic/package.json b/tests/specs/test/package_json_basic/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/test/package_json_basic/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/specs/test/package_json_basic/test.out b/tests/specs/test/package_json_basic/test.out new file mode 100644 index 0000000000..1ff57c1503 --- /dev/null +++ b/tests/specs/test/package_json_basic/test.out @@ -0,0 +1,6 @@ +Check file://[WILDCARD]/lib.test.ts +running 1 test from [WILDCARD]lib.test.ts +should add ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/package_json_basic_auto_install/__test__.jsonc b/tests/specs/test/package_json_basic_auto_install/__test__.jsonc new file mode 100644 index 0000000000..d80f3222a9 --- /dev/null +++ b/tests/specs/test/package_json_basic_auto_install/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "test", + "output": "test.out" + } + ] +} diff --git a/tests/specs/test/package_json_basic_auto_install/deno.json b/tests/specs/test/package_json_basic_auto_install/deno.json new file mode 100644 index 0000000000..fbd70ec480 --- /dev/null +++ b/tests/specs/test/package_json_basic_auto_install/deno.json @@ -0,0 +1,3 @@ +{ + "nodeModulesDir": "auto" +} diff --git a/tests/specs/test/package_json_basic_auto_install/lib.test.ts b/tests/specs/test/package_json_basic_auto_install/lib.test.ts new file mode 100644 index 0000000000..4e833e1f33 --- /dev/null +++ b/tests/specs/test/package_json_basic_auto_install/lib.test.ts @@ -0,0 +1,7 @@ +import { add } from "./lib.ts"; + +Deno.test("should add", () => { + if (add(1, 2) !== 3) { + throw new Error("Fail"); + } +}); diff --git a/tests/specs/test/package_json_basic_auto_install/lib.ts b/tests/specs/test/package_json_basic_auto_install/lib.ts new file mode 100644 index 0000000000..1deed81f7e --- /dev/null +++ b/tests/specs/test/package_json_basic_auto_install/lib.ts @@ -0,0 +1,9 @@ +import * as test from "@denotest/esm-basic"; + +export function add(a: number, b: number) { + return a + b; +} + +export function getValue() { + return test.getValue(); +} diff --git a/tests/specs/test/package_json_basic_auto_install/package.json b/tests/specs/test/package_json_basic_auto_install/package.json new file mode 100644 index 0000000000..54ca824d64 --- /dev/null +++ b/tests/specs/test/package_json_basic_auto_install/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@denotest/esm-basic": "*" + } +} diff --git a/tests/testdata/package_json/basic/lib.test.out b/tests/specs/test/package_json_basic_auto_install/test.out similarity index 82% rename from tests/testdata/package_json/basic/lib.test.out rename to tests/specs/test/package_json_basic_auto_install/test.out index 2f109ef38e..749c395485 100644 --- a/tests/testdata/package_json/basic/lib.test.out +++ b/tests/specs/test/package_json_basic_auto_install/test.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Initialize @denotest/esm-basic@1.0.0 Check file://[WILDCARD]/lib.test.ts diff --git a/tests/specs/test/parallel_flag/__test__.jsonc b/tests/specs/test/parallel_flag/__test__.jsonc new file mode 100644 index 0000000000..0c279e11d3 --- /dev/null +++ b/tests/specs/test/parallel_flag/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts --parallel", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/parallel_flag/main.out b/tests/specs/test/parallel_flag/main.out new file mode 100644 index 0000000000..54efc4cad4 --- /dev/null +++ b/tests/specs/test/parallel_flag/main.out @@ -0,0 +1,5 @@ +Check [WILDCARD]/main.ts +./main.ts => test ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/testdata/test/short-pass.ts b/tests/specs/test/parallel_flag/main.ts similarity index 100% rename from tests/testdata/test/short-pass.ts rename to tests/specs/test/parallel_flag/main.ts diff --git a/tests/specs/test/parallel_flag_with_env_variables/__test__.jsonc b/tests/specs/test/parallel_flag_with_env_variables/__test__.jsonc new file mode 100644 index 0000000000..330313467f --- /dev/null +++ b/tests/specs/test/parallel_flag_with_env_variables/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "args": "test main.ts --parallel", + "exitCode": 0, + "envs": { "DENO_JOBS": "2" }, + "output": "main.out" +} diff --git a/tests/specs/test/parallel_flag_with_env_variables/main.out b/tests/specs/test/parallel_flag_with_env_variables/main.out new file mode 100644 index 0000000000..54efc4cad4 --- /dev/null +++ b/tests/specs/test/parallel_flag_with_env_variables/main.out @@ -0,0 +1,5 @@ +Check [WILDCARD]/main.ts +./main.ts => test ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/parallel_flag_with_env_variables/main.ts b/tests/specs/test/parallel_flag_with_env_variables/main.ts new file mode 100644 index 0000000000..03818ae8d4 --- /dev/null +++ b/tests/specs/test/parallel_flag_with_env_variables/main.ts @@ -0,0 +1 @@ +Deno.test("test", () => {}); diff --git a/tests/specs/test/parallel_output/__test__.jsonc b/tests/specs/test/parallel_output/__test__.jsonc new file mode 100644 index 0000000000..dde5a1c6f6 --- /dev/null +++ b/tests/specs/test/parallel_output/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --parallel --reload main.ts", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/parallel_output/main.out b/tests/specs/test/parallel_output/main.out new file mode 100644 index 0000000000..3d020a71ff --- /dev/null +++ b/tests/specs/test/parallel_output/main.out @@ -0,0 +1,56 @@ +Check [WILDCARD]/main.ts +./main.ts => step output ... step 1 ... ok ([WILDCARD]s) +./main.ts => step output ... step 2 ... ok ([WILDCARD]s) +------- output ------- +Hello, world! (from step 3) +----- output end ----- +./main.ts => step output ... step 3 ... ok ([WILDCARD]s) +------- output ------- +Hello, world! (from step 4) +----- output end ----- +./main.ts => step output ... step 4 ... ok ([WILDCARD]s) +./main.ts => step output ... ok ([WILDCARD]s) +./main.ts => step failures ... step 1 ... ok ([WILDCARD]s) +./main.ts => step failures ... step 2 ... FAILED ([WILDCARD]s) +./main.ts => step failures ... step 3 ... FAILED ([WILDCARD]s) +./main.ts => step failures ... FAILED (due to 2 failed steps) ([WILDCARD]s) +./main.ts => step nested failure ... step 1 ... inner 1 ... ok ([WILDCARD]s) +./main.ts => step nested failure ... step 1 ... inner 2 ... FAILED ([WILDCARD]s) +./main.ts => step nested failure ... step 1 ... FAILED (due to 1 failed step) ([WILDCARD]s) +./main.ts => step nested failure ... FAILED (due to 1 failed step) ([WILDCARD]s) + + ERRORS + +step failures ... step 2 => ./main.ts:14:11 +error: Error: Fail. + throw new Error("Fail."); + ^ + at file:///[WILDCARD]/main.ts:15:11 + at [WILDCARD] + at file:///[WILDCARD]/main.ts:14:11 + +step failures ... step 3 => ./main.ts:17:11 +error: Error: Fail. + await t.step("step 3", () => Promise.reject(new Error("Fail."))); + ^ + at file:///[WILDCARD]/main.ts:17:47 + at [WILDCARD] + at file:///[WILDCARD]/main.ts:17:11 + +step nested failure ... step 1 ... inner 2 => ./main.ts:23:13 +error: Error: Failed. + throw new Error("Failed."); + ^ + at file:///[WILDCARD]/main.ts:24:13 + at [WILDCARD] + at file:///[WILDCARD]/main.ts:23:13 + + FAILURES + +step failures ... step 2 => ./main.ts:14:11 +step failures ... step 3 => ./main.ts:17:11 +step nested failure ... step 1 ... inner 2 => ./main.ts:23:13 + +FAILED | 1 passed (6 steps) | 2 failed (4 steps) ([WILDCARD]s) + +error: Test failed diff --git a/tests/testdata/test/parallel_output.ts b/tests/specs/test/parallel_output/main.ts similarity index 100% rename from tests/testdata/test/parallel_output.ts rename to tests/specs/test/parallel_output/main.ts diff --git a/tests/specs/test/pass/__test__.jsonc b/tests/specs/test/pass/__test__.jsonc new file mode 100644 index 0000000000..955107ebc2 --- /dev/null +++ b/tests/specs/test/pass/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/testdata/test/pass.out b/tests/specs/test/pass/main.out similarity index 93% rename from tests/testdata/test/pass.out rename to tests/specs/test/pass/main.out index 08b9f5a52b..d2541d08dd 100644 --- a/tests/testdata/test/pass.out +++ b/tests/specs/test/pass/main.out @@ -1,5 +1,5 @@ -Check [WILDCARD]/test/pass.ts -running 16 tests from ./test/pass.ts +Check [WILDCARD]/main.ts +running 16 tests from ./main.ts test 0 ... ok ([WILDCARD]) test 1 ... ok ([WILDCARD]) test 2 ... ok ([WILDCARD]) diff --git a/tests/specs/test/pass/main.ts b/tests/specs/test/pass/main.ts new file mode 100644 index 0000000000..c4c0f45dcd --- /dev/null +++ b/tests/specs/test/pass/main.ts @@ -0,0 +1,37 @@ +Deno.test("test 0", () => {}); +Deno.test("test 1", () => {}); +Deno.test("test 2", () => {}); +Deno.test("test 3", () => {}); +Deno.test("test 4", () => {}); +Deno.test("test 5", () => {}); +Deno.test("test 6", () => {}); +Deno.test("test 7", () => {}); +Deno.test("test 8", () => { + console.log("console.log"); +}); +Deno.test("test 9", () => { + console.error("console.error"); +}); + +Deno.test("test\b", () => { + console.error("console.error"); +}); +Deno.test("test\f", () => { + console.error("console.error"); +}); + +Deno.test("test\t", () => { + console.error("console.error"); +}); + +Deno.test("test\n", () => { + console.error("console.error"); +}); + +Deno.test("test\r", () => { + console.error("console.error"); +}); + +Deno.test("test\v", () => { + console.error("console.error"); +}); diff --git a/tests/specs/test/quiet/__test__.jsonc b/tests/specs/test/quiet/__test__.jsonc new file mode 100644 index 0000000000..799bc6ff28 --- /dev/null +++ b/tests/specs/test/quiet/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet main.ts", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/quiet.out b/tests/specs/test/quiet/main.out similarity index 82% rename from tests/testdata/test/quiet.out rename to tests/specs/test/quiet/main.out index 83dbe6ba90..5c72317f69 100644 --- a/tests/testdata/test/quiet.out +++ b/tests/specs/test/quiet/main.out @@ -1,4 +1,4 @@ -running 4 tests from ./test/quiet.ts +running 4 tests from ./main.ts console.log ... ok ([WILDCARD]) console.error ... ok ([WILDCARD]) console.info ... ok ([WILDCARD]) diff --git a/tests/testdata/test/quiet.ts b/tests/specs/test/quiet/main.ts similarity index 100% rename from tests/testdata/test/quiet.ts rename to tests/specs/test/quiet/main.ts diff --git a/tests/specs/test/recursive_permissions_pledge/__test__.jsonc b/tests/specs/test/recursive_permissions_pledge/__test__.jsonc new file mode 100644 index 0000000000..7dfb5b7ff2 --- /dev/null +++ b/tests/specs/test/recursive_permissions_pledge/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "args": "test main.js", + "exitCode": 1, + "envs": { + "RUST_BACKTRACE": "0" + }, + "output": "\n============================================================\nDeno has panicked. This is a bug in Deno. Please report this\nat https://github.com/denoland/deno/issues/new.\nIf you can reliably reproduce this panic, include the\nreproduction steps and re-run with the RUST_BACKTRACE=1 env\nvar set and include the backtrace in your report.\n\nPlatform: [WILDCARD]\nVersion: [WILDCARD]\nArgs: [[WILDCARD], \"test\", \"main.js\"]\n\nthread 'tokio-runtime-worker' panicked at [WILDCARD]testing.rs:[WILDCARD]:\npledge test permissions called before restoring previous pledge\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" +} diff --git a/tests/testdata/test/recursive_permissions_pledge.js b/tests/specs/test/recursive_permissions_pledge/main.js similarity index 100% rename from tests/testdata/test/recursive_permissions_pledge.js rename to tests/specs/test/recursive_permissions_pledge/main.js diff --git a/tests/specs/test/report_error/__test__.jsonc b/tests/specs/test/report_error/__test__.jsonc new file mode 100644 index 0000000000..59774f938a --- /dev/null +++ b/tests/specs/test/report_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/report_error.out b/tests/specs/test/report_error/main.out similarity index 63% rename from tests/testdata/test/report_error.out rename to tests/specs/test/report_error/main.out index 698550f97d..5fe3a44238 100644 --- a/tests/testdata/test/report_error.out +++ b/tests/specs/test/report_error/main.out @@ -1,22 +1,22 @@ -running 2 tests from [WILDCARD]/report_error.ts +running 2 tests from [WILDCARD]/main.ts foo ... -Uncaught error from [WILDCARD]/report_error.ts FAILED +Uncaught error from [WILDCARD]/main.ts FAILED foo ... cancelled (0ms) bar ... cancelled (0ms) ERRORS -[WILDCARD]/report_error.ts (uncaught error) +[WILDCARD]/main.ts (uncaught error) error: Error: foo reportError(new Error("foo")); ^ - at [WILDCARD]/report_error.ts:2:15 + at [WILDCARD]/main.ts:2:15 This error was not caught from a test and caused the test runner to fail on the referenced module. It most likely originated from a dangling promise, event/timeout handler or top-level code. FAILURES -[WILDCARD]/report_error.ts (uncaught error) +[WILDCARD]/main.ts (uncaught error) FAILED | 0 passed | 3 failed ([WILDCARD]) diff --git a/tests/testdata/test/report_error.ts b/tests/specs/test/report_error/main.ts similarity index 100% rename from tests/testdata/test/report_error.ts rename to tests/specs/test/report_error/main.ts diff --git a/tests/specs/test/resource_sanitizer/__test__.jsonc b/tests/specs/test/resource_sanitizer/__test__.jsonc new file mode 100644 index 0000000000..38417fba24 --- /dev/null +++ b/tests/specs/test/resource_sanitizer/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --allow-read resource_sanitizer.ts", + "output": "resource_sanitizer.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/sanitizer/resource_sanitizer.out b/tests/specs/test/resource_sanitizer/resource_sanitizer.out similarity index 100% rename from tests/testdata/test/sanitizer/resource_sanitizer.out rename to tests/specs/test/resource_sanitizer/resource_sanitizer.out diff --git a/tests/testdata/test/sanitizer/resource_sanitizer.ts b/tests/specs/test/resource_sanitizer/resource_sanitizer.ts similarity index 51% rename from tests/testdata/test/sanitizer/resource_sanitizer.ts rename to tests/specs/test/resource_sanitizer/resource_sanitizer.ts index 93c9222c51..7fa1bd8ad4 100644 --- a/tests/testdata/test/sanitizer/resource_sanitizer.ts +++ b/tests/specs/test/resource_sanitizer/resource_sanitizer.ts @@ -1,4 +1,4 @@ Deno.test("leak", function () { - Deno.openSync("run/001_hello.js"); + Deno.openSync("../../../testdata/run/001_hello.js"); Deno.stdin.close(); }); diff --git a/tests/specs/test/sanitizer_trace_ops_catch_error/__test__.jsonc b/tests/specs/test/sanitizer_trace_ops_catch_error/__test__.jsonc new file mode 100644 index 0000000000..a7ec0907c9 --- /dev/null +++ b/tests/specs/test/sanitizer_trace_ops_catch_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test -A --trace-leaks main.ts", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/specs/test/sanitizer_trace_ops_catch_error/main.out b/tests/specs/test/sanitizer_trace_ops_catch_error/main.out new file mode 100644 index 0000000000..c2c67605d6 --- /dev/null +++ b/tests/specs/test/sanitizer_trace_ops_catch_error/main.out @@ -0,0 +1,6 @@ +Check file:///[WILDCARD]main.ts +running 1 test from [WILDCARD]main.ts +handle thrown error in async function ... ok ([WILDCARD]) + +ok | 1 passed | 0 failed ([WILDCARD]) + diff --git a/tests/testdata/test/sanitizer/trace_ops_caught_error/main.ts b/tests/specs/test/sanitizer_trace_ops_catch_error/main.ts similarity index 100% rename from tests/testdata/test/sanitizer/trace_ops_caught_error/main.ts rename to tests/specs/test/sanitizer_trace_ops_catch_error/main.ts diff --git a/tests/specs/test/shuffle/__test__.jsonc b/tests/specs/test/shuffle/__test__.jsonc new file mode 100644 index 0000000000..975865e50e --- /dev/null +++ b/tests/specs/test/shuffle/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --shuffle shuffle", + "output": "[WILDCARD]", + "exitCode": 0 +} diff --git a/tests/testdata/test/shuffle/bar_test.ts b/tests/specs/test/shuffle/shuffle/bar_test.ts similarity index 100% rename from tests/testdata/test/shuffle/bar_test.ts rename to tests/specs/test/shuffle/shuffle/bar_test.ts diff --git a/tests/testdata/test/shuffle/baz_test.ts b/tests/specs/test/shuffle/shuffle/baz_test.ts similarity index 100% rename from tests/testdata/test/shuffle/baz_test.ts rename to tests/specs/test/shuffle/shuffle/baz_test.ts diff --git a/tests/testdata/test/shuffle/foo_test.ts b/tests/specs/test/shuffle/shuffle/foo_test.ts similarity index 100% rename from tests/testdata/test/shuffle/foo_test.ts rename to tests/specs/test/shuffle/shuffle/foo_test.ts diff --git a/tests/specs/test/shuffle_with_seed/__test__.jsonc b/tests/specs/test/shuffle_with_seed/__test__.jsonc new file mode 100644 index 0000000000..477f1dbcf8 --- /dev/null +++ b/tests/specs/test/shuffle_with_seed/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --shuffle=42 shuffle", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/testdata/test/shuffle.out b/tests/specs/test/shuffle_with_seed/main.out similarity index 71% rename from tests/testdata/test/shuffle.out rename to tests/specs/test/shuffle_with_seed/main.out index 9037ff518d..375b9bae2c 100644 --- a/tests/testdata/test/shuffle.out +++ b/tests/specs/test/shuffle_with_seed/main.out @@ -1,7 +1,7 @@ -Check [WILDCARD]/test/shuffle/bar_test.ts -Check [WILDCARD]/test/shuffle/baz_test.ts -Check [WILDCARD]/test/shuffle/foo_test.ts -running 10 tests from [WILDCARD]/test/shuffle/foo_test.ts +Check [WILDCARD]/test/shuffle_with_seed/shuffle/bar_test.ts +Check [WILDCARD]/test/shuffle_with_seed/shuffle/baz_test.ts +Check [WILDCARD]/test/shuffle_with_seed/shuffle/foo_test.ts +running 10 tests from [WILDCARD]shuffle/foo_test.ts test 3 ... ok ([WILDCARD]) test 2 ... ok ([WILDCARD]) test 7 ... ok ([WILDCARD]) @@ -12,7 +12,7 @@ test 9 ... ok ([WILDCARD]) test 4 ... ok ([WILDCARD]) test 6 ... ok ([WILDCARD]) test 1 ... ok ([WILDCARD]) -running 10 tests from [WILDCARD]/test/shuffle/baz_test.ts +running 10 tests from [WILDCARD]shuffle/baz_test.ts test 3 ... ok ([WILDCARD]) test 2 ... ok ([WILDCARD]) test 7 ... ok ([WILDCARD]) @@ -23,7 +23,7 @@ test 9 ... ok ([WILDCARD]) test 4 ... ok ([WILDCARD]) test 6 ... ok ([WILDCARD]) test 1 ... ok ([WILDCARD]) -running 10 tests from [WILDCARD]/test/shuffle/bar_test.ts +running 10 tests from [WILDCARD]shuffle/bar_test.ts test 3 ... ok ([WILDCARD]) test 2 ... ok ([WILDCARD]) test 7 ... ok ([WILDCARD]) diff --git a/tests/specs/test/shuffle_with_seed/shuffle/bar_test.ts b/tests/specs/test/shuffle_with_seed/shuffle/bar_test.ts new file mode 100644 index 0000000000..ca118dc0de --- /dev/null +++ b/tests/specs/test/shuffle_with_seed/shuffle/bar_test.ts @@ -0,0 +1,3 @@ +for (let i = 0; i < 10; i++) { + Deno.test(`test ${i}`, () => {}); +} diff --git a/tests/specs/test/shuffle_with_seed/shuffle/baz_test.ts b/tests/specs/test/shuffle_with_seed/shuffle/baz_test.ts new file mode 100644 index 0000000000..ca118dc0de --- /dev/null +++ b/tests/specs/test/shuffle_with_seed/shuffle/baz_test.ts @@ -0,0 +1,3 @@ +for (let i = 0; i < 10; i++) { + Deno.test(`test ${i}`, () => {}); +} diff --git a/tests/specs/test/shuffle_with_seed/shuffle/foo_test.ts b/tests/specs/test/shuffle_with_seed/shuffle/foo_test.ts new file mode 100644 index 0000000000..ca118dc0de --- /dev/null +++ b/tests/specs/test/shuffle_with_seed/shuffle/foo_test.ts @@ -0,0 +1,3 @@ +for (let i = 0; i < 10; i++) { + Deno.test(`test ${i}`, () => {}); +} diff --git a/tests/specs/test/steps_dot_failing_steps/__test__.jsonc b/tests/specs/test/steps_dot_failing_steps/__test__.jsonc new file mode 100644 index 0000000000..58ef6339a5 --- /dev/null +++ b/tests/specs/test/steps_dot_failing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=dot failing_steps.ts", + "exitCode": 1, + "output": "failing_steps.dot.out" +} diff --git a/tests/specs/test/steps_dot_failing_steps/failing_steps.dot.out b/tests/specs/test/steps_dot_failing_steps/failing_steps.dot.out new file mode 100644 index 0000000000..8222c13aeb --- /dev/null +++ b/tests/specs/test/steps_dot_failing_steps/failing_steps.dot.out @@ -0,0 +1,53 @@ +! +. +! +! +! +! +! +! +! + + ERRORS + +nested failure ... step 1 ... inner 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +error: Error: Failed. + throw new Error("Failed."); + ^ + at [WILDCARD]/failing_steps.ts:[WILDCARD] + +multiple test step failures ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +error: Error: Fail. + throw new Error("Fail."); + ^ + at [WILDCARD]/failing_steps.ts:[WILDCARD] + +multiple test step failures ... step 2 => [WILDCARD]failing_steps.ts:[WILDCARD] +error: Error: Fail. + await t.step("step 2", () => Promise.reject(new Error("Fail."))); + ^ + at [WILDCARD]/failing_steps.ts:[WILDCARD] + +failing step in failing test ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +error: Error: Fail. + throw new Error("Fail."); + ^ + at [WILDCARD]/failing_steps.ts:[WILDCARD] + +failing step in failing test => [WILDCARD]failing_steps.ts:[WILDCARD] +error: Error: Fail test. + throw new Error("Fail test."); + ^ + at [WILDCARD]/failing_steps.ts:[WILDCARD] + + FAILURES + +nested failure ... step 1 ... inner 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +multiple test step failures ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +multiple test step failures ... step 2 => [WILDCARD]failing_steps.ts:[WILDCARD] +failing step in failing test ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +failing step in failing test => [WILDCARD]failing_steps.ts:[WILDCARD] + +FAILED | 0 passed (1 step) | 3 failed (5 steps) ([WILDCARD]) + +error: Test failed diff --git a/tests/testdata/test/steps/failing_steps.ts b/tests/specs/test/steps_dot_failing_steps/failing_steps.ts similarity index 100% rename from tests/testdata/test/steps/failing_steps.ts rename to tests/specs/test/steps_dot_failing_steps/failing_steps.ts diff --git a/tests/specs/test/steps_dot_ignored_steps/__test__.jsonc b/tests/specs/test/steps_dot_ignored_steps/__test__.jsonc new file mode 100644 index 0000000000..672cc56f28 --- /dev/null +++ b/tests/specs/test/steps_dot_ignored_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=dot ignored_steps.ts", + "exitCode": 0, + "output": "ignored_steps.dot.out" +} diff --git a/tests/testdata/test/steps/ignored_steps.dot.out b/tests/specs/test/steps_dot_ignored_steps/ignored_steps.dot.out similarity index 100% rename from tests/testdata/test/steps/ignored_steps.dot.out rename to tests/specs/test/steps_dot_ignored_steps/ignored_steps.dot.out diff --git a/tests/testdata/test/steps/ignored_steps.ts b/tests/specs/test/steps_dot_ignored_steps/ignored_steps.ts similarity index 100% rename from tests/testdata/test/steps/ignored_steps.ts rename to tests/specs/test/steps_dot_ignored_steps/ignored_steps.ts diff --git a/tests/specs/test/steps_dot_passing_steps/__test__.jsonc b/tests/specs/test/steps_dot_passing_steps/__test__.jsonc new file mode 100644 index 0000000000..0ba87a6b28 --- /dev/null +++ b/tests/specs/test/steps_dot_passing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=dot passing_steps.ts", + "exitCode": 0, + "output": "passing_steps.dot.out" +} diff --git a/tests/testdata/test/steps/passing_steps.dot.out b/tests/specs/test/steps_dot_passing_steps/passing_steps.dot.out similarity index 100% rename from tests/testdata/test/steps/passing_steps.dot.out rename to tests/specs/test/steps_dot_passing_steps/passing_steps.dot.out diff --git a/tests/testdata/test/steps/passing_steps.ts b/tests/specs/test/steps_dot_passing_steps/passing_steps.ts similarity index 100% rename from tests/testdata/test/steps/passing_steps.ts rename to tests/specs/test/steps_dot_passing_steps/passing_steps.ts diff --git a/tests/specs/test/steps_failing_steps/__test__.jsonc b/tests/specs/test/steps_failing_steps/__test__.jsonc new file mode 100644 index 0000000000..f4194c50c8 --- /dev/null +++ b/tests/specs/test/steps_failing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test failing_steps.ts", + "exitCode": 1, + "output": "failing_steps.out" +} diff --git a/tests/testdata/test/steps/failing_steps.out b/tests/specs/test/steps_failing_steps/failing_steps.out similarity index 59% rename from tests/testdata/test/steps/failing_steps.out rename to tests/specs/test/steps_failing_steps/failing_steps.out index 4b717f5cc5..f66e089bcf 100644 --- a/tests/testdata/test/steps/failing_steps.out +++ b/tests/specs/test/steps_failing_steps/failing_steps.out @@ -1,5 +1,5 @@ [WILDCARD] -running 3 tests from ./test/steps/failing_steps.ts +running 3 tests from [WILDCARD]failing_steps.ts nested failure ... step 1 ... inner 1 ... FAILED ([WILDCARD]) @@ -16,31 +16,31 @@ failing step in failing test ... FAILED ([WILDCARD]) ERRORS -nested failure ... step 1 ... inner 1 => ./test/steps/failing_steps.ts:[WILDCARD] +nested failure ... step 1 ... inner 1 => [WILDCARD]failing_steps.ts:[WILDCARD] error: Error: Failed. throw new Error("Failed."); ^ at [WILDCARD]/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] +multiple test step failures ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] error: Error: Fail. throw new Error("Fail."); ^ at [WILDCARD]/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 2 => ./test/steps/failing_steps.ts:[WILDCARD] +multiple test step failures ... step 2 => [WILDCARD]failing_steps.ts:[WILDCARD] error: Error: Fail. await t.step("step 2", () => Promise.reject(new Error("Fail."))); ^ at [WILDCARD]/failing_steps.ts:[WILDCARD] -failing step in failing test ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] +failing step in failing test ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] error: Error: Fail. throw new Error("Fail."); ^ at [WILDCARD]/failing_steps.ts:[WILDCARD] -failing step in failing test => ./test/steps/failing_steps.ts:[WILDCARD] +failing step in failing test => [WILDCARD]failing_steps.ts:[WILDCARD] error: Error: Fail test. throw new Error("Fail test."); ^ @@ -48,11 +48,11 @@ error: Error: Fail test. FAILURES -nested failure ... step 1 ... inner 1 => ./test/steps/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 2 => ./test/steps/failing_steps.ts:[WILDCARD] -failing step in failing test ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -failing step in failing test => ./test/steps/failing_steps.ts:[WILDCARD] +nested failure ... step 1 ... inner 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +multiple test step failures ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +multiple test step failures ... step 2 => [WILDCARD]failing_steps.ts:[WILDCARD] +failing step in failing test ... step 1 => [WILDCARD]failing_steps.ts:[WILDCARD] +failing step in failing test => [WILDCARD]failing_steps.ts:[WILDCARD] FAILED | 0 passed (1 step) | 3 failed (5 steps) ([WILDCARD]) diff --git a/tests/specs/test/steps_failing_steps/failing_steps.ts b/tests/specs/test/steps_failing_steps/failing_steps.ts new file mode 100644 index 0000000000..efa18d54ef --- /dev/null +++ b/tests/specs/test/steps_failing_steps/failing_steps.ts @@ -0,0 +1,27 @@ +Deno.test("nested failure", async (t) => { + const success = await t.step("step 1", async (t) => { + let success = await t.step("inner 1", () => { + throw new Error("Failed."); + }); + if (success) throw new Error("Expected failure"); + + success = await t.step("inner 2", () => {}); + if (!success) throw new Error("Expected success"); + }); + + if (success) throw new Error("Expected failure"); +}); + +Deno.test("multiple test step failures", async (t) => { + await t.step("step 1", () => { + throw new Error("Fail."); + }); + await t.step("step 2", () => Promise.reject(new Error("Fail."))); +}); + +Deno.test("failing step in failing test", async (t) => { + await t.step("step 1", () => { + throw new Error("Fail."); + }); + throw new Error("Fail test."); +}); diff --git a/tests/specs/test/steps_ignored_steps/__test__.jsonc b/tests/specs/test/steps_ignored_steps/__test__.jsonc new file mode 100644 index 0000000000..d3f5a81cff --- /dev/null +++ b/tests/specs/test/steps_ignored_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test ignored_steps.ts", + "exitCode": 0, + "output": "ignored_steps.out" +} diff --git a/tests/testdata/test/steps/ignored_steps.out b/tests/specs/test/steps_ignored_steps/ignored_steps.out similarity index 79% rename from tests/testdata/test/steps/ignored_steps.out rename to tests/specs/test/steps_ignored_steps/ignored_steps.out index 2786e1e1a5..0960e62565 100644 --- a/tests/testdata/test/steps/ignored_steps.out +++ b/tests/specs/test/steps_ignored_steps/ignored_steps.out @@ -1,5 +1,5 @@ [WILDCARD] -running 1 test from ./test/steps/ignored_steps.ts +running 1 test from [WILDCARD]ignored_steps.ts ignored step ... step 1 ... ignored ([WILDCARD]) step 2 ... ok ([WILDCARD]) diff --git a/tests/specs/test/steps_ignored_steps/ignored_steps.ts b/tests/specs/test/steps_ignored_steps/ignored_steps.ts new file mode 100644 index 0000000000..102b481fba --- /dev/null +++ b/tests/specs/test/steps_ignored_steps/ignored_steps.ts @@ -0,0 +1,16 @@ +Deno.test("ignored step", async (t) => { + let result = await t.step({ + name: "step 1", + ignore: true, + fn: () => { + throw new Error("Fail."); + }, + }); + if (result !== false) throw new Error("Expected false."); + result = await t.step({ + name: "step 2", + ignore: false, + fn: () => {}, + }); + if (result !== true) throw new Error("Expected true."); +}); diff --git a/tests/specs/test/steps_invalid_usage/__test__.jsonc b/tests/specs/test/steps_invalid_usage/__test__.jsonc new file mode 100644 index 0000000000..763ec2a209 --- /dev/null +++ b/tests/specs/test/steps_invalid_usage/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test invalid_usage.ts", + "exitCode": 1, + "output": "invalid_usage.out" +} diff --git a/tests/testdata/test/steps/invalid_usage.out b/tests/specs/test/steps_invalid_usage/invalid_usage.out similarity index 67% rename from tests/testdata/test/steps/invalid_usage.out rename to tests/specs/test/steps_invalid_usage/invalid_usage.out index 4b82befaea..413a97cfde 100644 --- a/tests/testdata/test/steps/invalid_usage.out +++ b/tests/specs/test/steps_invalid_usage/invalid_usage.out @@ -1,5 +1,5 @@ [WILDCARD] -running 7 tests from ./test/steps/invalid_usage.ts +running 7 tests from [WILDCARD]invalid_usage.ts capturing ... some step ... ok ([WILDCARD]) capturing ... FAILED ([WILDCARD]) @@ -34,48 +34,48 @@ parallel steps where only inner tests have sanitizers ... FAILED (due to 1 faile ERRORS -capturing => ./test/steps/invalid_usage.ts:[WILDCARD] +capturing => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Error: Cannot run test step after parent scope has finished execution. Ensure any `.step(...)` calls are executed before their parent scope completes execution. await capturedContext.step("next step", () => {}); ^ at TestContext.step ([WILDCARD]) at [WILDCARD]/invalid_usage.ts:[WILDCARD] -top level missing await ... step => ./test/steps/invalid_usage.ts:[WILDCARD] +top level missing await ... step => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Didn't complete before parent. Await step with `await t.step(...)`. -inner missing await ... step ... inner => ./test/steps/invalid_usage.ts:[WILDCARD] +inner missing await ... step ... inner => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Didn't complete before parent. Await step with `await t.step(...)`. -parallel steps with sanitizers ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] +parallel steps with sanitizers ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Started test step while another test step with sanitizers was running: * parallel steps with sanitizers ... step 1 -parallel steps with sanitizers ... step 1 => ./test/steps/invalid_usage.ts:[WILDCARD] +parallel steps with sanitizers ... step 1 => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Didn't complete before parent. Await step with `await t.step(...)`. -parallel steps when first has sanitizer ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] +parallel steps when first has sanitizer ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Started test step while another test step with sanitizers was running: * parallel steps when first has sanitizer ... step 1 -parallel steps when second has sanitizer ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] +parallel steps when second has sanitizer ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Started test step with sanitizers while another test step was running: * parallel steps when second has sanitizer ... step 1 -parallel steps where only inner tests have sanitizers ... step 2 ... step inner => ./test/steps/invalid_usage.ts:[WILDCARD] +parallel steps where only inner tests have sanitizers ... step 2 ... step inner => [WILDCARD]invalid_usage.ts:[WILDCARD] error: Started test step with sanitizers while another test step was running: * parallel steps where only inner tests have sanitizers ... step 1 FAILURES -capturing => ./test/steps/invalid_usage.ts:1:6 -top level missing await ... step => ./test/steps/invalid_usage.ts:[WILDCARD] -inner missing await ... step ... inner => ./test/steps/invalid_usage.ts:[WILDCARD] -parallel steps with sanitizers ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] -parallel steps with sanitizers ... step 1 => ./test/steps/invalid_usage.ts:[WILDCARD] -parallel steps when first has sanitizer ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] -parallel steps when second has sanitizer ... step 2 => ./test/steps/invalid_usage.ts:[WILDCARD] -parallel steps where only inner tests have sanitizers ... step 2 ... step inner => ./test/steps/invalid_usage.ts:[WILDCARD] +capturing => [WILDCARD]invalid_usage.ts:1:6 +top level missing await ... step => [WILDCARD]invalid_usage.ts:[WILDCARD] +inner missing await ... step ... inner => [WILDCARD]invalid_usage.ts:[WILDCARD] +parallel steps with sanitizers ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] +parallel steps with sanitizers ... step 1 => [WILDCARD]invalid_usage.ts:[WILDCARD] +parallel steps when first has sanitizer ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] +parallel steps when second has sanitizer ... step 2 => [WILDCARD]invalid_usage.ts:[WILDCARD] +parallel steps where only inner tests have sanitizers ... step 2 ... step inner => [WILDCARD]invalid_usage.ts:[WILDCARD] FAILED | 0 passed (5 steps) | 7 failed (9 steps) ([WILDCARD]) diff --git a/tests/testdata/test/steps/invalid_usage.ts b/tests/specs/test/steps_invalid_usage/invalid_usage.ts similarity index 100% rename from tests/testdata/test/steps/invalid_usage.ts rename to tests/specs/test/steps_invalid_usage/invalid_usage.ts diff --git a/tests/specs/test/steps_output_within/__test__.jsonc b/tests/specs/test/steps_output_within/__test__.jsonc new file mode 100644 index 0000000000..2141b6b45a --- /dev/null +++ b/tests/specs/test/steps_output_within/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test output_within.ts", + "exitCode": 0, + "output": "output_within.out" +} diff --git a/tests/testdata/test/steps/output_within.out b/tests/specs/test/steps_output_within/output_within.out similarity index 90% rename from tests/testdata/test/steps/output_within.out rename to tests/specs/test/steps_output_within/output_within.out index d58722daa5..7c83b816f2 100644 --- a/tests/testdata/test/steps/output_within.out +++ b/tests/specs/test/steps_output_within/output_within.out @@ -1,5 +1,5 @@ [WILDCARD] -running 1 test from ./test/steps/output_within.ts +running 1 test from [WILDCARD]output_within.ts description ... ------- output ------- 1 diff --git a/tests/testdata/test/steps/output_within.ts b/tests/specs/test/steps_output_within/output_within.ts similarity index 100% rename from tests/testdata/test/steps/output_within.ts rename to tests/specs/test/steps_output_within/output_within.ts diff --git a/tests/specs/test/steps_passing_steps/__test__.jsonc b/tests/specs/test/steps_passing_steps/__test__.jsonc new file mode 100644 index 0000000000..daa8013921 --- /dev/null +++ b/tests/specs/test/steps_passing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test passing_steps.ts", + "exitCode": 0, + "output": "passing_steps.out" +} diff --git a/tests/testdata/test/steps/passing_steps.out b/tests/specs/test/steps_passing_steps/passing_steps.out similarity index 96% rename from tests/testdata/test/steps/passing_steps.out rename to tests/specs/test/steps_passing_steps/passing_steps.out index 0757a4ed36..c59be298ed 100644 --- a/tests/testdata/test/steps/passing_steps.out +++ b/tests/specs/test/steps_passing_steps/passing_steps.out @@ -1,5 +1,5 @@ [WILDCARD] -running 6 tests from ./test/steps/passing_steps.ts +running 6 tests from [WILDCARD]passing_steps.ts description ... step 1 ... inner 1 ... ok ([WILDCARD]s) diff --git a/tests/specs/test/steps_passing_steps/passing_steps.ts b/tests/specs/test/steps_passing_steps/passing_steps.ts new file mode 100644 index 0000000000..fd145954b5 --- /dev/null +++ b/tests/specs/test/steps_passing_steps/passing_steps.ts @@ -0,0 +1,127 @@ +Deno.test("description", async (t) => { + const success = await t.step("step 1", async (t) => { + await t.step("inner 1", () => {}); + await t.step("inner 2", () => {}); + }); + + if (!success) throw new Error("Expected the step to return true."); +}); + +Deno.test("description function as first arg", async (t) => { + const success = await t.step(async function step1(t) { + await t.step(function inner1() {}); + await t.step(function inner1() {}); + }); + + if (!success) throw new Error("Expected the step to return true."); +}); + +Deno.test("parallel steps without sanitizers", async (t) => { + // allowed + await Promise.all([ + t.step({ + name: "step 1", + fn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }, + sanitizeOps: false, + sanitizeResources: false, + sanitizeExit: false, + }), + t.step({ + name: "step 2", + fn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }, + sanitizeOps: false, + sanitizeResources: false, + sanitizeExit: false, + }), + ]); +}); + +Deno.test({ + name: "parallel steps without sanitizers due to parent", + fn: async (t) => { + // allowed because parent disabled the sanitizers + await Promise.all([ + t.step("step 1", async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }), + t.step("step 2", async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }), + ]); + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, +}); + +Deno.test({ + name: "steps with disabled sanitizers, then enabled, then parallel disabled", + fn: async (t) => { + await t.step("step 1", async (t) => { + await t.step({ + name: "step 1", + fn: async (t) => { + await Promise.all([ + t.step({ + name: "step 1", + fn: async (t) => { + await new Promise((resolve) => setTimeout(resolve, 10)); + await Promise.all([ + t.step("step 1", () => {}), + t.step("step 1", () => {}), + ]); + }, + sanitizeExit: false, + sanitizeResources: false, + sanitizeOps: false, + }), + t.step({ + name: "step 2", + fn: () => {}, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, + }), + ]); + }, + sanitizeResources: true, + sanitizeOps: true, + sanitizeExit: true, + }); + }); + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, +}); + +Deno.test("steps buffered then streaming reporting", async (t) => { + // no sanitizers so this will be buffered + await t.step({ + name: "step 1", + fn: async (t) => { + // also ensure the buffered tests display in order regardless of the second one finishing first + const step2Finished = Promise.withResolvers(); + const step1 = t.step("step 1 - 1", async () => { + await step2Finished.promise; + }); + const step2 = t.step("step 1 - 2", async (t) => { + await t.step("step 1 - 2 - 1", () => {}); + }); + await step2; + step2Finished.resolve(); + await step1; + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, + }); + + // now this will start streaming and we want to + // ensure it flushes the buffer of the last test + await t.step("step 2", async () => {}); +}); diff --git a/tests/specs/test/steps_tap_failing_steps/__test__.jsonc b/tests/specs/test/steps_tap_failing_steps/__test__.jsonc new file mode 100644 index 0000000000..f1e5b21082 --- /dev/null +++ b/tests/specs/test/steps_tap_failing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=tap failing_steps.ts", + "exitCode": 1, + "output": "failing_steps.tap.out" +} diff --git a/tests/testdata/test/steps/failing_steps.tap.out b/tests/specs/test/steps_tap_failing_steps/failing_steps.tap.out similarity index 68% rename from tests/testdata/test/steps/failing_steps.tap.out rename to tests/specs/test/steps_tap_failing_steps/failing_steps.tap.out index 11b289f08c..b47b9fed30 100644 --- a/tests/testdata/test/steps/failing_steps.tap.out +++ b/tests/specs/test/steps_tap_failing_steps/failing_steps.tap.out @@ -1,43 +1,43 @@ TAP version 14 -# ./test/steps/failing_steps.ts +# [WILDCARD]failing_steps.ts # Subtest: nested failure not ok 1 - inner 1 --- - {"message":"Error: Failed.\n throw new Error(\"Failed.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"Error: Failed.\n throw new Error(\"Failed.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... ok 2 - inner 2 not ok 3 - step 1 --- - {"message":"1 test step failed.","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"1 test step failed.","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... 1..3 not ok 1 - nested failure --- - {"message":"1 test step failed.","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"1 test step failed.","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... # Subtest: multiple test step failures not ok 1 - step 1 --- - {"message":"Error: Fail.\n throw new Error(\"Fail.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"Error: Fail.\n throw new Error(\"Fail.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... not ok 2 - step 2 --- - {"message":"Error: Fail.\n await t.step(\"step 2\", () => Promise.reject(new Error(\"Fail.\")));\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"Error: Fail.\n await t.step(\"step 2\", () => Promise.reject(new Error(\"Fail.\")));\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... 1..2 not ok 2 - multiple test step failures --- - {"message":"2 test steps failed.","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"2 test steps failed.","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... # Subtest: failing step in failing test not ok 1 - step 1 --- - {"message":"Error: Fail.\n throw new Error(\"Fail.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"Error: Fail.\n throw new Error(\"Fail.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]\n[WILDCARD]","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... 1..1 not ok 3 - failing step in failing test --- - {"message":"Error: Fail test.\n throw new Error(\"Fail test.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]","severity":"fail","at":{"file":"./test/steps/failing_steps.ts","line":[WILDCARD]}} + {"message":"Error: Fail test.\n throw new Error(\"Fail test.\");\n ^\n at [WILDCARD]/failing_steps.ts:[WILDCARD]","severity":"fail","at":{"file":"[WILDCARD]failing_steps.ts","line":[WILDCARD]}} ... 1..3 error: Test failed diff --git a/tests/specs/test/steps_tap_failing_steps/failing_steps.ts b/tests/specs/test/steps_tap_failing_steps/failing_steps.ts new file mode 100644 index 0000000000..efa18d54ef --- /dev/null +++ b/tests/specs/test/steps_tap_failing_steps/failing_steps.ts @@ -0,0 +1,27 @@ +Deno.test("nested failure", async (t) => { + const success = await t.step("step 1", async (t) => { + let success = await t.step("inner 1", () => { + throw new Error("Failed."); + }); + if (success) throw new Error("Expected failure"); + + success = await t.step("inner 2", () => {}); + if (!success) throw new Error("Expected success"); + }); + + if (success) throw new Error("Expected failure"); +}); + +Deno.test("multiple test step failures", async (t) => { + await t.step("step 1", () => { + throw new Error("Fail."); + }); + await t.step("step 2", () => Promise.reject(new Error("Fail."))); +}); + +Deno.test("failing step in failing test", async (t) => { + await t.step("step 1", () => { + throw new Error("Fail."); + }); + throw new Error("Fail test."); +}); diff --git a/tests/specs/test/steps_tap_ignored_steps/__test__.jsonc b/tests/specs/test/steps_tap_ignored_steps/__test__.jsonc new file mode 100644 index 0000000000..c28efe6917 --- /dev/null +++ b/tests/specs/test/steps_tap_ignored_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=tap ignored_steps.ts", + "exitCode": 0, + "output": "ignored_steps.tap.out" +} diff --git a/tests/testdata/test/steps/ignored_steps.tap.out b/tests/specs/test/steps_tap_ignored_steps/ignored_steps.tap.out similarity index 78% rename from tests/testdata/test/steps/ignored_steps.tap.out rename to tests/specs/test/steps_tap_ignored_steps/ignored_steps.tap.out index b2b2f50703..6389057729 100644 --- a/tests/testdata/test/steps/ignored_steps.tap.out +++ b/tests/specs/test/steps_tap_ignored_steps/ignored_steps.tap.out @@ -1,5 +1,5 @@ TAP version 14 -# ./test/steps/ignored_steps.ts +# [WILDCARD]ignored_steps.ts # Subtest: ignored step ok 1 - step 1 # SKIP ok 2 - step 2 diff --git a/tests/specs/test/steps_tap_ignored_steps/ignored_steps.ts b/tests/specs/test/steps_tap_ignored_steps/ignored_steps.ts new file mode 100644 index 0000000000..102b481fba --- /dev/null +++ b/tests/specs/test/steps_tap_ignored_steps/ignored_steps.ts @@ -0,0 +1,16 @@ +Deno.test("ignored step", async (t) => { + let result = await t.step({ + name: "step 1", + ignore: true, + fn: () => { + throw new Error("Fail."); + }, + }); + if (result !== false) throw new Error("Expected false."); + result = await t.step({ + name: "step 2", + ignore: false, + fn: () => {}, + }); + if (result !== true) throw new Error("Expected true."); +}); diff --git a/tests/specs/test/steps_tap_passing_steps/__test__.jsonc b/tests/specs/test/steps_tap_passing_steps/__test__.jsonc new file mode 100644 index 0000000000..b30d20d6b3 --- /dev/null +++ b/tests/specs/test/steps_tap_passing_steps/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --reporter=tap passing_steps.ts", + "exitCode": 0, + "output": "passing_steps.tap.out" +} diff --git a/tests/testdata/test/steps/passing_steps.tap.out b/tests/specs/test/steps_tap_passing_steps/passing_steps.tap.out similarity index 97% rename from tests/testdata/test/steps/passing_steps.tap.out rename to tests/specs/test/steps_tap_passing_steps/passing_steps.tap.out index 20a9fa312f..0797fb7dee 100644 --- a/tests/testdata/test/steps/passing_steps.tap.out +++ b/tests/specs/test/steps_tap_passing_steps/passing_steps.tap.out @@ -1,5 +1,5 @@ TAP version 14 -# ./test/steps/passing_steps.ts +# [WILDCARD]passing_steps.ts # Subtest: description ok 1 - inner 1 ok 2 - inner 2 diff --git a/tests/specs/test/steps_tap_passing_steps/passing_steps.ts b/tests/specs/test/steps_tap_passing_steps/passing_steps.ts new file mode 100644 index 0000000000..fd145954b5 --- /dev/null +++ b/tests/specs/test/steps_tap_passing_steps/passing_steps.ts @@ -0,0 +1,127 @@ +Deno.test("description", async (t) => { + const success = await t.step("step 1", async (t) => { + await t.step("inner 1", () => {}); + await t.step("inner 2", () => {}); + }); + + if (!success) throw new Error("Expected the step to return true."); +}); + +Deno.test("description function as first arg", async (t) => { + const success = await t.step(async function step1(t) { + await t.step(function inner1() {}); + await t.step(function inner1() {}); + }); + + if (!success) throw new Error("Expected the step to return true."); +}); + +Deno.test("parallel steps without sanitizers", async (t) => { + // allowed + await Promise.all([ + t.step({ + name: "step 1", + fn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }, + sanitizeOps: false, + sanitizeResources: false, + sanitizeExit: false, + }), + t.step({ + name: "step 2", + fn: async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }, + sanitizeOps: false, + sanitizeResources: false, + sanitizeExit: false, + }), + ]); +}); + +Deno.test({ + name: "parallel steps without sanitizers due to parent", + fn: async (t) => { + // allowed because parent disabled the sanitizers + await Promise.all([ + t.step("step 1", async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }), + t.step("step 2", async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }), + ]); + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, +}); + +Deno.test({ + name: "steps with disabled sanitizers, then enabled, then parallel disabled", + fn: async (t) => { + await t.step("step 1", async (t) => { + await t.step({ + name: "step 1", + fn: async (t) => { + await Promise.all([ + t.step({ + name: "step 1", + fn: async (t) => { + await new Promise((resolve) => setTimeout(resolve, 10)); + await Promise.all([ + t.step("step 1", () => {}), + t.step("step 1", () => {}), + ]); + }, + sanitizeExit: false, + sanitizeResources: false, + sanitizeOps: false, + }), + t.step({ + name: "step 2", + fn: () => {}, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, + }), + ]); + }, + sanitizeResources: true, + sanitizeOps: true, + sanitizeExit: true, + }); + }); + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, +}); + +Deno.test("steps buffered then streaming reporting", async (t) => { + // no sanitizers so this will be buffered + await t.step({ + name: "step 1", + fn: async (t) => { + // also ensure the buffered tests display in order regardless of the second one finishing first + const step2Finished = Promise.withResolvers(); + const step1 = t.step("step 1 - 1", async () => { + await step2Finished.promise; + }); + const step2 = t.step("step 1 - 2", async (t) => { + await t.step("step 1 - 2 - 1", () => {}); + }); + await step2; + step2Finished.resolve(); + await step1; + }, + sanitizeResources: false, + sanitizeOps: false, + sanitizeExit: false, + }); + + // now this will start streaming and we want to + // ensure it flushes the buffer of the last test + await t.step("step 2", async () => {}); +}); diff --git a/tests/specs/test/test_filtered_out_only/__test__.jsonc b/tests/specs/test/test_filtered_out_only/__test__.jsonc new file mode 100644 index 0000000000..b190d01661 --- /dev/null +++ b/tests/specs/test/test_filtered_out_only/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "test --quiet --filter foo main.ts", + "output": "main.out" +} diff --git a/tests/testdata/test/filtered_out_only.out b/tests/specs/test/test_filtered_out_only/main.out similarity index 62% rename from tests/testdata/test/filtered_out_only.out rename to tests/specs/test/test_filtered_out_only/main.out index 337893848a..488643c803 100644 --- a/tests/testdata/test/filtered_out_only.out +++ b/tests/specs/test/test_filtered_out_only/main.out @@ -1,4 +1,4 @@ -running 1 test from ./test/filtered_out_only.ts +running 1 test from ./main.ts foo ... ok ([WILDCARD]) ok | 1 passed | 0 failed | 1 filtered out ([WILDCARD]) diff --git a/tests/testdata/test/filtered_out_only.ts b/tests/specs/test/test_filtered_out_only/main.ts similarity index 100% rename from tests/testdata/test/filtered_out_only.ts rename to tests/specs/test/test_filtered_out_only/main.ts diff --git a/tests/specs/test/test_replace_timers/__test__.jsonc b/tests/specs/test/test_replace_timers/__test__.jsonc new file mode 100644 index 0000000000..bc91243185 --- /dev/null +++ b/tests/specs/test/test_replace_timers/__test__.jsonc @@ -0,0 +1,5 @@ +// Regression test for https://github.com/denoland/deno/issues/23041 +{ + "args": "test main.js", + "output": "main.out" +} diff --git a/tests/testdata/test/replace_timers.js b/tests/specs/test/test_replace_timers/main.js similarity index 100% rename from tests/testdata/test/replace_timers.js rename to tests/specs/test/test_replace_timers/main.js diff --git a/tests/testdata/test/replace_timers.js.out b/tests/specs/test/test_replace_timers/main.out similarity index 70% rename from tests/testdata/test/replace_timers.js.out rename to tests/specs/test/test_replace_timers/main.out index 81beb5ebe0..cfac499437 100644 --- a/tests/testdata/test/replace_timers.js.out +++ b/tests/specs/test/test_replace_timers/main.out @@ -1,4 +1,4 @@ -running 1 test from ./test/replace_timers.js +running 1 test from [WILDCARD]/main.js foo ... bar ... ok ([WILDCARD]) foo ... ok ([WILDCARD]) diff --git a/tests/specs/test/test_with_config/__test__.jsonc b/tests/specs/test/test_with_config/__test__.jsonc new file mode 100644 index 0000000000..8bd1e2a9e9 --- /dev/null +++ b/tests/specs/test/test_with_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config collect/deno.jsonc collect", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/test_with_config/collect/deno.jsonc b/tests/specs/test/test_with_config/collect/deno.jsonc new file mode 100644 index 0000000000..e14ce86da0 --- /dev/null +++ b/tests/specs/test/test_with_config/collect/deno.jsonc @@ -0,0 +1,5 @@ +{ + "test": { + "exclude": ["./ignore"] + } +} diff --git a/tests/specs/test/test_with_config/collect/deno.malformed.jsonc b/tests/specs/test/test_with_config/collect/deno.malformed.jsonc new file mode 100644 index 0000000000..f2d8cbc652 --- /dev/null +++ b/tests/specs/test/test_with_config/collect/deno.malformed.jsonc @@ -0,0 +1,5 @@ +{ + "test": { + "dont_know_this_field": {} + } +} diff --git a/tests/specs/test/test_with_config/collect/deno2.jsonc b/tests/specs/test/test_with_config/collect/deno2.jsonc new file mode 100644 index 0000000000..b7af09d1c0 --- /dev/null +++ b/tests/specs/test/test_with_config/collect/deno2.jsonc @@ -0,0 +1,6 @@ +{ + "test": { + "include": ["./include/"], + "exclude": ["./ignore", "./include/2_test.ts"] + } +} diff --git a/tests/specs/test/test_with_config/collect/ignore/test.ts b/tests/specs/test/test_with_config/collect/ignore/test.ts new file mode 100644 index 0000000000..16fb63ba7a --- /dev/null +++ b/tests/specs/test/test_with_config/collect/ignore/test.ts @@ -0,0 +1 @@ +throw new Error("this module should be ignored"); diff --git a/tests/specs/test/test_with_config/collect/include.ts b/tests/specs/test/test_with_config/collect/include.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config/collect/include/2_test.ts b/tests/specs/test/test_with_config/collect/include/2_test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config/collect/include/test.ts b/tests/specs/test/test_with_config/collect/include/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config/collect/test.ts b/tests/specs/test/test_with_config/collect/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config/main.out b/tests/specs/test/test_with_config/main.out new file mode 100644 index 0000000000..c140f2f7c4 --- /dev/null +++ b/tests/specs/test/test_with_config/main.out @@ -0,0 +1,9 @@ +Check [WILDCARD]collect/include/2_test.ts +Check [WILDCARD]collect/include/test.ts +Check [WILDCARD]collect/test.ts +running 0 tests from [WILDCARD]collect/include/2_test.ts +running 0 tests from [WILDCARD]collect/include/test.ts +running 0 tests from [WILDCARD]collect/test.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/test_with_config2/__test__.jsonc b/tests/specs/test/test_with_config2/__test__.jsonc new file mode 100644 index 0000000000..51d0a8c6b3 --- /dev/null +++ b/tests/specs/test/test_with_config2/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config collect/deno2.jsonc collect", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/test_with_config2/collect/deno.jsonc b/tests/specs/test/test_with_config2/collect/deno.jsonc new file mode 100644 index 0000000000..e14ce86da0 --- /dev/null +++ b/tests/specs/test/test_with_config2/collect/deno.jsonc @@ -0,0 +1,5 @@ +{ + "test": { + "exclude": ["./ignore"] + } +} diff --git a/tests/specs/test/test_with_config2/collect/deno.malformed.jsonc b/tests/specs/test/test_with_config2/collect/deno.malformed.jsonc new file mode 100644 index 0000000000..f2d8cbc652 --- /dev/null +++ b/tests/specs/test/test_with_config2/collect/deno.malformed.jsonc @@ -0,0 +1,5 @@ +{ + "test": { + "dont_know_this_field": {} + } +} diff --git a/tests/specs/test/test_with_config2/collect/deno2.jsonc b/tests/specs/test/test_with_config2/collect/deno2.jsonc new file mode 100644 index 0000000000..b7af09d1c0 --- /dev/null +++ b/tests/specs/test/test_with_config2/collect/deno2.jsonc @@ -0,0 +1,6 @@ +{ + "test": { + "include": ["./include/"], + "exclude": ["./ignore", "./include/2_test.ts"] + } +} diff --git a/tests/specs/test/test_with_config2/collect/ignore/test.ts b/tests/specs/test/test_with_config2/collect/ignore/test.ts new file mode 100644 index 0000000000..16fb63ba7a --- /dev/null +++ b/tests/specs/test/test_with_config2/collect/ignore/test.ts @@ -0,0 +1 @@ +throw new Error("this module should be ignored"); diff --git a/tests/specs/test/test_with_config2/collect/include.ts b/tests/specs/test/test_with_config2/collect/include.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config2/collect/include/2_test.ts b/tests/specs/test/test_with_config2/collect/include/2_test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config2/collect/include/test.ts b/tests/specs/test/test_with_config2/collect/include/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config2/collect/test.ts b/tests/specs/test/test_with_config2/collect/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/test/test_with_config2/main.out b/tests/specs/test/test_with_config2/main.out new file mode 100644 index 0000000000..3354c16cc5 --- /dev/null +++ b/tests/specs/test/test_with_config2/main.out @@ -0,0 +1,7 @@ +Check [WILDCARD]/collect/include/test.ts +Check [WILDCARD]/collect/test.ts +running 0 tests from [WILDCARD]/collect/include/test.ts +running 0 tests from [WILDCARD]/collect/test.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/test_with_custom_jsx/__test__.jsonc b/tests/specs/test/test_with_custom_jsx/__test__.jsonc new file mode 100644 index 0000000000..e516467eea --- /dev/null +++ b/tests/specs/test/test_with_custom_jsx/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet --allow-read main.ts --config=deno_custom_jsx.json", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/testdata/test/deno_custom_jsx.json b/tests/specs/test/test_with_custom_jsx/deno_custom_jsx.json similarity index 100% rename from tests/testdata/test/deno_custom_jsx.json rename to tests/specs/test/test_with_custom_jsx/deno_custom_jsx.json diff --git a/tests/testdata/test/hello_world.out b/tests/specs/test/test_with_custom_jsx/main.out similarity index 64% rename from tests/testdata/test/hello_world.out rename to tests/specs/test/test_with_custom_jsx/main.out index aee8a64d48..cfeb14fd5c 100644 --- a/tests/testdata/test/hello_world.out +++ b/tests/specs/test/test_with_custom_jsx/main.out @@ -1,4 +1,4 @@ -running 1 test from ./test/hello_world.ts +running 1 test from ./main.ts hello world test ... ok ([WILDCARD]) ok | 1 passed | 0 failed ([WILDCARD]) diff --git a/tests/testdata/test/hello_world.ts b/tests/specs/test/test_with_custom_jsx/main.ts similarity index 100% rename from tests/testdata/test/hello_world.ts rename to tests/specs/test/test_with_custom_jsx/main.ts diff --git a/tests/specs/test/test_with_glob_config/__test__.jsonc b/tests/specs/test/test_with_glob_config/__test__.jsonc new file mode 100644 index 0000000000..9e2deabf95 --- /dev/null +++ b/tests/specs/test/test_with_glob_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config deno.glob.json", + "output": "main.out", + "exitCode": 0 +} diff --git a/tests/specs/test/test_with_glob_config/deno.glob.json b/tests/specs/test/test_with_glob_config/deno.glob.json new file mode 100644 index 0000000000..9deb4d2f22 --- /dev/null +++ b/tests/specs/test/test_with_glob_config/deno.glob.json @@ -0,0 +1,11 @@ +{ + "test": { + "include": [ + "glob/data/test1.?s", + "glob/nested/foo/*.ts", + "glob/nested/fizz/*.ts", + "glob/pages/[id].ts" + ], + "exclude": ["glob/nested/**/*bazz.ts"] + } +} diff --git a/tests/specs/test/test_with_glob_config/glob/data/tes.ts b/tests/specs/test/test_with_glob_config/glob/data/tes.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/data/tes.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/data/test1.js b/tests/specs/test/test_with_glob_config/glob/data/test1.js new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/data/test1.js @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/data/test1.ts b/tests/specs/test/test_with_glob_config/glob/data/test1.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/data/test1.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/data/test12.ts b/tests/specs/test/test_with_glob_config/glob/data/test12.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/data/test12.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/fizz/bar.ts b/tests/specs/test/test_with_glob_config/glob/nested/fizz/bar.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/fizz/bar.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/fizz/bazz.ts b/tests/specs/test/test_with_glob_config/glob/nested/fizz/bazz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/fizz/bazz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/fizz/fizz.ts b/tests/specs/test/test_with_glob_config/glob/nested/fizz/fizz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/fizz/fizz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/fizz/foo.ts b/tests/specs/test/test_with_glob_config/glob/nested/fizz/foo.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/fizz/foo.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/foo/bar.ts b/tests/specs/test/test_with_glob_config/glob/nested/foo/bar.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/foo/bar.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/foo/bazz.ts b/tests/specs/test/test_with_glob_config/glob/nested/foo/bazz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/foo/bazz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/foo/fizz.ts b/tests/specs/test/test_with_glob_config/glob/nested/foo/fizz.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/foo/fizz.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/nested/foo/foo.ts b/tests/specs/test/test_with_glob_config/glob/nested/foo/foo.ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/nested/foo/foo.ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/glob/pages/[id].ts b/tests/specs/test/test_with_glob_config/glob/pages/[id].ts new file mode 100644 index 0000000000..6940729e9e --- /dev/null +++ b/tests/specs/test/test_with_glob_config/glob/pages/[id].ts @@ -0,0 +1,2 @@ +function foo() { +} diff --git a/tests/specs/test/test_with_glob_config/main.out b/tests/specs/test/test_with_glob_config/main.out new file mode 100644 index 0000000000..fbff4d934c --- /dev/null +++ b/tests/specs/test/test_with_glob_config/main.out @@ -0,0 +1,21 @@ +Check [WILDCARD]/glob/pages/[id].ts +Check [WILDCARD]/glob/data/test1.js +Check [WILDCARD]/glob/data/test1.ts +Check [WILDCARD]/glob/nested/fizz/bar.ts +Check [WILDCARD]/glob/nested/fizz/fizz.ts +Check [WILDCARD]/glob/nested/fizz/foo.ts +Check [WILDCARD]/glob/nested/foo/bar.ts +Check [WILDCARD]/glob/nested/foo/fizz.ts +Check [WILDCARD]/glob/nested/foo/foo.ts +running 0 tests from ./glob/pages/[id].ts +running 0 tests from ./glob/data/test1.js +running 0 tests from ./glob/data/test1.ts +running 0 tests from ./glob/nested/fizz/bar.ts +running 0 tests from ./glob/nested/fizz/fizz.ts +running 0 tests from ./glob/nested/fizz/foo.ts +running 0 tests from ./glob/nested/foo/bar.ts +running 0 tests from ./glob/nested/foo/fizz.ts +running 0 tests from ./glob/nested/foo/foo.ts + +ok | 0 passed | 0 failed ([WILDCARD]) + diff --git a/tests/specs/test/test_with_malformed_config/__test__.jsonc b/tests/specs/test/test_with_malformed_config/__test__.jsonc new file mode 100644 index 0000000000..56c30bce6a --- /dev/null +++ b/tests/specs/test/test_with_malformed_config/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --config deno.malformed.jsonc", + "exitCode": 1, + "output": "main.out" +} diff --git a/tests/specs/test/test_with_malformed_config/deno.malformed.jsonc b/tests/specs/test/test_with_malformed_config/deno.malformed.jsonc new file mode 100644 index 0000000000..f2d8cbc652 --- /dev/null +++ b/tests/specs/test/test_with_malformed_config/deno.malformed.jsonc @@ -0,0 +1,5 @@ +{ + "test": { + "dont_know_this_field": {} + } +} diff --git a/tests/testdata/test/collect_with_malformed_config.out b/tests/specs/test/test_with_malformed_config/main.out similarity index 100% rename from tests/testdata/test/collect_with_malformed_config.out rename to tests/specs/test/test_with_malformed_config/main.out diff --git a/tests/specs/test/text/__test__.jsonc b/tests/specs/test/text/__test__.jsonc new file mode 100644 index 0000000000..35ec2225b4 --- /dev/null +++ b/tests/specs/test/text/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --doc --allow-all main.md", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/testdata/test/text.md b/tests/specs/test/text/main.md similarity index 100% rename from tests/testdata/test/text.md rename to tests/specs/test/text/main.md diff --git a/tests/testdata/test/text.out b/tests/specs/test/text/main.out similarity index 100% rename from tests/testdata/test/text.out rename to tests/specs/test/text/main.out diff --git a/tests/specs/test/type_check_with_doc/main.out b/tests/specs/test/type_check_with_doc/main.out index 931a6a5f3e..56b7ba9e8b 100644 --- a/tests/specs/test/type_check_with_doc/main.out +++ b/tests/specs/test/type_check_with_doc/main.out @@ -6,8 +6,8 @@ const a: string = 1; at file://[WILDCARD]/main.ts:8:7 TS2322 [ERROR]: Type 'string' is not assignable to type 'number'. -const b: number = "1"; - ^ - at file://[WILDCARD]/main.ts$2-5.ts:1:7 + const b: number = "1"; + ^ + at file://[WILDCARD]/main.ts$2-5.ts:2:11 Found 2 errors. diff --git a/tests/specs/test/uncaught_errors/__test__.jsonc b/tests/specs/test/uncaught_errors/__test__.jsonc new file mode 100644 index 0000000000..746ddfc26d --- /dev/null +++ b/tests/specs/test/uncaught_errors/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test --quiet uncaught_errors_1.ts uncaught_errors_2.ts uncaught_errors_3.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/uncaught_errors.out b/tests/specs/test/uncaught_errors/main.out similarity index 53% rename from tests/testdata/test/uncaught_errors.out rename to tests/specs/test/uncaught_errors/main.out index a52f95d574..23d59e61c3 100644 --- a/tests/testdata/test/uncaught_errors.out +++ b/tests/specs/test/uncaught_errors/main.out @@ -1,58 +1,58 @@ -running 3 tests from ./test/uncaught_errors_1.ts +running 3 tests from [WILDCARD]/uncaught_errors_1.ts foo 1 ... FAILED ([WILDCARD]) foo 2 ... ok ([WILDCARD]) foo 3 ... -Uncaught error from ./test/uncaught_errors_1.ts FAILED +Uncaught error from [WILDCARD]/uncaught_errors_1.ts FAILED foo 3 ... cancelled (0ms) -running 3 tests from ./test/uncaught_errors_2.ts +running 3 tests from [WILDCARD]/uncaught_errors_2.ts bar 1 ... ok ([WILDCARD]) bar 2 ... FAILED ([WILDCARD]) bar 3 ... FAILED ([WILDCARD]) -Uncaught error from ./test/uncaught_errors_3.ts FAILED +Uncaught error from [WILDCARD]/uncaught_errors_3.ts FAILED ERRORS -foo 1 => ./test/uncaught_errors_1.ts:1:6 +foo 1 => [WILDCARD]/uncaught_errors_1.ts:1:6 error: Error: foo 1 message throw new Error("foo 1 message"); ^ - at [WILDCARD]/test/uncaught_errors_1.ts:2:9 + at [WILDCARD]/uncaught_errors_1.ts:2:9 -./test/uncaught_errors_1.ts (uncaught error) +[WILDCARD]/uncaught_errors_1.ts (uncaught error) error: (in promise) Error: foo 3 message Promise.reject(new Error("foo 3 message")); ^ - at [WILDCARD]/test/uncaught_errors_1.ts:8:18 + at [WILDCARD]/uncaught_errors_1.ts:8:18 This error was not caught from a test and caused the test runner to fail on the referenced module. It most likely originated from a dangling promise, event/timeout handler or top-level code. -bar 2 => ./test/uncaught_errors_2.ts:3:6 +bar 2 => [WILDCARD]/uncaught_errors_2.ts:3:6 error: Error: bar 2 throw new Error("bar 2"); ^ - at [WILDCARD]/test/uncaught_errors_2.ts:4:9 + at [WILDCARD]/uncaught_errors_2.ts:4:9 -bar 3 => ./test/uncaught_errors_2.ts:6:6 +bar 3 => [WILDCARD]/uncaught_errors_2.ts:6:6 error: Error: bar 3 message throw new Error("bar 3 message"); ^ - at [WILDCARD]/test/uncaught_errors_2.ts:7:9 + at [WILDCARD]/uncaught_errors_2.ts:7:9 -./test/uncaught_errors_3.ts (uncaught error) +[WILDCARD]/uncaught_errors_3.ts (uncaught error) error: (in promise) Error: baz throw new Error("baz"); ^ - at [WILDCARD]/test/uncaught_errors_3.ts:1:7 + at [WILDCARD]/uncaught_errors_3.ts:1:7 This error was not caught from a test and caused the test runner to fail on the referenced module. It most likely originated from a dangling promise, event/timeout handler or top-level code. FAILURES -foo 1 => ./test/uncaught_errors_1.ts:1:6 -./test/uncaught_errors_1.ts (uncaught error) -bar 2 => ./test/uncaught_errors_2.ts:3:6 -bar 3 => ./test/uncaught_errors_2.ts:6:6 -./test/uncaught_errors_3.ts (uncaught error) +foo 1 => [WILDCARD]/uncaught_errors_1.ts:1:6 +[WILDCARD]/uncaught_errors_1.ts (uncaught error) +bar 2 => [WILDCARD]/uncaught_errors_2.ts:3:6 +bar 3 => [WILDCARD]/uncaught_errors_2.ts:6:6 +[WILDCARD]/uncaught_errors_3.ts (uncaught error) FAILED | 2 passed | 6 failed ([WILDCARD]) diff --git a/tests/testdata/test/uncaught_errors_1.ts b/tests/specs/test/uncaught_errors/uncaught_errors_1.ts similarity index 100% rename from tests/testdata/test/uncaught_errors_1.ts rename to tests/specs/test/uncaught_errors/uncaught_errors_1.ts diff --git a/tests/testdata/test/uncaught_errors_2.ts b/tests/specs/test/uncaught_errors/uncaught_errors_2.ts similarity index 100% rename from tests/testdata/test/uncaught_errors_2.ts rename to tests/specs/test/uncaught_errors/uncaught_errors_2.ts diff --git a/tests/testdata/test/uncaught_errors_3.ts b/tests/specs/test/uncaught_errors/uncaught_errors_3.ts similarity index 100% rename from tests/testdata/test/uncaught_errors_3.ts rename to tests/specs/test/uncaught_errors/uncaught_errors_3.ts diff --git a/tests/specs/test/unhandled_rejection/__test__.jsonc b/tests/specs/test/unhandled_rejection/__test__.jsonc new file mode 100644 index 0000000000..d8887f7538 --- /dev/null +++ b/tests/specs/test/unhandled_rejection/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/unhandled_rejection.out b/tests/specs/test/unhandled_rejection/main.out similarity index 56% rename from tests/testdata/test/unhandled_rejection.out rename to tests/specs/test/unhandled_rejection/main.out index bc83879296..e708ae20c3 100644 --- a/tests/testdata/test/unhandled_rejection.out +++ b/tests/specs/test/unhandled_rejection/main.out @@ -1,21 +1,21 @@ -Check [WILDCARD]/test/unhandled_rejection.ts -Uncaught error from ./test/unhandled_rejection.ts FAILED +Check [WILDCARD]/main.ts +Uncaught error from ./main.ts FAILED ERRORS -./test/unhandled_rejection.ts (uncaught error) +./main.ts (uncaught error) error: (in promise) Error: rejection reject(new Error("rejection")); ^ - at [WILDCARD]/test/unhandled_rejection.ts:2:10 + at [WILDCARD]/main.ts:2:10 at new Promise () - at [WILDCARD]/test/unhandled_rejection.ts:1:1 + at [WILDCARD]/main.ts:1:1 This error was not caught from a test and caused the test runner to fail on the referenced module. It most likely originated from a dangling promise, event/timeout handler or top-level code. FAILURES -./test/unhandled_rejection.ts (uncaught error) +./main.ts (uncaught error) FAILED | 0 passed | 1 failed ([WILDCARD]) diff --git a/tests/testdata/test/unhandled_rejection.ts b/tests/specs/test/unhandled_rejection/main.ts similarity index 100% rename from tests/testdata/test/unhandled_rejection.ts rename to tests/specs/test/unhandled_rejection/main.ts diff --git a/tests/specs/test/unresolved_promise/__test__.jsonc b/tests/specs/test/unresolved_promise/__test__.jsonc new file mode 100644 index 0000000000..d8887f7538 --- /dev/null +++ b/tests/specs/test/unresolved_promise/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "test main.ts", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/testdata/test/unresolved_promise.out b/tests/specs/test/unresolved_promise/main.out similarity index 74% rename from tests/testdata/test/unresolved_promise.out rename to tests/specs/test/unresolved_promise/main.out index 88535e1714..0195400b6b 100644 --- a/tests/testdata/test/unresolved_promise.out +++ b/tests/specs/test/unresolved_promise/main.out @@ -1,9 +1,9 @@ [WILDCARD] -./test/unresolved_promise.ts (uncaught error) +./main.ts (uncaught error) error: Top-level await promise never resolved await new Promise((_resolve, _reject) => {}); ^ - at ([WILDCARD]/test/unresolved_promise.ts:1:1) + at ([WILDCARD]/main.ts:1:1) This error was not caught from a test and caused the test runner to fail on the referenced module. It most likely originated from a dangling promise, event/timeout handler or top-level code. [WILDCARD] diff --git a/tests/testdata/test/unresolved_promise.ts b/tests/specs/test/unresolved_promise/main.ts similarity index 100% rename from tests/testdata/test/unresolved_promise.ts rename to tests/specs/test/unresolved_promise/main.ts diff --git a/tests/specs/upgrade/canary/__test__.jsonc b/tests/specs/upgrade/canary/__test__.jsonc new file mode 100644 index 0000000000..bf97313d92 --- /dev/null +++ b/tests/specs/upgrade/canary/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --canary --force", + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/canary/upgrade.out b/tests/specs/upgrade/canary/upgrade.out new file mode 100644 index 0000000000..07daf03d50 --- /dev/null +++ b/tests/specs/upgrade/canary/upgrade.out @@ -0,0 +1,10 @@ +Current Deno version: [WILDCARD] +Looking up canary version + +Found latest canary version [WILDCARD] + +Downloading https://dl.deno.land/canary/[WILDCARD]/deno-[WILDCARD].zip +Deno is upgrading to version [WILDCARD] + +Upgraded successfully to Deno [WILDCARD] (canary) + diff --git a/tests/specs/upgrade/canary/version.out b/tests/specs/upgrade/canary/version.out new file mode 100644 index 0000000000..0cfbb01c46 --- /dev/null +++ b/tests/specs/upgrade/canary/version.out @@ -0,0 +1,3 @@ +deno [WILDCARD]+[WILDCARD] (canary, release, [WILDCARD]) +v8 [WILDCARD] +typescript [WILDCARD] diff --git a/tests/specs/upgrade/invalid_version/__test__.jsonc b/tests/specs/upgrade/invalid_version/__test__.jsonc new file mode 100644 index 0000000000..1fa81c1075 --- /dev/null +++ b/tests/specs/upgrade/invalid_version/__test__.jsonc @@ -0,0 +1,19 @@ +{ + "tests": { + "canary": { + "args": "upgrade --canary asdfasdf", + "output": "canary.out", + "exitCode": 1 + }, + "version": { + "args": "upgrade --version asdfasdf", + "output": "version.out", + "exitCode": 1 + }, + "shorthand": { + "args": "upgrade asdfasdf", + "output": "shorthand.out", + "exitCode": 1 + } + } +} diff --git a/tests/specs/upgrade/invalid_version/canary.out b/tests/specs/upgrade/invalid_version/canary.out new file mode 100644 index 0000000000..60a7b9f092 --- /dev/null +++ b/tests/specs/upgrade/invalid_version/canary.out @@ -0,0 +1,17 @@ +error: Invalid commit hash passed (asdfasdf) + +Pass a semver, or a full 40 character git commit hash, or a release channel name. + +Usage: +Latest + deno upgrade + +Specific version + deno upgrade 1.45.0 + deno upgrade 1.46.0-rc.1 + deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 + +Channel + deno upgrade stable + deno upgrade rc + deno upgrade canary diff --git a/tests/specs/upgrade/invalid_version/shorthand.out b/tests/specs/upgrade/invalid_version/shorthand.out new file mode 100644 index 0000000000..134284cab9 --- /dev/null +++ b/tests/specs/upgrade/invalid_version/shorthand.out @@ -0,0 +1,17 @@ +error: Invalid version passed (asdfasdf) + +Pass a semver, or a full 40 character git commit hash, or a release channel name. + +Usage: +Latest + deno upgrade + +Specific version + deno upgrade 1.45.0 + deno upgrade 1.46.0-rc.1 + deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 + +Channel + deno upgrade stable + deno upgrade rc + deno upgrade canary diff --git a/tests/specs/upgrade/invalid_version/version.out b/tests/specs/upgrade/invalid_version/version.out new file mode 100644 index 0000000000..134284cab9 --- /dev/null +++ b/tests/specs/upgrade/invalid_version/version.out @@ -0,0 +1,17 @@ +error: Invalid version passed (asdfasdf) + +Pass a semver, or a full 40 character git commit hash, or a release channel name. + +Usage: +Latest + deno upgrade + +Specific version + deno upgrade 1.45.0 + deno upgrade 1.46.0-rc.1 + deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 + +Channel + deno upgrade stable + deno upgrade rc + deno upgrade canary diff --git a/tests/specs/upgrade/out/__test__.jsonc b/tests/specs/upgrade/out/__test__.jsonc new file mode 100644 index 0000000000..1365ec5630 --- /dev/null +++ b/tests/specs/upgrade/out/__test__.jsonc @@ -0,0 +1,29 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --force --version 1.43.2 --output ./deno_copy2", + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": ["eval", "if (Deno.version.deno === '1.43.2') { Deno.exit(1); }"], + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy2", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/out/upgrade.out b/tests/specs/upgrade/out/upgrade.out new file mode 100644 index 0000000000..a2b47d0ec8 --- /dev/null +++ b/tests/specs/upgrade/out/upgrade.out @@ -0,0 +1,14 @@ +Current Deno version: [WILDCARD] +Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip +Deno is upgrading to version 1.43.2 + +Upgraded successfully to Deno v1.43.2 (stable) + +Release notes: + + https://github.com/denoland/deno/releases/tag/v1.43.2 + +Blog post: + + https://deno.com/blog/v1.43 + diff --git a/tests/specs/upgrade/out/version.out b/tests/specs/upgrade/out/version.out new file mode 100644 index 0000000000..9ddecf67c2 --- /dev/null +++ b/tests/specs/upgrade/out/version.out @@ -0,0 +1,3 @@ +deno 1.43.2 (release, [WILDCARD]) +v8 12.4.254.12 +typescript 5.4.5 diff --git a/tests/specs/upgrade/space_in_tmp/__test__.jsonc b/tests/specs/upgrade/space_in_tmp/__test__.jsonc new file mode 100644 index 0000000000..f54c0bf833 --- /dev/null +++ b/tests/specs/upgrade/space_in_tmp/__test__.jsonc @@ -0,0 +1,30 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "mkdir", + "args": ["space in cwd"], + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --force --version 1.43.2", + "envs": { "TMP": "./space in cwd" }, + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/space_in_tmp/upgrade.out b/tests/specs/upgrade/space_in_tmp/upgrade.out new file mode 100644 index 0000000000..a2b47d0ec8 --- /dev/null +++ b/tests/specs/upgrade/space_in_tmp/upgrade.out @@ -0,0 +1,14 @@ +Current Deno version: [WILDCARD] +Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip +Deno is upgrading to version 1.43.2 + +Upgraded successfully to Deno v1.43.2 (stable) + +Release notes: + + https://github.com/denoland/deno/releases/tag/v1.43.2 + +Blog post: + + https://deno.com/blog/v1.43 + diff --git a/tests/specs/upgrade/space_in_tmp/version.out b/tests/specs/upgrade/space_in_tmp/version.out new file mode 100644 index 0000000000..9ddecf67c2 --- /dev/null +++ b/tests/specs/upgrade/space_in_tmp/version.out @@ -0,0 +1,3 @@ +deno 1.43.2 (release, [WILDCARD]) +v8 12.4.254.12 +typescript 5.4.5 diff --git a/tests/specs/upgrade/specific_canary/__test__.jsonc b/tests/specs/upgrade/specific_canary/__test__.jsonc new file mode 100644 index 0000000000..ea86ee117d --- /dev/null +++ b/tests/specs/upgrade/specific_canary/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --force --canary --version aaf2bf4bfbf90bed0b6e9812f337f057d1d24f93", + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/specific_canary/upgrade.out b/tests/specs/upgrade/specific_canary/upgrade.out new file mode 100644 index 0000000000..d73116777d --- /dev/null +++ b/tests/specs/upgrade/specific_canary/upgrade.out @@ -0,0 +1,6 @@ +Current Deno version: [WILDCARD] +Downloading https://dl.deno.land/canary/aaf2bf4bfbf90bed0b6e9812f337f057d1d24f93/deno-[WILDCARD].zip +Deno is upgrading to version aaf2bf4bfbf90bed0b6e9812f337f057d1d24f93 + +Upgraded successfully to Deno aaf2bf4bfbf90bed0b6e9812f337f057d1d24f93 (canary) + diff --git a/tests/specs/upgrade/specific_canary/version.out b/tests/specs/upgrade/specific_canary/version.out new file mode 100644 index 0000000000..da474c0449 --- /dev/null +++ b/tests/specs/upgrade/specific_canary/version.out @@ -0,0 +1,3 @@ +deno 2.0.0-rc.2+aaf2bf4 (canary, release, [WILDCARD]) +v8 12.9.202.13-rusty +typescript 5.6.2 diff --git a/tests/specs/upgrade/specific_stable/__test__.jsonc b/tests/specs/upgrade/specific_stable/__test__.jsonc new file mode 100644 index 0000000000..9d8f2bd8af --- /dev/null +++ b/tests/specs/upgrade/specific_stable/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --force --version 1.43.2", + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/specific_stable/upgrade.out b/tests/specs/upgrade/specific_stable/upgrade.out new file mode 100644 index 0000000000..a2b47d0ec8 --- /dev/null +++ b/tests/specs/upgrade/specific_stable/upgrade.out @@ -0,0 +1,14 @@ +Current Deno version: [WILDCARD] +Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip +Deno is upgrading to version 1.43.2 + +Upgraded successfully to Deno v1.43.2 (stable) + +Release notes: + + https://github.com/denoland/deno/releases/tag/v1.43.2 + +Blog post: + + https://deno.com/blog/v1.43 + diff --git a/tests/specs/upgrade/specific_stable/version.out b/tests/specs/upgrade/specific_stable/version.out new file mode 100644 index 0000000000..9ddecf67c2 --- /dev/null +++ b/tests/specs/upgrade/specific_stable/version.out @@ -0,0 +1,3 @@ +deno 1.43.2 (release, [WILDCARD]) +v8 12.4.254.12 +typescript 5.4.5 diff --git a/tests/specs/upgrade/stable/__test__.jsonc b/tests/specs/upgrade/stable/__test__.jsonc new file mode 100644 index 0000000000..97e2ddb3ce --- /dev/null +++ b/tests/specs/upgrade/stable/__test__.jsonc @@ -0,0 +1,23 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "eval Deno.copyFileSync(Deno.execPath(),'./deno_copy');", + "exitCode": 0, + "output": "" + }, + { + "commandName": "./deno_copy", + "args": "upgrade --force", + "output": "upgrade.out", + "exitCode": 0, + "flaky": true + }, + { + "commandName": "./deno_copy", + "args": "--version", + "exitCode": 0, + "output": "version.out" + } + ] +} diff --git a/tests/specs/upgrade/stable/upgrade.out b/tests/specs/upgrade/stable/upgrade.out new file mode 100644 index 0000000000..3fe8f3ee81 --- /dev/null +++ b/tests/specs/upgrade/stable/upgrade.out @@ -0,0 +1,10 @@ +Current Deno version: [WILDCARD] +Looking up stable version + +Found latest stable version [WILDCARD] + +Downloading https://github.com/denoland/deno/releases/download/[WILDCARD]/deno-[WILDCARD].zip +Deno is upgrading to version [WILDCARD] + +Upgraded successfully to Deno [WILDCARD] (stable) + diff --git a/tests/specs/upgrade/stable/version.out b/tests/specs/upgrade/stable/version.out new file mode 100644 index 0000000000..43b90e51ed --- /dev/null +++ b/tests/specs/upgrade/stable/version.out @@ -0,0 +1,3 @@ +deno [WILDCARD] (stable, release, [WILDCARD]) +v8 [WILDCARD] +typescript [WILDCARD] diff --git a/tests/specs/vendor/removed/__test__.jsonc b/tests/specs/vendor/removed/__test__.jsonc new file mode 100644 index 0000000000..abbcfe4653 --- /dev/null +++ b/tests/specs/vendor/removed/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "steps": [ + { + "args": "vendor", + "output": "vendor.out", + "exitCode": 1 + }, + { + "args": "vendor --help", + "output": "vendor_help.out" + } + ] +} diff --git a/tests/specs/vendor/removed/vendor.out b/tests/specs/vendor/removed/vendor.out new file mode 100644 index 0000000000..ee7e9ca556 --- /dev/null +++ b/tests/specs/vendor/removed/vendor.out @@ -0,0 +1,3 @@ +error: ⚠️ `deno vendor` was removed in Deno 2. + +See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations diff --git a/tests/specs/vendor/removed/vendor_help.out b/tests/specs/vendor/removed/vendor_help.out new file mode 100644 index 0000000000..176b2211af --- /dev/null +++ b/tests/specs/vendor/removed/vendor_help.out @@ -0,0 +1,10 @@ +⚠️ `deno vendor` was removed in Deno 2. + +See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations + +Usage: deno vendor [OPTIONS] + +Options: + -q, --quiet Suppress diagnostic output + --unstable Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features + To view the list of individual unstable feature flags, run this command again with --help=unstable diff --git a/tests/specs/worker/_084_worker_custom_inspect/__test__.jsonc b/tests/specs/worker/_084_worker_custom_inspect/__test__.jsonc new file mode 100644 index 0000000000..8d47afab45 --- /dev/null +++ b/tests/specs/worker/_084_worker_custom_inspect/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read custom_inspect/main.ts", + "output": "custom_inspect/main.out" +} diff --git a/tests/testdata/workers/custom_inspect/main.out b/tests/specs/worker/_084_worker_custom_inspect/custom_inspect/main.out similarity index 100% rename from tests/testdata/workers/custom_inspect/main.out rename to tests/specs/worker/_084_worker_custom_inspect/custom_inspect/main.out diff --git a/tests/testdata/workers/custom_inspect/main.ts b/tests/specs/worker/_084_worker_custom_inspect/custom_inspect/main.ts similarity index 100% rename from tests/testdata/workers/custom_inspect/main.ts rename to tests/specs/worker/_084_worker_custom_inspect/custom_inspect/main.ts diff --git a/tests/testdata/workers/custom_inspect/worker.ts b/tests/specs/worker/_084_worker_custom_inspect/custom_inspect/worker.ts similarity index 100% rename from tests/testdata/workers/custom_inspect/worker.ts rename to tests/specs/worker/_084_worker_custom_inspect/custom_inspect/worker.ts diff --git a/tests/specs/worker/error_worker_permissions_local/__test__.jsonc b/tests/specs/worker/error_worker_permissions_local/__test__.jsonc new file mode 100644 index 0000000000..a36e19fa64 --- /dev/null +++ b/tests/specs/worker/error_worker_permissions_local/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --reload error_worker_permissions_local.ts", + "output": "error_worker_permissions_local.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/error_worker_permissions_local.ts b/tests/specs/worker/error_worker_permissions_local/error_worker_permissions_local.ts similarity index 100% rename from tests/testdata/workers/error_worker_permissions_local.ts rename to tests/specs/worker/error_worker_permissions_local/error_worker_permissions_local.ts diff --git a/tests/testdata/workers/error_worker_permissions_local.ts.out b/tests/specs/worker/error_worker_permissions_local/error_worker_permissions_local.ts.out similarity index 100% rename from tests/testdata/workers/error_worker_permissions_local.ts.out rename to tests/specs/worker/error_worker_permissions_local/error_worker_permissions_local.ts.out diff --git a/tests/testdata/workers/worker_types.ts b/tests/specs/worker/error_worker_permissions_local/worker_types.ts similarity index 100% rename from tests/testdata/workers/worker_types.ts rename to tests/specs/worker/error_worker_permissions_local/worker_types.ts diff --git a/tests/specs/worker/error_worker_permissions_remote/__test__.jsonc b/tests/specs/worker/error_worker_permissions_remote/__test__.jsonc new file mode 100644 index 0000000000..d40e31a49f --- /dev/null +++ b/tests/specs/worker/error_worker_permissions_remote/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --reload --allow-import=other.host error_worker_permissions_remote.ts", + "output": "error_worker_permissions_remote.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/error_worker_permissions_remote.ts b/tests/specs/worker/error_worker_permissions_remote/error_worker_permissions_remote.ts similarity index 100% rename from tests/testdata/workers/error_worker_permissions_remote.ts rename to tests/specs/worker/error_worker_permissions_remote/error_worker_permissions_remote.ts diff --git a/tests/specs/worker/error_worker_permissions_remote/error_worker_permissions_remote.ts.out b/tests/specs/worker/error_worker_permissions_remote/error_worker_permissions_remote.ts.out new file mode 100644 index 0000000000..8019bb46d1 --- /dev/null +++ b/tests/specs/worker/error_worker_permissions_remote/error_worker_permissions_remote.ts.out @@ -0,0 +1,2 @@ +error: Uncaught (in worker "") Requires import access to "localhost:4545", run again with the --allow-import flag +[WILDCARD] diff --git a/tests/specs/worker/nonexistent_worker/__test__.jsonc b/tests/specs/worker/nonexistent_worker/__test__.jsonc new file mode 100644 index 0000000000..eada833525 --- /dev/null +++ b/tests/specs/worker/nonexistent_worker/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --allow-read nonexistent_worker.ts", + "output": "nonexistent_worker.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/nonexistent_worker.out b/tests/specs/worker/nonexistent_worker/nonexistent_worker.out similarity index 80% rename from tests/testdata/workers/nonexistent_worker.out rename to tests/specs/worker/nonexistent_worker/nonexistent_worker.out index a624c0b517..977d2af48a 100644 --- a/tests/testdata/workers/nonexistent_worker.out +++ b/tests/specs/worker/nonexistent_worker/nonexistent_worker.out @@ -1,3 +1,3 @@ -[WILDCARD]error: Uncaught (in worker "") Module not found "file:///[WILDCARD]/workers/doesnt_exist.js". +[WILDCARD]error: Uncaught (in worker "") Module not found "file:///[WILDCARD]/doesnt_exist.js". error: Uncaught (in promise) Error: Unhandled error in child worker. at Worker.#pollControl[WILDCARD] diff --git a/tests/testdata/workers/nonexistent_worker.ts b/tests/specs/worker/nonexistent_worker/nonexistent_worker.ts similarity index 100% rename from tests/testdata/workers/nonexistent_worker.ts rename to tests/specs/worker/nonexistent_worker/nonexistent_worker.ts diff --git a/tests/specs/worker/worker_async_error/__test__.jsonc b/tests/specs/worker/worker_async_error/__test__.jsonc new file mode 100644 index 0000000000..0e48d3f320 --- /dev/null +++ b/tests/specs/worker/worker_async_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet --reload worker_async_error.ts", + "output": "worker_async_error.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/async_error.ts b/tests/specs/worker/worker_async_error/async_error.ts similarity index 100% rename from tests/testdata/workers/async_error.ts rename to tests/specs/worker/worker_async_error/async_error.ts diff --git a/tests/testdata/workers/worker_async_error.ts b/tests/specs/worker/worker_async_error/worker_async_error.ts similarity index 100% rename from tests/testdata/workers/worker_async_error.ts rename to tests/specs/worker/worker_async_error/worker_async_error.ts diff --git a/tests/testdata/workers/worker_async_error.ts.out b/tests/specs/worker/worker_async_error/worker_async_error.ts.out similarity index 100% rename from tests/testdata/workers/worker_async_error.ts.out rename to tests/specs/worker/worker_async_error/worker_async_error.ts.out diff --git a/tests/specs/worker/worker_doest_stall_event_loop/__test__.jsonc b/tests/specs/worker/worker_doest_stall_event_loop/__test__.jsonc new file mode 100644 index 0000000000..a5ccc6cabd --- /dev/null +++ b/tests/specs/worker/worker_doest_stall_event_loop/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet -A worker_doest_stall_event_loop.ts", + "output": "worker_doest_stall_event_loop.ts.out", + "exitCode": 0 +} diff --git a/tests/testdata/workers/worker_doest_stall_event_loop.ts b/tests/specs/worker/worker_doest_stall_event_loop/worker_doest_stall_event_loop.ts similarity index 100% rename from tests/testdata/workers/worker_doest_stall_event_loop.ts rename to tests/specs/worker/worker_doest_stall_event_loop/worker_doest_stall_event_loop.ts diff --git a/tests/testdata/workers/worker_doest_stall_event_loop.ts.out b/tests/specs/worker/worker_doest_stall_event_loop/worker_doest_stall_event_loop.ts.out similarity index 100% rename from tests/testdata/workers/worker_doest_stall_event_loop.ts.out rename to tests/specs/worker/worker_doest_stall_event_loop/worker_doest_stall_event_loop.ts.out diff --git a/tests/specs/worker/worker_error/__test__.jsonc b/tests/specs/worker/worker_error/__test__.jsonc new file mode 100644 index 0000000000..9c50a78563 --- /dev/null +++ b/tests/specs/worker/worker_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A worker_error.ts", + "output": "worker_error.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/error.ts b/tests/specs/worker/worker_error/error.ts similarity index 100% rename from tests/testdata/workers/error.ts rename to tests/specs/worker/worker_error/error.ts diff --git a/tests/testdata/workers/worker_error.ts b/tests/specs/worker/worker_error/worker_error.ts similarity index 100% rename from tests/testdata/workers/worker_error.ts rename to tests/specs/worker/worker_error/worker_error.ts diff --git a/tests/testdata/workers/worker_error.ts.out b/tests/specs/worker/worker_error/worker_error.ts.out similarity index 100% rename from tests/testdata/workers/worker_error.ts.out rename to tests/specs/worker/worker_error/worker_error.ts.out diff --git a/tests/specs/worker/worker_error_event/__test__.jsonc b/tests/specs/worker/worker_error_event/__test__.jsonc new file mode 100644 index 0000000000..a05481a132 --- /dev/null +++ b/tests/specs/worker/worker_error_event/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet -A error_event.ts", + "output": "error_event.ts.out", + "exitCode": 1 +} diff --git a/tests/specs/worker/worker_error_event/error.ts b/tests/specs/worker/worker_error_event/error.ts new file mode 100644 index 0000000000..495971090d --- /dev/null +++ b/tests/specs/worker/worker_error_event/error.ts @@ -0,0 +1,5 @@ +function foo() { + throw new Error("foo"); +} + +foo(); diff --git a/tests/testdata/workers/error_event.ts b/tests/specs/worker/worker_error_event/error_event.ts similarity index 100% rename from tests/testdata/workers/error_event.ts rename to tests/specs/worker/worker_error_event/error_event.ts diff --git a/tests/testdata/workers/error_event.ts.out b/tests/specs/worker/worker_error_event/error_event.ts.out similarity index 100% rename from tests/testdata/workers/error_event.ts.out rename to tests/specs/worker/worker_error_event/error_event.ts.out diff --git a/tests/specs/worker/worker_ids_are_sequential/__test__.jsonc b/tests/specs/worker/worker_ids_are_sequential/__test__.jsonc new file mode 100644 index 0000000000..b90bebac80 --- /dev/null +++ b/tests/specs/worker/worker_ids_are_sequential/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet -A worker_ids_are_sequential.ts", + "output": "worker_ids_are_sequential.ts.out", + "exitCode": 0 +} diff --git a/tests/testdata/workers/worker_ids_are_sequential.ts b/tests/specs/worker/worker_ids_are_sequential/worker_ids_are_sequential.ts similarity index 100% rename from tests/testdata/workers/worker_ids_are_sequential.ts rename to tests/specs/worker/worker_ids_are_sequential/worker_ids_are_sequential.ts diff --git a/tests/testdata/workers/worker_ids_are_sequential.ts.out b/tests/specs/worker/worker_ids_are_sequential/worker_ids_are_sequential.ts.out similarity index 100% rename from tests/testdata/workers/worker_ids_are_sequential.ts.out rename to tests/specs/worker/worker_ids_are_sequential/worker_ids_are_sequential.ts.out diff --git a/tests/specs/worker/worker_message_handler_error/__test__.jsonc b/tests/specs/worker/worker_message_handler_error/__test__.jsonc new file mode 100644 index 0000000000..ea00753a79 --- /dev/null +++ b/tests/specs/worker/worker_message_handler_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A --quiet --reload worker_message_handler_error.ts", + "output": "worker_message_handler_error.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/message_handler_error.ts b/tests/specs/worker/worker_message_handler_error/message_handler_error.ts similarity index 100% rename from tests/testdata/workers/message_handler_error.ts rename to tests/specs/worker/worker_message_handler_error/message_handler_error.ts diff --git a/tests/testdata/workers/worker_message_handler_error.ts b/tests/specs/worker/worker_message_handler_error/worker_message_handler_error.ts similarity index 100% rename from tests/testdata/workers/worker_message_handler_error.ts rename to tests/specs/worker/worker_message_handler_error/worker_message_handler_error.ts diff --git a/tests/testdata/workers/worker_message_handler_error.ts.out b/tests/specs/worker/worker_message_handler_error/worker_message_handler_error.ts.out similarity index 100% rename from tests/testdata/workers/worker_message_handler_error.ts.out rename to tests/specs/worker/worker_message_handler_error/worker_message_handler_error.ts.out diff --git a/tests/specs/worker/worker_nested_error/__test__.jsonc b/tests/specs/worker/worker_nested_error/__test__.jsonc new file mode 100644 index 0000000000..71d7c8109e --- /dev/null +++ b/tests/specs/worker/worker_nested_error/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A worker_nested_error.ts", + "output": "worker_nested_error.ts.out", + "exitCode": 1 +} diff --git a/tests/specs/worker/worker_nested_error/error.ts b/tests/specs/worker/worker_nested_error/error.ts new file mode 100644 index 0000000000..495971090d --- /dev/null +++ b/tests/specs/worker/worker_nested_error/error.ts @@ -0,0 +1,5 @@ +function foo() { + throw new Error("foo"); +} + +foo(); diff --git a/tests/specs/worker/worker_nested_error/worker_error.ts b/tests/specs/worker/worker_nested_error/worker_error.ts new file mode 100644 index 0000000000..403223d0a7 --- /dev/null +++ b/tests/specs/worker/worker_nested_error/worker_error.ts @@ -0,0 +1,5 @@ +const worker = new Worker( + import.meta.resolve("./error.ts"), + { type: "module", name: "bar" }, +); +setTimeout(() => worker.terminate(), 30000); diff --git a/tests/testdata/workers/worker_nested_error.ts b/tests/specs/worker/worker_nested_error/worker_nested_error.ts similarity index 100% rename from tests/testdata/workers/worker_nested_error.ts rename to tests/specs/worker/worker_nested_error/worker_nested_error.ts diff --git a/tests/testdata/workers/worker_nested_error.ts.out b/tests/specs/worker/worker_nested_error/worker_nested_error.ts.out similarity index 77% rename from tests/testdata/workers/worker_nested_error.ts.out rename to tests/specs/worker/worker_nested_error/worker_nested_error.ts.out index 3622acfb3d..404b0aa3d3 100644 --- a/tests/testdata/workers/worker_nested_error.ts.out +++ b/tests/specs/worker/worker_nested_error/worker_nested_error.ts.out @@ -1,8 +1,8 @@ [WILDCARD]error: Uncaught (in worker "bar") (in promise) Error: foo[WILDCARD] throw new Error("foo"); ^ - at foo ([WILDCARD]/workers/error.ts:[WILDCARD]) - at [WILDCARD]/workers/error.ts:[WILDCARD] + at foo ([WILDCARD]/error.ts:[WILDCARD]) + at [WILDCARD]/error.ts:[WILDCARD] error: Uncaught (in worker "baz") (in promise) Error: Unhandled error in child worker. at Worker.#pollControl [WILDCARD] error: Uncaught (in promise) Error: Unhandled error in child worker. diff --git a/tests/specs/worker/worker_permissions_blob_local/__test__.jsonc b/tests/specs/worker/worker_permissions_blob_local/__test__.jsonc new file mode 100644 index 0000000000..27a747b3a5 --- /dev/null +++ b/tests/specs/worker/worker_permissions_blob_local/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-net=localhost:4545 permissions_blob_local.ts", + "output": "permissions_blob_local.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_blob_local.ts b/tests/specs/worker/worker_permissions_blob_local/permissions_blob_local.ts similarity index 100% rename from tests/testdata/workers/permissions_blob_local.ts rename to tests/specs/worker/worker_permissions_blob_local/permissions_blob_local.ts diff --git a/tests/testdata/workers/permissions_blob_local.ts.out b/tests/specs/worker/worker_permissions_blob_local/permissions_blob_local.ts.out similarity index 100% rename from tests/testdata/workers/permissions_blob_local.ts.out rename to tests/specs/worker/worker_permissions_blob_local/permissions_blob_local.ts.out diff --git a/tests/specs/worker/worker_permissions_blob_remote/__test__.jsonc b/tests/specs/worker/worker_permissions_blob_remote/__test__.jsonc new file mode 100644 index 0000000000..f9d66b6b38 --- /dev/null +++ b/tests/specs/worker/worker_permissions_blob_remote/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-net=localhost:4545 permissions_blob_remote.ts", + "output": "permissions_blob_remote.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_blob_remote.ts b/tests/specs/worker/worker_permissions_blob_remote/permissions_blob_remote.ts similarity index 100% rename from tests/testdata/workers/permissions_blob_remote.ts rename to tests/specs/worker/worker_permissions_blob_remote/permissions_blob_remote.ts diff --git a/tests/testdata/workers/permissions_blob_remote.ts.out b/tests/specs/worker/worker_permissions_blob_remote/permissions_blob_remote.ts.out similarity index 54% rename from tests/testdata/workers/permissions_blob_remote.ts.out rename to tests/specs/worker/worker_permissions_blob_remote/permissions_blob_remote.ts.out index 6dc4f0f5fa..67b817d6df 100644 --- a/tests/testdata/workers/permissions_blob_remote.ts.out +++ b/tests/specs/worker/worker_permissions_blob_remote/permissions_blob_remote.ts.out @@ -1,4 +1,4 @@ -error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in worker "") Requires import access to "example.com:443", run again with the --allow-import flag at blob:null/[WILDCARD]:1:8 error: Uncaught (in promise) Error: Unhandled error in child worker. at Worker.#pollControl[WILDCARD] diff --git a/tests/specs/worker/worker_permissions_data_local/__test__.jsonc b/tests/specs/worker/worker_permissions_data_local/__test__.jsonc new file mode 100644 index 0000000000..8f118d8be3 --- /dev/null +++ b/tests/specs/worker/worker_permissions_data_local/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-net=localhost:4545 permissions_data_local.ts", + "output": "permissions_data_local.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_data_local.ts b/tests/specs/worker/worker_permissions_data_local/permissions_data_local.ts similarity index 100% rename from tests/testdata/workers/permissions_data_local.ts rename to tests/specs/worker/worker_permissions_data_local/permissions_data_local.ts diff --git a/tests/testdata/workers/permissions_data_local.ts.out b/tests/specs/worker/worker_permissions_data_local/permissions_data_local.ts.out similarity index 100% rename from tests/testdata/workers/permissions_data_local.ts.out rename to tests/specs/worker/worker_permissions_data_local/permissions_data_local.ts.out diff --git a/tests/specs/worker/worker_permissions_data_remote/__test__.jsonc b/tests/specs/worker/worker_permissions_data_remote/__test__.jsonc new file mode 100644 index 0000000000..6096b4280a --- /dev/null +++ b/tests/specs/worker/worker_permissions_data_remote/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-net=localhost:4545 permissions_data_remote.ts", + "output": "permissions_data_remote.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_data_remote.ts b/tests/specs/worker/worker_permissions_data_remote/permissions_data_remote.ts similarity index 100% rename from tests/testdata/workers/permissions_data_remote.ts rename to tests/specs/worker/worker_permissions_data_remote/permissions_data_remote.ts diff --git a/tests/testdata/workers/permissions_data_remote.ts.out b/tests/specs/worker/worker_permissions_data_remote/permissions_data_remote.ts.out similarity index 64% rename from tests/testdata/workers/permissions_data_remote.ts.out rename to tests/specs/worker/worker_permissions_data_remote/permissions_data_remote.ts.out index e7af110bb5..0f5a994345 100644 --- a/tests/testdata/workers/permissions_data_remote.ts.out +++ b/tests/specs/worker/worker_permissions_data_remote/permissions_data_remote.ts.out @@ -1,4 +1,4 @@ -error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in worker "") Requires import access to "example.com:443", run again with the --allow-import flag at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8 error: Uncaught (in promise) Error: Unhandled error in child worker. at Worker.#pollControl[WILDCARD] diff --git a/tests/specs/worker/worker_permissions_dynamic_remote/__test__.jsonc b/tests/specs/worker/worker_permissions_dynamic_remote/__test__.jsonc new file mode 100644 index 0000000000..498d9d5079 --- /dev/null +++ b/tests/specs/worker/worker_permissions_dynamic_remote/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-import --unstable-worker-options permissions_dynamic_remote.ts", + "output": "permissions_dynamic_remote.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_dynamic_remote.ts b/tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts similarity index 64% rename from tests/testdata/workers/permissions_dynamic_remote.ts rename to tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts index 54a361bc00..5f0fdf7a17 100644 --- a/tests/testdata/workers/permissions_dynamic_remote.ts +++ b/tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts @@ -4,7 +4,8 @@ new Worker( type: "module", deno: { permissions: { - net: false, + // dynamic_remote.ts will import from example.com + import: false, }, }, }, diff --git a/tests/testdata/workers/permissions_dynamic_remote.ts.out b/tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts.out similarity index 80% rename from tests/testdata/workers/permissions_dynamic_remote.ts.out rename to tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts.out index 4fb2c2234f..fa4232efd0 100644 --- a/tests/testdata/workers/permissions_dynamic_remote.ts.out +++ b/tests/specs/worker/worker_permissions_dynamic_remote/permissions_dynamic_remote.ts.out @@ -1,4 +1,4 @@ -error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in worker "") (in promise) TypeError: Requires import access to "example.com:443", run again with the --allow-import flag await import("" + "https://example.com/some/file.ts"); ^ at async http://localhost:4545/workers/dynamic_remote.ts:2:1 diff --git a/tests/specs/worker/worker_permissions_remote_remote/__test__.jsonc b/tests/specs/worker/worker_permissions_remote_remote/__test__.jsonc new file mode 100644 index 0000000000..00fd2a6e4c --- /dev/null +++ b/tests/specs/worker/worker_permissions_remote_remote/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --quiet --reload --allow-import=localhost:4545 permissions_remote_remote.ts", + "output": "permissions_remote_remote.ts.out", + "exitCode": 1 +} diff --git a/tests/testdata/workers/permissions_remote_remote.ts b/tests/specs/worker/worker_permissions_remote_remote/permissions_remote_remote.ts similarity index 100% rename from tests/testdata/workers/permissions_remote_remote.ts rename to tests/specs/worker/worker_permissions_remote_remote/permissions_remote_remote.ts diff --git a/tests/specs/worker/worker_permissions_remote_remote/permissions_remote_remote.ts.out b/tests/specs/worker/worker_permissions_remote_remote/permissions_remote_remote.ts.out new file mode 100644 index 0000000000..423120bb0c --- /dev/null +++ b/tests/specs/worker/worker_permissions_remote_remote/permissions_remote_remote.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires import access to "example.com:443", run again with the --allow-import flag + at http://localhost:4545/[WILDCARD]/static_remote.ts:2:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/specs/worker/worker_terminate_tla_crash/__test__.jsonc b/tests/specs/worker/worker_terminate_tla_crash/__test__.jsonc new file mode 100644 index 0000000000..a3e04da857 --- /dev/null +++ b/tests/specs/worker/worker_terminate_tla_crash/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --quiet --reload terminate_tla_crash.js", + "output": "terminate_tla_crash.js.out" +} diff --git a/tests/testdata/workers/terminate_tla_crash.js b/tests/specs/worker/worker_terminate_tla_crash/terminate_tla_crash.js similarity index 100% rename from tests/testdata/workers/terminate_tla_crash.js rename to tests/specs/worker/worker_terminate_tla_crash/terminate_tla_crash.js diff --git a/tests/specs/worker/worker_terminate_tla_crash/terminate_tla_crash.js.out b/tests/specs/worker/worker_terminate_tla_crash/terminate_tla_crash.js.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/workspaces/auto_install_pkg_json_member_only/__test__.jsonc b/tests/specs/workspaces/auto_install_pkg_json_member_only/__test__.jsonc new file mode 100644 index 0000000000..15c10d573f --- /dev/null +++ b/tests/specs/workspaces/auto_install_pkg_json_member_only/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run -A pkg_json/main.ts", + "output": "pkg_json/main.out" +} diff --git a/tests/specs/workspaces/auto_install_pkg_json_member_only/deno.json b/tests/specs/workspaces/auto_install_pkg_json_member_only/deno.json new file mode 100644 index 0000000000..0c1e5e08e1 --- /dev/null +++ b/tests/specs/workspaces/auto_install_pkg_json_member_only/deno.json @@ -0,0 +1,4 @@ +{ + "lock": false, + "workspace": ["pkg_json"] +} diff --git a/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.out b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.out new file mode 100644 index 0000000000..392591008d --- /dev/null +++ b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4260/chalk +Download http://localhost:4260/chalk/chalk-5.0.1.tgz +Hi diff --git a/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.ts b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.ts new file mode 100644 index 0000000000..009e10e7ea --- /dev/null +++ b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/main.ts @@ -0,0 +1,3 @@ +import chalk from "chalk"; + +console.log(chalk.green("Hi")); diff --git a/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/package.json b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/package.json new file mode 100644 index 0000000000..c58c3ac3c8 --- /dev/null +++ b/tests/specs/workspaces/auto_install_pkg_json_member_only/pkg_json/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "chalk": "*" + } +} diff --git a/tests/specs/workspaces/lockfile/expected-lock.out b/tests/specs/workspaces/lockfile/expected-lock.out index dcc479a201..1559be0858 100644 --- a/tests/specs/workspaces/lockfile/expected-lock.out +++ b/tests/specs/workspaces/lockfile/expected-lock.out @@ -1,16 +1,13 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0" - }, - "jsr": { - "@denotest/add@1.0.0": { - "integrity": "3b2e675c1ad7fba2a45bc251992e01aff08a3c974ac09079b11e6a5b95d4bfcb" - } + "version": "4", + "specifiers": { + "jsr:@denotest/add@1": "1.0.0" + }, + "jsr": { + "@denotest/add@1.0.0": { + "integrity": "3b2e675c1ad7fba2a45bc251992e01aff08a3c974ac09079b11e6a5b95d4bfcb" } }, - "remote": {}, "workspace": { "members": { "pkg": { diff --git a/tests/specs/workspaces/nested_deno_pkg_npm_conflict/__test__.jsonc b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/__test__.jsonc new file mode 100644 index 0000000000..d0d7579b87 --- /dev/null +++ b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "run --allow-read main.js", + "output": "4\n1.0.0\n" + }, { + "args": "run --allow-read member/main.js", + "output": "3\n" + }] +} diff --git a/tests/specs/workspaces/nested_deno_pkg_npm_conflict/deno.json b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/deno.json new file mode 100644 index 0000000000..f03a591e23 --- /dev/null +++ b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/deno.json @@ -0,0 +1,7 @@ +{ + "nodeModulesDir": "manual", + "workspace": ["./member"], + "imports": { + "@denotest/add": "npm:@denotest/add@0.5" + } +} diff --git a/tests/specs/workspaces/nested_deno_pkg_npm_conflict/main.js b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/main.js new file mode 100644 index 0000000000..188da6f975 --- /dev/null +++ b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/main.js @@ -0,0 +1,9 @@ +import { sum } from "@denotest/add"; + +console.log(sum(2, 2)); + +console.log( + JSON.parse(Deno.readTextFileSync( + new URL("node_modules/@denotest/add/package.json", import.meta.url), + )).version, +); diff --git a/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/deno.json b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/deno.json new file mode 100644 index 0000000000..1d36d0aab7 --- /dev/null +++ b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@denotest/add": "npm:@denotest/add@1" + } +} diff --git a/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/main.js b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/main.js new file mode 100644 index 0000000000..1ca631410f --- /dev/null +++ b/tests/specs/workspaces/nested_deno_pkg_npm_conflict/member/main.js @@ -0,0 +1,3 @@ +import { add } from "@denotest/add"; + +console.log(add(1, 2)); diff --git a/tests/testdata/add.ts b/tests/testdata/add.ts new file mode 100644 index 0000000000..8d9b8a22a1 --- /dev/null +++ b/tests/testdata/add.ts @@ -0,0 +1,3 @@ +export function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/testdata/allow_run_allowlist_resolution.ts b/tests/testdata/allow_run_allowlist_resolution.ts deleted file mode 100644 index c7369d928a..0000000000 --- a/tests/testdata/allow_run_allowlist_resolution.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Testing the following (but with `deno` instead of `echo`): -// | `deno run --allow-run=echo` | `which path == "/usr/bin/echo"` at startup | `which path != "/usr/bin/echo"` at startup | -// |-------------------------------------|--------------------------------------------|--------------------------------------------| -// | **`Deno.Command("echo")`** | ✅ | ✅ | -// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ❌ | - -// | `deno run --allow-run=/usr/bin/echo | `which path == "/usr/bin/echo"` at runtime | `which path != "/usr/bin/echo"` at runtime | -// |-------------------------------------|--------------------------------------------|--------------------------------------------| -// | **`Deno.Command("echo")`** | ✅ | ❌ | -// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ✅ | - -const execPath = Deno.execPath(); -const execPathParent = execPath.replace(/[/\\][^/\\]+$/, ""); - -const testUrl = `data:application/typescript;base64,${ - btoa(` - console.log(await Deno.permissions.query({ name: "run", command: "deno" })); - console.log(await Deno.permissions.query({ name: "run", command: "${ - execPath.replaceAll("\\", "\\\\") - }" })); - Deno.env.set("PATH", ""); - console.log(await Deno.permissions.query({ name: "run", command: "deno" })); - console.log(await Deno.permissions.query({ name: "run", command: "${ - execPath.replaceAll("\\", "\\\\") - }" })); -`) -}`; - -const process1 = await new Deno.Command(Deno.execPath(), { - args: [ - "run", - "--quiet", - "--allow-env", - "--allow-run=deno", - testUrl, - ], - stderr: "null", - env: { "PATH": execPathParent }, -}).output(); -console.log(new TextDecoder().decode(process1.stdout)); - -const process2 = await new Deno.Command(Deno.execPath(), { - args: [ - "run", - "--quiet", - "--allow-env", - "--allow-run=deno", - testUrl, - ], - stderr: "null", - env: { "PATH": "" }, -}).output(); -console.log(new TextDecoder().decode(process2.stdout)); - -const process3 = await new Deno.Command(Deno.execPath(), { - args: [ - "run", - "--quiet", - "--allow-env", - `--allow-run=${execPath}`, - testUrl, - ], - stderr: "null", - env: { "PATH": execPathParent }, -}).output(); -console.log(new TextDecoder().decode(process3.stdout)); diff --git a/tests/testdata/bench/allow_all.out b/tests/testdata/bench/allow_all.out index b118856e98..0aba21914d 100644 --- a/tests/testdata/bench/allow_all.out +++ b/tests/testdata/bench/allow_all.out @@ -1,21 +1,20 @@ Check [WILDCARD]/bench/allow_all.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/allow_all.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ------------------------------------------------------------------- ----------------------------- -read false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -read true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -write false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -write true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -net false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -net true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -env false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -env true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -run false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -run true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -ffi false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -ffi true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -hrtime false [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -hrtime true [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +-------------- ----------------------------- --------------------- -------------------------- +read false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +read true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +write false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +write true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +net false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +net true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +env false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +env true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +run false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +run true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +ffi false [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +ffi true [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/allow_none.out b/tests/testdata/bench/allow_none.out index 7c443075b9..2a75ab5fdd 100644 --- a/tests/testdata/bench/allow_none.out +++ b/tests/testdata/bench/allow_none.out @@ -1,22 +1,21 @@ Check [WILDCARD]/bench/allow_none.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/allow_none.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -read error: PermissionDenied: Can't escalate parent thread permissions + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +read error: NotCapable: Can't escalate parent thread permissions [WILDCARD] -write error: PermissionDenied: Can't escalate parent thread permissions +write error: NotCapable: Can't escalate parent thread permissions [WILDCARD] -net error: PermissionDenied: Can't escalate parent thread permissions +net error: NotCapable: Can't escalate parent thread permissions [WILDCARD] -env error: PermissionDenied: Can't escalate parent thread permissions +env error: NotCapable: Can't escalate parent thread permissions [WILDCARD] -run error: PermissionDenied: Can't escalate parent thread permissions +run error: NotCapable: Can't escalate parent thread permissions [WILDCARD] -ffi error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] -hrtime error: PermissionDenied: Can't escalate parent thread permissions +ffi error: NotCapable: Can't escalate parent thread permissions [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/before_unload_prevent_default.out b/tests/testdata/bench/before_unload_prevent_default.out index dcb6d81948..c394795e45 100644 --- a/tests/testdata/bench/before_unload_prevent_default.out +++ b/tests/testdata/bench/before_unload_prevent_default.out @@ -1,7 +1,8 @@ -cpu: [WILDCARD] -runtime: deno [WILDCARD] + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] [WILDCARD]/before_unload_prevent_default.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -foo [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +foo [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/bench_formatting.out b/tests/testdata/bench/bench_formatting.out index 5e3eed1cd0..fa898a2c1d 100644 --- a/tests/testdata/bench/bench_formatting.out +++ b/tests/testdata/bench/bench_formatting.out @@ -1,8 +1,9 @@ Check [WILDCARD]/bench/bench_formatting.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/bench_formatting.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -[WILDCARD] [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] \ No newline at end of file + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +[WILDCARD] [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] \ No newline at end of file diff --git a/tests/testdata/bench/check_local_by_default.out b/tests/testdata/bench/check_local_by_default.out index bf07bcc443..b82627db3c 100644 --- a/tests/testdata/bench/check_local_by_default.out +++ b/tests/testdata/bench/check_local_by_default.out @@ -1,6 +1,7 @@ [WILDCARD] [WILDCARD]/bench/check_local_by_default.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- diff --git a/tests/testdata/bench/clear_timeout.out b/tests/testdata/bench/clear_timeout.out index fe17b4ae3e..24ba4f607c 100644 --- a/tests/testdata/bench/clear_timeout.out +++ b/tests/testdata/bench/clear_timeout.out @@ -1,10 +1,11 @@ Check [WILDCARD]/bench/clear_timeout.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/clear_timeout.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench1 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench1 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/exit_sanitizer.out b/tests/testdata/bench/exit_sanitizer.out index 9f15d3f261..a5c03434d5 100644 --- a/tests/testdata/bench/exit_sanitizer.out +++ b/tests/testdata/bench/exit_sanitizer.out @@ -1,14 +1,15 @@ Check [WILDCARD]/bench/exit_sanitizer.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/exit_sanitizer.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -exit(0) error: Error: Bench attempted to exit with exit code: 0 + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +exit(0) error: Error: Bench attempted to exit with exit code: 0 [WILDCARD] -exit(1) error: Error: Bench attempted to exit with exit code: 1 +exit(1) error: Error: Bench attempted to exit with exit code: 1 [WILDCARD] -exit(2) error: Error: Bench attempted to exit with exit code: 2 +exit(2) error: Error: Bench attempted to exit with exit code: 2 [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/explicit_start_and_end.out b/tests/testdata/bench/explicit_start_and_end.out index fa118540c9..6759d39cad 100644 --- a/tests/testdata/bench/explicit_start_and_end.out +++ b/tests/testdata/bench/explicit_start_and_end.out @@ -1,23 +1,24 @@ -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/explicit_start_and_end.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 -------------------------------------------------------------------- ----------------------------- -start and end [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -start only [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -end only [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -double start error: TypeError: BenchContext::start() has already been invoked. + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +--------------- ----------------------------- --------------------- -------------------------- +start and end [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +start only [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +end only [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +double start error: Type error: BenchContext::start() has already been invoked t.start(); ^ at BenchContext.start ([WILDCARD]) at [WILDCARD]/explicit_start_and_end.ts:[WILDCARD] -double end error: TypeError: BenchContext::end() has already been invoked. +double end error: Type error: BenchContext::end() has already been invoked t.end(); ^ at BenchContext.end ([WILDCARD]) at [WILDCARD]/explicit_start_and_end.ts:[WILDCARD] -captured error: TypeError: The benchmark which this context belongs to is not being executed. +captured error: Type error: The benchmark which this context belongs to is not being executed captured!.start(); ^ at BenchContext.start ([WILDCARD]) diff --git a/tests/testdata/bench/fail.out b/tests/testdata/bench/fail.out index ff3c29b927..c41ebec0e3 100644 --- a/tests/testdata/bench/fail.out +++ b/tests/testdata/bench/fail.out @@ -1,28 +1,29 @@ Check [WILDCARD]/bench/fail.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/fail.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench0 error: Error + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench0 error: Error [WILDCARD] -bench1 error: Error +bench1 error: Error [WILDCARD] -bench2 error: Error +bench2 error: Error [WILDCARD] -bench3 error: Error +bench3 error: Error [WILDCARD] -bench4 error: Error +bench4 error: Error [WILDCARD] -bench5 error: Error +bench5 error: Error [WILDCARD] -bench6 error: Error +bench6 error: Error [WILDCARD] -bench7 error: Error +bench7 error: Error [WILDCARD] -bench8 error: Error +bench8 error: Error [WILDCARD] -bench9 error: Error +bench9 error: Error [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/file_protocol.out b/tests/testdata/bench/file_protocol.out index 7086c861c2..fbe4e9d0a4 100644 --- a/tests/testdata/bench/file_protocol.out +++ b/tests/testdata/bench/file_protocol.out @@ -1,8 +1,10 @@ Check file://[WILDCARD]/bench/file_protocol.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/file_protocol.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench0 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench0 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] + diff --git a/tests/testdata/bench/finally_timeout.out b/tests/testdata/bench/finally_timeout.out index 96bec017dc..331b205383 100644 --- a/tests/testdata/bench/finally_timeout.out +++ b/tests/testdata/bench/finally_timeout.out @@ -1,11 +1,12 @@ Check [WILDCARD]/bench/finally_timeout.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/finally_timeout.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -error error: Error: fail + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +error error: Error: fail [WILDCARD] -success [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] +success [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/group_baseline.out b/tests/testdata/bench/group_baseline.out index 5de0ac1fe5..c005f5b5e3 100644 --- a/tests/testdata/bench/group_baseline.out +++ b/tests/testdata/bench/group_baseline.out @@ -1,17 +1,18 @@ [WILDCARD]/bench/group_baseline.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 --------------------------------------------------------------------- ----------------------------- -noop [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -noop2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +---------------- ----------------------------- --------------------- -------------------------- +noop [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +noop2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary noo[WILDCARD] [WILDCARD]x [WILDCARD] than noo[WILDCARD] group url -noop3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 2x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 200x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] +noop3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 2x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 200x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary parse url 2x diff --git a/tests/testdata/bench/ignore.out b/tests/testdata/bench/ignore.out index 0693a7fc8d..3973ceb5fe 100644 --- a/tests/testdata/bench/ignore.out +++ b/tests/testdata/bench/ignore.out @@ -1,8 +1,9 @@ Check [WILDCARD]/bench/ignore.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/ignore.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- diff --git a/tests/testdata/bench/ignore_permissions.out b/tests/testdata/bench/ignore_permissions.out index 1c8e93535f..e1987e1e3a 100644 --- a/tests/testdata/bench/ignore_permissions.out +++ b/tests/testdata/bench/ignore_permissions.out @@ -1,8 +1,9 @@ Check [WILDCARD]/bench/ignore_permissions.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/ignore_permissions.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- diff --git a/tests/testdata/bench/interval.out b/tests/testdata/bench/interval.out index 389b891629..5f6c2c93e1 100644 --- a/tests/testdata/bench/interval.out +++ b/tests/testdata/bench/interval.out @@ -1,8 +1,9 @@ Check [WILDCARD]/bench/interval.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/interval.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- diff --git a/tests/testdata/bench/load_unload.out b/tests/testdata/bench/load_unload.out index e5bc6b29e2..ec4006ee46 100644 --- a/tests/testdata/bench/load_unload.out +++ b/tests/testdata/bench/load_unload.out @@ -1,8 +1,9 @@ Check [WILDCARD]/bench/load_unload.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/load_unload.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/meta.out b/tests/testdata/bench/meta.out index 8c9aa91236..0b822b722b 100644 --- a/tests/testdata/bench/meta.out +++ b/tests/testdata/bench/meta.out @@ -1,10 +1,11 @@ Check [WILDCARD]/bench/meta.ts import.meta.main: false import.meta.url: [WILDCARD]/bench/meta.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/meta.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- diff --git a/tests/testdata/bench/multifile_summary.out b/tests/testdata/bench/multifile_summary.out index 37aebe1875..7f3b247f63 100644 --- a/tests/testdata/bench/multifile_summary.out +++ b/tests/testdata/bench/multifile_summary.out @@ -1,23 +1,24 @@ Check [WILDCARD]/bench/group_baseline.ts Check [WILDCARD]/bench/pass.ts Check [WILDCARD]/bench/multiple_group.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/group_baseline.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 --------------------------------------------------------------------- ----------------------------- -noop [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -noop2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +---------------- ----------------------------- --------------------- -------------------------- +noop [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +noop2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary noo[WILDCARD] [WILDCARD]x [WILDCARD] than noo[WILDCARD] group url -noop3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 2x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 200x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] +noop3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 2x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 200x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary parse url 2x @@ -26,36 +27,38 @@ summary [WILDCARD]/bench/pass.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench0 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench1 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench4 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench5 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench6 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench7 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench8 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench9 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench0 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench1 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench4 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench5 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench6 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench7 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench8 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench9 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] [WILDCARD]/bench/multiple_group.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 --------------------------------------------------------------------- ----------------------------- + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +---------------- ----------------------------- --------------------- -------------------------- group noop -noop [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -noop2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] +noop [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +noop2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary noo[WILDCARD] [WILDCARD]x [WILDCARD] than noo[WILDCARD] group url -noop3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 2x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -parse url 200x [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] +noop3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 2x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +parse url 200x [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] summary parse url 2x diff --git a/tests/testdata/bench/no_color.ts b/tests/testdata/bench/no_color.ts index d15bf35728..e3476353e0 100644 --- a/tests/testdata/bench/no_color.ts +++ b/tests/testdata/bench/no_color.ts @@ -3,6 +3,27 @@ Deno.bench({ fn() {}, }); +Deno.bench({ + name: "success long", + fn() { + 1024n ** 10000n; + }, +}); + +Deno.bench({ + name: "success but longer", + fn() { + 1024n ** 1000000n; + }, +}); + +Deno.bench({ + name: "success long and the longest name", + async fn() { + await new Promise((resolve) => setTimeout(resolve, 100)); + }, +}); + Deno.bench({ name: "fail", fn() { diff --git a/tests/testdata/bench/no_prompt_by_default.out b/tests/testdata/bench/no_prompt_by_default.out index 4c7e7f1460..d9e83cf258 100644 --- a/tests/testdata/bench/no_prompt_by_default.out +++ b/tests/testdata/bench/no_prompt_by_default.out @@ -1,9 +1,10 @@ -[WILDCARD]cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) +[WILDCARD] CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/no_prompt_by_default.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -no prompt error: PermissionDenied: Requires read access to "./some_file.txt", run again with the --allow-read flag + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +no prompt error: NotCapable: Requires read access to "./some_file.txt", run again with the --allow-read flag [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/no_prompt_with_denied_perms.out b/tests/testdata/bench/no_prompt_with_denied_perms.out index 74400dafe7..81db3068ac 100644 --- a/tests/testdata/bench/no_prompt_with_denied_perms.out +++ b/tests/testdata/bench/no_prompt_with_denied_perms.out @@ -1,9 +1,10 @@ -[WILDCARD]cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) +[WILDCARD] CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/no_prompt_with_denied_perms.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -no prompt error: PermissionDenied: Requires read access to "./some_file.txt", run again with the --allow-read flag + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +no prompt error: NotCapable: Requires read access to "./some_file.txt", run again with the --allow-read flag [WILDCARD] error: Bench failed diff --git a/tests/testdata/bench/only.out b/tests/testdata/bench/only.out index 00338af8ec..ab9827b34e 100644 --- a/tests/testdata/bench/only.out +++ b/tests/testdata/bench/only.out @@ -1,9 +1,10 @@ Check [WILDCARD]/bench/only.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/only.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -only [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +only [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] error: Bench failed because the "only" option was used diff --git a/tests/testdata/bench/overloads.out b/tests/testdata/bench/overloads.out index 289c8dde65..57f9b783e8 100644 --- a/tests/testdata/bench/overloads.out +++ b/tests/testdata/bench/overloads.out @@ -1,12 +1,13 @@ Check [WILDCARD]/bench/overloads.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/overloads.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench0 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench1 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench4 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench0 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench1 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench4 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/pass.out b/tests/testdata/bench/pass.out index 19ea6fd133..72e16c21d3 100644 --- a/tests/testdata/bench/pass.out +++ b/tests/testdata/bench/pass.out @@ -1,17 +1,18 @@ Check [WILDCARD]/bench/pass.ts -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/pass.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 ---------------------------------------------------------------- ----------------------------- -bench0 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench1 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench2 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench3 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench4 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench5 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench6 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench7 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench8 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -bench9 [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +----------- ----------------------------- --------------------- -------------------------- +bench0 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench1 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench2 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench3 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench4 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench5 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench6 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench7 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench8 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +bench9 [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bench/quiet.out b/tests/testdata/bench/quiet.out index ed9e06c84c..4a013ec210 100644 --- a/tests/testdata/bench/quiet.out +++ b/tests/testdata/bench/quiet.out @@ -1,10 +1,11 @@ -cpu: [WILDCARD] -runtime: deno [WILDCARD] ([WILDCARD]) + CPU | [WILDCARD] +Runtime | Deno [WILDCARD] ([WILDCARD]) [WILDCARD]/bench/quiet.ts -benchmark time (avg) iter/s (min … max) p75 p99 p995 -------------------------------------------------------------------- ----------------------------- -console.log [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -console.error [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -console.info [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] -console.warn [WILDCARD] [WILDCARD]/iter[WILDCARD]([WILDCARD] … [WILDCARD]) [WILDCARD] + +benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 +--------------- ----------------------------- --------------------- -------------------------- +console.log [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +console.error [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +console.info [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] +console.warn [WILDCARD] [WILDCARD] [WILDCARD] ([WILDCARD] … [WILDCARD]) [WILDCARD] diff --git a/tests/testdata/bundle/bare_imports/error_with_bare_import.ts b/tests/testdata/bundle/bare_imports/error_with_bare_import.ts deleted file mode 100644 index c0748305d5..0000000000 --- a/tests/testdata/bundle/bare_imports/error_with_bare_import.ts +++ /dev/null @@ -1 +0,0 @@ -import "foo"; diff --git a/tests/testdata/bundle/bare_imports/error_with_bare_import.ts.out b/tests/testdata/bundle/bare_imports/error_with_bare_import.ts.out deleted file mode 100644 index 44d063a5ee..0000000000 --- a/tests/testdata/bundle/bare_imports/error_with_bare_import.ts.out +++ /dev/null @@ -1,2 +0,0 @@ -[WILDCARD]error: Relative import path "foo" not prefixed with / or ./ or ../ - at file:///[WILDCARD]/error_with_bare_import.ts:[WILDCARD] diff --git a/tests/testdata/bundle/bundle.test.out b/tests/testdata/bundle/bundle.test.out deleted file mode 100644 index 6b1c109d38..0000000000 --- a/tests/testdata/bundle/bundle.test.out +++ /dev/null @@ -1,27 +0,0 @@ -[WILDCARD] -function printHello() { - console.log("Hello"); -} -function returnsFoo() { - return "Foo"; -} -function printHello2() { - printHello(); -} -function returnsHi() { - return "Hi"; -} -function returnsFoo2() { - return returnsFoo(); -} -function printHello3() { - printHello2(); -} -function throwsError() { - throw Error("exception from mod1"); -} -export { returnsHi as returnsHi }; -export { returnsFoo2 as returnsFoo2 }; -export { printHello3 as printHello3 }; -export { throwsError as throwsError }; - diff --git a/tests/testdata/bundle/check_local_by_default/no_errors.out b/tests/testdata/bundle/check_local_by_default/no_errors.out deleted file mode 100644 index c4559d1fad..0000000000 --- a/tests/testdata/bundle/check_local_by_default/no_errors.out +++ /dev/null @@ -1,6 +0,0 @@ -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -console.log(12); - diff --git a/tests/testdata/bundle/check_local_by_default/type_error.out b/tests/testdata/bundle/check_local_by_default/type_error.out deleted file mode 100644 index 6d53e94980..0000000000 --- a/tests/testdata/bundle/check_local_by_default/type_error.out +++ /dev/null @@ -1,4 +0,0 @@ -error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'. -const b: "b" = 12; - ^ - at [WILDCARD]bundle/check_local_by_default/type_error.ts:3:7 diff --git a/tests/testdata/bundle/decorators/ts_decorators.out b/tests/testdata/bundle/decorators/ts_decorators.out deleted file mode 100644 index e988aadd38..0000000000 --- a/tests/testdata/bundle/decorators/ts_decorators.out +++ /dev/null @@ -1,49 +0,0 @@ -[WILDCARD] -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -function _ts_decorate(decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -} -function a() { - console.log("a(): evaluated"); - return (_target, _propertyKey, _descriptor)=>{ - console.log("a(): called"); - }; -} -class B { - method() { - console.log("method"); - } -} -_ts_decorate([ - a() -], B.prototype, "method", null); -function _ts_decorate1(decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -} -function Decorator() { - return function(target, propertyKey, descriptor) { - const originalFn = descriptor.value; - descriptor.value = async function(...args) { - return await originalFn.apply(this, args); - }; - return descriptor; - }; -} -class SomeClass { - async test() {} -} -_ts_decorate1([ - Decorator() -], SomeClass.prototype, "test", null); -new SomeClass().test(); -new B().method(); -[WILDCARD] \ No newline at end of file diff --git a/tests/testdata/bundle/decorators/ts_decorators.ts b/tests/testdata/bundle/decorators/ts_decorators.ts deleted file mode 100644 index 61299bccf2..0000000000 --- a/tests/testdata/bundle/decorators/ts_decorators.ts +++ /dev/null @@ -1,25 +0,0 @@ -// deno-lint-ignore-file - -import { B } from "../../subdir/more_decorators.ts"; - -function Decorator() { - return function ( - target: Record, - propertyKey: string, - descriptor: TypedPropertyDescriptor, - ) { - const originalFn: Function = descriptor.value as Function; - descriptor.value = async function (...args: any[]) { - return await originalFn.apply(this, args); - }; - return descriptor; - }; -} - -class SomeClass { - @Decorator() - async test() {} -} - -new SomeClass().test(); -new B().method(); diff --git a/tests/testdata/bundle/dynamic_import.ts b/tests/testdata/bundle/dynamic_import.ts deleted file mode 100644 index d8c7d08ec5..0000000000 --- a/tests/testdata/bundle/dynamic_import.ts +++ /dev/null @@ -1,3 +0,0 @@ -const mod1 = await import("http://localhost:4545/subdir/mod1.ts"); - -mod1.printHello3(); diff --git a/tests/testdata/bundle/file_extensions/js_without_extension.out b/tests/testdata/bundle/file_extensions/js_without_extension.out deleted file mode 100644 index 0273e6207f..0000000000 --- a/tests/testdata/bundle/file_extensions/js_without_extension.out +++ /dev/null @@ -1,8 +0,0 @@ -[WILDCARD] -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -"hello"; -console.log("executing javascript with no extension"); - diff --git a/tests/testdata/bundle/file_extensions/ts_without_extension.out b/tests/testdata/bundle/file_extensions/ts_without_extension.out deleted file mode 100644 index 39e355d146..0000000000 --- a/tests/testdata/bundle/file_extensions/ts_without_extension.out +++ /dev/null @@ -1,7 +0,0 @@ -[WILDCARD] -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -console.log("executing typescript with no extension"); - diff --git a/tests/testdata/bundle/file_tests-fixture01.ts b/tests/testdata/bundle/file_tests-fixture01.ts deleted file mode 100644 index 3598d0298e..0000000000 --- a/tests/testdata/bundle/file_tests-fixture01.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as a from "./subdir/a.ts"; - -console.log(a); diff --git a/tests/testdata/bundle/file_tests-fixture02.ts b/tests/testdata/bundle/file_tests-fixture02.ts deleted file mode 100644 index 0cd2913299..0000000000 --- a/tests/testdata/bundle/file_tests-fixture02.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as b from "./subdir/b.ts"; - -console.log(b.b); // "b" -console.log(b.c); // { c: "c", default: class C } diff --git a/tests/testdata/bundle/file_tests-fixture03.ts b/tests/testdata/bundle/file_tests-fixture03.ts deleted file mode 100644 index 78365ce13f..0000000000 --- a/tests/testdata/bundle/file_tests-fixture03.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { d } from "./subdir/d.ts"; - -console.log(d); diff --git a/tests/testdata/bundle/file_tests-fixture04.ts b/tests/testdata/bundle/file_tests-fixture04.ts deleted file mode 100644 index 590f4fef92..0000000000 --- a/tests/testdata/bundle/file_tests-fixture04.ts +++ /dev/null @@ -1,3 +0,0 @@ -const a = await import("./subdir/a.ts"); - -console.log(a); diff --git a/tests/testdata/bundle/file_tests-fixture05.ts b/tests/testdata/bundle/file_tests-fixture05.ts deleted file mode 100644 index 19541ce59b..0000000000 --- a/tests/testdata/bundle/file_tests-fixture05.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { a } from "./subdir/e.ts"; - -console.log(a); diff --git a/tests/testdata/bundle/file_tests-fixture06.ts b/tests/testdata/bundle/file_tests-fixture06.ts deleted file mode 100644 index 3d94332df9..0000000000 --- a/tests/testdata/bundle/file_tests-fixture06.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { isMain, modUrl } from "./subdir/f.ts"; - -console.log(isMain, modUrl); -console.log(import.meta.main, import.meta.url); diff --git a/tests/testdata/bundle/file_tests-fixture07.ts b/tests/testdata/bundle/file_tests-fixture07.ts deleted file mode 100644 index 0475a6c531..0000000000 --- a/tests/testdata/bundle/file_tests-fixture07.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { G } from "./subdir/g.ts"; -import { H } from "./subdir/h.ts"; - -console.log(new G(true), new H(true)); diff --git a/tests/testdata/bundle/file_tests-fixture08.ts b/tests/testdata/bundle/file_tests-fixture08.ts deleted file mode 100644 index 6af5d172e9..0000000000 --- a/tests/testdata/bundle/file_tests-fixture08.ts +++ /dev/null @@ -1 +0,0 @@ -export * as a from "./subdir/a.ts"; diff --git a/tests/testdata/bundle/file_tests-fixture09.ts b/tests/testdata/bundle/file_tests-fixture09.ts deleted file mode 100644 index 30ba983ee1..0000000000 --- a/tests/testdata/bundle/file_tests-fixture09.ts +++ /dev/null @@ -1 +0,0 @@ -export { a } from "./subdir/k.ts"; diff --git a/tests/testdata/bundle/file_tests-fixture10.ts b/tests/testdata/bundle/file_tests-fixture10.ts deleted file mode 100644 index bec555da8a..0000000000 --- a/tests/testdata/bundle/file_tests-fixture10.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { a as defaultA } from "./subdir/l.ts"; - -const o: { a?: string } = {}; - -const { a = defaultA } = o; - -console.log(a); diff --git a/tests/testdata/bundle/file_tests-fixture11.ts b/tests/testdata/bundle/file_tests-fixture11.ts deleted file mode 100644 index 1c361438f3..0000000000 --- a/tests/testdata/bundle/file_tests-fixture11.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { a as defaultA, O } from "./subdir/m.ts"; -export { O } from "./subdir/m.ts"; - -interface AOptions { - a?(); - c?: O; -} - -class A { - #a: () => void; - #c?: O; - constructor(o: AOptions = {}) { - const { - a = defaultA, - c, - } = o; - this.#a = a; - this.#c = c; - } - - a() { - this.#a(); - } - - c() { - console.log(this.#c); - } -} - -const a = new A(); -a.a(); -a.c(); diff --git a/tests/testdata/bundle/file_tests-fixture12.ts b/tests/testdata/bundle/file_tests-fixture12.ts deleted file mode 100644 index 32b9566bd4..0000000000 --- a/tests/testdata/bundle/file_tests-fixture12.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { a } from "./subdir/p.ts"; - -function b() { - a(); -} - -b(); diff --git a/tests/testdata/bundle/file_tests-fixture13.ts b/tests/testdata/bundle/file_tests-fixture13.ts deleted file mode 100644 index 7dc13534c1..0000000000 --- a/tests/testdata/bundle/file_tests-fixture13.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { D, d } from "./subdir/q.ts"; - -class A { - private s: D = d(); - - a() { - this.s.resolve(); - } -} - -new A(); diff --git a/tests/testdata/bundle/file_tests-fixture14.ts b/tests/testdata/bundle/file_tests-fixture14.ts deleted file mode 100644 index aa8eef1b88..0000000000 --- a/tests/testdata/bundle/file_tests-fixture14.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @deno-types="https://deno.land/x/lib/mod.d.ts" -import * as lib from "https://deno.land/x/lib/mod.js"; - -console.log(lib); diff --git a/tests/testdata/bundle/file_tests-fixture15.ts b/tests/testdata/bundle/file_tests-fixture15.ts deleted file mode 100644 index c1dd3bc894..0000000000 --- a/tests/testdata/bundle/file_tests-fixture15.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function getIndex(c: string): number { - return "\x00\r\n\x85\u2028\u2029".indexOf(c); -} diff --git a/tests/testdata/bundle/file_tests-fixture16.ts b/tests/testdata/bundle/file_tests-fixture16.ts deleted file mode 100644 index 5d0b05e92a..0000000000 --- a/tests/testdata/bundle/file_tests-fixture16.ts +++ /dev/null @@ -1,6 +0,0 @@ -// todo(dsherret): use ./subdir/a.ts once fixtures are restored -export { a as test1 } from "./file_tests-fixture16_2.ts"; -export { a as test2 } from "./file_tests-fixture16_2.ts"; -import { a } from "./file_tests-fixture16_2.ts"; - -console.log(a); diff --git a/tests/testdata/bundle/file_tests-fixture16_2.ts b/tests/testdata/bundle/file_tests-fixture16_2.ts deleted file mode 100644 index 7115949c9d..0000000000 --- a/tests/testdata/bundle/file_tests-fixture16_2.ts +++ /dev/null @@ -1,2 +0,0 @@ -// todo(dsherret): delete this and use ./subdir/a.ts in the file once fixtures are restored -export const a = "a"; diff --git a/tests/testdata/bundle/file_tests-subdir-a.ts b/tests/testdata/bundle/file_tests-subdir-a.ts deleted file mode 100644 index 9233cce2f0..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-a.ts +++ /dev/null @@ -1 +0,0 @@ -export const a = "a"; diff --git a/tests/testdata/bundle/file_tests-subdir-b.ts b/tests/testdata/bundle/file_tests-subdir-b.ts deleted file mode 100644 index 1cf751c225..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-b.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as c from "./c.ts"; - -export const b = "b"; diff --git a/tests/testdata/bundle/file_tests-subdir-c.ts b/tests/testdata/bundle/file_tests-subdir-c.ts deleted file mode 100644 index 7cc01f9932..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-c.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const c = "c"; -export default class C {} diff --git a/tests/testdata/bundle/file_tests-subdir-d.ts b/tests/testdata/bundle/file_tests-subdir-d.ts deleted file mode 100644 index 9f1ba7f673..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { a } from "./a.ts"; - -export const d = { a }; diff --git a/tests/testdata/bundle/file_tests-subdir-e.ts b/tests/testdata/bundle/file_tests-subdir-e.ts deleted file mode 100644 index 55e8e0e180..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-e.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./a.ts"; diff --git a/tests/testdata/bundle/file_tests-subdir-f.ts b/tests/testdata/bundle/file_tests-subdir-f.ts deleted file mode 100644 index 8bc8d9bf4f..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-f.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const isMain = import.meta.main; -export const modUrl = import.meta.url; diff --git a/tests/testdata/bundle/file_tests-subdir-g.ts b/tests/testdata/bundle/file_tests-subdir-g.ts deleted file mode 100644 index 3eb4cd3cc2..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-g.ts +++ /dev/null @@ -1,12 +0,0 @@ -const g: number[] = []; - -export class G { - #g!: number[]; - constructor(shared: boolean) { - if (shared) { - this.#g = g; - } else { - this.#g = []; - } - } -} diff --git a/tests/testdata/bundle/file_tests-subdir-h.ts b/tests/testdata/bundle/file_tests-subdir-h.ts deleted file mode 100644 index 9c86dd5c55..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-h.ts +++ /dev/null @@ -1,12 +0,0 @@ -const g: number[] = []; - -export class H { - #g!: number[]; - constructor(shared: boolean) { - if (shared) { - this.#g = g; - } else { - this.#g = []; - } - } -} diff --git a/tests/testdata/bundle/file_tests-subdir-i.ts b/tests/testdata/bundle/file_tests-subdir-i.ts deleted file mode 100644 index 4ad9ce4498..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-i.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function a(...d: string[]): string { - return d.join(" "); -} diff --git a/tests/testdata/bundle/file_tests-subdir-j.ts b/tests/testdata/bundle/file_tests-subdir-j.ts deleted file mode 100644 index ac7bce0ea5..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-j.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function a(...d: string[]): string { - return d.join("/"); -} diff --git a/tests/testdata/bundle/file_tests-subdir-k.ts b/tests/testdata/bundle/file_tests-subdir-k.ts deleted file mode 100644 index 1b8a533f13..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-k.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as _i from "./i.ts"; -import * as _j from "./j.ts"; - -const k = globalThis.value ? _i : _j; - -export const i = _i; -export const j = _j; - -export const { - a, -} = k; diff --git a/tests/testdata/bundle/file_tests-subdir-l.ts b/tests/testdata/bundle/file_tests-subdir-l.ts deleted file mode 100644 index d767e6ad09..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-l.ts +++ /dev/null @@ -1 +0,0 @@ -export { a } from "./a.ts"; diff --git a/tests/testdata/bundle/file_tests-subdir-m.ts b/tests/testdata/bundle/file_tests-subdir-m.ts deleted file mode 100644 index 21e86d07ce..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-m.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { a } from "./n.ts"; -export { O } from "./o.ts"; diff --git a/tests/testdata/bundle/file_tests-subdir-n.ts b/tests/testdata/bundle/file_tests-subdir-n.ts deleted file mode 100644 index ac3c370051..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-n.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function a() { - console.log("a"); -} diff --git a/tests/testdata/bundle/file_tests-subdir-o.ts b/tests/testdata/bundle/file_tests-subdir-o.ts deleted file mode 100644 index ab9753fea8..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-o.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum O { - A, - B, - C, -} diff --git a/tests/testdata/bundle/file_tests-subdir-p.ts b/tests/testdata/bundle/file_tests-subdir-p.ts deleted file mode 100644 index 19b486f71d..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-p.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./i.ts"; diff --git a/tests/testdata/bundle/file_tests-subdir-q.ts b/tests/testdata/bundle/file_tests-subdir-q.ts deleted file mode 100644 index eebe0a38bb..0000000000 --- a/tests/testdata/bundle/file_tests-subdir-q.ts +++ /dev/null @@ -1,13 +0,0 @@ -// deno-lint-ignore-file -export interface D { - resolve: any; - reject: any; -} - -export function d(): D { - let methods; - const promise = new Promise((resolve, reject) => { - methods = { resolve, reject }; - }); - return Object.assign(promise, methods); -} diff --git a/tests/testdata/bundle/fixture01.out b/tests/testdata/bundle/fixture01.out deleted file mode 100644 index a825140b77..0000000000 --- a/tests/testdata/bundle/fixture01.out +++ /dev/null @@ -1,7 +0,0 @@ -const a = "a"; -const mod = function() { - return { - a: a - }; -}(); -console.log(mod); diff --git a/tests/testdata/bundle/fixture02.out b/tests/testdata/bundle/fixture02.out deleted file mode 100644 index 5c502e2f0a..0000000000 --- a/tests/testdata/bundle/fixture02.out +++ /dev/null @@ -1,12 +0,0 @@ -const c = "c"; -class C { -} -const mod = function() { - return { - default: C, - c: c - }; -}(); -const b = "b"; -console.log(b); -console.log(mod); diff --git a/tests/testdata/bundle/fixture03.out b/tests/testdata/bundle/fixture03.out deleted file mode 100644 index 524e77abbb..0000000000 --- a/tests/testdata/bundle/fixture03.out +++ /dev/null @@ -1,5 +0,0 @@ -const a = "a"; -const d = { - a -}; -console.log(d); diff --git a/tests/testdata/bundle/fixture04.out b/tests/testdata/bundle/fixture04.out deleted file mode 100644 index 37869205b8..0000000000 --- a/tests/testdata/bundle/fixture04.out +++ /dev/null @@ -1,2 +0,0 @@ -const a = await import("./subdir/a.ts"); -console.log(a); diff --git a/tests/testdata/bundle/fixture05.out b/tests/testdata/bundle/fixture05.out deleted file mode 100644 index 1289cca5f6..0000000000 --- a/tests/testdata/bundle/fixture05.out +++ /dev/null @@ -1,2 +0,0 @@ -const a = "a"; -console.log(a); diff --git a/tests/testdata/bundle/fixture06.out b/tests/testdata/bundle/fixture06.out deleted file mode 100644 index 47288d5e43..0000000000 --- a/tests/testdata/bundle/fixture06.out +++ /dev/null @@ -1,12 +0,0 @@ -const importMeta = { - url: "file:///tests/subdir/f.ts", - main: false -}; -const isMain = importMeta.main; -const modUrl = importMeta.url; -const importMeta1 = { - url: "file:///tests/fixture06.ts", - main: import.meta.main -}; -console.log(isMain, modUrl); -console.log(importMeta1.main, importMeta1.url); diff --git a/tests/testdata/bundle/fixture07.out b/tests/testdata/bundle/fixture07.out deleted file mode 100644 index 39e6a11e8f..0000000000 --- a/tests/testdata/bundle/fixture07.out +++ /dev/null @@ -1,23 +0,0 @@ -const g = []; -class G { - #g; - constructor(shared){ - if (shared) { - this.#g = g; - } else { - this.#g = []; - } - } -} -const g1 = []; -class H { - #g; - constructor(shared1){ - if (shared1) { - this.#g = g1; - } else { - this.#g = []; - } - } -} -console.log(new G(true), new H(true)); diff --git a/tests/testdata/bundle/fixture08.out b/tests/testdata/bundle/fixture08.out deleted file mode 100644 index bfe40aa37c..0000000000 --- a/tests/testdata/bundle/fixture08.out +++ /dev/null @@ -1,7 +0,0 @@ -const a1 = "a"; -const mod = function() { - return { - a: a1 - }; -}(); -export { mod as a }; diff --git a/tests/testdata/bundle/fixture09.out b/tests/testdata/bundle/fixture09.out deleted file mode 100644 index e06cc92dec..0000000000 --- a/tests/testdata/bundle/fixture09.out +++ /dev/null @@ -1,19 +0,0 @@ -function a3(...d) { - return d.join(" "); -} -const mod = function() { - return { - a: a3 - }; -}(); -function a1(...d) { - return d.join("/"); -} -const mod1 = function() { - return { - a: a1 - }; -}(); -const k = globalThis.value ? mod : mod1; -const { a: a2 , } = k; -export { a2 as a }; diff --git a/tests/testdata/bundle/fixture10.out b/tests/testdata/bundle/fixture10.out deleted file mode 100644 index 5491e5e7f2..0000000000 --- a/tests/testdata/bundle/fixture10.out +++ /dev/null @@ -1,5 +0,0 @@ -const a = "a"; -const o = { -}; -const { a: a1 = a } = o; -console.log(a1); diff --git a/tests/testdata/bundle/fixture11.out b/tests/testdata/bundle/fixture11.out deleted file mode 100644 index 4f333a513f..0000000000 --- a/tests/testdata/bundle/fixture11.out +++ /dev/null @@ -1,30 +0,0 @@ -function a() { - console.log("a"); -} -var O1; -(function(O) { - O[O["A"] = 0] = "A"; - O[O["B"] = 1] = "B"; - O[O["C"] = 2] = "C"; -})(O1 || (O1 = { -})); -export { O1 as O }; -class A { - #a; - #c; - constructor(o = { - }){ - const { a: a1 = a , c , } = o; - this.#a = a1; - this.#c = c; - } - a() { - this.#a(); - } - c() { - console.log(this.#c); - } -} -const a2 = new A(); -a2.a(); -a2.c(); diff --git a/tests/testdata/bundle/fixture12.out b/tests/testdata/bundle/fixture12.out deleted file mode 100644 index 64e2d6cdba..0000000000 --- a/tests/testdata/bundle/fixture12.out +++ /dev/null @@ -1,7 +0,0 @@ -function a(...d) { - return d.join(" "); -} -function b() { - a(); -} -b(); diff --git a/tests/testdata/bundle/fixture13.out b/tests/testdata/bundle/fixture13.out deleted file mode 100644 index 1c7a8c9919..0000000000 --- a/tests/testdata/bundle/fixture13.out +++ /dev/null @@ -1,17 +0,0 @@ -function d() { - let methods; - const promise = new Promise((resolve, reject)=>{ - methods = { - resolve, - reject - }; - }); - return Object.assign(promise, methods); -} -class A { - s = d(); - a() { - this.s.resolve(); - } -} -new A(); diff --git a/tests/testdata/bundle/fixture14.out b/tests/testdata/bundle/fixture14.out deleted file mode 100644 index 392bb6478b..0000000000 --- a/tests/testdata/bundle/fixture14.out +++ /dev/null @@ -1,2 +0,0 @@ -const mod = []; -console.log(mod); diff --git a/tests/testdata/bundle/fixture15.out b/tests/testdata/bundle/fixture15.out deleted file mode 100644 index dc72fdeff6..0000000000 --- a/tests/testdata/bundle/fixture15.out +++ /dev/null @@ -1,4 +0,0 @@ -function getIndex1(c) { - return "\x00\r\n\x85\u2028\u2029".indexOf(c); -} -export { getIndex1 as getIndex }; diff --git a/tests/testdata/bundle/fixture16.out b/tests/testdata/bundle/fixture16.out deleted file mode 100644 index 5e21c2a718..0000000000 --- a/tests/testdata/bundle/fixture16.out +++ /dev/null @@ -1,6 +0,0 @@ -[WILDCARD] -const a = "a"; -export { a as test1 }; -export { a as test2 }; -console.log(a); - diff --git a/tests/testdata/bundle/https_deno.land-x-lib-a.ts b/tests/testdata/bundle/https_deno.land-x-lib-a.ts deleted file mode 100644 index a0a6f8e948..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-a.ts +++ /dev/null @@ -1 +0,0 @@ -export const a: string[] = []; diff --git a/tests/testdata/bundle/https_deno.land-x-lib-b.js b/tests/testdata/bundle/https_deno.land-x-lib-b.js deleted file mode 100644 index 13cacdd8b0..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-b.js +++ /dev/null @@ -1 +0,0 @@ -export const b = []; diff --git a/tests/testdata/bundle/https_deno.land-x-lib-c.d.ts b/tests/testdata/bundle/https_deno.land-x-lib-c.d.ts deleted file mode 100644 index fac988e490..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-c.d.ts +++ /dev/null @@ -1 +0,0 @@ -export const c: string[]; diff --git a/tests/testdata/bundle/https_deno.land-x-lib-c.js b/tests/testdata/bundle/https_deno.land-x-lib-c.js deleted file mode 100644 index 620ca0b66f..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-c.js +++ /dev/null @@ -1,3 +0,0 @@ -/// - -export const c = []; diff --git a/tests/testdata/bundle/https_deno.land-x-lib-mod.d.ts b/tests/testdata/bundle/https_deno.land-x-lib-mod.d.ts deleted file mode 100644 index 76ed81df0a..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-mod.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * as a from "./a.ts"; -export * as b from "./b.js"; -export * as c from "./c.js"; - -export interface A { - a: string; -} - -export const mod: A[]; diff --git a/tests/testdata/bundle/https_deno.land-x-lib-mod.js b/tests/testdata/bundle/https_deno.land-x-lib-mod.js deleted file mode 100644 index 5051620941..0000000000 --- a/tests/testdata/bundle/https_deno.land-x-lib-mod.js +++ /dev/null @@ -1,5 +0,0 @@ -export * as a from "./a.ts"; -export * as b from "./b.js"; -export * as c from "./c.js"; - -export const mod = []; diff --git a/tests/testdata/bundle/ignore_directives.test.out b/tests/testdata/bundle/ignore_directives.test.out deleted file mode 100644 index b69c2632c0..0000000000 --- a/tests/testdata/bundle/ignore_directives.test.out +++ /dev/null @@ -1,6 +0,0 @@ -[WILDCARD] -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -[WILDCARD] diff --git a/tests/testdata/bundle/import_map/import_map.json b/tests/testdata/bundle/import_map/import_map.json deleted file mode 100644 index c02f72718c..0000000000 --- a/tests/testdata/bundle/import_map/import_map.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "imports": { - "mod2": "../../subdir/subdir2/mod2.ts" - } -} diff --git a/tests/testdata/bundle/jsx.out b/tests/testdata/bundle/jsx.out deleted file mode 100644 index da83cde828..0000000000 --- a/tests/testdata/bundle/jsx.out +++ /dev/null @@ -1,9 +0,0 @@ -[WILDCARD] -const React = { - createElement () {} -}; -function app() { - return React.createElement("div", null, React.createElement("h2", null, "asdf")); -} -console.log(app); - diff --git a/tests/testdata/bundle/shebang_file.bundle.out b/tests/testdata/bundle/shebang_file.bundle.out deleted file mode 100644 index d3369bc9c7..0000000000 --- a/tests/testdata/bundle/shebang_file.bundle.out +++ /dev/null @@ -1,12 +0,0 @@ -⚠️ Warning: `deno bundle` is deprecated and will be removed in Deno 2.0. -Use an alternative bundler like "deno_emit", "esbuild" or "rollup" instead. -Bundle file:///[WILDCARD]/subdir/shebang_file.js -#!/usr/bin/env -S deno run --allow-read -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -for (const item of Deno.readDirSync(".")){ - console.log(item.name); -} - diff --git a/tests/testdata/check/jsximportsource_importmap_config/main.bundle.js b/tests/testdata/check/jsximportsource_importmap_config/main.bundle.js deleted file mode 100644 index 6f39c876eb..0000000000 --- a/tests/testdata/check/jsximportsource_importmap_config/main.bundle.js +++ /dev/null @@ -1,9 +0,0 @@ -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - -const makeParagraph = ()=>jsx("p", { - children: "A paragraph!" - }); -export { makeParagraph as makeParagraph }; - diff --git a/tests/testdata/check/missing_override.ts b/tests/testdata/check/missing_override.ts new file mode 100644 index 0000000000..b3163d484a --- /dev/null +++ b/tests/testdata/check/missing_override.ts @@ -0,0 +1,10 @@ +export class Base { + method() { + } +} + +export class Derived extends Base { + // missing override keyword + method() { + } +} diff --git a/tests/testdata/compile/node_modules_symlink_outside/main_compile_folder.out b/tests/testdata/compile/node_modules_symlink_outside/main_compile_folder.out index 2067bf1c60..1a7eb0a4f2 100644 --- a/tests/testdata/compile/node_modules_symlink_outside/main_compile_folder.out +++ b/tests/testdata/compile/node_modules_symlink_outside/main_compile_folder.out @@ -1,4 +1,4 @@ -Download http://localhost:4260/@denotest/esm-basic +Download http://localhost:4260/@denotest%2fesm-basic Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz Initialize @denotest/esm-basic@1.0.0 Check file:///[WILDCARD]/node_modules_symlink_outside/main.ts diff --git a/tests/testdata/coverage/complex_test.ts b/tests/testdata/coverage/complex_test.ts index d6e9c26910..6a711a91a0 100644 --- a/tests/testdata/coverage/complex_test.ts +++ b/tests/testdata/coverage/complex_test.ts @@ -7,32 +7,29 @@ Deno.test("complex", function () { Deno.test("sub process with stdin", async () => { // ensure launching deno run with stdin doesn't affect coverage const code = "console.log('5')"; - // deno-lint-ignore no-deprecated-deno-api - const p = await Deno.run({ - cmd: [Deno.execPath(), "run", "-"], + const command = new Deno.Command(Deno.execPath(), { + args: ["run", "-"], stdin: "piped", stdout: "piped", }); - const encoder = new TextEncoder(); - await p.stdin.write(encoder.encode(code)); - await p.stdin.close(); - const output = new TextDecoder().decode(await p.output()); - p.close(); + await using child = command.spawn(); + await ReadableStream.from([code]) + .pipeThrough(new TextEncoderStream()) + .pipeTo(child.stdin); + const { stdout } = await child.output(); + const output = new TextDecoder().decode(stdout); if (output.trim() !== "5") { throw new Error("Failed"); } }); -Deno.test("sub process with deno eval", async () => { +Deno.test("sub process with deno eval", () => { // ensure launching deno eval doesn't affect coverage const code = "console.log('5')"; - // deno-lint-ignore no-deprecated-deno-api - const p = await Deno.run({ - cmd: [Deno.execPath(), "eval", code], - stdout: "piped", - }); - const output = new TextDecoder().decode(await p.output()); - p.close(); + const { stdout } = new Deno.Command(Deno.execPath(), { + args: ["eval", code], + }).outputSync(); + const output = new TextDecoder().decode(stdout); if (output.trim() !== "5") { throw new Error("Failed"); } diff --git a/tests/testdata/doc/lint_success_json.out b/tests/testdata/doc/lint_success_json.out deleted file mode 100644 index 19f04c6a86..0000000000 --- a/tests/testdata/doc/lint_success_json.out +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "name": "Test", - "isDefault": false, - "location": { - "filename": "file:///[WILDCARD]/lint_success.ts", - "line": 2, - "col": 0, - "byteIndex": 22 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "My test class." - }, - "kind": "class", - "classDef": { - "isAbstract": false, - "constructors": [], - "properties": [ - { - "jsDoc": { - "doc": "My property." - }, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - }, - "readonly": false, - "accessibility": null, - "optional": false, - "isAbstract": false, - "isStatic": false, - "name": "prop", - "location": { - "filename": "file:///[WILDCARD]/lint_success.ts", - "line": 4, - "col": 2, - "byteIndex": 66 - } - } - ], - "indexSignatures": [], - "methods": [], - "extends": null, - "implements": [], - "typeParams": [], - "superTypeParams": [] - } - } -] diff --git a/tests/testdata/doc/referenced_private_types.out b/tests/testdata/doc/referenced_private_types.out deleted file mode 100644 index 3c91dbe153..0000000000 --- a/tests/testdata/doc/referenced_private_types.out +++ /dev/null @@ -1,12 +0,0 @@ -Defined in file:///[WILDCARD]/doc/referenced_private_types.ts:5:1 - -class MyClass - - prop: MyInterface - -Defined in file:///[WILDCARD]/doc/referenced_private_types.ts:1:1 - -private interface MyInterface - - prop?: string - diff --git a/tests/testdata/doc/types_hint.out b/tests/testdata/doc/types_hint.out deleted file mode 100644 index bfd5191a1f..0000000000 --- a/tests/testdata/doc/types_hint.out +++ /dev/null @@ -1,5 +0,0 @@ -Defined in [WILDCARD]/type_definitions/foo.d.ts:2:14 - -const foo: string - An exported value. - diff --git a/tests/testdata/doc/types_hint.ts b/tests/testdata/doc/types_hint.ts deleted file mode 100644 index bacea46db3..0000000000 --- a/tests/testdata/doc/types_hint.ts +++ /dev/null @@ -1,2 +0,0 @@ -// @deno-types="../type_definitions/foo.d.ts" -export * from "../type_definitions/foo.js"; diff --git a/tests/testdata/doc/types_ref.js b/tests/testdata/doc/types_ref.js deleted file mode 100644 index 03d8b5570f..0000000000 --- a/tests/testdata/doc/types_ref.js +++ /dev/null @@ -1,2 +0,0 @@ -/// -export const foo = "foo"; diff --git a/tests/testdata/doc/types_ref.out b/tests/testdata/doc/types_ref.out deleted file mode 100644 index bfd5191a1f..0000000000 --- a/tests/testdata/doc/types_ref.out +++ /dev/null @@ -1,5 +0,0 @@ -Defined in [WILDCARD]/type_definitions/foo.d.ts:2:14 - -const foo: string - An exported value. - diff --git a/tests/testdata/dynamic_import/permissions_blob_local.ts b/tests/testdata/dynamic_import/permissions_blob_local.ts index 9ef4158ce9..865c1777a9 100644 --- a/tests/testdata/dynamic_import/permissions_blob_local.ts +++ b/tests/testdata/dynamic_import/permissions_blob_local.ts @@ -1,4 +1,4 @@ -// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +// This file doesn't really exist, but it doesn't matter, a "NotCapable" error should be thrown. const code = `import "file:///${ Deno.build.os == "windows" ? "C:/" : "" }local_file.ts";`; diff --git a/tests/testdata/dynamic_import/permissions_blob_remote.ts b/tests/testdata/dynamic_import/permissions_blob_remote.ts index 1e2c8c21a4..569b1f84c5 100644 --- a/tests/testdata/dynamic_import/permissions_blob_remote.ts +++ b/tests/testdata/dynamic_import/permissions_blob_remote.ts @@ -1,4 +1,3 @@ -// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. const code = `import "https://example.com/some/file.ts";`; const blob = new Blob([code]); await import(URL.createObjectURL(blob)); diff --git a/tests/testdata/dynamic_import/permissions_blob_remote.ts.out b/tests/testdata/dynamic_import/permissions_blob_remote.ts.out index f436a5eb84..20b6839e4c 100644 --- a/tests/testdata/dynamic_import/permissions_blob_remote.ts.out +++ b/tests/testdata/dynamic_import/permissions_blob_remote.ts.out @@ -1,5 +1,5 @@ -error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in promise) TypeError: Requires import access to "example.com:443", run again with the --allow-import flag at blob:null/[WILDCARD]:1:8 await import(URL.createObjectURL(blob)); ^ - at async file:///[WILDCARD]/dynamic_import/permissions_blob_remote.ts:4:1 + at async file:///[WILDCARD]/dynamic_import/permissions_blob_remote.ts:3:1 diff --git a/tests/testdata/dynamic_import/permissions_data_local.ts b/tests/testdata/dynamic_import/permissions_data_local.ts index be4fc1c346..01bff7d7a2 100644 --- a/tests/testdata/dynamic_import/permissions_data_local.ts +++ b/tests/testdata/dynamic_import/permissions_data_local.ts @@ -1,4 +1,4 @@ -// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +// This file doesn't really exist, but it doesn't matter, a "NotCapable" error should be thrown. const code = `import "file:///${ Deno.build.os == "windows" ? "C:/" : "" }local_file.ts";`; diff --git a/tests/testdata/dynamic_import/permissions_data_remote.ts.out b/tests/testdata/dynamic_import/permissions_data_remote.ts.out index 00248e2778..67c8512050 100644 --- a/tests/testdata/dynamic_import/permissions_data_remote.ts.out +++ b/tests/testdata/dynamic_import/permissions_data_remote.ts.out @@ -1,4 +1,4 @@ -error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in promise) TypeError: Requires import access to "example.com:443", run again with the --allow-import flag at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8 await import(`data:application/javascript;base64,${btoa(code)}`); ^ diff --git a/tests/testdata/dynamic_import/permissions_remote_remote.ts.out b/tests/testdata/dynamic_import/permissions_remote_remote.ts.out index 0e8b0fc1f1..2676d7551f 100644 --- a/tests/testdata/dynamic_import/permissions_remote_remote.ts.out +++ b/tests/testdata/dynamic_import/permissions_remote_remote.ts.out @@ -1,4 +1,4 @@ -error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag +error: Uncaught (in promise) TypeError: Requires import access to "example.com:443", run again with the --allow-import flag at http://localhost:4545/dynamic_import/static_remote.ts:2:8 await import( ^ diff --git a/tests/testdata/fmt/fmt_with_deprecated_config.out b/tests/testdata/fmt/fmt_with_deprecated_config.out deleted file mode 100644 index 793fac1bc4..0000000000 --- a/tests/testdata/fmt/fmt_with_deprecated_config.out +++ /dev/null @@ -1,3 +0,0 @@ -Warning: "options" configuration is deprecated. Please use "flat" options instead. -Warning: "files" configuration is deprecated. Please use "include" and "exclude" instead. -Checked 2 files diff --git a/tests/testdata/fmt/with_config/deno.deprecated.jsonc b/tests/testdata/fmt/with_config/deno.deprecated.jsonc deleted file mode 100644 index e053233fd2..0000000000 --- a/tests/testdata/fmt/with_config/deno.deprecated.jsonc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "fmt": { - "files": { - "include": [ - "./subdir/" - ], - "exclude": [ - "./subdir/b.ts" - ] - }, - "options": { - "useTabs": true, - "lineWidth": 40, - "indentWidth": 8, - "singleQuote": true, - "proseWrap": "always", - "semiColons": false - } - } -} diff --git a/tests/testdata/import_attributes/dynamic_import.out b/tests/testdata/import_attributes/dynamic_import.out index 01bc76c8ad..7a7b4c91fe 100644 --- a/tests/testdata/import_attributes/dynamic_import.out +++ b/tests/testdata/import_attributes/dynamic_import.out @@ -1,3 +1,2 @@ [WILDCARD] [Module: null prototype] { default: { a: "b", c: { d: 10 } } } -[Module: null prototype] { default: { a: "b", c: { d: 10 } } } diff --git a/tests/testdata/import_attributes/dynamic_import.ts b/tests/testdata/import_attributes/dynamic_import.ts index afff52e1a7..093136fb07 100644 --- a/tests/testdata/import_attributes/dynamic_import.ts +++ b/tests/testdata/import_attributes/dynamic_import.ts @@ -1,6 +1,3 @@ const data1 = await import("./data.json", { with: { type: "json" } }); -// deno-lint-ignore no-import-assertions -const data2 = await import("./data.json", { assert: { type: "json" } }); console.log(data1); -console.log(data2); diff --git a/tests/testdata/import_attributes/json_with_shebang.ts b/tests/testdata/import_attributes/json_with_shebang.ts index 0a785210fc..9524026bce 100644 --- a/tests/testdata/import_attributes/json_with_shebang.ts +++ b/tests/testdata/import_attributes/json_with_shebang.ts @@ -1,4 +1,3 @@ -// deno-lint-ignore no-import-assertions -import json from "./json_with_shebang.json" assert { type: "json" }; +import json from "./json_with_shebang.json" with { type: "json" }; console.log(json); diff --git a/tests/testdata/import_attributes/static_import.ts b/tests/testdata/import_attributes/static_import.ts index 1538a4a2f0..f585b893f3 100644 --- a/tests/testdata/import_attributes/static_import.ts +++ b/tests/testdata/import_attributes/static_import.ts @@ -1,6 +1,5 @@ import data1 from "./data.json" with { type: "json" }; -// deno-lint-ignore no-import-assertions -import data2 from "./data.json" assert { type: "json" }; +import data2 from "./data.json" with { type: "json" }; console.log(data1); console.log(data2); diff --git a/tests/testdata/import_attributes/static_reexport.ts b/tests/testdata/import_attributes/static_reexport.ts index 81af428bed..e6175691c6 100644 --- a/tests/testdata/import_attributes/static_reexport.ts +++ b/tests/testdata/import_attributes/static_reexport.ts @@ -1 +1 @@ -export { default } from "./data.json" assert { type: "json" }; +export { default } from "./data.json" with { type: "json" }; diff --git a/tests/testdata/info/054_info_local_imports.out b/tests/testdata/info/054_info_local_imports.out deleted file mode 100644 index ee1773b76b..0000000000 --- a/tests/testdata/info/054_info_local_imports.out +++ /dev/null @@ -1,9 +0,0 @@ -local: [WILDCARD]005_more_imports.ts -type: TypeScript -dependencies: 3 unique -size: [WILDCARD] - -file://[WILDCARD]/005_more_imports.ts ([WILDCARD]) -└─┬ file://[WILDCARD]/subdir/mod1.ts ([WILDCARD]) - └─┬ file://[WILDCARD]/subdir/subdir2/mod2.ts ([WILDCARD]) - └── file://[WILDCARD]/subdir/print_hello.ts ([WILDCARD]) diff --git a/tests/testdata/lint/expected_verbose.out b/tests/testdata/lint/expected_verbose.out deleted file mode 100644 index eb8a2651ab..0000000000 --- a/tests/testdata/lint/expected_verbose.out +++ /dev/null @@ -1,3 +0,0 @@ -[WILDCARD] -Found 3 problems -Checked 3 files diff --git a/tests/testdata/node/require_esm/esm.js b/tests/testdata/node/require_esm/esm.js new file mode 100644 index 0000000000..0613f1911a --- /dev/null +++ b/tests/testdata/node/require_esm/esm.js @@ -0,0 +1 @@ +export class Test {} diff --git a/tests/testdata/node/require_esm/main.out b/tests/testdata/node/require_esm/main.out new file mode 100644 index 0000000000..aab0d5c285 --- /dev/null +++ b/tests/testdata/node/require_esm/main.out @@ -0,0 +1 @@ +[Module: null prototype] { Test: [class Test] } diff --git a/tests/testdata/node/require_esm/main.ts b/tests/testdata/node/require_esm/main.ts new file mode 100644 index 0000000000..67ac808f06 --- /dev/null +++ b/tests/testdata/node/require_esm/main.ts @@ -0,0 +1,5 @@ +import { createRequire } from "node:module"; + +const require = createRequire(import.meta.url); + +console.log(require("./esm.js")); diff --git a/tests/testdata/node/require_esm_error/main.out b/tests/testdata/node/require_esm_error/main.out deleted file mode 100644 index 3db23ff244..0000000000 --- a/tests/testdata/node/require_esm_error/main.out +++ /dev/null @@ -1,3 +0,0 @@ -error: Uncaught (in promise) Error: require() of ES Module [WILDCARD]esm.js from [WILDCARD]main.ts not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules. - at [WILDCARD] - at file:///[WILDCARD]/require_esm_error/main.ts:5:1 diff --git a/tests/testdata/npm/cjs_require_esm_error/main.out b/tests/testdata/npm/cjs_require_esm_error/main.out deleted file mode 100644 index b6ade69042..0000000000 --- a/tests/testdata/npm/cjs_require_esm_error/main.out +++ /dev/null @@ -1,2 +0,0 @@ -error: Uncaught (in promise) Error: require() of ES Module [WILDCARD]my_es_module.js from [WILDCARD]index.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules. - [WILDCARD] diff --git a/tests/testdata/npm/cjs_require_esm_error/main.ts b/tests/testdata/npm/cjs_require_esm_error/main.ts deleted file mode 100644 index 3fbb1215ad..0000000000 --- a/tests/testdata/npm/cjs_require_esm_error/main.ts +++ /dev/null @@ -1 +0,0 @@ -import "npm:@denotest/cjs-require-esm-error"; diff --git a/tests/testdata/npm/cjs_require_esm_mjs_error/main.out b/tests/testdata/npm/cjs_require_esm_mjs_error/main.out deleted file mode 100644 index e779cfaf84..0000000000 --- a/tests/testdata/npm/cjs_require_esm_mjs_error/main.out +++ /dev/null @@ -1,2 +0,0 @@ -error: Uncaught (in promise) Error: require() of ES Module [WILDCARD]esm_mjs.mjs from [WILDCARD]require_mjs.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules. - [WILDCARD] diff --git a/tests/testdata/npm/cjs_require_esm_mjs_error/main.ts b/tests/testdata/npm/cjs_require_esm_mjs_error/main.ts deleted file mode 100644 index 2121f1dbb4..0000000000 --- a/tests/testdata/npm/cjs_require_esm_mjs_error/main.ts +++ /dev/null @@ -1 +0,0 @@ -import "npm:@denotest/cjs-require-esm-error/require_mjs.js"; diff --git a/tests/testdata/npm/cjs_with_deps/main_info_json.out b/tests/testdata/npm/cjs_with_deps/main_info_json.out index fd850b8a1c..137b9f8ce5 100644 --- a/tests/testdata/npm/cjs_with_deps/main_info_json.out +++ b/tests/testdata/npm/cjs_with_deps/main_info_json.out @@ -1,4 +1,5 @@ { + "version": 1, "roots": [ "file://[WILDCARD]/main.js" ], @@ -42,8 +43,6 @@ } ], "local": "[WILDCARD]main.js", - "emit": null, - "map": null, "size": 325, "mediaType": "JavaScript", "specifier": "[WILDCARD]/main.js" diff --git a/tests/testdata/npm/compare_globals/main.out b/tests/testdata/npm/compare_globals/main.out deleted file mode 100644 index 9c9c2203aa..0000000000 --- a/tests/testdata/npm/compare_globals/main.out +++ /dev/null @@ -1,32 +0,0 @@ -[UNORDERED_START] -Download http://localhost:4260/@types/node -Download http://localhost:4260/@denotest/globals -[UNORDERED_END] -[UNORDERED_START] -Download http://localhost:4260/@denotest/globals/1.0.0.tgz -Download http://localhost:4260/@types/node/node-18.16.19.tgz -[UNORDERED_END] -Check file:///[WILDCARD]/npm/compare_globals/main.ts -true -true -[] -false -function -function -function -undefined -false -false -true -true -true -true -true -true -false -false -false -false -bar -bar -true diff --git a/tests/testdata/npm/d_ext/main.out b/tests/testdata/npm/d_ext/main.out deleted file mode 100644 index 5c22a76a0c..0000000000 --- a/tests/testdata/npm/d_ext/main.out +++ /dev/null @@ -1,3 +0,0 @@ -Download http://localhost:4260/@denotest/d-ext -Download http://localhost:4260/@denotest/d-ext/1.0.0.tgz -Check file:///[WILDCARD]/npm/d_ext/main.ts diff --git a/tests/testdata/npm/deno_run_cowsay_no_permissions.out b/tests/testdata/npm/deno_run_cowsay_no_permissions.out index 837394d495..6434620e2e 100644 --- a/tests/testdata/npm/deno_run_cowsay_no_permissions.out +++ b/tests/testdata/npm/deno_run_cowsay_no_permissions.out @@ -1,2 +1,2 @@ -error: Uncaught PermissionDenied: Requires read access to , specify the required permissions during compilation using `deno compile --allow-read` +error: Uncaught NotCapable: Requires read access to , specify the required permissions during compilation using `deno compile --allow-read` [WILDCARD] diff --git a/tests/testdata/npm/invalid_package_name/main.out b/tests/testdata/npm/invalid_package_name/main.out deleted file mode 100644 index b4a421bd7f..0000000000 --- a/tests/testdata/npm/invalid_package_name/main.out +++ /dev/null @@ -1,2 +0,0 @@ -error: Invalid package specifier 'npm:@foo'. Did not contain a valid package name. - at [WILDCARD]/invalid_package_name/main.js:1:22 diff --git a/tests/testdata/npm/local_dir_resolves_symlinks/index.out b/tests/testdata/npm/local_dir_resolves_symlinks/index.out deleted file mode 100644 index 25d44c6b8e..0000000000 --- a/tests/testdata/npm/local_dir_resolves_symlinks/index.out +++ /dev/null @@ -1,2 +0,0 @@ -Download [WILDCARD] -true it works diff --git a/tests/testdata/npm/peer_deps_with_copied_folders/main.out b/tests/testdata/npm/peer_deps_with_copied_folders/main.out index 3c133bcde4..b7a5835577 100644 --- a/tests/testdata/npm/peer_deps_with_copied_folders/main.out +++ b/tests/testdata/npm/peer_deps_with_copied_folders/main.out @@ -1,7 +1,7 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/peer-dep-test-child -Download http://localhost:4260/@denotest/peer-dep-test-grandchild -Download http://localhost:4260/@denotest/peer-dep-test-peer +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz diff --git a/tests/testdata/npm/peer_deps_with_copied_folders/main_info_json.out b/tests/testdata/npm/peer_deps_with_copied_folders/main_info_json.out index a4306a6d5f..d87496d6d5 100644 --- a/tests/testdata/npm/peer_deps_with_copied_folders/main_info_json.out +++ b/tests/testdata/npm/peer_deps_with_copied_folders/main_info_json.out @@ -1,4 +1,5 @@ { + "version": 1, "roots": [ "[WILDCARD]/npm/peer_deps_with_copied_folders/main.ts" ], @@ -42,8 +43,6 @@ } ], "local": "[WILDCARD]main.ts", - "emit": null, - "map": null, "size": 171, "mediaType": "TypeScript", "specifier": "file://[WILDCARD]/main.ts" diff --git a/tests/testdata/npm/peer_deps_with_copied_folders/main_node_modules_reload.out b/tests/testdata/npm/peer_deps_with_copied_folders/main_node_modules_reload.out index 9c81452118..18d7f7865b 100644 --- a/tests/testdata/npm/peer_deps_with_copied_folders/main_node_modules_reload.out +++ b/tests/testdata/npm/peer_deps_with_copied_folders/main_node_modules_reload.out @@ -1,7 +1,7 @@ [UNORDERED_START] -Download http://localhost:4260/@denotest/peer-dep-test-child -Download http://localhost:4260/@denotest/peer-dep-test-grandchild -Download http://localhost:4260/@denotest/peer-dep-test-peer +Download http://localhost:4260/@denotest%2fpeer-dep-test-child +Download http://localhost:4260/@denotest%2fpeer-dep-test-grandchild +Download http://localhost:4260/@denotest%2fpeer-dep-test-peer [UNORDERED_END] [UNORDERED_START] Download http://localhost:4260/@denotest/peer-dep-test-child/1.0.0.tgz diff --git a/tests/testdata/npm/remote_npm_specifier/main.ts b/tests/testdata/npm/remote_npm_specifier/main.ts deleted file mode 100644 index 20a99b6883..0000000000 --- a/tests/testdata/npm/remote_npm_specifier/main.ts +++ /dev/null @@ -1 +0,0 @@ -import "http://localhost:4545/npm/remote_npm_specifier/remote.ts"; diff --git a/tests/testdata/npm/run_existing_npm_package/main.out b/tests/testdata/npm/run_existing_npm_package/main.out index 147ed6a995..373059db53 100644 --- a/tests/testdata/npm/run_existing_npm_package/main.out +++ b/tests/testdata/npm/run_existing_npm_package/main.out @@ -1,3 +1,3 @@ -Download http://localhost:4260/@denotest/bin +Download http://localhost:4260/@denotest%2fbin Download http://localhost:4260/@denotest/bin/0.5.0.tgz Initialize @denotest/bin@0.5.0 diff --git a/tests/testdata/package_json/invalid_value/error.ts.out b/tests/testdata/package_json/invalid_value/error.ts.out deleted file mode 100644 index 80893ede0a..0000000000 --- a/tests/testdata/package_json/invalid_value/error.ts.out +++ /dev/null @@ -1,4 +0,0 @@ -error: Invalid npm version requirement. Unexpected character. - invalid stuff that won't parse - ~ - at file:///[WILDCARD]/error.ts:2:23 diff --git a/tests/testdata/package_json/invalid_value/task.out b/tests/testdata/package_json/invalid_value/task.out deleted file mode 100644 index 79249d1757..0000000000 --- a/tests/testdata/package_json/invalid_value/task.out +++ /dev/null @@ -1,2 +0,0 @@ -Task test echo 1 -1 diff --git a/tests/testdata/run/025_hrtime.ts b/tests/testdata/run/025_hrtime.ts deleted file mode 100644 index b69d614885..0000000000 --- a/tests/testdata/run/025_hrtime.ts +++ /dev/null @@ -1,5 +0,0 @@ -window.onload = async () => { - console.log(performance.now() % 2 !== 0); - await Deno.permissions.revoke({ name: "hrtime" }); - console.log(performance.now() % 2 === 0); -}; diff --git a/tests/testdata/run/025_hrtime.ts.out b/tests/testdata/run/025_hrtime.ts.out deleted file mode 100644 index bb101b641b..0000000000 --- a/tests/testdata/run/025_hrtime.ts.out +++ /dev/null @@ -1,2 +0,0 @@ -true -true diff --git a/tests/testdata/run/025_reload_js_type_error.js b/tests/testdata/run/025_reload_js_type_error.js index 3b7c23cc99..660626a684 100644 --- a/tests/testdata/run/025_reload_js_type_error.js +++ b/tests/testdata/run/025_reload_js_type_error.js @@ -1,6 +1,6 @@ // deno-lint-ignore-file // There was a bug where if this was executed with --reload it would throw a // type error. -window.test = null; +globalThis.test = null; test = console; test.log("hello"); diff --git a/tests/testdata/run/056_make_temp_file_write_perm.out b/tests/testdata/run/056_make_temp_file_write_perm.out deleted file mode 100644 index c56aae43f6..0000000000 --- a/tests/testdata/run/056_make_temp_file_write_perm.out +++ /dev/null @@ -1 +0,0 @@ -good [WILDCARD]subdir[WILDCARD] diff --git a/tests/testdata/run/056_make_temp_file_write_perm.ts b/tests/testdata/run/056_make_temp_file_write_perm.ts deleted file mode 100644 index c0deda8a25..0000000000 --- a/tests/testdata/run/056_make_temp_file_write_perm.ts +++ /dev/null @@ -1,9 +0,0 @@ -const path = await Deno.makeTempFile({ dir: `subdir` }); -try { - if (!path.match(/^subdir[/\\][^/\\]+/)) { - throw Error("bad " + path); - } - console.log("good", path); -} finally { - await Deno.remove(path); -} diff --git a/tests/testdata/run/058_tasks_microtasks_close.ts b/tests/testdata/run/058_tasks_microtasks_close.ts index 38e1560441..df6f85ea0a 100644 --- a/tests/testdata/run/058_tasks_microtasks_close.ts +++ b/tests/testdata/run/058_tasks_microtasks_close.ts @@ -9,7 +9,7 @@ setTimeout(() => { Promise.resolve().then(() => { console.log("promise 1"); }); -window.close(); +globalThis.close(); console.log("sync 2"); setTimeout(() => { console.log("setTimeout 2"); diff --git a/tests/testdata/run/059_fs_relative_path_perm.ts.out b/tests/testdata/run/059_fs_relative_path_perm.ts.out index b23628cd66..0d04122083 100644 --- a/tests/testdata/run/059_fs_relative_path_perm.ts.out +++ b/tests/testdata/run/059_fs_relative_path_perm.ts.out @@ -1,4 +1,4 @@ -[WILDCARD]error: Uncaught (in promise) PermissionDenied: Requires read access to "non-existent", run again with the --allow-read flag +[WILDCARD]error: Uncaught (in promise) NotCapable: Requires read access to "non-existent", run again with the --allow-read flag Deno.readFileSync("non-existent"); ^ at [WILDCARD] diff --git a/tests/testdata/run/078_unload_on_exit.ts b/tests/testdata/run/078_unload_on_exit.ts index 43d33eb253..aaa80c578a 100644 --- a/tests/testdata/run/078_unload_on_exit.ts +++ b/tests/testdata/run/078_unload_on_exit.ts @@ -1,4 +1,4 @@ -window.onunload = () => { +globalThis.onunload = () => { console.log("onunload is called"); // This second exit call doesn't trigger unload event, // and therefore actually stops the process. diff --git a/tests/testdata/run/089_run_allow_list.ts.out b/tests/testdata/run/089_run_allow_list.ts.out index 68a4a2ac57..8b07d6e048 100644 --- a/tests/testdata/run/089_run_allow_list.ts.out +++ b/tests/testdata/run/089_run_allow_list.ts.out @@ -1,3 +1,3 @@ -[WILDCARD]PermissionDenied: Requires run access to "ls", run again with the --allow-run flag +[WILDCARD]NotCapable: Requires run access to "ls", run again with the --allow-run flag [WILDCARD] true diff --git a/tests/testdata/run/add.cjs b/tests/testdata/run/add.cjs new file mode 100644 index 0000000000..2a886fbc18 --- /dev/null +++ b/tests/testdata/run/add.cjs @@ -0,0 +1,3 @@ +module.exports.add = function (a, b) { + return a + b; +}; diff --git a/tests/testdata/run/checkjs.tsconfig.json b/tests/testdata/run/checkjs.tsconfig.json index 46d96db9ed..08ac60b6cd 100644 --- a/tests/testdata/run/checkjs.tsconfig.json +++ b/tests/testdata/run/checkjs.tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "allowJs": true, "checkJs": true } } diff --git a/tests/testdata/run/cjs_imports/commonjs.cjs b/tests/testdata/run/cjs_imports/commonjs.cjs deleted file mode 100644 index accefceba6..0000000000 --- a/tests/testdata/run/cjs_imports/commonjs.cjs +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello World"); diff --git a/tests/testdata/run/cjs_imports/main.out b/tests/testdata/run/cjs_imports/main.out deleted file mode 100644 index 557db03de9..0000000000 --- a/tests/testdata/run/cjs_imports/main.out +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/testdata/run/cjs_imports/main.ts b/tests/testdata/run/cjs_imports/main.ts deleted file mode 100644 index d8b77c22eb..0000000000 --- a/tests/testdata/run/cjs_imports/main.ts +++ /dev/null @@ -1 +0,0 @@ -import "./commonjs.cjs"; diff --git a/tests/testdata/run/config_json_import.ts b/tests/testdata/run/config_json_import.ts index 9cf1cceaa7..7141f14950 100644 --- a/tests/testdata/run/config_json_import.ts +++ b/tests/testdata/run/config_json_import.ts @@ -1,2 +1,2 @@ -import config from "../jsx/deno-jsx.json" assert { type: "json" }; +import config from "../jsx/deno-jsx.json" with { type: "json" }; console.log(config); diff --git a/tests/testdata/run/decorators/experimental/ts/main.out b/tests/testdata/run/decorators/experimental/ts/main.out index ee77417cf2..ea64fbaa63 100644 --- a/tests/testdata/run/decorators/experimental/ts/main.out +++ b/tests/testdata/run/decorators/experimental/ts/main.out @@ -1,2 +1,3 @@ +Warning experimentalDecorators compiler option is deprecated and may be removed at any time Check [WILDCARD] SomeClass { someField: "asdf" } diff --git a/tests/testdata/run/delete_window.js b/tests/testdata/run/delete_window.js deleted file mode 100644 index f2f16820d8..0000000000 --- a/tests/testdata/run/delete_window.js +++ /dev/null @@ -1 +0,0 @@ -console.log(delete globalThis.window); diff --git a/tests/testdata/run/deny_all_permission_args.js b/tests/testdata/run/deny_all_permission_args.js index b0ca864fbd..c63d2c362c 100644 --- a/tests/testdata/run/deny_all_permission_args.js +++ b/tests/testdata/run/deny_all_permission_args.js @@ -5,4 +5,3 @@ console.log(Deno.permissions.querySync({ name: "ffi" })); console.log(Deno.permissions.querySync({ name: "run" })); console.log(Deno.permissions.querySync({ name: "sys" })); console.log(Deno.permissions.querySync({ name: "net" })); -console.log(Deno.permissions.querySync({ name: "hrtime" })); diff --git a/tests/testdata/run/deny_all_permission_args.out b/tests/testdata/run/deny_all_permission_args.out index 2a5228d620..de6f687f43 100644 --- a/tests/testdata/run/deny_all_permission_args.out +++ b/tests/testdata/run/deny_all_permission_args.out @@ -5,4 +5,3 @@ PermissionStatus { state: "denied", onchange: null } PermissionStatus { state: "denied", onchange: null } PermissionStatus { state: "denied", onchange: null } PermissionStatus { state: "denied", onchange: null } -PermissionStatus { state: "denied", onchange: null } diff --git a/tests/testdata/run/deny_some_permission_args.js b/tests/testdata/run/deny_some_permission_args.js index 320376b6fe..357dda238c 100644 --- a/tests/testdata/run/deny_some_permission_args.js +++ b/tests/testdata/run/deny_some_permission_args.js @@ -19,4 +19,3 @@ console.log(Deno.permissions.querySync({ name: "sys", kind: "loadavg" })); console.log(Deno.permissions.querySync({ name: "net" })); console.log(Deno.permissions.querySync({ name: "net", host: "127.0.0.1" })); console.log(Deno.permissions.querySync({ name: "net", host: "192.168.0.1" })); -console.log(Deno.permissions.querySync({ name: "hrtime" })); diff --git a/tests/testdata/run/deny_some_permission_args.out b/tests/testdata/run/deny_some_permission_args.out index 80c37159ba..abb5274eed 100644 --- a/tests/testdata/run/deny_some_permission_args.out +++ b/tests/testdata/run/deny_some_permission_args.out @@ -19,4 +19,3 @@ PermissionStatus { state: "granted", onchange: null } PermissionStatus { state: "granted", onchange: null, partial: true } PermissionStatus { state: "denied", onchange: null } PermissionStatus { state: "granted", onchange: null } -PermissionStatus { state: "denied", onchange: null } diff --git a/tests/testdata/run/error_009_extensions_error.js.out b/tests/testdata/run/error_009_extensions_error.js.out index 0fd1306de7..2ed936643a 100644 --- a/tests/testdata/run/error_009_extensions_error.js.out +++ b/tests/testdata/run/error_009_extensions_error.js.out @@ -1,4 +1,4 @@ -[WILDCARD]error: Uncaught (in promise) TypeError: Failed to construct 'Event': 1 argument required, but only 0 present. +[WILDCARD]error: Uncaught (in promise) TypeError: Failed to construct 'Event': 1 argument required, but only 0 present new Event(); ^ at [WILDCARD] diff --git a/tests/testdata/run/error_015_dynamic_import_permissions.js b/tests/testdata/run/error_015_dynamic_import_permissions.js index 47961cf63b..bdf423b59c 100644 --- a/tests/testdata/run/error_015_dynamic_import_permissions.js +++ b/tests/testdata/run/error_015_dynamic_import_permissions.js @@ -1,3 +1,3 @@ (async () => { - await import("" + "http://localhost:4545/subdir/mod4.js"); + await import("" + "http://example.com/subdir/mod4.js"); })(); diff --git a/tests/testdata/run/error_015_dynamic_import_permissions.out b/tests/testdata/run/error_015_dynamic_import_permissions.out index 87ce43e9cd..15c26b4251 100644 --- a/tests/testdata/run/error_015_dynamic_import_permissions.out +++ b/tests/testdata/run/error_015_dynamic_import_permissions.out @@ -1,4 +1,4 @@ -error: Uncaught (in promise) TypeError: Requires net access to "localhost:4545", run again with the --allow-net flag - await import("" + "http://localhost:4545/subdir/mod4.js"); +error: Uncaught (in promise) TypeError: Requires import access to "example.com:80", run again with the --allow-import flag + await import("" + "http://example.com/subdir/mod4.js"); ^ at async file://[WILDCARD]/error_015_dynamic_import_permissions.js:2:3 diff --git a/tests/testdata/run/error_for_await.ts b/tests/testdata/run/error_for_await.ts index 64c81abe4f..ce8571df1a 100644 --- a/tests/testdata/run/error_for_await.ts +++ b/tests/testdata/run/error_for_await.ts @@ -5,7 +5,7 @@ for await (const conn of listener) { } function handleConn(conn: Deno.Conn) { - const httpConn = Deno.serveHttp(conn); + const httpConn = (Deno as any).serveHttp(conn); for await (const event of httpConn) { event.respondWith(new Response("html", { status: 200 })); } diff --git a/tests/testdata/run/error_syntax_empty_trailing_line.mjs.out b/tests/testdata/run/error_syntax_empty_trailing_line.mjs.out index 2eb290bb52..2c9b97aa41 100644 --- a/tests/testdata/run/error_syntax_empty_trailing_line.mjs.out +++ b/tests/testdata/run/error_syntax_empty_trailing_line.mjs.out @@ -1,4 +1,6 @@ -error: The module's source code could not be parsed: Unexpected eof at [WILDCARD]/error_syntax_empty_trailing_line.mjs:2:22 +error: The module's source code could not be parsed: Unexpected eof at [WILDCARD]/error_syntax_empty_trailing_line.mjs:3:1 setTimeout(() => {}), - ~ + ~~~~~~~~~~~~~~~~~~~~~ + + ~ diff --git a/tests/testdata/run/error_type_definitions.ts.out b/tests/testdata/run/error_type_definitions.ts.out index d60d4d483c..057c21df51 100644 --- a/tests/testdata/run/error_type_definitions.ts.out +++ b/tests/testdata/run/error_type_definitions.ts.out @@ -1,2 +1,3 @@ [WILDCARD]error: Failed resolving types. Relative import path "baz" not prefixed with / or ./ or ../ + hint: If you want to use a JSR or npm package, try running `deno add jsr:baz` or `deno add npm:baz` at [WILDCARD]/type_definitions/bar.d.ts:[WILDCARD] diff --git a/tests/testdata/run/heapstats.js.out b/tests/testdata/run/heapstats.js.out index b75a755f8e..9542663331 100644 --- a/tests/testdata/run/heapstats.js.out +++ b/tests/testdata/run/heapstats.js.out @@ -1,2 +1,2 @@ -Allocated: 4MB -Freed: -4MB +Allocated: 8MB +Freed: -8MB diff --git a/tests/testdata/run/http2_request_url.ts b/tests/testdata/run/http2_request_url.ts index 5acff8cc24..1c9cab2ea7 100644 --- a/tests/testdata/run/http2_request_url.ts +++ b/tests/testdata/run/http2_request_url.ts @@ -5,6 +5,7 @@ const listener = Deno.listen({ console.log("READY"); for await (const conn of listener) { + // @ts-ignore `Deno.serveHttp()` was soft-removed in Deno 2. for await (const { request, respondWith } of Deno.serveHttp(conn)) { const href = new URL(request.url).href; respondWith(new Response(href)); diff --git a/tests/testdata/run/lock_check_ok2.json b/tests/testdata/run/lock_check_ok2.json index 14d8b71171..55a6f98924 100644 --- a/tests/testdata/run/lock_check_ok2.json +++ b/tests/testdata/run/lock_check_ok2.json @@ -1,5 +1,5 @@ { - "version": "3", + "version": "4", "remote": { "http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18", "http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18", diff --git a/tests/testdata/run/lock_write_fetch/file_exists.ts b/tests/testdata/run/lock_write_fetch/file_exists.ts deleted file mode 100644 index 20de4d4f2f..0000000000 --- a/tests/testdata/run/lock_write_fetch/file_exists.ts +++ /dev/null @@ -1,6 +0,0 @@ -try { - await Deno.open(Deno.args[0]); - Deno.exit(0); -} catch (_e) { - Deno.exit(1); -} diff --git a/tests/testdata/run/lock_write_fetch/main.ts b/tests/testdata/run/lock_write_fetch/main.ts index 57bc54d029..d8a50a9aa6 100644 --- a/tests/testdata/run/lock_write_fetch/main.ts +++ b/tests/testdata/run/lock_write_fetch/main.ts @@ -9,9 +9,9 @@ const fetchProc = await new Deno.Command(Deno.execPath(), { stderr: "null", args: [ "cache", + "--allow-import", "--reload", "--lock=lock_write_fetch.json", - "--lock-write", "--cert=tls/RootCA.pem", "run/https_import.ts", ], @@ -24,6 +24,7 @@ const fetchCheckProc = await new Deno.Command(Deno.execPath(), { stderr: "null", args: [ "cache", + "--allow-import", "--lock=lock_write_fetch.json", "--cert=tls/RootCA.pem", "run/https_import.ts", @@ -39,14 +40,15 @@ const runProc = await new Deno.Command(Deno.execPath(), { stderr: "null", args: [ "run", + "--allow-import", "--lock=lock_write_fetch.json", - "--lock-write", "--allow-read", - "run/lock_write_fetch/file_exists.ts", - "lock_write_fetch.json", + "--cert=tls/RootCA.pem", + "run/https_import.ts", ], }).output(); console.log(`run code: ${runProc.code}`); +await Deno.stat("./lock_write_fetch.json"); Deno.removeSync("./lock_write_fetch.json"); diff --git a/tests/testdata/run/no_check_imports_not_used_as_values/hello.ts b/tests/testdata/run/no_check_imports_not_used_as_values/hello.ts deleted file mode 100644 index 1a9d8f114f..0000000000 --- a/tests/testdata/run/no_check_imports_not_used_as_values/hello.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type SomeType = unknown; -console.log("Hello, world!"); diff --git a/tests/testdata/run/no_check_imports_not_used_as_values/main.out b/tests/testdata/run/no_check_imports_not_used_as_values/main.out deleted file mode 100644 index f744c41839..0000000000 --- a/tests/testdata/run/no_check_imports_not_used_as_values/main.out +++ /dev/null @@ -1,2 +0,0 @@ -[WILDCARD]Hello, world! -Hi! diff --git a/tests/testdata/run/no_check_imports_not_used_as_values/main.ts b/tests/testdata/run/no_check_imports_not_used_as_values/main.ts deleted file mode 100644 index 80e17aa35d..0000000000 --- a/tests/testdata/run/no_check_imports_not_used_as_values/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { SomeType } from "./hello.ts"; - -const string: SomeType = "Hi!"; -console.log(string); diff --git a/tests/testdata/run/no_check_imports_not_used_as_values/preserve_imports.tsconfig.json b/tests/testdata/run/no_check_imports_not_used_as_values/preserve_imports.tsconfig.json deleted file mode 100644 index 9b19291aa0..0000000000 --- a/tests/testdata/run/no_check_imports_not_used_as_values/preserve_imports.tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "importsNotUsedAsValues": "preserve" - } -} diff --git a/tests/testdata/run/node_env_var_allowlist.ts.out b/tests/testdata/run/node_env_var_allowlist.ts.out index ea66a2965b..2dcffd67b9 100644 --- a/tests/testdata/run/node_env_var_allowlist.ts.out +++ b/tests/testdata/run/node_env_var_allowlist.ts.out @@ -1,5 +1,5 @@ ok -[WILDCARD]error: Uncaught (in promise) PermissionDenied: Requires env access to "NOT_NODE_DEBUG", run again with the --allow-env flag +[WILDCARD]error: Uncaught (in promise) NotCapable: Requires env access to "NOT_NODE_DEBUG", run again with the --allow-env flag Deno.env.get("NOT_NODE_DEBUG"); ^ at [WILDCARD] diff --git a/tests/testdata/run/node_prefix_missing/config.json b/tests/testdata/run/node_prefix_missing/config.json deleted file mode 100644 index 67480c3d48..0000000000 --- a/tests/testdata/run/node_prefix_missing/config.json +++ /dev/null @@ -1 +0,0 @@ -{ "unstable": ["bare-node-builtins"] } diff --git a/tests/testdata/run/node_prefix_missing/import_map.json b/tests/testdata/run/node_prefix_missing/import_map.json deleted file mode 100644 index 3add7d009c..0000000000 --- a/tests/testdata/run/node_prefix_missing/import_map.json +++ /dev/null @@ -1 +0,0 @@ -{ "imports": {} } diff --git a/tests/testdata/run/node_prefix_missing/main.ts.out_feature_enabled b/tests/testdata/run/node_prefix_missing/main.ts.out_feature_enabled deleted file mode 100644 index 513b411ce1..0000000000 --- a/tests/testdata/run/node_prefix_missing/main.ts.out_feature_enabled +++ /dev/null @@ -1,2 +0,0 @@ -[WILDCARD]Warning: Resolving "fs" as "node:fs" at file:///[WILDCARD]/tests/testdata/run/node_prefix_missing/main.ts:1:16. If you want to use a built-in Node module, add a "node:" prefix. -[Function: writeFile] diff --git a/tests/testdata/run/onload/imported.ts b/tests/testdata/run/onload/imported.ts index 77d3da9980..643e2fc787 100644 --- a/tests/testdata/run/onload/imported.ts +++ b/tests/testdata/run/onload/imported.ts @@ -1,4 +1,3 @@ -// deno-lint-ignore-file no-window-prefix import { assert } from "@std/assert"; import "./nest_imported.ts"; @@ -7,7 +6,7 @@ const handler = (e: Event) => { console.log(`got ${e.type} event in event handler (imported)`); }; -window.addEventListener("load", handler); -window.addEventListener("beforeunload", handler); -window.addEventListener("unload", handler); +globalThis.addEventListener("load", handler); +globalThis.addEventListener("beforeunload", handler); +globalThis.addEventListener("unload", handler); console.log("log from imported script"); diff --git a/tests/testdata/run/onload/main.ts b/tests/testdata/run/onload/main.ts index 69bd174fa6..c4b8424fbc 100644 --- a/tests/testdata/run/onload/main.ts +++ b/tests/testdata/run/onload/main.ts @@ -1,32 +1,32 @@ -// deno-lint-ignore-file no-window-prefix no-prototype-builtins +// deno-lint-ignore-file no-prototype-builtins import { assert } from "@std/assert"; import "./imported.ts"; -assert(window.hasOwnProperty("onload")); -assert(window.onload === null); +assert(globalThis.hasOwnProperty("onload")); +assert(globalThis.onload === null); const eventHandler = (e: Event) => { assert(e.type === "beforeunload" ? e.cancelable : !e.cancelable); console.log(`got ${e.type} event in event handler (main)`); }; -window.addEventListener("load", eventHandler); +globalThis.addEventListener("load", eventHandler); -window.addEventListener("beforeunload", eventHandler); +globalThis.addEventListener("beforeunload", eventHandler); -window.addEventListener("unload", eventHandler); +globalThis.addEventListener("unload", eventHandler); -window.onload = (e: Event) => { +globalThis.onload = (e: Event) => { assert(!e.cancelable); console.log(`got ${e.type} event in onload function`); }; -window.onbeforeunload = (e: BeforeUnloadEvent) => { +globalThis.onbeforeunload = (e: BeforeUnloadEvent) => { assert(e.cancelable); console.log(`got ${e.type} event in onbeforeunload function`); }; -window.onunload = (e: Event) => { +globalThis.onunload = (e: Event) => { assert(!e.cancelable); console.log(`got ${e.type} event in onunload function`); }; diff --git a/tests/testdata/run/onload/nest_imported.ts b/tests/testdata/run/onload/nest_imported.ts index dbe313b9c8..f1d28e8dc7 100644 --- a/tests/testdata/run/onload/nest_imported.ts +++ b/tests/testdata/run/onload/nest_imported.ts @@ -1,4 +1,3 @@ -// deno-lint-ignore-file no-window-prefix import { assert } from "@std/assert"; const handler = (e: Event) => { @@ -6,7 +5,7 @@ const handler = (e: Event) => { console.log(`got ${e.type} event in event handler (nest_imported)`); }; -window.addEventListener("load", handler); -window.addEventListener("beforeunload", handler); -window.addEventListener("unload", handler); +globalThis.addEventListener("load", handler); +globalThis.addEventListener("beforeunload", handler); +globalThis.addEventListener("unload", handler); console.log("log from nest_imported script"); diff --git a/tests/testdata/run/permission_request_no_prompt.ts b/tests/testdata/run/permission_request_no_prompt.ts new file mode 100644 index 0000000000..e33ffe3ce8 --- /dev/null +++ b/tests/testdata/run/permission_request_no_prompt.ts @@ -0,0 +1 @@ +console.log(await Deno.permissions.request({ name: "read" })); diff --git a/tests/testdata/run/rejection_handled.ts b/tests/testdata/run/rejection_handled.ts index 16506ea4a0..8822203f14 100644 --- a/tests/testdata/run/rejection_handled.ts +++ b/tests/testdata/run/rejection_handled.ts @@ -1,9 +1,9 @@ -window.addEventListener("unhandledrejection", (event) => { +globalThis.addEventListener("unhandledrejection", (event) => { console.log("unhandledrejection", event.reason, event.promise); event.preventDefault(); }); -window.addEventListener("rejectionhandled", (event) => { +globalThis.addEventListener("rejectionhandled", (event) => { console.log("rejectionhandled", event.reason, event.promise); }); diff --git a/tests/testdata/run/resolve_dns.ts b/tests/testdata/run/resolve_dns.ts index a2d0fd0468..163a68f333 100644 --- a/tests/testdata/run/resolve_dns.ts +++ b/tests/testdata/run/resolve_dns.ts @@ -67,7 +67,7 @@ try { // @ts-ignore testing invalid overloads await Deno.resolveDns("example.com", "SSHFP", nameServer); } catch (e) { - console.log(e.message); + console.log((e as Error).message); } try { @@ -78,7 +78,7 @@ try { signal: ac.signal, }); } catch (e) { - console.log(e.name); + console.log((e as Error).name); } try { @@ -89,5 +89,5 @@ try { signal: ac.signal, }); } catch (e) { - console.log(e.name); + console.log((e as Error).name); } diff --git a/tests/testdata/run/tls_connecttls.js b/tests/testdata/run/tls_connecttls.js index b44b950fdb..07b361f9ce 100644 --- a/tests/testdata/run/tls_connecttls.js +++ b/tests/testdata/run/tls_connecttls.js @@ -37,7 +37,6 @@ const conn = await Deno.connectTls({ hostname, port, }); -assert(conn.rid > 0); const w = new BufWriter(conn); const r = new BufReader(conn); const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`; diff --git a/tests/testdata/run/tls_starttls.js b/tests/testdata/run/tls_starttls.js index 3d9439811a..8e7ac03ee6 100644 --- a/tests/testdata/run/tls_starttls.js +++ b/tests/testdata/run/tls_starttls.js @@ -36,7 +36,6 @@ listener.accept().then( let conn = await Deno.connect({ hostname, port }); conn = await Deno.startTls(conn, { hostname }); -assert(conn.rid > 0); const w = new BufWriter(conn); const r = new BufReader(conn); const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`; diff --git a/tests/testdata/run/type_directives_01.ts b/tests/testdata/run/type_directives_01.ts index 71305824c7..2129d90b4a 100644 --- a/tests/testdata/run/type_directives_01.ts +++ b/tests/testdata/run/type_directives_01.ts @@ -1,3 +1,3 @@ -import * as foo from "http://127.0.0.1:4545/xTypeScriptTypes.js"; +import * as foo from "http://localhost:4545/xTypeScriptTypes.js"; console.log(foo.foo); diff --git a/tests/testdata/run/type_directives_01.ts.out b/tests/testdata/run/type_directives_01.ts.out index 77ed3ae264..466218a965 100644 --- a/tests/testdata/run/type_directives_01.ts.out +++ b/tests/testdata/run/type_directives_01.ts.out @@ -1,3 +1,3 @@ [WILDCARD] -DEBUG TS - host.getSourceFile("http://127.0.0.1:4545/xTypeScriptTypes.d.ts", Latest) +DEBUG TS - host.getSourceFile("http://localhost:4545/xTypeScriptTypes.d.ts", Latest) [WILDCARD] \ No newline at end of file diff --git a/tests/testdata/run/type_headers_deno_types.ts b/tests/testdata/run/type_headers_deno_types.ts index 9670f68cd2..197ac1801d 100644 --- a/tests/testdata/run/type_headers_deno_types.ts +++ b/tests/testdata/run/type_headers_deno_types.ts @@ -12,7 +12,7 @@ * header. */ -// @deno-types="http://127.0.0.1:4545/run/type_headers_deno_types.foo.d.ts" -import { foo } from "http://127.0.0.1:4545/run/type_headers_deno_types.foo.js"; +// @deno-types="http://localhost:4545/run/type_headers_deno_types.foo.d.ts" +import { foo } from "http://localhost:4545/run/type_headers_deno_types.foo.js"; foo("hello"); diff --git a/tests/testdata/run/unstable.js b/tests/testdata/run/unstable.js deleted file mode 100644 index 8c01b214e3..0000000000 --- a/tests/testdata/run/unstable.js +++ /dev/null @@ -1 +0,0 @@ -console.log(Deno.umask); diff --git a/tests/testdata/run/unstable.ts b/tests/testdata/run/unstable.ts deleted file mode 100644 index 8c01b214e3..0000000000 --- a/tests/testdata/run/unstable.ts +++ /dev/null @@ -1 +0,0 @@ -console.log(Deno.umask); diff --git a/tests/testdata/run/unstable_disabled_js.out b/tests/testdata/run/unstable_disabled_js.out deleted file mode 100644 index 417b7b5370..0000000000 --- a/tests/testdata/run/unstable_disabled_js.out +++ /dev/null @@ -1 +0,0 @@ -undefined diff --git a/tests/testdata/run/unstable_enabled.out b/tests/testdata/run/unstable_enabled.out deleted file mode 100644 index 5f88c778cd..0000000000 --- a/tests/testdata/run/unstable_enabled.out +++ /dev/null @@ -1 +0,0 @@ -[Function: umask] diff --git a/tests/testdata/run/unstable_enabled_js.out b/tests/testdata/run/unstable_enabled_js.out deleted file mode 100644 index 5f88c778cd..0000000000 --- a/tests/testdata/run/unstable_enabled_js.out +++ /dev/null @@ -1 +0,0 @@ -[Function: umask] diff --git a/tests/testdata/run/unstable_ffi.disabled.out b/tests/testdata/run/unstable_ffi.disabled.out deleted file mode 100644 index 0d8ac4410f..0000000000 --- a/tests/testdata/run/unstable_ffi.disabled.out +++ /dev/null @@ -1,10 +0,0 @@ -main undefined -main undefined -main undefined -main undefined -main undefined -worker undefined -worker undefined -worker undefined -worker undefined -worker undefined diff --git a/tests/testdata/run/unstable_ffi.enabled.out b/tests/testdata/run/unstable_ffi.enabled.out deleted file mode 100644 index 672b2a2a23..0000000000 --- a/tests/testdata/run/unstable_ffi.enabled.out +++ /dev/null @@ -1,10 +0,0 @@ -main [class UnsafeCallback] -main [class UnsafeFnPointer] -main [class UnsafePointer] -main [class UnsafePointerView] -main [Function: dlopen] -worker [class UnsafeCallback] -worker [class UnsafeFnPointer] -worker [class UnsafePointer] -worker [class UnsafePointerView] -worker [Function: dlopen] diff --git a/tests/testdata/run/unstable_ffi.js b/tests/testdata/run/unstable_ffi.js deleted file mode 100644 index 4809c5ffe4..0000000000 --- a/tests/testdata/run/unstable_ffi.js +++ /dev/null @@ -1,14 +0,0 @@ -const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; - -console.log(scope, Deno.UnsafeCallback); -console.log(scope, Deno.UnsafeFnPointer); -console.log(scope, Deno.UnsafePointer); -console.log(scope, Deno.UnsafePointerView); -console.log(scope, Deno.dlopen); - -if (scope === "worker") { - postMessage("done"); -} else { - const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); - worker.onmessage = () => Deno.exit(0); -} diff --git a/tests/testdata/run/unstable_fs.disabled.out b/tests/testdata/run/unstable_fs.disabled.out deleted file mode 100644 index 0d8ac4410f..0000000000 --- a/tests/testdata/run/unstable_fs.disabled.out +++ /dev/null @@ -1,10 +0,0 @@ -main undefined -main undefined -main undefined -main undefined -main undefined -worker undefined -worker undefined -worker undefined -worker undefined -worker undefined diff --git a/tests/testdata/run/unstable_fs.enabled.out b/tests/testdata/run/unstable_fs.enabled.out deleted file mode 100644 index 6938fa9c22..0000000000 --- a/tests/testdata/run/unstable_fs.enabled.out +++ /dev/null @@ -1,10 +0,0 @@ -main [AsyncFunction: flock] -main [Function: flockSync] -main [AsyncFunction: funlock] -main [Function: funlockSync] -main [Function: umask] -worker [AsyncFunction: flock] -worker [Function: flockSync] -worker [AsyncFunction: funlock] -worker [Function: funlockSync] -worker [Function: umask] diff --git a/tests/testdata/run/unstable_fs.js b/tests/testdata/run/unstable_fs.js deleted file mode 100644 index 83f14f2fd7..0000000000 --- a/tests/testdata/run/unstable_fs.js +++ /dev/null @@ -1,14 +0,0 @@ -const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; - -console.log(scope, Deno.flock); -console.log(scope, Deno.flockSync); -console.log(scope, Deno.funlock); -console.log(scope, Deno.funlockSync); -console.log(scope, Deno.umask); - -if (scope === "worker") { - postMessage("done"); -} else { - const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); - worker.onmessage = () => Deno.exit(0); -} diff --git a/tests/testdata/run/unstable_http.disabled.out b/tests/testdata/run/unstable_http.disabled.out deleted file mode 100644 index 3562f72fdd..0000000000 --- a/tests/testdata/run/unstable_http.disabled.out +++ /dev/null @@ -1,4 +0,0 @@ -main undefined -main undefined -worker undefined -worker undefined diff --git a/tests/testdata/run/unstable_http.enabled.out b/tests/testdata/run/unstable_http.enabled.out deleted file mode 100644 index f7aa776e9e..0000000000 --- a/tests/testdata/run/unstable_http.enabled.out +++ /dev/null @@ -1,4 +0,0 @@ -main [class HttpClient] -main [Function: createHttpClient] -worker [class HttpClient] -worker [Function: createHttpClient] diff --git a/tests/testdata/run/unstable_http.js b/tests/testdata/run/unstable_http.js deleted file mode 100644 index 7ad09aec57..0000000000 --- a/tests/testdata/run/unstable_http.js +++ /dev/null @@ -1,11 +0,0 @@ -const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; - -console.log(scope, Deno.HttpClient); -console.log(scope, Deno.createHttpClient); - -if (scope === "worker") { - postMessage("done"); -} else { - const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); - worker.onmessage = () => Deno.exit(0); -} diff --git a/tests/testdata/run/unstable_webgpu.disabled.out b/tests/testdata/run/unstable_webgpu.disabled.out deleted file mode 100644 index 7758663527..0000000000 --- a/tests/testdata/run/unstable_webgpu.disabled.out +++ /dev/null @@ -1,2 +0,0 @@ -main undefined -worker undefined diff --git a/tests/testdata/run/unstable_webgpu.enabled.out b/tests/testdata/run/unstable_webgpu.enabled.out deleted file mode 100644 index e2cc915ba2..0000000000 --- a/tests/testdata/run/unstable_webgpu.enabled.out +++ /dev/null @@ -1,2 +0,0 @@ -main [class GPU] -worker [class GPU] diff --git a/tests/testdata/run/unstable_webgpu.js b/tests/testdata/run/unstable_webgpu.js deleted file mode 100644 index a796b1c4d7..0000000000 --- a/tests/testdata/run/unstable_webgpu.js +++ /dev/null @@ -1,10 +0,0 @@ -const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; - -console.log(scope, globalThis.GPU); - -if (scope === "worker") { - postMessage("done"); -} else { - const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); - worker.onmessage = () => Deno.exit(0); -} diff --git a/tests/testdata/run/warn_on_deprecated_api/main.js b/tests/testdata/run/warn_on_deprecated_api/main.js index a464be60a3..8811df78de 100644 --- a/tests/testdata/run/warn_on_deprecated_api/main.js +++ b/tests/testdata/run/warn_on_deprecated_api/main.js @@ -1,5 +1,6 @@ import { runEcho as runEcho2 } from "http://localhost:4545/run/warn_on_deprecated_api/mod.ts"; +// @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -11,6 +12,7 @@ await p.status(); p.close(); async function runEcho() { + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), diff --git a/tests/testdata/run/warn_on_deprecated_api/main.out b/tests/testdata/run/warn_on_deprecated_api/main.out index ff44c885f1..ef85a6f99b 100644 --- a/tests/testdata/run/warn_on_deprecated_api/main.out +++ b/tests/testdata/run/warn_on_deprecated_api/main.out @@ -1,5 +1,4 @@ Download http://localhost:4545/run/warn_on_deprecated_api/mod.ts -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. Run again with DENO_VERBOSE_WARNINGS=1 to get more details. hello world hello world hello world diff --git a/tests/testdata/run/warn_on_deprecated_api/main.verbose.out b/tests/testdata/run/warn_on_deprecated_api/main.verbose.out index 184051de12..e17562eef3 100644 --- a/tests/testdata/run/warn_on_deprecated_api/main.verbose.out +++ b/tests/testdata/run/warn_on_deprecated_api/main.verbose.out @@ -1,5 +1,4 @@ Download http://localhost:4545/run/warn_on_deprecated_api/mod.ts -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. See the Deno 1 to 2 Migration Guide for more information at https://docs.deno.com/runtime/manual/advanced/migrate_deprecations @@ -9,7 +8,6 @@ Stack trace: hint: Use "Deno.Command()" API instead. hello world -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. See the Deno 1 to 2 Migration Guide for more information at https://docs.deno.com/runtime/manual/advanced/migrate_deprecations @@ -20,7 +18,6 @@ Stack trace: hint: Use "Deno.Command()" API instead. hello world -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. See the Deno 1 to 2 Migration Guide for more information at https://docs.deno.com/runtime/manual/advanced/migrate_deprecations @@ -31,7 +28,6 @@ Stack trace: hint: Use "Deno.Command()" API instead. hello world -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. See the Deno 1 to 2 Migration Guide for more information at https://docs.deno.com/runtime/manual/advanced/migrate_deprecations @@ -51,7 +47,6 @@ hello world hello world hello world hello world -warning: Use of deprecated "Deno.run()" API. This API will be removed in Deno 2. See the Deno 1 to 2 Migration Guide for more information at https://docs.deno.com/runtime/manual/advanced/migrate_deprecations diff --git a/tests/testdata/run/wasm_streaming_panic_test.js.out b/tests/testdata/run/wasm_streaming_panic_test.js.out index 8a3c68e375..4ec523f1d0 100644 --- a/tests/testdata/run/wasm_streaming_panic_test.js.out +++ b/tests/testdata/run/wasm_streaming_panic_test.js.out @@ -1,2 +1,2 @@ -error: Uncaught (in promise) TypeError: Invalid WebAssembly content type. +error: Uncaught (in promise) TypeError: Invalid WebAssembly content type at handleWasmStreaming (ext:deno_fetch/26_fetch.js:[WILDCARD]) diff --git a/tests/testdata/run/websocket_server_idletimeout.ts b/tests/testdata/run/websocket_server_idletimeout.ts index c33fd9efb1..91e359eab4 100644 --- a/tests/testdata/run/websocket_server_idletimeout.ts +++ b/tests/testdata/run/websocket_server_idletimeout.ts @@ -5,6 +5,7 @@ const closeDeferred = Promise.withResolvers(); const listener = Deno.listen({ port: 4509 }); console.log("READY"); +// @ts-ignore `Deno.serveHttp()` was soft-removed in Deno 2. const httpConn = Deno.serveHttp(await listener.accept()); const { request, respondWith } = (await httpConn.nextRequest())!; const { response, socket } = Deno.upgradeWebSocket(request, { diff --git a/tests/testdata/run/websocket_server_multi_field_connection_header_test.ts b/tests/testdata/run/websocket_server_multi_field_connection_header_test.ts index d947097675..eee86624d5 100644 --- a/tests/testdata/run/websocket_server_multi_field_connection_header_test.ts +++ b/tests/testdata/run/websocket_server_multi_field_connection_header_test.ts @@ -2,6 +2,7 @@ const { promise, resolve } = Promise.withResolvers(); const listener = Deno.listen({ port: 4319 }); console.log("READY"); const conn = await listener.accept(); +// @ts-ignore `Deno.serveHttp()` was soft-removed in Deno 2. const httpConn = Deno.serveHttp(conn); const { request, respondWith } = (await httpConn.nextRequest())!; const { diff --git a/tests/testdata/run/webstorage/logger.ts b/tests/testdata/run/webstorage/logger.ts index 3898c4445f..feadd39eb6 100644 --- a/tests/testdata/run/webstorage/logger.ts +++ b/tests/testdata/run/webstorage/logger.ts @@ -1 +1 @@ -console.log(window.localStorage); +console.log(globalThis.localStorage); diff --git a/tests/testdata/run/webstorage/serialization.ts b/tests/testdata/run/webstorage/serialization.ts index f3791d355f..f125331bbe 100644 --- a/tests/testdata/run/webstorage/serialization.ts +++ b/tests/testdata/run/webstorage/serialization.ts @@ -1,4 +1,4 @@ -window.sessionStorage.setItem("hello", "deno"); +globalThis.sessionStorage.setItem("hello", "deno"); -console.log(window.localStorage); -console.log(window.sessionStorage); +console.log(globalThis.localStorage); +console.log(globalThis.sessionStorage); diff --git a/tests/testdata/run/webstorage/setter.ts b/tests/testdata/run/webstorage/setter.ts index ec6d474f52..cf5a7bfaf6 100644 --- a/tests/testdata/run/webstorage/setter.ts +++ b/tests/testdata/run/webstorage/setter.ts @@ -1 +1 @@ -window.localStorage.setItem("hello", "deno"); +globalThis.localStorage.setItem("hello", "deno"); diff --git a/tests/testdata/run/with_package_json/npm_binary/main.out b/tests/testdata/run/with_package_json/npm_binary/main.out deleted file mode 100644 index 13d196a5e1..0000000000 --- a/tests/testdata/run/with_package_json/npm_binary/main.out +++ /dev/null @@ -1,7 +0,0 @@ -[WILDCARD]package.json file found at '[WILDCARD]with_package_json[WILDCARD]npm_binary[WILDCARD]package.json' -[WILDCARD] -this -is -a -test -[WILDCARD] diff --git a/tests/testdata/run/with_package_json/with_stop/main.out b/tests/testdata/run/with_package_json/with_stop/main.out index f5eb79ca6d..44098a2d86 100644 --- a/tests/testdata/run/with_package_json/with_stop/main.out +++ b/tests/testdata/run/with_package_json/with_stop/main.out @@ -1,4 +1,5 @@ [WILDCARD]Config file found at '[WILDCARD]with_package_json[WILDCARD]with_stop[WILDCARD]some[WILDCARD]nested[WILDCARD]deno.json' [WILDCARD] error: Relative import path "chalk" not prefixed with / or ./ or ../ + hint: If you want to use a JSR or npm package, try running `deno add jsr:chalk` or `deno add npm:chalk` at file:///[WILDCARD]with_package_json/with_stop/some/nested/dir/main.ts:3:19 diff --git a/tests/testdata/serve/parallel.ts b/tests/testdata/serve/parallel.ts index f1f118c71e..2ba7ccfca1 100644 --- a/tests/testdata/serve/parallel.ts +++ b/tests/testdata/serve/parallel.ts @@ -1,7 +1,7 @@ -console.log("starting serve"); +console.error("starting serve"); export default { fetch(_req: Request) { - console.log("serving request"); + console.error("serving request"); return new Response("deno serve parallel"); }, }; diff --git a/tests/testdata/task/both/package_json_selected.out b/tests/testdata/task/both/package_json_selected.out deleted file mode 100644 index c72baeb640..0000000000 --- a/tests/testdata/task/both/package_json_selected.out +++ /dev/null @@ -1,8 +0,0 @@ -Download http://localhost:4260/@denotest/bin -Download http://localhost:4260/@denotest/bin/1.0.0.tgz -Initialize @denotest/bin@1.0.0 -Task bin cli-esm testing this out "asdf" -testing -this -out -asdf diff --git a/tests/testdata/task/deno_json/task_cwd.out b/tests/testdata/task/deno_json/task_cwd.out deleted file mode 100644 index bfe3e7b111..0000000000 --- a/tests/testdata/task/deno_json/task_cwd.out +++ /dev/null @@ -1 +0,0 @@ -[WILDCARD]tests diff --git a/tests/testdata/task/deno_json/task_init_cwd.out b/tests/testdata/task/deno_json/task_init_cwd.out deleted file mode 100644 index 95ea8a5458..0000000000 --- a/tests/testdata/task/deno_json/task_init_cwd.out +++ /dev/null @@ -1 +0,0 @@ -[WILDCARD]testdata diff --git a/tests/testdata/task/package_json_node_modules_dir_false/bin.out b/tests/testdata/task/package_json_node_modules_dir_false/bin.out deleted file mode 100644 index d5d59d5515..0000000000 --- a/tests/testdata/task/package_json_node_modules_dir_false/bin.out +++ /dev/null @@ -1,2 +0,0 @@ -Task echo deno eval 'console.log(1)' -1 diff --git a/tests/testdata/task/package_json_node_modules_dir_false/deno.json b/tests/testdata/task/package_json_node_modules_dir_false/deno.json deleted file mode 100644 index 23a325cfc2..0000000000 --- a/tests/testdata/task/package_json_node_modules_dir_false/deno.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "nodeModulesDir": false -} diff --git a/tests/testdata/task/package_json_post/echo.out b/tests/testdata/task/package_json_post/echo.out deleted file mode 100644 index 573541ac97..0000000000 --- a/tests/testdata/task/package_json_post/echo.out +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/tests/testdata/task/package_json_post_only/echo.out b/tests/testdata/task/package_json_post_only/echo.out deleted file mode 100644 index 573541ac97..0000000000 --- a/tests/testdata/task/package_json_post_only/echo.out +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/tests/testdata/task/package_json_pre/echo.out b/tests/testdata/task/package_json_pre/echo.out deleted file mode 100644 index 573541ac97..0000000000 --- a/tests/testdata/task/package_json_pre/echo.out +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/tests/testdata/task/package_json_pre_post/echo.out b/tests/testdata/task/package_json_pre_post/echo.out deleted file mode 100644 index 573541ac97..0000000000 --- a/tests/testdata/task/package_json_pre_post/echo.out +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/tests/testdata/test/aggregate_error.out b/tests/testdata/test/aggregate_error.out deleted file mode 100644 index e70bf5963e..0000000000 --- a/tests/testdata/test/aggregate_error.out +++ /dev/null @@ -1,22 +0,0 @@ -running 1 test from ./test/aggregate_error.ts -aggregate ... FAILED ([WILDCARD]) - - ERRORS - -aggregate => ./test/aggregate_error.ts:[WILDCARD] -error: AggregateError - Error: Error 1 - at [WILDCARD]/testdata/test/aggregate_error.ts:2:18 - Error: Error 2 - at [WILDCARD]/testdata/test/aggregate_error.ts:3:18 - throw new AggregateError([error1, error2]); - ^ - at [WILDCARD]/testdata/test/aggregate_error.ts:5:9 - - FAILURES - -aggregate => ./test/aggregate_error.ts:[WILDCARD] - -FAILED | 0 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/test/allow_none.out b/tests/testdata/test/allow_none.out deleted file mode 100644 index aaa467344a..0000000000 --- a/tests/testdata/test/allow_none.out +++ /dev/null @@ -1,51 +0,0 @@ -[WILDCARD] -running 7 tests from [WILDCARD] -read ... FAILED [WILDCARD] -write ... FAILED [WILDCARD] -net ... FAILED [WILDCARD] -env ... FAILED [WILDCARD] -run ... FAILED [WILDCARD] -ffi ... FAILED [WILDCARD] -hrtime ... FAILED [WILDCARD] - - ERRORS - -read => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -write => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -net => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -env => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -run => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -ffi => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - -hrtime => ./test/allow_none.ts:[WILDCARD] -error: PermissionDenied: Can't escalate parent thread permissions -[WILDCARD] - - FAILURES - -read => ./test/allow_none.ts:[WILDCARD] -write => ./test/allow_none.ts:[WILDCARD] -net => ./test/allow_none.ts:[WILDCARD] -env => ./test/allow_none.ts:[WILDCARD] -run => ./test/allow_none.ts:[WILDCARD] -ffi => ./test/allow_none.ts:[WILDCARD] -hrtime => ./test/allow_none.ts:[WILDCARD] - -FAILED | 0 passed | 7 failed [WILDCARD] diff --git a/tests/testdata/test/check_local_by_default.out b/tests/testdata/test/check_local_by_default.out deleted file mode 100644 index 4564f99b86..0000000000 --- a/tests/testdata/test/check_local_by_default.out +++ /dev/null @@ -1,4 +0,0 @@ -running 0 tests from ./test/check_local_by_default.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/check_local_by_default.ts b/tests/testdata/test/check_local_by_default.ts deleted file mode 100644 index 2ae8c2692c..0000000000 --- a/tests/testdata/test/check_local_by_default.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as a from "http://localhost:4545/subdir/type_error.ts"; - -console.log(a.a); diff --git a/tests/testdata/test/check_local_by_default2.ts b/tests/testdata/test/check_local_by_default2.ts deleted file mode 100644 index 5177ff944a..0000000000 --- a/tests/testdata/test/check_local_by_default2.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as a from "http://localhost:4545/subdir/type_error.ts"; - -const b: "b" = 12; - -console.log(a.a); -console.log(b); diff --git a/tests/testdata/test/collect.deprecated.out b/tests/testdata/test/collect.deprecated.out deleted file mode 100644 index 7db2f276c1..0000000000 --- a/tests/testdata/test/collect.deprecated.out +++ /dev/null @@ -1,10 +0,0 @@ -Warning: "files" configuration is deprecated. Please use "include" and "exclude" instead. -Check [WILDCARD]/test/collect/include/2_test.ts -Check [WILDCARD]/test/collect/include/test.ts -Check [WILDCARD]/test/collect/test.ts -running 0 tests from [WILDCARD]/test/collect/include/2_test.ts -running 0 tests from [WILDCARD]/test/collect/include/test.ts -running 0 tests from [WILDCARD]/test/collect/test.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/collect.out b/tests/testdata/test/collect.out deleted file mode 100644 index 734adbe6b1..0000000000 --- a/tests/testdata/test/collect.out +++ /dev/null @@ -1,9 +0,0 @@ -Check [WILDCARD]/test/collect/include/2_test.ts -Check [WILDCARD]/test/collect/include/test.ts -Check [WILDCARD]/test/collect/test.ts -running 0 tests from [WILDCARD]/test/collect/include/2_test.ts -running 0 tests from [WILDCARD]/test/collect/include/test.ts -running 0 tests from [WILDCARD]/test/collect/test.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/collect/deno.deprecated.jsonc b/tests/testdata/test/collect/deno.deprecated.jsonc deleted file mode 100644 index b8acda27d0..0000000000 --- a/tests/testdata/test/collect/deno.deprecated.jsonc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "test": { - "files": { - "exclude": ["./ignore"] - } - } -} diff --git a/tests/testdata/test/collect2.out b/tests/testdata/test/collect2.out deleted file mode 100644 index 0c00c956a8..0000000000 --- a/tests/testdata/test/collect2.out +++ /dev/null @@ -1,7 +0,0 @@ -Check [WILDCARD]/test/collect/include/test.ts -Check [WILDCARD]/test/collect/test.ts -running 0 tests from [WILDCARD]/test/collect/include/test.ts -running 0 tests from [WILDCARD]/test/collect/test.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/doc.out b/tests/testdata/test/doc.out deleted file mode 100644 index cd8bbb6203..0000000000 --- a/tests/testdata/test/doc.out +++ /dev/null @@ -1,9 +0,0 @@ -Check [WILDCARD]/doc.ts$6-9.js -Check [WILDCARD]/doc.ts$10-13.jsx -Check [WILDCARD]/doc.ts$14-17.ts -Check [WILDCARD]/doc.ts$18-21.tsx -Check [WILDCARD]/doc.ts$30-35.ts -error: TS2367 [ERROR]: This comparison appears to be unintentional because the types 'string' and 'number' have no overlap. -console.assert(check() == 42); - ~~~~~~~~~~~~~ - at [WILDCARD]/doc.ts$30-35.ts:3:16 diff --git a/tests/testdata/test/doc.ts b/tests/testdata/test/doc.ts deleted file mode 100644 index 519479fc52..0000000000 --- a/tests/testdata/test/doc.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * ``` - * import * as doc from "./doc.ts"; - * ``` - * - * ```js - * import * as doc from "./doc.ts"; - * ``` - * - * ```jsx - * import * as doc from "./doc.ts"; - * ``` - * - * ```ts - * import * as doc from "./doc.ts"; - * ``` - * - * ```tsx - * import * as doc from "./doc.ts"; - * ``` - * - * ```text - * import * as doc from "./doc.ts"; - * ``` - * - * @module doc - */ - -/** - * ```ts - * import { check } from "./doc.ts"; - * - * console.assert(check() == 42); - * ``` - */ -export function check(): string { - return "check"; -} diff --git a/tests/testdata/test/doc_only.out b/tests/testdata/test/doc_only.out deleted file mode 100644 index 2b8b6dc735..0000000000 --- a/tests/testdata/test/doc_only.out +++ /dev/null @@ -1,4 +0,0 @@ -Check [WILDCARD]/test/doc_only/mod.ts$2-5.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/fail.out b/tests/testdata/test/fail.out deleted file mode 100644 index 3fcf6fd8ff..0000000000 --- a/tests/testdata/test/fail.out +++ /dev/null @@ -1,91 +0,0 @@ -Check [WILDCARD]/test/fail.ts -running 10 tests from ./test/fail.ts -test 0 ... FAILED ([WILDCARD]) -test 1 ... FAILED ([WILDCARD]) -test 2 ... FAILED ([WILDCARD]) -test 3 ... FAILED ([WILDCARD]) -test 4 ... FAILED ([WILDCARD]) -test 5 ... FAILED ([WILDCARD]) -test 6 ... FAILED ([WILDCARD]) -test 7 ... FAILED ([WILDCARD]) -test 8 ... FAILED ([WILDCARD]) -test 9 ... FAILED ([WILDCARD]) - - ERRORS - -test 0 => ./test/fail.ts:1:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:2:9 - -test 1 => ./test/fail.ts:4:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:5:9 - -test 2 => ./test/fail.ts:7:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:8:9 - -test 3 => ./test/fail.ts:10:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:11:9 - -test 4 => ./test/fail.ts:13:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:14:9 - -test 5 => ./test/fail.ts:16:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:17:9 - -test 6 => ./test/fail.ts:19:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:20:9 - -test 7 => ./test/fail.ts:22:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:23:9 - -test 8 => ./test/fail.ts:25:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:26:9 - -test 9 => ./test/fail.ts:28:6 -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail.ts:29:9 - - FAILURES - -test 0 => ./test/fail.ts:1:6 -test 1 => ./test/fail.ts:4:6 -test 2 => ./test/fail.ts:7:6 -test 3 => ./test/fail.ts:10:6 -test 4 => ./test/fail.ts:13:6 -test 5 => ./test/fail.ts:16:6 -test 6 => ./test/fail.ts:19:6 -test 7 => ./test/fail.ts:22:6 -test 8 => ./test/fail.ts:25:6 -test 9 => ./test/fail.ts:28:6 - -FAILED | 0 passed | 10 failed ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/test/fail_fast.out b/tests/testdata/test/fail_fast.out deleted file mode 100644 index 606d5b345f..0000000000 --- a/tests/testdata/test/fail_fast.out +++ /dev/null @@ -1,20 +0,0 @@ -Check [WILDCARD]/test/fail_fast.ts -Check [WILDCARD]/test/fail_fast_other.ts -running 10 tests from ./test/fail_fast.ts -test 1 ... FAILED ([WILDCARD]) - - ERRORS - -test 1 => ./test/fail_fast.ts:[WILDCARD] -error: Error - throw new Error(); - ^ - at [WILDCARD]/test/fail_fast.ts:2:9 - - FAILURES - -test 1 => ./test/fail_fast.ts:[WILDCARD] - -FAILED | 0 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/test/fail_fast_with_val.out b/tests/testdata/test/fail_fast_with_val.out deleted file mode 100644 index a844b05c1a..0000000000 --- a/tests/testdata/test/fail_fast_with_val.out +++ /dev/null @@ -1,23 +0,0 @@ -[WILDCARD] -running 10 tests from [WILDCARD]/test/fail_fast_with_val.ts -test test 1 ... FAILED ([WILDCARD]) -test test 2 ... FAILED ([WILDCARD]) - - ERRORS - -test 1 => ./test/fail_fast_with_val.ts:[WILDCARD] -error: Error - at [WILDCARD]/test/fail_fast_with_val.ts:2:9 - at [WILDCARD] - -test 2 => ./test/fail_fast_with_val.ts:[WILDCARD] -error: Error - at [WILDCARD]/test/fail_fast_with_val.ts:5:9 - at [WILDCARD] - - FAILURES - -test 1 => ./test/fail_fast_with_val.ts:[WILDCARD] -test 2 => ./test/fail_fast_with_val.ts:[WILDCARD] - -FAILED | 0 passed | 2 failed ([WILDCARD]) diff --git a/tests/testdata/test/file_protocol.out b/tests/testdata/test/file_protocol.out deleted file mode 100644 index 3f9c73f7e3..0000000000 --- a/tests/testdata/test/file_protocol.out +++ /dev/null @@ -1,6 +0,0 @@ -Check file://[WILDCARD]/test/file_protocol.ts -running 1 test from ./test/file_protocol.ts -test 0 ... ok ([WILDCARD]) - -ok | 1 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/filter.out b/tests/testdata/test/filter.out deleted file mode 100644 index af3e43ab81..0000000000 --- a/tests/testdata/test/filter.out +++ /dev/null @@ -1,12 +0,0 @@ -Check [WILDCARD]/test/filter/a_test.ts -Check [WILDCARD]/test/filter/b_test.ts -Check [WILDCARD]/test/filter/c_test.ts -running 1 test from [WILDCARD]/test/filter/a_test.ts -foo ... ok ([WILDCARD]) -running 1 test from [WILDCARD]/test/filter/b_test.ts -foo ... ok ([WILDCARD]) -running 1 test from [WILDCARD]/test/filter/c_test.ts -foo ... ok ([WILDCARD]) - -ok | 3 passed | 0 failed | 6 filtered out ([WILDCARD]) - diff --git a/tests/testdata/test/finally_timeout.out b/tests/testdata/test/finally_timeout.out deleted file mode 100644 index 26153da06d..0000000000 --- a/tests/testdata/test/finally_timeout.out +++ /dev/null @@ -1,20 +0,0 @@ -Check [WILDCARD]/test/finally_timeout.ts -running 2 tests from ./test/finally_timeout.ts -error ... FAILED ([WILDCARD]) -success ... ok ([WILDCARD]) - - ERRORS - -error => ./test/finally_timeout.ts:[WILDCARD] -error: Error: fail - throw new Error("fail"); - ^ - at [WILDCARD]/test/finally_timeout.ts:4:11 - - FAILURES - -error => ./test/finally_timeout.ts:[WILDCARD] - -FAILED | 1 passed | 1 failed ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/test/glob/data/tes.ts b/tests/testdata/test/glob/data/tes.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/data/tes.ts +++ b/tests/testdata/test/glob/data/tes.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/data/test1.js b/tests/testdata/test/glob/data/test1.js index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/data/test1.js +++ b/tests/testdata/test/glob/data/test1.js @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/data/test1.ts b/tests/testdata/test/glob/data/test1.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/data/test1.ts +++ b/tests/testdata/test/glob/data/test1.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/data/test12.ts b/tests/testdata/test/glob/data/test12.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/data/test12.ts +++ b/tests/testdata/test/glob/data/test12.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/fizz/bar.ts b/tests/testdata/test/glob/nested/fizz/bar.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/fizz/bar.ts +++ b/tests/testdata/test/glob/nested/fizz/bar.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/fizz/bazz.ts b/tests/testdata/test/glob/nested/fizz/bazz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/fizz/bazz.ts +++ b/tests/testdata/test/glob/nested/fizz/bazz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/fizz/foo.ts b/tests/testdata/test/glob/nested/fizz/foo.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/fizz/foo.ts +++ b/tests/testdata/test/glob/nested/fizz/foo.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/foo/bar.ts b/tests/testdata/test/glob/nested/foo/bar.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/foo/bar.ts +++ b/tests/testdata/test/glob/nested/foo/bar.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/foo/bazz.ts b/tests/testdata/test/glob/nested/foo/bazz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/foo/bazz.ts +++ b/tests/testdata/test/glob/nested/foo/bazz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/foo/fizz.ts b/tests/testdata/test/glob/nested/foo/fizz.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/foo/fizz.ts +++ b/tests/testdata/test/glob/nested/foo/fizz.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/nested/foo/foo.ts b/tests/testdata/test/glob/nested/foo/foo.ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/nested/foo/foo.ts +++ b/tests/testdata/test/glob/nested/foo/foo.ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/glob/pages/[id].ts b/tests/testdata/test/glob/pages/[id].ts index 26f07fba54..6940729e9e 100644 --- a/tests/testdata/test/glob/pages/[id].ts +++ b/tests/testdata/test/glob/pages/[id].ts @@ -1,3 +1,2 @@ function foo() { - -} \ No newline at end of file +} diff --git a/tests/testdata/test/ignore_permissions.out b/tests/testdata/test/ignore_permissions.out deleted file mode 100644 index cc2574da9c..0000000000 --- a/tests/testdata/test/ignore_permissions.out +++ /dev/null @@ -1,6 +0,0 @@ -Check [WILDCARD]/test/ignore_permissions.ts -running 1 test from ./test/ignore_permissions.ts -ignore ... ignored ([WILDCARD]) - -ok | 0 passed | 0 failed | 1 ignored ([WILDCARD]) - diff --git a/tests/testdata/test/interval.out b/tests/testdata/test/interval.out deleted file mode 100644 index 1d0bc15ac2..0000000000 --- a/tests/testdata/test/interval.out +++ /dev/null @@ -1,5 +0,0 @@ -Check [WILDCARD]/test/interval.ts -running 0 tests from ./test/interval.ts - -ok | 0 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/junit_multiple_test_files.junit.out b/tests/testdata/test/junit_multiple_test_files.junit.out deleted file mode 100644 index bf6f3eaa4c..0000000000 --- a/tests/testdata/test/junit_multiple_test_files.junit.out +++ /dev/null @@ -1,102 +0,0 @@ -Check file:///[WILDCARD]/test/pass.ts -Check file:///[WILDCARD]/test/fail.ts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:2:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:5:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:8:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:11:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:14:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:17:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:20:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:23:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:26:9 - - - Error - throw new Error(); - ^ - at file:///[WILDCARD]/test/fail.ts:29:9 - - - -error: Test failed diff --git a/tests/testdata/test/markdown.out b/tests/testdata/test/markdown.out deleted file mode 100644 index 38c9f0349f..0000000000 --- a/tests/testdata/test/markdown.out +++ /dev/null @@ -1,7 +0,0 @@ -Check [WILDCARD]/test/markdown.md$11-14.js -Check [WILDCARD]/test/markdown.md$17-20.ts -Check [WILDCARD]/test/markdown.md$29-32.ts -error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. -const a: string = 42; - ^ - at [WILDCARD]/test/markdown.md$29-32.ts:1:7 diff --git a/tests/testdata/test/markdown_full_block_names.out b/tests/testdata/test/markdown_full_block_names.out deleted file mode 100644 index 13051112ea..0000000000 --- a/tests/testdata/test/markdown_full_block_names.out +++ /dev/null @@ -1,6 +0,0 @@ -Check [WILDCARD]/test/markdown_full_block_names.md$5-8.js -Check [WILDCARD]/test/markdown_full_block_names.md$17-20.ts -error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. -const a: string = 42; - ^ - at [WILDCARD]/test/markdown_full_block_names.md$17-20.ts:1:7 diff --git a/tests/testdata/test/markdown_windows.out b/tests/testdata/test/markdown_windows.out deleted file mode 100644 index 4810e50cd3..0000000000 --- a/tests/testdata/test/markdown_windows.out +++ /dev/null @@ -1,7 +0,0 @@ -Check [WILDCARD]/test/markdown_windows.md$11-14.js -Check [WILDCARD]/test/markdown_windows.md$17-20.ts -Check [WILDCARD]/test/markdown_windows.md$29-32.ts -error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. -const a: string = 42; - ^ - at [WILDCARD]/test/markdown_windows.md$29-32.ts:1:7 diff --git a/tests/testdata/test/markdown_with_comment.out b/tests/testdata/test/markdown_with_comment.out deleted file mode 100644 index b202919d8f..0000000000 --- a/tests/testdata/test/markdown_with_comment.out +++ /dev/null @@ -1,5 +0,0 @@ -Check [WILDCARD]/test/markdown_with_comment.md$34-37.ts -error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'. -const a: string = 42; - ^ - at [WILDCARD]/test/markdown_with_comment.md$34-37.ts:1:7 diff --git a/tests/testdata/test/nested_failures.junit.out b/tests/testdata/test/nested_failures.junit.out deleted file mode 100644 index 3e4d3c0d4b..0000000000 --- a/tests/testdata/test/nested_failures.junit.out +++ /dev/null @@ -1,47 +0,0 @@ -Check file:///[WILDCARD]/test/nested_failures.ts - - - - - 1 test step failed. - - - 2 test steps failed. - - - - - - - Error: Fail. - throw new Error("Fail."); - ^ - at file:///[WILDCARD]/test/nested_failures.ts:4:11 - [WILDCARD] - - - 1 test step failed. - - - - - Error: Fail. - throw new Error("Fail."); - ^ - at file:///[WILDCARD]/test/nested_failures.ts:12:13 - [WILDCARD] - - - Error: Fail. - throw new Error("Fail."); - ^ - at file:///[WILDCARD]/test/nested_failures.ts:16:11 - [WILDCARD] - - - - - - - -error: Test failed diff --git a/tests/testdata/test/no_prompt_by_default.out b/tests/testdata/test/no_prompt_by_default.out deleted file mode 100644 index a35e3f7aed..0000000000 --- a/tests/testdata/test/no_prompt_by_default.out +++ /dev/null @@ -1,16 +0,0 @@ -running 1 test from ./test/no_prompt_by_default.ts -no prompt ... FAILED ([WILDCARD]s) - - ERRORS - -no prompt => ./test/no_prompt_by_default.ts:[WILDCARD] -error: PermissionDenied: Requires read access to "./some_file.txt", run again with the --allow-read flag -[WILDCARD] - - FAILURES - -no prompt => ./test/no_prompt_by_default.ts:[WILDCARD] - -FAILED | 0 passed | 1 failed ([WILDCARD]s) - -error: Test failed diff --git a/tests/testdata/test/no_prompt_with_denied_perms.out b/tests/testdata/test/no_prompt_with_denied_perms.out deleted file mode 100644 index 4293ff1bb2..0000000000 --- a/tests/testdata/test/no_prompt_with_denied_perms.out +++ /dev/null @@ -1,16 +0,0 @@ -running 1 test from ./test/no_prompt_with_denied_perms.ts -no prompt ... FAILED ([WILDCARD]s) - - ERRORS - -no prompt => ./test/no_prompt_with_denied_perms.ts:[WILDCARD] -error: PermissionDenied: Requires read access to "./some_file.txt", run again with the --allow-read flag -[WILDCARD] - - FAILURES - -no prompt => ./test/no_prompt_with_denied_perms.ts:[WILDCARD] - -FAILED | 0 passed | 1 failed ([WILDCARD]s) - -error: Test failed diff --git a/tests/testdata/test/non_error_thrown.out b/tests/testdata/test/non_error_thrown.out deleted file mode 100644 index 6755f2905f..0000000000 --- a/tests/testdata/test/non_error_thrown.out +++ /dev/null @@ -1,40 +0,0 @@ -running 6 tests from [WILDCARD]/non_error_thrown.ts -foo ... FAILED ([WILDCARD]) -bar ... FAILED ([WILDCARD]) -baz ... FAILED ([WILDCARD]) -qux ... FAILED ([WILDCARD]) -quux ... FAILED ([WILDCARD]) -quuz ... FAILED ([WILDCARD]) - - ERRORS - -foo => [WILDCARD]/non_error_thrown.ts:1:6 -error: undefined - -bar => [WILDCARD]/non_error_thrown.ts:5:6 -error: null - -baz => [WILDCARD]/non_error_thrown.ts:9:6 -error: 123 - -qux => [WILDCARD]/non_error_thrown.ts:13:6 -error: "Hello, world!" - -quux => [WILDCARD]/non_error_thrown.ts:17:6 -error: [ 1, 2, 3 ] - -quuz => [WILDCARD]/non_error_thrown.ts:21:6 -error: { a: "Hello, world!", b: [ 1, 2, 3 ] } - - FAILURES - -foo => [WILDCARD]/non_error_thrown.ts:1:6 -bar => [WILDCARD]/non_error_thrown.ts:5:6 -baz => [WILDCARD]/non_error_thrown.ts:9:6 -qux => [WILDCARD]/non_error_thrown.ts:13:6 -quux => [WILDCARD]/non_error_thrown.ts:17:6 -quuz => [WILDCARD]/non_error_thrown.ts:21:6 - -FAILED | 0 passed | 6 failed ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/test/parallel_output.out b/tests/testdata/test/parallel_output.out deleted file mode 100644 index d3528a6e0b..0000000000 --- a/tests/testdata/test/parallel_output.out +++ /dev/null @@ -1,56 +0,0 @@ -Check [WILDCARD]/test/parallel_output.ts -./test/parallel_output.ts => step output ... step 1 ... ok ([WILDCARD]s) -./test/parallel_output.ts => step output ... step 2 ... ok ([WILDCARD]s) -------- output ------- -Hello, world! (from step 3) ------ output end ----- -./test/parallel_output.ts => step output ... step 3 ... ok ([WILDCARD]s) -------- output ------- -Hello, world! (from step 4) ------ output end ----- -./test/parallel_output.ts => step output ... step 4 ... ok ([WILDCARD]s) -./test/parallel_output.ts => step output ... ok ([WILDCARD]s) -./test/parallel_output.ts => step failures ... step 1 ... ok ([WILDCARD]s) -./test/parallel_output.ts => step failures ... step 2 ... FAILED ([WILDCARD]s) -./test/parallel_output.ts => step failures ... step 3 ... FAILED ([WILDCARD]s) -./test/parallel_output.ts => step failures ... FAILED (due to 2 failed steps) ([WILDCARD]s) -./test/parallel_output.ts => step nested failure ... step 1 ... inner 1 ... ok ([WILDCARD]s) -./test/parallel_output.ts => step nested failure ... step 1 ... inner 2 ... FAILED ([WILDCARD]s) -./test/parallel_output.ts => step nested failure ... step 1 ... FAILED (due to 1 failed step) ([WILDCARD]s) -./test/parallel_output.ts => step nested failure ... FAILED (due to 1 failed step) ([WILDCARD]s) - - ERRORS - -step failures ... step 2 => ./test/parallel_output.ts:14:11 -error: Error: Fail. - throw new Error("Fail."); - ^ - at file:///[WILDCARD]/test/parallel_output.ts:15:11 - at [WILDCARD] - at file:///[WILDCARD]/test/parallel_output.ts:14:11 - -step failures ... step 3 => ./test/parallel_output.ts:17:11 -error: Error: Fail. - await t.step("step 3", () => Promise.reject(new Error("Fail."))); - ^ - at file:///[WILDCARD]/test/parallel_output.ts:17:47 - at [WILDCARD] - at file:///[WILDCARD]/test/parallel_output.ts:17:11 - -step nested failure ... step 1 ... inner 2 => ./test/parallel_output.ts:23:13 -error: Error: Failed. - throw new Error("Failed."); - ^ - at file:///[WILDCARD]/test/parallel_output.ts:24:13 - at [WILDCARD] - at file:///[WILDCARD]/test/parallel_output.ts:23:13 - - FAILURES - -step failures ... step 2 => ./test/parallel_output.ts:14:11 -step failures ... step 3 => ./test/parallel_output.ts:17:11 -step nested failure ... step 1 ... inner 2 => ./test/parallel_output.ts:23:13 - -FAILED | 1 passed (6 steps) | 2 failed (4 steps) ([WILDCARD]s) - -error: Test failed diff --git a/tests/testdata/test/pass.junit.out b/tests/testdata/test/pass.junit.out deleted file mode 100644 index af9fd6f6b8..0000000000 --- a/tests/testdata/test/pass.junit.out +++ /dev/null @@ -1,38 +0,0 @@ -Check file:///[WILDCARD]/test/pass.ts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.out b/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.out deleted file mode 100644 index be88a6e1da..0000000000 --- a/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.out +++ /dev/null @@ -1,10 +0,0 @@ -Check [WILDCARD]/ops_sanitizer_step_leak.ts -running 1 test from [WILDCARD]/ops_sanitizer_step_leak.ts -timeout ... - step ... ok [WILDCARD] -------- output ------- -done ------ output end ----- -timeout ... ok [WILDCARD] - -ok | 1 passed (1 step) | 0 failed [WILDCARD] \ No newline at end of file diff --git a/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.ts b/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.ts deleted file mode 100644 index 3fb9b397e5..0000000000 --- a/tests/testdata/test/sanitizer/ops_sanitizer_step_leak.ts +++ /dev/null @@ -1,10 +0,0 @@ -Deno.test("timeout", async (t) => { - const timer = setTimeout(() => { - console.log("timeout"); - }, 10000); - clearTimeout(timer); - await t.step("step", async () => { - await new Promise((resolve) => setTimeout(() => resolve(), 10)); - }); - console.log("done"); -}); diff --git a/tests/testdata/test/sanitizer/trace_ops_caught_error/main.out b/tests/testdata/test/sanitizer/trace_ops_caught_error/main.out deleted file mode 100644 index 4e591adf1e..0000000000 --- a/tests/testdata/test/sanitizer/trace_ops_caught_error/main.out +++ /dev/null @@ -1,6 +0,0 @@ -Check file:///[WILDCARD]/trace_ops_caught_error/main.ts -running 1 test from [WILDCARD]/trace_ops_caught_error/main.ts -handle thrown error in async function ... ok ([WILDCARD]) - -ok | 1 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/short-pass-jobs-flag-warning.out b/tests/testdata/test/short-pass-jobs-flag-warning.out deleted file mode 100644 index 0d9e1fd9b5..0000000000 --- a/tests/testdata/test/short-pass-jobs-flag-warning.out +++ /dev/null @@ -1,8 +0,0 @@ -⚠️ The `--jobs` flag is deprecated and will be removed in Deno 2.0. -Use the `--parallel` flag with possibly the `DENO_JOBS` environment variable instead. -Learn more at: https://docs.deno.com/runtime/manual/basics/env_variables -Check [WILDCARD]/test/short-pass.ts -./test/short-pass.ts => test ... ok ([WILDCARD]) - -ok | 1 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/short-pass.out b/tests/testdata/test/short-pass.out deleted file mode 100644 index 3f239de414..0000000000 --- a/tests/testdata/test/short-pass.out +++ /dev/null @@ -1,5 +0,0 @@ -Check [WILDCARD]/test/short-pass.ts -./test/short-pass.ts => test ... ok ([WILDCARD]) - -ok | 1 passed | 0 failed ([WILDCARD]) - diff --git a/tests/testdata/test/steps/failing_steps.dot.out b/tests/testdata/test/steps/failing_steps.dot.out deleted file mode 100644 index f8ba8d8e62..0000000000 --- a/tests/testdata/test/steps/failing_steps.dot.out +++ /dev/null @@ -1,53 +0,0 @@ -! -. -! -! -! -! -! -! -! - - ERRORS - -nested failure ... step 1 ... inner 1 => ./test/steps/failing_steps.ts:[WILDCARD] -error: Error: Failed. - throw new Error("Failed."); - ^ - at [WILDCARD]/failing_steps.ts:[WILDCARD] - -multiple test step failures ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -error: Error: Fail. - throw new Error("Fail."); - ^ - at [WILDCARD]/failing_steps.ts:[WILDCARD] - -multiple test step failures ... step 2 => ./test/steps/failing_steps.ts:[WILDCARD] -error: Error: Fail. - await t.step("step 2", () => Promise.reject(new Error("Fail."))); - ^ - at [WILDCARD]/failing_steps.ts:[WILDCARD] - -failing step in failing test ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -error: Error: Fail. - throw new Error("Fail."); - ^ - at [WILDCARD]/failing_steps.ts:[WILDCARD] - -failing step in failing test => ./test/steps/failing_steps.ts:[WILDCARD] -error: Error: Fail test. - throw new Error("Fail test."); - ^ - at [WILDCARD]/failing_steps.ts:[WILDCARD] - - FAILURES - -nested failure ... step 1 ... inner 1 => ./test/steps/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -multiple test step failures ... step 2 => ./test/steps/failing_steps.ts:[WILDCARD] -failing step in failing test ... step 1 => ./test/steps/failing_steps.ts:[WILDCARD] -failing step in failing test => ./test/steps/failing_steps.ts:[WILDCARD] - -FAILED | 0 passed (1 step) | 3 failed (5 steps) ([WILDCARD]) - -error: Test failed diff --git a/tests/testdata/vendor/dynamic.ts b/tests/testdata/vendor/dynamic.ts deleted file mode 100644 index e2cbb0e59e..0000000000 --- a/tests/testdata/vendor/dynamic.ts +++ /dev/null @@ -1,3 +0,0 @@ -const { Logger } = await import("./logger.ts"); - -export { Logger }; diff --git a/tests/testdata/vendor/dynamic_non_analyzable.ts b/tests/testdata/vendor/dynamic_non_analyzable.ts deleted file mode 100644 index 1847939f64..0000000000 --- a/tests/testdata/vendor/dynamic_non_analyzable.ts +++ /dev/null @@ -1,4 +0,0 @@ -const value = (() => "./logger.ts")(); -const { Logger } = await import(value); - -export { Logger }; diff --git a/tests/testdata/vendor/dynamic_non_existent.ts b/tests/testdata/vendor/dynamic_non_existent.ts deleted file mode 100644 index a48e2accb0..0000000000 --- a/tests/testdata/vendor/dynamic_non_existent.ts +++ /dev/null @@ -1,11 +0,0 @@ -// this should still vendor -// deno-lint-ignore no-constant-condition -if (false) { - await import("./non-existent.js"); -} - -export class Logger { - log(text: string) { - console.log(text); - } -} diff --git a/tests/testdata/vendor/dynamic_non_existent.ts.out b/tests/testdata/vendor/dynamic_non_existent.ts.out deleted file mode 100644 index 1bbd01f7b4..0000000000 --- a/tests/testdata/vendor/dynamic_non_existent.ts.out +++ /dev/null @@ -1,9 +0,0 @@ -⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0. -Add `"vendor": true` to your `deno.json` or use the `--vendor` flag instead. -Download http://localhost:4545/vendor/dynamic_non_existent.ts -Download http://localhost:4545/vendor/non-existent.js -Ignoring: Dynamic import not found "http://localhost:4545/vendor/non-existent.js". - at http://localhost:4545/vendor/dynamic_non_existent.ts:4:16 -Vendored 1 module into vendor/ directory. - -To use vendored modules, specify the `--import-map vendor/import_map.json` flag when invoking Deno subcommands or add an `"importMap": ""` entry to a deno.json file. diff --git a/tests/testdata/vendor/logger.ts b/tests/testdata/vendor/logger.ts deleted file mode 100644 index 97f603a48b..0000000000 --- a/tests/testdata/vendor/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class Logger { - log(text: string) { - console.log(text); - } -} diff --git a/tests/testdata/vendor/mod.ts b/tests/testdata/vendor/mod.ts deleted file mode 100644 index 8824d1b2ae..0000000000 --- a/tests/testdata/vendor/mod.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./logger.ts"; diff --git a/tests/testdata/vendor/npm_and_node_specifier.ts b/tests/testdata/vendor/npm_and_node_specifier.ts deleted file mode 100644 index 61962e836b..0000000000 --- a/tests/testdata/vendor/npm_and_node_specifier.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as path } from "node:path"; -export { getValue, setValue } from "npm:@denotest/esm-basic"; diff --git a/tests/testdata/vendor/query_reexport.ts b/tests/testdata/vendor/query_reexport.ts deleted file mode 100644 index 5dfafb5329..0000000000 --- a/tests/testdata/vendor/query_reexport.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./logger.ts?test"; diff --git a/tests/testdata/workers/error_worker_permissions_remote.ts.out b/tests/testdata/workers/error_worker_permissions_remote.ts.out deleted file mode 100644 index afecff0a88..0000000000 --- a/tests/testdata/workers/error_worker_permissions_remote.ts.out +++ /dev/null @@ -1,2 +0,0 @@ -error: Uncaught (in worker "") Requires net access to "localhost:4545", run again with the --allow-net flag -[WILDCARD] diff --git a/tests/testdata/workers/http_worker.js b/tests/testdata/workers/http_worker.js index c617e2e92f..27bc9c038c 100644 --- a/tests/testdata/workers/http_worker.js +++ b/tests/testdata/workers/http_worker.js @@ -6,6 +6,7 @@ const listener = Deno.listen({ hostname: "127.0.0.1", port: 4506 }); postMessage("ready"); for await (const conn of listener) { (async () => { + // @ts-ignore `Deno.serveHttp()` was soft-removed in Deno 2. const requests = Deno.serveHttp(conn); for await (const { respondWith } of requests) { respondWith(new Response("Hello world")); diff --git a/tests/testdata/workers/no_permissions_worker.js b/tests/testdata/workers/no_permissions_worker.js index f49f690abe..505f3b925b 100644 --- a/tests/testdata/workers/no_permissions_worker.js +++ b/tests/testdata/workers/no_permissions_worker.js @@ -1,13 +1,11 @@ self.onmessage = async () => { - const hrtime = await Deno.permissions.query({ name: "hrtime" }); const net = await Deno.permissions.query({ name: "net" }); const ffi = await Deno.permissions.query({ name: "ffi" }); const read = await Deno.permissions.query({ name: "read" }); const run = await Deno.permissions.query({ name: "run" }); const write = await Deno.permissions.query({ name: "write" }); self.postMessage( - hrtime.state === "prompt" && - net.state === "prompt" && + net.state === "prompt" && ffi.state === "prompt" && read.state === "prompt" && run.state === "prompt" && diff --git a/tests/testdata/workers/permission_echo.js b/tests/testdata/workers/permission_echo.js index f492a25f26..501eaf2ca2 100644 --- a/tests/testdata/workers/permission_echo.js +++ b/tests/testdata/workers/permission_echo.js @@ -1,7 +1,6 @@ self.onmessage = async () => { const env = await Deno.permissions.query({ name: "env" }); const ffi = await Deno.permissions.query({ name: "ffi" }); - const hrtime = await Deno.permissions.query({ name: "hrtime" }); const net = await Deno.permissions.query({ name: "net" }); const read = await Deno.permissions.query({ name: "read" }); const run = await Deno.permissions.query({ name: "run" }); @@ -9,7 +8,6 @@ self.onmessage = async () => { self.postMessage({ env: env.state, ffi: ffi.state, - hrtime: hrtime.state, net: net.state, read: read.state, run: run.state, diff --git a/tests/testdata/workers/permissions_remote_remote.ts.out b/tests/testdata/workers/permissions_remote_remote.ts.out deleted file mode 100644 index a095f1938b..0000000000 --- a/tests/testdata/workers/permissions_remote_remote.ts.out +++ /dev/null @@ -1,4 +0,0 @@ -error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag - at http://localhost:4545/workers/static_remote.ts:2:8 -error: Uncaught (in promise) Error: Unhandled error in child worker. - at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/read_check_granular_worker.js b/tests/testdata/workers/read_check_granular_worker.js index d40fac876c..01df8ca97d 100644 --- a/tests/testdata/workers/read_check_granular_worker.js +++ b/tests/testdata/workers/read_check_granular_worker.js @@ -1,9 +1,20 @@ // deno-fmt-ignore-file +import { toFileUrl } from "@std/path/to-file-url"; + +function tryGetCwd() { + // will throw in one test but not the other + try { + return Deno.cwd() + } catch { + return import.meta.dirname; + } +} + +const fooExePath = tryGetCwd() + "/foo" + (Deno.build.os === "windows" ? ".exe" : ""); postMessage({ envGlobal: (await Deno.permissions.query({ name: "env" })).state, envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state, envAbsent: (await Deno.permissions.query({ name: "env", variable: "absent" })).state, - hrtime: (await Deno.permissions.query({ name: "hrtime" })).state, netGlobal: (await Deno.permissions.query({ name: "net" })).state, netFoo: (await Deno.permissions.query({ name: "net", host: "foo" })).state, netFoo8000: (await Deno.permissions.query({ name: "net", host: "foo:8000" })).state, @@ -16,11 +27,13 @@ postMessage({ readGlobal: (await Deno.permissions.query({ name: "read" })).state, readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state, readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state, - readAbsent: (await Deno.permissions.query({ name: "read", path: "absent" })).state, + readAbsent: (await Deno.permissions.query({ name: "read", path: "../absent" })).state, runGlobal: (await Deno.permissions.query({ name: "run" })).state, - runFoo: (await Deno.permissions.query({ name: "run", command: new URL("foo", import.meta.url) })).state, + runFoo: (await Deno.permissions.query({ name: "run", command: toFileUrl(fooExePath) })).state, + runFooPath: (await Deno.permissions.query({ name: "run", command: fooExePath })).state, runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state, runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state, + runUnresolved: (await Deno.permissions.query({ name: "run", command: "unresolved-exec" })).state, runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state, writeGlobal: (await Deno.permissions.query({ name: "write" })).state, writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state, diff --git a/tests/testdata/workers/static_remote.ts b/tests/testdata/workers/static_remote.ts index 2d6e820fd6..6bb64eccdb 100644 --- a/tests/testdata/workers/static_remote.ts +++ b/tests/testdata/workers/static_remote.ts @@ -1,2 +1,2 @@ -// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +// This file doesn't really exist, but it doesn't matter, a "NotCapable" error should be thrown. import "https://example.com/some/file.ts"; diff --git a/tests/unit/README.md b/tests/unit/README.md index af31c08fcc..549a9d3caa 100644 --- a/tests/unit/README.md +++ b/tests/unit/README.md @@ -30,10 +30,10 @@ There are two ways to run `unit_test_runner.ts`: ```sh # Run all tests. -cargo run --bin deno -- test --allow-all --unstable --location=http://js-unit-tests/foo/bar cli/tests/unit/ +cargo run --bin deno -- test --allow-all --location=http://js-unit-tests/foo/bar cli/tests/unit/ # Run a specific test module -cargo run --bin deno -- test --allow-all --unstable --location=http://js-unit-tests/foo/bar cli/tests/unit/files_test.ts +cargo run --bin deno -- test --allow-all --location=http://js-unit-tests/foo/bar cli/tests/unit/files_test.ts ``` ### Http server diff --git a/tests/unit/buffer_test.ts b/tests/unit/buffer_test.ts deleted file mode 100644 index 2215748825..0000000000 --- a/tests/unit/buffer_test.ts +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -// deno-lint-ignore-file no-deprecated-deno-api - -// This code has been ported almost directly from Go's src/bytes/buffer_test.go -// Copyright 2009 The Go Authors. All rights reserved. BSD license. -// https://github.com/golang/go/blob/master/LICENSE -import { - assert, - assertEquals, - assertRejects, - assertThrows, -} from "./test_util.ts"; -import { writeAllSync } from "@std/io/write-all"; - -const MAX_SIZE = 2 ** 32 - 2; -// N controls how many iterations of certain checks are performed. -const N = 100; -let testBytes: Uint8Array | null; -let testString: string | null; - -const ignoreMaxSizeTests = true; - -function init() { - if (testBytes == null) { - testBytes = new Uint8Array(N); - for (let i = 0; i < N; i++) { - testBytes[i] = "a".charCodeAt(0) + (i % 26); - } - const decoder = new TextDecoder(); - testString = decoder.decode(testBytes); - } -} - -function check(buf: Deno.Buffer, s: string) { - const bytes = buf.bytes(); - assertEquals(buf.length, bytes.byteLength); - const decoder = new TextDecoder(); - const bytesStr = decoder.decode(bytes); - assertEquals(bytesStr, s); - assertEquals(buf.length, s.length); -} - -// Fill buf through n writes of byte slice fub. -// The initial contents of buf corresponds to the string s; -// the result is the final contents of buf returned as a string. -async function fillBytes( - buf: Deno.Buffer, - s: string, - n: number, - fub: Uint8Array, -): Promise { - check(buf, s); - for (; n > 0; n--) { - const m = await buf.write(fub); - assertEquals(m, fub.byteLength); - const decoder = new TextDecoder(); - s += decoder.decode(fub); - check(buf, s); - } - return s; -} - -// Empty buf through repeated reads into fub. -// The initial contents of buf corresponds to the string s. -async function empty( - buf: Deno.Buffer, - s: string, - fub: Uint8Array, -) { - check(buf, s); - while (true) { - const r = await buf.read(fub); - if (r === null) { - break; - } - s = s.slice(r); - check(buf, s); - } - check(buf, ""); -} - -function repeat(c: string, bytes: number): Uint8Array { - assertEquals(c.length, 1); - const ui8 = new Uint8Array(bytes); - ui8.fill(c.charCodeAt(0)); - return ui8; -} - -Deno.test(function bufferNewBuffer() { - init(); - assert(testBytes); - assert(testString); - const buf = new Deno.Buffer(testBytes.buffer as ArrayBuffer); - check(buf, testString); -}); - -Deno.test(async function bufferBasicOperations() { - init(); - assert(testBytes); - assert(testString); - const buf = new Deno.Buffer(); - for (let i = 0; i < 5; i++) { - check(buf, ""); - - buf.reset(); - check(buf, ""); - - buf.truncate(0); - check(buf, ""); - - let n = await buf.write(testBytes.subarray(0, 1)); - assertEquals(n, 1); - check(buf, "a"); - - n = await buf.write(testBytes.subarray(1, 2)); - assertEquals(n, 1); - check(buf, "ab"); - - n = await buf.write(testBytes.subarray(2, 26)); - assertEquals(n, 24); - check(buf, testString.slice(0, 26)); - - buf.truncate(26); - check(buf, testString.slice(0, 26)); - - buf.truncate(20); - check(buf, testString.slice(0, 20)); - - await empty(buf, testString.slice(0, 20), new Uint8Array(5)); - await empty(buf, "", new Uint8Array(100)); - - // TODO(bartlomieju): buf.writeByte() - // TODO(bartlomieju): buf.readByte() - } -}); - -Deno.test(async function bufferReadEmptyAtEOF() { - // check that EOF of 'buf' is not reached (even though it's empty) if - // results are written to buffer that has 0 length (ie. it can't store any data) - const buf = new Deno.Buffer(); - const zeroLengthTmp = new Uint8Array(0); - const result = await buf.read(zeroLengthTmp); - assertEquals(result, 0); -}); - -Deno.test(async function bufferLargeByteWrites() { - init(); - const buf = new Deno.Buffer(); - const limit = 9; - for (let i = 3; i < limit; i += 3) { - const s = await fillBytes(buf, "", 5, testBytes!); - await empty(buf, s, new Uint8Array(Math.floor(testString!.length / i))); - } - check(buf, ""); -}); - -Deno.test(async function bufferTooLargeByteWrites() { - init(); - const tmp = new Uint8Array(72); - const growLen = Number.MAX_VALUE; - const xBytes = repeat("x", 0); - const buf = new Deno.Buffer(xBytes.buffer as ArrayBuffer); - await buf.read(tmp); - - assertThrows( - () => { - buf.grow(growLen); - }, - Error, - "grown beyond the maximum size", - ); -}); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - function bufferGrowWriteMaxBuffer() { - const bufSize = 16 * 1024; - const capacities = [MAX_SIZE, MAX_SIZE - 1]; - for (const capacity of capacities) { - let written = 0; - const buf = new Deno.Buffer(); - const writes = Math.floor(capacity / bufSize); - for (let i = 0; i < writes; i++) { - written += buf.writeSync(repeat("x", bufSize)); - } - - if (written < capacity) { - written += buf.writeSync(repeat("x", capacity - written)); - } - - assertEquals(written, capacity); - } - }, -); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - async function bufferGrowReadCloseMaxBufferPlus1() { - const reader = new Deno.Buffer(new ArrayBuffer(MAX_SIZE + 1)); - const buf = new Deno.Buffer(); - - await assertRejects( - async () => { - await buf.readFrom(reader); - }, - Error, - "grown beyond the maximum size", - ); - }, -); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - function bufferGrowReadSyncCloseMaxBufferPlus1() { - const reader = new Deno.Buffer(new ArrayBuffer(MAX_SIZE + 1)); - const buf = new Deno.Buffer(); - - assertThrows( - () => { - buf.readFromSync(reader); - }, - Error, - "grown beyond the maximum size", - ); - }, -); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - function bufferGrowReadSyncCloseToMaxBuffer() { - const capacities = [MAX_SIZE, MAX_SIZE - 1]; - for (const capacity of capacities) { - const reader = new Deno.Buffer(new ArrayBuffer(capacity)); - const buf = new Deno.Buffer(); - buf.readFromSync(reader); - - assertEquals(buf.length, capacity); - } - }, -); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - async function bufferGrowReadCloseToMaxBuffer() { - const capacities = [MAX_SIZE, MAX_SIZE - 1]; - for (const capacity of capacities) { - const reader = new Deno.Buffer(new ArrayBuffer(capacity)); - const buf = new Deno.Buffer(); - await buf.readFrom(reader); - assertEquals(buf.length, capacity); - } - }, -); - -Deno.test( - { ignore: ignoreMaxSizeTests }, - async function bufferReadCloseToMaxBufferWithInitialGrow() { - const capacities = [MAX_SIZE, MAX_SIZE - 1, MAX_SIZE - 512]; - for (const capacity of capacities) { - const reader = new Deno.Buffer(new ArrayBuffer(capacity)); - const buf = new Deno.Buffer(); - buf.grow(MAX_SIZE); - await buf.readFrom(reader); - assertEquals(buf.length, capacity); - } - }, -); - -Deno.test(async function bufferLargeByteReads() { - init(); - assert(testBytes); - assert(testString); - const buf = new Deno.Buffer(); - for (let i = 3; i < 30; i += 3) { - const n = Math.floor(testBytes.byteLength / i); - const s = await fillBytes(buf, "", 5, testBytes.subarray(0, n)); - await empty(buf, s, new Uint8Array(testString.length)); - } - check(buf, ""); -}); - -Deno.test(function bufferCapWithPreallocatedSlice() { - const buf = new Deno.Buffer(new ArrayBuffer(10)); - assertEquals(buf.capacity, 10); -}); - -Deno.test(async function bufferReadFrom() { - init(); - assert(testBytes); - assert(testString); - const buf = new Deno.Buffer(); - for (let i = 3; i < 30; i += 3) { - const s = await fillBytes( - buf, - "", - 5, - testBytes.subarray(0, Math.floor(testBytes.byteLength / i)), - ); - const b = new Deno.Buffer(); - await b.readFrom(buf); - const fub = new Uint8Array(testString.length); - await empty(b, s, fub); - } - await assertRejects(async function () { - await new Deno.Buffer().readFrom(null!); - }); -}); - -Deno.test(async function bufferReadFromSync() { - init(); - assert(testBytes); - assert(testString); - const buf = new Deno.Buffer(); - for (let i = 3; i < 30; i += 3) { - const s = await fillBytes( - buf, - "", - 5, - testBytes.subarray(0, Math.floor(testBytes.byteLength / i)), - ); - const b = new Deno.Buffer(); - b.readFromSync(buf); - const fub = new Uint8Array(testString.length); - await empty(b, s, fub); - } - assertThrows(function () { - new Deno.Buffer().readFromSync(null!); - }); -}); - -Deno.test(async function bufferTestGrow() { - const tmp = new Uint8Array(72); - for (const startLen of [0, 100, 1000, 10000]) { - const xBytes = repeat("x", startLen); - for (const growLen of [0, 100, 1000, 10000]) { - const buf = new Deno.Buffer(xBytes.buffer as ArrayBuffer); - // If we read, this affects buf.off, which is good to test. - const nread = (await buf.read(tmp)) ?? 0; - buf.grow(growLen); - const yBytes = repeat("y", growLen); - await buf.write(yBytes); - // Check that buffer has correct data. - assertEquals( - buf.bytes().subarray(0, startLen - nread), - xBytes.subarray(nread), - ); - assertEquals( - buf.bytes().subarray(startLen - nread, startLen - nread + growLen), - yBytes, - ); - } - } -}); - -Deno.test(async function testReadAll() { - init(); - assert(testBytes); - const reader = new Deno.Buffer(testBytes.buffer as ArrayBuffer); - const actualBytes = await Deno.readAll(reader); - assertEquals(testBytes.byteLength, actualBytes.byteLength); - for (let i = 0; i < testBytes.length; ++i) { - assertEquals(testBytes[i], actualBytes[i]); - } -}); - -Deno.test(function testReadAllSync() { - init(); - assert(testBytes); - const reader = new Deno.Buffer(testBytes.buffer as ArrayBuffer); - const actualBytes = Deno.readAllSync(reader); - assertEquals(testBytes.byteLength, actualBytes.byteLength); - for (let i = 0; i < testBytes.length; ++i) { - assertEquals(testBytes[i], actualBytes[i]); - } -}); - -Deno.test(async function testWriteAll() { - init(); - assert(testBytes); - const writer = new Deno.Buffer(); - await Deno.writeAll(writer, testBytes); - const actualBytes = writer.bytes(); - assertEquals(testBytes.byteLength, actualBytes.byteLength); - for (let i = 0; i < testBytes.length; ++i) { - assertEquals(testBytes[i], actualBytes[i]); - } -}); - -Deno.test(function testWriteAllSync() { - init(); - assert(testBytes); - const writer = new Deno.Buffer(); - Deno.writeAllSync(writer, testBytes); - const actualBytes = writer.bytes(); - assertEquals(testBytes.byteLength, actualBytes.byteLength); - for (let i = 0; i < testBytes.length; ++i) { - assertEquals(testBytes[i], actualBytes[i]); - } -}); - -Deno.test(function testBufferBytesArrayBufferLength() { - // defaults to copy - const args = [{}, { copy: undefined }, undefined, { copy: true }]; - for (const arg of args) { - const bufSize = 64 * 1024; - const bytes = new TextEncoder().encode("a".repeat(bufSize)); - const reader = new Deno.Buffer(); - writeAllSync(reader, bytes); - - const writer = new Deno.Buffer(); - writer.readFromSync(reader); - const actualBytes = writer.bytes(arg); - - assertEquals(actualBytes.byteLength, bufSize); - assert(actualBytes.buffer !== writer.bytes(arg).buffer); - assertEquals(actualBytes.byteLength, actualBytes.buffer.byteLength); - } -}); - -Deno.test(function testBufferBytesCopyFalse() { - const bufSize = 64 * 1024; - const bytes = new TextEncoder().encode("a".repeat(bufSize)); - const reader = new Deno.Buffer(); - writeAllSync(reader, bytes); - - const writer = new Deno.Buffer(); - writer.readFromSync(reader); - const actualBytes = writer.bytes({ copy: false }); - - assertEquals(actualBytes.byteLength, bufSize); - assertEquals(actualBytes.buffer, writer.bytes({ copy: false }).buffer); - assert(actualBytes.buffer.byteLength > actualBytes.byteLength); -}); - -Deno.test(function testBufferBytesCopyFalseGrowExactBytes() { - const bufSize = 64 * 1024; - const bytes = new TextEncoder().encode("a".repeat(bufSize)); - const reader = new Deno.Buffer(); - writeAllSync(reader, bytes); - - const writer = new Deno.Buffer(); - writer.grow(bufSize); - writer.readFromSync(reader); - const actualBytes = writer.bytes({ copy: false }); - - assertEquals(actualBytes.byteLength, bufSize); - assertEquals(actualBytes.buffer.byteLength, actualBytes.byteLength); -}); - -Deno.test(function testThrowsErrorWhenBufferExceedsMaxLength() { - const kStringMaxLengthPlusOne = 536870888 + 1; - const bytes = new Uint8Array(kStringMaxLengthPlusOne); - - assertThrows( - () => { - new TextDecoder().decode(bytes); - }, - TypeError, - "buffer exceeds maximum length", - ); -}); diff --git a/tests/unit/cache_api_test.ts b/tests/unit/cache_api_test.ts index 792929870d..08f768e334 100644 --- a/tests/unit/cache_api_test.ts +++ b/tests/unit/cache_api_test.ts @@ -118,7 +118,7 @@ Deno.test(async function cachePutReaderLock() { await response.arrayBuffer(); }, TypeError, - "Body already consumed.", + "Body already consumed", ); await promise; diff --git a/tests/unit/chmod_test.ts b/tests/unit/chmod_test.ts index df3771bbc1..9ff6301e28 100644 --- a/tests/unit/chmod_test.ts +++ b/tests/unit/chmod_test.ts @@ -94,7 +94,7 @@ Deno.test({ permissions: { write: true } }, function chmodSyncFailure() { Deno.test({ permissions: { write: false } }, function chmodSyncPerm() { assertThrows(() => { Deno.chmodSync("/somefile.txt", 0o777); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -186,5 +186,5 @@ Deno.test({ permissions: { write: true } }, async function chmodFailure() { Deno.test({ permissions: { write: false } }, async function chmodPerm() { await assertRejects(async () => { await Deno.chmod("/somefile.txt", 0o777); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); diff --git a/tests/unit/chown_test.ts b/tests/unit/chown_test.ts index 033d4592d6..eda4d34037 100644 --- a/tests/unit/chown_test.ts +++ b/tests/unit/chown_test.ts @@ -26,7 +26,7 @@ Deno.test( const filePath = "chown_test_file.txt"; await assertRejects(async () => { await Deno.chown(filePath, 1000, 1000); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/command_test.ts b/tests/unit/command_test.ts index dd83525473..51bbdd8600 100644 --- a/tests/unit/command_test.ts +++ b/tests/unit/command_test.ts @@ -73,8 +73,16 @@ Deno.test( }); const child = command.spawn(); - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); + assertThrows( + () => child.stdout, + TypeError, + "Cannot get 'stdout': 'stdout' is not piped", + ); + assertThrows( + () => child.stderr, + TypeError, + "Cannot get 'stderr': 'stderr' is not piped", + ); const msg = new TextEncoder().encode("hello"); const writer = child.stdin.getWriter(); @@ -99,9 +107,21 @@ Deno.test( }); const child = command.spawn(); - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); + assertThrows( + () => child.stdin, + TypeError, + "Cannot get 'stdin': 'stdin' is not piped", + ); + assertThrows( + () => child.stdout, + TypeError, + "Cannot get 'stdout': 'stdout' is not piped", + ); + assertThrows( + () => child.stderr, + TypeError, + "Cannot get 'stderr': 'stderr' is not piped", + ); await child.status; }, @@ -120,8 +140,16 @@ Deno.test( }); const child = command.spawn(); - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stderr, TypeError, "stderr is not piped"); + assertThrows( + () => child.stdin, + TypeError, + "Cannot get 'stdin': 'stdin' is not piped", + ); + assertThrows( + () => child.stderr, + TypeError, + "Cannot get 'stderr': 'stderr' is not piped", + ); const readable = child.stdout.pipeThrough(new TextDecoderStream()); const reader = readable.getReader(); @@ -154,8 +182,16 @@ Deno.test( }); const child = command.spawn(); - assertThrows(() => child.stdin, TypeError, "stdin is not piped"); - assertThrows(() => child.stdout, TypeError, "stdout is not piped"); + assertThrows( + () => child.stdin, + TypeError, + "Cannot get 'stdin': 'stdin' is not piped", + ); + assertThrows( + () => child.stdout, + TypeError, + "Cannot get 'stdout': 'stdout' is not piped", + ); const readable = child.stderr.pipeThrough(new TextDecoderStream()); const reader = readable.getReader(); @@ -382,7 +418,7 @@ Deno.test( await new Deno.Command(Deno.execPath(), { args: ["eval", "console.log('hello world')"], }).output(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -393,7 +429,7 @@ Deno.test( new Deno.Command(Deno.execPath(), { args: ["eval", "console.log('hello world')"], }).outputSync(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -528,7 +564,7 @@ Deno.test( }, async function commandFailedWithSignal() { const output = await new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], + args: ["eval", "Deno.kill(Deno.pid, 'SIGKILL')"], }).output(); assertEquals(output.success, false); if (Deno.build.os === "windows") { @@ -547,7 +583,7 @@ Deno.test( }, function commandSyncFailedWithSignal() { const output = new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], + args: ["eval", "Deno.kill(Deno.pid, 'SIGKILL')"], }).outputSync(); assertEquals(output.success, false); if (Deno.build.os === "windows") { @@ -835,7 +871,7 @@ Deno.test( const command = await new Deno.Command(Deno.execPath(), { cwd: Deno.args[0], stdout: "piped", - args: ["run", "-A", "--unstable", Deno.args[1]], + args: ["run", "-A", Deno.args[1]], }); const child = command.spawn(); const readable = child.stdout.pipeThrough(new TextDecoderStream()); @@ -877,7 +913,7 @@ setInterval(() => { Deno.execPath(), { cwd, - args: ["run", "-A", "--unstable", programFile, cwd, childProgramFile], + args: ["run", "-A", programFile, cwd, childProgramFile], }, ).output(); @@ -955,7 +991,7 @@ Deno.test( assertThrows( () => child.kill(), TypeError, - "Child process has already terminated.", + "Child process has already terminated", ); }, ); @@ -975,3 +1011,56 @@ Deno.test( ); }, ); + +Deno.test( + { permissions: { write: true, run: true, read: true } }, + async function commandWithCwdOrPath() { + const cwd = Deno.makeTempDirSync({ prefix: "deno_command_test" }); + try { + const suffix = Deno.build.os === "windows" ? ".exe" : ""; + Deno.mkdirSync(`${cwd}/subdir`); + Deno.copyFileSync(Deno.execPath(), `${cwd}/subdir/my_binary${suffix}`); + // cwd + { + const output = await new Deno.Command(`./my_binary${suffix}`, { + cwd: `${cwd}/subdir`, + args: ["-v"], + }).output(); + assertEquals(output.success, true); + } + // path + { + const output = await new Deno.Command(`my_binary${suffix}`, { + env: { + PATH: `${cwd}/subdir`, + }, + args: ["-v"], + }).output(); + assertEquals(output.success, true); + } + } finally { + Deno.removeSync(cwd, { recursive: true }); + } + }, +); + +Deno.test(async function outputWhenManuallyConsumingStreams() { + const command = new Deno.Command(Deno.execPath(), { + args: ["eval", "console.log('hello world')"], + stdout: "piped", + stderr: "piped", + }); + const child = command.spawn(); + for await (const _ of child.stdout) { + // consume stdout + } + for await (const _ of child.stderr) { + // consume stderr + } + const status = await child.output(); + assertEquals(status.success, true); + assertEquals(status.code, 0); + assertEquals(status.signal, null); + assertEquals(status.stdout, new Uint8Array()); + assertEquals(status.stderr, new Uint8Array()); +}); diff --git a/tests/unit/console_test.ts b/tests/unit/console_test.ts index c133624196..06f5dd7e61 100644 --- a/tests/unit/console_test.ts +++ b/tests/unit/console_test.ts @@ -8,6 +8,8 @@ // std/fmt/colors auto determines whether to put colors in or not. We need // better infrastructure here so we can properly test the colors. +// deno-lint-ignore-file no-console + import { assert, assertEquals, @@ -1160,7 +1162,7 @@ Deno.test(function consoleTestWithIntegerFormatSpecifier() { assertEquals(stringify("%i"), "%i"); assertEquals(stringify("%i", 42.0), "42"); assertEquals(stringify("%i", 42), "42"); - assertEquals(stringify("%i", "42"), "NaN"); + assertEquals(stringify("%i", "42"), "42"); assertEquals(stringify("%i", 1.5), "1"); assertEquals(stringify("%i", -0.5), "0"); assertEquals(stringify("%i", ""), "NaN"); @@ -1170,7 +1172,7 @@ Deno.test(function consoleTestWithIntegerFormatSpecifier() { assertEquals(stringify("%d", 12345678901234567890123), "1"); assertEquals( stringify("%i", 12345678901234567890123n), - "12345678901234567890123n", + "1.2345678901234568e+22", ); }); @@ -1178,13 +1180,13 @@ Deno.test(function consoleTestWithFloatFormatSpecifier() { assertEquals(stringify("%f"), "%f"); assertEquals(stringify("%f", 42.0), "42"); assertEquals(stringify("%f", 42), "42"); - assertEquals(stringify("%f", "42"), "NaN"); + assertEquals(stringify("%f", "42"), "42"); assertEquals(stringify("%f", 1.5), "1.5"); assertEquals(stringify("%f", -0.5), "-0.5"); assertEquals(stringify("%f", Math.PI), "3.141592653589793"); assertEquals(stringify("%f", ""), "NaN"); assertEquals(stringify("%f", Symbol("foo")), "NaN"); - assertEquals(stringify("%f", 5n), "NaN"); + assertEquals(stringify("%f", 5n), "5"); assertEquals(stringify("%f %f", 42, 43), "42 43"); assertEquals(stringify("%f %f", 42), "42 %f"); }); @@ -1225,6 +1227,7 @@ Deno.test(function consoleParseCssColor() { assertEquals(parseCssColor("inherit"), null); assertEquals(parseCssColor("black"), [0, 0, 0]); assertEquals(parseCssColor("darkmagenta"), [139, 0, 139]); + assertEquals(parseCssColor("darkMaGenta"), [139, 0, 139]); assertEquals(parseCssColor("slateblue"), [106, 90, 205]); assertEquals(parseCssColor("#ffaa00"), [255, 170, 0]); assertEquals(parseCssColor("#ffAA00"), [255, 170, 0]); @@ -1892,6 +1895,40 @@ Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedTypedArray() { }); }); +Deno.test(function consoleLogWhenCauseIsAssignedShouldNotPrintCauseTwice() { + mockConsole((console, out) => { + const typeError = new TypeError("Type incorrect"); + const syntaxError = new SyntaxError("Improper syntax"); + typeError.cause = syntaxError; + console.log(typeError); + const result = stripAnsiCode(out.toString()); + // Filter out stack trace lines, keeping only the first line and the cause line + const filteredOutput = result + .split("\n") + .filter((line) => !line.trim().startsWith("at")) + .join("\n"); + + const expectedResult = + "TypeError: Type incorrect\nCaused by SyntaxError: Improper syntax\n"; + assertEquals(filteredOutput.trim(), expectedResult.trim()); + }); +}); + +Deno.test(function consoleLogCauseNotFilteredOnNonError() { + mockConsole((console, out) => { + const foo = { + a: 1, + b: 2, + cause: 3, + }; + console.log(foo); + + const result = stripAnsiCode(out.toString()); + const expected = "{ a: 1, b: 2, cause: 3 }\n"; + assertEquals(result.trim(), expected.trim()); + }); +}); + // console.log(new Proxy(new RegExp(), {})) Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedRegExp() { mockConsole((console, out) => { diff --git a/tests/unit/copy_file_test.ts b/tests/unit/copy_file_test.ts index ad467f5107..9405184e33 100644 --- a/tests/unit/copy_file_test.ts +++ b/tests/unit/copy_file_test.ts @@ -84,7 +84,7 @@ Deno.test( function copyFileSyncPerm1() { assertThrows(() => { Deno.copyFileSync("/from.txt", "/to.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -93,7 +93,7 @@ Deno.test( function copyFileSyncPerm2() { assertThrows(() => { Deno.copyFileSync("/from.txt", "/to.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -197,7 +197,7 @@ Deno.test( async function copyFilePerm1() { await assertRejects(async () => { await Deno.copyFile("/from.txt", "/to.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -206,7 +206,7 @@ Deno.test( async function copyFilePerm2() { await assertRejects(async () => { await Deno.copyFile("/from.txt", "/to.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/cron_test.ts b/tests/unit/cron_test.ts index 02573a898d..5f14f6c784 100644 --- a/tests/unit/cron_test.ts +++ b/tests/unit/cron_test.ts @@ -15,7 +15,7 @@ Deno.test(function noNameTest() { // @ts-ignore test () => Deno.cron(), TypeError, - "Deno.cron requires a unique name", + "Cannot create cron job, a unique name is required: received 'undefined'", ); }); @@ -24,7 +24,7 @@ Deno.test(function noSchedule() { // @ts-ignore test () => Deno.cron("foo"), TypeError, - "Deno.cron requires a valid schedule", + "Cannot create cron job, a schedule is required: received 'undefined'", ); }); @@ -33,7 +33,7 @@ Deno.test(function noHandler() { // @ts-ignore test () => Deno.cron("foo", "*/1 * * * *"), TypeError, - "Deno.cron requires a handler", + "Cannot create cron job: a handler is required", ); }); @@ -66,7 +66,7 @@ Deno.test(function invalidNameTest() { () => {}, ), TypeError, - "Cron name is too long", + "Cron name cannot exceed 64 characters: current length 70", ); }); @@ -388,7 +388,7 @@ Deno.test("error on two handlers", () => { Deno.cron("abc", "* * * * *", () => {}, () => {}); }, TypeError, - "Deno.cron requires a single handler", + "Cannot create cron job, a single handler is required: two handlers were specified", ); }); diff --git a/tests/unit/dir_test.ts b/tests/unit/dir_test.ts index 4aaadfb124..1e702f549a 100644 --- a/tests/unit/dir_test.ts +++ b/tests/unit/dir_test.ts @@ -43,7 +43,7 @@ Deno.test({ permissions: { read: false } }, function dirCwdPermError() { () => { Deno.cwd(); }, - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, "Requires read access to , run again with the --allow-read flag", ); }); diff --git a/tests/unit/error_test.ts b/tests/unit/error_test.ts index 9ba09ce0d6..bf0ef50627 100644 --- a/tests/unit/error_test.ts +++ b/tests/unit/error_test.ts @@ -22,6 +22,7 @@ Deno.test("Errors work", () => { assert(new Deno.errors.Http("msg") instanceof Error); assert(new Deno.errors.Busy("msg") instanceof Error); assert(new Deno.errors.NotSupported("msg") instanceof Error); + assert(new Deno.errors.NotCapable("msg") instanceof Error); }); Deno.test("Errors have some tamper resistance", () => { diff --git a/tests/unit/event_target_test.ts b/tests/unit/event_target_test.ts index 3577587d19..3f7d8ee24a 100644 --- a/tests/unit/event_target_test.ts +++ b/tests/unit/event_target_test.ts @@ -67,6 +67,64 @@ Deno.test(function anEventTargetCanBeSubclassed() { assertEquals(callCount, 0); }); +Deno.test(function removeEventListenerTest() { + const target = new EventTarget(); + let callCount = 0; + const listener = () => { + ++callCount; + }; + + target.addEventListener("incr", listener, true); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 1); + + // Should not remove the listener because useCapture does not match + target.removeEventListener("incr", listener, false); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 2); + + // Should remove the listener because useCapture matches + target.removeEventListener("incr", listener, true); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 2); + + // Only the capture setting matters to removeEventListener + target.addEventListener("incr", listener, { passive: true }); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 3); + + // Should not remove the listener because useCapture does not match + target.removeEventListener("incr", listener, { capture: true }); + target.removeEventListener("incr", listener, true); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 4); + + // Should remove the listener because useCapture matches + target.removeEventListener("incr", listener); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 4); + + // Again, should remove the listener because useCapture matches + target.addEventListener("incr", listener, { passive: true }); + target.removeEventListener("incr", listener, false); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 4); + + // Again, should remove the listener because useCapture matches + target.addEventListener("incr", listener, { passive: true }); + target.removeEventListener("incr", listener, { capture: false }); + + target.dispatchEvent(new Event("incr")); + assertEquals(callCount, 4); +}); + Deno.test(function removingNullEventListenerShouldSucceed() { const document = new EventTarget(); assertEquals(document.removeEventListener("x", null, false), undefined); diff --git a/tests/unit/fetch_test.ts b/tests/unit/fetch_test.ts index 9b2463bcc3..3ae96746a7 100644 --- a/tests/unit/fetch_test.ts +++ b/tests/unit/fetch_test.ts @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { assert, assertEquals, @@ -120,7 +123,7 @@ Deno.test({ permissions: { net: true } }, async function fetchJsonSuccess() { Deno.test({ permissions: { net: false } }, async function fetchPerm() { await assertRejects(async () => { await fetch("http://localhost:4545/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { net: true } }, async function fetchUrl() { @@ -1127,7 +1130,7 @@ Deno.test(function fetchResponseConstructorInvalidStatus() { assert(e instanceof RangeError); assert( e.message.endsWith( - "is not equal to 101 and outside the range [200, 599].", + "is not equal to 101 and outside the range [200, 599]", ), ); } @@ -1153,6 +1156,7 @@ Deno.test( > { const caCert = Deno.readTextFileSync("tests/testdata/tls/RootCA.pem"); const client = Deno.createHttpClient({ caCerts: [caCert] }); + assert(client instanceof Deno.HttpClient); const response = await fetch("https://localhost:5545/assets/fixture.json", { client, }); @@ -1633,7 +1637,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, async function fetchFilePerm() { await assertRejects(async () => { await fetch(import.meta.resolve("../testdata/subdir/json_1.json")); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -1641,7 +1645,7 @@ Deno.test( async function fetchFilePermDoesNotExist() { await assertRejects(async () => { await fetch(import.meta.resolve("./bad.json")); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -1658,7 +1662,7 @@ Deno.test( ); }, TypeError, - "Fetching files only supports the GET method. Received POST.", + "Fetching files only supports the GET method: received POST", ); }, ); diff --git a/tests/unit/ffi_test.ts b/tests/unit/ffi_test.ts index 70a914c0af..98338b15e6 100644 --- a/tests/unit/ffi_test.ts +++ b/tests/unit/ffi_test.ts @@ -24,10 +24,10 @@ Deno.test({ permissions: { ffi: true } }, function dlopenInvalidArguments() { }, TypeError); }); -Deno.test({ permissions: { ffi: false } }, function ffiPermissionDenied() { +Deno.test({ permissions: { ffi: false } }, function ffiNotCapable() { assertThrows(() => { Deno.dlopen("/usr/lib/libc.so.6", {}); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); const fnptr = new Deno.UnsafeFnPointer( // @ts-expect-error: Not NonNullable but null check is after permissions check. null, @@ -38,44 +38,44 @@ Deno.test({ permissions: { ffi: false } }, function ffiPermissionDenied() { ); assertThrows(() => { fnptr.call(123, null); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { Deno.UnsafePointer.of(new Uint8Array(0)); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); const ptrView = new Deno.UnsafePointerView( // @ts-expect-error: Not NonNullable but null check is after permissions check. null, ); assertThrows(() => { ptrView.copyInto(new Uint8Array(0)); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getCString(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getUint8(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getInt8(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getUint16(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getInt16(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getUint32(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getInt32(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getFloat32(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); assertThrows(() => { ptrView.getFloat64(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { ffi: true } }, function pointerOf() { diff --git a/tests/unit/files_test.ts b/tests/unit/files_test.ts index 754c6fb155..a847104c28 100644 --- a/tests/unit/files_test.ts +++ b/tests/unit/files_test.ts @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// deno-lint-ignore-file no-deprecated-deno-api - import { assert, assertEquals, @@ -13,152 +11,26 @@ import { copy } from "@std/io/copy"; // Note tests for Deno.FsFile.setRaw is in integration tests. Deno.test(function filesStdioFileDescriptors() { + // @ts-ignore `Deno.stdin.rid` was soft-removed in Deno 2. assertEquals(Deno.stdin.rid, 0); + // @ts-ignore `Deno.stdout.rid` was soft-removed in Deno 2. assertEquals(Deno.stdout.rid, 1); + // @ts-ignore `Deno.stderr.rid` was soft-removed in Deno 2. assertEquals(Deno.stderr.rid, 2); }); -Deno.test({ permissions: { read: true } }, async function filesCopyToStdout() { - const filename = "tests/testdata/assets/fixture.json"; - using file = await Deno.open(filename); - assert(file instanceof Deno.File); - assert(file instanceof Deno.FsFile); - assert(file.rid > 2); - const bytesWritten = await copy(file, Deno.stdout); - const fileSize = Deno.statSync(filename).size; - assertEquals(bytesWritten, fileSize); -}); - -Deno.test({ permissions: { read: true } }, async function filesIter() { - const filename = "tests/testdata/assets/hello.txt"; - using file = await Deno.open(filename); - - let totalSize = 0; - for await (const buf of Deno.iter(file)) { - totalSize += buf.byteLength; - } - - assertEquals(totalSize, 12); -}); - Deno.test( { permissions: { read: true } }, - async function filesIterCustomBufSize() { - const filename = "tests/testdata/assets/hello.txt"; + async function filesCopyToStdout() { + const filename = "tests/testdata/assets/fixture.json"; using file = await Deno.open(filename); - - let totalSize = 0; - let iterations = 0; - for await (const buf of Deno.iter(file, { bufSize: 6 })) { - totalSize += buf.byteLength; - iterations += 1; - } - - assertEquals(totalSize, 12); - assertEquals(iterations, 2); + assert(file instanceof Deno.FsFile); + const bytesWritten = await copy(file, Deno.stdout); + const fileSize = Deno.statSync(filename).size; + assertEquals(bytesWritten, fileSize); }, ); -Deno.test({ permissions: { read: true } }, function filesIterSync() { - const filename = "tests/testdata/assets/hello.txt"; - using file = Deno.openSync(filename); - - let totalSize = 0; - for (const buf of Deno.iterSync(file)) { - totalSize += buf.byteLength; - } - - assertEquals(totalSize, 12); -}); - -Deno.test( - { permissions: { read: true } }, - function filesIterSyncCustomBufSize() { - const filename = "tests/testdata/assets/hello.txt"; - using file = Deno.openSync(filename); - - let totalSize = 0; - let iterations = 0; - for (const buf of Deno.iterSync(file, { bufSize: 6 })) { - totalSize += buf.byteLength; - iterations += 1; - } - - assertEquals(totalSize, 12); - assertEquals(iterations, 2); - }, -); - -Deno.test(async function readerIter() { - // ref: https://github.com/denoland/deno/issues/2330 - const encoder = new TextEncoder(); - - class TestReader implements Deno.Reader { - #offset = 0; - #buf: Uint8Array; - - constructor(s: string) { - this.#buf = new Uint8Array(encoder.encode(s)); - } - - read(p: Uint8Array): Promise { - const n = Math.min(p.byteLength, this.#buf.byteLength - this.#offset); - p.set(this.#buf.slice(this.#offset, this.#offset + n)); - this.#offset += n; - - if (n === 0) { - return Promise.resolve(null); - } - - return Promise.resolve(n); - } - } - - const reader = new TestReader("hello world!"); - - let totalSize = 0; - for await (const buf of Deno.iter(reader)) { - totalSize += buf.byteLength; - } - - assertEquals(totalSize, 12); -}); - -Deno.test(async function readerIterSync() { - // ref: https://github.com/denoland/deno/issues/2330 - const encoder = new TextEncoder(); - - class TestReader implements Deno.ReaderSync { - #offset = 0; - #buf: Uint8Array; - - constructor(s: string) { - this.#buf = new Uint8Array(encoder.encode(s)); - } - - readSync(p: Uint8Array): number | null { - const n = Math.min(p.byteLength, this.#buf.byteLength - this.#offset); - p.set(this.#buf.slice(this.#offset, this.#offset + n)); - this.#offset += n; - - if (n === 0) { - return null; - } - - return n; - } - } - - const reader = new TestReader("hello world!"); - - let totalSize = 0; - for await (const buf of Deno.iterSync(reader)) { - totalSize += buf.byteLength; - } - - assertEquals(totalSize, 12); -}); - Deno.test( { permissions: { read: true, write: true }, @@ -253,7 +125,7 @@ Deno.test( for (const options of openOptions) { await assertRejects(async () => { await Deno.open(filename, options); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); } }, ); @@ -296,7 +168,7 @@ Deno.test(async function openOptions() { Deno.test({ permissions: { read: false } }, async function readPermFailure() { await assertRejects(async () => { await Deno.open("package.json", { read: true }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -355,7 +227,7 @@ Deno.test( const filename = "tests/hello.txt"; await assertRejects(async () => { await Deno.open(filename, { read: true }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -908,14 +780,14 @@ Deno.test({ permissions: { read: true } }, function fsFileIsTerminal() { }); Deno.test( - { permissions: { read: true, run: true, hrtime: true } }, + { permissions: { read: true, run: true } }, async function fsFileLockFileSync() { await runFlockTests({ sync: true }); }, ); Deno.test( - { permissions: { read: true, run: true, hrtime: true } }, + { permissions: { read: true, run: true } }, async function fsFileLockFileAsync() { await runFlockTests({ sync: false }); }, @@ -1055,7 +927,7 @@ function runFlockTestProcess(opts: { exclusive: boolean; sync: boolean }) { `; const process = new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", scriptText], + args: ["eval", scriptText], stdin: "piped", stdout: "piped", stderr: "null", diff --git a/tests/unit/flock_test.ts b/tests/unit/flock_test.ts deleted file mode 100644 index 4b194ce553..0000000000 --- a/tests/unit/flock_test.ts +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assertEquals } from "./test_util.ts"; - -Deno.test( - { permissions: { read: true, run: true, hrtime: true } }, - async function flockFileSync() { - await runFlockTests({ sync: true }); - }, -); - -Deno.test( - { permissions: { read: true, run: true, hrtime: true } }, - async function flockFileAsync() { - await runFlockTests({ sync: false }); - }, -); - -async function runFlockTests(opts: { sync: boolean }) { - assertEquals( - await checkFirstBlocksSecond({ - firstExclusive: true, - secondExclusive: false, - sync: opts.sync, - }), - true, - "exclusive blocks shared", - ); - assertEquals( - await checkFirstBlocksSecond({ - firstExclusive: false, - secondExclusive: true, - sync: opts.sync, - }), - true, - "shared blocks exclusive", - ); - assertEquals( - await checkFirstBlocksSecond({ - firstExclusive: true, - secondExclusive: true, - sync: opts.sync, - }), - true, - "exclusive blocks exclusive", - ); - assertEquals( - await checkFirstBlocksSecond({ - firstExclusive: false, - secondExclusive: false, - sync: opts.sync, - // need to wait for both to enter the lock to prevent the case where the - // first process enters and exits the lock before the second even enters - waitBothEnteredLock: true, - }), - false, - "shared does not block shared", - ); -} - -async function checkFirstBlocksSecond(opts: { - firstExclusive: boolean; - secondExclusive: boolean; - sync: boolean; - waitBothEnteredLock?: boolean; -}) { - const firstProcess = runFlockTestProcess({ - exclusive: opts.firstExclusive, - sync: opts.sync, - }); - const secondProcess = runFlockTestProcess({ - exclusive: opts.secondExclusive, - sync: opts.sync, - }); - try { - const sleep = (time: number) => new Promise((r) => setTimeout(r, time)); - - await Promise.all([ - firstProcess.waitStartup(), - secondProcess.waitStartup(), - ]); - - await firstProcess.enterLock(); - await firstProcess.waitEnterLock(); - - await secondProcess.enterLock(); - await sleep(100); - - if (!opts.waitBothEnteredLock) { - await firstProcess.exitLock(); - } - - await secondProcess.waitEnterLock(); - - if (opts.waitBothEnteredLock) { - await firstProcess.exitLock(); - } - - await secondProcess.exitLock(); - - // collect the final output - const firstPsTimes = await firstProcess.getTimes(); - const secondPsTimes = await secondProcess.getTimes(); - return firstPsTimes.exitTime < secondPsTimes.enterTime; - } finally { - await firstProcess.close(); - await secondProcess.close(); - } -} - -function runFlockTestProcess(opts: { exclusive: boolean; sync: boolean }) { - const path = "tests/testdata/assets/lock_target.txt"; - const scriptText = ` - const { rid } = Deno.openSync("${path}"); - - // ready signal - Deno.stdout.writeSync(new Uint8Array(1)); - // wait for enter lock signal - Deno.stdin.readSync(new Uint8Array(1)); - - // entering signal - Deno.stdout.writeSync(new Uint8Array(1)); - // lock and record the entry time - ${ - opts.sync - ? `Deno.flockSync(rid, ${opts.exclusive ? "true" : "false"});` - : `await Deno.flock(rid, ${opts.exclusive ? "true" : "false"});` - } - const enterTime = new Date().getTime(); - // entered signal - Deno.stdout.writeSync(new Uint8Array(1)); - - // wait for exit lock signal - Deno.stdin.readSync(new Uint8Array(1)); - - // record the exit time and wait a little bit before releasing - // the lock so that the enter time of the next process doesn't - // occur at the same time as this exit time - const exitTime = new Date().getTime(); - await new Promise(resolve => setTimeout(resolve, 100)); - - // release the lock - ${opts.sync ? "Deno.funlockSync(rid);" : "await Deno.funlock(rid);"} - - // exited signal - Deno.stdout.writeSync(new Uint8Array(1)); - - // output the enter and exit time - console.log(JSON.stringify({ enterTime, exitTime })); -`; - - const process = new Deno.Command(Deno.execPath(), { - args: ["eval", "--unstable", scriptText], - stdin: "piped", - stdout: "piped", - stderr: "null", - }).spawn(); - - const waitSignal = async () => { - const reader = process.stdout.getReader({ mode: "byob" }); - await reader.read(new Uint8Array(1)); - reader.releaseLock(); - }; - const signal = async () => { - const writer = process.stdin.getWriter(); - await writer.write(new Uint8Array(1)); - writer.releaseLock(); - }; - - return { - async waitStartup() { - await waitSignal(); - }, - async enterLock() { - await signal(); - await waitSignal(); // entering signal - }, - async waitEnterLock() { - await waitSignal(); - }, - async exitLock() { - await signal(); - await waitSignal(); - }, - getTimes: async () => { - const { stdout } = await process.output(); - const text = new TextDecoder().decode(stdout); - return JSON.parse(text) as { - enterTime: number; - exitTime: number; - }; - }, - close: async () => { - await process.status; - await process.stdin.close(); - }, - }; -} diff --git a/tests/unit/fs_events_test.ts b/tests/unit/fs_events_test.ts index 3a867f07ee..cc2f2cd571 100644 --- a/tests/unit/fs_events_test.ts +++ b/tests/unit/fs_events_test.ts @@ -7,7 +7,7 @@ import { assert, assertEquals, assertThrows, delay } from "./test_util.ts"; Deno.test({ permissions: { read: false } }, function watchFsPermissions() { assertThrows(() => { Deno.watchFs("."); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function watchFsInvalidPath() { @@ -90,8 +90,6 @@ Deno.test( }, ); -// TODO(kt3k): This test is for the backward compatibility of `.return` method. -// This should be removed at 2.0 Deno.test( { permissions: { read: true, write: true } }, async function watchFsReturn() { diff --git a/tests/unit/globals_test.ts b/tests/unit/globals_test.ts index e4cbe7daf1..45a0458357 100644 --- a/tests/unit/globals_test.ts +++ b/tests/unit/globals_test.ts @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// deno-lint-ignore-file no-window-prefix no-window import { assert, assertEquals, @@ -19,34 +18,18 @@ Deno.test(function noInternalGlobals() { } }); -Deno.test(function windowExists() { - assert(window != null); -}); - Deno.test(function selfExists() { assert(self != null); }); -Deno.test(function windowWindowExists() { - assert(window.window === window); -}); - -Deno.test(function windowSelfExists() { - assert(window.self === window); -}); - -Deno.test(function globalThisEqualsWindow() { - assert(globalThis === window); +Deno.test(function globalThisWindowEqualsUndefined() { + assert(globalThis.window === undefined); }); Deno.test(function globalThisEqualsSelf() { assert(globalThis === self); }); -Deno.test(function globalThisInstanceofWindow() { - assert(globalThis instanceof Window); -}); - Deno.test(function globalThisConstructorLength() { assert(globalThis.constructor.length === 0); }); @@ -65,10 +48,6 @@ Deno.test(function DenoNamespaceExists() { assert(Deno != null); }); -Deno.test(function DenoNamespaceEqualsWindowDeno() { - assert(Deno === window.Deno); -}); - Deno.test(function DenoNamespaceIsNotFrozen() { assert(!Object.isFrozen(Deno)); }); @@ -119,7 +98,7 @@ Deno.test(async function windowQueueMicrotask() { res(); }; }); - window.queueMicrotask(resolve1!); + globalThis.queueMicrotask(resolve1!); setTimeout(resolve2!, 0); await p1; await p2; @@ -138,12 +117,9 @@ Deno.test(function webApiGlobalThis() { Deno.test(function windowNameIsDefined() { assertEquals(typeof globalThis.name, "string"); assertEquals(name, ""); - assertEquals(window.name, name); name = "foobar"; - assertEquals(window.name, "foobar"); assertEquals(name, "foobar"); name = ""; - assertEquals(window.name, ""); assertEquals(name, ""); }); diff --git a/tests/unit/headers_test.ts b/tests/unit/headers_test.ts index ad453b67f6..ea72f784b5 100644 --- a/tests/unit/headers_test.ts +++ b/tests/unit/headers_test.ts @@ -406,11 +406,11 @@ Deno.test(function invalidHeadersFlaky() { assertThrows( () => new Headers([["x", "\u0000x"]]), TypeError, - "Header value is not valid.", + 'Invalid header value: "\u0000x"', ); assertThrows( () => new Headers([["x", "\u0000x"]]), TypeError, - "Header value is not valid.", + 'Invalid header value: "\u0000x"', ); }); diff --git a/tests/unit/http_test.ts b/tests/unit/http_test.ts index 6d3543e444..355b155afd 100644 --- a/tests/unit/http_test.ts +++ b/tests/unit/http_test.ts @@ -1,8 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// @ts-nocheck `Deno.serveHttp()` was soft-removed in Deno 2. // deno-lint-ignore-file no-deprecated-deno-api -import { Buffer, BufReader, BufWriter } from "@std/io"; +import { Buffer, BufReader, BufWriter, type Reader } from "@std/io"; import { TextProtoReader } from "../testdata/run/textproto.ts"; import { assert, @@ -51,7 +52,8 @@ async function writeRequestAndReadResponse(conn: Deno.Conn): Promise { } Deno.test({ permissions: { net: true } }, async function httpServerBasic() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -146,7 +148,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerGetRequestBody() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -187,7 +190,8 @@ Deno.test( writer.write(new TextEncoder().encode("world")); writer.close(); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -250,7 +254,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerStreamDuplex() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -363,7 +368,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerRegressionHang() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -482,7 +488,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerEmptyBlobResponse() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -505,7 +512,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerNextRequestResolvesOnClose() { - const httpConnList: Deno.HttpConn[] = []; + // deno-lint-ignore no-explicit-any + const httpConnList: any[] = []; async function serve(l: Deno.Listener) { for await (const conn of l) { @@ -544,7 +552,8 @@ Deno.test( return new Response(s).body!; } - const httpConns: Deno.HttpConn[] = []; + // deno-lint-ignore no-explicit-any + const httpConns: any[] = []; const promise = (async () => { let count = 0; const listener = Deno.listen({ port: listenPort }); @@ -648,7 +657,8 @@ Deno.test( }).pipeThrough(new TextEncoderStream()); } - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const finished = (async () => { const conn = await listener.accept(); @@ -675,7 +685,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpRequestLatin1Headers() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -724,7 +735,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerRequestWithoutPath() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -896,7 +908,8 @@ Deno.test(function httpUpgradeWebSocketWithoutUpgradeHeader() { Deno.test( { permissions: { net: true } }, async function httpCookieConcatenation() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -955,7 +968,8 @@ Deno.test( using file = await Deno.open(tmpFile, { write: true, read: true }); await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -1094,7 +1108,8 @@ Deno.test( { permissions: { net: true } }, async function httpServerDoesntLeakResources2() { let listener: Deno.Listener; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { listener = Deno.listen({ port: listenPort }); @@ -1161,7 +1176,8 @@ Deno.test( const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ hostname, port }); async function server() { const tcpConn = await listener.accept(); @@ -1248,7 +1264,8 @@ Deno.test( const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ hostname, port }); async function server() { const tcpConn = await listener.accept(); @@ -1279,7 +1296,8 @@ Deno.test( Deno.test( { permissions: { net: true } }, async function httpServerRespondNonAsciiUint8Array() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -1318,7 +1336,8 @@ Deno.test( async function httpServerOnUnixSocket() { const filePath = tmpUnixSocketPath(); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ path: filePath, transport: "unix" }); const conn = await listener.accept(); @@ -1367,7 +1386,8 @@ Deno.test({ const data = { hello: "deno", now: "with", compressed: "body" }; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const tcpConn = await listener.accept(); httpConn = Deno.serveHttp(tcpConn); @@ -1419,7 +1439,8 @@ Deno.test({ const data = { hello: "deno", now: "with", compressed: "body" }; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const tcpConn = await listener.accept(); httpConn = Deno.serveHttp(tcpConn); @@ -1473,7 +1494,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1526,7 +1548,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1582,7 +1605,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1635,7 +1659,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1695,7 +1720,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1754,7 +1780,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1810,7 +1837,8 @@ Deno.test({ const hostname = "localhost"; const port = listenPort; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -1871,7 +1899,8 @@ Deno.test({ const data = { hello: "deno", now: "with", compressed: "body" }; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const tcpConn = await listener.accept(); httpConn = Deno.serveHttp(tcpConn); @@ -1933,7 +1962,8 @@ Deno.test({ const data = { hello: "deno", now: "with", compressed: "body" }; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const tcpConn = await listener.accept(); httpConn = Deno.serveHttp(tcpConn); @@ -1995,7 +2025,8 @@ Deno.test({ const port = listenPort; let contentLength: string; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -2061,7 +2092,8 @@ Deno.test({ const port = listenPort; let contentLength: string; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -2087,7 +2119,6 @@ Deno.test({ async function client() { const url = `http://${hostname}:${port}/`; const cmd = [ - "curl", "-i", "--request", "GET", @@ -2097,16 +2128,17 @@ Deno.test({ "--header", "Accept-Encoding: deflate, gzip", ]; - const proc = Deno.run({ cmd, stdout: "piped", stderr: "null" }); - const status = await proc.status(); - assert(status.success); - const output = decoder.decode(await proc.output()); + const { success, stdout } = await new Deno.Command("curl", { + args: cmd, + stderr: "null", + }).output(); + assert(success); + const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: gzip\r\n")); // Ensure the content-length header is updated. assert(!output.includes(`content-length: ${contentLength}\r\n`)); assert(output.includes("content-length: ")); - proc.close(); } await Promise.all([server(), client()]); @@ -2122,7 +2154,8 @@ Deno.test({ const port = listenPort; let contentLength: string; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const listener = Deno.listen({ hostname, port }); const tcpConn = await listener.accept(); @@ -2149,7 +2182,6 @@ Deno.test({ async function client() { const url = `http://${hostname}:${port}/`; const cmd = [ - "curl", "-i", "--request", "GET", @@ -2159,13 +2191,15 @@ Deno.test({ "--header", "Accept-Encoding: deflate, gzip", ]; - const proc = Deno.run({ cmd, stdout: "piped", stderr: "null" }); - const status = await proc.status(); - assert(status.success); - const output = decoder.decode(await proc.output()); + const { success, stdout } = await new Deno.Command("curl", { + args: cmd, + stderr: "null", + stdout: "piped", + }).output(); + assert(success); + const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: arbitrary\r\n")); - proc.close(); } await Promise.all([server(), client()]); @@ -2181,7 +2215,8 @@ Deno.test( const body = "aa\n" + "deno.land large body\n".repeat(TLS_PACKET_SIZE) + "zz"; - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -2228,7 +2263,8 @@ Deno.test( } writer.close(); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -2269,7 +2305,7 @@ Deno.test( const buf = new Uint8Array(128); const readPromise = serverConn.read(buf); - assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.Busy); clientConn.close(); listener.close(); @@ -2302,7 +2338,7 @@ Deno.test( const buf = new Uint8Array(128); const readPromise = serverConn.read(buf); - assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.Busy); clientConn.close(); listener.close(); @@ -2326,7 +2362,7 @@ Deno.test( const buf = new Uint8Array(128); const readPromise = serverConn.read(buf); - assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.Busy); clientConn.close(); listener.close(); @@ -2338,7 +2374,8 @@ Deno.test( { permissions: { net: true } }, async function httpServerRequestResponseClone() { const body = "deno".repeat(64 * 1024); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const listener = Deno.listen({ port: listenPort }); const promise = (async () => { const conn = await listener.accept(); @@ -2402,7 +2439,8 @@ Deno.test({ const listener = Deno.listen({ hostname, port }); const listener2 = Deno.listen({ hostname, port: port2 }); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function server() { const tcpConn = await listener.accept(); httpConn = Deno.serveHttp(tcpConn); @@ -2419,7 +2457,8 @@ Deno.test({ const writer = ts.writable.getWriter(); writer.write(encoder.encode("hello")); - let httpConn2: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn2: any; async function server2() { const tcpConn = await listener2.accept(); httpConn2 = Deno.serveHttp(tcpConn); @@ -2498,7 +2537,8 @@ Deno.test("case insensitive comma value finder", async (t) => { async function httpServerWithErrorBody( listener: Deno.Listener, compression: boolean, -): Promise { + // deno-lint-ignore no-explicit-any +): Promise { const conn = await listener.accept(); listener.close(); const httpConn = Deno.serveHttp(conn); @@ -2626,7 +2666,8 @@ Deno.test({ name: "request signal is aborted when response errors", permissions: { net: true }, async fn() { - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; const promise = (async () => { const listener = Deno.listen({ port: listenPort }); const conn = await listener.accept(); @@ -2681,7 +2722,8 @@ Deno.test("proxy with fetch", async () => { return new Response("Hello world"); }); - let httpConn: Deno.HttpConn; + // deno-lint-ignore no-explicit-any + let httpConn: any; async function handleHttp(conn: Deno.Conn) { httpConn = Deno.serveHttp(conn); for await (const e of httpConn) { @@ -2728,7 +2770,7 @@ Deno.test("proxy with fetch", async () => { httpConn!.close(); }); -function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader { +function chunkedBodyReader(h: Headers, r: BufReader): Reader { // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 const tp = new TextProtoReader(r); let finished = false; diff --git a/tests/unit/io_test.ts b/tests/unit/io_test.ts deleted file mode 100644 index 5b55729dd7..0000000000 --- a/tests/unit/io_test.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assertEquals } from "./test_util.ts"; -import { Buffer } from "@std/io/buffer"; - -const DEFAULT_BUF_SIZE = 32 * 1024; - -type Spy = { calls: number }; - -function repeat(c: string, bytes: number): Uint8Array { - assertEquals(c.length, 1); - const ui8 = new Uint8Array(bytes); - ui8.fill(c.charCodeAt(0)); - return ui8; -} - -function spyRead(obj: Buffer): Spy { - const spy: Spy = { - calls: 0, - }; - - const orig = obj.read.bind(obj); - - obj.read = (p: Uint8Array): Promise => { - spy.calls++; - return orig(p); - }; - - return spy; -} - -Deno.test(async function copyWithDefaultBufferSize() { - const xBytes = repeat("b", DEFAULT_BUF_SIZE); - const reader = new Buffer(xBytes.buffer as ArrayBuffer); - const write = new Buffer(); - - const readSpy = spyRead(reader); - - // deno-lint-ignore no-deprecated-deno-api - const n = await Deno.copy(reader, write); - - assertEquals(n, xBytes.length); - assertEquals(write.length, xBytes.length); - assertEquals(readSpy.calls, 2); // read with DEFAULT_BUF_SIZE bytes + read with 0 bytes -}); - -Deno.test(async function copyWithCustomBufferSize() { - const bufSize = 1024; - const xBytes = repeat("b", DEFAULT_BUF_SIZE); - const reader = new Buffer(xBytes.buffer as ArrayBuffer); - const write = new Buffer(); - - const readSpy = spyRead(reader); - - // deno-lint-ignore no-deprecated-deno-api - const n = await Deno.copy(reader, write, { bufSize }); - - assertEquals(n, xBytes.length); - assertEquals(write.length, xBytes.length); - assertEquals(readSpy.calls, DEFAULT_BUF_SIZE / bufSize + 1); -}); - -Deno.test({ permissions: { write: true } }, async function copyBufferToFile() { - const filePath = "test-file.txt"; - // bigger than max File possible buffer 16kb - const bufSize = 32 * 1024; - const xBytes = repeat("b", bufSize); - const reader = new Buffer(xBytes.buffer as ArrayBuffer); - const write = await Deno.open(filePath, { write: true, create: true }); - - // deno-lint-ignore no-deprecated-deno-api - const n = await Deno.copy(reader, write, { bufSize }); - - assertEquals(n, xBytes.length); - - write.close(); - await Deno.remove(filePath); -}); diff --git a/tests/unit/kv_queue_test.ts b/tests/unit/kv_queue_test.ts index e052dcbf75..d92977169f 100644 --- a/tests/unit/kv_queue_test.ts +++ b/tests/unit/kv_queue_test.ts @@ -8,6 +8,6 @@ Deno.test({}, async function queueTestDbClose() { await db.listenQueue(() => {}); assertFalse(false); } catch (e) { - assertEquals(e.message, "already closed"); + assertEquals((e as Error).message, "Queue already closed"); } }); diff --git a/tests/unit/kv_test.ts b/tests/unit/kv_test.ts index 28d79d1f9a..e603bc196d 100644 --- a/tests/unit/kv_test.ts +++ b/tests/unit/kv_test.ts @@ -707,7 +707,7 @@ dbTest("list prefix with start equal to prefix", async (db) => { await assertRejects( async () => await collect(db.list({ prefix: ["a"], start: ["a"] })), TypeError, - "start key is not in the keyspace defined by prefix", + "Start key is not in the keyspace defined by prefix", ); }); @@ -716,7 +716,7 @@ dbTest("list prefix with start out of bounds", async (db) => { await assertRejects( async () => await collect(db.list({ prefix: ["b"], start: ["a"] })), TypeError, - "start key is not in the keyspace defined by prefix", + "Start key is not in the keyspace defined by prefix", ); }); @@ -740,7 +740,7 @@ dbTest("list prefix with end equal to prefix", async (db) => { await assertRejects( async () => await collect(db.list({ prefix: ["a"], end: ["a"] })), TypeError, - "end key is not in the keyspace defined by prefix", + "End key is not in the keyspace defined by prefix", ); }); @@ -749,7 +749,7 @@ dbTest("list prefix with end out of bounds", async (db) => { await assertRejects( async () => await collect(db.list({ prefix: ["a"], end: ["b"] })), TypeError, - "end key is not in the keyspace defined by prefix", + "End key is not in the keyspace defined by prefix", ); }); @@ -1061,7 +1061,7 @@ dbTest("list range with start greater than end", async (db) => { await assertRejects( async () => await collect(db.list({ start: ["b"], end: ["a"] })), TypeError, - "start key is greater than end key", + "Start key is greater than end key", ); }); @@ -1177,13 +1177,13 @@ dbTest("key size limit", async (db) => { await assertRejects( async () => await db.set([firstInvalidKey], 1), TypeError, - "key too large for write (max 2048 bytes)", + "Key too large for write (max 2048 bytes)", ); await assertRejects( async () => await db.get([firstInvalidKey]), TypeError, - "key too large for read (max 2049 bytes)", + "Key too large for read (max 2049 bytes)", ); }); @@ -1201,7 +1201,7 @@ dbTest("value size limit", async (db) => { await assertRejects( async () => await db.set(["b"], firstInvalidValue), TypeError, - "value too large (max 65536 bytes)", + "Value too large (max 65536 bytes)", ); }); @@ -1225,7 +1225,7 @@ dbTest("operation size limit", async (db) => { await assertRejects( async () => await db.getMany(firstInvalidKeys), TypeError, - "too many ranges (max 10)", + "Too many ranges (max 10)", ); const res2 = await collect(db.list({ prefix: ["a"] }, { batchSize: 1000 })); @@ -1234,7 +1234,7 @@ dbTest("operation size limit", async (db) => { await assertRejects( async () => await collect(db.list({ prefix: ["a"] }, { batchSize: 1001 })), TypeError, - "too many entries (max 1000)", + "Too many entries (max 1000)", ); // when batchSize is not specified, limit is used but is clamped to 500 @@ -1271,7 +1271,7 @@ dbTest("operation size limit", async (db) => { .commit(); }, TypeError, - "too many checks (max 100)", + "Too many checks (max 100)", ); const validMutateKeys: Deno.KvKey[] = new Array(1000).fill(0).map(( @@ -1311,7 +1311,7 @@ dbTest("operation size limit", async (db) => { .commit(); }, TypeError, - "too many mutations (max 1000)", + "Too many mutations (max 1000)", ); }); @@ -1339,7 +1339,7 @@ dbTest("total mutation size limit", async (db) => { await atomic.commit(); }, TypeError, - "total mutation size too large (max 819200 bytes)", + "Total mutation size too large (max 819200 bytes)", ); }); @@ -1354,7 +1354,7 @@ dbTest("total key size limit", async (db) => { await assertRejects( () => atomic.commit(), TypeError, - "total key size too large (max 81920 bytes)", + "Total key size too large (max 81920 bytes)", ); }); @@ -1655,7 +1655,7 @@ queueTest("queue retries with backoffSchedule", async (db) => { let count = 0; const listener = db.listenQueue((_msg) => { count += 1; - throw new TypeError("dequeue error"); + throw new TypeError("Dequeue error"); }); try { await db.enqueue("test", { backoffSchedule: [1] }); @@ -1945,20 +1945,20 @@ Deno.test({ }, }); -dbTest("invalid backoffSchedule", async (db) => { +dbTest("Invalid backoffSchedule", async (db) => { await assertRejects( async () => { await db.enqueue("foo", { backoffSchedule: [1, 1, 1, 1, 1, 1] }); }, TypeError, - "invalid backoffSchedule", + "Invalid backoffSchedule", ); await assertRejects( async () => { await db.enqueue("foo", { backoffSchedule: [3600001] }); }, TypeError, - "invalid backoffSchedule", + "Invalid backoffSchedule", ); }); diff --git a/tests/unit/link_test.ts b/tests/unit/link_test.ts index 6048b8add9..dfa72479c5 100644 --- a/tests/unit/link_test.ts +++ b/tests/unit/link_test.ts @@ -87,7 +87,7 @@ Deno.test( function linkSyncReadPerm() { assertThrows(() => { Deno.linkSync("oldbaddir", "newbaddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -96,7 +96,7 @@ Deno.test( function linkSyncWritePerm() { assertThrows(() => { Deno.linkSync("oldbaddir", "newbaddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -181,7 +181,7 @@ Deno.test( async function linkReadPerm() { await assertRejects(async () => { await Deno.link("oldbaddir", "newbaddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -190,6 +190,6 @@ Deno.test( async function linkWritePerm() { await assertRejects(async () => { await Deno.link("oldbaddir", "newbaddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/make_temp_test.ts b/tests/unit/make_temp_test.ts index 2c771177bc..32383387b5 100644 --- a/tests/unit/make_temp_test.ts +++ b/tests/unit/make_temp_test.ts @@ -42,7 +42,7 @@ Deno.test({ permissions: { write: false } }, function makeTempDirSyncPerm() { // makeTempDirSync should require write permissions (for now). assertThrows(() => { Deno.makeTempDirSync({ dir: "/baddir" }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -117,7 +117,7 @@ Deno.test({ permissions: { write: false } }, function makeTempFileSyncPerm() { // makeTempFileSync should require write permissions (for now). assertThrows(() => { Deno.makeTempFileSync({ dir: "/baddir" }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( diff --git a/tests/unit/mkdir_test.ts b/tests/unit/mkdir_test.ts index 0948a1a84c..def77cd3e4 100644 --- a/tests/unit/mkdir_test.ts +++ b/tests/unit/mkdir_test.ts @@ -36,7 +36,7 @@ Deno.test( Deno.test({ permissions: { write: false } }, function mkdirSyncPerm() { assertThrows(() => { Deno.mkdirSync("/baddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( diff --git a/tests/unit/net_test.ts b/tests/unit/net_test.ts index ddc55b8c4e..cfa42b3d36 100644 --- a/tests/unit/net_test.ts +++ b/tests/unit/net_test.ts @@ -2,7 +2,6 @@ import { assert, assertEquals, - assertNotEquals, assertRejects, assertThrows, delay, @@ -27,7 +26,6 @@ Deno.test({ permissions: { net: true } }, function netTcpListenClose() { assert(listener.addr.transport === "tcp"); assertEquals(listener.addr.hostname, "127.0.0.1"); assertEquals(listener.addr.port, listenPort); - assertNotEquals(listener.rid, 0); listener.close(); }); @@ -97,7 +95,7 @@ Deno.test( assert(socket.addr.transport === "unix"); assertEquals(socket.addr.path, filePath); socket.close(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -116,7 +114,7 @@ Deno.test( assert(socket.addr.transport === "unixpacket"); assertEquals(socket.addr.path, filePath); socket.close(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -128,8 +126,6 @@ Deno.test( const listener = Deno.listen({ port: listenPort }); const p = listener.accept(); listener.close(); - // TODO(piscisaureus): the error type should be `Interrupted` here, which - // gets thrown, but then ext/net catches it and rethrows `BadResource`. await assertRejects( () => p, Deno.errors.BadResource, @@ -170,7 +166,7 @@ Deno.test( } else if (e.message === "Another accept task is ongoing") { acceptErrCount++; } else { - throw new Error("Unexpected error message"); + throw e; } }; const p = listener.accept().catch(checkErr); @@ -233,7 +229,6 @@ Deno.test({ permissions: { net: true } }, async function netTcpDialListen() { assertEquals(1, buf[0]); assertEquals(2, buf[1]); assertEquals(3, buf[2]); - assert(conn.rid > 0); assert(readResult !== null); @@ -269,7 +264,6 @@ Deno.test({ permissions: { net: true } }, async function netTcpSetNoDelay() { assertEquals(1, buf[0]); assertEquals(2, buf[1]); assertEquals(3, buf[2]); - assert(conn.rid > 0); assert(readResult !== null); @@ -305,7 +299,6 @@ Deno.test({ permissions: { net: true } }, async function netTcpSetKeepAlive() { assertEquals(1, buf[0]); assertEquals(2, buf[1]); assertEquals(3, buf[2]); - assert(conn.rid > 0); assert(readResult !== null); @@ -343,7 +336,6 @@ Deno.test( assertEquals(1, buf[0]); assertEquals(2, buf[1]); assertEquals(3, buf[2]); - assert(conn.rid > 0); assert(readResult !== null); @@ -432,7 +424,7 @@ Deno.test( // Note: we have to do the test this way as different OS's have // different UDP size limits enabled, so we will just ensure if // an error is thrown it is the one we are expecting. - assert(err.message.match(rx)); + assert((err as Error).message.match(rx)); alice.close(); bob.close(); return; @@ -839,7 +831,6 @@ Deno.test( assertEquals(1, buf[0]); assertEquals(2, buf[1]); assertEquals(3, buf[2]); - assert(conn.rid > 0); assert(readResult !== null); diff --git a/tests/unit/ops_test.ts b/tests/unit/ops_test.ts index 6de55f8b66..4ba7c5ce33 100644 --- a/tests/unit/ops_test.ts +++ b/tests/unit/ops_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -const EXPECTED_OP_COUNT = 12; +const EXPECTED_OP_COUNT = 11; Deno.test(function checkExposedOps() { // @ts-ignore TS doesn't allow to index with symbol diff --git a/tests/unit/os_test.ts b/tests/unit/os_test.ts index 42b5985111..a70796505f 100644 --- a/tests/unit/os_test.ts +++ b/tests/unit/os_test.ts @@ -48,16 +48,16 @@ Deno.test({ permissions: { env: true } }, function avoidEmptyNamedEnv() { assertThrows(() => Deno.env.delete("a\0a"), TypeError); }); -Deno.test({ permissions: { env: false } }, function envPermissionDenied1() { +Deno.test({ permissions: { env: false } }, function envPerm1() { assertThrows(() => { Deno.env.toObject(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); -Deno.test({ permissions: { env: false } }, function envPermissionDenied2() { +Deno.test({ permissions: { env: false } }, function envPerm2() { assertThrows(() => { Deno.env.get("PATH"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); // This test verifies that on Windows, environment variables are @@ -79,7 +79,9 @@ Deno.test( ) => { const src = ` console.log( - ${JSON.stringify(Object.keys(expectedEnv))}.map(k => Deno.env.get(k)) + ${ + JSON.stringify(Object.keys(expectedEnv)) + }.map(k => Deno.env.get(k) ?? null) )`; const { success, stdout } = await new Deno.Command(Deno.execPath(), { args: ["eval", src], @@ -172,7 +174,7 @@ Deno.test( async function osPpidIsEqualToPidOfParentProcess() { const decoder = new TextDecoder(); const { stdout } = await new Deno.Command(Deno.execPath(), { - args: ["eval", "-p", "--unstable", "Deno.ppid"], + args: ["eval", "-p", "Deno.ppid"], env: { NO_COLOR: "true" }, }).output(); @@ -191,7 +193,7 @@ Deno.test({ permissions: { read: false } }, function execPathPerm() { () => { Deno.execPath(); }, - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, "Requires read access to , run again with the --allow-read flag", ); }); @@ -206,7 +208,7 @@ Deno.test( () => { Deno.readTextFileSync("/proc/net/dev"); }, - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, `Requires all access to "/proc/net/dev", run again with the --allow-all flag`, ); }, @@ -223,7 +225,7 @@ Deno.test( Deno.test({ permissions: { sys: false } }, function loadavgPerm() { assertThrows(() => { Deno.loadavg(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -239,6 +241,11 @@ Deno.test( async function hostnameWithoutOtherNetworkUsages() { const { stdout } = await new Deno.Command(Deno.execPath(), { args: ["eval", "-p", "Deno.hostname()"], + env: { + LD_PRELOAD: "", + LD_LIBRARY_PATH: "", + DYLD_FALLBACK_LIBRARY_PATH: "", + }, }).output(); const hostname = new TextDecoder().decode(stdout).trim(); assert(hostname.length > 0); @@ -248,7 +255,7 @@ Deno.test( Deno.test({ permissions: { sys: false } }, function hostnamePerm() { assertThrows(() => { Deno.hostname(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -261,7 +268,7 @@ Deno.test( Deno.test({ permissions: { sys: false } }, function releasePerm() { assertThrows(() => { Deno.osRelease(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { sys: ["osUptime"] } }, function osUptime() { @@ -273,7 +280,7 @@ Deno.test({ permissions: { sys: ["osUptime"] } }, function osUptime() { Deno.test({ permissions: { sys: false } }, function osUptimePerm() { assertThrows(() => { Deno.osUptime(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( diff --git a/tests/unit/performance_test.ts b/tests/unit/performance_test.ts index 0c9ed21df1..fa056c7f54 100644 --- a/tests/unit/performance_test.ts +++ b/tests/unit/performance_test.ts @@ -2,12 +2,13 @@ import { assert, assertEquals, + assertNotEquals, assertNotStrictEquals, assertStringIncludes, assertThrows, } from "./test_util.ts"; -Deno.test({ permissions: { hrtime: false } }, async function performanceNow() { +Deno.test({ permissions: {} }, async function performanceNow() { const { promise, resolve } = Promise.withResolvers(); const start = performance.now(); let totalTime = 0; @@ -36,6 +37,41 @@ Deno.test(function performanceToJSON() { assertEquals(Object.keys(json).length, 1); }); +Deno.test(function clearMarks() { + performance.mark("a"); + performance.mark("a"); + performance.mark("b"); + performance.mark("c"); + + const marksNum = performance.getEntriesByType("mark").length; + + performance.clearMarks("a"); + assertEquals(performance.getEntriesByType("mark").length, marksNum - 2); + + performance.clearMarks(); + assertEquals(performance.getEntriesByType("mark").length, 0); +}); + +Deno.test(function clearMeasures() { + performance.measure("from-start"); + performance.mark("a"); + performance.measure("from-mark-a", "a"); + performance.measure("from-start"); + performance.measure("from-mark-a", "a"); + performance.mark("b"); + performance.measure("between-a-and-b", "a", "b"); + + const measuresNum = performance.getEntriesByType("measure").length; + + performance.clearMeasures("from-start"); + assertEquals(performance.getEntriesByType("measure").length, measuresNum - 2); + + performance.clearMeasures(); + assertEquals(performance.getEntriesByType("measure").length, 0); + + performance.clearMarks(); +}); + Deno.test(function performanceMark() { const mark = performance.mark("test"); assert(mark instanceof PerformanceMark); @@ -127,6 +163,25 @@ Deno.test(function performanceMeasure() { }); }); +Deno.test(function performanceMeasureUseMostRecentMark() { + const markName1 = "mark1"; + const measureName1 = "measure1"; + const mark1 = performance.mark(markName1); + return new Promise((resolve, reject) => { + setTimeout(() => { + try { + const laterMark1 = performance.mark(markName1); + const measure1 = performance.measure(measureName1, markName1); + assertNotEquals(mark1.startTime, measure1.startTime); + assertEquals(laterMark1.startTime, measure1.startTime); + } catch (e) { + return reject(e); + } + resolve(); + }, 100); + }); +}); + Deno.test(function performanceCustomInspectFunction() { assertStringIncludes(Deno.inspect(performance), "Performance"); assertStringIncludes( diff --git a/tests/unit/permissions_test.ts b/tests/unit/permissions_test.ts index 4dab0696a5..f981b10fd6 100644 --- a/tests/unit/permissions_test.ts +++ b/tests/unit/permissions_test.ts @@ -20,57 +20,75 @@ Deno.test(function permissionInvalidNameSync() { }, TypeError); }); -Deno.test(async function permissionNetInvalidHost() { - await assertRejects(async () => { - await Deno.permissions.query({ name: "net", host: ":" }); - }, URIError); -}); +Deno.test( + { permissions: { net: [] } }, + async function permissionNetInvalidHost() { + await assertRejects(async () => { + await Deno.permissions.query({ name: "net", host: ":" }); + }, URIError); + }, +); -Deno.test(function permissionNetInvalidHostSync() { - assertThrows(() => { - Deno.permissions.querySync({ name: "net", host: ":" }); - }, URIError); -}); +Deno.test( + { permissions: { net: [] } }, + function permissionNetInvalidHostSync() { + assertThrows(() => { + Deno.permissions.querySync({ name: "net", host: ":" }); + }, URIError); + }, +); -Deno.test(async function permissionSysValidKind() { - await Deno.permissions.query({ name: "sys", kind: "loadavg" }); - await Deno.permissions.query({ name: "sys", kind: "osRelease" }); - await Deno.permissions.query({ name: "sys", kind: "osUptime" }); - await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" }); - await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" }); - await Deno.permissions.query({ name: "sys", kind: "hostname" }); - await Deno.permissions.query({ name: "sys", kind: "uid" }); - await Deno.permissions.query({ name: "sys", kind: "gid" }); - await Deno.permissions.query({ name: "sys", kind: "cpus" }); -}); +Deno.test( + { permissions: { sys: [] } }, + async function permissionSysValidKind() { + await Deno.permissions.query({ name: "sys", kind: "loadavg" }); + await Deno.permissions.query({ name: "sys", kind: "osRelease" }); + await Deno.permissions.query({ name: "sys", kind: "osUptime" }); + await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" }); + await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" }); + await Deno.permissions.query({ name: "sys", kind: "hostname" }); + await Deno.permissions.query({ name: "sys", kind: "uid" }); + await Deno.permissions.query({ name: "sys", kind: "gid" }); + await Deno.permissions.query({ name: "sys", kind: "cpus" }); + }, +); -Deno.test(function permissionSysValidKindSync() { - Deno.permissions.querySync({ name: "sys", kind: "loadavg" }); - Deno.permissions.querySync({ name: "sys", kind: "osRelease" }); - Deno.permissions.querySync({ name: "sys", kind: "networkInterfaces" }); - Deno.permissions.querySync({ name: "sys", kind: "systemMemoryInfo" }); - Deno.permissions.querySync({ name: "sys", kind: "hostname" }); - Deno.permissions.querySync({ name: "sys", kind: "uid" }); - Deno.permissions.querySync({ name: "sys", kind: "gid" }); - Deno.permissions.querySync({ name: "sys", kind: "cpus" }); -}); +Deno.test( + { permissions: { sys: [] } }, + function permissionSysValidKindSync() { + Deno.permissions.querySync({ name: "sys", kind: "loadavg" }); + Deno.permissions.querySync({ name: "sys", kind: "osRelease" }); + Deno.permissions.querySync({ name: "sys", kind: "networkInterfaces" }); + Deno.permissions.querySync({ name: "sys", kind: "systemMemoryInfo" }); + Deno.permissions.querySync({ name: "sys", kind: "hostname" }); + Deno.permissions.querySync({ name: "sys", kind: "uid" }); + Deno.permissions.querySync({ name: "sys", kind: "gid" }); + Deno.permissions.querySync({ name: "sys", kind: "cpus" }); + }, +); -Deno.test(async function permissionSysInvalidKind() { - await assertRejects(async () => { - // deno-lint-ignore no-explicit-any - await Deno.permissions.query({ name: "sys", kind: "abc" as any }); - }, TypeError); -}); +Deno.test( + { permissions: { sys: [] } }, + async function permissionSysInvalidKind() { + await assertRejects(async () => { + // deno-lint-ignore no-explicit-any + await Deno.permissions.query({ name: "sys", kind: "abc" as any }); + }, TypeError); + }, +); -Deno.test(function permissionSysInvalidKindSync() { - assertThrows(() => { - // deno-lint-ignore no-explicit-any - Deno.permissions.querySync({ name: "sys", kind: "abc" as any }); - }, TypeError); -}); +Deno.test( + { permissions: { sys: [] } }, + function permissionSysInvalidKindSync() { + assertThrows(() => { + // deno-lint-ignore no-explicit-any + Deno.permissions.querySync({ name: "sys", kind: "abc" as any }); + }, TypeError); + }, +); Deno.test(async function permissionQueryReturnsEventTarget() { - const status = await Deno.permissions.query({ name: "hrtime" }); + const status = await Deno.permissions.query({ name: "read", path: "." }); assert(["granted", "denied", "prompt"].includes(status.state)); let called = false; status.addEventListener("change", () => { @@ -78,11 +96,13 @@ Deno.test(async function permissionQueryReturnsEventTarget() { }); status.dispatchEvent(new Event("change")); assert(called); - assert(status === (await Deno.permissions.query({ name: "hrtime" }))); + assert( + status === (await Deno.permissions.query({ name: "read", path: "." })), + ); }); Deno.test(function permissionQueryReturnsEventTargetSync() { - const status = Deno.permissions.querySync({ name: "hrtime" }); + const status = Deno.permissions.querySync({ name: "read", path: "." }); assert(["granted", "denied", "prompt"].includes(status.state)); let called = false; status.addEventListener("change", () => { @@ -90,7 +110,7 @@ Deno.test(function permissionQueryReturnsEventTargetSync() { }); status.dispatchEvent(new Event("change")); assert(called); - assert(status === Deno.permissions.querySync({ name: "hrtime" })); + assert(status === Deno.permissions.querySync({ name: "read", path: "." })); }); Deno.test(async function permissionQueryForReadReturnsSameStatus() { @@ -118,7 +138,7 @@ Deno.test(function permissionQueryForReadReturnsSameStatusSync() { }); Deno.test(function permissionsIllegalConstructor() { - assertThrows(() => new Deno.Permissions(), TypeError, "Illegal constructor."); + assertThrows(() => new Deno.Permissions(), TypeError, "Illegal constructor"); assertEquals(Deno.Permissions.length, 0); }); @@ -126,35 +146,41 @@ Deno.test(function permissionStatusIllegalConstructor() { assertThrows( () => new Deno.PermissionStatus(), TypeError, - "Illegal constructor.", + "Illegal constructor", ); assertEquals(Deno.PermissionStatus.length, 0); }); // Regression test for https://github.com/denoland/deno/issues/17020 -Deno.test(async function permissionURL() { - const path = new URL(".", import.meta.url); +Deno.test( + { permissions: { read: [], write: [], ffi: [], run: [] } }, + async function permissionURL() { + const path = new URL(".", import.meta.url); - await Deno.permissions.query({ name: "read", path }); - await Deno.permissions.query({ name: "write", path }); - await Deno.permissions.query({ name: "ffi", path }); - await Deno.permissions.query({ name: "run", command: path }); -}); + await Deno.permissions.query({ name: "read", path }); + await Deno.permissions.query({ name: "write", path }); + await Deno.permissions.query({ name: "ffi", path }); + await Deno.permissions.query({ name: "run", command: path }); + }, +); -Deno.test(function permissionURLSync() { - Deno.permissions.querySync({ - name: "read", - path: new URL(".", import.meta.url), - }); - Deno.permissions.querySync({ - name: "write", - path: new URL(".", import.meta.url), - }); - Deno.permissions.querySync({ - name: "run", - command: new URL(".", import.meta.url), - }); -}); +Deno.test( + { permissions: { read: [], write: [], ffi: [], run: [] } }, + function permissionURLSync() { + Deno.permissions.querySync({ + name: "read", + path: new URL(".", import.meta.url), + }); + Deno.permissions.querySync({ + name: "write", + path: new URL(".", import.meta.url), + }); + Deno.permissions.querySync({ + name: "run", + command: new URL(".", import.meta.url), + }); + }, +); Deno.test(async function permissionDescriptorValidation() { for (const value of [undefined, null, {}]) { diff --git a/tests/unit/process_test.ts b/tests/unit/process_test.ts index 040c6ee197..5cbab3b4c5 100644 --- a/tests/unit/process_test.ts +++ b/tests/unit/process_test.ts @@ -1,3 +1,4 @@ +// deno-lint-ignore-file no-deprecated-deno-api // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assert, @@ -11,18 +12,18 @@ Deno.test( { permissions: { read: true, run: false } }, function runPermissions() { assertThrows(() => { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. Deno.run({ cmd: [Deno.execPath(), "eval", "console.log('hello world')"], }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); Deno.test( { permissions: { run: true, read: true } }, async function runSuccess() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ // freeze the array to ensure it's not modified cmd: Object.freeze([ @@ -45,7 +46,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runUrl() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ new URL(`file:///${Deno.execPath()}`), @@ -69,7 +70,7 @@ Deno.test( async function runStdinRid0(): Promise< void > { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [Deno.execPath(), "eval", "console.log('hello world')"], stdin: 0, @@ -89,26 +90,23 @@ Deno.test( { permissions: { run: true, read: true } }, function runInvalidStdio() { assertThrows(() => - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. Deno.run({ cmd: [Deno.execPath(), "eval", "console.log('hello world')"], - // @ts-expect-error because Deno.run should throw on invalid stdin. stdin: "a", }) ); assertThrows(() => - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. Deno.run({ cmd: [Deno.execPath(), "eval", "console.log('hello world')"], - // @ts-expect-error because Deno.run should throw on invalid stdout. stdout: "b", }) ); assertThrows(() => - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. Deno.run({ cmd: [Deno.execPath(), "eval", "console.log('hello world')"], - // @ts-expect-error because Deno.run should throw on invalid stderr. stderr: "c", }) ); @@ -118,7 +116,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runCommandFailedWithCode() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [Deno.execPath(), "eval", "Deno.exit(41 + 1)"], }); @@ -135,7 +133,7 @@ Deno.test( permissions: { run: true, read: true }, }, async function runCommandFailedWithSignal() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -159,7 +157,7 @@ Deno.test( Deno.test({ permissions: { run: true } }, function runNotFound() { let error; try { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. Deno.run({ cmd: ["this file hopefully doesn't exist"] }); } catch (e) { error = e; @@ -191,7 +189,7 @@ tryExit(); `; Deno.writeFileSync(`${cwd}/${programFile}`, enc.encode(program)); - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cwd, cmd: [Deno.execPath(), "run", "--allow-read", programFile], @@ -215,7 +213,7 @@ Deno.test( async function runStdinPiped(): Promise< void > { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -253,7 +251,7 @@ Deno.test( async function runStdoutPiped(): Promise< void > { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -290,7 +288,7 @@ Deno.test( async function runStderrPiped(): Promise< void > { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -325,7 +323,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runOutput() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -346,7 +344,7 @@ Deno.test( async function runStderrOutput(): Promise< void > { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -363,7 +361,9 @@ Deno.test( ); Deno.test( - { permissions: { run: true, write: true, read: true } }, + { + permissions: { run: true, write: true, read: true }, + }, async function runRedirectStdoutStderr() { const tempDir = await Deno.makeTempDir(); const fileName = tempDir + "/redirected_stdio.txt"; @@ -372,17 +372,19 @@ Deno.test( write: true, }); - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), "eval", "Deno.stderr.write(new TextEncoder().encode('error\\n')); Deno.stdout.write(new TextEncoder().encode('output\\n'));", ], - stdout: file.rid, - stderr: file.rid, + stdout: "piped", + stderr: "piped", }); + await p.stdout.readable.pipeTo(file.writable, { preventClose: true }); + await p.stderr.readable.pipeTo(file.writable); await p.status(); p.close(); @@ -392,18 +394,22 @@ Deno.test( assertStringIncludes(text, "error"); assertStringIncludes(text, "output"); + // deno-lint-ignore no-console + console.log("finished tgis test"); }, ); Deno.test( - { permissions: { run: true, write: true, read: true } }, + { + permissions: { run: true, write: true, read: true }, + }, async function runRedirectStdin() { const tempDir = await Deno.makeTempDir(); const fileName = tempDir + "/redirected_stdio.txt"; await Deno.writeTextFile(fileName, "hello"); using file = await Deno.open(fileName); - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -416,9 +422,10 @@ Deno.test( } `, ], - stdin: file.rid, + stdin: "piped", }); + await file.readable.pipeTo(p.stdin.writable); const status = await p.status(); assertEquals(status.code, 0); p.close(); @@ -428,7 +435,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runEnv() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -451,7 +458,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runClose() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -475,7 +482,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function runKillAfterStatus() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [Deno.execPath(), "eval", 'console.log("hello")'], }); @@ -508,7 +515,7 @@ Deno.test({ permissions: { run: false } }, function killPermissions() { // process - assuming that Deno does not have a special handler set for it // and will just continue even if a signal is erroneously sent. Deno.kill(Deno.pid, "SIGCONT"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -532,7 +539,7 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function killSuccess() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [Deno.execPath(), "eval", "setTimeout(() => {}, 10000)"], }); @@ -556,7 +563,7 @@ Deno.test( ); Deno.test({ permissions: { run: true, read: true } }, function killFailed() { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [Deno.execPath(), "eval", "setTimeout(() => {}, 10000)"], }); @@ -571,109 +578,13 @@ Deno.test({ permissions: { run: true, read: true } }, function killFailed() { p.close(); }); -Deno.test( - { permissions: { run: true, read: true, env: true } }, - async function clearEnv(): Promise { - // deno-lint-ignore no-deprecated-deno-api - const p = Deno.run({ - cmd: [ - Deno.execPath(), - "eval", - "-p", - "JSON.stringify(Deno.env.toObject())", - ], - stdout: "piped", - clearEnv: true, - env: { - FOO: "23147", - }, - }); - - const obj = JSON.parse(new TextDecoder().decode(await p.output())); - - // can't check for object equality because the OS may set additional env - // vars for processes, so we check if PATH isn't present as that is a common - // env var across OS's and isn't set for processes. - assertEquals(obj.FOO, "23147"); - assert(!("PATH" in obj)); - - p.close(); - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - async function uid(): Promise { - // deno-lint-ignore no-deprecated-deno-api - const p = Deno.run({ - cmd: [ - "id", - "-u", - ], - stdout: "piped", - }); - - const currentUid = new TextDecoder().decode(await p.output()); - p.close(); - - if (currentUid !== "0") { - assertThrows(() => { - // deno-lint-ignore no-deprecated-deno-api - Deno.run({ - cmd: [ - "echo", - "fhqwhgads", - ], - uid: 0, - }); - }, Deno.errors.PermissionDenied); - } - }, -); - -Deno.test( - { - permissions: { run: true, read: true }, - ignore: Deno.build.os === "windows", - }, - async function gid(): Promise { - // deno-lint-ignore no-deprecated-deno-api - const p = Deno.run({ - cmd: [ - "id", - "-g", - ], - stdout: "piped", - }); - - const currentGid = new TextDecoder().decode(await p.output()); - p.close(); - - if (currentGid !== "0") { - assertThrows(() => { - // deno-lint-ignore no-deprecated-deno-api - Deno.run({ - cmd: [ - "echo", - "fhqwhgads", - ], - gid: 0, - }); - }, Deno.errors.PermissionDenied); - } - }, -); - Deno.test( { permissions: { run: true, read: true, write: true }, ignore: Deno.build.os === "windows", }, async function non_existent_cwd(): Promise { - // deno-lint-ignore no-deprecated-deno-api + // @ts-ignore `Deno.run()` was soft-removed in Deno 2. const p = Deno.run({ cmd: [ Deno.execPath(), @@ -696,6 +607,6 @@ Deno.test( p.close(); p.stdout.close(); assertStrictEquals(code, 1); - assertStringIncludes(stderr, "Failed getting cwd."); + assertStringIncludes(stderr, "failed resolving cwd:"); }, ); diff --git a/tests/unit/read_dir_test.ts b/tests/unit/read_dir_test.ts index cba9647e5b..b00495eb45 100644 --- a/tests/unit/read_dir_test.ts +++ b/tests/unit/read_dir_test.ts @@ -35,7 +35,7 @@ Deno.test({ permissions: { read: true } }, function readDirSyncWithUrl() { Deno.test({ permissions: { read: false } }, function readDirSyncPerm() { assertThrows(() => { Deno.readDirSync("tests/"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readDirSyncNotDir() { @@ -79,7 +79,7 @@ Deno.test({ permissions: { read: true } }, async function readDirWithUrl() { Deno.test({ permissions: { read: false } }, async function readDirPerm() { await assertRejects(async () => { await Deno.readDir("tests/")[Symbol.asyncIterator]().next(); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( diff --git a/tests/unit/read_file_test.ts b/tests/unit/read_file_test.ts index 67944813bb..7123833e9c 100644 --- a/tests/unit/read_file_test.ts +++ b/tests/unit/read_file_test.ts @@ -31,7 +31,7 @@ Deno.test({ permissions: { read: true } }, function readFileSyncUrl() { Deno.test({ permissions: { read: false } }, function readFileSyncPerm() { assertThrows(() => { Deno.readFileSync("tests/testdata/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readFileSyncNotFound() { @@ -63,7 +63,7 @@ Deno.test({ permissions: { read: true } }, async function readFileSuccess() { Deno.test({ permissions: { read: false } }, async function readFilePerm() { await assertRejects(async () => { await Deno.readFile("tests/testdata/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readFileSyncLoop() { @@ -161,7 +161,7 @@ Deno.test( try { await Deno.readFile("definitely-not-found.json"); } catch (e) { - assertEquals(e.code, "ENOENT"); + assertEquals((e as { code: string }).code, "ENOENT"); } }, ); @@ -172,7 +172,7 @@ Deno.test( try { await Deno.readFile("tests/testdata/assets/"); } catch (e) { - assertEquals(e.code, "EISDIR"); + assertEquals((e as { code: string }).code, "EISDIR"); } }, ); diff --git a/tests/unit/read_link_test.ts b/tests/unit/read_link_test.ts index 3ed1817bbf..c89ffe4927 100644 --- a/tests/unit/read_link_test.ts +++ b/tests/unit/read_link_test.ts @@ -39,7 +39,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, function readLinkSyncPerm() { assertThrows(() => { Deno.readLinkSync("/symlink"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readLinkSyncNotFound() { @@ -85,7 +85,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, async function readLinkPerm() { await assertRejects(async () => { await Deno.readLink("/symlink"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, async function readLinkNotFound() { diff --git a/tests/unit/read_text_file_test.ts b/tests/unit/read_text_file_test.ts index cab75fd47b..1ec57bde35 100644 --- a/tests/unit/read_text_file_test.ts +++ b/tests/unit/read_text_file_test.ts @@ -28,7 +28,7 @@ Deno.test({ permissions: { read: true } }, function readTextFileSyncByUrl() { Deno.test({ permissions: { read: false } }, function readTextFileSyncPerm() { assertThrows(() => { Deno.readTextFileSync("tests/testdata/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readTextFileSyncNotFound() { @@ -61,7 +61,7 @@ Deno.test({ permissions: { read: true } }, async function readTextFileByUrl() { Deno.test({ permissions: { read: false } }, async function readTextFilePerm() { await assertRejects(async () => { await Deno.readTextFile("tests/testdata/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function readTextFileSyncLoop() { diff --git a/tests/unit/real_path_test.ts b/tests/unit/real_path_test.ts index b3656a927c..7832846308 100644 --- a/tests/unit/real_path_test.ts +++ b/tests/unit/real_path_test.ts @@ -50,7 +50,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, function realPathSyncPerm() { assertThrows(() => { Deno.realPathSync("some_file"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function realPathSyncNotFound() { @@ -104,7 +104,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, async function realPathPerm() { await assertRejects(async () => { await Deno.realPath("some_file"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, async function realPathNotFound() { diff --git a/tests/unit/remove_test.ts b/tests/unit/remove_test.ts index f4e54dc523..261ff6bd05 100644 --- a/tests/unit/remove_test.ts +++ b/tests/unit/remove_test.ts @@ -153,7 +153,7 @@ Deno.test({ permissions: { write: false } }, async function removePerm() { for (const method of REMOVE_METHODS) { await assertRejects(async () => { await Deno[method]("/baddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); } }); @@ -233,7 +233,7 @@ Deno.test({ permissions: { write: false } }, async function removeAllPerm() { for (const method of REMOVE_METHODS) { await assertRejects(async () => { await Deno[method]("/baddir", { recursive: true }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); } }); diff --git a/tests/unit/rename_test.ts b/tests/unit/rename_test.ts index 4f6bb09cf6..3162c699c6 100644 --- a/tests/unit/rename_test.ts +++ b/tests/unit/rename_test.ts @@ -70,7 +70,7 @@ Deno.test( const oldpath = "/oldbaddir"; const newpath = "/newbaddir"; Deno.renameSync(oldpath, newpath); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -81,7 +81,7 @@ Deno.test( const oldpath = "/oldbaddir"; const newpath = "/newbaddir"; Deno.renameSync(oldpath, newpath); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/resources_test.ts b/tests/unit/resources_test.ts deleted file mode 100644 index 921a8af8f9..0000000000 --- a/tests/unit/resources_test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -// deno-lint-ignore-file no-deprecated-deno-api - -import { assert, assertEquals, assertThrows } from "./test_util.ts"; - -const listenPort = 4505; - -Deno.test(function resourcesCloseBadArgs() { - assertThrows(() => { - Deno.close((null as unknown) as number); - }, TypeError); -}); - -Deno.test(function resourcesStdio() { - const res = Deno.resources(); - - assertEquals(res[0], "stdin"); - assertEquals(res[1], "stdout"); - assertEquals(res[2], "stderr"); -}); - -Deno.test({ permissions: { net: true } }, async function resourcesNet() { - const listener = Deno.listen({ port: listenPort }); - const dialerConn = await Deno.connect({ port: listenPort }); - const listenerConn = await listener.accept(); - - const res = Deno.resources(); - assertEquals( - Object.values(res).filter((r): boolean => r === "tcpListener").length, - 1, - ); - const tcpStreams = Object.values(res).filter( - (r): boolean => r === "tcpStream", - ); - assert(tcpStreams.length >= 2); - - listenerConn.close(); - dialerConn.close(); - listener.close(); -}); - -Deno.test({ permissions: { read: true } }, async function resourcesFile() { - const resourcesBefore = Deno.resources(); - const f = await Deno.open("tests/testdata/assets/hello.txt"); - const resourcesAfter = Deno.resources(); - f.close(); - - // check that exactly one new resource (file) was added - assertEquals( - Object.keys(resourcesAfter).length, - Object.keys(resourcesBefore).length + 1, - ); - const newRid = +Object.keys(resourcesAfter).find((rid): boolean => { - return !Object.prototype.hasOwnProperty.call(resourcesBefore, rid); - })!; - assertEquals(resourcesAfter[newRid], "fsFile"); -}); diff --git a/tests/unit/serve_test.ts b/tests/unit/serve_test.ts index 353621154e..439d71d553 100644 --- a/tests/unit/serve_test.ts +++ b/tests/unit/serve_test.ts @@ -1,7 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import { assertMatch, assertRejects } from "@std/assert"; -import { Buffer, BufReader, BufWriter } from "@std/io"; +import { Buffer, BufReader, BufWriter, type Reader } from "@std/io"; import { TextProtoReader } from "../testdata/run/textproto.ts"; import { assert, @@ -17,7 +19,7 @@ import { } from "./test_util.ts"; // Since these tests may run in parallel, ensure this port is unique to this file -const servePort = 4502; +const servePort = 4511; const { upgradeHttpRaw, @@ -676,6 +678,40 @@ Deno.test( }, ); +Deno.test( + { permissions: { net: true } }, + async function httpServerReturnErrorResponse() { + const ac = new AbortController(); + const { promise, resolve } = Promise.withResolvers(); + let hadError = false; + const server = Deno.serve({ + handler: () => { + return Response.error(); + }, + port: servePort, + signal: ac.signal, + onListen: onListen(resolve), + onError: () => { + hadError = true; + return new Response("Internal Server Error", { status: 500 }); + }, + }); + + await promise; + + const resp = await fetch(`http://127.0.0.1:${servePort}/`, { + headers: { "connection": "close" }, + }); + assertEquals(resp.status, 500); + const text = await resp.text(); + assertEquals(text, "Internal Server Error"); + assert(hadError); + + ac.abort(); + await server.finished; + }, +); + Deno.test({ permissions: { net: true } }, async function httpServerOverload1() { const ac = new AbortController(); const deferred = Promise.withResolvers(); @@ -790,8 +826,8 @@ Deno.test( async function httpServerDefaultOnListenCallback() { const ac = new AbortController(); - const consoleLog = console.log; - console.log = (msg) => { + const consoleError = console.error; + console.error = (msg) => { try { const match = msg.match( /Listening on http:\/\/(localhost|0\.0\.0\.0):(\d+)\//, @@ -816,7 +852,7 @@ Deno.test( await server.finished; } finally { - console.log = consoleLog; + console.error = consoleError; } }, ); @@ -859,6 +895,118 @@ Deno.test( }, ); +Deno.test({ permissions: { net: true } }, async function validPortString() { + const server = Deno.serve({ + handler: (_request) => new Response(), + port: "4501" as unknown as number, + }); + assertEquals(server.addr.transport, "tcp"); + assertEquals(server.addr.port, 4501); + await server.shutdown(); +}); + +Deno.test({ permissions: { net: true } }, async function ipv6Hostname() { + const ac = new AbortController(); + let url = ""; + + const consoleError = console.error; + console.error = (msg) => { + try { + const match = msg.match(/Listening on (http:\/\/(.*?):(\d+)\/)/); + assert(!!match, `Didn't match ${msg}`); + url = match[1]; + } finally { + ac.abort(); + } + }; + + try { + const server = Deno.serve({ + handler: () => new Response(), + hostname: "::1", + port: 0, + signal: ac.signal, + }); + assertEquals(server.addr.transport, "tcp"); + assert(new URL(url), `Not a valid URL "${url}"`); + await server.shutdown(); + } finally { + console.error = consoleError; + } +}); + +Deno.test({ permissions: { net: true } }, function invalidPortFloat() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: 45.1, + }), + TypeError, + `Invalid port: 45.1`, + ); +}); + +Deno.test({ permissions: { net: true } }, function invalidPortNaN() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: NaN, + }), + TypeError, + `Invalid port: NaN`, + ); +}); + +Deno.test({ permissions: { net: true } }, function invalidPortString() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: "some-non-number-string" as unknown as number, + }), + TypeError, + `Invalid port: 'some-non-number-string'`, + ); +}); + +Deno.test({ permissions: { net: true } }, function invalidPortTooSmall() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: -111, + }), + RangeError, + `Invalid port (out of range): -111`, + ); +}); + +Deno.test({ permissions: { net: true } }, function invalidPortTooLarge() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: 100000, + }), + RangeError, + `Invalid port (out of range): 100000`, + ); +}); + +Deno.test({ permissions: { net: true } }, function invalidPortType() { + assertThrows( + () => + Deno.serve({ + handler: (_request) => new Response(), + port: true as unknown as number, + }), + TypeError, + `Invalid port (expected number): true`, + ); +}); + function createUrlTest( name: string, methodAndPath: string, @@ -1444,7 +1592,7 @@ Deno.test( Deno.upgradeWebSocket(request); }, Deno.errors.Http, - "already upgraded", + "Already upgraded", ); socket.onerror = (e) => { console.error(e); @@ -3546,7 +3694,7 @@ Deno.test( } catch (cloneError) { assert(cloneError instanceof TypeError); assert( - cloneError.message.endsWith("Body is unusable."), + cloneError.message.endsWith("Body is unusable"), ); ac.abort(); @@ -3595,7 +3743,7 @@ Deno.test({ } catch (cloneError) { assert(cloneError instanceof TypeError); assert( - cloneError.message.endsWith("Body is unusable."), + cloneError.message.endsWith("Body is unusable"), ); ac.abort(); @@ -3659,7 +3807,7 @@ Deno.test( }, ); -function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader { +function chunkedBodyReader(h: Headers, r: BufReader): Reader { // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 const tp = new TextProtoReader(r); let finished = false; @@ -3747,7 +3895,7 @@ async function readTrailers( const tp = new TextProtoReader(r); const result = await tp.readMimeHeader(); if (result == null) { - throw new Deno.errors.InvalidData("Missing trailer header."); + throw new Deno.errors.InvalidData("Missing trailer header"); } const undeclared = [...result.keys()].filter( (k) => !trailerNames.includes(k), @@ -3775,7 +3923,7 @@ function parseTrailer(field: string | null): Headers | undefined { } const trailerNames = field.split(",").map((v) => v.trim().toLowerCase()); if (trailerNames.length === 0) { - throw new Deno.errors.InvalidData("Empty trailer header."); + throw new Deno.errors.InvalidData("Empty trailer header"); } const prohibited = trailerNames.filter((k) => isProhibitedForTrailer(k)); if (prohibited.length > 0) { @@ -4106,3 +4254,19 @@ Deno.test({ 'Operation `"op_net_listen_unix"` not supported on non-unix platforms.', ); }); + +Deno.test({ + name: "onListen callback gets 0.0.0.0 hostname as is", +}, async () => { + const { promise, resolve } = Promise.withResolvers<{ hostname: string }>(); + + const server = Deno.serve({ + handler: (_) => new Response("ok"), + hostname: "0.0.0.0", + port: 0, + onListen: resolve, + }); + const { hostname } = await promise; + assertEquals(hostname, "0.0.0.0"); + await server.shutdown(); +}); diff --git a/tests/unit/signal_test.ts b/tests/unit/signal_test.ts index 0c0676428a..8923aa75bf 100644 --- a/tests/unit/signal_test.ts +++ b/tests/unit/signal_test.ts @@ -5,101 +5,101 @@ Deno.test( { ignore: Deno.build.os !== "windows" }, function signalsNotImplemented() { const msg = - "Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK)."; + "Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK), but got "; assertThrows( () => { Deno.addSignalListener("SIGALRM", () => {}); }, Error, - msg, + msg + "SIGALRM", ); assertThrows( () => { Deno.addSignalListener("SIGCHLD", () => {}); }, Error, - msg, + msg + "SIGCHLD", ); assertThrows( () => { Deno.addSignalListener("SIGHUP", () => {}); }, Error, - msg, + msg + "SIGHUP", ); assertThrows( () => { Deno.addSignalListener("SIGIO", () => {}); }, Error, - msg, + msg + "SIGIO", ); assertThrows( () => { Deno.addSignalListener("SIGPIPE", () => {}); }, Error, - msg, + msg + "SIGPIPE", ); assertThrows( () => { Deno.addSignalListener("SIGQUIT", () => {}); }, Error, - msg, + msg + "SIGQUIT", ); assertThrows( () => { Deno.addSignalListener("SIGTERM", () => {}); }, Error, - msg, + msg + "SIGTERM", ); assertThrows( () => { Deno.addSignalListener("SIGUSR1", () => {}); }, Error, - msg, + msg + "SIGUSR1", ); assertThrows( () => { Deno.addSignalListener("SIGUSR2", () => {}); }, Error, - msg, + msg + "SIGUSR2", ); assertThrows( () => { Deno.addSignalListener("SIGWINCH", () => {}); }, Error, - msg, + msg + "SIGWINCH", ); assertThrows( () => Deno.addSignalListener("SIGKILL", () => {}), Error, - msg, + msg + "SIGKILL", ); assertThrows( () => Deno.addSignalListener("SIGSTOP", () => {}), Error, - msg, + msg + "SIGSTOP", ); assertThrows( () => Deno.addSignalListener("SIGILL", () => {}), Error, - msg, + msg + "SIGILL", ); assertThrows( () => Deno.addSignalListener("SIGFPE", () => {}), Error, - msg, + msg + "SIGFPE", ); assertThrows( () => Deno.addSignalListener("SIGSEGV", () => {}), Error, - msg, + msg + "SIGSEGV", ); }, ); @@ -209,7 +209,6 @@ Deno.test( const { code } = await new Deno.Command(Deno.execPath(), { args: [ "eval", - "--unstable", "Deno.addSignalListener('SIGINT', () => {})", ], }).output(); diff --git a/tests/unit/stat_test.ts b/tests/unit/stat_test.ts index e64b47536e..59831a069f 100644 --- a/tests/unit/stat_test.ts +++ b/tests/unit/stat_test.ts @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// deno-lint-ignore-file no-deprecated-deno-api - import { assert, assertEquals, @@ -10,32 +8,6 @@ import { pathToAbsoluteFileUrl, } from "./test_util.ts"; -Deno.test({ permissions: { read: true } }, function fstatSyncSuccess() { - using file = Deno.openSync("README.md"); - const fileInfo = Deno.fstatSync(file.rid); - assert(fileInfo.isFile); - assert(!fileInfo.isSymlink); - assert(!fileInfo.isDirectory); - assert(fileInfo.size); - assert(fileInfo.atime); - assert(fileInfo.mtime); - // The `birthtime` field is not available on Linux before kernel version 4.11. - assert(fileInfo.birthtime || Deno.build.os === "linux"); -}); - -Deno.test({ permissions: { read: true } }, async function fstatSuccess() { - using file = await Deno.open("README.md"); - const fileInfo = await Deno.fstat(file.rid); - assert(fileInfo.isFile); - assert(!fileInfo.isSymlink); - assert(!fileInfo.isDirectory); - assert(fileInfo.size); - assert(fileInfo.atime); - assert(fileInfo.mtime); - // The `birthtime` field is not available on Linux before kernel version 4.11. - assert(fileInfo.birthtime || Deno.build.os === "linux"); -}); - Deno.test( { permissions: { read: true, write: true } }, function statSyncSuccess() { @@ -102,7 +74,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, function statSyncPerm() { assertThrows(() => { Deno.statSync("README.md"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function statSyncNotFound() { @@ -146,7 +118,7 @@ Deno.test({ permissions: { read: true } }, function lstatSyncSuccess() { Deno.test({ permissions: { read: false } }, function lstatSyncPerm() { assertThrows(() => { Deno.lstatSync("assets/hello.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, function lstatSyncNotFound() { @@ -228,7 +200,7 @@ Deno.test( Deno.test({ permissions: { read: false } }, async function statPerm() { await assertRejects(async () => { await Deno.stat("README.md"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, async function statNotFound() { @@ -272,7 +244,7 @@ Deno.test({ permissions: { read: true } }, async function lstatSuccess() { Deno.test({ permissions: { read: false } }, async function lstatPerm() { await assertRejects(async () => { await Deno.lstat("README.md"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { read: true } }, async function lstatNotFound() { diff --git a/tests/unit/streams_test.ts b/tests/unit/streams_test.ts index c0adbda07c..b866fa7d51 100644 --- a/tests/unit/streams_test.ts +++ b/tests/unit/streams_test.ts @@ -1,10 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { - assertEquals, - assertRejects, - assertThrows, - fail, -} from "./test_util.ts"; +import { assertEquals, assertRejects, fail } from "./test_util.ts"; const { core, @@ -303,7 +298,7 @@ for ( await core.read(rid, new Uint8Array(1)); fail(); } catch (e) { - assertEquals(e.message, `Uh oh (${type})!`); + assertEquals((e as Error).message, `Uh oh (${type})!`); } core.close(rid); }); @@ -434,7 +429,7 @@ function createStreamTest( fail(); } catch (e) { // We expect this to be thrown - assertEquals(e.message, "Expected error!"); + assertEquals((e as Error).message, "Expected error!"); } } else { const buffer = new Uint8Array(1); @@ -476,7 +471,7 @@ for (const packetCount of [1, 1024]) { } fail(); } catch (e) { - assertEquals(e.message, "operation canceled"); + assertEquals((e as Error).message, "operation canceled"); } assertEquals(await promise, "resource closed"); }); @@ -538,11 +533,3 @@ Deno.test(async function decompressionStreamInvalidGzipStillReported() { "corrupt gzip stream does not have a matching checksum", ); }); - -Deno.test(function readableStreamFromWithStringThrows() { - assertThrows( - () => ReadableStream.from("string"), - TypeError, - "Failed to execute 'ReadableStream.from': Argument 1 can not be converted to async iterable.", - ); -}); diff --git a/tests/unit/symlink_test.ts b/tests/unit/symlink_test.ts index 0ee4a36fda..47a685ec61 100644 --- a/tests/unit/symlink_test.ts +++ b/tests/unit/symlink_test.ts @@ -62,7 +62,7 @@ Deno.test( function symlinkSyncPerm() { assertThrows(() => { Deno.symlinkSync("oldbaddir", "newbaddir"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -152,11 +152,11 @@ Deno.test( async function symlinkNoFullWritePermissions() { await assertRejects( () => Deno.symlink("old", "new"), - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, ); assertThrows( () => Deno.symlinkSync("old", "new"), - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, ); }, ); @@ -166,11 +166,11 @@ Deno.test( async function symlinkNoFullReadPermissions() { await assertRejects( () => Deno.symlink("old", "new"), - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, ); assertThrows( () => Deno.symlinkSync("old", "new"), - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, ); }, ); diff --git a/tests/unit/sync_test.ts b/tests/unit/sync_test.ts deleted file mode 100644 index 93eb4f0b08..0000000000 --- a/tests/unit/sync_test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assertEquals } from "./test_util.ts"; - -Deno.test( - { permissions: { read: true, write: true } }, - function fdatasyncSyncSuccess() { - const filename = Deno.makeTempDirSync() + "/test_fdatasyncSync.txt"; - using file = Deno.openSync(filename, { - read: true, - write: true, - create: true, - }); - const data = new Uint8Array(64); - file.writeSync(data); - Deno.fdatasyncSync(file.rid); - Deno.removeSync(filename); - }, -); - -Deno.test( - { permissions: { read: true, write: true } }, - async function fdatasyncSuccess() { - const filename = (await Deno.makeTempDir()) + "/test_fdatasync.txt"; - using file = await Deno.open(filename, { - read: true, - write: true, - create: true, - }); - const data = new Uint8Array(64); - await file.write(data); - await Deno.fdatasync(file.rid); - assertEquals(await Deno.readFile(filename), data); - await Deno.remove(filename); - }, -); - -Deno.test( - { permissions: { read: true, write: true } }, - function fsyncSyncSuccess() { - const filename = Deno.makeTempDirSync() + "/test_fsyncSync.txt"; - using file = Deno.openSync(filename, { - read: true, - write: true, - create: true, - }); - const size = 64; - file.truncateSync(size); - Deno.fsyncSync(file.rid); - assertEquals(Deno.statSync(filename).size, size); - Deno.removeSync(filename); - }, -); - -Deno.test( - { permissions: { read: true, write: true } }, - async function fsyncSuccess() { - const filename = (await Deno.makeTempDir()) + "/test_fsync.txt"; - using file = await Deno.open(filename, { - read: true, - write: true, - create: true, - }); - const size = 64; - await file.truncate(size); - await Deno.fsync(file.rid); - assertEquals((await Deno.stat(filename)).size, size); - await Deno.remove(filename); - }, -); diff --git a/tests/unit/test_util.ts b/tests/unit/test_util.ts index e45a963e9a..a987cb5427 100644 --- a/tests/unit/test_util.ts +++ b/tests/unit/test_util.ts @@ -78,7 +78,7 @@ export function execCode3(cmd: string, args: string[]) { } export function execCode2(code: string) { - return execCode3(Deno.execPath(), ["eval", "--unstable", "--no-check", code]); + return execCode3(Deno.execPath(), ["eval", code]); } export function tmpUnixSocketPath(): string { diff --git a/tests/unit/testing_test.ts b/tests/unit/testing_test.ts index e04ab921c7..51372c42b0 100644 --- a/tests/unit/testing_test.ts +++ b/tests/unit/testing_test.ts @@ -8,7 +8,7 @@ Deno.test(function testWrongOverloads() { Deno.test("some name", { fn: () => {} }, () => {}); }, TypeError, - "Unexpected 'fn' field in options, test function is already provided as the third argument.", + "Unexpected 'fn' field in options, test function is already provided as the third argument", ); assertThrows( () => { @@ -16,7 +16,7 @@ Deno.test(function testWrongOverloads() { Deno.test("some name", { name: "some name2" }, () => {}); }, TypeError, - "Unexpected 'name' field in options, test name is already provided as the first argument.", + "Unexpected 'name' field in options, test name is already provided as the first argument", ); assertThrows( () => { @@ -40,7 +40,7 @@ Deno.test(function testWrongOverloads() { Deno.test({ fn: () => {} }, function foo() {}); }, TypeError, - "Unexpected 'fn' field in options, test function is already provided as the second argument.", + "Unexpected 'fn' field in options, test function is already provided as the second argument", ); assertThrows( () => { @@ -48,7 +48,7 @@ Deno.test(function testWrongOverloads() { Deno.test({}); }, TypeError, - "Expected 'fn' field in the first argument to be a test function.", + "Expected 'fn' field in the first argument to be a test function", ); assertThrows( () => { @@ -56,7 +56,7 @@ Deno.test(function testWrongOverloads() { Deno.test({ fn: "boo!" }); }, TypeError, - "Expected 'fn' field in the first argument to be a test function.", + "Expected 'fn' field in the first argument to be a test function", ); }); @@ -87,7 +87,7 @@ Deno.test(async function invalidStepArguments(t) { await (t as any).step("test"); }, TypeError, - "Expected function for second argument.", + "Expected function for second argument", ); await assertRejects( @@ -96,7 +96,7 @@ Deno.test(async function invalidStepArguments(t) { await (t as any).step("test", "not a function"); }, TypeError, - "Expected function for second argument.", + "Expected function for second argument", ); await assertRejects( @@ -105,7 +105,7 @@ Deno.test(async function invalidStepArguments(t) { await (t as any).step(); }, TypeError, - "Expected a test definition or name and function.", + "Expected a test definition or name and function", ); await assertRejects( @@ -114,7 +114,7 @@ Deno.test(async function invalidStepArguments(t) { await (t as any).step(() => {}); }, TypeError, - "The step function must have a name.", + "The step function must have a name", ); }); diff --git a/tests/unit/timers_test.ts b/tests/unit/timers_test.ts index 6e829c07fc..580d8c524e 100644 --- a/tests/unit/timers_test.ts +++ b/tests/unit/timers_test.ts @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { assert, assertEquals, @@ -308,11 +311,11 @@ Deno.test(async function timeoutCallbackThis() { }; setTimeout(obj.foo, 1); await promise; - assertEquals(capturedThis, window); + assertEquals(capturedThis, globalThis); }); Deno.test(async function timeoutBindThis() { - const thisCheckPassed = [null, undefined, window, globalThis]; + const thisCheckPassed = [null, undefined, globalThis]; const thisCheckFailed = [ 0, diff --git a/tests/unit/tls_sni_test.ts b/tests/unit/tls_sni_test.ts index 404f8016e3..a8d51108e7 100644 --- a/tests/unit/tls_sni_test.ts +++ b/tests/unit/tls_sni_test.ts @@ -25,9 +25,8 @@ Deno.test( return keys[sni]!; }, }; - const listener = Deno.listenTls( - opts, - ); + // @ts-ignore Trust me + const listener = Deno.listenTls(opts); for ( const server of ["server-1", "server-2", "fail-server-3", "fail-server-4"] diff --git a/tests/unit/tls_test.ts b/tests/unit/tls_test.ts index 34061bb21e..219f4a4508 100644 --- a/tests/unit/tls_test.ts +++ b/tests/unit/tls_test.ts @@ -54,7 +54,7 @@ function unreachable(): never { Deno.test({ permissions: { net: false } }, async function connectTLSNoPerm() { await assertRejects(async () => { await Deno.connectTls({ hostname: "deno.land", port: 443 }); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -66,111 +66,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { net: true, read: false } }, - async function connectTLSCertFileNoReadPerm() { - await assertRejects(async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - certFile: "tests/testdata/tls/RootCA.crt", - }); - }, Deno.errors.PermissionDenied); - }, -); - -Deno.test( - { permissions: { read: true, net: true } }, - function listenTLSNonExistentCertKeyFiles() { - const options = { - hostname: "localhost", - port: 0, - certFile: "tests/testdata/tls/localhost.crt", - keyFile: "tests/testdata/tls/localhost.key", - }; - - assertThrows(() => { - Deno.listenTls({ - ...options, - certFile: "./non/existent/file", - }); - }, Deno.errors.NotFound); - - assertThrows(() => { - Deno.listenTls({ - ...options, - keyFile: "./non/existent/file", - }); - }, Deno.errors.NotFound); - }, -); - -Deno.test( - { permissions: { net: true, read: false } }, - function listenTLSNoReadPerm() { - assertThrows(() => { - Deno.listenTls({ - hostname: "localhost", - port: 0, - certFile: "tests/testdata/tls/localhost.crt", - keyFile: "tests/testdata/tls/localhost.key", - }); - }, Deno.errors.PermissionDenied); - }, -); - -Deno.test( - { - permissions: { read: true, write: true, net: true }, - }, - function listenTLSEmptyKeyFile() { - const options = { - hostname: "localhost", - port: 0, - certFile: "tests/testdata/tls/localhost.crt", - keyFile: "tests/testdata/tls/localhost.key", - }; - - const testDir = Deno.makeTempDirSync(); - const keyFilename = testDir + "/key.pem"; - Deno.writeFileSync(keyFilename, new Uint8Array([]), { - mode: 0o666, - }); - - assertThrows(() => { - Deno.listenTls({ - ...options, - keyFile: keyFilename, - }); - }, Error); - }, -); - -Deno.test( - { permissions: { read: true, write: true, net: true } }, - function listenTLSEmptyCertFile() { - const options = { - hostname: "localhost", - port: 0, - certFile: "tests/testdata/tls/localhost.crt", - keyFile: "tests/testdata/tls/localhost.key", - }; - - const testDir = Deno.makeTempDirSync(); - const certFilename = testDir + "/cert.crt"; - Deno.writeFileSync(certFilename, new Uint8Array([]), { - mode: 0o666, - }); - - assertThrows(() => { - Deno.listenTls({ - ...options, - certFile: certFilename, - }); - }, Error); - }, -); - Deno.test( { permissions: { net: true } }, async function startTlsWithoutExclusiveAccessToTcpConn() { @@ -186,7 +81,7 @@ Deno.test( // `Deno.startTls` cannot consume the connection. await assertRejects( () => Deno.startTls(clientConn, { hostname }), - Deno.errors.BadResource, + Deno.errors.Busy, ); serverConn.close(); @@ -219,7 +114,6 @@ Deno.test( ); const conn = await Deno.connectTls({ hostname, port, caCerts }); - assert(conn.rid > 0); const w = new BufWriter(conn); const r = new BufReader(conn); const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`; @@ -271,7 +165,6 @@ Deno.test( ); const conn = await Deno.connectTls({ hostname, port, caCerts }); - assert(conn.rid > 0); const w = new BufWriter(conn); const r = new BufReader(conn); const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`; @@ -586,7 +479,9 @@ async function receiveAlotSendNothing(conn: Deno.Conn) { } } catch (e) { throw new Error( - `Got an error (${e.message}) after reading ${nread}/${largeAmount} bytes`, + `Got an error (${ + (e as Error).message + }) after reading ${nread}/${largeAmount} bytes`, { cause: e }, ); } @@ -1145,22 +1040,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTLSBadClientCertPrivateKey(): Promise { - await assertRejects(async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - certChain: "bad data", - privateKey: Deno.readTextFileSync( - "tests/testdata/tls/localhost.key", - ), - }); - }, Deno.errors.InvalidData); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function connectTLSBadCertKey(): Promise { @@ -1177,22 +1056,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTLSBadPrivateKey(): Promise { - await assertRejects(async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - certChain: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - privateKey: "bad data", - }); - }, Deno.errors.InvalidData); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function connectTLSBadKey(): Promise { @@ -1209,22 +1072,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTLSNotPrivateKey(): Promise { - await assertRejects(async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - certChain: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - privateKey: "", - }); - }, Deno.errors.InvalidData); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function connectTLSNotKey(): Promise { @@ -1241,31 +1088,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectWithClientCert() { - // The test_server running on port 4552 responds with 'PASS' if client - // authentication was successful. Try it by running test_server and - // curl --key tests/testdata/tls/localhost.key \ - // --cert tests/testdata/tls/localhost.crt \ - // --cacert tests/testdata/tls/RootCA.crt https://localhost:4552/ - const conn = await Deno.connectTls({ - hostname: "localhost", - port: 4552, - certChain: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - privateKey: Deno.readTextFileSync( - "tests/testdata/tls/localhost.key", - ), - caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")], - }); - const result = decoder.decode(await readAll(conn)); - assertEquals(result, "PASS"); - conn.close(); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function connectWithCert() { @@ -1291,56 +1113,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTlsConflictingCertOptions(): Promise { - await assertRejects( - async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - cert: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - certChain: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - key: Deno.readTextFileSync( - "tests/testdata/tls/localhost.key", - ), - }); - }, - TypeError, - "Cannot specify both `certChain` and `cert`", - ); - }, -); - -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTlsConflictingKeyOptions(): Promise { - await assertRejects( - async () => { - await Deno.connectTls({ - hostname: "deno.land", - port: 443, - cert: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - privateKey: Deno.readTextFileSync( - "tests/testdata/tls/localhost.crt", - ), - key: Deno.readTextFileSync( - "tests/testdata/tls/localhost.key", - ), - }); - }, - TypeError, - "Cannot specify both `key` and `privateKey` for `Deno.connectTls`.", - ); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function connectTLSCaCerts() { @@ -1355,20 +1127,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, net: true } }, - async function connectTLSCertFile() { - const conn = await Deno.connectTls({ - hostname: "localhost", - port: 4557, - certFile: "tests/testdata/tls/RootCA.pem", - }); - const result = decoder.decode(await readAll(conn)); - assertEquals(result, "PASS"); - conn.close(); - }, -); - Deno.test( { permissions: { read: true, net: true } }, async function startTLSCaCerts() { @@ -1395,7 +1153,7 @@ Deno.test( const connectPromise = Deno.connectTls({ hostname, port, - certFile: "tests/testdata/tls/RootCA.crt", + caCerts: [await Deno.readTextFile("tests/testdata/tls/RootCA.crt")], }); const [conn1, conn2] = await Promise.all([acceptPromise, connectPromise]); listener.close(); @@ -1613,8 +1371,8 @@ Deno.test( Deno.listenTls({ hostname: "localhost", port: 0, - certFile: "tests/testdata/tls/invalid.crt", - keyFile: "tests/testdata/tls/localhost.key", + cert: Deno.readTextFileSync("tests/testdata/tls/invalid.crt"), + key: Deno.readTextFileSync("tests/testdata/tls/localhost.key"), }); }, Deno.errors.InvalidData); }, @@ -1627,8 +1385,8 @@ Deno.test( Deno.listenTls({ hostname: "localhost", port: 0, - certFile: "tests/testdata/tls/localhost.crt", - keyFile: "tests/testdata/tls/invalid.key", + cert: Deno.readTextFileSync("tests/testdata/tls/localhost.crt"), + key: Deno.readTextFileSync("tests/testdata/tls/invalid.key"), }); }, Deno.errors.InvalidData); }, @@ -1640,8 +1398,8 @@ Deno.test( const listener = Deno.listenTls({ hostname: "localhost", port: 0, - certFile: "tests/testdata/tls/localhost_ecc.crt", - keyFile: "tests/testdata/tls/localhost_ecc.key", + cert: Deno.readTextFileSync("tests/testdata/tls/localhost_ecc.crt"), + key: Deno.readTextFileSync("tests/testdata/tls/localhost_ecc.key"), }); listener.close(); }, diff --git a/tests/unit/truncate_test.ts b/tests/unit/truncate_test.ts index 95b76052d3..cebd6e8ee1 100644 --- a/tests/unit/truncate_test.ts +++ b/tests/unit/truncate_test.ts @@ -76,13 +76,13 @@ Deno.test( Deno.test({ permissions: { write: false } }, function truncateSyncPerm() { assertThrows(() => { Deno.truncateSync("/test_truncateSyncPermission.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test({ permissions: { write: false } }, async function truncatePerm() { await assertRejects(async () => { await Deno.truncate("/test_truncatePermission.txt"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( diff --git a/tests/unit/tty_test.ts b/tests/unit/tty_test.ts index 0c1140804e..1d29a0b706 100644 --- a/tests/unit/tty_test.ts +++ b/tests/unit/tty_test.ts @@ -15,17 +15,11 @@ Deno.test(function consoleSize() { assert(typeof result.rows !== "undefined"); }); -Deno.test({ permissions: { read: true } }, function isatty() { - // CI not under TTY, so cannot test stdin/stdout/stderr. - const f = Deno.openSync("tests/testdata/assets/hello.txt"); - assert(!Deno.isatty(f.rid)); - f.close(); -}); - Deno.test(function isattyError() { let caught = false; try { // Absurdly large rid. + // @ts-ignore `Deno.isatty()` was soft-removed in Deno 2. Deno.isatty(0x7fffffff); } catch (e) { caught = true; diff --git a/tests/unit/url_search_params_test.ts b/tests/unit/url_search_params_test.ts index c547ef9385..d682c291a9 100644 --- a/tests/unit/url_search_params_test.ts +++ b/tests/unit/url_search_params_test.ts @@ -330,7 +330,7 @@ Deno.test( function urlSearchParamsOverridingAppendNotChangeConstructorAndSet() { let overriddenAppendCalled = 0; class CustomSearchParams extends URLSearchParams { - append(name: string, value: string) { + override append(name: string, value: string) { ++overriddenAppendCalled; super.append(name, value); } @@ -345,7 +345,7 @@ Deno.test( Deno.test(function urlSearchParamsOverridingEntriesNotChangeForEach() { class CustomSearchParams extends URLSearchParams { - *entries(): IterableIterator<[string, string]> { + override *entries(): IterableIterator<[string, string]> { yield* []; } } diff --git a/tests/unit/utime_test.ts b/tests/unit/utime_test.ts index 49bc966230..7a1fee74eb 100644 --- a/tests/unit/utime_test.ts +++ b/tests/unit/utime_test.ts @@ -1,7 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -// deno-lint-ignore-file no-deprecated-deno-api - import { assertEquals, assertRejects, @@ -9,27 +7,6 @@ import { pathToAbsoluteFileUrl, } from "./test_util.ts"; -Deno.test( - { permissions: { read: true, write: true } }, - async function futimeSyncSuccess() { - const testDir = await Deno.makeTempDir(); - const filename = testDir + "/file.txt"; - using file = await Deno.open(filename, { - create: true, - write: true, - }); - - const atime = 1000; - const mtime = 50000; - await Deno.futime(file.rid, atime, mtime); - await file.syncData(); - - const fileInfo = Deno.statSync(filename); - assertEquals(fileInfo.atime, new Date(atime * 1000)); - assertEquals(fileInfo.mtime, new Date(mtime * 1000)); - }, -); - Deno.test( { permissions: { read: true, write: true } }, async function fsFileUtimeSyncSuccess() { @@ -51,27 +28,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { read: true, write: true } }, - function futimeSyncSuccess() { - const testDir = Deno.makeTempDirSync(); - const filename = testDir + "/file.txt"; - using file = Deno.openSync(filename, { - create: true, - write: true, - }); - - const atime = 1000; - const mtime = 50000; - Deno.futimeSync(file.rid, atime, mtime); - file.syncDataSync(); - - const fileInfo = Deno.statSync(filename); - assertEquals(fileInfo.atime, new Date(atime * 1000)); - assertEquals(fileInfo.mtime, new Date(mtime * 1000)); - }, -); - Deno.test( { permissions: { read: true, write: true } }, function futimeSyncSuccess() { @@ -220,7 +176,7 @@ Deno.test( assertThrows(() => { Deno.utimeSync("/some_dir", atime, mtime); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -335,6 +291,6 @@ Deno.test( await assertRejects(async () => { await Deno.utime("/some_dir", atime, mtime); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/version_test.ts b/tests/unit/version_test.ts index 96319c630f..307295ad87 100644 --- a/tests/unit/version_test.ts +++ b/tests/unit/version_test.ts @@ -6,5 +6,5 @@ Deno.test(function version() { const pattern = /^\d+\.\d+\.\d+/; assert(pattern.test(Deno.version.deno)); assert(pattern.test(Deno.version.v8)); - assertEquals(Deno.version.typescript, "5.5.2"); + assertEquals(Deno.version.typescript, "5.6.2"); }); diff --git a/tests/unit/wasm_test.ts b/tests/unit/wasm_test.ts index fab9c9308f..e0db41ed0e 100644 --- a/tests/unit/wasm_test.ts +++ b/tests/unit/wasm_test.ts @@ -53,7 +53,7 @@ Deno.test( await assertRejects( () => wasmPromise, TypeError, - "Invalid WebAssembly content type.", + "Invalid WebAssembly content type", ); }, ); diff --git a/tests/unit/webcrypto_test.ts b/tests/unit/webcrypto_test.ts index 58f59edc69..09552a0587 100644 --- a/tests/unit/webcrypto_test.ts +++ b/tests/unit/webcrypto_test.ts @@ -9,7 +9,7 @@ import { // https://github.com/denoland/deno/issues/11664 Deno.test(async function testImportArrayBufferKey() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); // deno-fmt-ignore @@ -29,7 +29,7 @@ Deno.test(async function testImportArrayBufferKey() { }); Deno.test(async function testSignVerify() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); for (const algorithm of ["RSA-PSS", "RSASSA-PKCS1-v1_5"]) { for ( @@ -101,7 +101,7 @@ const hashPlainTextVector = [ ]; Deno.test(async function testEncryptDecrypt() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); for ( const { hash, plainText } of hashPlainTextVector @@ -154,7 +154,7 @@ Deno.test(async function testEncryptDecrypt() { }); Deno.test(async function testGenerateRSAKey() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); const keyPair = await subtle.generateKey( @@ -175,7 +175,7 @@ Deno.test(async function testGenerateRSAKey() { }); Deno.test(async function testGenerateHMACKey() { - const key = await window.crypto.subtle.generateKey( + const key = await globalThis.crypto.subtle.generateKey( { name: "HMAC", hash: "SHA-512", @@ -190,7 +190,7 @@ Deno.test(async function testGenerateHMACKey() { }); Deno.test(async function testECDSASignVerify() { - const key = await window.crypto.subtle.generateKey( + const key = await globalThis.crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-384", @@ -201,7 +201,7 @@ Deno.test(async function testECDSASignVerify() { const encoder = new TextEncoder(); const encoded = encoder.encode("Hello, World!"); - const signature = await window.crypto.subtle.sign( + const signature = await globalThis.crypto.subtle.sign( { name: "ECDSA", hash: "SHA-384" }, key.privateKey, encoded, @@ -210,7 +210,7 @@ Deno.test(async function testECDSASignVerify() { assert(signature); assert(signature instanceof ArrayBuffer); - const verified = await window.crypto.subtle.verify( + const verified = await globalThis.crypto.subtle.verify( { hash: { name: "SHA-384" }, name: "ECDSA" }, key.publicKey, signature, @@ -221,7 +221,7 @@ Deno.test(async function testECDSASignVerify() { // Tests the "bad paths" as a temporary replacement for sign_verify/ecdsa WPT. Deno.test(async function testECDSASignVerifyFail() { - const key = await window.crypto.subtle.generateKey( + const key = await globalThis.crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-384", @@ -233,7 +233,7 @@ Deno.test(async function testECDSASignVerifyFail() { const encoded = new Uint8Array([1]); // Signing with a public key (InvalidAccessError) await assertRejects(async () => { - await window.crypto.subtle.sign( + await globalThis.crypto.subtle.sign( { name: "ECDSA", hash: "SHA-384" }, key.publicKey, new Uint8Array([1]), @@ -242,7 +242,7 @@ Deno.test(async function testECDSASignVerifyFail() { }, DOMException); // Do a valid sign for later verifying. - const signature = await window.crypto.subtle.sign( + const signature = await globalThis.crypto.subtle.sign( { name: "ECDSA", hash: "SHA-384" }, key.privateKey, encoded, @@ -250,7 +250,7 @@ Deno.test(async function testECDSASignVerifyFail() { // Verifying with a private key (InvalidAccessError) await assertRejects(async () => { - await window.crypto.subtle.verify( + await globalThis.crypto.subtle.verify( { hash: { name: "SHA-384" }, name: "ECDSA" }, key.privateKey, signature, @@ -262,7 +262,7 @@ Deno.test(async function testECDSASignVerifyFail() { // https://github.com/denoland/deno/issues/11313 Deno.test(async function testSignRSASSAKey() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); const keyPair = await subtle.generateKey( @@ -284,7 +284,7 @@ Deno.test(async function testSignRSASSAKey() { const encoder = new TextEncoder(); const encoded = encoder.encode("Hello, World!"); - const signature = await window.crypto.subtle.sign( + const signature = await globalThis.crypto.subtle.sign( { name: "RSASSA-PKCS1-v1_5" }, keyPair.privateKey, encoded, @@ -1056,7 +1056,7 @@ const jwtRSAKeys = { }; Deno.test(async function testImportRsaJwk() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); for (const [_key, jwkData] of Object.entries(jwtRSAKeys)) { @@ -1496,7 +1496,7 @@ const ecTestKeys = [ ]; Deno.test(async function testImportEcSpkiPkcs8() { - const subtle = window.crypto.subtle; + const subtle = globalThis.crypto.subtle; assert(subtle); for ( @@ -2045,3 +2045,43 @@ Deno.test(async function p521Generate() { assert(key.privateKey instanceof CryptoKey); assert(key.publicKey instanceof CryptoKey); }); + +Deno.test(async function x25519SharedSecret() { + const alicesKeyPair = await crypto.subtle.generateKey( + { + name: "X25519", + }, + false, + ["deriveBits"], + ) as CryptoKeyPair; + + const bobsKeyPair = await crypto.subtle.generateKey( + { + name: "X25519", + }, + false, + ["deriveBits"], + ) as CryptoKeyPair; + + const sharedSecret1 = await crypto.subtle.deriveBits( + { + name: "X25519", + public: bobsKeyPair.publicKey, + }, + alicesKeyPair.privateKey, + 128, + ); + + const sharedSecret2 = await crypto.subtle.deriveBits( + { + name: "X25519", + public: alicesKeyPair.publicKey, + }, + bobsKeyPair.privateKey, + 128, + ); + + assertEquals(sharedSecret1.byteLength, sharedSecret2.byteLength); + assertEquals(sharedSecret1.byteLength, 16); + assertEquals(new Uint8Array(sharedSecret1), new Uint8Array(sharedSecret2)); +}); diff --git a/tests/unit/webgpu_test.ts b/tests/unit/webgpu_test.ts index 43b24e41aa..6c91abe4ad 100644 --- a/tests/unit/webgpu_test.ts +++ b/tests/unit/webgpu_test.ts @@ -10,15 +10,15 @@ try { } // Skip these tests on linux CI, because the vulkan emulator is not good enough -// yet, and skip on macOS CI because these do not have virtual GPUs. -const isLinuxOrMacCI = - (Deno.build.os === "linux" || Deno.build.os === "darwin") && isCI; +// yet, and skip on macOS x86 CI because these do not have virtual GPUs. +const isCIWithoutGPU = (Deno.build.os === "linux" || + (Deno.build.os === "darwin" && Deno.build.arch === "x86_64")) && isCI; // Skip these tests in WSL because it doesn't have good GPU support. const isWsl = await checkIsWsl(); Deno.test({ permissions: { read: true, env: true }, - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function webgpuComputePass() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -104,7 +104,7 @@ Deno.test({ Deno.test({ permissions: { read: true, env: true }, - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function webgpuHelloTriangle() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -216,7 +216,7 @@ Deno.test({ }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function webgpuAdapterHasFeatures() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -226,7 +226,7 @@ Deno.test({ }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function webgpuNullWindowSurfaceThrows() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -236,20 +236,39 @@ Deno.test({ assertThrows( () => { - new Deno.UnsafeWindowSurface("cocoa", null, null); + new Deno.UnsafeWindowSurface({ + system: "cocoa", + windowHandle: null, + displayHandle: null, + width: 0, + height: 0, + }); }, ); device.destroy(); }); +Deno.test(function webgpuWindowSurfaceNoWidthHeight() { + assertThrows( + () => { + // @ts-expect-error width and height are required + new Deno.UnsafeWindowSurface({ + system: "x11", + windowHandle: null, + displayHandle: null, + }); + }, + ); +}); + Deno.test(function getPreferredCanvasFormat() { const preferredFormat = navigator.gpu.getPreferredCanvasFormat(); assert(preferredFormat === "bgra8unorm" || preferredFormat === "rgba8unorm"); }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function validateGPUColor() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -271,7 +290,7 @@ Deno.test({ const invalidSize = [0, 0, 0]; const msgIncludes = - "A sequence of number used as a GPUColor must have exactly 4 elements."; + "A sequence of number used as a GPUColor must have exactly 4 elements, received 3 elements"; // validate the argument of descriptor.colorAttachments[@@iterator].clearValue property's length of GPUCommandEncoder.beginRenderPass when its a sequence // https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-beginrenderpass @@ -312,7 +331,7 @@ Deno.test({ }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function validateGPUExtent3D() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -337,7 +356,7 @@ Deno.test({ const overSize = [256, 256, 1, 1]; const msgIncludes = - "A sequence of number used as a GPUExtent3D must have between 1 and 3 elements."; + "A sequence of number used as a GPUExtent3D must have between 1 and 3 elements"; // validate the argument of descriptor.size property's length of GPUDevice.createTexture when its a sequence // https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpudevice-createtexture @@ -412,7 +431,7 @@ Deno.test({ }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function validateGPUOrigin3D() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); @@ -437,7 +456,7 @@ Deno.test({ const overSize = [256, 256, 1, 1]; const msgIncludes = - "A sequence of number used as a GPUOrigin3D must have at most 3 elements."; + "A sequence of number used as a GPUOrigin3D must have at most 3 elements, received 4 elements"; // validate the argument of destination.origin property's length of GPUCommandEncoder.copyBufferToTexture when its a sequence // https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copybuffertotexture @@ -505,7 +524,7 @@ Deno.test({ }); Deno.test({ - ignore: isWsl || isLinuxOrMacCI, + ignore: isWsl || isCIWithoutGPU, }, async function beginRenderPassWithoutDepthClearValue() { const adapter = await navigator.gpu.requestAdapter(); assert(adapter); diff --git a/tests/unit/websocket_test.ts b/tests/unit/websocket_test.ts index 362957b2df..7db876b177 100644 --- a/tests/unit/websocket_test.ts +++ b/tests/unit/websocket_test.ts @@ -7,7 +7,7 @@ const serveUrl = `ws://localhost:${servePort}/`; Deno.test({ permissions: "none" }, function websocketPermissionless() { assertThrows( () => new WebSocket("ws://localhost"), - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, ); }); diff --git a/tests/unit/webstorage_test.ts b/tests/unit/webstorage_test.ts index 9dc560af1b..aa832b1c4b 100644 --- a/tests/unit/webstorage_test.ts +++ b/tests/unit/webstorage_test.ts @@ -50,3 +50,8 @@ Deno.test(function webstorageProxy() { assertEquals(localStorage[symbol as any], "bar"); assertEquals(symbol in localStorage, true); }); + +Deno.test(function webstorageGetOwnPropertyDescriptorSymbol() { + localStorage.clear(); + Object.getOwnPropertyDescriptor(localStorage, Symbol("foo")); +}); diff --git a/tests/unit/worker_test.ts b/tests/unit/worker_test.ts index 526618d548..42c257282c 100644 --- a/tests/unit/worker_test.ts +++ b/tests/unit/worker_test.ts @@ -1,8 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + // Requires to be run with `--allow-net` flag import { assert, assertEquals, assertMatch, assertThrows } from "@std/assert"; +import { toFileUrl } from "@std/path/to-file-url"; function resolveWorker(worker: string): string { return import.meta.resolve(`../testdata/workers/${worker}`); @@ -440,7 +443,31 @@ Deno.test("Worker limit children permissions", async function () { worker.terminate(); }); +function setupReadCheckGranularWorkerTest() { + const tempDir = Deno.realPathSync(Deno.makeTempDirSync()); + const initialPath = Deno.env.get("PATH")!; + const initialCwd = Deno.cwd(); + Deno.chdir(tempDir); + const envSep = Deno.build.os === "windows" ? ";" : ":"; + Deno.env.set("PATH", initialPath + envSep + tempDir); + + // create executables that will be resolved when doing `which` + const ext = Deno.build.os === "windows" ? ".exe" : ""; + Deno.copyFileSync(Deno.execPath(), tempDir + "/bar" + ext); + + return { + tempDir, + runFooFilePath: tempDir + "/foo" + ext, + [Symbol.dispose]() { + Deno.removeSync(tempDir, { recursive: true }); + Deno.env.set("PATH", initialPath); + Deno.chdir(initialCwd); + }, + }; +} + Deno.test("Worker limit children permissions granularly", async function () { + const ctx = setupReadCheckGranularWorkerTest(); const workerUrl = resolveWorker("read_check_granular_worker.js"); const worker = new Worker( workerUrl, @@ -449,11 +476,15 @@ Deno.test("Worker limit children permissions granularly", async function () { deno: { permissions: { env: ["foo"], - hrtime: true, net: ["foo", "bar:8000"], ffi: [new URL("foo", workerUrl), "bar"], - read: [new URL("foo", workerUrl), "bar"], - run: [new URL("foo", workerUrl), "bar", "./baz"], + read: [new URL("foo", workerUrl), "bar", ctx.tempDir], + run: [ + toFileUrl(ctx.runFooFilePath), + "bar", + "./baz", + "unresolved-exec", + ], write: [new URL("foo", workerUrl), "bar"], }, }, @@ -466,7 +497,6 @@ Deno.test("Worker limit children permissions granularly", async function () { envGlobal: "prompt", envFoo: "granted", envAbsent: "prompt", - hrtime: "granted", netGlobal: "prompt", netFoo: "granted", netFoo8000: "granted", @@ -482,8 +512,10 @@ Deno.test("Worker limit children permissions granularly", async function () { readAbsent: "prompt", runGlobal: "prompt", runFoo: "granted", + runFooPath: "granted", runBar: "granted", runBaz: "granted", + runUnresolved: "prompt", // unresolved binaries remain as "prompt" runAbsent: "prompt", writeGlobal: "prompt", writeFoo: "granted", @@ -494,6 +526,7 @@ Deno.test("Worker limit children permissions granularly", async function () { }); Deno.test("Nested worker limit children permissions", async function () { + const _cleanup = setupReadCheckGranularWorkerTest(); /** This worker has permissions but doesn't grant them to its children */ const worker = new Worker( resolveWorker("parent_read_check_worker.js"), @@ -506,7 +539,6 @@ Deno.test("Nested worker limit children permissions", async function () { envGlobal: "prompt", envFoo: "prompt", envAbsent: "prompt", - hrtime: "prompt", netGlobal: "prompt", netFoo: "prompt", netFoo8000: "prompt", @@ -522,8 +554,10 @@ Deno.test("Nested worker limit children permissions", async function () { readAbsent: "prompt", runGlobal: "prompt", runFoo: "prompt", + runFooPath: "prompt", runBar: "prompt", runBaz: "prompt", + runUnresolved: "prompt", runAbsent: "prompt", writeGlobal: "prompt", writeFoo: "prompt", @@ -547,7 +581,7 @@ Deno.test({ ); worker.terminate(); }, - Deno.errors.PermissionDenied, + Deno.errors.NotCapable, "Can't escalate parent thread permissions", ); }, @@ -584,7 +618,6 @@ Deno.test("Worker permissions are not inherited with empty permission object", a worker.postMessage(null); assertEquals(await promise, { env: "prompt", - hrtime: "prompt", net: "prompt", ffi: "prompt", read: "prompt", @@ -609,7 +642,6 @@ Deno.test("Worker permissions are not inherited with single specified permission worker.postMessage(null); assertEquals(await promise, { env: "prompt", - hrtime: "prompt", net: "granted", ffi: "prompt", read: "prompt", diff --git a/tests/unit/write_file_test.ts b/tests/unit/write_file_test.ts index 29780446cf..15e462cca9 100644 --- a/tests/unit/write_file_test.ts +++ b/tests/unit/write_file_test.ts @@ -57,7 +57,7 @@ Deno.test({ permissions: { write: false } }, function writeFileSyncPerm() { // The following should fail due to no write permission assertThrows(() => { Deno.writeFileSync(filename, data); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -190,7 +190,7 @@ Deno.test( // The following should fail due to no write permission await assertRejects(async () => { await Deno.writeFile(filename, data); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit/write_text_file_test.ts b/tests/unit/write_text_file_test.ts index a58d919975..9e1b75326b 100644 --- a/tests/unit/write_text_file_test.ts +++ b/tests/unit/write_text_file_test.ts @@ -45,7 +45,7 @@ Deno.test({ permissions: { write: false } }, function writeTextFileSyncPerm() { // The following should fail due to no write permission assertThrows(() => { Deno.writeTextFileSync(filename, "Hello"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }); Deno.test( @@ -144,7 +144,7 @@ Deno.test( // The following should fail due to no write permission await assertRejects(async () => { await Deno.writeTextFile(filename, "Hello"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); diff --git a/tests/unit_node/_fs/_fs_appendFile_test.ts b/tests/unit_node/_fs/_fs_appendFile_test.ts index f50eba8568..5ee8eabed4 100644 --- a/tests/unit_node/_fs/_fs_appendFile_test.ts +++ b/tests/unit_node/_fs/_fs_appendFile_test.ts @@ -64,6 +64,9 @@ Deno.test({ Deno.test({ name: "Async: Data is written to passed in rid", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = await Deno.makeTempFile(); using file = await Deno.open(tempFile, { @@ -72,6 +75,7 @@ Deno.test({ read: true, }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used appendFile(file.rid, "hello world", (err) => { if (err) reject(); else resolve(); @@ -153,6 +157,9 @@ Deno.test({ Deno.test({ name: "Sync: Data is written to passed in rid", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const tempFile: string = Deno.makeTempFileSync(); using file = Deno.openSync(tempFile, { @@ -160,6 +167,7 @@ Deno.test({ write: true, read: true, }); + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used appendFileSync(file.rid, "hello world"); const data = Deno.readFileSync(tempFile); assertEquals(decoder.decode(data), "hello world"); diff --git a/tests/unit_node/_fs/_fs_close_test.ts b/tests/unit_node/_fs/_fs_close_test.ts index e417111262..8880bc0461 100644 --- a/tests/unit_node/_fs/_fs_close_test.ts +++ b/tests/unit_node/_fs/_fs_close_test.ts @@ -5,11 +5,15 @@ import { close, closeSync } from "node:fs"; Deno.test({ name: "ASYNC: File is closed", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = await Deno.makeTempFile(); const file: Deno.FsFile = await Deno.open(tempFile); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used close(file.rid, (err) => { if (err !== null) reject(); else resolve(); @@ -33,12 +37,16 @@ Deno.test({ Deno.test({ name: "close callback should be asynchronous", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = Deno.makeTempFileSync(); const file: Deno.FsFile = Deno.openSync(tempFile); let foo: string; const promise = new Promise((resolve) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used close(file.rid, () => { assert(foo === "bar"); resolve(); @@ -53,10 +61,14 @@ Deno.test({ Deno.test({ name: "SYNC: File is closed", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const tempFile: string = Deno.makeTempFileSync(); const file: Deno.FsFile = Deno.openSync(tempFile); + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used closeSync(file.rid); Deno.removeSync(tempFile); }, @@ -69,7 +81,12 @@ Deno.test({ }, }); -Deno.test("[std/node/fs] close callback isn't called twice if error is thrown", async () => { +Deno.test({ + name: "[std/node/fs] close callback isn't called twice if error is thrown", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, +}, async () => { const tempFile = await Deno.makeTempFile(); const importUrl = new URL("node:fs", import.meta.url); await assertCallbackErrorUncaught({ diff --git a/tests/unit_node/_fs/_fs_fdatasync_test.ts b/tests/unit_node/_fs/_fs_fdatasync_test.ts index 6e0143d64e..40ca2969f9 100644 --- a/tests/unit_node/_fs/_fs_fdatasync_test.ts +++ b/tests/unit_node/_fs/_fs_fdatasync_test.ts @@ -5,6 +5,9 @@ import { fdatasync, fdatasyncSync } from "node:fs"; Deno.test({ name: "ASYNC: flush any pending data operations of the given file stream to disk", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = await Deno.makeTempFile(); using file = await Deno.open(filePath, { @@ -16,6 +19,7 @@ Deno.test({ await file.write(data); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fdatasync(file.rid, (err: Error | null) => { if (err !== null) reject(); else resolve(); @@ -38,6 +42,9 @@ Deno.test({ Deno.test({ name: "SYNC: flush any pending data operations of the given file stream to disk.", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); using file = Deno.openSync(filePath, { @@ -49,6 +56,7 @@ Deno.test({ file.writeSync(data); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fdatasyncSync(file.rid); assertEquals(Deno.readFileSync(filePath), data); } finally { diff --git a/tests/unit_node/_fs/_fs_fstat_test.ts b/tests/unit_node/_fs/_fs_fstat_test.ts index 46ab508cf8..afcac836f6 100644 --- a/tests/unit_node/_fs/_fs_fstat_test.ts +++ b/tests/unit_node/_fs/_fs_fstat_test.ts @@ -7,11 +7,15 @@ import type { BigIntStats, Stats } from "node:fs"; Deno.test({ name: "ASYNC: get a file Stats", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = await Deno.makeTempFile(); using file = await Deno.open(filePath); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fstat(file.rid, (err: Error | null, stat: Stats) => { if (err) reject(err); resolve(stat); @@ -31,12 +35,16 @@ Deno.test({ Deno.test({ name: "ASYNC: get a file BigInt Stats", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = await Deno.makeTempFile(); using file = await Deno.open(filePath); await new Promise((resolve, reject) => { fstat( + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used file.rid, { bigint: true }, (err: Error | null, stat: BigIntStats) => { @@ -57,11 +65,15 @@ Deno.test({ Deno.test({ name: "SYNC: get a file Stats", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); using file = Deno.openSync(filePath); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used assertStats(fstatSync(file.rid), file.statSync()); } finally { Deno.removeSync(filePath); @@ -71,15 +83,20 @@ Deno.test({ Deno.test({ name: "SYNC: get a file BigInt Stats", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); using file = Deno.openSync(filePath); try { // HEAD + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used assertStatsBigInt(fstatSync(file.rid, { bigint: true }), file.statSync()); // assertStatsBigInt( + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fstatSync(file.rid, { bigint: true }), file.statSync(), ); diff --git a/tests/unit_node/_fs/_fs_fsync_test.ts b/tests/unit_node/_fs/_fs_fsync_test.ts index 3a162f97c7..3c1509410e 100644 --- a/tests/unit_node/_fs/_fs_fsync_test.ts +++ b/tests/unit_node/_fs/_fs_fsync_test.ts @@ -4,6 +4,9 @@ import { fsync, fsyncSync } from "node:fs"; Deno.test({ name: "ASYNC: flush any pending data of the given file stream to disk", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = await Deno.makeTempFile(); using file = await Deno.open(filePath, { @@ -15,6 +18,7 @@ Deno.test({ await file.truncate(size); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fsync(file.rid, (err: Error | null) => { if (err !== null) reject(); else resolve(); @@ -36,6 +40,9 @@ Deno.test({ Deno.test({ name: "SYNC: flush any pending data the given file stream to disk", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); using file = Deno.openSync(filePath, { @@ -47,6 +54,7 @@ Deno.test({ file.truncateSync(size); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used fsyncSync(file.rid); assertEquals(Deno.statSync(filePath).size, size); } finally { diff --git a/tests/unit_node/_fs/_fs_ftruncate_test.ts b/tests/unit_node/_fs/_fs_ftruncate_test.ts index 78cbe630a8..974f8f168e 100644 --- a/tests/unit_node/_fs/_fs_ftruncate_test.ts +++ b/tests/unit_node/_fs/_fs_ftruncate_test.ts @@ -18,6 +18,9 @@ Deno.test({ Deno.test({ name: "ASYNC: truncate entire file contents", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = Deno.makeTempFileSync(); await Deno.writeTextFile(filePath, "hello world"); @@ -28,6 +31,7 @@ Deno.test({ }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used ftruncate(file.rid, (err: Error | null) => { if (err !== null) reject(); else resolve(); @@ -50,6 +54,9 @@ Deno.test({ Deno.test({ name: "ASYNC: truncate file to a size of precisely len bytes", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = Deno.makeTempFileSync(); await Deno.writeTextFile(filePath, "hello world"); @@ -60,6 +67,7 @@ Deno.test({ }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used ftruncate(file.rid, 3, (err: Error | null) => { if (err !== null) reject(); else resolve(); @@ -82,6 +90,9 @@ Deno.test({ Deno.test({ name: "SYNC: truncate entire file contents", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); Deno.writeFileSync(filePath, new TextEncoder().encode("hello world")); @@ -92,6 +103,7 @@ Deno.test({ }); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used ftruncateSync(file.rid); const fileInfo: Deno.FileInfo = Deno.lstatSync(filePath); assertEquals(fileInfo.size, 0); @@ -103,6 +115,9 @@ Deno.test({ Deno.test({ name: "SYNC: truncate file to a size of precisely len bytes", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); Deno.writeFileSync(filePath, new TextEncoder().encode("hello world")); @@ -113,6 +128,7 @@ Deno.test({ }); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used ftruncateSync(file.rid, 3); const fileInfo: Deno.FileInfo = Deno.lstatSync(filePath); assertEquals(fileInfo.size, 3); diff --git a/tests/unit_node/_fs/_fs_futimes_test.ts b/tests/unit_node/_fs/_fs_futimes_test.ts index 48f949b1a8..9b0c64efd6 100644 --- a/tests/unit_node/_fs/_fs_futimes_test.ts +++ b/tests/unit_node/_fs/_fs_futimes_test.ts @@ -7,11 +7,15 @@ const randomDate = new Date(Date.now() + 1000); Deno.test({ name: "ASYNC: change the file system timestamps of the object referenced by path", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const filePath = Deno.makeTempFileSync(); using file = await Deno.open(filePath, { create: true, write: true }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used futimes(file.rid, randomDate, randomDate, (err: Error | null) => { if (err !== null) reject(); else resolve(); @@ -62,11 +66,15 @@ Deno.test({ Deno.test({ name: "SYNC: change the file system timestamps of the object referenced by path", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const filePath = Deno.makeTempFileSync(); using file = Deno.openSync(filePath, { create: true, write: true }); try { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used futimesSync(file.rid, randomDate, randomDate); const fileInfo: Deno.FileInfo = Deno.lstatSync(filePath); diff --git a/tests/unit_node/_fs/_fs_stat_test.ts b/tests/unit_node/_fs/_fs_stat_test.ts index 09d78f9db3..02c620e2dc 100644 --- a/tests/unit_node/_fs/_fs_stat_test.ts +++ b/tests/unit_node/_fs/_fs_stat_test.ts @@ -133,7 +133,9 @@ Deno.test("[std/node/fs] stat callback isn't called twice if error is thrown", a Deno.test({ name: "[std/node/fs] stat default methods", fn() { - const stats = new Stats(); + // stats ctor is private + // deno-lint-ignore no-explicit-any + const stats = new (Stats as any)(); assertEquals(stats.isFile(), false); assertEquals(stats.isDirectory(), false); assertEquals(stats.isBlockDevice(), false); diff --git a/tests/unit_node/_fs/_fs_writeFile_test.ts b/tests/unit_node/_fs/_fs_writeFile_test.ts index 53af660cf3..2733a2df0b 100644 --- a/tests/unit_node/_fs/_fs_writeFile_test.ts +++ b/tests/unit_node/_fs/_fs_writeFile_test.ts @@ -104,7 +104,12 @@ Deno.test( ); Deno.test( - "Data is written to correct rid", + { + name: "Data is written to correct rid", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, + }, async function testCorrectWriteUsingRid() { const tempFile: string = await Deno.makeTempFile(); using file = await Deno.open(tempFile, { @@ -114,6 +119,7 @@ Deno.test( }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used writeFile(file.rid, "hello world", (err) => { if (err) return reject(err); resolve(); @@ -191,7 +197,12 @@ Deno.test("Path can be an URL", async function testCorrectWriteUsingURL() { assertEquals(decoder.decode(data), "hello world"); }); -Deno.test("Mode is correctly set", async function testCorrectFileMode() { +Deno.test({ + name: "Mode is correctly set", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, +}, async function testCorrectFileMode() { if (Deno.build.os === "windows") return; const filename = "_fs_writeFile_test_file.txt"; @@ -207,7 +218,12 @@ Deno.test("Mode is correctly set", async function testCorrectFileMode() { }); Deno.test( - "Mode is not set when rid is passed", + { + name: "Mode is not set when rid is passed", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, + }, async function testCorrectFileModeRid() { if (Deno.build.os === "windows") return; @@ -219,6 +235,7 @@ Deno.test( }); await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used writeFile(file.rid, "hello world", { mode: 0o777 }, (err) => { if (err) return reject(err); resolve(); @@ -259,7 +276,12 @@ Deno.test( ); Deno.test( - "Data is written synchronously to correct rid", + { + name: "Data is written synchronously to correct rid", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, + }, function testCorrectWriteSyncUsingRid() { const tempFile: string = Deno.makeTempFileSync(); using file = Deno.openSync(tempFile, { @@ -268,6 +290,7 @@ Deno.test( read: true, }); + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used writeFileSync(file.rid, "hello world"); const data = Deno.readFileSync(tempFile); diff --git a/tests/unit_node/_fs/_fs_write_test.ts b/tests/unit_node/_fs/_fs_write_test.ts index a140548e12..400fce73aa 100644 --- a/tests/unit_node/_fs/_fs_write_test.ts +++ b/tests/unit_node/_fs/_fs_write_test.ts @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { write, writeSync } from "node:fs"; import { assertEquals } from "@std/assert"; import { Buffer } from "node:buffer"; @@ -7,6 +10,9 @@ const decoder = new TextDecoder("utf-8"); Deno.test({ name: "Data is written to the file with the correct length", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = await Deno.makeTempFile(); using file = await Deno.open(tempFile, { @@ -16,6 +22,7 @@ Deno.test({ }); const buffer = Buffer.from("hello world"); const bytesWrite = await new Promise((resolve, reject) => { + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used write(file.rid, buffer, 0, 5, (err: unknown, nwritten: number) => { if (err) return reject(err); resolve(nwritten); @@ -32,6 +39,9 @@ Deno.test({ Deno.test({ name: "Data is written synchronously to the file with the correct length", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, fn() { const tempFile: string = Deno.makeTempFileSync(); using file = Deno.openSync(tempFile, { @@ -40,6 +50,7 @@ Deno.test({ read: true, }); const buffer = Buffer.from("hello world"); + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used const bytesWrite = writeSync(file.rid, buffer, 0, 5); const data = Deno.readFileSync(tempFile); @@ -52,6 +63,9 @@ Deno.test({ Deno.test({ name: "Data is padded if position > length", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = Deno.makeTempFileSync(); @@ -63,6 +77,7 @@ Deno.test({ const str = "hello world"; const buffer = Buffer.from(str); + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used const bytesWritten = writeSync(file.rid, buffer, 0, str.length, 4); const data = Deno.readFileSync(tempFile); @@ -76,6 +91,9 @@ Deno.test({ Deno.test({ name: "write with offset TypedArray buffers", + // TODO(bartlomieju): this test is broken in Deno 2, because `file.rid` is undefined. + // The fs APIs should be rewritten to use actual FDs, not RIDs + ignore: true, async fn() { const tempFile: string = Deno.makeTempFileSync(); using file = Deno.openSync(tempFile, { @@ -107,6 +125,7 @@ Deno.test({ for (let i = 0; i < bytes.length; i++) { buffer[offset + i] = i; } + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used let nWritten = writeSync(file.rid, buffer, offset, bytes.length, 0); let data = Deno.readFileSync(tempFile); @@ -116,6 +135,7 @@ Deno.test({ assertEquals(data, new Uint8Array(bytes)); nWritten = await new Promise((resolve, reject) => write( + // @ts-ignore (iuioiua) `file.rid` should no longer be needed once FDs are used file.rid, buffer, offset, diff --git a/tests/unit_node/_test_utils.ts b/tests/unit_node/_test_utils.ts index d9dd4e5d59..c451ccd84b 100644 --- a/tests/unit_node/_test_utils.ts +++ b/tests/unit_node/_test_utils.ts @@ -21,7 +21,6 @@ export async function assertCallbackErrorUncaught( const p = new Deno.Command(Deno.execPath(), { args: [ "eval", - "--unstable", `${prelude ?? ""} ${invocation}(err) => { diff --git a/tests/unit_node/async_hooks_test.ts b/tests/unit_node/async_hooks_test.ts index f153f67532..edad57bf76 100644 --- a/tests/unit_node/async_hooks_test.ts +++ b/tests/unit_node/async_hooks_test.ts @@ -1,5 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { AsyncLocalStorage, AsyncResource } from "node:async_hooks"; +import process from "node:process"; +import { setImmediate } from "node:timers"; import { assert, assertEquals } from "@std/assert"; Deno.test(async function foo() { @@ -92,7 +94,7 @@ Deno.test(async function enterWith() { }); assertEquals(await deferred.promise, { x: 2 }); - assertEquals(await deferred1.promise, { x: 1 }); + assertEquals(await deferred1.promise, null); }); Deno.test(async function snapshot() { @@ -135,3 +137,38 @@ Deno.test(function emitDestroyStub() { const resource = new AsyncResource("foo"); assert(typeof resource.emitDestroy === "function"); }); + +Deno.test(async function worksWithAsyncAPIs() { + const store = new AsyncLocalStorage(); + const test = () => assertEquals(store.getStore(), "data"); + await store.run("data", async () => { + test(); + queueMicrotask(() => test()); + process.nextTick(() => test()); + setImmediate(() => test()); + setTimeout(() => test(), 0); + const intervalId = setInterval(() => { + test(); + clearInterval(intervalId); + }, 0); + + store.run("data2", () => { + assertEquals(store.getStore(), "data2"); + }); + + await new Promise((r) => setTimeout(r, 50)); + test(); + }); +}); + +Deno.test(async function worksWithDynamicImports() { + const store = new AsyncLocalStorage(); + // @ts-expect-error implicit any + globalThis.alsDynamicImport = () => store.getStore(); + const dataUrl = + `data:application/javascript,export const data = alsDynamicImport()`; + await store.run("data", async () => { + const { data } = await import(dataUrl); + assertEquals(data, "data"); + }); +}); diff --git a/tests/unit_node/child_process_test.ts b/tests/unit_node/child_process_test.ts index d613d29894..0ea3c46cf0 100644 --- a/tests/unit_node/child_process_test.ts +++ b/tests/unit_node/child_process_test.ts @@ -12,7 +12,7 @@ import { assertThrows, } from "@std/assert"; import * as path from "@std/path"; -import { setTimeout } from "node:timers"; +import { clearTimeout, setTimeout } from "node:timers"; const { spawn, spawnSync, execFile, execFileSync, ChildProcess } = CP; @@ -528,7 +528,6 @@ Deno.test({ const childProcess = spawn(Deno.execPath(), [ "run", "-A", - "--unstable", script, ]); const deferred = Promise.withResolvers(); @@ -1046,3 +1045,19 @@ Deno.test(async function sendAfterClosedThrows() { await timeout.promise; }); + +Deno.test(async function noWarningsFlag() { + const code = ``; + const file = await Deno.makeTempFile(); + await Deno.writeTextFile(file, code); + const timeout = withTimeout(); + const child = CP.fork(file, [], { + execArgv: ["--no-warnings"], + stdio: ["inherit", "inherit", "inherit", "ipc"], + }); + child.on("close", () => { + timeout.resolve(); + }); + + await timeout.promise; +}); diff --git a/tests/unit_node/cluster_test.ts b/tests/unit_node/cluster_test.ts new file mode 100644 index 0000000000..d9a59ae63a --- /dev/null +++ b/tests/unit_node/cluster_test.ts @@ -0,0 +1,43 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +import { assertEquals } from "@std/assert"; +import cluster from "node:cluster"; +import * as clusterNamed from "node:cluster"; + +Deno.test("[node/cluster] has all node exports", () => { + assertEquals(cluster.isPrimary, true); + assertEquals(cluster.isMaster, true); + assertEquals(cluster.isWorker, false); + assertEquals(typeof cluster.disconnect, "function"); + assertEquals(typeof cluster.on, "function"); + assertEquals(cluster.workers, {}); + assertEquals(cluster.settings, {}); + assertEquals(cluster.SCHED_NONE, 1); + assertEquals(cluster.SCHED_RR, 2); + assertEquals(typeof cluster.fork, "function"); + assertEquals(typeof cluster.disconnect, "function"); + assertEquals(typeof cluster.setupPrimary, "function"); + assertEquals(cluster.setupPrimary, cluster.setupMaster); + + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.setupPrimary, clusterNamed.setupPrimary); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.setupMaster, clusterNamed.setupMaster); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.workers, clusterNamed.workers); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.settings, clusterNamed.settings); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.fork, clusterNamed.fork); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.disconnect, clusterNamed.disconnect); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.SCHED_NONE, clusterNamed.SCHED_NONE); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.SCHED_RR, clusterNamed.SCHED_RR); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.isWorker, clusterNamed.isWorker); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.isPrimary, clusterNamed.isPrimary); + // @ts-ignore Our @types/node version is too old + assertEquals(cluster.isMaster, clusterNamed.isMaster); +}); diff --git a/tests/unit_node/crypto/crypto_cipher_gcm_test.ts b/tests/unit_node/crypto/crypto_cipher_gcm_test.ts index e87ae23f01..b379a43696 100644 --- a/tests/unit_node/crypto/crypto_cipher_gcm_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_gcm_test.ts @@ -101,3 +101,21 @@ for ( }); } } + +Deno.test({ + name: "aes-128-gcm encrypt multiple", + fn() { + const key = Buffer.alloc(16); + const nonce = Buffer.alloc(12); + + const gcm = crypto.createCipheriv("aes-128-gcm", key, nonce); + + assertEquals(gcm.update("hello", "utf8", "hex"), "6bedb6a20f"); + assertEquals(gcm.update("world", "utf8", "hex"), "c1cce09f4c"); + gcm.final(); + assertEquals( + gcm.getAuthTag().toString("hex"), + "bf6d20a38e0c828bea3de63b7ff1dfbd", + ); + }, +}); diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index 91227cf006..65a5b29eeb 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -139,16 +139,32 @@ Deno.test({ Deno.test({ name: "createCipheriv - input encoding", fn() { - const cipher = crypto.createCipheriv( - "aes-128-cbc", - new Uint8Array(16), - new Uint8Array(16), - ); - assertEquals( - cipher.update("hello, world! hello, world!", "utf-8", "hex"), - "ca7df4d74f51b77a7440ead38343ab0f", - ); - assertEquals(cipher.final("hex"), "d0da733dec1fa61125c80a6f97e6166e"); + { + const cipher = crypto.createCipheriv( + "aes-128-cbc", + new Uint8Array(16), + new Uint8Array(16), + ); + assertEquals( + cipher.update("hello, world! hello, world!", "utf-8", "hex"), + "ca7df4d74f51b77a7440ead38343ab0f", + ); + assertEquals(cipher.final("hex"), "d0da733dec1fa61125c80a6f97e6166e"); + } + + { + const cipher = crypto.createCipheriv( + "aes-128-cbc", + new Uint8Array(16), + new Uint8Array(16), + ); + // update with string without input encoding + assertEquals( + cipher.update("hello, world! hello, world!").toString("hex"), + "ca7df4d74f51b77a7440ead38343ab0f", + ); + assertEquals(cipher.final("hex"), "d0da733dec1fa61125c80a6f97e6166e"); + } }, }); @@ -245,6 +261,44 @@ Deno.test({ }, }); +Deno.test({ + name: "createCipheriv - invalid inputs", + fn() { + assertThrows( + () => + crypto.createCipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), + RangeError, + "Invalid key length", + ); + assertThrows( + () => + crypto.createCipheriv( + "aes-256-cbc", + new Uint8Array(31), + new Uint8Array(16), + ), + RangeError, + "Invalid key length", + ); + assertThrows( + () => + crypto.createCipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), + TypeError, + "Invalid initialization vector", + ); + assertThrows( + () => + crypto.createCipheriv( + "aes-256-cbc", + new Uint8Array(32), + new Uint8Array(15), + ), + TypeError, + "Invalid initialization vector", + ); + }, +}); + Deno.test({ name: "createDecipheriv - invalid algorithm", fn() { @@ -257,6 +311,52 @@ Deno.test({ }, }); +Deno.test({ + name: "createDecipheriv - invalid inputs", + fn() { + assertThrows( + () => + crypto.createDecipheriv( + "aes256", + new Uint8Array(31), + new Uint8Array(16), + ), + RangeError, + "Invalid key length", + ); + assertThrows( + () => + crypto.createDecipheriv( + "aes-256-cbc", + new Uint8Array(31), + new Uint8Array(16), + ), + RangeError, + "Invalid key length", + ); + assertThrows( + () => + crypto.createDecipheriv( + "aes256", + new Uint8Array(32), + new Uint8Array(15), + ), + TypeError, + "Invalid initialization vector", + ); + assertThrows( + () => + crypto.createDecipheriv( + "aes-256-cbc", + new Uint8Array(32), + new Uint8Array(15), + ), + TypeError, + "Invalid initialization vector", + ); + }, +}); + Deno.test({ name: "getCiphers", fn() { @@ -278,3 +378,41 @@ Deno.test({ assertEquals(info2.ivLength, 16); }, }); + +Deno.test({ + name: + "createDecipheriv - handling of the last chunk when auto padding enabled/disabled", + fn() { + const algorithm = "aes-256-cbc"; + const key = Buffer.from( + "84dcdd964968734fdf0de4a2cba471c2e0a753930b841c014b1e77f456b5797b", + "hex", + ); + const val = Buffer.from( + "feabbdf66e2c71cc780d0cd2765dcce283e8ae7e58fcc1a9acafc678581e0e06", + "hex", + ); + const iv = Buffer.alloc(16, 0); + + { + const decipher = crypto.createDecipheriv(algorithm, key, iv); + decipher.setAutoPadding(false); + assertEquals( + decipher.update(val, undefined, "hex"), + "ed2c908f26571bf8e50d60b77fb9c25f95b933b59111543c6fac41ad6b47e681", + ); + assertEquals(decipher.final("hex"), ""); + } + + { + const decipher = crypto.createDecipheriv(algorithm, key, iv); + assertEquals( + decipher.update(val, undefined, "hex"), + "ed2c908f26571bf8e50d60b77fb9c25f", + ); + assertThrows(() => { + decipher.final(); + }); + } + }, +}); diff --git a/tests/unit_node/crypto/crypto_key_test.ts b/tests/unit_node/crypto/crypto_key_test.ts index 6365119e23..3c7ad44232 100644 --- a/tests/unit_node/crypto/crypto_key_test.ts +++ b/tests/unit_node/crypto/crypto_key_test.ts @@ -439,3 +439,241 @@ Deno.test("create private key with invalid utf-8 string", function () { "not valid utf8", ); }); + +Deno.test("RSA JWK import public key", function () { + const key = { + "kty": "RSA", + "alg": "RS256", + "n": + "5Ddosh0Bze5zy-nQ6gAJFpBfL13muCXrTyKYTps61bmnUxpp3bJnt_2N2MXGfuxBENO0Rbc8DhVPd-lNa4H3XjMwIBdxDAwW32z3pfVr8pHyWxeFtK4SCbvX8B0C6n8ZHigJsvdiCNmoj7_LO_QUzIXmXLFvEXtAqzD_hCr0pJxRIr0BrBjYwL23PkxOYzBR-URcd4Ilji6410Eh9NXycyFzKOcqZ7rjG_PnRyUX1EBZH_PN4RExjJuXYgiqhtU-tDjQFzXLhvwAd5s3ThP9lax27A6MUpjLSKkNy-dG5tlaA0QvECfDzA-5eQjcL_OfvbHlKHQH9zPh-U9Q8gsf3iXmbJrypkalUiTCqnzJu5TgZORSg6zmxNyOCz53YxBHEEaF8yROPwxWDylZfC4fxCRTdoAyFgmFLfMbiepV7AZ24KLj4jfMbGfKpkbPq0xirnSAS-3vbOfkgko5X420AttP8Z1ZBbFSD20Ath_TA9PSHiRCak4AXvOoCZg0t-WuMwzkd_B2V_JZZSTb1yBWrKTL1QzUamqlufjdWuz7M-O2Wkb2cyDSESVNuQyJgDkYb0AOWo0BaN3wbOeT_D4cSrjQoo01xQQCZHQ9SVR4QzUQNAiQcSriqEiptHYhbi6R5_GfGAeMHmlJa4atO2hense0Qk4vDc2fc-sbnQ1jPiE", + "e": "AQAB", + "key_ops": [ + "verify", + ], + "ext": true, + }; + + const keyObject = createPublicKey({ key, format: "jwk" }); + const expectedPem = `-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5Ddosh0Bze5zy+nQ6gAJ +FpBfL13muCXrTyKYTps61bmnUxpp3bJnt/2N2MXGfuxBENO0Rbc8DhVPd+lNa4H3 +XjMwIBdxDAwW32z3pfVr8pHyWxeFtK4SCbvX8B0C6n8ZHigJsvdiCNmoj7/LO/QU +zIXmXLFvEXtAqzD/hCr0pJxRIr0BrBjYwL23PkxOYzBR+URcd4Ilji6410Eh9NXy +cyFzKOcqZ7rjG/PnRyUX1EBZH/PN4RExjJuXYgiqhtU+tDjQFzXLhvwAd5s3ThP9 +lax27A6MUpjLSKkNy+dG5tlaA0QvECfDzA+5eQjcL/OfvbHlKHQH9zPh+U9Q8gsf +3iXmbJrypkalUiTCqnzJu5TgZORSg6zmxNyOCz53YxBHEEaF8yROPwxWDylZfC4f +xCRTdoAyFgmFLfMbiepV7AZ24KLj4jfMbGfKpkbPq0xirnSAS+3vbOfkgko5X420 +AttP8Z1ZBbFSD20Ath/TA9PSHiRCak4AXvOoCZg0t+WuMwzkd/B2V/JZZSTb1yBW +rKTL1QzUamqlufjdWuz7M+O2Wkb2cyDSESVNuQyJgDkYb0AOWo0BaN3wbOeT/D4c +SrjQoo01xQQCZHQ9SVR4QzUQNAiQcSriqEiptHYhbi6R5/GfGAeMHmlJa4atO2he +nse0Qk4vDc2fc+sbnQ1jPiECAwEAAQ== +-----END PUBLIC KEY----- +`; + + const pem = keyObject.export({ format: "pem", type: "spki" }); + assertEquals(pem, expectedPem); +}); + +Deno.test("Ed25519 import jwk public key #1", function () { + const key = { + "kty": "OKP", + "crv": "Ed25519", + "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", + }; + const keyObject = createPublicKey({ key, format: "jwk" }); + + assertEquals(keyObject.type, "public"); + const spkiActual = keyObject.export({ type: "spki", format: "pem" }); + + const spkiExpected = `-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo= +-----END PUBLIC KEY----- +`; + + assertEquals(spkiActual, spkiExpected); +}); + +Deno.test("Ed25519 import jwk public key #2", function () { + const key = { + "kty": "OKP", + "crv": "Ed25519", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", + }; + + const keyObject = createPublicKey({ key, format: "jwk" }); + assertEquals(keyObject.type, "public"); + + const spki = keyObject.export({ type: "spki", format: "pem" }); + const spkiExpected = `-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo= +-----END PUBLIC KEY----- +`; + assertEquals(spki, spkiExpected); +}); + +Deno.test("Ed25519 import jwk private key", function () { + const key = { + "kty": "OKP", + "crv": "Ed25519", + "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", + }; + + const keyObject = createPrivateKey({ key, format: "jwk" }); + assertEquals(keyObject.type, "private"); + + const pkcs8Actual = keyObject.export({ type: "pkcs8", format: "pem" }); + const pkcs8Expected = `-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIJ1hsZ3v/VpguoRK9JLsLMREScVpezJpGXA7rAMcrn9g +-----END PRIVATE KEY----- +`; + + assertEquals(pkcs8Actual, pkcs8Expected); +}); + +Deno.test("RSA export public JWK", function () { + const importKey = "-----BEGIN PUBLIC KEY-----\n" + + "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqF66soiDvuqUB7ufWtuV\n" + + "5a1nZIw90m9qHEl2MeNt66HeEjG2GeHDfF5a4uplutnAh3dwpFweHqGIyB16POTI\n" + + "YysJ/rMPKoWZFQ1LEcr23rSgmL49YpifDetl5V/UR+zEygL3UzzZmbdjuyZz+Sjt\n" + + "FY+SAoZ9XPCqIaNha9uVFcurW44MvAkhzQR/yy5NWPaJ/yv4oI/exvuZnUwwBHvH\n" + + "gwVchfr7Jh5LRmYTPeyuI1lUOovVzE+0Ty/2tFfrm2hpedqYXvEuVu+yJzfuNoLf\n" + + "TGfz15J76eoRdFTCTdaG/MQnrzxZnIlmIpdpTPl0xVOwjKRpeYK06GS7EAa7cS9D\n" + + "dnsHkF/Mr9Yys5jw/49fXqh9BH3Iy0p5YmeQIMep04CUDFj7MZ+3SK8b0mA4SscH\n" + + "dIraZZynLZ1crM0ECAJBldM4TKqIDACYGU7XyRV+419cPJvYybHys5m7thS3QI7E\n" + + "LTpMV+WoYtZ5xeBCm7z5i3iPY6eSh2JtTu6oa3ALwwnXPAaZqDIFer8SoQNyVb0v\n" + + "EU8bVDeGXm1ha5gcC5KxqqnadO/WDD6Jke79Ji04sBEKTTodSOARyTGpGFEcC3Nn\n" + + "xSSScGCxMrGJuTDtnz+Eh6l6ysT+Nei9ZRMxNu8sZKAR43XkVXxF/OdSCbftFOAs\n" + + "wyPJtyhQALGPcK5cWPQS2sUCAwEAAQ==\n" + + "-----END PUBLIC KEY-----\n"; + const publicKey = createPublicKey(importKey); + + const jwk = publicKey.export({ format: "jwk" }); + assertEquals(jwk, { + kty: "RSA", + n: "qF66soiDvuqUB7ufWtuV5a1nZIw90m9qHEl2MeNt66HeEjG2GeHDfF5a4uplutnAh3dwpFweHqGIyB16POTIYysJ_rMPKoWZFQ1LEcr23rSgmL49YpifDetl5V_UR-zEygL3UzzZmbdjuyZz-SjtFY-SAoZ9XPCqIaNha9uVFcurW44MvAkhzQR_yy5NWPaJ_yv4oI_exvuZnUwwBHvHgwVchfr7Jh5LRmYTPeyuI1lUOovVzE-0Ty_2tFfrm2hpedqYXvEuVu-yJzfuNoLfTGfz15J76eoRdFTCTdaG_MQnrzxZnIlmIpdpTPl0xVOwjKRpeYK06GS7EAa7cS9DdnsHkF_Mr9Yys5jw_49fXqh9BH3Iy0p5YmeQIMep04CUDFj7MZ-3SK8b0mA4SscHdIraZZynLZ1crM0ECAJBldM4TKqIDACYGU7XyRV-419cPJvYybHys5m7thS3QI7ELTpMV-WoYtZ5xeBCm7z5i3iPY6eSh2JtTu6oa3ALwwnXPAaZqDIFer8SoQNyVb0vEU8bVDeGXm1ha5gcC5KxqqnadO_WDD6Jke79Ji04sBEKTTodSOARyTGpGFEcC3NnxSSScGCxMrGJuTDtnz-Eh6l6ysT-Nei9ZRMxNu8sZKAR43XkVXxF_OdSCbftFOAswyPJtyhQALGPcK5cWPQS2sU", + e: "AQAB", + }); +}); + +Deno.test("EC export public jwk", function () { + const key = "-----BEGIN PUBLIC KEY-----\n" + + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVEEIrFEZ+40Pk90LtKBQ3r7FGAPl\n" + + "v4bvX9grC8bNiNiVAcyEKs+QZKQj/0/CUPJV10AmavrUoPk/7Wy0sejopQ==\n" + + "-----END PUBLIC KEY-----\n"; + const publicKey = createPublicKey(key); + + const jwk = publicKey.export({ format: "jwk" }); + assertEquals(jwk, { + kty: "EC", + x: "VEEIrFEZ-40Pk90LtKBQ3r7FGAPlv4bvX9grC8bNiNg", + y: "lQHMhCrPkGSkI_9PwlDyVddAJmr61KD5P-1stLHo6KU", + crv: "P-256", + }); +}); + +Deno.test("Ed25519 export public jwk", function () { + const key = "-----BEGIN PUBLIC KEY-----\n" + + "MCowBQYDK2VwAyEAKCVFOD6Le61XM7HbN/MB/N06mX5bti2p50qjLvT1mzE=\n" + + "-----END PUBLIC KEY-----\n"; + const publicKey = createPublicKey(key); + + const jwk = publicKey.export({ format: "jwk" }); + assertEquals(jwk, { + crv: "Ed25519", + x: "KCVFOD6Le61XM7HbN_MB_N06mX5bti2p50qjLvT1mzE", + kty: "OKP", + }); +}); + +Deno.test("EC import jwk public key", function () { + const publicKey = createPublicKey({ + key: { + kty: "EC", + x: "_GGuz19zab5J70zyiUK6sAM5mHqUbsY8H6U2TnVlt-k", + y: "TcZG5efXZDIhNGDp6XuujoJqOEJU2D2ckjG9nOnSPIQ", + crv: "P-256", + }, + format: "jwk", + }); + + const publicSpki = publicKey.export({ type: "spki", format: "pem" }); + const spkiExpected = `-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/GGuz19zab5J70zyiUK6sAM5mHqU +bsY8H6U2TnVlt+lNxkbl59dkMiE0YOnpe66Ogmo4QlTYPZySMb2c6dI8hA== +-----END PUBLIC KEY----- +`; + + assertEquals(publicSpki, spkiExpected); +}); + +Deno.test("EC import jwk private key", function () { + const privateKey = createPrivateKey({ + key: { + kty: "EC", + x: "_GGuz19zab5J70zyiUK6sAM5mHqUbsY8H6U2TnVlt-k", + y: "TcZG5efXZDIhNGDp6XuujoJqOEJU2D2ckjG9nOnSPIQ", + crv: "P-256", + d: "Wobjne0GqlB_1NynKu19rsw7zBHa94tKcWIxwIb88m8", + }, + format: "jwk", + }); + + const privatePkcs8 = privateKey.export({ type: "pkcs8", format: "pem" }); + + const pkcs8Expected = `-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWobjne0GqlB/1Nyn +Ku19rsw7zBHa94tKcWIxwIb88m+hRANCAAT8Ya7PX3NpvknvTPKJQrqwAzmYepRu +xjwfpTZOdWW36U3GRuXn12QyITRg6el7ro6CajhCVNg9nJIxvZzp0jyE +-----END PRIVATE KEY----- +`; + + assertEquals(privatePkcs8, pkcs8Expected); +}); + +Deno.test("createPublicKey x509", function () { + const certificate = `-----BEGIN CERTIFICATE----- +MIIC8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExB0ZXN0 +LWNlcnRpZmljYXRlMB4XDTI0MDkxNzA5MTczNVoXDTI3MDkxNzA5MTczNVowGzEZ +MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMOzTIrwvbUbPIrxCr5DO1XMd3tH37pID0no4cOUq1hxNEnB4l1j +2201atvmXwzWI3xtPzfwOYUtE/DGagFh805/nod5yXwR6liGd9RjkABxPi0UF7jl +lWHfBLyILUHVR9hEOl65vUpKx5ORNgbO9L7WsL/FKH9pvCbWjdI29+pQnZ4gOoWZ +YC6auoKfG7TcbaFb9AubolcIlofC2MHP+cWjPA+iX6ezUqqN1Ug5xGiF/sC79M0o +5d6E83zdXxyyFwydUWUv3EKgmVTLln/2hYQFKCRhy72n6L7y9JNcieOauQK0efJB ++2HwaWeAr2xkhSnWVCRl4nEgiu/E0nL/zNUCAwEAAaNCMEAwDgYDVR0PAQH/BAQD +AgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIAeXho137l8V6daKI33IvRb +N6CyMA0GCSqGSIb3DQEBCwUAA4IBAQAQU1Sast6VsD4uTJiSz/lSEkLZ6wC/6v+R +az0YSnbNmQ5YczBLdTLs07hBC1tDvv0vfopRXvNxP7AxkopX5O7Lc15zf5JdTZnY +/tJwO62jZiaLsfAo2JzrZ31h2cFFFRTYPTx+8E4djgdmwKtaECeQFXqdpOHOJCGv +NfwVlZ7Z/cd8fI8oiNtvJDAhPa/UZXAhFV74hT0DiuMwPiJvsG83rutvAYpZ8lPu +yG6QSsxPnxzEHIKR+vgxUHKwTdv0sWt3XBmpIY5CGXFR2eIQP1jv0ohtcnLMJe8N +z6TExWlQMjt66nV7R8cRAkzmABrG+NW3e8Zpac7Lkuv+zu0S+K7c +-----END CERTIFICATE-----`; + + const publicKey = createPublicKey(certificate); + assertEquals(publicKey.type, "public"); + assertEquals(publicKey.asymmetricKeyType, "rsa"); +}); + +// https://github.com/denoland/deno/issues/26188 +Deno.test("generateKeyPair large pem", function () { + const passphrase = "mypassphrase"; + const cipher = "aes-256-cbc"; + const modulusLength = 4096; + + generateKeyPairSync("rsa", { + modulusLength, + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher, + passphrase, + }, + }); +}); diff --git a/tests/unit_node/crypto/crypto_misc_test.ts b/tests/unit_node/crypto/crypto_misc_test.ts index 47a48b1bf8..007009339d 100644 --- a/tests/unit_node/crypto/crypto_misc_test.ts +++ b/tests/unit_node/crypto/crypto_misc_test.ts @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { randomFillSync, randomUUID } from "node:crypto"; +import { randomFillSync, randomUUID, timingSafeEqual } from "node:crypto"; +import { Buffer } from "node:buffer"; import { assert, assertEquals } from "../../unit/test_util.ts"; import { assertNotEquals } from "@std/assert"; @@ -28,3 +29,10 @@ Deno.test("[node/crypto.randomFillSync] array buffer view", () => { assertEquals(buf.subarray(0, 8), new Uint8Array(8)); assertEquals(buf.subarray(24, 32), new Uint8Array(8)); }); + +Deno.test("[node/crypto.timingSafeEqual] compares equal Buffer with different byteOffset", () => { + const a = Buffer.from([212, 213]); + const b = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 212, 213]).subarray(8); + + assert(timingSafeEqual(a, b)); +}); diff --git a/tests/unit_node/crypto/crypto_sign_test.ts b/tests/unit_node/crypto/crypto_sign_test.ts index c33c9758f4..97c80b28af 100644 --- a/tests/unit_node/crypto/crypto_sign_test.ts +++ b/tests/unit_node/crypto/crypto_sign_test.ts @@ -154,16 +154,21 @@ Deno.test("crypto.createSign|sign - compare with node", async (t) => { new URL(import.meta.resolve("../testdata/rsa_private.pem")), ); for (const { digest, signature } of fixtures) { - await t.step(digest, () => { - let actual: string | null; - try { - const s = createSign(digest); - s.update(DATA); - actual = s.sign(privateKey).toString("hex"); - } catch { - actual = null; - } - assertEquals(actual, signature); + await t.step({ + name: digest, + // TODO(lucacasonato): our md4 implementation does not have an OID, so it can't sign/verify + ignore: digest.toLowerCase().includes("md4"), + fn: () => { + let actual: string | null; + try { + const s = createSign(digest); + s.update(DATA); + actual = s.sign(privateKey).toString("hex"); + } catch { + actual = null; + } + assertEquals(actual, signature); + }, }); } }); @@ -176,7 +181,8 @@ Deno.test("crypto.createVerify|verify - compare with node", async (t) => { for (const { digest, signature } of fixtures) { await t.step({ name: digest, - ignore: signature === null, + // TODO(lucacasonato): our md4 implementation does not have an OID, so it can't sign/verify + ignore: signature === null || digest.toLowerCase().includes("md4"), fn: () => { const s = createVerify(digest); s.update(DATA); diff --git a/tests/unit_node/events_test.ts b/tests/unit_node/events_test.ts index 1fc7ad1e37..8cfef6319a 100644 --- a/tests/unit_node/events_test.ts +++ b/tests/unit_node/events_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import events, { EventEmitter } from "node:events"; +import events, { addAbortListener, EventEmitter } from "node:events"; EventEmitter.captureRejections = true; @@ -34,3 +34,13 @@ Deno.test("eventemitter async resource", () => { // @ts-ignore: @types/node is outdated foo.emit("bar"); }); + +Deno.test("addAbortListener", async () => { + const { promise, resolve } = Promise.withResolvers(); + const abortController = new AbortController(); + addAbortListener(abortController.signal, () => { + resolve(); + }); + abortController.abort(); + await promise; +}); diff --git a/tests/unit_node/fetch_test.ts b/tests/unit_node/fetch_test.ts deleted file mode 100644 index 399d6052a5..0000000000 --- a/tests/unit_node/fetch_test.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -import { assertEquals } from "@std/assert"; -import { createReadStream } from "node:fs"; - -Deno.test("fetch node stream", async () => { - const file = createReadStream("tests/testdata/assets/fixture.json"); - - const response = await fetch("http://localhost:4545/echo_server", { - method: "POST", - body: file, - }); - - assertEquals( - await response.text(), - await Deno.readTextFile("tests/testdata/assets/fixture.json"), - ); -}); diff --git a/tests/unit_node/fs_test.ts b/tests/unit_node/fs_test.ts index c94a2447e6..ef8f829cda 100644 --- a/tests/unit_node/fs_test.ts +++ b/tests/unit_node/fs_test.ts @@ -1,22 +1,28 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assert, assertEquals, assertThrows } from "@std/assert"; +/// +import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { + closeSync, constants, + copyFileSync, createWriteStream, existsSync, lstatSync, mkdtempSync, + openSync, promises, readFileSync, + readSync, Stats, statSync, writeFileSync, } from "node:fs"; import { constants as fsPromiseConstants, + copyFile, cp, FileHandle, open, @@ -88,7 +94,7 @@ Deno.test( () => { assertThrows(() => { existsSync("tests/testdata/assets/fixture.json"); - }, Deno.errors.PermissionDenied); + }, Deno.errors.NotCapable); }, ); @@ -201,3 +207,40 @@ Deno.test( assertEquals(res, [0, 1, 2, 3, 4, 5]); }, ); + +Deno.test("[node/fs] readSync works", () => { + const fd = openSync("tests/testdata/assets/hello.txt", "r"); + const buf = new Uint8Array(256); + const bytesRead = readSync(fd!, buf); + assertEquals(bytesRead, 12); + closeSync(fd!); +}); + +Deno.test("[node/fs] copyFile COPYFILE_EXCL works", async () => { + const dir = mkdtempSync(join(tmpdir(), "foo-")); + const src = join(dir, "src.txt"); + const dest = join(dir, "dest.txt"); + await writeFile(src, ""); + await copyFile(src, dest, fsPromiseConstants.COPYFILE_EXCL); + assert(existsSync(dest)); + await assertRejects(() => + copyFile(src, dest, fsPromiseConstants.COPYFILE_EXCL) + ); + const dest2 = join(dir, "dest2.txt"); + copyFileSync(src, dest2, fsPromiseConstants.COPYFILE_EXCL); + assert(existsSync(dest2)); + assertThrows(() => + copyFileSync(src, dest2, fsPromiseConstants.COPYFILE_EXCL) + ); +}); + +Deno.test("[node/fs] statSync throws ENOENT for invalid path containing colon in it", () => { + // deno-lint-ignore no-explicit-any + const err: any = assertThrows(() => { + // Note: Deno.stat throws ERROR_INVALID_NAME (os error 123) instead of + // ERROR_FILE_NOT_FOUND (os error 2) on windows. This case checks that + // ERROR_INVALID_NAME is mapped to ENOENT correctly on node compat layer. + statSync("jsr:@std/assert"); + }); + assertEquals(err.code, "ENOENT"); +}); diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts index 7cffd04322..7473a487ad 100644 --- a/tests/unit_node/http2_test.ts +++ b/tests/unit_node/http2_test.ts @@ -1,5 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import * as http2 from "node:http2"; import { Buffer } from "node:buffer"; import { readFile } from "node:fs/promises"; @@ -8,7 +10,7 @@ import * as net from "node:net"; import { assert, assertEquals } from "@std/assert"; import { curlRequest } from "../unit/test_util.ts"; -for (const url of ["http://127.0.0.1:4246", "https://127.0.0.1:4247"]) { +for (const url of ["http://localhost:4246", "https://localhost:4247"]) { Deno.test(`[node/http2 client] ${url}`, { ignore: Deno.build.os === "windows", }, async () => { @@ -153,7 +155,7 @@ Deno.test("[node/http2.createServer()]", { res.end(); }); server.listen(0); - const port = ( server.address()).port; + const port = (server.address() as net.AddressInfo).port; const endpoint = `http://localhost:${port}`; const response = await curlRequest([ @@ -313,3 +315,71 @@ Deno.test("[node/http2 ClientHttp2Session.socket]", async () => { client.socket.setTimeout(0); assertEquals(receivedData, "hello world\n"); }); + +Deno.test("[node/http2 client] connection states", async () => { + const expected = { + beforeConnect: { connecting: true, closed: false, destroyed: false }, + afterConnect: { connecting: false, closed: false, destroyed: false }, + afterClose: { connecting: false, closed: true, destroyed: false }, + afterDestroy: { connecting: false, closed: true, destroyed: true }, + }; + const actual: Partial = {}; + + const url = "http://127.0.0.1:4246"; + const connectPromise = Promise.withResolvers(); + const client = http2.connect(url, {}, () => { + connectPromise.resolve(); + }); + client.on("error", (err) => console.error(err)); + + // close event happens after destory has been called + const destroyPromise = Promise.withResolvers(); + client.on("close", () => { + destroyPromise.resolve(); + }); + + actual.beforeConnect = { + connecting: client.connecting, + closed: client.closed, + destroyed: client.destroyed, + }; + + await connectPromise.promise; + actual.afterConnect = { + connecting: client.connecting, + closed: client.closed, + destroyed: client.destroyed, + }; + + // leave a request open to prevent immediate destroy + const req = client.request(); + req.on("data", () => {}); + req.on("error", (err) => console.error(err)); + const reqClosePromise = Promise.withResolvers(); + req.on("close", () => { + reqClosePromise.resolve(); + }); + + client.close(); + actual.afterClose = { + connecting: client.connecting, + closed: client.closed, + destroyed: client.destroyed, + }; + + await destroyPromise.promise; + actual.afterDestroy = { + connecting: client.connecting, + closed: client.closed, + destroyed: client.destroyed, + }; + + await reqClosePromise.promise; + + assertEquals(actual, expected); +}); + +Deno.test("request and response exports", () => { + assert(http2.Http2ServerRequest); + assert(http2.Http2ServerResponse); +}); diff --git a/tests/unit_node/http_test.ts b/tests/unit_node/http_test.ts index ec20ec7d7c..84d6f57279 100644 --- a/tests/unit_node/http_test.ts +++ b/tests/unit_node/http_test.ts @@ -1,15 +1,23 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import EventEmitter from "node:events"; -import http, { type RequestOptions, type ServerResponse } from "node:http"; +import http, { + IncomingMessage, + type RequestOptions, + ServerResponse, +} from "node:http"; import url from "node:url"; import https from "node:https"; -import net from "node:net"; +import net, { Socket } from "node:net"; import fs from "node:fs"; +import { text } from "node:stream/consumers"; import { assert, assertEquals, fail } from "@std/assert"; import { assertSpyCalls, spy } from "@std/testing/mock"; import { fromFileUrl, relative } from "@std/path"; +import { retry } from "@std/async/retry"; import { gzip } from "node:zlib"; import { Buffer } from "node:buffer"; @@ -314,10 +322,14 @@ Deno.test("[node/http] IncomingRequest socket has remoteAddress + remotePort", a // deno-lint-ignore no-explicit-any const port = (server.address() as any).port; const res = await fetch( - `http://127.0.0.1:${port}/`, + `http://localhost:${port}/`, ); await res.arrayBuffer(); - assertEquals(remoteAddress, "127.0.0.1"); + if (Deno.build.os === "windows") { + assertEquals(remoteAddress, "127.0.0.1"); + } else { + assertEquals(remoteAddress, "::1"); + } assertEquals(typeof remotePort, "number"); server.close(() => resolve()); }); @@ -1139,6 +1151,34 @@ Deno.test("[node/http] ServerResponse appendHeader set-cookie", async () => { await promise; }); +Deno.test("[node/http] ServerResponse header names case insensitive", async () => { + const { promise, resolve } = Promise.withResolvers(); + const server = http.createServer((_req, res) => { + res.setHeader("Content-Length", "12345"); + res.removeHeader("content-length"); + assertEquals(res.getHeader("Content-Length"), undefined); + assert(!res.hasHeader("Content-Length")); + res.appendHeader("content-length", "12345"); + res.removeHeader("Content-Length"); + assertEquals(res.getHeader("content-length"), undefined); + assert(!res.hasHeader("content-length")); + res.end("Hello World"); + }); + + server.listen(async () => { + const { port } = server.address() as { port: number }; + const res = await fetch(`http://localhost:${port}`); + assertEquals(res.headers.get("Content-Length"), null); + assertEquals(res.headers.get("content-length"), null); + assertEquals(await res.text(), "Hello World"); + server.close(() => { + resolve(); + }); + }); + + await promise; +}); + Deno.test("[node/http] IncomingMessage override", () => { const req = new http.IncomingMessage(new net.Socket()); // https://github.com/dougmoscrop/serverless-http/blob/3aaa6d0fe241109a8752efb011c242d249f32368/lib/request.js#L20-L30 @@ -1557,3 +1597,186 @@ Deno.test("[node/http] req.url equals pathname + search", async () => { await promise; }); + +Deno.test("[node/http] ClientRequest content-disposition header works", async () => { + const payload = Buffer.from("hello world"); + let body = ""; + let headers = {} as http.IncomingHttpHeaders; + const { promise, resolve, reject } = Promise.withResolvers(); + const req = http.request("http://localhost:4545/echo_server", { + method: "PUT", + headers: { + "content-disposition": "attachment", + }, + }, (resp) => { + headers = resp.headers; + resp.on("data", (chunk) => { + body += chunk; + }); + + resp.on("end", () => { + resolve(); + }); + }); + req.once("error", (e) => reject(e)); + req.end(payload); + await promise; + assertEquals(body, "hello world"); + assertEquals(headers["content-disposition"], "attachment"); +}); + +Deno.test("[node/http] In ClientRequest, option.hostname has precedence over options.host", async () => { + const responseReceived = Promise.withResolvers(); + + new http.ClientRequest({ + hostname: "localhost", + host: "invalid-hostname.test", + port: 4545, + path: "/http_version", + }).on("response", async (res) => { + assertEquals(res.statusCode, 200); + assertEquals(await text(res), "HTTP/1.1"); + responseReceived.resolve(); + }).end(); + + await responseReceived.promise; +}); + +Deno.test("[node/http] upgraded socket closes when the server closed without closing handshake", async () => { + const clientSocketClosed = Promise.withResolvers(); + const serverProcessClosed = Promise.withResolvers(); + + // Uses the server in different process to shutdown it without closing handshake + const server = ` + Deno.serve({ port: 1337 }, (req) => { + if (req.headers.get("upgrade") != "websocket") { + return new Response("ok"); + } + console.log("upgrade on server"); + const { socket, response } = Deno.upgradeWebSocket(req); + socket.addEventListener("message", (event) => { + console.log("server received", event.data); + socket.send("pong"); + }); + return response; + }); + `; + + const p = new Deno.Command("deno", { args: ["eval", server] }).spawn(); + + // Wait for the server to respond + await retry(async () => { + const resp = await fetch("http://localhost:1337"); + const _text = await resp.text(); + }); + + const options = { + port: 1337, + host: "127.0.0.1", + headers: { + "Connection": "Upgrade", + "Upgrade": "websocket", + "Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==", + }, + }; + + http.request(options).on("upgrade", (_res, socket) => { + socket.on("close", () => { + console.log("client socket closed"); + clientSocketClosed.resolve(); + }); + socket.on("data", async (data) => { + // receives pong message + assertEquals(data, Buffer.from("8104706f6e67", "hex")); + + p.kill(); + await p.status; + + console.log("process closed"); + serverProcessClosed.resolve(); + + // sending some additional message + socket.write(Buffer.from("81847de88e01", "hex")); + socket.write(Buffer.from("0d81e066", "hex")); + }); + + // sending ping message + socket.write(Buffer.from("81847de88e01", "hex")); + socket.write(Buffer.from("0d81e066", "hex")); + }).end(); + + await clientSocketClosed.promise; + await serverProcessClosed.promise; +}); + +// deno-lint-ignore require-await +Deno.test("[node/http] ServerResponse.call()", async () => { + function Wrapper(this: unknown, req: IncomingMessage) { + ServerResponse.call(this, req); + } + Object.setPrototypeOf(Wrapper.prototype, ServerResponse.prototype); + + // deno-lint-ignore no-explicit-any + const wrapper = new (Wrapper as any)(new IncomingMessage(new Socket())); + + assert(wrapper instanceof ServerResponse); +}); + +Deno.test("[node/http] ServerResponse _header", async () => { + const { promise, resolve } = Promise.withResolvers(); + const server = http.createServer((_req, res) => { + assert(Object.hasOwn(res, "_header")); + res.end(); + }); + + server.listen(async () => { + const { port } = server.address() as { port: number }; + const res = await fetch(`http://localhost:${port}`); + await res.body?.cancel(); + server.close(() => { + resolve(); + }); + }); + + await promise; +}); + +Deno.test("[node/http] ServerResponse connection", async () => { + const { promise, resolve } = Promise.withResolvers(); + const server = http.createServer((_req, res) => { + assert(Object.hasOwn(res, "connection")); + assert(res.connection instanceof Socket); + res.end(); + }); + + server.listen(async () => { + const { port } = server.address() as { port: number }; + const res = await fetch(`http://localhost:${port}`); + await res.body?.cancel(); + server.close(() => { + resolve(); + }); + }); + + await promise; +}); + +Deno.test("[node/http] ServerResponse socket", async () => { + const { promise, resolve } = Promise.withResolvers(); + const server = http.createServer((_req, res) => { + assert(Object.hasOwn(res, "socket")); + assert(res.socket instanceof Socket); + res.end(); + }); + + server.listen(async () => { + const { port } = server.address() as { port: number }; + const res = await fetch(`http://localhost:${port}`); + await res.body?.cancel(); + server.close(() => { + resolve(); + }); + }); + + await promise; +}); diff --git a/tests/unit_node/module_test.ts b/tests/unit_node/module_test.ts index 994dcfb639..96c3504bd2 100644 --- a/tests/unit_node/module_test.ts +++ b/tests/unit_node/module_test.ts @@ -74,7 +74,7 @@ Deno.test("Built-in Node modules have `node:` prefix", () => { createRequire(); } catch (e) { thrown = true; - const stackLines = e.stack.split("\n"); + const stackLines = (e as Error).stack!.split("\n"); // Assert that built-in node modules have `node:` specifiers. assert(stackLines.some((line: string) => line.includes("(node:module:"))); } diff --git a/tests/unit_node/net_test.ts b/tests/unit_node/net_test.ts index 521de1e73d..83d751866f 100644 --- a/tests/unit_node/net_test.ts +++ b/tests/unit_node/net_test.ts @@ -1,5 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import * as net from "node:net"; import { assert, assertEquals } from "@std/assert"; import * as path from "@std/path"; @@ -77,6 +79,7 @@ Deno.test("[node/net] net.connect().unref() works", async () => { port: 0, // any available port will do handler: () => new Response("hello"), onListen: async ({ port, hostname }) => { + hostname = Deno.build.os === "windows" ? "localhost" : hostname; const { stdout, stderr } = await new Deno.Command(Deno.execPath(), { args: [ "eval", @@ -110,7 +113,7 @@ Deno.test({ const s = new net.Server(); s.listen(3000); } catch (e) { - assert(e instanceof Deno.errors.PermissionDenied); + assert(e instanceof Deno.errors.NotCapable); } }, }); @@ -225,3 +228,22 @@ Deno.test("[node/net] BlockList doesn't leak resources", () => { blockList.addAddress("1.1.1.1"); assert(blockList.check("1.1.1.1")); }); + +Deno.test("[node/net] net.Server can listen on the same port immediately after it's closed", async () => { + const serverClosed = Promise.withResolvers(); + const server = net.createServer(); + server.on("error", (e) => { + console.error(e); + }); + server.listen(0, () => { + // deno-lint-ignore no-explicit-any + const { port } = server.address() as any; + server.close(); + server.listen(port, () => { + server.close(() => { + serverClosed.resolve(); + }); + }); + }); + await serverClosed.promise; +}); diff --git a/tests/unit_node/os_test.ts b/tests/unit_node/os_test.ts index a75b668073..78636e755d 100644 --- a/tests/unit_node/os_test.ts +++ b/tests/unit_node/os_test.ts @@ -8,6 +8,7 @@ import { assertNotEquals, assertThrows, } from "@std/assert"; +import console from "node:console"; Deno.test({ name: "build architecture is a string", @@ -298,7 +299,14 @@ Deno.test({ args: ["eval", "while (true) { console.log('foo') }"], }).spawn(); assertThrows( - () => os.setPriority(child.pid, os.constants.priority.PRIORITY_HIGH), + () => { + try { + os.setPriority(child.pid, os.constants.priority.PRIORITY_HIGH); + } catch (err) { + console.error(err); + throw err; + } + }, Deno.errors.PermissionDenied, ); os.getPriority(child.pid); diff --git a/tests/unit_node/process_test.ts b/tests/unit_node/process_test.ts index cc9e4dbd4d..f9138c8f08 100644 --- a/tests/unit_node/process_test.ts +++ b/tests/unit_node/process_test.ts @@ -1,11 +1,14 @@ -// deno-lint-ignore-file no-undef // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-undef no-console + import process, { arch as importedArch, argv, argv0 as importedArgv0, env, + execArgv as importedExecArgv, + execPath as importedExecPath, geteuid, pid as importedPid, platform as importedPlatform, @@ -170,7 +173,6 @@ Deno.test({ args: [ "run", "--quiet", - "--unstable", "./testdata/process_exit.ts", ], cwd, @@ -458,6 +460,7 @@ Deno.test({ Deno.test({ name: "process.stdin", fn() { + // @ts-ignore `Deno.stdin.rid` was soft-removed in Deno 2. assertEquals(process.stdin.fd, Deno.stdin.rid); assertEquals(process.stdin.isTTY, Deno.stdin.isTerminal()); }, @@ -637,6 +640,7 @@ Deno.test({ Deno.test({ name: "process.stdout", fn() { + // @ts-ignore `Deno.stdout.rid` was soft-removed in Deno 2. assertEquals(process.stdout.fd, Deno.stdout.rid); const isTTY = Deno.stdout.isTerminal(); assertEquals(process.stdout.isTTY, isTTY); @@ -659,12 +663,23 @@ Deno.test({ assertStrictEquals(process.stdout.clearLine, undefined); assertStrictEquals(process.stdout.clearScreenDown, undefined); } + + // Allows overwriting `process.stdout.isTTY` + // https://github.com/denoland/deno/issues/26123 + const original = process.stdout.isTTY; + try { + process.stdout.isTTY = !isTTY; + assertEquals(process.stdout.isTTY, !isTTY); + } finally { + process.stdout.isTTY = original; + } }, }); Deno.test({ name: "process.stderr", fn() { + // @ts-ignore `Deno.stderr.rid` was soft-removed in Deno 2. assertEquals(process.stderr.fd, Deno.stderr.rid); const isTTY = Deno.stderr.isTerminal(); assertEquals(process.stderr.isTTY, isTTY); @@ -889,7 +904,6 @@ Deno.test({ args: [ "run", "--quiet", - "--unstable", "./testdata/process_exit2.ts", ], cwd: testDir, @@ -908,7 +922,6 @@ Deno.test({ args: [ "run", "--quiet", - "--unstable", "./testdata/process_really_exit.ts", ], cwd: testDir, @@ -1120,3 +1133,22 @@ Deno.test("process.listeners - include SIG* events", () => { Deno.test(function processVersionsOwnProperty() { assert(Object.prototype.hasOwnProperty.call(process, "versions")); }); + +Deno.test(function importedExecArgvTest() { + assert(Array.isArray(importedExecArgv)); +}); + +Deno.test(function importedExecPathTest() { + assertEquals(importedExecPath, Deno.execPath()); +}); + +Deno.test("process.cpuUsage()", () => { + const cpuUsage = process.cpuUsage(); + assert(typeof cpuUsage.user === "number"); + assert(typeof cpuUsage.system === "number"); +}); + +Deno.test("process.stdout.columns writable", () => { + process.stdout.columns = 80; + assertEquals(process.stdout.columns, 80); +}); diff --git a/tests/unit_node/stream_test.ts b/tests/unit_node/stream_test.ts index a54f8b421b..b8542f6cfd 100644 --- a/tests/unit_node/stream_test.ts +++ b/tests/unit_node/stream_test.ts @@ -1,9 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assert } from "@std/assert"; +import { assert, assertEquals } from "@std/assert"; import { fromFileUrl, relative } from "@std/path"; import { pipeline } from "node:stream/promises"; +import { getDefaultHighWaterMark, Stream } from "node:stream"; import { createReadStream, createWriteStream } from "node:fs"; +import { EventEmitter } from "node:events"; Deno.test("stream/promises pipeline", async () => { const filePath = relative( @@ -23,3 +25,13 @@ Deno.test("stream/promises pipeline", async () => { // pass } }); + +Deno.test("stream getDefaultHighWaterMark", () => { + assertEquals(getDefaultHighWaterMark(false), 16 * 1024); + assertEquals(getDefaultHighWaterMark(true), 16); +}); + +Deno.test("stream is an instance of EventEmitter", () => { + const stream = new Stream(); + assert(stream instanceof EventEmitter); +}); diff --git a/tests/unit_node/testdata/crypto_digest_fixtures.json b/tests/unit_node/testdata/crypto_digest_fixtures.json index c5b65261df..984657d24f 100644 --- a/tests/unit_node/testdata/crypto_digest_fixtures.json +++ b/tests/unit_node/testdata/crypto_digest_fixtures.json @@ -1,4 +1,11 @@ [ + { + "digest": "RSA-MD4", + "hash": "0abe9ee1f376caa1bcecad9042f16e73", + "signature": "9e0ea2ddcde181d9304e0cc56fd5e83f3bcc7921aa8605c4abb47c3829e79f99e856e323555222765d2b92328ff72b34ccbbc9e417033e1214c79bc4cccaf9d3a7f73105ab8f54507aa6a1909ec4754bd5a3b0ac588836c10c79c28ab81294b91aa5fa622574112dfeb52e8d785aa16193713ff66c11f23277eb27cfc8a6cd658777e3310aa9eede84b638673565f41978d278ef51b68a7e9855543f70e0c7ca823a7dfcfd922ea4973360a58c41132472737c6d68d30c2b4ca50882092e12f3e3b017199f45180a897cd155107ddd7fccca3eea565521b3f75dd8db6b0e8817c20b96e7e0d2bfe5c73e10a2d1e720dc00809def92c419411fcdd6e029fb6053", + "pkdf2": "a94d60cc0f44f11f4dd836de5313642956fee6f36ed7460b91d80e5dbc4089f123d6c70c6da4de059248a863af93da1f2776fae7065f008cf3fc7ebfe7592d7a", + "hkdf": "0104d69f3cb07f15194061d20905c559fcd1e3e2f71012ef88c964b16dca5253cda26f4c84fbafab14e638be1d1a972109b8725d5fb4dfa50b95d6ad3c4b6a88" + }, { "digest": "RSA-MD5", "hash": "6cd3556deb0da54bca060b4c39479839", @@ -146,6 +153,20 @@ "pkdf2": "e1f0b454bf5d729fbb13e534229521a87aee130078555791d83834a8c51fb681ce4dfe02afd5f063082d8abba0b456084c677aeb6f8e0d70305322ec2ea97203", "hkdf": "f27d87f9f6b87718073c8d2ad6bae00b4162cecde350c856252dd611120c433373a0c0d3946a8582bf855bf581439a14ca4f355fcd18881331f4a3b1027e84b2" }, + { + "digest": "md4", + "hash": "0abe9ee1f376caa1bcecad9042f16e73", + "signature": "9e0ea2ddcde181d9304e0cc56fd5e83f3bcc7921aa8605c4abb47c3829e79f99e856e323555222765d2b92328ff72b34ccbbc9e417033e1214c79bc4cccaf9d3a7f73105ab8f54507aa6a1909ec4754bd5a3b0ac588836c10c79c28ab81294b91aa5fa622574112dfeb52e8d785aa16193713ff66c11f23277eb27cfc8a6cd658777e3310aa9eede84b638673565f41978d278ef51b68a7e9855543f70e0c7ca823a7dfcfd922ea4973360a58c41132472737c6d68d30c2b4ca50882092e12f3e3b017199f45180a897cd155107ddd7fccca3eea565521b3f75dd8db6b0e8817c20b96e7e0d2bfe5c73e10a2d1e720dc00809def92c419411fcdd6e029fb6053", + "pkdf2": "a94d60cc0f44f11f4dd836de5313642956fee6f36ed7460b91d80e5dbc4089f123d6c70c6da4de059248a863af93da1f2776fae7065f008cf3fc7ebfe7592d7a", + "hkdf": "0104d69f3cb07f15194061d20905c559fcd1e3e2f71012ef88c964b16dca5253cda26f4c84fbafab14e638be1d1a972109b8725d5fb4dfa50b95d6ad3c4b6a88" + }, + { + "digest": "md4WithRSAEncryption", + "hash": "0abe9ee1f376caa1bcecad9042f16e73", + "signature": "9e0ea2ddcde181d9304e0cc56fd5e83f3bcc7921aa8605c4abb47c3829e79f99e856e323555222765d2b92328ff72b34ccbbc9e417033e1214c79bc4cccaf9d3a7f73105ab8f54507aa6a1909ec4754bd5a3b0ac588836c10c79c28ab81294b91aa5fa622574112dfeb52e8d785aa16193713ff66c11f23277eb27cfc8a6cd658777e3310aa9eede84b638673565f41978d278ef51b68a7e9855543f70e0c7ca823a7dfcfd922ea4973360a58c41132472737c6d68d30c2b4ca50882092e12f3e3b017199f45180a897cd155107ddd7fccca3eea565521b3f75dd8db6b0e8817c20b96e7e0d2bfe5c73e10a2d1e720dc00809def92c419411fcdd6e029fb6053", + "pkdf2": "a94d60cc0f44f11f4dd836de5313642956fee6f36ed7460b91d80e5dbc4089f123d6c70c6da4de059248a863af93da1f2776fae7065f008cf3fc7ebfe7592d7a", + "hkdf": "0104d69f3cb07f15194061d20905c559fcd1e3e2f71012ef88c964b16dca5253cda26f4c84fbafab14e638be1d1a972109b8725d5fb4dfa50b95d6ad3c4b6a88" + }, { "digest": "md5", "hash": "6cd3556deb0da54bca060b4c39479839", diff --git a/tests/unit_node/tls_test.ts b/tests/unit_node/tls_test.ts index 6033efa312..236dab2086 100644 --- a/tests/unit_node/tls_test.ts +++ b/tests/unit_node/tls_test.ts @@ -1,19 +1,24 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assertEquals, assertInstanceOf } from "@std/assert"; +import { + assert, + assertEquals, + assertInstanceOf, + assertStringIncludes, + assertThrows, +} from "@std/assert"; import { delay } from "@std/async/delay"; import { fromFileUrl, join } from "@std/path"; import * as tls from "node:tls"; import * as net from "node:net"; import * as stream from "node:stream"; +import { execCode } from "../unit/test_util.ts"; const tlsTestdataDir = fromFileUrl( new URL("../testdata/tls", import.meta.url), ); -const keyFile = join(tlsTestdataDir, "localhost.key"); -const certFile = join(tlsTestdataDir, "localhost.crt"); -const key = Deno.readTextFileSync(keyFile); -const cert = Deno.readTextFileSync(certFile); +const key = Deno.readTextFileSync(join(tlsTestdataDir, "localhost.key")); +const cert = Deno.readTextFileSync(join(tlsTestdataDir, "localhost.crt")); const rootCaCert = Deno.readTextFileSync(join(tlsTestdataDir, "RootCA.pem")); for ( @@ -27,13 +32,15 @@ for ( ) { Deno.test(`tls.connect sends correct ALPN: '${alpnServer}' + '${alpnClient}' = '${expected}'`, async () => { const listener = Deno.listenTls({ + hostname: "localhost", port: 0, key, cert, alpnProtocols: alpnServer, }); const outgoing = tls.connect({ - host: "localhost", + host: "::1", + servername: "localhost", port: listener.addr.port, ALPNProtocols: alpnClient, secureContext: { @@ -56,6 +63,7 @@ Deno.test("tls.connect makes tls connection", async () => { const ctl = new AbortController(); let port; const serve = Deno.serve({ + hostname: "localhost", port: 0, key, cert, @@ -66,7 +74,8 @@ Deno.test("tls.connect makes tls connection", async () => { await delay(200); const conn = tls.connect({ - host: "localhost", + host: "::1", + servername: "localhost", port, secureContext: { ca: rootCaCert, @@ -97,6 +106,7 @@ Deno.test("tls.connect mid-read tcp->tls upgrade", async () => { const { promise, resolve } = Promise.withResolvers(); const ctl = new AbortController(); const serve = Deno.serve({ + hostname: "localhost", port: 8443, key, cert, @@ -106,7 +116,8 @@ Deno.test("tls.connect mid-read tcp->tls upgrade", async () => { await delay(200); const conn = tls.connect({ - host: "localhost", + host: "::1", + servername: "localhost", port: 8443, secureContext: { ca: rootCaCert, @@ -144,10 +155,12 @@ Deno.test("tls.createServer creates a TLS server", async () => { }, ); server.listen(0, async () => { - const conn = await Deno.connectTls({ - hostname: "127.0.0.1", + const tcpConn = await Deno.connect({ // deno-lint-ignore no-explicit-any port: (server.address() as any).port, + }); + const conn = await Deno.startTls(tcpConn, { + hostname: "localhost", caCerts: [rootCaCert], }); @@ -191,3 +204,62 @@ Deno.test("tlssocket._handle._parentWrap is set", () => { ._parentWrap; assertInstanceOf(parentWrap, stream.PassThrough); }); + +Deno.test("tls.connect() throws InvalidData when there's error in certificate", async () => { + // Uses execCode to avoid `--unsafely-ignore-certificate-errors` option applied + const [status, output] = await execCode(` + import tls from "node:tls"; + const conn = tls.connect({ + host: "localhost", + port: 4557, + }); + + conn.on("error", (err) => { + console.log(err); + }); + `); + + assertEquals(status, 0); + assertStringIncludes( + output, + "InvalidData: invalid peer certificate: UnknownIssuer", + ); +}); + +Deno.test("tls.rootCertificates is not empty", () => { + assert(tls.rootCertificates.length > 0); + assert(Object.isFrozen(tls.rootCertificates)); + assert(tls.rootCertificates instanceof Array); + assert(tls.rootCertificates.every((cert) => typeof cert === "string")); + assertThrows(() => { + (tls.rootCertificates as string[]).push("new cert"); + }, TypeError); +}); + +Deno.test("TLSSocket.alpnProtocol is set for client", async () => { + const listener = Deno.listenTls({ + hostname: "localhost", + port: 0, + key, + cert, + alpnProtocols: ["a"], + }); + const outgoing = tls.connect({ + host: "::1", + servername: "localhost", + port: listener.addr.port, + ALPNProtocols: ["a"], + secureContext: { + ca: rootCaCert, + // deno-lint-ignore no-explicit-any + } as any, + }); + + const conn = await listener.accept(); + const handshake = await conn.handshake(); + assertEquals(handshake.alpnProtocol, "a"); + conn.close(); + outgoing.destroy(); + listener.close(); + await new Promise((resolve) => outgoing.on("close", resolve)); +}); diff --git a/tests/unit_node/tty_test.ts b/tests/unit_node/tty_test.ts index 7f0395682d..df2888ddd0 100644 --- a/tests/unit_node/tty_test.ts +++ b/tests/unit_node/tty_test.ts @@ -7,12 +7,9 @@ import tty from "node:tty"; import process from "node:process"; Deno.test("[node/tty isatty] returns true when fd is a tty, false otherwise", () => { - assert(Deno.stdin.isTerminal() === isatty(Deno.stdin.rid)); - assert(Deno.stdout.isTerminal() === isatty(Deno.stdout.rid)); - assert(Deno.stderr.isTerminal() === isatty(Deno.stderr.rid)); - - using file = Deno.openSync("README.md"); - assert(!isatty(file.rid)); + assert(Deno.stdin.isTerminal() === isatty((Deno as any).stdin.rid)); + assert(Deno.stdout.isTerminal() === isatty((Deno as any).stdout.rid)); + assert(Deno.stderr.isTerminal() === isatty((Deno as any).stderr.rid)); }); Deno.test("[node/tty isatty] returns false for irrelevant values", () => { diff --git a/tests/unit_node/util_test.ts b/tests/unit_node/util_test.ts index 2b639538cb..6267018b12 100644 --- a/tests/unit_node/util_test.ts +++ b/tests/unit_node/util_test.ts @@ -330,3 +330,31 @@ Deno.test("[util] debuglog() and debug()", () => { assertEquals(util.debuglog, util.debug); assertEquals(utilDefault.debuglog, utilDefault.debug); }); + +Deno.test("[util] aborted()", async () => { + const abortController = new AbortController(); + let done = false; + const promise = util.aborted( + // deno-lint-ignore no-explicit-any + abortController.signal as any, + abortController.signal, + ); + promise.then(() => { + done = true; + }); + await new Promise((r) => setTimeout(r, 100)); + assertEquals(done, false); + abortController.abort(); + await promise; + assertEquals(done, true); +}); + +Deno.test("[util] styleText()", () => { + const redText = util.styleText("red", "error"); + assertEquals(redText, "\x1B[31merror\x1B[39m"); +}); + +Deno.test("[util] styleText() with array of formats", () => { + const colored = util.styleText(["red", "green"], "error"); + assertEquals(colored, "\x1b[32m\x1b[31merror\x1b[39m\x1b[39m"); +}); diff --git a/tests/unit_node/wasi_test.ts b/tests/unit_node/wasi_test.ts new file mode 100644 index 0000000000..6af2d4b1db --- /dev/null +++ b/tests/unit_node/wasi_test.ts @@ -0,0 +1,7 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +import wasi from "node:wasi"; +import { assertThrows } from "@std/assert"; + +Deno.test("[node/wasi] - WASI should throw (not implemented)", () => { + assertThrows(() => new wasi.WASI()); +}); diff --git a/tests/unit_node/worker_threads_test.ts b/tests/unit_node/worker_threads_test.ts index d9fe9f77d5..24a9107898 100644 --- a/tests/unit_node/worker_threads_test.ts +++ b/tests/unit_node/worker_threads_test.ts @@ -590,3 +590,235 @@ Deno.test({ channel.port2.close(); }, }); + +Deno.test({ + name: "[node/worker_threads] Emits online event", + async fn() { + const worker = new workerThreads.Worker( + ` + import { parentPort } from "node:worker_threads"; + const p = Promise.withResolvers(); + let ok = false; + parentPort.on("message", () => { + ok = true; + p.resolve(); + }); + await Promise.race([p.promise, new Promise(resolve => setTimeout(resolve, 20000))]); + if (ok) { + parentPort.postMessage("ok"); + } else { + parentPort.postMessage("timed out"); + } + `, + { + eval: true, + }, + ); + worker.on("online", () => { + worker.postMessage("ok"); + }); + assertEquals((await once(worker, "message"))[0], "ok"); + worker.terminate(); + }, +}); + +Deno.test({ + name: "[node/worker_threads] receiveMessageOnPort doesn't exit receive loop", + async fn() { + const worker = new workerThreads.Worker( + ` + import { parentPort, receiveMessageOnPort } from "node:worker_threads"; + parentPort.on("message", (msg) => { + const port = msg.port; + port.on("message", (msg2) => { + if (msg2 === "c") { + port.postMessage("done"); + port.unref(); + parentPort.unref(); + } + }); + parentPort.postMessage("ready"); + const msg2 = receiveMessageOnPort(port); + }); + `, + { eval: true }, + ); + + const { port1, port2 } = new workerThreads.MessageChannel(); + + worker.postMessage({ port: port2 }, [port2]); + + const done = Promise.withResolvers(); + + port1.on("message", (msg) => { + assertEquals(msg, "done"); + worker.unref(); + port1.close(); + done.resolve(true); + }); + worker.on("message", (msg) => { + assertEquals(msg, "ready"); + port1.postMessage("a"); + port1.postMessage("b"); + port1.postMessage("c"); + }); + + const timeout = setTimeout(() => { + fail("Test timed out"); + }, 20_000); + try { + const result = await done.promise; + assertEquals(result, true); + } finally { + clearTimeout(timeout); + } + }, +}); + +Deno.test({ + name: "[node/worker_threads] MessagePort.unref doesn't exit receive loop", + async fn() { + const worker = new workerThreads.Worker( + ` + import { parentPort } from "node:worker_threads"; + const assertEquals = (a, b) => { + if (a !== b) { + throw new Error(); + } + }; + let state = 0; + parentPort.on("message", (msg) => { + const port = msg.port; + const expect = ["a", "b", "c"]; + port.on("message", (msg2) => { + assertEquals(msg2, expect[state++]); + if (msg2 === "c") { + port.postMessage({ type: "done", got: msg2 }); + parentPort.unref(); + } + }); + port.unref(); + parentPort.postMessage("ready"); + }); + `, + { eval: true }, + ); + + const { port1, port2 } = new workerThreads.MessageChannel(); + + const done = Promise.withResolvers(); + + port1.on("message", (msg) => { + assertEquals(msg.type, "done"); + assertEquals(msg.got, "c"); + worker.unref(); + port1.close(); + done.resolve(true); + }); + worker.on("message", (msg) => { + assertEquals(msg, "ready"); + port1.postMessage("a"); + port1.postMessage("b"); + port1.postMessage("c"); + }); + worker.postMessage({ port: port2 }, [port2]); + + const timeout = setTimeout(() => { + fail("Test timed out"); + }, 20_000); + try { + const result = await done.promise; + assertEquals(result, true); + } finally { + clearTimeout(timeout); + } + }, +}); + +Deno.test({ + name: "[node/worker_threads] npm:piscina wait loop hang regression", + async fn() { + const worker = new workerThreads.Worker( + ` + import { assert, assertEquals } from "@std/assert"; + import { parentPort, receiveMessageOnPort } from "node:worker_threads"; + + assert(parentPort !== null); + + let currentTasks = 0; + let lastSeen = 0; + + parentPort.on("message", (msg) => { + (async () => { + assert(typeof msg === "object" && msg !== null); + assert(msg.buf !== undefined); + assert(msg.port !== undefined); + const { buf, port } = msg; + port.postMessage("ready"); + port.on("message", (msg) => onMessage(msg, buf, port)); + atomicsWaitLoop(buf, port); + })(); + }); + + function onMessage(msg, buf, port) { + currentTasks++; + (async () => { + assert(msg.taskName !== undefined); + port.postMessage({ type: "response", taskName: msg.taskName }); + currentTasks--; + atomicsWaitLoop(buf, port); + })(); + } + + function atomicsWaitLoop(buf, port) { + while (currentTasks === 0) { + Atomics.wait(buf, 0, lastSeen); + lastSeen = Atomics.load(buf, 0); + let task; + while ((task = receiveMessageOnPort(port)) !== undefined) { + onMessage(task.message, buf, port); + } + } + } + `, + { eval: true }, + ); + + const sab = new SharedArrayBuffer(4); + const buf = new Int32Array(sab); + const { port1, port2 } = new workerThreads.MessageChannel(); + + const done = Promise.withResolvers(); + + port1.unref(); + + worker.postMessage({ + type: "init", + buf, + port: port2, + }, [port2]); + + let count = 0; + port1.on("message", (msg) => { + if (count++ === 0) { + assertEquals(msg, "ready"); + } else { + assertEquals(msg.type, "response"); + port1.close(); + done.resolve(true); + } + }); + + port1.postMessage({ + taskName: "doThing", + }); + + Atomics.add(buf, 0, 1); + Atomics.notify(buf, 0, 1); + + worker.unref(); + + const result = await done.promise; + assertEquals(result, true); + }, +}); diff --git a/tests/util/server/Cargo.toml b/tests/util/server/Cargo.toml index a321501b85..aee7ef0be6 100644 --- a/tests/util/server/Cargo.toml +++ b/tests/util/server/Cargo.toml @@ -35,7 +35,7 @@ lazy-regex.workspace = true libc.workspace = true lsp-types.workspace = true monch.workspace = true -nix.workspace = true +nix = { workspace = true, features = ["fs", "term", "signal"] } once_cell.workspace = true os_pipe.workspace = true parking_lot.workspace = true diff --git a/tests/util/server/src/builders.rs b/tests/util/server/src/builders.rs index 698543f507..3bf5c704a1 100644 --- a/tests/util/server/src/builders.rs +++ b/tests/util/server/src/builders.rs @@ -78,6 +78,7 @@ impl DiagnosticLogger { logger.write_all(text.as_ref().as_bytes()).unwrap(); logger.write_all(b"\n").unwrap(); } + #[allow(clippy::print_stderr)] None => eprintln!("{}", text.as_ref()), } } @@ -208,11 +209,6 @@ impl TestContextBuilder { self } - pub fn add_future_env_vars(mut self) -> Self { - self = self.env("DENO_FUTURE", "1"); - self - } - pub fn add_jsr_env_vars(mut self) -> Self { for (key, value) in env_vars_for_jsr_tests() { self = self.env(key, value); diff --git a/tests/util/server/src/fs.rs b/tests/util/server/src/fs.rs index fc27e44859..7feb0799ae 100644 --- a/tests/util/server/src/fs.rs +++ b/tests/util/server/src/fs.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use lsp_types::Uri; use pretty_assertions::assert_eq; use std::borrow::Cow; use std::collections::HashSet; @@ -10,12 +11,13 @@ use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::process::Command; +use std::str::FromStr; use std::sync::Arc; use anyhow::Context; -use lsp_types::Url; use serde::de::DeserializeOwned; use serde::Serialize; +use url::Url; use crate::assertions::assert_wildcard_match; use crate::testdata_path; @@ -52,14 +54,22 @@ impl PathRef { PathRef(self.as_path().parent().unwrap().to_path_buf()) } - pub fn uri_dir(&self) -> Url { + pub fn url_dir(&self) -> Url { Url::from_directory_path(self.as_path()).unwrap() } - pub fn uri_file(&self) -> Url { + pub fn url_file(&self) -> Url { Url::from_file_path(self.as_path()).unwrap() } + pub fn uri_dir(&self) -> Uri { + Uri::from_str(self.url_dir().as_str()).unwrap() + } + + pub fn uri_file(&self) -> Uri { + Uri::from_str(self.url_file().as_str()).unwrap() + } + pub fn as_path(&self) -> &Path { self.0.as_path() } @@ -275,7 +285,10 @@ impl PathRef { #[track_caller] pub fn assert_matches_file(&self, wildcard_file: impl AsRef) -> &Self { let wildcard_file = testdata_path().join(wildcard_file); - println!("output path {}", wildcard_file); + #[allow(clippy::print_stdout)] + { + println!("output path {}", wildcard_file); + } let expected_text = wildcard_file.read_to_string(); self.assert_matches_text(&expected_text) } @@ -444,10 +457,14 @@ impl TempDir { })) } - pub fn uri(&self) -> Url { + pub fn url(&self) -> Url { Url::from_directory_path(self.path()).unwrap() } + pub fn uri(&self) -> Uri { + Uri::from_str(self.url().as_str()).unwrap() + } + pub fn path(&self) -> &PathRef { self.0.path() } diff --git a/tests/util/server/src/lib.rs b/tests/util/server/src/lib.rs index f09e7c2249..67dbcd820c 100644 --- a/tests/util/server/src/lib.rs +++ b/tests/util/server/src/lib.rs @@ -1,8 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -#![allow(clippy::print_stdout)] -#![allow(clippy::print_stderr)] - use std::collections::HashMap; use std::env; use std::io::Write; @@ -48,7 +45,7 @@ pub use fs::TempDir; pub const PERMISSION_VARIANTS: [&str; 5] = ["read", "write", "env", "net", "run"]; -pub const PERMISSION_DENIED_PATTERN: &str = "PermissionDenied"; +pub const PERMISSION_DENIED_PATTERN: &str = "NotCapable"; static GUARD: Lazy> = Lazy::new(Default::default); @@ -302,12 +299,15 @@ async fn get_tcp_listener_stream( .collect::>(); // Eye catcher for HttpServerCount - println!("ready: {name} on {:?}", addresses); + #[allow(clippy::print_stdout)] + { + println!("ready: {name} on {:?}", addresses); + } futures::stream::select_all(listeners) } -pub const TEST_SERVERS_COUNT: usize = 30; +pub const TEST_SERVERS_COUNT: usize = 32; #[derive(Default)] struct HttpServerCount { @@ -345,7 +345,10 @@ struct HttpServerStarter { impl Default for HttpServerStarter { fn default() -> Self { - println!("test_server starting..."); + #[allow(clippy::print_stdout)] + { + println!("test_server starting..."); + } let mut test_server = Command::new(test_server_path()) .current_dir(testdata_path()) .stdout(Stdio::piped()) @@ -479,6 +482,7 @@ pub fn run_collect( } = prog.wait_with_output().expect("failed to wait on child"); let stdout = String::from_utf8(stdout).unwrap(); let stderr = String::from_utf8(stderr).unwrap(); + #[allow(clippy::print_stderr)] if expect_success != status.success() { eprintln!("stdout: <<<{stdout}>>>"); eprintln!("stderr: <<<{stderr}>>>"); @@ -539,6 +543,7 @@ pub fn run_and_collect_output_with_args( } = deno.wait_with_output().expect("failed to wait on child"); let stdout = String::from_utf8(stdout).unwrap(); let stderr = String::from_utf8(stderr).unwrap(); + #[allow(clippy::print_stderr)] if expect_success != status.success() { eprintln!("stdout: <<<{stdout}>>>"); eprintln!("stderr: <<<{stderr}>>>"); @@ -563,6 +568,7 @@ pub fn deno_cmd_with_deno_dir(deno_dir: &TempDir) -> TestCommandBuilder { .env("JSR_URL", jsr_registry_unset_url()) } +#[allow(clippy::print_stdout)] pub fn run_powershell_script_file( script_file_path: &str, args: Vec<&str>, @@ -654,6 +660,7 @@ impl<'a> CheckOutputIntegrationTest<'a> { } pub fn wildcard_match(pattern: &str, text: &str) -> bool { + #[allow(clippy::print_stderr)] match wildcard_match_detailed(pattern, text) { WildcardMatchResult::Success => true, WildcardMatchResult::Fail(debug_output) => { diff --git a/tests/util/server/src/lsp.rs b/tests/util/server/src/lsp.rs index b615ed4750..d34deb2161 100644 --- a/tests/util/server/src/lsp.rs +++ b/tests/util/server/src/lsp.rs @@ -21,7 +21,6 @@ use lsp_types::FoldingRangeClientCapabilities; use lsp_types::InitializeParams; use lsp_types::TextDocumentClientCapabilities; use lsp_types::TextDocumentSyncClientCapabilities; -use lsp_types::Url; use lsp_types::WorkspaceClientCapabilities; use once_cell::sync::Lazy; use parking_lot::Condvar; @@ -47,10 +46,12 @@ use std::process::ChildStdin; use std::process::ChildStdout; use std::process::Command; use std::process::Stdio; +use std::str::FromStr; use std::sync::mpsc; use std::sync::Arc; use std::time::Duration; use std::time::Instant; +use url::Url; static CONTENT_TYPE_REG: Lazy = lazy_regex::lazy_regex!(r"(?i)^content-length:\s+(\d+)"); @@ -156,6 +157,7 @@ impl LspStdoutReader { self.pending_messages.0.lock().len() } + #[allow(clippy::print_stderr)] pub fn output_pending_messages(&self) { let messages = self.pending_messages.0.lock(); eprintln!("{:?}", messages); @@ -234,7 +236,6 @@ impl InitializeParamsBuilder { name: "test-harness".to_string(), version: Some("1.0.0".to_string()), }), - root_uri: None, initialization_options: Some(config_as_options), capabilities: ClientCapabilities { text_document: Some(TextDocumentClientCapabilities { @@ -289,8 +290,10 @@ impl InitializeParamsBuilder { } } + #[allow(deprecated)] pub fn set_maybe_root_uri(&mut self, value: Option) -> &mut Self { - self.params.root_uri = value; + self.params.root_uri = + value.map(|v| lsp::Uri::from_str(v.as_str()).unwrap()); self } @@ -306,34 +309,6 @@ impl InitializeParamsBuilder { self } - pub fn enable_inlay_hints(&mut self) -> &mut Self { - let options = self.initialization_options_mut(); - options.insert( - "inlayHints".to_string(), - json!({ - "parameterNames": { - "enabled": "all" - }, - "parameterTypes": { - "enabled": true - }, - "variableTypes": { - "enabled": true - }, - "propertyDeclarationTypes": { - "enabled": true - }, - "functionLikeReturnTypes": { - "enabled": true - }, - "enumMemberValues": { - "enabled": true - } - }), - ); - self - } - pub fn disable_testing_api(&mut self) -> &mut Self { let obj = self .params @@ -599,6 +574,7 @@ impl LspClientBuilder { for line in stderr.lines() { match line { Ok(line) => { + #[allow(clippy::print_stderr)] if print_stderr { eprintln!("{}", line); } @@ -613,7 +589,10 @@ impl LspClientBuilder { continue; } Err(err) => { - eprintln!("failed to parse perf record: {:#}", err); + #[allow(clippy::print_stderr)] + { + eprintln!("failed to parse perf record: {:#}", err); + } } } } @@ -808,11 +787,14 @@ impl LspClient { std::thread::sleep(Duration::from_millis(20)); } - eprintln!("==== STDERR OUTPUT ===="); - for line in found_lines { - eprintln!("{}", line) + #[allow(clippy::print_stderr)] + { + eprintln!("==== STDERR OUTPUT ===="); + for line in found_lines { + eprintln!("{}", line) + } + eprintln!("== END STDERR OUTPUT =="); } - eprintln!("== END STDERR OUTPUT =="); panic!("Timed out waiting on condition.") } @@ -871,7 +853,7 @@ impl LspClient { mut config: Value, ) { let mut builder = InitializeParamsBuilder::new(config.clone()); - builder.set_root_uri(self.root_dir.uri_dir()); + builder.set_root_uri(self.root_dir.url_dir()); do_build(&mut builder); let params: InitializeParams = builder.build(); // `config` must be updated to account for the builder changes. @@ -1234,7 +1216,7 @@ impl CollectedDiagnostics { self .all_messages() .iter() - .filter(|p| p.uri == *specifier) + .filter(|p| p.uri.as_str() == specifier.as_str()) .flat_map(|p| p.diagnostics.iter()) .cloned() .collect() @@ -1272,7 +1254,7 @@ impl CollectedDiagnostics { .all_messages() .iter() .find(|p| { - p.uri == specifier + p.uri.as_str() == specifier.as_str() && p .diagnostics .iter() @@ -1301,8 +1283,13 @@ impl SourceFile { let lang = match path.as_path().extension().unwrap().to_str().unwrap() { "js" => "javascript", "ts" | "d.ts" => "typescript", + "jsx" => "javascriptreact", + "tsx" => "typescriptreact", "json" => "json", "md" => "markdown", + "html" => "html", + "css" => "css", + "yaml" => "yaml", other => panic!("unsupported file extension: {other}"), }; Self { @@ -1321,7 +1308,11 @@ impl SourceFile { range_of_nth(n, text, &self.src) } - pub fn uri(&self) -> lsp::Url { + pub fn url(&self) -> Url { + self.path.url_file() + } + + pub fn uri(&self) -> lsp::Uri { self.path.uri_file() } diff --git a/tests/util/server/src/npm.rs b/tests/util/server/src/npm.rs index f1c341738a..31686fa854 100644 --- a/tests/util/server/src/npm.rs +++ b/tests/util/server/src/npm.rs @@ -18,6 +18,7 @@ use crate::PathRef; pub const DENOTEST_SCOPE_NAME: &str = "@denotest"; pub const DENOTEST2_SCOPE_NAME: &str = "@denotest2"; +pub const DENOTEST3_SCOPE_NAME: &str = "@denotest3"; pub static PUBLIC_TEST_NPM_REGISTRY: Lazy = Lazy::new(|| { TestNpmRegistry::new( @@ -54,6 +55,18 @@ pub static PRIVATE_TEST_NPM_REGISTRY_2: Lazy = ) }); +pub static PRIVATE_TEST_NPM_REGISTRY_3: Lazy = + Lazy::new(|| { + TestNpmRegistry::new( + NpmRegistryKind::Private, + &format!( + "http://localhost:{}", + crate::servers::PRIVATE_NPM_REGISTRY_3_PORT + ), + "npm-private3", + ) + }); + pub enum NpmRegistryKind { Public, Private, @@ -161,6 +174,17 @@ impl TestNpmRegistry { return Some((DENOTEST2_SCOPE_NAME, package_name_with_path)); } + let prefix1 = format!("/{}/", DENOTEST3_SCOPE_NAME); + let prefix2 = format!("/{}%2f", DENOTEST3_SCOPE_NAME); + + let maybe_package_name_with_path = uri_path + .strip_prefix(&prefix1) + .or_else(|| uri_path.strip_prefix(&prefix2)); + + if let Some(package_name_with_path) = maybe_package_name_with_path { + return Some((DENOTEST3_SCOPE_NAME, package_name_with_path)); + } + None } } diff --git a/tests/util/server/src/pty.rs b/tests/util/server/src/pty.rs index 5d8049fee9..07659262cf 100644 --- a/tests/util/server/src/pty.rs +++ b/tests/util/server/src/pty.rs @@ -61,7 +61,10 @@ impl Pty { if is_windows && *IS_CI { // the pty tests don't really start up on the windows CI for some reason // so ignore them for now - eprintln!("Ignoring windows CI."); + #[allow(clippy::print_stderr)] + { + eprintln!("Ignoring windows CI."); + } false } else { true @@ -250,11 +253,14 @@ impl Pty { } let text = self.next_text(); - eprintln!( - "------ Start Full Text ------\n{:?}\n------- End Full Text -------", - String::from_utf8_lossy(&self.read_bytes) - ); - eprintln!("Next text: {:?}", text); + #[allow(clippy::print_stderr)] + { + eprintln!( + "------ Start Full Text ------\n{:?}\n------- End Full Text -------", + String::from_utf8_lossy(&self.read_bytes) + ); + eprintln!("Next text: {:?}", text); + } false } @@ -297,10 +303,12 @@ fn setup_pty(fd: i32) { use nix::sys::termios::tcsetattr; use nix::sys::termios::SetArg; - let mut term = tcgetattr(fd).unwrap(); + // SAFETY: Nix crate requires value to implement the AsFd trait + let as_fd = unsafe { std::os::fd::BorrowedFd::borrow_raw(fd) }; + let mut term = tcgetattr(as_fd).unwrap(); // disable cooked mode term.local_flags.remove(termios::LocalFlags::ICANON); - tcsetattr(fd, SetArg::TCSANOW, &term).unwrap(); + tcsetattr(as_fd, SetArg::TCSANOW, &term).unwrap(); // turn on non-blocking mode so we get timeouts let flags = fcntl(fd, FcntlArg::F_GETFL).unwrap(); diff --git a/tests/util/server/src/servers/hyper_utils.rs b/tests/util/server/src/servers/hyper_utils.rs index c2db7ea668..8e01151ed4 100644 --- a/tests/util/server/src/servers/hyper_utils.rs +++ b/tests/util/server/src/servers/hyper_utils.rs @@ -42,7 +42,10 @@ where let fut: Pin>>> = async move { let listener = TcpListener::bind(options.addr).await?; - println!("ready: {}", options.addr); + #[allow(clippy::print_stdout)] + { + println!("ready: {}", options.addr); + } loop { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); @@ -58,6 +61,7 @@ where if let Err(e) = fut.await { let err_str = e.to_string(); + #[allow(clippy::print_stderr)] if !err_str.contains("early eof") { eprintln!("{}: {:?}", options.error_msg, e); } @@ -89,6 +93,7 @@ pub async fn run_server_with_acceptor<'a, A, F, S>( if let Err(e) = fut.await { let err_str = e.to_string(); + #[allow(clippy::print_stderr)] if !err_str.contains("early eof") { eprintln!("{}: {:?}", error_msg, e); } @@ -135,6 +140,7 @@ async fn hyper_serve_connection( if let Err(e) = result { let err_str = e.to_string(); + #[allow(clippy::print_stderr)] if !err_str.contains("early eof") { eprintln!("{}: {:?}", error_msg, e); } diff --git a/tests/util/server/src/servers/mod.rs b/tests/util/server/src/servers/mod.rs index 3e18aafce4..6c960ce522 100644 --- a/tests/util/server/src/servers/mod.rs +++ b/tests/util/server/src/servers/mod.rs @@ -91,6 +91,7 @@ const PROVENANCE_MOCK_SERVER_PORT: u16 = 4251; pub(crate) const PUBLIC_NPM_REGISTRY_PORT: u16 = 4260; pub(crate) const PRIVATE_NPM_REGISTRY_1_PORT: u16 = 4261; pub(crate) const PRIVATE_NPM_REGISTRY_2_PORT: u16 = 4262; +pub(crate) const PRIVATE_NPM_REGISTRY_3_PORT: u16 = 4263; // Use the single-threaded scheduler. The hyper server is used as a point of // comparison for the (single-threaded!) benchmarks in cli/bench. We're not @@ -143,6 +144,8 @@ pub async fn run_all_servers() { npm_registry::private_npm_registry1(PRIVATE_NPM_REGISTRY_1_PORT); let private_npm_registry_2_server_futs = npm_registry::private_npm_registry2(PRIVATE_NPM_REGISTRY_2_PORT); + let private_npm_registry_3_server_futs = + npm_registry::private_npm_registry3(PRIVATE_NPM_REGISTRY_3_PORT); let mut futures = vec![ redirect_server_fut.boxed_local(), @@ -173,6 +176,7 @@ pub async fn run_all_servers() { futures.extend(npm_registry_server_futs); futures.extend(private_npm_registry_1_server_futs); futures.extend(private_npm_registry_2_server_futs); + futures.extend(private_npm_registry_3_server_futs); assert_eq!(futures.len(), TEST_SERVERS_COUNT); @@ -194,7 +198,6 @@ fn json_body(value: serde_json::Value) -> UnsyncBoxBody { /// Benchmark server that just serves "hello world" responses. async fn hyper_hello(port: u16) { - println!("hyper hello"); let addr = SocketAddr::from(([127, 0, 0, 1], port)); let handler = move |_: Request| async move { Ok::<_, anyhow::Error>(Response::new(UnsyncBoxBody::new( @@ -338,7 +341,10 @@ async fn get_tcp_listener_stream( .collect::>(); // Eye catcher for HttpServerCount - println!("ready: {name} on {:?}", addresses); + #[allow(clippy::print_stdout)] + { + println!("ready: {name} on {:?}", addresses); + } futures::stream::select_all(listeners) } @@ -354,7 +360,10 @@ async fn run_tls_client_auth_server(port: u16) { while let Some(Ok(mut tls_stream)) = tls.next().await { tokio::spawn(async move { let Ok(handshake) = tls_stream.handshake().await else { - eprintln!("Failed to handshake"); + #[allow(clippy::print_stderr)] + { + eprintln!("Failed to handshake"); + } return; }; // We only need to check for the presence of client certificates @@ -401,7 +410,6 @@ async fn absolute_redirect( .collect(); if let Some(url) = query_params.get("redirect_to") { - println!("URL: {url:?}"); let redirect = redirect_resp(url.to_owned()); return Ok(redirect); } @@ -409,7 +417,6 @@ async fn absolute_redirect( if path.starts_with("/REDIRECT") { let url = &req.uri().path()[9..]; - println!("URL: {url:?}"); let redirect = redirect_resp(url.to_string()); return Ok(redirect); } @@ -1353,6 +1360,7 @@ async fn wrap_client_auth_https_server(port: u16) { // here. Rusttls ensures that they are valid and signed by the CA. match handshake.has_peer_certificates { true => { yield Ok(tls); }, + #[allow(clippy::print_stderr)] false => { eprintln!("https_client_auth: no valid client certificate"); }, }; } diff --git a/tests/util/server/src/servers/npm_registry.rs b/tests/util/server/src/servers/npm_registry.rs index acbd9cab48..4ada468fac 100644 --- a/tests/util/server/src/servers/npm_registry.rs +++ b/tests/util/server/src/servers/npm_registry.rs @@ -56,6 +56,14 @@ pub fn private_npm_registry2(port: u16) -> Vec> { ) } +pub fn private_npm_registry3(port: u16) -> Vec> { + run_npm_server( + port, + "npm private registry server error", + private_npm_registry3_handler, + ) +} + fn run_npm_server( port: u16, error_msg: &'static str, @@ -141,6 +149,13 @@ async fn private_npm_registry2_handler( handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_2).await } +async fn private_npm_registry3_handler( + req: Request, +) -> Result>, anyhow::Error> { + // No auth for this registry + handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_3).await +} + async fn handle_req_for_registry( req: Request, test_npm_registry: &npm::TestNpmRegistry, diff --git a/tests/util/server/src/servers/ws.rs b/tests/util/server/src/servers/ws.rs index 815119b6a1..dd4efbf659 100644 --- a/tests/util/server/src/servers/ws.rs +++ b/tests/util/server/src/servers/ws.rs @@ -76,6 +76,7 @@ pub async fn run_wss2_server(port: u16) { let server: Handshake<_, Bytes> = h2.handshake(tls); let mut server = match server.await { Ok(server) => server, + #[allow(clippy::print_stdout)] Err(e) => { println!("Failed to handshake h2: {e:?}"); return; @@ -87,6 +88,7 @@ pub async fn run_wss2_server(port: u16) { }; let (recv, send) = match conn { Ok(conn) => conn, + #[allow(clippy::print_stdout)] Err(e) => { println!("Failed to accept a connection: {e:?}"); break; @@ -137,6 +139,7 @@ where .map_err(|e| anyhow!("Error upgrading websocket connection: {}", e)) .unwrap(); + #[allow(clippy::print_stderr)] if let Err(e) = handler(ws).await { eprintln!("Error in websocket connection: {}", e); } @@ -152,6 +155,7 @@ where .serve_connection(io, service) .with_upgrades(); + #[allow(clippy::print_stderr)] if let Err(e) = conn.await { eprintln!("websocket server error: {e:?}"); } @@ -162,16 +166,19 @@ async fn handle_wss_stream( recv: Request, mut send: SendResponse, ) -> Result<(), h2::Error> { + #[allow(clippy::print_stderr)] if recv.method() != Method::CONNECT { eprintln!("wss2: refusing non-CONNECT stream"); send.send_reset(Reason::REFUSED_STREAM); return Ok(()); } + #[allow(clippy::print_stderr)] let Some(protocol) = recv.extensions().get::() else { eprintln!("wss2: refusing no-:protocol stream"); send.send_reset(Reason::REFUSED_STREAM); return Ok(()); }; + #[allow(clippy::print_stderr)] if protocol.as_str() != "websocket" && protocol.as_str() != "WebSocket" { eprintln!("wss2: refusing non-websocket stream"); send.send_reset(Reason::REFUSED_STREAM); diff --git a/tests/util/std b/tests/util/std index 3ee4c4dd43..c5d7930d57 160000 --- a/tests/util/std +++ b/tests/util/std @@ -1 +1 @@ -Subproject commit 3ee4c4dd43ad3a38d1b09aa981332fae1e593ab6 +Subproject commit c5d7930d5700dbbbedea607f9cf3e50acdc33e2d diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json index f59806feae..3477d8d9bf 100644 --- a/tests/wpt/runner/expectation.json +++ b/tests/wpt/runner/expectation.json @@ -6,46 +6,26 @@ "ecdh_bits.https.any.html": [ "P-521 good parameters", "P-521 mixed case parameters", - "P-521 with null length", "P-521 short result", "P-521 non-multiple of 8 bits", - "P-521 mismatched curves", - "P-521 public property of algorithm is not an ECDSA public key", "P-521 no deriveBits usage for base key", - "P-521 public property value is a private key", - "P-521 public property value is a secret key", "P-521 asking for too many bits" ], "ecdh_bits.https.any.worker.html": [ "P-521 good parameters", "P-521 mixed case parameters", - "P-521 with null length", "P-521 short result", "P-521 non-multiple of 8 bits", - "P-521 mismatched curves", - "P-521 public property of algorithm is not an ECDSA public key", "P-521 no deriveBits usage for base key", - "P-521 public property value is a private key", - "P-521 public property value is a secret key", "P-521 asking for too many bits" ], "ecdh_keys.https.any.html": [ "P-521 good parameters", - "P-521 mixed case parameters", - "P-521 mismatched curves", - "P-521 public property of algorithm is not an ECDSA public key", - "P-521 no deriveKey usage for base key", - "P-521 public property value is a private key", - "P-521 public property value is a secret key" + "P-521 mixed case parameters" ], "ecdh_keys.https.any.worker.html": [ "P-521 good parameters", - "P-521 mixed case parameters", - "P-521 mismatched curves", - "P-521 public property of algorithm is not an ECDSA public key", - "P-521 no deriveKey usage for base key", - "P-521 public property value is a private key", - "P-521 public property value is a secret key" + "P-521 mixed case parameters" ], "hkdf.https.any.html?1-1000": true, "hkdf.https.any.html?1001-2000": true, @@ -74,117 +54,65 @@ "pbkdf2.https.any.worker.html?7001-8000": true, "pbkdf2.https.any.worker.html?8001-last": true, "cfrg_curves_bits.https.any.html": [ - "X25519 key derivation checks for all-zero value result with a key of order 0", - "X25519 key derivation checks for all-zero value result with a key of order 1", - "X25519 key derivation checks for all-zero value result with a key of order 8", - "X25519 key derivation checks for all-zero value result with a key of order p-1 (order 2)", - "X25519 key derivation checks for all-zero value result with a key of order p (=0, order 4)", - "X25519 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)", "X448 key derivation checks for all-zero value result with a key of order 0", "X448 key derivation checks for all-zero value result with a key of order 1", "X448 key derivation checks for all-zero value result with a key of order p-1 (order 2)", "X448 key derivation checks for all-zero value result with a key of order p (=0, order 4)", "X448 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)", - "X25519 good parameters", - "X25519 mixed case parameters", - "X25519 with null length", - "X25519 short result", - "X25519 non-multiple of 8 bits", - "X25519 mismatched algorithms", - "X25519 no deriveBits usage for base key", "X448 good parameters", "X448 mixed case parameters", - "X448 with null length", "X448 short result", "X448 non-multiple of 8 bits", "X448 mismatched algorithms", "X448 no deriveBits usage for base key", - "X448 base key is not a private key", "X448 public property value is a private key", "X448 public property value is a secret key", "X448 asking for too many bits" ], "cfrg_curves_bits.https.any.worker.html": [ - "X25519 key derivation checks for all-zero value result with a key of order 0", - "X25519 key derivation checks for all-zero value result with a key of order 1", - "X25519 key derivation checks for all-zero value result with a key of order 8", - "X25519 key derivation checks for all-zero value result with a key of order p-1 (order 2)", - "X25519 key derivation checks for all-zero value result with a key of order p (=0, order 4)", - "X25519 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)", "X448 key derivation checks for all-zero value result with a key of order 0", "X448 key derivation checks for all-zero value result with a key of order 1", "X448 key derivation checks for all-zero value result with a key of order p-1 (order 2)", "X448 key derivation checks for all-zero value result with a key of order p (=0, order 4)", "X448 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)", - "X25519 good parameters", - "X25519 mixed case parameters", - "X25519 with null length", - "X25519 short result", - "X25519 non-multiple of 8 bits", - "X25519 mismatched algorithms", - "X25519 no deriveBits usage for base key", "X448 good parameters", "X448 mixed case parameters", - "X448 with null length", "X448 short result", "X448 non-multiple of 8 bits", "X448 mismatched algorithms", "X448 no deriveBits usage for base key", - "X448 base key is not a private key", "X448 public property value is a private key", "X448 public property value is a secret key", "X448 asking for too many bits" ], "cfrg_curves_keys.https.any.html": [ - "X25519 deriveBits checks for all-zero value result with a key of order 0", - "X25519 deriveBits checks for all-zero value result with a key of order 1", - "X25519 deriveBits checks for all-zero value result with a key of order 8", - "X25519 deriveBits checks for all-zero value result with a key of order p-1 (order 2)", - "X25519 deriveBits checks for all-zero value result with a key of order p (=0, order 4)", - "X25519 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)", "X448 deriveBits checks for all-zero value result with a key of order 0", "X448 deriveBits checks for all-zero value result with a key of order 1", "X448 deriveBits checks for all-zero value result with a key of order p-1 (order 2)", "X448 deriveBits checks for all-zero value result with a key of order p (=0, order 4)", "X448 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)", - "Key derivation using a X25519 generated keys.", - "Key derivation using a X448 generated keys.", - "X25519 good parameters", - "X25519 mixed case parameters", - "X25519 mismatched algorithms", "X448 good parameters", "X448 mixed case parameters", "X448 mismatched algorithms", "X448 no deriveKey usage for base key", - "X448 base key is not a private key", "X448 public property value is a private key", "X448 public property value is a secret key" ], "cfrg_curves_keys.https.any.worker.html": [ - "X25519 deriveBits checks for all-zero value result with a key of order 0", - "X25519 deriveBits checks for all-zero value result with a key of order 1", - "X25519 deriveBits checks for all-zero value result with a key of order 8", - "X25519 deriveBits checks for all-zero value result with a key of order p-1 (order 2)", - "X25519 deriveBits checks for all-zero value result with a key of order p (=0, order 4)", - "X25519 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)", "X448 deriveBits checks for all-zero value result with a key of order 0", "X448 deriveBits checks for all-zero value result with a key of order 1", "X448 deriveBits checks for all-zero value result with a key of order p-1 (order 2)", "X448 deriveBits checks for all-zero value result with a key of order p (=0, order 4)", "X448 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)", - "Key derivation using a X25519 generated keys.", - "Key derivation using a X448 generated keys.", - "X25519 good parameters", - "X25519 mixed case parameters", - "X25519 mismatched algorithms", "X448 good parameters", "X448 mixed case parameters", "X448 mismatched algorithms", "X448 no deriveKey usage for base key", - "X448 base key is not a private key", "X448 public property value is a private key", "X448 public property value is a secret key" - ] + ], + "derived_bits_length.https.any.html": true, + "derived_bits_length.https.any.worker.html": true }, "digest": { "digest.https.any.html": true, @@ -829,734 +757,62 @@ ], "failures_X25519.https.any.html": true, "failures_X25519.https.any.worker.html": true, - "failures_X448.https.any.html": [ - "Bad usages: generateKey({name: X448}, true, [encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])", - "Bad usages: generateKey({name: X448}, true, [decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])", - "Bad usages: generateKey({name: X448}, true, [sign])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])", - "Bad usages: generateKey({name: X448}, true, [verify])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])", - "Bad usages: generateKey({name: X448}, true, [wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])", - "Empty usages: generateKey({name: X448}, false, [])", - "Empty usages: generateKey({name: X448}, true, [])" - ], - "failures_X448.https.any.worker.html": [ - "Bad usages: generateKey({name: X448}, true, [encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, encrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])", - "Bad usages: generateKey({name: X448}, true, [decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, decrypt])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])", - "Bad usages: generateKey({name: X448}, true, [sign])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, sign])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])", - "Bad usages: generateKey({name: X448}, true, [verify])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, verify])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])", - "Bad usages: generateKey({name: X448}, true, [wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])", - "Bad usages: generateKey({name: X448}, true, [unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveBits, unwrapKey])", - "Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])", - "Empty usages: generateKey({name: X448}, false, [])", - "Empty usages: generateKey({name: X448}, true, [])" - ], + "failures_X448.https.any.html": true, + "failures_X448.https.any.worker.html": true, "successes_Ed25519.https.any.html": true, "successes_Ed25519.https.any.worker.html": true, "successes_Ed448.https.any.html": false, "successes_Ed448.https.any.worker.html": false, "successes_X25519.https.any.html": true, "successes_X25519.https.any.worker.html": true, - "successes_X448.https.any.html": false, - "successes_X448.https.any.worker.html": false + "successes_X448.https.any.html": true, + "successes_X448.https.any.worker.html": true }, "historical.any.html": false, "historical.any.worker.html": false, "idlharness.https.any.html": [ - "Window interface: attribute crypto", - "SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)" + "Window interface: attribute crypto" ], "idlharness.https.any.worker.html": [ - "WorkerGlobalScope interface: attribute crypto", - "SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)" + "WorkerGlobalScope interface: attribute crypto" ], "import_export": { "ec_importKey.https.any.html": [ - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDSA, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDSA, namedCurve: P-256}, false, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-256}, false, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-384}, false, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [sign])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [sign, sign])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [sign])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [sign, sign])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDH, namedCurve: P-256}, false, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-256}, false, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDH, namedCurve: P-384}, false, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [])" + "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" ], "ec_importKey.https.any.worker.html": [ - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDSA, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDSA, namedCurve: P-256}, false, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-256}, false, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-384}, false, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [sign])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [sign, sign])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, false, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [sign])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [sign, sign])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, false, [])", - "Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, true, [])", - "Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-256}, true, [])", - "Empty Usages: P-256 bits (pkcs8, buffer(138), {name: ECDH, namedCurve: P-256}, false, [])", - "Empty Usages: P-256 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-256}, false, [])", - "Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, true, [])", - "Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, true, [])", - "Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDH, namedCurve: P-384}, false, [])", - "Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [])", - "Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])", "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveKey])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveBits])", - "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [])" - ], - "rsa_importKey.https.any.html": [ - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])" - ], - "rsa_importKey.https.any.worker.html": [ - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-OAEP}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSA-PSS}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 1024 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 1024 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 2048 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 2048 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [])", - "Empty Usages: 4096 bits (pkcs8, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])", - "Empty Usages: 4096 bits (jwk, object(spki, pkcs8, jwk), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, false, [])" - ], - "symmetric_importKey.https.any.html": [ - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CTR, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CTR, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CBC, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CBC, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128GCM, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128GCM, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128KW, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128KW, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])" - ], - "symmetric_importKey.https.any.worker.html": [ - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CTR, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CTR, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CTR}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CTR}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CTR, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CTR}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CBC, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128CBC, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CBC}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-CBC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256CBC, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-CBC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128GCM, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128GCM, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-GCM}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-GCM}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256GCM, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-GCM}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 128 bits (jwk, {alg: A128KW, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: A128KW, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 192 bits (jwk, {alg: A192KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: A192KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, true, [])", - "Empty Usages: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, true, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 128 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 192 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 256 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [])", - "Empty Usages: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])", - "Empty Usages: 192 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])", - "Empty Usages: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: PBKDF2}, false, [])" + "Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" ], + "rsa_importKey.https.any.html": true, + "rsa_importKey.https.any.worker.html": true, + "symmetric_importKey.https.any.html": true, + "symmetric_importKey.https.any.worker.html": true, "okp_importKey.https.any.html": [ "Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, true, [verify])", "Good parameters: Ed448 bits (jwk, object(kty, crv, x), {name: Ed448}, true, [verify])", @@ -1597,10 +853,6 @@ "Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])", "Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])", - "Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])", - "Good parameters with ignored JWK alg: X448 (jwk, object(kty, crv, x), {name: X448}, true, [])", - "Good parameters: X448 bits (raw, buffer(56), {name: X448}, true, [])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])", "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])", "Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])", @@ -1613,17 +865,10 @@ "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])", - "Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])", - "Good parameters: X448 bits (raw, buffer(56), {name: X448}, false, [])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])", - "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])" + "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])" ], "okp_importKey.https.any.worker.html": [ "Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, true, [verify])", @@ -1665,10 +910,6 @@ "Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])", "Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])", - "Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])", - "Good parameters with ignored JWK alg: X448 (jwk, object(kty, crv, x), {name: X448}, true, [])", - "Good parameters: X448 bits (raw, buffer(56), {name: X448}, true, [])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])", "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])", "Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])", @@ -1681,23 +922,12 @@ "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", "Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])", - "Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])", - "Good parameters: X448 bits (raw, buffer(56), {name: X448}, false, [])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])", "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])", - "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", - "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])" + "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])" ], "okp_importKey_failures_Ed25519.https.any.html": [ - "Empty usages: importKey(pkcs8, {name: Ed25519}, true, [])", - "Empty usages: importKey(pkcs8, {name: Ed25519}, false, [])", - "Empty usages: importKey(jwk(private), {name: Ed25519}, true, [])", - "Empty usages: importKey(jwk(private), {name: Ed25519}, false, [])", "Bad key length: importKey(raw, {name: Ed25519}, true, [verify])", "Bad key length: importKey(raw, {name: Ed25519}, false, [verify])", "Bad key length: importKey(raw, {name: Ed25519}, true, [verify, verify])", @@ -1710,10 +940,6 @@ "Invalid key pair: importKey(jwk(private), {name: Ed25519}, true, [sign, sign])" ], "okp_importKey_failures_Ed25519.https.any.worker.html": [ - "Empty usages: importKey(pkcs8, {name: Ed25519}, true, [])", - "Empty usages: importKey(pkcs8, {name: Ed25519}, false, [])", - "Empty usages: importKey(jwk(private), {name: Ed25519}, true, [])", - "Empty usages: importKey(jwk(private), {name: Ed25519}, false, [])", "Bad key length: importKey(raw, {name: Ed25519}, true, [verify])", "Bad key length: importKey(raw, {name: Ed25519}, false, [verify])", "Bad key length: importKey(raw, {name: Ed25519}, true, [verify, verify])", @@ -1728,10 +954,6 @@ "okp_importKey_failures_Ed448.https.any.html": false, "okp_importKey_failures_Ed448.https.any.worker.html": false, "okp_importKey_failures_X25519.https.any.html": [ - "Empty usages: importKey(pkcs8, {name: X25519}, true, [])", - "Empty usages: importKey(pkcs8, {name: X25519}, false, [])", - "Empty usages: importKey(jwk(private), {name: X25519}, true, [])", - "Empty usages: importKey(jwk(private), {name: X25519}, false, [])", "Bad key length: importKey(raw, {name: X25519}, true, [])", "Bad key length: importKey(raw, {name: X25519}, false, [])", "Bad key length: importKey(jwk (public) , {name: X25519}, true, [])", @@ -1758,10 +980,6 @@ "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" ], "okp_importKey_failures_X25519.https.any.worker.html": [ - "Empty usages: importKey(pkcs8, {name: X25519}, true, [])", - "Empty usages: importKey(pkcs8, {name: X25519}, false, [])", - "Empty usages: importKey(jwk(private), {name: X25519}, true, [])", - "Empty usages: importKey(jwk(private), {name: X25519}, false, [])", "Bad key length: importKey(raw, {name: X25519}, true, [])", "Bad key length: importKey(raw, {name: X25519}, false, [])", "Bad key length: importKey(jwk (public) , {name: X25519}, true, [])", @@ -1787,8 +1005,66 @@ "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits])", "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" ], - "okp_importKey_failures_X448.https.any.html": false, - "okp_importKey_failures_X448.https.any.worker.html": false + "okp_importKey_failures_X448.https.any.html": [ + "Empty usages: importKey(pkcs8, {name: X448}, true, [])", + "Empty usages: importKey(pkcs8, {name: X448}, false, [])", + "Bad key length: importKey(raw, {name: X448}, true, [])", + "Bad key length: importKey(raw, {name: X448}, false, [])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk (public) , {name: X448}, true, [])", + "Bad key length: importKey(jwk (public) , {name: X448}, false, [])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" + ], + "okp_importKey_failures_X448.https.any.worker.html": [ + "Empty usages: importKey(pkcs8, {name: X448}, true, [])", + "Empty usages: importKey(pkcs8, {name: X448}, false, [])", + "Bad key length: importKey(raw, {name: X448}, true, [])", + "Bad key length: importKey(raw, {name: X448}, false, [])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk (public) , {name: X448}, true, [])", + "Bad key length: importKey(jwk (public) , {name: X448}, false, [])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" + ], + "crashtests": { + "importKey-unsettled-promise.https.any.html": true, + "importKey-unsettled-promise.https.any.worker.html": true + } }, "randomUUID.https.any.html": true, "randomUUID.https.any.worker.html": true, @@ -1800,62 +1076,50 @@ "ECDSA P-384 with SHA-1 verification", "ECDSA P-384 with SHA-256 verification", "ECDSA P-384 with SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification", + "ECDSA P-521 with SHA-1 verification", + "ECDSA P-521 with SHA-256 verification", + "ECDSA P-521 with SHA-384 verification", + "ECDSA P-521 with SHA-512 verification", "ECDSA P-256 with SHA-1 verification with altered signature after call", "ECDSA P-256 with SHA-384 verification with altered signature after call", "ECDSA P-256 with SHA-512 verification with altered signature after call", "ECDSA P-384 with SHA-1 verification with altered signature after call", "ECDSA P-384 with SHA-256 verification with altered signature after call", "ECDSA P-384 with SHA-512 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification with altered signature after call", + "ECDSA P-521 with SHA-1 verification with altered signature after call", + "ECDSA P-521 with SHA-256 verification with altered signature after call", + "ECDSA P-521 with SHA-384 verification with altered signature after call", + "ECDSA P-521 with SHA-512 verification with altered signature after call", "ECDSA P-256 with SHA-1 with altered plaintext after call", "ECDSA P-256 with SHA-384 with altered plaintext after call", "ECDSA P-256 with SHA-512 with altered plaintext after call", "ECDSA P-384 with SHA-1 with altered plaintext after call", "ECDSA P-384 with SHA-256 with altered plaintext after call", "ECDSA P-384 with SHA-512 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-256 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-384 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-512 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-256 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-384 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-512 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-1 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-256 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-384 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-512 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-1 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-256 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-384 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-512 no verify usage", + "ECDSA P-521 with SHA-1 with altered plaintext after call", + "ECDSA P-521 with SHA-256 with altered plaintext after call", + "ECDSA P-521 with SHA-384 with altered plaintext after call", + "ECDSA P-521 with SHA-512 with altered plaintext after call", "ECDSA P-256 with SHA-1 round trip", "ECDSA P-256 with SHA-384 round trip", "ECDSA P-256 with SHA-512 round trip", "ECDSA P-384 with SHA-1 round trip", "ECDSA P-384 with SHA-256 round trip", "ECDSA P-384 with SHA-512 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-1 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-256 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-384 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-512 round trip", + "ECDSA P-521 with SHA-1 round trip", + "ECDSA P-521 with SHA-256 round trip", + "ECDSA P-521 with SHA-384 round trip", + "ECDSA P-521 with SHA-512 round trip", "ECDSA P-256 with SHA-1 verification failure due to altered signature", "ECDSA P-256 with SHA-384 verification failure due to altered signature", "ECDSA P-256 with SHA-512 verification failure due to altered signature", "ECDSA P-384 with SHA-1 verification failure due to altered signature", "ECDSA P-384 with SHA-256 verification failure due to altered signature", "ECDSA P-384 with SHA-512 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to altered signature", + "ECDSA P-521 with SHA-1 verification failure due to altered signature", + "ECDSA P-521 with SHA-256 verification failure due to altered signature", + "ECDSA P-521 with SHA-384 verification failure due to altered signature", + "ECDSA P-521 with SHA-512 verification failure due to altered signature", "ECDSA P-256 with SHA-256 verification failure due to wrong hash", "ECDSA P-256 with SHA-384 verification failure due to wrong hash", "ECDSA P-256 with SHA-512 verification failure due to wrong hash", @@ -1863,34 +1127,30 @@ "ECDSA P-384 with SHA-256 verification failure due to wrong hash", "ECDSA P-384 with SHA-384 verification failure due to wrong hash", "ECDSA P-384 with SHA-512 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to bad hash name", + "ECDSA P-521 with SHA-1 verification failure due to wrong hash", + "ECDSA P-521 with SHA-256 verification failure due to wrong hash", + "ECDSA P-521 with SHA-384 verification failure due to wrong hash", + "ECDSA P-521 with SHA-512 verification failure due to wrong hash", "ECDSA P-256 with SHA-1 verification failure due to shortened signature", "ECDSA P-256 with SHA-384 verification failure due to shortened signature", "ECDSA P-256 with SHA-512 verification failure due to shortened signature", "ECDSA P-384 with SHA-1 verification failure due to shortened signature", "ECDSA P-384 with SHA-256 verification failure due to shortened signature", "ECDSA P-384 with SHA-512 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to shortened signature", + "ECDSA P-521 with SHA-1 verification failure due to shortened signature", + "ECDSA P-521 with SHA-256 verification failure due to shortened signature", + "ECDSA P-521 with SHA-384 verification failure due to shortened signature", + "ECDSA P-521 with SHA-512 verification failure due to shortened signature", "ECDSA P-256 with SHA-1 verification failure due to altered plaintext", "ECDSA P-256 with SHA-384 verification failure due to altered plaintext", "ECDSA P-256 with SHA-512 verification failure due to altered plaintext", "ECDSA P-384 with SHA-1 verification failure due to altered plaintext", "ECDSA P-384 with SHA-256 verification failure due to altered plaintext", "ECDSA P-384 with SHA-512 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-1 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-256 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-384 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-512 verification failure due to altered plaintext", "ECDSA P-256 with SHA-1 - The signature was truncated by 1 byte verification", "ECDSA P-256 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", "ECDSA P-256 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", @@ -1933,42 +1193,34 @@ "ECDSA P-384 with SHA-512 - Signature has excess padding verification", "ECDSA P-384 with SHA-512 - The signature is empty verification", "ECDSA P-384 with SHA-512 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-256 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-384 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-512 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-1 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-256 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-384 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-512 verifying with wrong algorithm name" + "ECDSA P-521 with SHA-1 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-1 - Signature has excess padding verification", + "ECDSA P-521 with SHA-1 - The signature is empty verification", + "ECDSA P-521 with SHA-1 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-256 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-256 - Signature has excess padding verification", + "ECDSA P-521 with SHA-256 - The signature is empty verification", + "ECDSA P-521 with SHA-256 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-384 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-384 - Signature has excess padding verification", + "ECDSA P-521 with SHA-384 - The signature is empty verification", + "ECDSA P-521 with SHA-384 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-512 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-512 - Signature has excess padding verification", + "ECDSA P-521 with SHA-512 - The signature is empty verification", + "ECDSA P-521 with SHA-512 - The signature is all zeroes verification" ], "ecdsa.https.any.worker.html": [ "ECDSA P-256 with SHA-1 verification", @@ -1977,62 +1229,50 @@ "ECDSA P-384 with SHA-1 verification", "ECDSA P-384 with SHA-256 verification", "ECDSA P-384 with SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification", + "ECDSA P-521 with SHA-1 verification", + "ECDSA P-521 with SHA-256 verification", + "ECDSA P-521 with SHA-384 verification", + "ECDSA P-521 with SHA-512 verification", "ECDSA P-256 with SHA-1 verification with altered signature after call", "ECDSA P-256 with SHA-384 verification with altered signature after call", "ECDSA P-256 with SHA-512 verification with altered signature after call", "ECDSA P-384 with SHA-1 verification with altered signature after call", "ECDSA P-384 with SHA-256 verification with altered signature after call", "ECDSA P-384 with SHA-512 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification with altered signature after call", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification with altered signature after call", + "ECDSA P-521 with SHA-1 verification with altered signature after call", + "ECDSA P-521 with SHA-256 verification with altered signature after call", + "ECDSA P-521 with SHA-384 verification with altered signature after call", + "ECDSA P-521 with SHA-512 verification with altered signature after call", "ECDSA P-256 with SHA-1 with altered plaintext after call", "ECDSA P-256 with SHA-384 with altered plaintext after call", "ECDSA P-256 with SHA-512 with altered plaintext after call", "ECDSA P-384 with SHA-1 with altered plaintext after call", "ECDSA P-384 with SHA-256 with altered plaintext after call", "ECDSA P-384 with SHA-512 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-256 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-384 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-512 with altered plaintext after call", - "importVectorKeys step: ECDSA P-521 with SHA-1 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-256 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-384 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-512 using privateKey to verify", - "importVectorKeys step: ECDSA P-521 with SHA-1 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-256 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-384 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-512 using publicKey to sign", - "importVectorKeys step: ECDSA P-521 with SHA-1 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-256 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-384 no verify usage", - "importVectorKeys step: ECDSA P-521 with SHA-512 no verify usage", + "ECDSA P-521 with SHA-1 with altered plaintext after call", + "ECDSA P-521 with SHA-256 with altered plaintext after call", + "ECDSA P-521 with SHA-384 with altered plaintext after call", + "ECDSA P-521 with SHA-512 with altered plaintext after call", "ECDSA P-256 with SHA-1 round trip", "ECDSA P-256 with SHA-384 round trip", "ECDSA P-256 with SHA-512 round trip", "ECDSA P-384 with SHA-1 round trip", "ECDSA P-384 with SHA-256 round trip", "ECDSA P-384 with SHA-512 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-1 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-256 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-384 round trip", - "importVectorKeys step: ECDSA P-521 with SHA-512 round trip", + "ECDSA P-521 with SHA-1 round trip", + "ECDSA P-521 with SHA-256 round trip", + "ECDSA P-521 with SHA-384 round trip", + "ECDSA P-521 with SHA-512 round trip", "ECDSA P-256 with SHA-1 verification failure due to altered signature", "ECDSA P-256 with SHA-384 verification failure due to altered signature", "ECDSA P-256 with SHA-512 verification failure due to altered signature", "ECDSA P-384 with SHA-1 verification failure due to altered signature", "ECDSA P-384 with SHA-256 verification failure due to altered signature", "ECDSA P-384 with SHA-512 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to altered signature", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to altered signature", + "ECDSA P-521 with SHA-1 verification failure due to altered signature", + "ECDSA P-521 with SHA-256 verification failure due to altered signature", + "ECDSA P-521 with SHA-384 verification failure due to altered signature", + "ECDSA P-521 with SHA-512 verification failure due to altered signature", "ECDSA P-256 with SHA-256 verification failure due to wrong hash", "ECDSA P-256 with SHA-384 verification failure due to wrong hash", "ECDSA P-256 with SHA-512 verification failure due to wrong hash", @@ -2040,34 +1280,30 @@ "ECDSA P-384 with SHA-256 verification failure due to wrong hash", "ECDSA P-384 with SHA-384 verification failure due to wrong hash", "ECDSA P-384 with SHA-512 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to wrong hash", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to bad hash name", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to bad hash name", + "ECDSA P-521 with SHA-1 verification failure due to wrong hash", + "ECDSA P-521 with SHA-256 verification failure due to wrong hash", + "ECDSA P-521 with SHA-384 verification failure due to wrong hash", + "ECDSA P-521 with SHA-512 verification failure due to wrong hash", "ECDSA P-256 with SHA-1 verification failure due to shortened signature", "ECDSA P-256 with SHA-384 verification failure due to shortened signature", "ECDSA P-256 with SHA-512 verification failure due to shortened signature", "ECDSA P-384 with SHA-1 verification failure due to shortened signature", "ECDSA P-384 with SHA-256 verification failure due to shortened signature", "ECDSA P-384 with SHA-512 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to shortened signature", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to shortened signature", + "ECDSA P-521 with SHA-1 verification failure due to shortened signature", + "ECDSA P-521 with SHA-256 verification failure due to shortened signature", + "ECDSA P-521 with SHA-384 verification failure due to shortened signature", + "ECDSA P-521 with SHA-512 verification failure due to shortened signature", "ECDSA P-256 with SHA-1 verification failure due to altered plaintext", "ECDSA P-256 with SHA-384 verification failure due to altered plaintext", "ECDSA P-256 with SHA-512 verification failure due to altered plaintext", "ECDSA P-384 with SHA-1 verification failure due to altered plaintext", "ECDSA P-384 with SHA-256 verification failure due to altered plaintext", "ECDSA P-384 with SHA-512 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-1 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-256 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-384 verification failure due to altered plaintext", - "importVectorKeys step: ECDSA P-521 with SHA-512 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-1 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-256 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-384 verification failure due to altered plaintext", + "ECDSA P-521 with SHA-512 verification failure due to altered plaintext", "ECDSA P-256 with SHA-1 - The signature was truncated by 1 byte verification", "ECDSA P-256 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", "ECDSA P-256 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", @@ -2110,42 +1346,34 @@ "ECDSA P-384 with SHA-512 - Signature has excess padding verification", "ECDSA P-384 with SHA-512 - The signature is empty verification", "ECDSA P-384 with SHA-512 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-256 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-512 verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-384 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was truncated by 1 byte verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-1 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-256 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-384 verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - Signature has excess padding verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature is empty verification", - "importVectorKeys step: ECDSA P-521 with SHA-512 - The signature is all zeroes verification", - "importVectorKeys step: ECDSA P-521 with SHA-1 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-256 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-384 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-512 signing with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-1 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-256 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-384 verifying with wrong algorithm name", - "importVectorKeys step: ECDSA P-521 with SHA-512 verifying with wrong algorithm name" + "ECDSA P-521 with SHA-1 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-1 - The signature was made using SHA-1, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-1 - Signature has excess padding verification", + "ECDSA P-521 with SHA-1 - The signature is empty verification", + "ECDSA P-521 with SHA-1 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-256 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-256 - The signature was made using SHA-256, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-256 - Signature has excess padding verification", + "ECDSA P-521 with SHA-256 - The signature is empty verification", + "ECDSA P-521 with SHA-256 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-384 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-384 - The signature was made using SHA-384, however verification is being done using SHA-512 verification", + "ECDSA P-521 with SHA-384 - Signature has excess padding verification", + "ECDSA P-521 with SHA-384 - The signature is empty verification", + "ECDSA P-521 with SHA-384 - The signature is all zeroes verification", + "ECDSA P-521 with SHA-512 - The signature was truncated by 1 byte verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-1 verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-256 verification", + "ECDSA P-521 with SHA-512 - The signature was made using SHA-512, however verification is being done using SHA-384 verification", + "ECDSA P-521 with SHA-512 - Signature has excess padding verification", + "ECDSA P-521 with SHA-512 - The signature is empty verification", + "ECDSA P-521 with SHA-512 - The signature is all zeroes verification" ], "hmac.https.any.html": true, "hmac.https.any.worker.html": true, @@ -2166,13 +1394,7 @@ "EdDSA Ed448 verification failure due to altered signature", "EdDSA Ed448 verification failure due to shortened signature", "EdDSA Ed448 verification failure due to altered data", - "Sign and verify using generated Ed448 keys.", - "Ed25519 Verification checks with small-order key of order - Test 0", - "Ed25519 Verification checks with small-order key of order - Test 1", - "Ed25519 Verification checks with small-order key of order - Test 2", - "Ed25519 Verification checks with small-order key of order - Test 11", - "Ed25519 Verification checks with small-order key of order - Test 12", - "Ed25519 Verification checks with small-order key of order - Test 13" + "Sign and verify using generated Ed448 keys." ], "eddsa.https.any.worker.html": [ "EdDSA Ed448 verification", @@ -2187,7 +1409,17 @@ "EdDSA Ed448 verification failure due to altered signature", "EdDSA Ed448 verification failure due to shortened signature", "EdDSA Ed448 verification failure due to altered data", - "Sign and verify using generated Ed448 keys.", + "Sign and verify using generated Ed448 keys." + ], + "eddsa_small_order_points.https.any.html": [ + "Ed25519 Verification checks with small-order key of order - Test 0", + "Ed25519 Verification checks with small-order key of order - Test 1", + "Ed25519 Verification checks with small-order key of order - Test 2", + "Ed25519 Verification checks with small-order key of order - Test 11", + "Ed25519 Verification checks with small-order key of order - Test 12", + "Ed25519 Verification checks with small-order key of order - Test 13" + ], + "eddsa_small_order_points.https.any.worker.html": [ "Ed25519 Verification checks with small-order key of order - Test 0", "Ed25519 Verification checks with small-order key of order - Test 1", "Ed25519 Verification checks with small-order key of order - Test 2", @@ -2203,18 +1435,28 @@ }, "wrapKey_unwrapKey": { "wrapKey_unwrapKey.https.any.html": [ - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-CTR", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-CBC", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-GCM", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-KW", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and RSA-OAEP" + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-CTR", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CTR", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-CBC", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CBC", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-GCM", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-GCM", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-KW", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-KW", + "Can wrap and unwrap X448 private key keys using pkcs8 and RSA-OAEP", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and RSA-OAEP" ], "wrapKey_unwrapKey.https.any.worker.html": [ - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-CTR", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-CBC", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-GCM", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and AES-KW", - "Can wrap and unwrap X25519 private key keys as non-extractable using pkcs8 and RSA-OAEP" + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-CTR", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CTR", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-CBC", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CBC", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-GCM", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-GCM", + "Can wrap and unwrap X448 private key keys using pkcs8 and AES-KW", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-KW", + "Can wrap and unwrap X448 private key keys using pkcs8 and RSA-OAEP", + "Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and RSA-OAEP" ] } }, @@ -2554,9 +1796,9 @@ "Document interface: attribute firstElementChild", "Document interface: attribute lastElementChild", "Document interface: attribute childElementCount", - "Document interface: operation prepend((Node or TrustedScript or DOMString)...)", - "Document interface: operation append((Node or TrustedScript or DOMString)...)", - "Document interface: operation replaceChildren((Node or TrustedScript or DOMString)...)", + "Document interface: operation prepend((Node or DOMString)...)", + "Document interface: operation append((Node or DOMString)...)", + "Document interface: operation replaceChildren((Node or DOMString)...)", "Document interface: operation querySelector(DOMString)", "Document interface: operation querySelectorAll(DOMString)", "Document interface: operation createExpression(DOMString, optional XPathNSResolver?)", @@ -2587,9 +1829,9 @@ "DocumentType interface: attribute name", "DocumentType interface: attribute publicId", "DocumentType interface: attribute systemId", - "DocumentType interface: operation before((Node or TrustedScript or DOMString)...)", - "DocumentType interface: operation after((Node or TrustedScript or DOMString)...)", - "DocumentType interface: operation replaceWith((Node or TrustedScript or DOMString)...)", + "DocumentType interface: operation before((Node or DOMString)...)", + "DocumentType interface: operation after((Node or DOMString)...)", + "DocumentType interface: operation replaceWith((Node or DOMString)...)", "DocumentType interface: operation remove()", "DocumentFragment interface: existence and properties of interface object", "DocumentFragment interface object length", @@ -2602,9 +1844,9 @@ "DocumentFragment interface: attribute firstElementChild", "DocumentFragment interface: attribute lastElementChild", "DocumentFragment interface: attribute childElementCount", - "DocumentFragment interface: operation prepend((Node or TrustedScript or DOMString)...)", - "DocumentFragment interface: operation append((Node or TrustedScript or DOMString)...)", - "DocumentFragment interface: operation replaceChildren((Node or TrustedScript or DOMString)...)", + "DocumentFragment interface: operation prepend((Node or DOMString)...)", + "DocumentFragment interface: operation append((Node or DOMString)...)", + "DocumentFragment interface: operation replaceChildren((Node or DOMString)...)", "DocumentFragment interface: operation querySelector(DOMString)", "DocumentFragment interface: operation querySelectorAll(DOMString)", "ShadowRoot interface: existence and properties of interface object", @@ -2669,16 +1911,16 @@ "Element interface: attribute firstElementChild", "Element interface: attribute lastElementChild", "Element interface: attribute childElementCount", - "Element interface: operation prepend((Node or TrustedScript or DOMString)...)", - "Element interface: operation append((Node or TrustedScript or DOMString)...)", - "Element interface: operation replaceChildren((Node or TrustedScript or DOMString)...)", + "Element interface: operation prepend((Node or DOMString)...)", + "Element interface: operation append((Node or DOMString)...)", + "Element interface: operation replaceChildren((Node or DOMString)...)", "Element interface: operation querySelector(DOMString)", "Element interface: operation querySelectorAll(DOMString)", "Element interface: attribute previousElementSibling", "Element interface: attribute nextElementSibling", - "Element interface: operation before((Node or TrustedScript or DOMString)...)", - "Element interface: operation after((Node or TrustedScript or DOMString)...)", - "Element interface: operation replaceWith((Node or TrustedScript or DOMString)...)", + "Element interface: operation before((Node or DOMString)...)", + "Element interface: operation after((Node or DOMString)...)", + "Element interface: operation replaceWith((Node or DOMString)...)", "Element interface: operation remove()", "Element interface: attribute assignedSlot", "NamedNodeMap interface: existence and properties of interface object", @@ -2723,9 +1965,9 @@ "CharacterData interface: operation replaceData(unsigned long, unsigned long, DOMString)", "CharacterData interface: attribute previousElementSibling", "CharacterData interface: attribute nextElementSibling", - "CharacterData interface: operation before((Node or TrustedScript or DOMString)...)", - "CharacterData interface: operation after((Node or TrustedScript or DOMString)...)", - "CharacterData interface: operation replaceWith((Node or TrustedScript or DOMString)...)", + "CharacterData interface: operation before((Node or DOMString)...)", + "CharacterData interface: operation after((Node or DOMString)...)", + "CharacterData interface: operation replaceWith((Node or DOMString)...)", "CharacterData interface: operation remove()", "Text interface: existence and properties of interface object", "Text interface object length", @@ -3089,7 +2331,16 @@ "Node member must be removed: getFeature", "Node member must be removed: getUserData", "Node member must be removed: setUserData", - "Node member must be removed: rootNode" + "Node member must be removed: rootNode", + "The DOMSubtreeModified mutation event must not be fired.", + "The DOMNodeInserted mutation event must not be fired.", + "The DOMNodeRemoved mutation event must not be fired.", + "The DOMNodeRemovedFromDocument mutation event must not be fired.", + "The DOMNodeInsertedIntoDocument mutation event must not be fired.", + "The DOMCharacterDataModified mutation event must not be fired.", + "The DOMAttrModified mutation event must not be fired.", + "The DOMAttributeNameChanged mutation event must not be fired.", + "The DOMElementNameChanged mutation event must not be fired." ], "idlharness.any.serviceworker.html": false, "idlharness.any.sharedworker.html": false, @@ -3684,7 +2935,6 @@ "Range-intersectsNode-binding.html": false, "Range-intersectsNode-shadow.html": false, "Range-intersectsNode.html": false, - "Range-isPointInRange-shadowdom.tentative.html": false, "Range-isPointInRange.html": false, "Range-mutations-appendChild.html": false, "Range-mutations-appendData.html": false, @@ -4007,14 +3257,8 @@ "owning-type-message-port.any.worker.html": false, "owning-type.any.html": false, "owning-type.any.worker.html": false, - "from.any.html": [ - "ReadableStream.from ignores a null @@asyncIterator", - "ReadableStream.from accepts a string" - ], - "from.any.worker.html": [ - "ReadableStream.from ignores a null @@asyncIterator", - "ReadableStream.from accepts a string" - ] + "from.any.html": true, + "from.any.worker.html": true }, "transform-streams": { "backpressure.any.html": true, @@ -4584,7 +3828,31 @@ "≯ (using .host)", "≯ (using .hostname)", "≯ (using .host)", - "≯ (using .hostname)" + "≯ (using .hostname)", + "≠ (using .host)", + "≠ (using .hostname)", + "≠ (using .host)", + "≠ (using .hostname)", + "≮ (using .host)", + "≮ (using .hostname)", + "≮ (using .host)", + "≮ (using .hostname)", + "≯ (using .host)", + "≯ (using .hostname)", + "≯ (using .host)", + "≯ (using .hostname)", + "=­̸ (using .host)", + "=­̸ (using .hostname)", + "=­̸ (using .host)", + "=­̸ (using .hostname)", + "<­̸ (using .host)", + "<­̸ (using .hostname)", + "<­̸ (using .host)", + "<­̸ (using .hostname)", + ">­̸ (using .host)", + ">­̸ (using .hostname)", + ">­̸ (using .host)", + ">­̸ (using .hostname)" ], "url-origin.any.html": [ "Origin parsing: without base", @@ -4857,6 +4125,7 @@ "Parsing: against " ], "url-constructor.any.html?include=file": [ + "Parsing: without base", "Parsing: against ", "Parsing: without base", "Parsing: without base", @@ -4919,6 +4188,7 @@ "Parsing: against " ], "url-constructor.any.worker.html?include=file": [ + "Parsing: without base", "Parsing: against ", "Parsing: without base", "Parsing: without base", @@ -5797,7 +5067,6 @@ "Parsing origin: against ", "Parsing origin: against ", "Parsing origin: against ", - "Parsing origin: against ", "Parsing origin: against ", "Parsing origin: against ", "Parsing origin: against ", @@ -5898,7 +5167,21 @@ "Parsing origin: against ", "Parsing origin: against ", "Parsing origin: against ", - "Parsing origin: against " + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against ", + "Parsing origin: against " ], "a-element.html?exclude=(file|javascript|mailto)": [ "Test that embedded 0x0A is stripped", @@ -6229,7 +5512,6 @@ "Parsing: against ", "Parsing: against ", "Parsing: against ", - "Parsing: against ", "Parsing: against ", "Parsing: against ", "Parsing: against ", @@ -6575,6 +5857,19 @@ "Parsing: against ", "Parsing: against ", "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", "Parsing: against ", "Parsing: against ", "Parsing: against ", @@ -6582,7 +5877,8 @@ "Parsing: against ", "Parsing: against ", "Parsing: against ", - "Parsing: against " + "Parsing: against ", + "Parsing: against " ], "a-element.html?include=file": [ "Test that embedded 0x0A is stripped", @@ -6610,6 +5906,11 @@ "Parsing: against ", "Parsing: against ", "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", + "Parsing: against ", "Parsing: against ", "Parsing: against ", "Parsing: against ", @@ -10286,10 +9587,6 @@ "semantics": { "scripting-1": { "the-script-element": { - "import-assertions": { - "dynamic-import-with-assertion-argument.any.html": true, - "dynamic-import-with-assertion-argument.any.worker.html": true - }, "json-module": { "charset-bom.any.html": true, "charset-bom.any.worker.html": true, @@ -10327,12 +9624,10 @@ "blob-url-workers.window.html": [], "microtasks": { "basic.any.html": [ - "import() should not drain the microtask queue if it fails during specifier resolution", - "import() should not drain the microtask queue when loading an already loaded module" + "import() should not drain the microtask queue if it fails during specifier resolution" ], "basic.any.worker.html": [ - "import() should not drain the microtask queue if it fails during specifier resolution", - "import() should not drain the microtask queue when loading an already loaded module" + "import() should not drain the microtask queue if it fails during specifier resolution" ], "css-import-in-worker.any.worker.html": true, "with-import-assertions.any.html": true, @@ -10347,6 +9642,11 @@ "import.meta.resolve is not a constructor" ] } + }, + "import-attributes": { + "dynamic-import-with-attributes-argument.any.html": true, + "dynamic-import-with-attributes-argument.any.sharedworker.html": false, + "dynamic-import-with-attributes-argument.any.worker.html": true } } }, @@ -10730,7 +10030,6 @@ "localStorage: defineProperty not configurable", "sessionStorage: defineProperty not configurable" ], - "localstorage-cross-origin-iframe.tentative.https.window.html": false, "storage_local_window_open.window.html": false, "storage_session_window_noopener.window.html": false, "storage_session_window_open.window.html": false, @@ -10752,10 +10051,7 @@ "event_session_removeitem.html": false, "event_session_storagearea.html": false, "event_session_url.html": false, - "event_setattribute.html": false, - "localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html": false, - "localstorage-basic-partitioned.tentative.sub.html": false, - "sessionStorage-basic-partitioned.tentative.sub.html": false + "event_setattribute.html": false }, "webmessaging": { "broadcastchannel": { @@ -12329,9 +11625,6 @@ "ctor-1.html": false, "ctor-null.html": false, "ctor-undefined.html": false, - "same-origin.html": [ - "non-parsable URL" - ], "terminate.html": true, "use-base-url.html": false }, diff --git a/tests/wpt/runner/runner.ts b/tests/wpt/runner/runner.ts index b404f2ad8b..6e654fd334 100644 --- a/tests/wpt/runner/runner.ts +++ b/tests/wpt/runner/runner.ts @@ -214,17 +214,20 @@ async function generateBundle(location: URL): Promise { join(ROOT_PATH, "./tests/wpt/runner/testharnessreport.js"), ); const contents = await Deno.readTextFile(url); + scriptContents.push([url.href, "globalThis.window = globalThis;"]); scriptContents.push([url.href, contents]); } else if (src) { const url = new URL(src, location); const res = await fetch(url); if (res.ok) { const contents = await res.text(); + scriptContents.push([url.href, "globalThis.window = globalThis;"]); scriptContents.push([url.href, contents]); } } else { const url = new URL(`#${inlineScriptCount}`, location); inlineScriptCount++; + scriptContents.push([url.href, "globalThis.window = globalThis;"]); scriptContents.push([url.href, script.textContent]); } } diff --git a/tests/wpt/runner/utils.ts b/tests/wpt/runner/utils.ts index 1674419cd1..140c388ec2 100644 --- a/tests/wpt/runner/utils.ts +++ b/tests/wpt/runner/utils.ts @@ -76,7 +76,10 @@ export function getManifest(): Manifest { /// WPT TEST EXPECTATIONS -const EXPECTATION_PATH = join(ROOT_PATH, "./tests/wpt/runner/expectation.json"); +export const EXPECTATION_PATH = join( + ROOT_PATH, + "./tests/wpt/runner/expectation.json", +); export interface Expectation { [key: string]: Expectation | boolean | string[] | { ignore: boolean }; @@ -87,9 +90,12 @@ export function getExpectation(): Expectation { return JSON.parse(expectationText); } -export function saveExpectation(expectation: Expectation) { +export function saveExpectation( + expectation: Expectation, + path: string = EXPECTATION_PATH, +) { Deno.writeTextFileSync( - EXPECTATION_PATH, + path, JSON.stringify(expectation, undefined, " ") + "\n", ); } @@ -134,6 +140,15 @@ export function runPy>( }).spawn(); } +export async function runGitDiff(args: string[]): string { + await new Deno.Command("git", { + args: ["diff", ...args], + stdout: "inherit", + stderr: "inherit", + cwd: ROOT_PATH, + }).output(); +} + export async function checkPy3Available() { const { success, stdout } = await runPy(["--version"], { stdout: "piped", diff --git a/tests/wpt/suite b/tests/wpt/suite index a7b5eac8f2..e78446e34a 160000 --- a/tests/wpt/suite +++ b/tests/wpt/suite @@ -1 +1 @@ -Subproject commit a7b5eac8f2cfac28bb12beeea15a9e2b126a568e +Subproject commit e78446e34a1921371658a5df08c71d83f50a2a2f diff --git a/tests/wpt/wpt.ts b/tests/wpt/wpt.ts index 8879de1332..b13a10cf4c 100755 --- a/tests/wpt/wpt.ts +++ b/tests/wpt/wpt.ts @@ -1,6 +1,8 @@ #!/usr/bin/env -S deno run --allow-write --allow-read --allow-net --allow-env --allow-run --config=tests/config/deno.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + // This script is used to run WPT tests for Deno. import { @@ -16,6 +18,7 @@ import { checkPy3Available, escapeLoneSurrogates, Expectation, + EXPECTATION_PATH, generateRunInfo, getExpectation, getExpectFailForCase, @@ -28,6 +31,7 @@ import { noIgnore, quiet, rest, + runGitDiff, runPy, updateManifest, wptreport, @@ -254,7 +258,16 @@ async function run() { await Deno.writeTextFile(wptreport, JSON.stringify(report) + "\n"); } + const newExpectations = newExpectation(results); + const tmp = Deno.makeTempFileSync(); + saveExpectation(newExpectations, tmp); + const code = reportFinal(results, endTime - startTime); + + // Run git diff to see what changed + await runGitDiff([EXPECTATION_PATH, tmp]); + Deno.removeSync(tmp); + Deno.exit(code); } @@ -388,6 +401,19 @@ async function update() { await Deno.writeTextFile(json, JSON.stringify(results) + "\n"); } + const newExpectations = newExpectation(results); + saveExpectation(newExpectations); + + reportFinal(results, endTime - startTime); + + console.log(blue("Updated expectation.json to match reality.")); + + Deno.exit(0); +} + +function newExpectation( + results: { test: TestToRun; result: TestResult }[], +): Expectation { const resultTests: Record< string, { passed: string[]; failed: string[]; testSucceeded: boolean } @@ -429,13 +455,7 @@ async function update() { ); } - saveExpectation(currentExpectation); - - reportFinal(results, endTime - startTime); - - console.log(blue("Updated expectation.json to match reality.")); - - Deno.exit(0); + return currentExpectation; } function insertExpectation( diff --git a/tools/build_bench.ts b/tools/build_bench.ts index 31f7a29a94..400737561b 100755 --- a/tools/build_bench.ts +++ b/tools/build_bench.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S deno run --allow-env --allow-read --allow-write --allow-run +#!/usr/bin/env -S deno run --allow-env --allow-read --allow-write --allow-run=git,cargo // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import $ from "https://deno.land/x/dax@0.32.0/mod.ts"; diff --git a/tools/copyright_checker.js b/tools/copyright_checker.js index 3c46f3b1ed..24afe1dfd7 100755 --- a/tools/copyright_checker.js +++ b/tools/copyright_checker.js @@ -1,6 +1,8 @@ #!/usr/bin/env -S deno run --allow-read=. --allow-run=git --config=tests/config/deno.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import { getSources, ROOT_PATH } from "./util.js"; const copyrightYear = 2024; diff --git a/tools/core_import_map.json b/tools/core_import_map.json index ba4cd105d9..aae4e63a45 100644 --- a/tools/core_import_map.json +++ b/tools/core_import_map.json @@ -40,9 +40,10 @@ "ext:deno_node/_fs/_fs_write.mjs": "../ext/node/polyfills/_fs/_fs_write.mjs", "ext:deno_node/_fs/_fs_writev.mjs": "../ext/node/polyfills/_fs/_fs_writev.mjs", "ext:deno_node/_global.d.ts": "../ext/node/polyfills/_global.d.ts", - "ext:deno_node/_http_agent.mjs": "../ext/node/polyfills/_http_agent.mjs", - "ext:deno_node/_http_common.ts": "../ext/node/polyfills/_http_common.ts", - "ext:deno_node/_http_outgoing.ts": "../ext/node/polyfills/_http_outgoing.ts", + "node:_http_agent": "../ext/node/polyfills/_http_agent.mjs", + "node:_http_common": "../ext/node/polyfills/_http_common.ts", + "node:_http_outgoing": "../ext/node/polyfills/_http_outgoing.ts", + "node:_http_server": "../ext/node/polyfills/_http_server.ts", "ext:deno_node/_next_tick.ts": "../ext/node/polyfills/_next_tick.ts", "ext:deno_node/_process/exiting.ts": "../ext/node/polyfills/_process/exiting.ts", "ext:deno_node/_process/process.ts": "../ext/node/polyfills/_process/process.ts", @@ -50,7 +51,7 @@ "ext:deno_node/_readline_shared_types.d.ts": "../ext/node/polyfills/_readline_shared_types.d.ts", "ext:deno_node/_stream.d.ts": "../ext/node/polyfills/_stream.d.ts", "ext:deno_node/_stream.mjs": "../ext/node/polyfills/_stream.mjs", - "ext:deno_node/_tls_common.ts": "../ext/node/polyfills/_tls_common.ts", + "node:_tls_common": "../ext/node/polyfills/_tls_common.ts", "ext:deno_node/_util/asserts.ts": "../ext/node/polyfills/_util/asserts.ts", "ext:deno_node/_util/async.ts": "../ext/node/polyfills/_util/async.ts", "ext:deno_node/_util/os.ts": "../ext/node/polyfills/_util/os.ts", @@ -154,15 +155,15 @@ "ext:deno_node/internal/streams/add-abort-signal.mjs": "../ext/node/polyfills/internal/streams/add-abort-signal.mjs", "ext:deno_node/internal/streams/buffer_list.mjs": "../ext/node/polyfills/internal/streams/buffer_list.mjs", "ext:deno_node/internal/streams/destroy.mjs": "../ext/node/polyfills/internal/streams/destroy.mjs", - "ext:deno_node/internal/streams/duplex.mjs": "../ext/node/polyfills/internal/streams/duplex.mjs", + "node:_stream_duplex": "../ext/node/polyfills/internal/streams/duplex.mjs", "ext:deno_node/internal/streams/end-of-stream.mjs": "../ext/node/polyfills/internal/streams/end-of-stream.mjs", "ext:deno_node/internal/streams/lazy_transform.mjs": "../ext/node/polyfills/internal/streams/lazy_transform.mjs", - "ext:deno_node/internal/streams/passthrough.mjs": "../ext/node/polyfills/internal/streams/passthrough.mjs", - "ext:deno_node/internal/streams/readable.mjs": "../ext/node/polyfills/internal/streams/readable.mjs", + "node:_stream_readable": "../ext/node/polyfills/internal/streams/readable.mjs", + "node:_stream_passthrough": "../ext/node/polyfills/internal/streams/passthrough.mjs", "ext:deno_node/internal/streams/state.mjs": "../ext/node/polyfills/internal/streams/state.mjs", - "ext:deno_node/internal/streams/transform.mjs": "../ext/node/polyfills/internal/streams/transform.mjs", "ext:deno_node/internal/streams/utils.mjs": "../ext/node/polyfills/internal/streams/utils.mjs", - "ext:deno_node/internal/streams/writable.mjs": "../ext/node/polyfills/internal/streams/writable.mjs", + "node:_stream_transform": "../ext/node/polyfills/internal/streams/transform.mjs", + "node:_stream_writable": "../ext/node/polyfills/internal/streams/writable.mjs", "ext:deno_node/internal/test/binding.ts": "../ext/node/polyfills/internal/test/binding.ts", "ext:deno_node/internal/timers.mjs": "../ext/node/polyfills/internal/timers.mjs", "ext:deno_node/internal/url.ts": "../ext/node/polyfills/internal/url.ts", @@ -206,7 +207,7 @@ "node:util/types": "../ext/node/polyfills/util/types.ts", "node:v8": "../ext/node/polyfills/v8.ts", "node:vm": "../ext/node/polyfills/vm.js", - "ext:deno_node/wasi.ts": "../ext/node/polyfills/wasi.ts", + "node:wasi": "../ext/node/polyfills/wasi.ts", "node:worker_threads": "../ext/node/polyfills/worker_threads.ts", "node:zlib": "../ext/node/polyfills/zlib.ts", "ext:deno_url/00_url.js": "../ext/url/00_url.js", @@ -238,7 +239,6 @@ "ext:runtime/06_util.js": "../runtime/js/06_util.js", "ext:runtime/10_permissions.js": "../runtime/js/10_permissions.js", "ext:runtime/11_workers.js": "../runtime/js/11_workers.js", - "ext:runtime/13_buffer.js": "../runtime/js/13_buffer.js", "ext:runtime/30_os.js": "../runtime/js/30_os.js", "ext:runtime/40_fs_events.js": "../runtime/js/40_fs_events.js", "ext:runtime/40_process.js": "../runtime/js/40_process.js", diff --git a/tools/format.js b/tools/format.js index c1f151b552..b29667ca77 100755 --- a/tools/format.js +++ b/tools/format.js @@ -1,4 +1,4 @@ -#!/usr/bin/env -S deno run --allow-write --allow-read --allow-run --allow-net --config=tests/config/deno.json +#!/usr/bin/env -S deno run --allow-all --config=tests/config/deno.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { join, ROOT_PATH } from "./util.js"; diff --git a/tools/generate_types_deno.ts b/tools/generate_types_deno.ts new file mode 100755 index 0000000000..265b6f5371 --- /dev/null +++ b/tools/generate_types_deno.ts @@ -0,0 +1,100 @@ +#!/usr/bin/env -S deno run -A +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// This script is used to generate the @types/deno package on DefinitelyTyped. + +import $ from "jsr:@david/dax@0.42.0"; +import { Node, Project } from "jsr:@ts-morph/ts-morph@23.0.0"; +import * as semver from "jsr:@std/semver@1.0.3"; + +const rootDir = $.path(import.meta.dirname!).parentOrThrow(); +const definitelyTypedDir = rootDir.join( + "../DefinitelyTyped/types/deno/", +); + +if (!definitelyTypedDir.existsSync()) { + throw new Error(`Makes sure ${definitelyTypedDir} exists.`); +} + +const denoExec = rootDir.join( + "target/debug/deno" + (Deno.build.os === "windows" ? ".exe" : ""), +); + +$.logStep("Building Deno executable..."); +await $`cargo build`; + +$.logStep("Creating declaration file..."); +await createDenoDtsFile(); +$.logStep("Updating package.json..."); +await updatePkgJson(); +$.logStep("Formatting..."); +await $`pnpm dprint fmt`.cwd(definitelyTypedDir); + +async function createDenoDtsFile() { + function matchesAny(text: string | undefined, patterns: string[]): boolean { + if (text == null) { + return false; + } + for (const pattern of patterns) { + if (text.includes(pattern)) { + return true; + } + } + return false; + } + + const text = await $`${denoExec} types`.text(); + const project = new Project(); + const file = project.createSourceFile( + definitelyTypedDir.join("index.d.ts").toString(), + text, + { + overwrite: true, + }, + ); + + for (const statement of file.getStatementsWithComments()) { + if (Node.isCommentStatement(statement)) { + const statementText = statement.getText(); + if (statementText.includes(" tag.getTagName() === "category")) { - errors.push(getErrorPrefix(node) + "JSDoc @category tag"); + errors.push(getMissingErrorPrefix(node) + "JSDoc @category tag"); continue; } if (unstableFiles.includes(file)) { if (!tags.find((tag) => tag.getTagName() === "experimental")) { - errors.push(getErrorPrefix(node) + "JSDoc @experimental tag"); + errors.push(getMissingErrorPrefix(node) + "JSDoc @experimental tag"); } } } @@ -81,6 +87,10 @@ if (errors.length > 0) { throw new AggregateError(errors); } -function getErrorPrefix(node) { - return `Symbol at file://${node.getSourceFile().getFilePath()}:${node.getStartLineNumber()} is missing a `; +function getMissingErrorPrefix(node) { + return getErrorPrefix(node) + `is missing a `; +} + +function getErrorPrefix(node) { + return `Symbol at file://${node.getSourceFile().getFilePath()}:${node.getStartLineNumber()} `; } diff --git a/tools/lint.js b/tools/lint.js index aa02a3e2b3..1f3f56498b 100755 --- a/tools/lint.js +++ b/tools/lint.js @@ -1,5 +1,8 @@ -#!/usr/bin/env -S deno run --allow-write --allow-read --allow-run --allow-net --config=tests/config/deno.json +#!/usr/bin/env -S deno run --allow-all --config=tests/config/deno.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { buildMode, getPrebuilt, getSources, join, ROOT_PATH } from "./util.js"; import { checkCopyright } from "./copyright_checker.js"; import * as ciFile from "../.github/workflows/ci.generate.ts"; @@ -44,27 +47,19 @@ async function dlint() { "*.js", "*.ts", ":!:.github/mtime_cache/action.js", - ":!:tests/testdata/swc_syntax_error.ts", - ":!:tests/testdata/error_008_checkjs.js", ":!:cli/bench/testdata/npm/*", ":!:cli/bench/testdata/express-router.js", ":!:cli/bench/testdata/react-dom.js", ":!:cli/compilers/wasm_wrap.js", ":!:cli/tsc/dts/**", + ":!:cli/tsc/*typescript.js", + ":!:cli/tsc/compiler.d.ts", + ":!:runtime/examples/", ":!:target/", ":!:tests/registry/**", ":!:tests/specs/**", - ":!:tests/testdata/encoding/**", - ":!:tests/testdata/error_syntax.js", - ":!:tests/testdata/file_extensions/ts_with_js_extension.js", - ":!:tests/testdata/fmt/**", - ":!:tests/testdata/lint/**", - ":!:tests/testdata/npm/**", - ":!:tests/testdata/run/**", - ":!:tests/testdata/tsc/**", - ":!:tests/testdata/test/glob/**", - ":!:cli/tsc/*typescript.js", - ":!:cli/tsc/compiler.d.ts", + ":!:tests/testdata/**", + ":!:tests/unit_node/testdata/**", ":!:tests/wpt/suite/**", ":!:tests/wpt/runner/**", ]); @@ -93,7 +88,12 @@ async function dlint() { }), ); } - await Promise.all(pending); + const results = await Promise.allSettled(pending); + for (const result of results) { + if (result.status === "rejected") { + throw new Error(result.reason); + } + } } // `prefer-primordials` has to apply only to files related to bootstrapping, @@ -196,40 +196,36 @@ async function ensureNoNewITests() { // replace them with spec tests. const iTestCounts = { "bench_tests.rs": 0, - "bundle_tests.rs": 11, "cache_tests.rs": 0, "cert_tests.rs": 0, - "check_tests.rs": 23, + "check_tests.rs": 2, "compile_tests.rs": 0, "coverage_tests.rs": 0, - "doc_tests.rs": 15, - "eval_tests.rs": 9, + "eval_tests.rs": 0, "flags_tests.rs": 0, - "fmt_tests.rs": 17, - "info_tests.rs": 18, + "fmt_tests.rs": 16, "init_tests.rs": 0, "inspector_tests.rs": 0, "install_tests.rs": 0, "jsr_tests.rs": 0, "js_unit_tests.rs": 0, "jupyter_tests.rs": 0, - "lint_tests.rs": 18, // Read the comment above. Please don't increase these numbers! "lsp_tests.rs": 0, - "node_compat_tests.rs": 4, + "node_compat_tests.rs": 0, "node_unit_tests.rs": 2, - "npm_tests.rs": 93, + "npm_tests.rs": 5, "pm_tests.rs": 0, "publish_tests.rs": 0, "repl_tests.rs": 0, - "run_tests.rs": 360, + "run_tests.rs": 331, "shared_library_tests.rs": 0, - "task_tests.rs": 30, - "test_tests.rs": 77, + "task_tests.rs": 2, + "test_tests.rs": 0, "upgrade_tests.rs": 0, "vendor_tests.rs": 1, "watcher_tests.rs": 0, - "worker_tests.rs": 18, + "worker_tests.rs": 0, }; const integrationDir = join(ROOT_PATH, "tests", "integration"); for await (const entry of Deno.readDir(integrationDir)) { diff --git a/tools/napi/generate_symbols_lists.js b/tools/napi/generate_symbols_lists.js index 11cf1c434a..efb0edc043 100755 --- a/tools/napi/generate_symbols_lists.js +++ b/tools/napi/generate_symbols_lists.js @@ -1,7 +1,7 @@ #!/usr/bin/env -S deno run --allow-read --allow-write // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import exports from "../../cli/napi/sym/symbol_exports.json" with { +import exports from "../../ext/napi/sym/symbol_exports.json" with { type: "json", }; @@ -17,7 +17,7 @@ const symbolExportLists = { for await (const [os, def] of Object.entries(symbolExportLists)) { const defUrl = new URL( - `../../cli/napi/generated_symbol_exports_list_${os}.def`, + `../../ext/napi/generated_symbol_exports_list_${os}.def`, import.meta.url, ); await Deno.writeTextFile(defUrl.pathname, def, { create: true }); diff --git a/tools/release/00_start_release.ts b/tools/release/00_start_release.ts index b5c35ae5a5..125a76af66 100755 --- a/tools/release/00_start_release.ts +++ b/tools/release/00_start_release.ts @@ -1,5 +1,8 @@ #!/usr/bin/env -S deno run -A --quiet --lock=tools/deno.lock.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { $, createOctoKit, semver } from "./deps.ts"; const currentDirPath = $.path(import.meta).parentOrThrow(); diff --git a/tools/release/03_publish_crates.ts b/tools/release/03_publish_crates.ts index dcad8ed928..ecfb75e796 100755 --- a/tools/release/03_publish_crates.ts +++ b/tools/release/03_publish_crates.ts @@ -1,5 +1,8 @@ #!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { DenoWorkspace } from "./deno_workspace.ts"; import { $, getCratesPublishOrder } from "./deps.ts"; diff --git a/tools/release/promote_to_rc.ts b/tools/release/promote_to_release.ts old mode 100644 new mode 100755 similarity index 77% rename from tools/release/promote_to_rc.ts rename to tools/release/promote_to_release.ts index eb49336783..046f4d33a8 --- a/tools/release/promote_to_rc.ts +++ b/tools/release/promote_to_release.ts @@ -1,9 +1,11 @@ #!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-console + import { $ } from "jsr:@david/dax@0.41.0"; import { gray } from "jsr:@std/fmt@1/colors"; -import { patchver } from "jsr:@deno/patchver@0.1.0"; +import { patchver } from "jsr:@deno/patchver@0.2.0"; const SUPPORTED_TARGETS = [ "aarch64-apple-darwin", @@ -18,7 +20,10 @@ const DENO_BINARIES = [ "denort", ]; -const CHANNEL = "rc"; +const CHANNEL = Deno.args[0]; +if (CHANNEL !== "rc" && CHANNEL !== "lts") { + throw new Error(`Invalid channel: ${CHANNEL}`); +} const CANARY_URL = "https://dl.deno.land"; @@ -38,12 +43,12 @@ function getUnzippedFilename(binary: string, target: string) { } } -function getRcBinaryName(binary: string, target: string): string { +function getBinaryName(binary: string, target: string): string { let ext = ""; if (target.includes("windows")) { ext = ".exe"; } - return `${binary}-${target}-rc${ext}`; + return `${binary}-${target}-${CHANNEL}${ext}`; } function getArchiveName(binary: string, target: string): string { @@ -90,8 +95,8 @@ async function unzipArchive(archiveName: string, unzippedName: string) { } } -async function createArchive(rcBinaryName: string, archiveName: string) { - const output = await $`zip -r ./${archiveName} ./${rcBinaryName}`; +async function createArchive(binaryName: string, archiveName: string) { + const output = await $`zip -r ./${archiveName} ./${binaryName}`; if (output.code !== 0) { $.logError( @@ -104,13 +109,13 @@ async function createArchive(rcBinaryName: string, archiveName: string) { async function runPatchver( binary: string, target: string, - rcBinaryName: string, + binaryName: string, ) { const input = await Deno.readFile(binary); const output = patchver(input, CHANNEL); try { - await Deno.writeFile(rcBinaryName, output); + await Deno.writeFile(binaryName, output); } catch (e) { $.logError( `Failed to promote to RC ${binary} (${target}), error:`, @@ -122,19 +127,19 @@ async function runPatchver( async function runRcodesign( target: string, - rcBinaryName: string, + binaryName: string, commitHash: string, ) { - if (!target.includes("apple") || rcBinaryName.includes("denort")) { + if (!target.includes("apple") || binaryName.includes("denort")) { return; } - $.logStep(`Codesign ${rcBinaryName}`); + $.logStep(`Codesign ${binaryName}`); const tempFile = $.path("temp.p12"); let output; try { await $`echo $APPLE_CODESIGN_KEY | base64 -d`.stdout(tempFile); output = - await $`rcodesign sign ./${rcBinaryName} --binary-identifier=deno-${commitHash} --code-signature-flags=runtime --code-signature-flags=runtime --p12-password="$APPLE_CODESIGN_PASSWORD" --p12-file=${tempFile} --entitlements-xml-file=cli/entitlements.plist`; + await $`rcodesign sign ./${binaryName} --binary-identifier=deno-${commitHash} --code-signature-flags=runtime --code-signature-flags=runtime --p12-password="$APPLE_CODESIGN_PASSWORD" --p12-file=${tempFile} --entitlements-xml-file=cli/entitlements.plist`; } finally { try { tempFile.removeSync(); @@ -144,7 +149,7 @@ async function runRcodesign( } if (output.code !== 0) { $.logError( - `Failed to codesign ${rcBinaryName} (error code ${output.code})`, + `Failed to codesign ${binaryName} (error code ${output.code})`, ); Deno.exit(1); } @@ -157,17 +162,17 @@ async function promoteBinaryToRc( commitHash: string, ) { const unzippedName = getUnzippedFilename(binary, target); - const rcBinaryName = getRcBinaryName(binary, target); + const binaryName = getBinaryName(binary, target); const archiveName = getArchiveName(binary, target); await remove(unzippedName); - await remove(rcBinaryName); + await remove(binaryName); $.logStep( "Unzip", archiveName, gray("binary"), binary, - gray("rcBinaryName"), - rcBinaryName, + gray("binaryName"), + binaryName, ); await unzipArchive(archiveName, unzippedName); @@ -178,12 +183,12 @@ async function promoteBinaryToRc( unzippedName, `(${target})`, gray("output to"), - rcBinaryName, + binaryName, ); - await runPatchver(unzippedName, target, rcBinaryName); + await runPatchver(unzippedName, target, binaryName); // Remove the unpatched binary and rename patched one. await remove(unzippedName); - await Deno.rename(rcBinaryName, unzippedName); + await Deno.rename(binaryName, unzippedName); await runRcodesign(target, unzippedName, commitHash); // Set executable permission if (!target.includes("windows")) { @@ -207,7 +212,7 @@ async function promoteBinariesToRc(commitHash: string) { "Promote", binaryName, target, - "to RC...", + `to ${CHANNEL}...`, ); await promoteBinaryToRc(binaryName, target, commitHash); $.logLight( @@ -215,7 +220,7 @@ async function promoteBinariesToRc(commitHash: string) { "Promoted", binaryName, target, - "to RC!", + `to ${CHANNEL}!`, ); } } @@ -227,18 +232,21 @@ async function dumpRcVersion() { const output = await $`./deno -V`.stdout("piped"); const denoVersion = output.stdout.slice(5).split("+")[0]; $.logStep("Computed version", denoVersion); - await Deno.writeTextFile("./release-rc-latest.txt", `v${denoVersion}`); + await Deno.writeTextFile( + `./release-${CHANNEL}-latest.txt`, + `v${denoVersion}`, + ); } async function main() { - const commitHash = Deno.args[0]; + const commitHash = Deno.args[1]; if (!commitHash) { throw new Error("Commit hash needs to be provided as an argument"); } $.logStep("Download canary binaries..."); await fetchLatestCanaryBinaries(commitHash); console.log("All canary binaries ready"); - $.logStep("Promote canary binaries to RC..."); + $.logStep(`Promote canary binaries to ${CHANNEL}...`); await promoteBinariesToRc(commitHash); // Finally dump the version name to a `release.txt` file for uploading to GCP diff --git a/tools/release/release_doc_template.md b/tools/release/release_doc_template.md index 5cc7245ce7..b372185337 100644 --- a/tools/release/release_doc_template.md +++ b/tools/release/release_doc_template.md @@ -30,7 +30,7 @@ Release checklist: ## Patch release preparation -**If you are cutting a patch release**: First you need to sync commits to the +⛔ **If you are cutting a patch release**: First you need to sync commits to the `v$MINOR_VERSION` branch in the `deno` repo. To do that, you need to cherry-pick commits from the main branch to the @@ -75,13 +75,13 @@ verify on GitHub that everything looks correct. 1. Click on the "Run workflow" button. 1. In the drop down, select the minor branch (`v$MINOR_VERSION`) if doing a patch release or the main branch if doing a minor release. - 1. For the kind of release, select either "patch", "minor", or "major". + 1. For the kind of release, select either `patch` or `minor`. 1. Run the workflow. - [ ] Wait for the workflow to complete and for a pull request to be automatically opened. Review the pull request, make any necessary changes, and merge it. - - ⛔ DO NOT create a release tag manually That will automatically happen. + - ⛔ **DO NOT** create a release tag manually That will automatically happen.
Failure Steps @@ -120,7 +120,8 @@ verify on GitHub that everything looks correct. (https://github.com/denoland/deno/releases). - ⛔ Verify that: - - [ ] There are 14 assets on the release draft. + - [ ] There are 24 assets on the + [GitHub release draft](https://github.com/denoland/deno/releases/v$VERSION). - [ ] There are 10 zip files for this version on [dl.deno.land](https://console.cloud.google.com/storage/browser/dl.deno.land/release/v$VERSION). @@ -151,13 +152,6 @@ verify on GitHub that everything looks correct. - [ ] This will open a PR. Review and merge it. - [ ] Create a `$VERSION` tag (_without_ `v` prefix). -## Updating `deno-lambda` - -- [ ] Run the version bump workflow: - https://github.com/denoland/deno-lambda/actions/workflows/bump.yml -- [ ] This will open a PR. Review and merge it. -- [ ] Create a `$VERSION` tag (_without_ `v` prefix). - ## All done! - [ ] Write a message in company's #cli channel: diff --git a/tools/upload_wptfyi.js b/tools/upload_wptfyi.js index b8f6d7c5ab..23dd4c6602 100644 --- a/tools/upload_wptfyi.js +++ b/tools/upload_wptfyi.js @@ -4,6 +4,8 @@ // passed, will automatically add a status check to the commit with a link to // the wpt.fyi page. +// deno-lint-ignore-file no-console + import { gzip } from "https://deno.land/x/compress@v0.4.1/gzip/mod.ts"; const user = Deno.env.get("WPT_FYI_USER"); diff --git a/tools/util.js b/tools/util.js index ed322d0d87..99133628ce 100644 --- a/tools/util.js +++ b/tools/util.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + import { dirname, fromFileUrl, join, resolve, toFileUrl } from "@std/path"; import { wait } from "https://deno.land/x/wait@0.1.13/mod.ts"; export { dirname, fromFileUrl, join, resolve, toFileUrl }; diff --git a/tools/verify_pr_title.js b/tools/verify_pr_title.js index d7b393bcd3..90a045d3f4 100644 --- a/tools/verify_pr_title.js +++ b/tools/verify_pr_title.js @@ -1,4 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-console + const prTitle = Deno.args[0]; if (prTitle == null) { @@ -48,9 +51,6 @@ const validPrefixes = [ "Reland ", // Allow landing breaking changes that are properly marked "BREAKING", - // Allow landing breaking changes that will be applied in Deno 2, or available - // immediately with DENO_FUTURE=1 env var - "FUTURE", ]; if (validPrefixes.some((prefix) => prTitle.startsWith(prefix))) {